void OnCommandReceived(UdpBitStream buffer) { if (ParseHeader(ref buffer)) { stats.CommandsReceived += 1; buffer.Ptr = UdpHeader.GetSize(socket); UdpCommandType cmd = (UdpCommandType)buffer.ReadByte(8); switch (cmd) { case UdpCommandType.Connect: OnCommandConnect(buffer); break; case UdpCommandType.Accepted: OnCommandAccepted(buffer); break; case UdpCommandType.Refused: OnCommandRefused(buffer); break; case UdpCommandType.Disconnected: OnCommandDisconnected(buffer); break; case UdpCommandType.Ping: OnCommandPing(buffer); break; default: ConnectionError(UdpConnectionError.IncorrectCommand); break; } } }
internal void SendCommand(UdpCommandType cmd) { if (CheckCanSend(true) == UdpSendFailReason.None) { UdpStream stream = socket.GetWriteStream(mtu << 3, UdpSocket.HeaderBitSize); stream.WriteByte((byte)cmd, 8); UdpHeader header = MakeHeader(false); header.Pack(stream, socket); UdpHandle handle = MakeHandle(ref header); handle.Object = null; if (SendStream(stream, handle, false)) { // track stats stats.PacketSent((uint)stream.Ptr >> 3); socket.Stats.PacketSent((uint)stream.Ptr >> 3); } else { // should we do something here????? } } }
void RecvUnconnectedPacket(UdpBitStream buff, UdpEndPoint ep) { buff.Ptr = UdpHeader.GetSize(this); if (buff.ReadByte(8) == (byte)UdpCommandType.Connect) { if (Config.AllowIncommingConnections && ((connLookup.Count + pendingConnections.Count) < Config.ConnectionLimit || Config.ConnectionLimit == -1)) { if (Config.AutoAcceptIncommingConnections) { AcceptConnection(ep); } else { if (pendingConnections.Add(ep)) { Raise(UdpEvent.PUBLIC_CONNECT_REQUEST, ep); } } } else { SendRefusedCommand(ep); } } else { UdpLog.Debug("received invalid header byte in unconnected packet from {0}", ep.ToString()); } }
internal void SendObject(object o) { serializer.SendNext(o); while (serializer.HasQueuedObjects) { UdpSendFailReason reason = CheckCanSend(false); if (reason != UdpSendFailReason.None) { while (serializer.HasQueuedObjects) { socket.Raise(UdpEvent.PUBLIC_OBJECT_SEND_FAILED, this, serializer.NextObject(), reason); } break; } UdpStream stream = socket.GetWriteStream(mtu << 3, UdpSocket.HeaderBitSize); object obj = serializer.NextObject(); if (serializer.Pack(stream, ref obj)) { if (stream.Overflowing && (socket.Config.AllowPacketOverflow == false)) { UdpLog.Error("stream to {0} is overflowing, not sending", endpoint.ToString()); socket.Raise(UdpEvent.PUBLIC_OBJECT_SEND_FAILED, this, obj, UdpSendFailReason.StreamOverflow); return; } UdpHeader header = MakeHeader(true); header.Pack(stream, socket); UdpHandle handle = MakeHandle(ref header); handle.Object = obj; if (SendStream(stream, handle, alwaysSendMtu)) { // track stats stats.PacketSent((uint)stream.Ptr >> 3); socket.Statistics.PacketSent((uint)stream.Ptr >> 3); // push object to user thread socket.Raise(UdpEvent.PUBLIC_OBJECT_SENT, this, obj); Log.info(this, "SendObject##UdpSocket.HeaderBitSize: " + (UdpSocket.HeaderBitSize >> 3)); Log.info(this, "SendObject##size: " + (stream.Ptr >> 3)); } else { socket.Raise(UdpEvent.PUBLIC_OBJECT_SEND_FAILED, this, obj, UdpSendFailReason.SocketError); } } else { socket.Raise(UdpEvent.PUBLIC_OBJECT_SEND_FAILED, this, obj, UdpSendFailReason.SerializerReturnedFalse); } } }
UdpHandle MakeHandle(ref UdpHeader header) { UdpHandle handle = new UdpHandle(); handle.IsObject = header.IsObject; handle.ObjSequence = header.ObjSequence; handle.SendTime = header.Now; return(handle); }
void AckHandles(UdpHeader header, bool updateRtt) { while (!sendWindow.Empty) { UdpHandle handle = sendWindow.Peek(); int seqDistance = UdpMath.SeqDistance(handle.ObjSequence, header.AckSequence, UdpHeader.SEQ_PADD); if (seqDistance > 0) { break; } if (handle.IsObject) { if (seqDistance <= -UdpSocket.AckRedundancy) { // track stats stats.PacketLost(); socket.Statistics.PacketLost(); // handle lost ObjectLost(handle.Object); } else { if ((header.AckHistory & (1UL << -seqDistance)) != 0UL) { // track stats stats.PacketDelivered(); socket.Statistics.PacketDelivered(); // handle delivered objects ObjectDelivered(handle.Object); } else { // track stats stats.PacketLost(); socket.Statistics.PacketLost(); // handle ObjectLost(handle.Object); } } } if (seqDistance == 0 && header.AckTime > 0) { UpdatePing(recvTime, handle.SendTime, header.AckTime); } sendWindow.Dequeue(); } }
internal void SendObject(object o) { serializer.SendNext(o); while (serializer.HasQueuedObjects) { UdpSendFailReason reason = CheckCanSend(false); if (reason != UdpSendFailReason.None) { while (serializer.HasQueuedObjects) { socket.Raise(UdpEvent.PUBLIC_OBJECT_SEND_FAILED, this, serializer.NextObject(), reason); } break; } UdpBitStream stream = new UdpBitStream(socket.GetWriteBuffer(), mtu, UdpHeader.GetSize(socket)); object obj = serializer.NextObject(); if (serializer.Pack(ref stream, ref obj)) { if (stream.Overflowing && (socket.Config.AllowPacketOverflow == false)) { UdpLog.Error("stream to {0} is overflowing, not sending", endpoint.ToString()); socket.Raise(UdpEvent.PUBLIC_OBJECT_SEND_FAILED, this, obj, UdpSendFailReason.StreamOverflow); return; } UdpHeader header = MakeHeader(true); header.Pack(new UdpBitStream(stream.Data, mtu, 0), socket); UdpHandle handle = MakeHandle(ref header); handle.Object = obj; if (SendStream(stream, handle, alwaysSendMtu) == false) { socket.Raise(UdpEvent.PUBLIC_OBJECT_SEND_FAILED, this, obj, UdpSendFailReason.SocketError); } else { stats.PacketSent(); } } else { socket.Raise(UdpEvent.PUBLIC_OBJECT_SEND_FAILED, this, obj, UdpSendFailReason.SerializerReturnedFalse); } } }
UdpHeader MakeHeader(bool isObject) { UdpHeader header = new UdpHeader(); header.IsObject = isObject; header.AckHistory = recvHistory; header.AckSequence = recvSequence; header.ObjSequence = UdpMath.SeqNext(sendSequence, UdpHeader.SEQ_MASK); header.Now = socket.GetCurrentTime(); if (recvTime > 0) { header.AckTime = (ushort)UdpMath.Clamp(header.Now - recvTime, 0, socket.Config.MaxPing); } return(header); }
bool ParseHeader(ref UdpBitStream buffer) { UdpHeader header = new UdpHeader(); header.Unpack(new UdpBitStream(buffer.Data, buffer.Length, 0), socket); // Assign bit size if (socket.Config.WritePacketBitSize) { buffer.Length = header.BitSize; } int seqDistance = UdpMath.SeqDistance(header.ObjSequence, recvSequence, UdpHeader.SEQ_PADD); // we have to be within window size if (seqDistance > socket.Config.PacketWindow || seqDistance < -socket.Config.PacketWindow) { ConnectionError(UdpConnectionError.SequenceOutOfBounds); return(false); } // this is an old packet if (seqDistance <= 0) { return(false); } // update receive history if (seqDistance >= socket.Config.AckRedundancy) { recvHistory = 1UL; } else { recvHistory = (recvHistory << seqDistance) | 1UL; } // update our receive stats recvSequence = header.ObjSequence; recvSinceLastSend += 1; // ack sent objects AckHandles(header, true); return(true); }
bool ParseHeader(UdpStream stream) { // we should always start at ptr 0 UdpAssert.Assert(stream.Ptr == 0); UdpHeader header = new UdpHeader(); header.Unpack(stream, socket); // after unpacking the header, the pointer should be at the header size UdpAssert.Assert(stream.Ptr == UdpSocket.HeaderBitSize); int seqDistance = UdpMath.SeqDistance(header.ObjSequence, recvSequence, UdpHeader.SEQ_PADD); // we have to be within window size if (seqDistance > socket.Config.PacketWindow || seqDistance < -socket.Config.PacketWindow) { ConnectionError(UdpConnectionError.SequenceOutOfBounds); return(false); } // this is an old packet if (seqDistance <= 0) { return(false); } // update receive history if (seqDistance >= UdpSocket.AckRedundancy) { recvHistory = 1UL; } else { recvHistory = (recvHistory << seqDistance) | 1UL; } // update our receive stats recvSequence = header.ObjSequence; recvSinceLastSend += 1; // ack sent objects AckHandles(header, true); return(true); }
void SendRefusedCommand(UdpEndPoint endpoint) { UdpBitStream stream = new UdpBitStream(GetWriteBuffer(), Config.DefaultMtu, UdpHeader.GetSize(this)); stream.WriteByte((byte)UdpCommandType.Refused, 8); UdpHeader header = new UdpHeader(); header.IsObject = false; header.AckHistory = 0; header.AckSequence = 1; header.ObjSequence = 1; header.Now = 0; header.Pack(new UdpBitStream(stream.Data, Config.DefaultMtu, 0), this); if (Send(endpoint, stream.Data, UdpMath.BytesRequired(stream.Ptr)) == false) { // do something here? } }
void SendRefusedCommand(UdpEndPoint endpoint) { UdpStream stream = GetWriteStream(Config.PacketSize << 3, HeaderBitSize); stream.WriteByte((byte)UdpCommandType.Refused, 8); UdpHeader header = new UdpHeader(); header.IsObject = false; header.AckHistory = 0; header.AckSequence = 1; header.ObjSequence = 1; header.Now = 0; header.Pack(stream, this); if (Send(endpoint, stream.Data, UdpMath.BytesRequired(stream.Ptr)) == false) { // do something here? } }
internal void SendCommand(UdpCommandType cmd) { if (CheckCanSend(true) == UdpSendFailReason.None) { UdpBitStream stream = new UdpBitStream(socket.GetWriteBuffer(), mtu, UdpHeader.GetSize(socket)); stream.WriteByte((byte)cmd, 8); UdpHeader header = MakeHeader(false); header.Pack(new UdpBitStream(stream.Data, mtu, 0), socket); UdpHandle handle = MakeHandle(ref header); handle.Object = null; if (SendStream(stream, handle, false) == false) { // do something here? } stats.CommandSent += 1; } }
void OnObjectReceived(UdpBitStream buffer) { EnsureClientIsConnected(); if (CheckState(UdpConnectionState.Connected) == false) { return; } if (ParseHeader(ref buffer)) { object obj = null; buffer.Ptr = UdpHeader.GetSize(socket); if (serializer.Unpack(ref buffer, ref obj)) { socket.Raise(UdpEvent.PUBLIC_OBJECT_RECEIVED, this, obj); } stats.PacketReceived(); } }
void AckHandles(UdpHeader header, bool updateRtt) { while (!sendWindow.Empty) { UdpHandle handle = sendWindow.Peek(); int seqDistance = UdpMath.SeqDistance(handle.ObjSequence, header.AckSequence, UdpHeader.SEQ_PADD); if (seqDistance > 0) { break; } if (handle.IsObject) { if (seqDistance <= -socket.Config.AckRedundancy) { ObjectLost(handle.Object); } if ((header.AckHistory & (1UL << -seqDistance)) != 0UL) { ObjectDelivered(handle.Object); } else { ObjectLost(handle.Object); } } if (seqDistance == 0 && header.AckTime > 0) { UpdatePing(recvTime, handle.SendTime, header.AckTime); } sendWindow.Dequeue(); } }
bool ParseHeader(ref UdpBitStream buffer) { UdpHeader header = new UdpHeader(); header.Unpack(new UdpBitStream(buffer.Data, buffer.Length, 0), socket); // Assign bit size if (socket.Config.WritePacketBitSize) { buffer.Length = header.BitSize; } int seqDistance = UdpMath.SeqDistance(header.ObjSequence, recvSequence, UdpHeader.SEQ_PADD); // we have to be within window size if (seqDistance > socket.Config.PacketWindow || seqDistance < -socket.Config.PacketWindow) { ConnectionError(UdpConnectionError.SequenceOutOfBounds); return false; } // this is an old packet if (seqDistance <= 0) return false; // update receive history if (seqDistance >= socket.Config.AckRedundancy) { recvHistory = 1UL; } else { recvHistory = (recvHistory << seqDistance) | 1UL; } // update our receive stats recvSequence = header.ObjSequence; recvSinceLastSend += 1; // ack sent objects AckHandles(header, true); return true; }
UdpHeader MakeHeader(bool isObject) { UdpHeader header = new UdpHeader(); header.IsObject = isObject; header.AckHistory = recvHistory; header.AckSequence = recvSequence; header.ObjSequence = UdpMath.SeqNext(sendSequence, UdpHeader.SEQ_MASK); header.Now = socket.GetCurrentTime(); if (recvTime > 0) header.AckTime = (ushort) UdpMath.Clamp(header.Now - recvTime, 0, socket.Config.MaxPing); return header; }
UdpHandle MakeHandle(ref UdpHeader header) { UdpHandle handle = new UdpHandle(); handle.IsObject = header.IsObject; handle.ObjSequence = header.ObjSequence; handle.SendTime = header.Now; return handle; }