/// <summary> /// Process the next message in the queue. /// </summary> /// <param name="action"></param> public void ProcessNextMessage(SCTPSocket socket, Action <SCTPMessageReceivedEventArgs> action) { if (Interlocked.CompareExchange(ref this.signalMessageReceivedLock, 1, 0) == 0) { Task.Run( () => { bool more = false; try { SCTPMessage message = this.DequeueNextMessage(socket); if (message != null) { socket.PeerReceiveWindowSize += (uint)message.Length; more = true; action(new SCTPMessageReceivedEventArgs(message)); } } finally { Interlocked.Exchange(ref this.signalMessageReceivedLock, 0); } if (more == true) { this.ProcessNextMessage(socket, action); } }); } }
/// <summary> /// Initialises a new instance of the <see cref="TCB"/> class. /// </summary> /// <param name="socket">The owning SCTP socket.</param> /// <param name="localEndPoint">The local end point.</param> /// <param name="peerInitialTSN">The peers initial TSN.</param> public TCB(SCTPSocket socket, IPEndPoint localEndPoint) { this.socket = socket; this.State = SCTPSocketState.Closed; this.CreationTime = DateTime.UtcNow; this.Lifetime = SCTPConstants.ValidCookieLifetime; this.SourceEndPoint = localEndPoint; this.streams = new ConcurrentDictionary <ushort, SCTPStream>(); this.sequenceGenerator = new StreamSequenceGenerator(); this.ReceiveWindowSize = SCTPConstants.DefaultReceiverWindowSize; Random rnd = new Random(); uint itag = (uint)rnd.Next(int.MinValue, int.MaxValue); this.LocalVerificationTag = itag; this.initialTSN = itag; this.nextTSN = this.initialTSN; this.LastCumulativeTSNAcked = Convert.ToUInt32(this.nextTSN - 1); this.socket.WriteConsole(string.Format("Initial TSN {0}", this.initialTSN)); }
/// <summary> /// Dequeues the next message from the queue. /// </summary> /// <returns>A message; otherwise null.</returns> private SCTPMessage DequeueNextMessage(SCTPSocket socket) { lock (this.queue) { SCTPMessage message = null; if (this.queue.Count > 0) { KeyValuePair <int, SCTPMessage> item = this.queue.First(); if (item.Value.StreamSequenceNo == this.lastMessageSeqNo + 1 && item.Value.IsMessageComplete() == true) { this.lastMessageSeqNo = item.Value.StreamSequenceNo; message = item.Value; this.queue.RemoveAt(0); } } return(message); } }
static void Main(string[] args) { try { IPAddress address = GetFirstActiveAddress(); SCTPSocket local = new SCTPSocket(9100); local.Bind(address); Console.WriteLine("[{0}] Local", local.GetHashCode()); SCTPSocket remote = new SCTPSocket(9200); remote.Bind(address); remote.MessageReceived += Remote_MessageReceived; Console.WriteLine("[{0}] Remote", remote.GetHashCode()); streams = new StreamStat[100]; for (int i = 0; i < streams.Length; i++) { streams[i] = new StreamStat() { StreamId = i + 1 }; } while (true) { string[] cmd = Console.ReadLine().Split(' '); if (cmd[0] == "q") { break; } else if (cmd[0] == "c") { if (local.Connect(address, 9200) == true) { Console.WriteLine("Local Connected: {0}", local.Connected); Console.WriteLine("Remote Connected: {0}", remote.Connected); } } else if (cmd[0].StartsWith("s")) { string streamStr = cmd[0].Substring(1); int streamId = string.IsNullOrEmpty(streamStr) == false?Convert.ToInt32(streamStr) : 1; int count = cmd.Length > 1 ? Convert.ToInt32(cmd[1]) : 1; for (int i = 0; i < count; i++) { streams[streamId - 1].IncrementCounter(); var model = new TestModel { Data = $"Hello World-{streams[streamId - 1].Counter}" }; model.Hash = Convert.ToBase64String(SHA1.Create().ComputeHash(UTF8Encoding.UTF8.GetBytes(model.Data))); var json = JsonConvert.SerializeObject(model); local.SendMessageAsync(streamId, UTF8Encoding.UTF8.GetBytes(json)).Wait(); } } else if (cmd[0].StartsWith("a")) { string streamStr = cmd[0].Substring(1); int streamId = string.IsNullOrEmpty(streamStr) == false?Convert.ToInt32(streamStr) : 1; int count = cmd.Length > 1 ? Convert.ToInt32(cmd[1]) : 1; streams[streamId - 1].IncrementCounter(); var model = new TestModel(); for (int i = 0; i < count; i++) { model.Data += "Hello World"; } model.Data += $"-{streams[streamId-1].Counter}"; model.Hash = Convert.ToBase64String(SHA1.Create().ComputeHash(UTF8Encoding.UTF8.GetBytes(model.Data))); var json = JsonConvert.SerializeObject(model); local.SendMessageAsync(streamId, UTF8Encoding.UTF8.GetBytes(json)).Wait(); } else if (cmd[0] == "d") { local.Shutdown(); Console.WriteLine("Local Connected: {0}", local.Connected); Console.WriteLine("Remote Connected: {0}", remote.Connected); } else if (cmd[0] == "ua") { var chunks = local.GetUnackedChunks(); foreach (var chunk in chunks) { Console.WriteLine("Unacked Chunk: {0}", chunk.TSN); } } else if (cmd[0] == "prws") { Console.WriteLine("Peer Receive Window Size: {0}", local.PeerReceiveWindowSize); } else if (cmd[0] == "mtu") { Console.WriteLine("Path MTU Size: {0}", local.MTUSize); } } local.Dispose(); remote.Dispose(); Console.WriteLine("Local Connected: {0}", local.Connected); Console.WriteLine("Remote Connected: {0}", remote.Connected); } catch (Exception ex) { Console.ForegroundColor = ConsoleColor.Red; Console.WriteLine("Error: {0}", ex.ToString()); Console.ResetColor(); } }
/// <summary> /// Initialises a new instance of the <see cref="SCTPEndPoint"/> class. /// </summary> /// <param name="sctpSocket"></param> /// <param name="endPoint"></param> internal SCTPEndPoint(SCTPSocket sctpSocket, IPEndPoint endPoint) { this.sctpSocket = sctpSocket; this.EndPoint = endPoint; }