예제 #1
0
        public override void enqueue(DataChunk d)
        {
            // todo - this worries me - 2 nested synchronized
            //logger.LogDebug(" Aspiring to enqueue " + d.ToString());

            lock (this)
            {
                long now = TimeExtension.CurrentTimeMillis();
                d.setTsn(_nearTSN++);
                d.setGapAck(false);
                d.setRetryTime(now + getT3() - 1);
                d.setSentTime(now);
                SimpleSCTPTimer.setRunnable(run, getT3());
                reduceRwnd(d.getDataSize());
                //_outbound.put(new Long(d.getTsn()), d);
                //logger.LogDebug(" DataChunk enqueued " + d.ToString());
                // all sorts of things wrong here - being in a synchronized not the least of them

                Chunk[] toSend = addSackIfNeeded(d);
                try
                {
                    send(toSend);
                    //logger.LogDebug("sent, syncing on inFlight... " + d.getTsn());
                    lock (_inFlight)
                    {
                        _inFlight.Add(d.getTsn(), d);
                    }

                    //logger.LogDebug("added to inFlight... " + d.getTsn());
                }
                catch (SctpPacketFormatException ex)
                {
                    logger.LogError("badly formatted chunk " + d.ToString());
                    logger.LogError(ex.ToString());
                }
                catch (EndOfStreamException end)
                {
                    unexpectedClose(end);
                    logger.LogError(end.ToString());
                }
                catch (IOException ex)
                {
                    logger.LogError("Can not send chunk " + d.ToString());
                    logger.LogError(ex.ToString());
                }
            }

            //logger.LogDebug("leaving enqueue" + d.getTsn());
        }
예제 #2
0
            public void run()
            {
                ///logger.LogDebug("T1 init timer expired in state " + ta._state.ToString());

                if ((ta._state == State.COOKIEECHOED) || (ta._state == State.COOKIEWAIT))
                {
                    try
                    {
                        if (ta._state == State.COOKIEWAIT)
                        {
                            ta.sendInit();
                        }
                        else
                        {
                            // COOKIEECHOED
                            ta.send(ta._stashCookieEcho);
                        }
                    }
                    catch (EndOfStreamException end)
                    {
                        ta.unexpectedClose(end);
                        logger.LogError(end.ToString());
                    }
                    catch (Exception ex)
                    {
                        logger.LogError("Cant send Init/cookie retry " + retries + " because " + ex.ToString());
                    }

                    retries++;
                    if (retries < MAX_INIT_RETRANS)
                    {
                        SimpleSCTPTimer.setRunnable(run, ta.getT1());
                    }
                }
                else
                {
                    //logger.LogDebug("T1 init timer expired with nothing to do");
                }
            }
예제 #3
0
        /*
         * In instances where its peer endpoint is multi-homed, if an endpoint
         * receives a SACK that advances its Cumulative TSN Ack Point, then it
         * should update its cwnd (or cwnds) apportioned to the destination
         * addresses to which it transmitted the acknowledged data.  However, if
         *
         *
         *
         * Stewart                     Standards Track                    [Page 96]
         *
         * RFC 4960          Stream Control Transmission Protocol    September 2007
         *
         *
         * the received SACK does not advance the Cumulative TSN Ack Point, the
         * endpoint MUST NOT adjust the cwnd of any of the destination
         * addresses.
         *
         * Because an endpoint's cwnd is not tied to its Cumulative TSN Ack
         * Point, as duplicate SACKs come in, even though they may not advance
         * the Cumulative TSN Ack Point an endpoint can still use them to clock
         * out new data.  That is, the data newly acknowledged by the SACK
         * diminishes the amount of data now in flight to less than cwnd, and so
         * the current, unchanged value of cwnd now allows new data to be sent.
         * On the other hand, the increase of cwnd must be tied to the
         * Cumulative TSN Ack Point advancement as specified above.  Otherwise,
         * the duplicate SACKs will not only clock out new data, but also will
         * adversely clock out more new data than what has just left the
         * network, during a time of possible congestion.
         *
         * o  When the endpoint does not transmit data on a given transport
         * address, the cwnd of the transport address should be adjusted to
         * max(cwnd/2, 4*MTU) per RTO.
         *
         */

        // timer goes off,
        public void run()
        {
            if (canSend())
            {
                long now = TimeExtension.CurrentTimeMillis();
                //logger.LogDebug("retry timer went off at " + now);
                List <DataChunk> dcs = new List <DataChunk>();
                int  space           = _transpMTU - 12;// room for packet header
                bool resetTimer      = false;
                lock (_inFlight)
                {
                    foreach (var kvp in _inFlight)
                    {
                        DataChunk d = kvp.Value;
                        long      k = kvp.Key;
                        if (d.getGapAck())
                        {
                            //logger.LogDebug("skipping gap-acked tsn " + d.getTsn());
                            continue;
                        }

                        if (d.getRetryTime() <= now)
                        {
                            space -= d.getLength();
                            //logger.LogDebug("available space in pkt is " + space);
                            if (space <= 0)
                            {
                                resetTimer = true;
                                break;
                            }
                            else
                            {
                                dcs.Add(d);
                                d.setRetryTime(now + getT3() - 1);
                            }
                        }
                        else
                        {
                            //logger.LogDebug("retry not yet due for  " + d.ToString());
                            resetTimer = true;
                        }
                    }
                }

                if (dcs.Count != 0)
                {
                    dcs.Sort();
                    DataChunk[] da = new DataChunk[dcs.Count];
                    int         i  = 0;
                    foreach (DataChunk d in dcs)
                    {
                        da[i++] = d;
                    }

                    resetTimer = true;
                    try
                    {
                        //logger.LogDebug("Sending retry for  " + da.Length + " data chunks");
                        this.send(da);
                    }
                    catch (EndOfStreamException end)
                    {
                        logger.LogWarning("Retry send failed " + end.ToString());
                        unexpectedClose(end);
                        resetTimer = false;
                    }
                    catch (Exception ex)
                    {
                        logger.LogError("Cant send retry - eek " + ex.ToString());
                    }
                }
                else
                {
                    //logger.LogDebug("Nothing to do ");
                }

                if (resetTimer)
                {
                    SimpleSCTPTimer.setRunnable(run, getT3());
                    //logger.LogDebug("Try again in a while  " + getT3());
                }
            }
        }
예제 #4
0
 public override void associate()
 {
     sendInit();
     SimpleSCTPTimer.setRunnable(new AssocRun(this).run, getT1());
 }