コード例 #1
0
        /* <pre>
         * 5.2.1.  INIT Received in COOKIE-WAIT or COOKIE-ECHOED State (Item B)
         *
         * This usually indicates an initialization collision, i.e., each
         * endpoint is attempting, at about the same time, to establish an
         * association with the other endpoint.
         *
         * Upon receipt of an INIT in the COOKIE-WAIT state, an endpoint MUST
         * respond with an INIT ACK using the same parameters it sent in its
         * original INIT chunk (including its Initiate Tag, unchanged).  When
         * responding, the endpoint MUST send the INIT ACK back to the same
         * address that the original INIT (sent by this endpoint) was sent.
         *
         * Upon receipt of an INIT in the COOKIE-ECHOED state, an endpoint MUST
         * respond with an INIT ACK using the same parameters it sent in its
         * original INIT chunk (including its Initiate Tag, unchanged), provided
         * that no NEW address has been added to the forming association.  If
         * the INIT message indicates that a new address has been added to the
         * association, then the entire INIT MUST be discarded, and NO changes
         * should be made to the existing association.  An ABORT SHOULD be sent
         * in response that MAY include the error 'Restart of an association
         * with new addresses'.  The error SHOULD list the addresses that were
         * added to the restarting association.
         *
         * When responding in either state (COOKIE-WAIT or COOKIE-ECHOED) with
         * an INIT ACK, the original parameters are combined with those from the
         * newly received INIT chunk.  The endpoint shall also generate a State
         * Cookie with the INIT ACK.  The endpoint uses the parameters sent in
         * its INIT to calculate the State Cookie.
         *
         * After that, the endpoint MUST NOT change its state, the T1-init timer
         * shall be left running, and the corresponding TCB MUST NOT be
         * destroyed.  The normal procedures for handling State Cookies when a
         * TCB exists will resolve the duplicate INITs to a single association.
         *
         * For an endpoint that is in the COOKIE-ECHOED state, it MUST populate
         * its Tie-Tags within both the association TCB and inside the State
         * Cookie (see Section 5.2.2 for a description of the Tie-Tags).
         * </pre>
         */
        public virtual Chunk[] inboundInit(InitChunk init)
        {
            Chunk[] reply = null;
            _peerVerTag = init.getInitiateTag();
            _winCredit  = init.getAdRecWinCredit();
            _farTSN     = (uint)(init.getInitialTSN() - 1);

            _maxOutStreams = Math.Min(init.getNumInStreams(), MAXSTREAMS);
            _maxInStreams  = Math.Min(init.getNumOutStreams(), MAXSTREAMS);
            InitAckChunk iac = new InitAckChunk();

            iac.setAdRecWinCredit(MAXBUFF);
            iac.setNumInStreams(_maxInStreams);
            iac.setNumOutStreams(_maxOutStreams);
            iac.setInitialTSN(_nearTSN);
            iac.setInitiateTag(_myVerTag);
            CookieHolder cookie = new CookieHolder();

            cookie.cookieData = new byte[Association.COOKIESIZE];
            cookie.cookieTime = Time.CurrentTimeMillis();
            _random.NextBytes(cookie.cookieData);
            iac.setCookie(cookie.cookieData);
            _cookies.Add(cookie);

            byte[] fse = init.getFarSupportedExtensions();
            if (fse != null)
            {
                iac.setSupportedExtensions(this.getUnionSupportedExtensions(fse));
            }
            reply    = new Chunk[1];
            reply[0] = iac;
            Logger.Debug("Got in bound init :" + init.ToString());
            Logger.Debug("Replying with init-ack :" + iac.ToString());
            return(reply);
        }
コード例 #2
0
        public void sendInit()
        {
            InitChunk c = new InitChunk();

            c.setInitialTSN(this._nearTSN);
            c.setNumInStreams(this.MAXSTREAMS);
            c.setNumOutStreams(this.MAXSTREAMS);
            c.setAdRecWinCredit(MAXBUFF);
            c.setInitiate(this.getMyVerTag());
            Chunk[] s = new Chunk[1];
            s[0]        = c;
            this._state = State.COOKIEWAIT;
            try {
                this.send(s);
            }
            catch (EndOfStreamException end) {
                unexpectedClose(end);
                Logger.Error(end.ToString());
            }             // todo need timer here.....
        }
コード例 #3
0
ファイル: ThreadedAssociation.cs プロジェクト: sgf/SCTP
        /*
         *
         *
         * o  The initial value of ssthresh MAY be arbitrarily high (for
         * example, implementations MAY use the size of the receiver
         * advertised window).
         */

        void setSsthresh(InitChunk init)
        {
            this._ssthresh = init.getAdRecWinCredit();
        }
