UdpSendStatus SendFragmentedMessage(UdpRawMessage message, IChannel channel) { message.Position = 0; int mtu = this.Mtu; ushort frame = 1; ushort frames = (ushort)Math.Ceiling(message.Length / (float)(mtu - Datagram.GetHeaderSize(true))); ushort groupId = GetNextFragementationGroupId(); do { Debug.Assert(frame <= frames, "frame > frames"); Datagram datagramFrag = Datagram.CreateNew(peer.Configuration.MemoryStreamPool, mtu); datagramFrag.Type = MessageType.UserData; datagramFrag.Channel = channel.Descriptor.Channel; datagramFrag.DeliveryType = channel.Descriptor.DeliveryType; datagramFrag.FragmentationInfo = new Datagram.FragmentInfo(groupId, frame, frames); datagramFrag.ConnectionKey = this.EndPoint.ConnectionKey; int toCopy = mtu - Datagram.GetHeaderSize(true); if (toCopy > message.Length - message.Position) { toCopy = message.Length - message.Position; } message.CopyTo(datagramFrag.BaseStream, toCopy); channel.SendDatagram(datagramFrag); frame++; } while (message.Position < message.Length); message.Dispose(); return(UdpSendStatus.Enqueued); }
bool CheckCanBeSendUnfragmented(UdpRawMessage datagram) { if (datagram.Length + Datagram.GetHeaderSize(false) > Mtu) { return(false); } return(true); }
protected override UdpSendStatus SendRawMessage(Networking.Udp.Messages.MessageInfo messageInfo) { using (messageInfo.Message) { UdpRawMessage encryptedMessage = messageInfo.Message.Encrypt(cipher); return(base.SendRawMessage(new Networking.Udp.Messages.MessageInfo(encryptedMessage, messageInfo.DeliveryType, messageInfo.Channel))); } }
void CloseInternal(DisconnectReason reason, UdpRawMessage payload) { if (Status == UdpConnectionStatus.Disconnected) { return; } ChangeStatus(UdpConnectionStatus.Disconnected); logger.Trace($"{this} closing with ({reason})"); var disconnectReq_ = disconnectReq; if (disconnectReq_ != null) { disconnectReq_.Dispose(); disconnectReq = null; } var args = new ConnectionClosedEventArgs(this, reason, payload); logger.Trace($"{this} closing pre event syncronization"); peer.Configuration.SynchronizeSafe(() => { logger.Trace($"{this} firing event connection OnConnectionClosed"); try { OnConnectionClosed(args); } catch (Exception ex) { logger.Error($"Unhandled exception on {this.GetType().Name}.{nameof(OnConnectionClosed)}: {ex}"); } logger.Trace($"{this} firing event peer OnConnectionClosed"); peer.OnConnectionClosedInternalSynchronized(args); logger.Trace($"{this} events fired"); }, logger); logger.Trace($"{this} closing post event syncronization"); var connectTcs_ = this.connectTcs; if (connectTcs_ != null) { connectTcs_.TrySetException(new ConnectionFailed(reason)); } var disconnectTcs_ = this.disconnectTcs; if (disconnectTcs_ != null) { disconnectTcs_.TrySetResult(null); } logger.Info($"{this} closed ({reason})"); }
Datagram CreateSpecialDatagram(MessageType messageType, UdpRawMessage payload) { if (!CheckCanBeSendUnfragmented(payload)) { throw new ArgumentException($"Payload can be datagram only smaller than current MTU ({Mtu})"); } var datagram = Datagram.CreateNew(peer.Configuration.MemoryStreamPool, (int)payload.BaseStream.Length); datagram.Type = messageType; payload.BaseStream.Position = 0; payload.BaseStream.CopyTo(datagram.BaseStream); return(datagram); }
public virtual async Task CloseAsync(UdpRawMessage payload) { try { disconnectTcs = new TaskCompletionSource <object>(TaskCreationOptions.RunContinuationsAsynchronously); Close(payload); await disconnectTcs.Task; } finally { disconnectTcs = null; } }
void ReleaseMessage(UdpRawMessage message, DeliveryType deliveryType, int channel) { message.Position = 0; peer.Configuration.SynchronizeSafe(() => { try { OnMessageReceived(new MessageInfo(message, deliveryType, channel)); } catch (Exception ex) { logger.Error($"Unhandled exception on {this.GetType().Name}.{nameof(OnMessageReceived)}: {ex}"); } }, logger); }
internal async Task Connect(UdpRawMessage payload) { try { connectTcs = new TaskCompletionSource <object>(TaskCreationOptions.RunContinuationsAsynchronously); StartConnect(payload); await connectTcs.Task; } finally { connectTcs = null; } }
internal void StartConnect(UdpRawMessage payload) { if (!CheckStatus(UdpConnectionStatus.Waiting)) { throw new InvalidOperationException($"Couldn't connect wrong status: {Status}, expected {UdpConnectionStatus.Waiting}"); } logger.Info($"Connecting to {EndPoint.EndPoint}"); ChangeStatus(UdpConnectionStatus.Connecting); lastStatusPacketSent = DateTime.UtcNow; if (payload == null) { connectReq = CreateSpecialDatagram(MessageType.ConnectReq); } else { connectReq = CreateSpecialDatagram(MessageType.ConnectReq, payload); payload.Dispose(); } connectReq.DontDisposeOnSend = true; SendDatagramAsync(connectReq); }
public virtual void Close(UdpRawMessage payload) { if (Status >= UdpConnectionStatus.Disconnecting) { return; } ChangeStatus(UdpConnectionStatus.Disconnecting); Datagram disconnectReq; if (payload == null) { disconnectReq = CreateSpecialDatagram(MessageType.DisconnectReq); } else { disconnectReq = CreateSpecialDatagram(MessageType.DisconnectReq, payload); } disconnectReq.DontDisposeOnSend = true; this.disconnectReq = disconnectReq; lastStatusPacketSent = DateTime.UtcNow; SendDatagramAsync(disconnectReq); payload?.Dispose(); }
public OnAcceptConnectionEventArgs(EndPoint endpoint, UdpRawMessage payload) { this.Endpoint = endpoint; this.Payload = payload; }
public ConnectionClosedEventArgs(UdpConnection connection, DisconnectReason reason, UdpRawMessage payload) { this.Connection = connection; this.Reason = reason; this.Payload = payload; }