/// <summary> /// Gets an SCTP packet for a control (non-data) chunk. /// </summary> /// <param name="chunk">The control chunk to get a packet for.</param> /// <returns>A single control chunk SCTP packet.</returns> public SctpPacket GetControlPacket(SctpChunk chunk) { SctpPacket pkt = new SctpPacket( _sctpSourcePort, _sctpDestinationPort, _remoteVerificationTag); pkt.AddChunk(chunk); return(pkt); }
/// <summary> /// Sends a SCTP chunk to the remote party. /// </summary> /// <param name="chunk">The chunk to send.</param> internal void SendChunk(SctpChunk chunk) { if (!_wasAborted) { SctpPacket pkt = new SctpPacket( _sctpSourcePort, _sctpDestinationPort, _remoteVerificationTag); pkt.AddChunk(chunk); byte[] buffer = pkt.GetBytes(); _sctpTransport.Send(ID, buffer, 0, buffer.Length); } }
/// <summary> /// Creates the INIT ACK chunk and packet to send as a response to an SCTP /// packet containing an INIT chunk. /// </summary> /// <param name="initPacket">The received packet containing the INIT chunk.</param> /// <param name="remoteEP">Optional. The remote IP end point the INIT packet was /// received on. For transports that don't use an IP transport directly this parameter /// can be set to null and it will not form part of the COOKIE ECHO checks.</param> /// <returns>An SCTP packet with a single INIT ACK chunk.</returns> protected SctpPacket GetInitAck(SctpPacket initPacket, IPEndPoint remoteEP) { SctpInitChunk initChunk = initPacket.Chunks.Single(x => x.KnownType == SctpChunkType.INIT) as SctpInitChunk; SctpPacket initAckPacket = new SctpPacket( initPacket.Header.DestinationPort, initPacket.Header.SourcePort, initChunk.InitiateTag); var cookie = GetInitAckCookie( initPacket.Header.DestinationPort, initPacket.Header.SourcePort, initChunk.InitiateTag, initChunk.InitialTSN, initChunk.ARwnd, remoteEP != null ? remoteEP.ToString() : string.Empty, (int)(initChunk.CookiePreservative / 1000)); var json = cookie.ToJson(); var jsonBuffer = Encoding.UTF8.GetBytes(json); using (HMACSHA256 hmac = new HMACSHA256(_hmacKey)) { var result = hmac.ComputeHash(jsonBuffer); cookie.HMAC = result.HexStr(); } var jsonWithHMAC = cookie.ToJson(); var jsonBufferWithHMAC = Encoding.UTF8.GetBytes(jsonWithHMAC); SctpInitChunk initAckChunk = new SctpInitChunk( SctpChunkType.INIT_ACK, cookie.Tag, cookie.TSN, cookie.ARwnd, SctpAssociation.DEFAULT_NUMBER_OUTBOUND_STREAMS, SctpAssociation.DEFAULT_NUMBER_INBOUND_STREAMS); initAckChunk.StateCookie = jsonBufferWithHMAC; initAckChunk.UnrecognizedPeerParameters = initChunk.UnrecognizedPeerParameters; initAckPacket.AddChunk(initAckChunk); return(initAckPacket); }
/// <summary> /// Send an SCTP packet with one of the error type chunks (ABORT or ERROR) to the remote peer. /// </summary> /// <param name=isAbort">Set to true to use an ABORT chunk otherwise an ERROR chunk will be used.</param> /// <param name="desintationPort">The SCTP destination port.</param> /// <param name="sourcePort">The SCTP source port.</param> /// <param name="initiateTag">If available the initial tag for the remote peer.</param> /// <param name="error">The error to send.</param> private void SendError( bool isAbort, ushort destinationPort, ushort sourcePort, uint initiateTag, ISctpErrorCause error) { SctpPacket errorPacket = new SctpPacket( destinationPort, sourcePort, initiateTag); SctpErrorChunk errorChunk = isAbort ? new SctpAbortChunk(true) : new SctpErrorChunk(); errorChunk.AddErrorCause(error); errorPacket.AddChunk(errorChunk); var buffer = errorPacket.GetBytes(); Send(null, buffer, 0, buffer.Length); }
/// <summary> /// Attempts to create an association with a remote party by sending an initialisation /// control chunk. /// </summary> private void SendInit() { if (!_wasAborted) { // A packet containing an INIT chunk MUST have a zero Verification Tag (RFC4960 Pg 15). SctpPacket init = new SctpPacket(_sctpSourcePort, _sctpDestinationPort, 0); SctpInitChunk initChunk = new SctpInitChunk( SctpChunkType.INIT, VerificationTag, TSN, ARwnd, _numberOutboundStreams, _numberInboundStreams); init.AddChunk(initChunk); SetState(SctpAssociationState.CookieWait); byte[] buffer = init.GetBytes(); _sctpTransport.Send(ID, buffer, 0, buffer.Length); _t1Init = new Timer(T1InitTimerExpired, init, T1_INIT_TIMER_MILLISECONDS, T1_INIT_TIMER_MILLISECONDS); } }