コード例 #4
0
ファイル: ThreadedAssociation.cs プロジェクト: sgf/SCTP
 /*
  * 6.2.1.  Processing a Received SACK
  *
  * Each SACK an endpoint receives contains an a_rwnd value.  This value
  * represents the amount of buffer space the data receiver, at the time
  * of transmitting the SACK, has left of its total receive buffer space
  * (as specified in the INIT/INIT ACK).  Using a_rwnd, Cumulative TSN
  * Ack, and Gap Ack Blocks, the data sender can develop a representation
  * of the peer's receive buffer space.
  *
  * One of the problems the data sender must take into account when
  * processing a SACK is that a SACK can be received out of order.  That
  * is, a SACK sent by the data receiver can pass an earlier SACK and be
  * received first by the data sender.  If a SACK is received out of
  *
  *
  *
  *
  * Stewart                     Standards Track                    [Page 81]
  * 
  * RFC 4960          Stream Control Transmission Protocol    September 2007
  *
  *
  * order, the data sender can develop an incorrect view of the peer's
  * receive buffer space.
  *
  * Since there is no explicit identifier that can be used to detect
  * out-of-order SACKs, the data sender must use heuristics to determine
  * if a SACK is new.
  *
  * An endpoint SHOULD use the following rules to calculate the rwnd,
  * using the a_rwnd value, the Cumulative TSN Ack, and Gap Ack Blocks in
  * a received SACK.
  */
 /*
  * A) At the establishment of the association, the endpoint initializes
  * the rwnd to the Advertised Receiver Window Credit (a_rwnd) the
  * peer specified in the INIT or INIT ACK.
  */
 public override Chunk[] inboundInit(InitChunk init)
 {
     _rwnd = init.getAdRecWinCredit();
     setSsthresh(init);
     return(base.inboundInit(init));
 }
コード例 #5
0
ファイル: MockAssociation.cs プロジェクト: sgf/SCTP
 public override Chunk[] inboundInit(InitChunk i)
 {
     return(base.inboundInit(i));
 }
コード例 #6
0
        /**
         *
         * @param c - Chunk to be processed
         * @return valid - false if the remaining chunks of the packet should be
         * ignored.
         * @throws IOException
         * @throws SctpPacketFormatException
         */
        private bool deal(Chunk c, List <Chunk> replies)
        {
            Chunk.CType ty       = c.getType();
            bool        ret      = true;
            State       oldState = _state;

            Chunk[] reply = null;
            switch (ty)
            {
            case Chunk.CType.INIT:
                if (acceptableStateForInboundInit())
                {
                    InitChunk init = (InitChunk)c;
                    reply = inboundInit(init);
                }
                else
                {
                    Logger.Debug("Got an INIT when state was " + _state.ToString() + " - ignoring it for now ");
                }
                break;

            case Chunk.CType.INITACK:
                Logger.Debug("got initack " + c.ToString());
                if (_state == State.COOKIEWAIT)
                {
                    InitAckChunk iack = (InitAckChunk)c;
                    reply = iackDeal(iack);
                }
                else
                {
                    Logger.Debug("Got an INITACK when not waiting for it - ignoring it");
                }
                break;

            case Chunk.CType.COOKIE_ECHO:
                Logger.Debug("got cookie echo " + c.ToString());
                reply = cookieEchoDeal((CookieEchoChunk)c);
                if (reply.Length > 0)
                {
                    ret = !typeof(ErrorChunk).IsAssignableFrom(reply[0].GetType());                             // ignore any following data chunk.
                }
                break;

            case Chunk.CType.COOKIE_ACK:
                Logger.Debug("got cookie ack " + c.ToString());
                if (_state == State.COOKIEECHOED)
                {
                    _state = State.ESTABLISHED;
                }
                break;

            case Chunk.CType.DATA:
                Logger.Debug("got data " + c.ToString());
                reply = dataDeal((DataChunk)c);
                break;

            case Chunk.CType.ABORT:
                // no reply we should just bail I think.
                _rcv = null;
                _transp.Close();
                break;

            case Chunk.CType.HEARTBEAT:
                reply = ((HeartBeatChunk)c).mkReply();
                break;

            case Chunk.CType.SACK:
                Logger.Debug("got tsak for TSN " + ((SackChunk)c).getCumuTSNAck());
                reply = sackDeal((SackChunk)c);
                // fix the outbound list here
                break;

            case Chunk.CType.RE_CONFIG:
                reply = reconfigState.deal((ReConfigChunk)c);
                break;
            }
            if (reply != null)
            {
                foreach (Chunk r in reply)
                {
                    replies.Add(r);
                }
                // theoretically could be multiple DATA in a single packet -
                // we'd send multiple SACKs in reply - ToDo fix that
            }
            if ((_state == State.ESTABLISHED) && (oldState != State.ESTABLISHED))
            {
                if (null != _al)
                {
                    _al.onAssociated(this);
                }
                reconfigState = new ReconfigState(this, _farTSN);
            }
            if ((oldState == State.ESTABLISHED) && (_state != State.ESTABLISHED))
            {
                if (null != _al)
                {
                    _al.onDisAssociated(this);
                }
            }
            return(ret);
        }