/// <summary> /// Requests a new association be created. /// </summary> /// <param name="destination">The UDP endpoint to attempt to create the association with.</param> /// <param name="sourcePort">The SCTP source port.</param> /// <param name="destinationPort">The SCTP destination port.</param> /// <returns>An SCTP association.</returns> public SctpAssociation Associate( IPEndPoint destination, ushort sourcePort, ushort destinationPort, ushort numberOutboundStreams = SctpAssociation.DEFAULT_NUMBER_OUTBOUND_STREAMS, ushort numberInboundStreams = SctpAssociation.DEFAULT_NUMBER_INBOUND_STREAMS) { var association = new SctpAssociation( this, destination, sourcePort, destinationPort, DEFAULT_UDP_MTU, numberOutboundStreams, numberInboundStreams); if (_associations.TryAdd(association.ID, association)) { association.Init(); return(association); } else { logger.LogWarning("SCTP transport failed to add association."); association.Shutdown(); return(null); } }
/// <summary> /// Event handler for a packet receive on the UDP encapsulation socket. /// </summary> /// <param name="receiver">The UDP receiver that received the packet.</param> /// <param name="localPort">The local port the packet was received on.</param> /// <param name="remoteEndPoint">The remote end point the packet was received from.</param> /// <param name="packet">A buffer containing the packet.</param> private void OnEncapsulationSocketPacketReceived(UdpReceiver receiver, int localPort, IPEndPoint remoteEndPoint, byte[] packet) { try { if (!SctpPacket.VerifyChecksum(packet, 0, packet.Length)) { logger.LogWarning($"SCTP packet from UDP {remoteEndPoint} dropped due to invalid checksum."); } else { var sctpPacket = SctpPacket.Parse(packet, 0, packet.Length); // Process packet. if (sctpPacket.Header.VerificationTag == 0) { GotInit(sctpPacket, remoteEndPoint); } else if (sctpPacket.Chunks.Any(x => x.KnownType == SctpChunkType.COOKIE_ECHO)) { // The COOKIE ECHO chunk is the 3rd step in the SCTP handshake when the remote party has // requested a new association be created. var cookie = base.GetCookie(sctpPacket); if (cookie.IsEmpty()) { logger.LogWarning($"SCTP error acquiring handshake cookie from COOKIE ECHO chunk."); } else { logger.LogDebug($"SCTP creating new association for {remoteEndPoint}."); var association = new SctpAssociation(this, cookie, localPort); if (_associations.TryAdd(association.ID, association)) { if (sctpPacket.Chunks.Count > 1) { // There could be DATA chunks after the COOKIE ECHO chunk. association.OnPacketReceived(sctpPacket); } } else { logger.LogError($"SCTP failed to add new association to dictionary."); } } } else { // TODO: Lookup the existing association for the packet. _associations.Values.First().OnPacketReceived(sctpPacket); } } } catch (Exception excp) { logger.LogError($"Exception SctpTransport.OnEncapsulationSocketPacketReceived. {excp}"); } }