Пример #1
0
        internal override SCTPMessage makeMessage(string bytes, BlockingSCTPStream s)
        {
            SCTPMessage m = null;

            if (base.canSend())
            {
                if (bytes.Length < this.maxMessageSize())
                {
                    m = new SCTPMessage(bytes, s);
                    lock (s)
                    {
                        int mseq = s.getNextMessageSeqOut();
                        s.setNextMessageSeqOut(mseq + 1);
                        m.setSeq(mseq);
                    }
                }
                else
                {
                    logger.LogWarning("Message too long " + bytes.Length + " > " + this.maxMessageSize());
                }
            }
            else
            {
                logger.LogWarning("Can't send a message right now");
            }

            return(m);
        }
Пример #2
0
        internal override void sendAndBlock(SCTPMessage m)
        {
            while (m.hasMoreData())
            {
                DataChunk dc;
                lock (_freeBlocks)
                {
                    dc = _freeBlocks.Count > 0 ? _freeBlocks.Dequeue() : new DataChunk();
                }

                m.fill(dc);
                //logger.LogDebug("thinking about waiting for congestion " + dc.getTsn());

                lock (_congestion)
                {
                    //logger.LogDebug("In congestion sync block ");
                    while (!this.maySend(dc.getDataSize()))
                    {
                        //logger.LogDebug("about to wait for congestion for " + this.getT3());
                        Monitor.Wait(_congestion, (int)this.getT3());  // wholly wrong
                    }
                }

                // todo check rollover - will break at maxint.
                enqueue(dc);
            }
        }
 public override void send(byte[] message)
 {
     lock (this)
     {
         Association a = base.getAssociation();
         SCTPMessage m = a.makeMessage(message, this);
         undeliveredOutboundMessages.Add(m.getSeq(), m);
         a.sendAndBlock(m);
     }
 }
 public override void send(string message)
 {
     lock (this)
     {
         Association a = base.getAssociation();
         SCTPMessage m = a.makeMessage(message, this);
         if (m == null)
         {
             logger.LogError("SCTPMessage cannot be null, but it is");
         }
         a.sendAndBlock(m);
     }
 }
Пример #5
0
        public override async Task sendasync(string message)
        {
            await semaphore.WaitAsync().ConfigureAwait(false);

            try
            {
                Association a = base.getAssociation();
                SCTPMessage m = a.makeMessage(message, this);
                if (m == null)
                {
                    logger.LogError("SCTPMessage cannot be null, but it is");
                    return;
                }
                a.sendAndBlock(m);
            }
            finally
            {
                semaphore.Release();
            }
        }
Пример #6
0
        public override async Task sendasync(byte[] message)
        {
            await semaphore.WaitAsync().ConfigureAwait(false);

            try
            {
                Association a = base.getAssociation();
                SCTPMessage m = a.makeMessage(message, this);
                if (m == null)
                {
                    logger.LogError("SCTPMessage cannot be null, but it is");
                    return;
                }
                undeliveredOutboundMessages.AddOrUpdate(m.getSeq(), m, (id, b) => m);
                a.sendAndBlock(m);
            }
            finally
            {
                semaphore.Release();
            }
        }
Пример #7
0
 internal override SCTPMessage makeMessage(byte[] bytes, BlockingSCTPStream s)
 {
     lock (this)
     {
         SCTPMessage m = null;
         if (base.canSend())
         {
             if (bytes.Length < this.maxMessageSize())
             {
                 m = new SCTPMessage(bytes, s);
                 lock (s)
                 {
                     int mseq = s.getNextMessageSeqOut();
                     s.setNextMessageSeqOut(mseq + 1);
                     m.setSeq(mseq);
                 }
             }
         }
         return(m);
     }
 }
Пример #8
0
        public void deliver(SCTPStream s, SortedArray <DataChunk> stash, SCTPStreamListener l)
        {
            //stash is the list of all DataChunks that have not yet been turned into whole messages
            //we assume that it is sorted by stream sequence number.
            List <DataChunk> delivered = new List <DataChunk>();

            if (stash.Count == 0)
            {
                return; // I'm not fond of these early returns
            }

            long expectedTsn = stash.First.getTsn(); // This ignores gaps - but _hopefully_ messageNo will catch any

            // gaps we care about - ie gaps in the sequence for _this_ stream
            // we can deliver ordered messages on this stream even if earlier messages from other streams are missing
            // - this does assume that the tsn's of a message are contiguous -which is odd.


            foreach (DataChunk dc in stash)
            {
                int messageNo = s.getNextMessageSeqIn();

                int  flags = dc.getFlags() & DataChunk.SINGLEFLAG; // mask to the bits we want
                long tsn   = dc.getTsn();
                bool lookingForOrderedMessages = _ordered;
                if (lookingForOrderedMessages && (tsn != expectedTsn))
                {
                    logger.LogDebug("Hole in chunk sequence  " + tsn + " expected " + expectedTsn);
                    break;
                }

                switch (flags)
                {
                case DataChunk.SINGLEFLAG:
                    if (_ordered && (messageNo != dc.getSSeqNo()))
                    {
                        logger.LogDebug("Hole (single) in message sequence  " + dc.getSSeqNo() + " expected " +
                                        messageNo);
                        break;     // not the message we are looking for...
                    }

                    SCTPMessage single = new SCTPMessage(s, dc);
                    if (single.deliver(l))
                    {
                        delivered.Add(dc);
                        messageNo++;
                        s.setNextMessageSeqIn(messageNo);
                    }

                    break;

                case DataChunk.BEGINFLAG:
                case DataChunk.ENDFLAG:
                case DataChunk.CONTINUEFLAG:
                    if (_ordered && (messageNo != dc.getSSeqNo()))
                    {
                        logger.LogDebug("Hole (single) in message sequence  " + dc.getSSeqNo() + " expected " +
                                        messageNo);
                        break;     // not the message we are looking for...
                    }

                    var orderedMessage = _orderedMessageHandler.GetMessage(dc.getSSeqNo())
                                         .Add(dc, flags);

                    if (orderedMessage.IsReady)
                    {
                        orderedMessage.Finish(() =>
                        {
                            SCTPMessage deliverable = new SCTPMessage(s, orderedMessage.ToArray());
                            if (deliverable.deliver(l))
                            {
                                _orderedMessageHandler.RemoveMessage(orderedMessage);
                                orderedMessage.AddToList(delivered);
                                messageNo++;
                                s.setNextMessageSeqIn(messageNo);
                            }
                        });
                    }

                    break;

                default:
                    throw new Exception("[IllegalStateException] Impossible value in stream logic");
                }

                expectedTsn = tsn + 1;
            }

            stash.RemoveWhere((dc) => { return(delivered.Contains(dc)); });
        }
