private static void HandleMessage(NetMessageType type, NetConnection source, NetBuffer buffer) { switch (type) { case NetMessageType.DebugMessage: Console.WriteLine(buffer.ReadString()); break; case NetMessageType.StatusChanged: NetConnectionStatus status = source.Status; if (status == NetConnectionStatus.Connected) { source.Tag = ImageClientStatus.JustConnected; s_nextPixelToSend[source] = 0; } else if (status == NetConnectionStatus.Disconnected) { if (s_nextPixelToSend.ContainsKey(source)) s_nextPixelToSend.Remove(source); } break; case NetMessageType.Receipt: source.Tag = ImageClientStatus.Running; break; default: // unhandled break; } }
public bool ReadMessage(NetBuffer intoBuffer, out NetMessageType type, out INetConnection sender) { NetConnection senderInternal; bool messageExists = _netServer.ReadMessage(intoBuffer, out type, out senderInternal); sender = new NetConnectionWrapper(senderInternal); return messageExists; }
private static void HandleMessage(NetMessageType type, NetConnection source, NetBuffer buffer) { switch (type) { case NetMessageType.DebugMessage: WriteToConsole(buffer.ReadString()); break; case NetMessageType.StatusChanged: WriteToConsole("New status: " + source.Status + " (" + buffer.ReadString() + ")"); UpdateStatisticsDisplay(source); break; case NetMessageType.Data: //System.IO.File.AppendAllText("C:\\receivedpackets.txt", s_userMessagesReceived.ToString() + ": " + msg.ReadString() + " (" + msg.m_sequenceNumber + ")" + Environment.NewLine); s_userMessagesReceived++; // simulate some processing of the message here for (int i = 0; i < buffer.LengthBytes - 2; i++) buffer.ReadByte(); // check checksum ushort checksum = NetChecksum.Adler16(buffer.Data, 0, buffer.LengthBytes - 2); ushort given = buffer.ReadUInt16(); if (checksum != given) WriteToConsole("Wrong checksum! Expected " + checksum + " found given " + given); double b = s_userMessagesReceived; for (int i = 0; i < 1000; i++) b += Math.Sqrt((double)i) / Math.Sin(s_tmp); s_tmp += b / 10000.0; break; default: break; } }
private static void HandleMessage(NetMessageType type, NetConnection source, NetBuffer buffer) { switch (type) { case NetMessageType.StatusChanged: if (source.LocalHailData == null) source.LocalHailData = Encoding.ASCII.GetBytes("Hi; I'm " + s_peer.GetHashCode()); if (source.RemoteHailData != null) WriteToConsole("New status: " + source.Status + " - remote hail is: " + Encoding.ASCII.GetString(source.RemoteHailData)); else WriteToConsole("New status: " + source.Status + " - remote hail is null"); break; case NetMessageType.DebugMessage: case NetMessageType.VerboseDebugMessage: case NetMessageType.BadMessageReceived: case NetMessageType.ConnectionRejected: WriteToConsole(buffer.ReadString()); break; case NetMessageType.Data: WriteToConsole(source.RemoteEndpoint + " writes: " + buffer.ReadString()); break; case NetMessageType.ServerDiscovered: // discovered another peer! s_peer.Connect(buffer.ReadIPEndPoint(), Encoding.ASCII.GetBytes("Hi; I'm " + s_peer.GetHashCode())); break; default: // unhandled break; } }
internal void Reset() { m_messageType = NetMessageType.LibraryError; m_bitLength = 0; m_isSent = false; m_recyclingCount = 0; m_fragmentGroup = 0; }
internal void Reset() { m_messageType = NetMessageType.LibraryError; m_bitLength = 0; m_isSent = false; NetException.Assert(m_recyclingCount == 0); m_fragmentGroup = 0; }
//private Byte[] recBuffer; public NetMessage() { type = NetMessageType.NONE; m_terminalID = ""; clientID = -1; //bytes = 0; msg = String.Empty; //recBuffer = new Byte[256]; }
internal void Reset() { m_incomingMessageType = NetIncomingMessageType.Error; m_readPosition = 0; m_receivedMessageType = NetMessageType.LibraryError; m_senderConnection = null; m_bitLength = 0; m_isFragment = false; }
public void AddMessageHandler(NetMessageType messageType , Action<NetMessageType, NetIncomingMessage> handler) { if(!messagehandler.ContainsKey(messageType)) { messagehandler[messageType] = new List<Action<NetMessageType,NetIncomingMessage>>(); messagehandler[messageType].Add(handler); } else { messagehandler[messageType].Add(handler); } }
// returns true if message should be rejected internal bool ReceivedSequencedMessage(NetMessageType mtp, ushort seqNr) { int slot = (int)mtp - (int)NetMessageType.UserSequenced; int diff = Relate(seqNr, m_lastReceivedSequenced[slot]); if (diff == 0) return true; // reject; already received if (diff > (ushort.MaxValue / 2)) return true; // reject; out of window m_lastReceivedSequenced[slot] = seqNr; return false; }
internal ushort GetSendSequenceNumber(NetMessageType mtp) { if (mtp < NetMessageType.UserSequenced) return 0; int slot = (int)mtp - (int)NetMessageType.UserSequenced; int retval; lock (m_nextSendSequenceNumber) { retval = m_nextSendSequenceNumber[slot]; if (retval == ushort.MaxValue) retval = -1; m_nextSendSequenceNumber[slot] = retval + 1; } return (ushort)retval; }
void RecieveCreateNetworkObjectOnServer(NetMessageType NetMessageType, NetIncomingMessage NetIncomingMessage) { String ident = NetIncomingMessage.ReadString(); if (NetWorkObjects.ContainsKey(ident)) { ServerIObject obj = NetWorkObjects[ident].CreateLoadObjectOrder(NetIncomingMessage); world.AddObject(obj); //skip the message type NetIncomingMessage.Position = sizeof(short) * 8; NetOutgoingMessage o = CreateMessage(NetWorking.NetMessageType.CreateNetworkObjectOnClient); o.Write(obj.GetId()); NetOutgoingMessage mes = NetWorkObjects[ident].CreateRedistributeOrder(obj, NetIncomingMessage, o); this.SendMessageToAllClients(mes,NetDeliveryMethod.ReliableOrdered); } }
public NetOutgoingMessage CreateMessage(NetMessageType messageType) { NetOutgoingMessage mes = server.CreateMessage(); mes.Write((short)messageType); return mes; }
private void ReceivedUnconnectedLibraryMessage(double now, IPEndPoint senderEndpoint, NetMessageType tp, int ptr, int payloadByteLength) { NetConnection shake; if (m_handshakes.TryGetValue(senderEndpoint, out shake)) { shake.ReceivedHandshake(now, tp, ptr, payloadByteLength); return; } // // Library message from a completely unknown sender; lets just accept Connect // switch (tp) { case NetMessageType.Discovery: if (m_configuration.IsMessageTypeEnabled(NetIncomingMessageType.DiscoveryRequest)) { NetIncomingMessage dm = CreateIncomingMessage(NetIncomingMessageType.DiscoveryRequest, payloadByteLength); if (payloadByteLength > 0) Buffer.BlockCopy(m_receiveBuffer, ptr, dm.m_data, 0, payloadByteLength); dm.m_receiveTime = now; dm.m_bitLength = payloadByteLength * 8; dm.m_senderEndpoint = senderEndpoint; ReleaseMessage(dm); } return; case NetMessageType.DiscoveryResponse: if (m_configuration.IsMessageTypeEnabled(NetIncomingMessageType.DiscoveryResponse)) { NetIncomingMessage dr = CreateIncomingMessage(NetIncomingMessageType.DiscoveryResponse, payloadByteLength); if (payloadByteLength > 0) Buffer.BlockCopy(m_receiveBuffer, ptr, dr.m_data, 0, payloadByteLength); dr.m_receiveTime = now; dr.m_bitLength = payloadByteLength * 8; dr.m_senderEndpoint = senderEndpoint; ReleaseMessage(dr); } return; case NetMessageType.NatIntroduction: HandleNatIntroduction(ptr); return; case NetMessageType.NatPunchMessage: HandleNatPunch(ptr, senderEndpoint); return; case NetMessageType.Connect: // proceed break; case NetMessageType.Disconnect: // this is probably ok LogVerbose("Received Disconnect from unconnected source: " + senderEndpoint); return; default: LogWarning("Received unhandled library message " + tp + " from " + senderEndpoint); return; } // It's someone wanting to shake hands with us! int reservedSlots = m_handshakes.Count + m_connections.Count; if (reservedSlots >= m_configuration.m_maximumConnections) { // server full NetOutgoingMessage full = CreateMessage("Server full"); full.m_messageType = NetMessageType.Disconnect; SendLibrary(full, senderEndpoint); return; } // Ok, start handshake! NetConnection conn = new NetConnection(this, senderEndpoint); m_handshakes.Add(senderEndpoint, conn); conn.ReceivedHandshake(now, tp, ptr, payloadByteLength); return; }
private void ReceivedUnconnectedLibraryMessage(double now, IPEndPoint senderEndpoint, NetMessageType tp, int ptr, int payloadByteLength) { NetConnection shake; if (m_handshakes.TryGetValue(senderEndpoint, out shake)) { shake.ReceivedHandshake(now, tp, ptr, payloadByteLength); return; } // // Library message from a completely unknown sender; lets just accept Connect // switch (tp) { case NetMessageType.Discovery: HandleIncomingDiscoveryRequest(now, senderEndpoint, ptr, payloadByteLength); return; case NetMessageType.DiscoveryResponse: HandleIncomingDiscoveryResponse(now, senderEndpoint, ptr, payloadByteLength); return; case NetMessageType.NatIntroduction: HandleNatIntroduction(ptr); return; case NetMessageType.NatPunchMessage: HandleNatPunch(ptr, senderEndpoint); return; case NetMessageType.ConnectResponse: lock (m_handshakes) { foreach (var hs in m_handshakes) { if (hs.Key.Address.Equals(senderEndpoint.Address)) { if (hs.Value.m_connectionInitiator) { // // We are currently trying to connection to XX.XX.XX.XX:Y // ... but we just received a ConnectResponse from XX.XX.XX.XX:Z // Lets just assume the router decided to use this port instead // var hsconn = hs.Value; m_connectionLookup.Remove(hs.Key); m_handshakes.Remove(hs.Key); LogDebug("Detected host port change; rerouting connection to " + senderEndpoint); hsconn.MutateEndpoint(senderEndpoint); m_connectionLookup.Add(senderEndpoint, hsconn); m_handshakes.Add(senderEndpoint, hsconn); hsconn.ReceivedHandshake(now, tp, ptr, payloadByteLength); return; } } } } LogWarning("Received unhandled library message " + tp + " from " + senderEndpoint); return; case NetMessageType.Connect: // proceed break; case NetMessageType.Disconnect: // this is probably ok LogVerbose("Received Disconnect from unconnected source: " + senderEndpoint); return; default: LogWarning("Received unhandled library message " + tp + " from " + senderEndpoint); return; } // It's someone wanting to shake hands with us! int reservedSlots = m_handshakes.Count + m_connections.Count; if (reservedSlots >= m_configuration.m_maximumConnections) { // server full NetOutgoingMessage full = CreateMessage("Server full"); full.m_messageType = NetMessageType.Disconnect; SendLibrary(full, senderEndpoint); return; } // Ok, start handshake! NetConnection conn = new NetConnection(this, senderEndpoint); m_handshakes.Add(senderEndpoint, conn); conn.ReceivedHandshake(now, tp, ptr, payloadByteLength); return; }
private void HandleConnectResponse(double now, NetMessageType tp, int ptr, int payloadLength) { byte[] hail; switch (m_status) { case NetConnectionStatus.InitiatedConnect: // awesome bool ok = ValidateHandshakeData(ptr, payloadLength, out hail); if (ok) { if (hail != null) { m_remoteHailMessage = m_peer.CreateIncomingMessage(NetIncomingMessageType.Data, hail); m_remoteHailMessage.LengthBits = (hail.Length * 8); } else { m_remoteHailMessage = null; } m_peer.AcceptConnection(this); SendConnectionEstablished(); return; } break; case NetConnectionStatus.RespondedConnect: // hello, wtf? break; case NetConnectionStatus.Disconnecting: case NetConnectionStatus.Disconnected: case NetConnectionStatus.ReceivedInitiation: case NetConnectionStatus.None: // wtf? anyway, bye! break; case NetConnectionStatus.Connected: // my ConnectionEstablished must have been lost, send another one SendConnectionEstablished(); return; } }
private void ReceiveSocketData(double now) { int bytesReceived = m_socket.ReceiveFrom(m_receiveBuffer, 0, m_receiveBuffer.Length, SocketFlags.None, ref m_senderRemote); if (bytesReceived < NetConstants.HeaderByteSize) { return; } //LogVerbose("Received " + bytesReceived + " bytes"); var ipsender = (NetEndPoint)m_senderRemote; if (m_upnp != null && now < m_upnp.m_discoveryResponseDeadline && bytesReceived > 32) { // is this an UPnP response? string resp = System.Text.Encoding.UTF8.GetString(m_receiveBuffer, 0, bytesReceived); if (resp.Contains("upnp:rootdevice") || resp.Contains("UPnP/1.0")) { try { resp = resp.Substring(resp.ToLower().IndexOf("location:") + 9); resp = resp.Substring(0, resp.IndexOf("\r")).Trim(); m_upnp.ExtractServiceUrl(resp); return; } catch (Exception ex) { LogDebug("Failed to parse UPnP response: " + ex.ToString()); // don't try to parse this packet further return; } } } NetConnection sender = null; m_connectionLookup.TryGetValue(ipsender, out sender); // // parse packet into messages // int numMessages = 0; int numFragments = 0; int ptr = 0; while ((bytesReceived - ptr) >= NetConstants.HeaderByteSize) { // decode header // 8 bits - NetMessageType // 1 bit - Fragment? // 15 bits - Sequence number // 16 bits - Payload length in bits numMessages++; NetMessageType tp = (NetMessageType)m_receiveBuffer[ptr++]; byte low = m_receiveBuffer[ptr++]; byte high = m_receiveBuffer[ptr++]; bool isFragment = ((low & 1) == 1); ushort sequenceNumber = (ushort)((low >> 1) | (((int)high) << 7)); if (isFragment) { numFragments++; } ushort payloadBitLength = (ushort)(m_receiveBuffer[ptr++] | (m_receiveBuffer[ptr++] << 8)); int payloadByteLength = NetUtility.BytesToHoldBits(payloadBitLength); if (bytesReceived - ptr < payloadByteLength) { LogWarning("Malformed packet; stated payload length " + payloadByteLength + ", remaining bytes " + (bytesReceived - ptr)); return; } if (tp >= NetMessageType.Unused1 && tp <= NetMessageType.Unused29) { ThrowOrLog("Unexpected NetMessageType: " + tp); return; } try { if (tp >= NetMessageType.LibraryError) { if (sender != null) { sender.ReceivedLibraryMessage(tp, ptr, payloadByteLength); } else { ReceivedUnconnectedLibraryMessage(now, ipsender, tp, ptr, payloadByteLength); } } else { if (sender == null && !m_configuration.IsMessageTypeEnabled(NetIncomingMessageType.UnconnectedData)) { return; // dropping unconnected message since it's not enabled } NetIncomingMessage msg = CreateIncomingMessage(NetIncomingMessageType.Data, payloadByteLength); msg.m_isFragment = isFragment; msg.m_receiveTime = now; msg.m_sequenceNumber = sequenceNumber; msg.m_receivedMessageType = tp; msg.m_senderConnection = sender; msg.m_senderEndPoint = ipsender; msg.m_bitLength = payloadBitLength; Buffer.BlockCopy(m_receiveBuffer, ptr, msg.m_data, 0, payloadByteLength); if (sender != null) { if (tp == NetMessageType.Unconnected) { // We're connected; but we can still send unconnected messages to this peer msg.m_incomingMessageType = NetIncomingMessageType.UnconnectedData; ReleaseMessage(msg); } else { // connected application (non-library) message sender.ReceivedMessage(msg); } } else { // at this point we know the message type is enabled // unconnected application (non-library) message msg.m_incomingMessageType = NetIncomingMessageType.UnconnectedData; ReleaseMessage(msg); } } } catch (Exception ex) { LogError("Packet parsing error: " + ex.Message + " from " + ipsender); } ptr += payloadByteLength; } m_statistics.PacketReceived(bytesReceived, numMessages, numFragments); if (sender != null) { sender.m_statistics.PacketReceived(bytesReceived, numMessages, numFragments); } }
// received a library message while Connected internal void ReceivedLibraryMessage(NetMessageType tp, int ptr, int payloadLength) { m_peer.VerifyNetworkThread(); float now = (float)NetTime.Now; switch (tp) { case NetMessageType.Disconnect: NetIncomingMessage msg = m_peer.SetupReadHelperMessage(ptr, payloadLength); ExecuteDisconnect(msg.ReadString(), false); break; case NetMessageType.Acknowledge: for (int i = 0; i < payloadLength; i+=3) { NetMessageType acktp = (NetMessageType)m_peer.m_receiveBuffer[ptr++]; // netmessagetype int seqNr = m_peer.m_receiveBuffer[ptr++]; seqNr |= (m_peer.m_receiveBuffer[ptr++] << 8); NetSenderChannelBase chan = m_sendChannels[(int)acktp - 1]; if (chan == null) chan = CreateSenderChannel(acktp); //m_peer.LogVerbose("Received ack for " + acktp + "#" + seqNr); chan.ReceiveAcknowledge(now, seqNr); } break; case NetMessageType.Ping: int pingNr = m_peer.m_receiveBuffer[ptr++]; SendPong(pingNr); break; case NetMessageType.Pong: NetIncomingMessage pmsg = m_peer.SetupReadHelperMessage(ptr, payloadLength); int pongNr = pmsg.ReadByte(); float remoteSendTime = pmsg.ReadSingle(); ReceivedPong(now, pongNr, remoteSendTime); break; case NetMessageType.ExpandMTURequest: SendMTUSuccess(payloadLength); break; case NetMessageType.ExpandMTUSuccess: NetIncomingMessage emsg = m_peer.SetupReadHelperMessage(ptr, payloadLength); int size = emsg.ReadInt32(); HandleExpandMTUSuccess(now, size); break; default: m_peer.LogWarning("Connection received unhandled library message: " + tp); break; } }
// received a library message while Connected internal void ReceivedLibraryMessage(NetMessageType tp, int ptr, int payloadLength) { m_peer.VerifyNetworkThread(); float now = (float)NetTime.Now; switch (tp) { case NetMessageType.Connect: m_peer.LogDebug("Received handshake message (" + tp + ") despite connection being in place"); break; case NetMessageType.ConnectResponse: // handshake message must have been lost HandleConnectResponse(now, tp, ptr, payloadLength); break; case NetMessageType.ConnectionEstablished: // do nothing, all's well break; case NetMessageType.LibraryError: m_peer.ThrowOrLog("LibraryError received by ReceivedLibraryMessage; this usually indicates a malformed message"); break; case NetMessageType.Disconnect: NetIncomingMessage msg = m_peer.SetupReadHelperMessage(ptr, payloadLength); ExecuteDisconnect(msg.ReadString(), false); break; case NetMessageType.Acknowledge: for (int i = 0; i < payloadLength; i+=3) { NetMessageType acktp = (NetMessageType)m_peer.m_receiveBuffer[ptr++]; // netmessagetype int seqNr = m_peer.m_receiveBuffer[ptr++]; seqNr |= (m_peer.m_receiveBuffer[ptr++] << 8); // need to enqueue this and handle it in the netconnection heartbeat; so be able to send resends together with normal sends m_queuedIncomingAcks.Enqueue(new NetTuple<NetMessageType, int>(acktp, seqNr)); } break; case NetMessageType.Ping: int pingNr = m_peer.m_receiveBuffer[ptr++]; SendPong(pingNr); break; case NetMessageType.Pong: NetIncomingMessage pmsg = m_peer.SetupReadHelperMessage(ptr, payloadLength); int pongNr = pmsg.ReadByte(); float remoteSendTime = pmsg.ReadSingle(); ReceivedPong(now, pongNr, remoteSendTime); break; case NetMessageType.ExpandMTURequest: SendMTUSuccess(payloadLength); break; case NetMessageType.ExpandMTUSuccess: if (m_peer.Configuration.AutoExpandMTU == false) { m_peer.LogDebug("Received ExpandMTURequest altho AutoExpandMTU is turned off!"); break; } NetIncomingMessage emsg = m_peer.SetupReadHelperMessage(ptr, payloadLength); int size = emsg.ReadInt32(); HandleExpandMTUSuccess(now, size); break; case NetMessageType.NatIntroduction: // Unusual situation where server is actually already known, but got a nat introduction - oh well, lets handle it as usual m_peer.HandleNatIntroduction(ptr); break; default: m_peer.LogWarning("Connection received unhandled library message: " + tp); break; } }
/// <summary> /// Read any received message in any connection queue /// </summary> public bool ReadMessage( NetBuffer intoBuffer, out NetMessageType type, out NetConnection sender, out IPEndPoint senderEndPoint) { if (intoBuffer == null) throw new ArgumentNullException("intoBuffer"); if (m_receivedMessages.Count < 1) { sender = null; senderEndPoint = null; type = NetMessageType.None; m_dataReceivedEvent.Reset(); return false; } IncomingNetMessage msg; lock(m_receivedMessages) msg = m_receivedMessages.Dequeue(); if (msg == null) { sender = null; type = NetMessageType.None; senderEndPoint = null; return false; } #if DEBUG if (msg.m_data == null) throw new NetException("Ouch, no data!"); if (msg.m_data.Position != 0) throw new NetException("Ouch, stale data!"); #endif senderEndPoint = msg.m_senderEndPoint; sender = msg.m_sender; intoBuffer.Tag = msg.m_data.Tag; // // recycle NetMessage object and NetBuffer // NetBuffer content = msg.m_data; msg.m_data = null; type = msg.m_msgType; // swap content of buffers byte[] tmp = intoBuffer.Data; intoBuffer.Data = content.Data; if (tmp == null) tmp = new byte[8]; // application must have lost it somehow content.Data = tmp; // set correct values for returning value (ignore the other, it's being recycled anyway) intoBuffer.m_bitLength = content.m_bitLength; intoBuffer.m_readPosition = 0; // recycle message // m_messagePool.Push(msg); // recycle buffer RecycleBuffer(content); return true; }
/// <summary> /// Read any received message in any connection queue /// </summary> public bool ReadMessage(NetBuffer intoBuffer, out NetMessageType type, out NetConnection sender) { IPEndPoint senderEndPoint; return ReadMessage(intoBuffer, out type, out sender, out senderEndPoint); }
internal void QueueAck(NetMessageType tp, int sequenceNumber) { m_queuedOutgoingAcks.Enqueue(new NetTuple <NetMessageType, int>(tp, sequenceNumber)); }
private NetReceiverChannelBase CreateReceiverChannel(NetMessageType tp) { m_peer.VerifyNetworkThread(); // create receiver channel NetReceiverChannelBase chan; NetDeliveryMethod method = NetUtility.GetDeliveryMethod(tp); switch (method) { case NetDeliveryMethod.Unreliable: chan = new NetUnreliableUnorderedReceiver(this); break; case NetDeliveryMethod.ReliableOrdered: chan = new NetReliableOrderedReceiver(this, NetConstants.ReliableOrderedWindowSize); break; case NetDeliveryMethod.UnreliableSequenced: chan = new NetUnreliableSequencedReceiver(this); break; case NetDeliveryMethod.ReliableUnordered: chan = new NetReliableUnorderedReceiver(this, NetConstants.ReliableOrderedWindowSize); break; case NetDeliveryMethod.ReliableSequenced: chan = new NetReliableSequencedReceiver(this, NetConstants.ReliableSequencedWindowSize); break; default: throw new NetException("Unhandled NetDeliveryMethod!"); } int channelSlot = (int)tp - 1; NetException.Assert(m_receiveChannels[channelSlot] == null); m_receiveChannels[channelSlot] = chan; return chan; }
// may be on user thread private NetSenderChannelBase CreateSenderChannel(NetMessageType tp) { NetSenderChannelBase chan; lock (m_sendChannels) { NetDeliveryMethod method = NetUtility.GetDeliveryMethod(tp); int sequenceChannel = (int)tp - (int)method; int channelSlot = (int)method - 1 + sequenceChannel; if (m_sendChannels[channelSlot] != null) { // we were pre-empted by another call to this method chan = m_sendChannels[channelSlot]; } else { switch (method) { case NetDeliveryMethod.Unreliable: case NetDeliveryMethod.UnreliableSequenced: chan = new NetUnreliableSenderChannel(this, NetUtility.GetWindowSize(method)); break; case NetDeliveryMethod.ReliableOrdered: chan = new NetReliableSenderChannel(this, NetUtility.GetWindowSize(method)); break; case NetDeliveryMethod.ReliableSequenced: case NetDeliveryMethod.ReliableUnordered: default: chan = new NetReliableSenderChannel(this, NetUtility.GetWindowSize(method)); break; } m_sendChannels[channelSlot] = chan; } } return chan; }
public NetMessage() { m_msgType = NetMessageType.Data; }
private void Heartbeat() { VerifyNetworkThread(); double dnow = NetTime.Now; float now = (float)dnow; double delta = dnow - m_lastHeartbeat; int maxCHBpS = 1250 - m_connections.Count; if (maxCHBpS < 250) { maxCHBpS = 250; } if (delta > (1.0 / (double)maxCHBpS)) // max connection heartbeats/second max { m_frameCounter++; m_lastHeartbeat = dnow; // do handshake heartbeats if ((m_frameCounter % 3) == 0) { foreach (var kvp in m_handshakes) { NetConnection conn = kvp.Value as NetConnection; #if DEBUG // sanity check if (kvp.Key != kvp.Key) { LogWarning("Sanity fail! Connection in handshake list under wrong key!"); } #endif conn.UnconnectedHeartbeat(now); if (conn.m_status == NetConnectionStatus.Connected || conn.m_status == NetConnectionStatus.Disconnected) { #if DEBUG // sanity check if (conn.m_status == NetConnectionStatus.Disconnected && m_handshakes.ContainsKey(conn.RemoteEndpoint)) { LogWarning("Sanity fail! Handshakes list contained disconnected connection!"); m_handshakes.Remove(conn.RemoteEndpoint); } #endif break; // collection has been modified } } } #if DEBUG SendDelayedPackets(); #endif // update m_executeFlushSendQueue if (m_configuration.m_autoFlushSendQueue) { m_executeFlushSendQueue = true; } // do connection heartbeats lock (m_connections) { foreach (NetConnection conn in m_connections) { conn.Heartbeat(now, m_frameCounter); if (conn.m_status == NetConnectionStatus.Disconnected) { // // remove connection // m_connections.Remove(conn); m_connectionLookup.Remove(conn.RemoteEndpoint); break; // can't continue iteration here } } } m_executeFlushSendQueue = false; // send unsent unconnected messages NetTuple <IPEndPoint, NetOutgoingMessage> unsent; while (m_unsentUnconnectedMessages.TryDequeue(out unsent)) { NetOutgoingMessage om = unsent.Item2; bool connReset; int len = om.Encode(m_sendBuffer, 0, 0); SendPacket(len, unsent.Item1, 1, out connReset); Interlocked.Decrement(ref om.m_recyclingCount); if (om.m_recyclingCount <= 0) { Recycle(om); } } } // // read from socket // if (m_socket == null) { return; } if (!m_socket.Poll(1000, SelectMode.SelectRead)) // wait up to 1 ms for data to arrive { return; } //if (m_socket == null || m_socket.Available < 1) // return; do { int bytesReceived = 0; try { bytesReceived = m_socket.ReceiveFrom(m_receiveBuffer, 0, m_receiveBuffer.Length, SocketFlags.None, ref m_senderRemote); } catch (SocketException sx) { if (sx.SocketErrorCode == SocketError.ConnectionReset) { // connection reset by peer, aka connection forcibly closed aka "ICMP port unreachable" // we should shut down the connection; but m_senderRemote seemingly cannot be trusted, so which connection should we shut down?! // So, what to do? LogWarning("ConnectionReset"); return; } LogWarning(sx.ToString()); return; } if (bytesReceived < NetConstants.HeaderByteSize) { return; } //LogVerbose("Received " + bytesReceived + " bytes"); IPEndPoint ipsender = (IPEndPoint)m_senderRemote; if (ipsender.Port == 1900) { // UPnP response try { string resp = System.Text.Encoding.ASCII.GetString(m_receiveBuffer, 0, bytesReceived); if (resp.Contains("upnp:rootdevice")) { resp = resp.Substring(resp.ToLower().IndexOf("location:") + 9); resp = resp.Substring(0, resp.IndexOf("\r")).Trim(); m_upnp.ExtractServiceUrl(resp); return; } } catch { } } NetConnection sender = null; m_connectionLookup.TryGetValue(ipsender, out sender); double receiveTime = NetTime.Now; // // parse packet into messages // int numMessages = 0; int ptr = 0; while ((bytesReceived - ptr) >= NetConstants.HeaderByteSize) { // decode header // 8 bits - NetMessageType // 1 bit - Fragment? // 15 bits - Sequence number // 16 bits - Payload length in bits numMessages++; NetMessageType tp = (NetMessageType)m_receiveBuffer[ptr++]; byte low = m_receiveBuffer[ptr++]; byte high = m_receiveBuffer[ptr++]; bool isFragment = ((low & 1) == 1); ushort sequenceNumber = (ushort)((low >> 1) | (((int)high) << 7)); ushort payloadBitLength = (ushort)(m_receiveBuffer[ptr++] | (m_receiveBuffer[ptr++] << 8)); int payloadByteLength = NetUtility.BytesToHoldBits(payloadBitLength); if (bytesReceived - ptr < payloadByteLength) { LogWarning("Malformed packet; stated payload length " + payloadByteLength + ", remaining bytes " + (bytesReceived - ptr)); return; } try { NetException.Assert(tp <NetMessageType.Unused1 || tp> NetMessageType.Unused29); if (tp >= NetMessageType.LibraryError) { if (sender != null && tp != NetMessageType.NatIntroduction && tp != NetMessageType.NatPunchMessage) { sender.ReceivedLibraryMessage(tp, ptr, payloadByteLength); } else { ReceivedUnconnectedLibraryMessage(receiveTime, ipsender, tp, ptr, payloadByteLength); } } else { if (sender == null && !m_configuration.IsMessageTypeEnabled(NetIncomingMessageType.UnconnectedData)) { return; // dropping unconnected message since it's not enabled } NetIncomingMessage msg = CreateIncomingMessage(NetIncomingMessageType.Data, payloadByteLength); msg.m_isFragment = isFragment; msg.m_receiveTime = receiveTime; msg.m_sequenceNumber = sequenceNumber; msg.m_receivedMessageType = tp; msg.m_senderConnection = sender; msg.m_senderEndpoint = ipsender; msg.m_bitLength = payloadBitLength; Buffer.BlockCopy(m_receiveBuffer, ptr, msg.m_data, 0, payloadByteLength); if (sender != null) { if (tp == NetMessageType.Unconnected) { // We're connected; but we can still send unconnected messages to this peer msg.m_incomingMessageType = NetIncomingMessageType.UnconnectedData; ReleaseMessage(msg); } else { // connected application (non-library) message sender.ReceivedMessage(msg); } } else { // at this point we know the message type is enabled // unconnected application (non-library) message msg.m_incomingMessageType = NetIncomingMessageType.UnconnectedData; ReleaseMessage(msg); } } } catch (Exception ex) { LogError("Packet parsing error: " + ex.Message + " from " + ipsender); } ptr += payloadByteLength; } m_statistics.PacketReceived(bytesReceived, numMessages); if (sender != null) { sender.m_statistics.PacketReceived(bytesReceived, numMessages); } } while (m_socket.Available > 0); }
private void ReceivedUnconnectedLibraryMessage(double now, NetEndPoint senderEndPoint, NetMessageType tp, int ptr, int payloadByteLength) { NetConnection shake; if (m_handshakes.TryGetValue(senderEndPoint, out shake)) { shake.ReceivedHandshake(now, tp, ptr, payloadByteLength); return; } // // Library message from a completely unknown sender; lets just accept Connect // switch (tp) { case NetMessageType.Discovery: HandleIncomingDiscoveryRequest(now, senderEndPoint, ptr, payloadByteLength); return; case NetMessageType.DiscoveryResponse: HandleIncomingDiscoveryResponse(now, senderEndPoint, ptr, payloadByteLength); return; case NetMessageType.NatIntroduction: if (m_configuration.IsMessageTypeEnabled(NetIncomingMessageType.NatIntroductionSuccess)) { HandleNatIntroduction(ptr); } return; case NetMessageType.NatPunchMessage: if (m_configuration.IsMessageTypeEnabled(NetIncomingMessageType.NatIntroductionSuccess)) { HandleNatPunch(ptr, senderEndPoint); } return; case NetMessageType.NatIntroductionConfirmRequest: if (m_configuration.IsMessageTypeEnabled(NetIncomingMessageType.NatIntroductionSuccess)) { HandleNatPunchConfirmRequest(ptr, senderEndPoint); } return; case NetMessageType.NatIntroductionConfirmed: if (m_configuration.IsMessageTypeEnabled(NetIncomingMessageType.NatIntroductionSuccess)) { HandleNatPunchConfirmed(ptr, senderEndPoint); } return; case NetMessageType.ConnectResponse: lock (m_handshakes) { foreach (var hs in m_handshakes) { if (hs.Key.Address.Equals(senderEndPoint.Address)) { if (hs.Value.m_connectionInitiator) { // // We are currently trying to connection to XX.XX.XX.XX:Y // ... but we just received a ConnectResponse from XX.XX.XX.XX:Z // Lets just assume the router decided to use this port instead // var hsconn = hs.Value; m_connectionLookup.Remove(hs.Key); m_handshakes.Remove(hs.Key); LogDebug("Detected host port change; rerouting connection to " + senderEndPoint); hsconn.MutateEndPoint(senderEndPoint); m_connectionLookup.Add(senderEndPoint, hsconn); m_handshakes.Add(senderEndPoint, hsconn); hsconn.ReceivedHandshake(now, tp, ptr, payloadByteLength); return; } } } } LogWarning("Received unhandled library message " + tp + " from " + senderEndPoint); return; case NetMessageType.Connect: if (m_configuration.AcceptIncomingConnections == false) { LogWarning("Received Connect, but we're not accepting incoming connections!"); return; } // handle connect // It's someone wanting to shake hands with us! int reservedSlots = m_handshakes.Count + m_connections.Count; if (reservedSlots >= m_configuration.m_maximumConnections) { // server full NetOutgoingMessage full = CreateMessage("Server full"); full.m_messageType = NetMessageType.Disconnect; SendLibrary(full, senderEndPoint); return; } // Ok, start handshake! NetConnection conn = new NetConnection(this, senderEndPoint); conn.m_status = NetConnectionStatus.ReceivedInitiation; m_handshakes.Add(senderEndPoint, conn); conn.ReceivedHandshake(now, tp, ptr, payloadByteLength); return; case NetMessageType.Disconnect: // this is probably ok LogVerbose("Received Disconnect from unconnected source: " + senderEndPoint); return; default: LogWarning("Received unhandled library message " + tp + " from " + senderEndPoint); return; } }
void HandleEchoMessage(NetMessageType NetMessageType, NetIncomingMessage NetIncomingMessage) { String ident = NetIncomingMessage.ReadString(); long unique = NetIncomingMessage.ReadInt64(); if(NetWorkEcho.ContainsKey(ident)) { NetOutgoingMessage o = CreateMessage(NetWorking.NetMessageType.Echo); o.Write(ident); o.Write(unique); SendMessageToAllClients(NetWorkEcho[ident].AnswerMessage(NetIncomingMessage,o),NetDeliveryMethod.ReliableOrdered); } }
internal static NetDeliveryMethod GetDeliveryMethod(NetMessageType mtp) { if (mtp >= NetMessageType.UserReliableOrdered1) return NetDeliveryMethod.ReliableOrdered; else if (mtp >= NetMessageType.UserReliableSequenced1) return NetDeliveryMethod.ReliableSequenced; else if (mtp >= NetMessageType.UserReliableUnordered) return NetDeliveryMethod.ReliableUnordered; else if (mtp >= NetMessageType.UserSequenced1) return NetDeliveryMethod.UnreliableSequenced; return NetDeliveryMethod.Unreliable; }
internal void ReceivedHandshake(double now, NetMessageType tp, int ptr, int payloadLength) { m_peer.VerifyNetworkThread(); byte[] hail; switch (tp) { case NetMessageType.Connect: if (m_status == NetConnectionStatus.None) { // Whee! Server full has already been checked bool ok = ValidateHandshakeData(ptr, payloadLength, out hail); if (ok) { if (hail != null) { m_remoteHailMessage = m_peer.CreateIncomingMessage(NetIncomingMessageType.Data, hail); m_remoteHailMessage.LengthBits = (hail.Length * 8); } else { m_remoteHailMessage = null; } if (m_peerConfiguration.IsMessageTypeEnabled(NetIncomingMessageType.ConnectionApproval)) { // ok, let's not add connection just yet NetIncomingMessage appMsg = m_peer.CreateIncomingMessage(NetIncomingMessageType.ConnectionApproval, (m_remoteHailMessage == null ? 0 : m_remoteHailMessage.LengthBytes)); appMsg.m_receiveTime = now; appMsg.m_senderConnection = this; appMsg.m_senderEndpoint = this.m_remoteEndpoint; if (m_remoteHailMessage != null) appMsg.Write(m_remoteHailMessage.m_data, 0, m_remoteHailMessage.LengthBytes); m_peer.ReleaseMessage(appMsg); return; } SendConnectResponse((float)now, true); } return; } if (m_status == NetConnectionStatus.RespondedConnect) { // our ConnectResponse must have been lost SendConnectResponse((float)now, true); return; } m_peer.LogDebug("Unhandled Connect: " + tp + ", status is " + m_status + " length: " + payloadLength); break; case NetMessageType.ConnectResponse: switch (m_status) { case NetConnectionStatus.InitiatedConnect: // awesome bool ok = ValidateHandshakeData(ptr, payloadLength, out hail); if (ok) { if (hail != null) { m_remoteHailMessage = m_peer.CreateIncomingMessage(NetIncomingMessageType.Data, hail); m_remoteHailMessage.LengthBits = (hail.Length * 8); } else { m_remoteHailMessage = null; } m_peer.AcceptConnection(this); SendConnectionEstablished(); return; } break; case NetConnectionStatus.RespondedConnect: // hello, wtf? break; case NetConnectionStatus.Disconnecting: case NetConnectionStatus.Disconnected: case NetConnectionStatus.None: // wtf? anyway, bye! break; case NetConnectionStatus.Connected: // my ConnectionEstablished must have been lost, send another one SendConnectionEstablished(); return; } break; case NetMessageType.ConnectionEstablished: switch (m_status) { case NetConnectionStatus.Connected: // ok... break; case NetConnectionStatus.Disconnected: case NetConnectionStatus.Disconnecting: case NetConnectionStatus.None: // too bad, almost made it break; case NetConnectionStatus.InitiatedConnect: // weird, should have been ConnectResponse... break; case NetConnectionStatus.RespondedConnect: // awesome NetIncomingMessage msg = m_peer.SetupReadHelperMessage(ptr, payloadLength); InitializeRemoteTimeOffset(msg.ReadSingle()); m_peer.AcceptConnection(this); InitializePing(); SetStatus(NetConnectionStatus.Connected, "Connected to " + NetUtility.ToHexString(m_remoteUniqueIdentifier)); return; } break; case NetMessageType.Disconnect: // ouch string reason = "Ouch"; try { NetIncomingMessage inc = m_peer.SetupReadHelperMessage(ptr, payloadLength); reason = inc.ReadString(); } catch { } ExecuteDisconnect(reason, false); break; case NetMessageType.Discovery: m_peer.HandleIncomingDiscoveryRequest(now, m_remoteEndpoint, ptr, payloadLength); return; case NetMessageType.DiscoveryResponse: m_peer.HandleIncomingDiscoveryResponse(now, m_remoteEndpoint, ptr, payloadLength); return; case NetMessageType.Ping: // silently ignore return; default: m_peer.LogDebug("Unhandled type during handshake: " + tp + " length: " + payloadLength); break; } }
/// <summary> /// Handle incoming message /// </summary> private void HandleMessage(NetMessageType type, NetBuffer buffer) { switch (type) { case NetMessageType.DebugMessage: // // it's a library debug message; just display it in the console if debugger is attached // Console.WriteLine(buffer.ReadString()); break; case NetMessageType.StatusChanged: // // it's a status change message; set the reason as window title and refresh picture // this.Text = buffer.ReadString(); pictureBox1.Refresh(); break; case NetMessageType.ServerDiscovered: // // it's a server discovered message; connect to the discovered server // m_imageWidth = 0; m_imageHeight = 0; m_lineDisplayed = 0; m_client.Connect(buffer.ReadIPEndPoint()); break; case NetMessageType.Data: // // it's a data message (data sent from the server) // if (m_imageWidth == 0) { // first message is size m_imageWidth = (int)buffer.ReadVariableUInt32(); m_imageHeight = (int)buffer.ReadVariableUInt32(); this.Size = new System.Drawing.Size(m_imageWidth + 40, m_imageHeight + 60); pictureBox1.Image = new Bitmap(m_imageWidth, m_imageHeight); pictureBox1.SetBounds(12, 12, m_imageWidth, m_imageHeight); return; } uint pixelPos = buffer.ReadUInt32(); // it's color data int y = (int)(pixelPos / m_imageWidth); int x = (int)(pixelPos - (y * m_imageWidth)); Bitmap bm = pictureBox1.Image as Bitmap; pictureBox1.SuspendLayout(); int pixels = (buffer.LengthBytes - 4) / 3; for (int i = 0; i < pixels; i++) { // set pixel byte r = buffer.ReadByte(); byte g = buffer.ReadByte(); byte b = buffer.ReadByte(); Color col = Color.FromArgb(r, g, b); if (y > m_imageHeight) continue; bm.SetPixel(x, y, col); x++; if (x >= m_imageWidth) { x = 0; y++; } } pictureBox1.ResumeLayout(); // refresh image every horizontal line if (pixelPos / m_imageWidth > m_lineDisplayed) { m_lineDisplayed = (int)(pixelPos / m_imageWidth); pictureBox1.Refresh(); } break; default: // unhandled break; } }
// received a library message while Connected internal void ReceivedLibraryMessage(NetMessageType tp, int ptr, int payloadLength) { m_peer.VerifyNetworkThread(); float now = (float)NetTime.Now; switch (tp) { case NetMessageType.Disconnect: NetIncomingMessage msg = m_peer.SetupReadHelperMessage(ptr, payloadLength); ExecuteDisconnect(msg.ReadString(), false); break; case NetMessageType.Acknowledge: for (int i = 0; i < payloadLength; i+=3) { NetMessageType acktp = (NetMessageType)m_peer.m_receiveBuffer[ptr++]; // netmessagetype int seqNr = m_peer.m_receiveBuffer[ptr++]; seqNr |= (m_peer.m_receiveBuffer[ptr++] << 8); // need to enqueue this and handle it in the netconnection heartbeat; so be able to send resends together with normal sends m_queuedIncomingAcks.Enqueue(new NetTuple<NetMessageType, int>(acktp, seqNr)); } break; case NetMessageType.Ping: int pingNr = m_peer.m_receiveBuffer[ptr++]; SendPong(pingNr); break; case NetMessageType.Pong: NetIncomingMessage pmsg = m_peer.SetupReadHelperMessage(ptr, payloadLength); int pongNr = pmsg.ReadByte(); float remoteSendTime = pmsg.ReadSingle(); ReceivedPong(now, pongNr, remoteSendTime); break; case NetMessageType.ExpandMTURequest: SendMTUSuccess(payloadLength); break; case NetMessageType.ExpandMTUSuccess: NetIncomingMessage emsg = m_peer.SetupReadHelperMessage(ptr, payloadLength); int size = emsg.ReadInt32(); HandleExpandMTUSuccess(now, size); break; case NetMessageType.NatIntroduction: // Unusual situation where server is actually already known, but got a nat introduction - oh well, lets handle it as usual m_peer.HandleNatIntroduction(ptr); break; default: m_peer.LogWarning("Connection received unhandled library message: " + tp); break; } }
/* /// <summary> /// Read any received message in any connection queue /// </summary> public NetBuffer ReadMessage(out NetConnection sender) { if (m_receivedMessages.Count < 1) { sender = null; return null; } NetMessage msg = m_receivedMessages.Dequeue(); sender = msg.m_sender; NetBuffer retval = msg.m_data; msg.m_data = null; m_messagePool.Push(msg); Debug.Assert(retval.Position == 0); return retval; } */ /// <summary> /// Read any received message in any connection queue /// </summary> public bool ReadMessage( NetBuffer intoBuffer, IList<NetConnection> onlyFor, bool includeNullConnectionMessages, out NetMessageType type, out NetConnection sender) { if (m_receivedMessages.Count < 1) { sender = null; type = NetMessageType.None; m_dataReceivedEvent.Reset(); return false; } IncomingNetMessage msg = null; lock (m_receivedMessages) { int sz = m_receivedMessages.Count; for (int i = 0; i < sz; i++) { msg = m_receivedMessages.Peek(i); if (msg != null) { if ((msg.m_sender == null && includeNullConnectionMessages) || onlyFor.Contains(msg.m_sender)) { m_receivedMessages.Dequeue(i); break; } msg = null; } } } if (msg == null) { sender = null; type = NetMessageType.None; return false; } sender = msg.m_sender; // recycle NetMessage object NetBuffer content = msg.m_data; msg.m_data = null; type = msg.m_msgType; // m_messagePool.Push(msg); Debug.Assert(content.Position == 0); // swap content of buffers byte[] tmp = intoBuffer.Data; intoBuffer.Data = content.Data; content.Data = tmp; // set correct values for returning value (ignore the other, it's being recycled anyway) intoBuffer.m_bitLength = content.m_bitLength; intoBuffer.m_readPosition = 0; // recycle NetBuffer object (incl. old intoBuffer byte array) RecycleBuffer(content); return true; }
internal void QueueAck(NetMessageType tp, int sequenceNumber) { m_queuedOutgoingAcks.Enqueue(new NetTuple<NetMessageType, int>(tp, sequenceNumber)); }
// received a library message while Connected internal void ReceivedLibraryMessage(NetMessageType tp, int ptr, int payloadLength) { m_peer.VerifyNetworkThread(); double now = NetTime.Now; switch (tp) { case NetMessageType.Connect: m_peer.LogDebug("Received handshake message (" + tp + ") despite connection being in place"); break; case NetMessageType.ConnectResponse: // handshake message must have been lost HandleConnectResponse(now, tp, ptr, payloadLength); break; case NetMessageType.ConnectionEstablished: // do nothing, all's well break; case NetMessageType.LibraryError: m_peer.ThrowOrLog("LibraryError received by ReceivedLibraryMessage; this usually indicates a malformed message"); break; case NetMessageType.Disconnect: NetIncomingMessage msg = m_peer.SetupReadHelperMessage(ptr, payloadLength); m_disconnectRequested = true; m_disconnectMessage = msg.ReadString(); m_disconnectReqSendBye = false; //ExecuteDisconnect(msg.ReadString(), false); break; case NetMessageType.Acknowledge: for (int i = 0; i < payloadLength; i += 3) { NetMessageType acktp = (NetMessageType)m_peer.m_receiveBuffer[ptr++]; // netmessagetype int seqNr = m_peer.m_receiveBuffer[ptr++]; seqNr |= (m_peer.m_receiveBuffer[ptr++] << 8); // need to enqueue this and handle it in the netconnection heartbeat; so be able to send resends together with normal sends m_queuedIncomingAcks.Enqueue(new NetTuple <NetMessageType, int>(acktp, seqNr)); } break; case NetMessageType.Ping: int pingNr = m_peer.m_receiveBuffer[ptr++]; SendPong(pingNr); break; case NetMessageType.Pong: NetIncomingMessage pmsg = m_peer.SetupReadHelperMessage(ptr, payloadLength); int pongNr = pmsg.ReadByte(); float remoteSendTime = pmsg.ReadSingle(); ReceivedPong(now, pongNr, remoteSendTime); break; case NetMessageType.ExpandMTURequest: SendMTUSuccess(payloadLength); break; case NetMessageType.ExpandMTUSuccess: if (m_peer.Configuration.AutoExpandMTU == false) { m_peer.LogDebug("Received ExpandMTURequest altho AutoExpandMTU is turned off!"); break; } NetIncomingMessage emsg = m_peer.SetupReadHelperMessage(ptr, payloadLength); int size = emsg.ReadInt32(); HandleExpandMTUSuccess(now, size); break; case NetMessageType.NatIntroduction: // Unusual situation where server is actually already known, but got a nat introduction - oh well, lets handle it as usual m_peer.HandleNatIntroduction(ptr); break; default: m_peer.LogWarning("Connection received unhandled library message: " + tp); break; } }