Пример #9
0
 internal override void deliverMessage(SCTPMessage message)
 {
     message.run();
 }
Пример #10
0
 abstract internal void deliverMessage(SCTPMessage message);
Пример #11
0
 abstract internal void sendAndBlock(SCTPMessage m);
 internal override void deliverMessage(SCTPMessage message)
 {
     ThreadPool.QueueUserWorkItem((obj) => { message.run(); });
 }
        public void deliver(SCTPStream s, SortedArray <DataChunk> stash, SCTPStreamListener l)
        {
            //stash is the list of all DataChunks that have not yet been turned into whole messages
            //we assume that it is sorted by stream sequence number.
            List <DataChunk>        delivered = new List <DataChunk>();
            SortedArray <DataChunk> message   = null;

            if (stash.Count == 0)
            {
                return;                              // I'm not fond of these early returns
            }
            long expectedTsn = stash.First.getTsn(); // This ignores gaps - but _hopefully_ messageNo will catch any

            // gaps we care about - ie gaps in the sequence for _this_ stream
            // we can deliver ordered messages on this stream even if earlier messages from other streams are missing
            // - this does assume that the tsn's of a message are contiguous -which is odd.


            foreach (DataChunk dc in stash)
            {
                int messageNo = s.getNextMessageSeqIn();

                int  flags = dc.getFlags() & DataChunk.SINGLEFLAG; // mask to the bits we want
                long tsn   = dc.getTsn();
                bool lookingForOrderedMessages = _ordered || (message != null);
                // which is to say for unordered messages we can tolerate gaps _between_ messages
                // but not within them
                if (lookingForOrderedMessages && (tsn != expectedTsn))
                {
                    logger.LogDebug("Hole in chunk sequence  " + tsn + " expected " + expectedTsn);
                    break;
                }
                switch (flags)
                {
                case DataChunk.SINGLEFLAG:
                    // singles are easy - just dispatch.
                    if (_ordered && (messageNo != dc.getSSeqNo()))
                    {
                        logger.LogDebug("Hole (single) in message sequence  " + dc.getSSeqNo() + " expected " + messageNo);
                        break;     // not the message we are looking for...
                    }
                    SCTPMessage single = new SCTPMessage(s, dc);
                    if (single.deliver(l))
                    {
                        delivered.Add(dc);
                        messageNo++;
                        s.setNextMessageSeqIn(messageNo);
                    }
                    break;

                case DataChunk.BEGINFLAG:
                    if (_ordered && (messageNo != dc.getSSeqNo()))
                    {
                        logger.LogDebug("Hole (begin) in message sequence  " + dc.getSSeqNo() + " expected " + messageNo);
                        break;     // not the message we are looking for...
                    }
                    message = new SortedArray <DataChunk>();
                    message.Add(dc);
                    logger.LogDebug("new message no" + dc.getSSeqNo() + " starts with  " + dc.getTsn());
                    break;

                case 0:     // middle
                    if (message != null)
                    {
                        message.Add(dc);
                        logger.LogDebug("continued message no" + dc.getSSeqNo() + " with  " + dc.getTsn());
                    }
                    else
                    {
                        // perhaps check sno ?
                        logger.LogDebug("Middle with no start" + dc.getSSeqNo() + " tsn " + dc.getTsn());
                    }
                    break;

                case DataChunk.ENDFLAG:
                    if (message != null)
                    {
                        message.Add(dc);
                        logger.LogDebug("finished message no" + dc.getSSeqNo() + " with  " + dc.getTsn());
                        SCTPMessage deliverable = new SCTPMessage(s, message);
                        if (deliverable.deliver(l))
                        {
                            message.AddToList(delivered);
                            messageNo++;
                            s.setNextMessageSeqIn(messageNo);
                        }
                        message = null;
                    }
                    else
                    {
                        logger.LogDebug("End with no start" + dc.getSSeqNo() + " tsn " + dc.getTsn());
                        message = null;
                    }
                    break;

                default:
                    throw new Exception("[IllegalStateException] Impossible value in stream logic");
                }
                expectedTsn = tsn + 1;
            }
            stash.RemoveWhere((dc) => { return(delivered.Contains(dc)); });
        }