public void SendMessageToClient(Guid clientGuid, int type, byte[] data) { if (type < 0) { throw new IndexOutOfRangeException("Implementers must use positive ID's"); } UdpPeer peer = GetPeer(clientGuid); if (peer == null) { return; } byte[] sendBytes = UdpMeshCommon.GetPayload(type, data); if (peer.usev4 && peer.usev6 && clientSocketv4 != null && clientSocketv6 != null) { if (peer.latency4 < peer.latency6) { UdpMeshCommon.Send(clientSocketv4, sendBytes, peer.contactV4); } else { UdpMeshCommon.Send(clientSocketv6, sendBytes, peer.contactV6); } return; } if (peer.usev6 && clientSocketv6 != null) { UdpMeshCommon.Send(clientSocketv6, sendBytes, peer.contactV6); return; } if (peer.usev4 && clientSocketv4 != null) { UdpMeshCommon.Send(clientSocketv4, sendBytes, peer.contactV4); return; } byte[] relayBytes = new byte[40 + sendBytes.Length]; Array.Copy(relayHeader, 0, relayBytes, 0, relayHeader.Length); byte[] destination = clientGuid.ToByteArray(); Array.Copy(destination, 0, relayBytes, 24, 16); Array.Copy(sendBytes, 0, relayBytes, 40, sendBytes.Length); if (connectedv6 && clientSocketv6 != null) { UdpMeshCommon.Send(clientSocketv6, relayBytes, serverEndpointv6); return; } if (connectedv4 && clientSocketv4 != null) { UdpMeshCommon.Send(clientSocketv4, relayBytes, serverEndpointv4); return; } }
/// <summary> /// Initializes a new instance of the <see cref="T:UDPMeshLib.UdpMeshClient"/> class. /// </summary> /// <param name="serverEndpointv4">Mesh servers IPv4 address to connect to.</param> /// <param name="serverEndpointv6">Mesh servers IPv6 address to connect to.</param> /// <param name="myAddresses">List of local addresses to inform the server about for in-network meshing</param> /// <param name="debugLog">Debug logging callback, leave <see langword="null"/> to disable</param> public UdpMeshClient(IPEndPoint serverEndpointv4, IPEndPoint serverEndpointv6, IPAddress[] myAddresses, Action <string> debugLog) { this.me = new UdpPeer(UdpMeshCommon.GetMeshAddress()); this.myAddresses = myAddresses; this.serverEndpointv4 = serverEndpointv4; this.serverEndpointv6 = serverEndpointv6; this.debugLog = debugLog; callbacks[-1] = HandleServerReport; callbacks[-2] = HandleClientInfo; callbacks[-3] = HandleRelayMessage; callbacks[-201] = HandleHeartBeat; callbacks[-202] = HandleHeartBeatReply; UdpStun.callback = HandleStun; }
private void HandleHeartBeatReply(byte[] inputData, int inputDataLength, Guid clientGuid, IPEndPoint iPEndPoint) { lock (tempTime) { if (inputDataLength != 40) { return; } UdpPeer peer = GetPeer(clientGuid); if (peer == null) { return; } lock (tempTime) { Array.Copy(inputData, 24, tempTime, 0, 8); UdpMeshCommon.FlipEndian(ref tempTime); long sendTime = BitConverter.ToInt64(tempTime, 0); Array.Copy(inputData, 32, tempTime, 0, 8); UdpMeshCommon.FlipEndian(ref tempTime); long remoteTime = BitConverter.ToInt64(tempTime, 0); long receiveTime = DateTime.UtcNow.Ticks; peer.lastReceiveTime = receiveTime; if (UdpMeshCommon.IsIPv4(iPEndPoint.Address)) { peer.latency4 = receiveTime - sendTime; long expectedReceive = (peer.latency4 / 2) + sendTime; peer.offset = expectedReceive - remoteTime; } if (UdpMeshCommon.IsIPv6(iPEndPoint.Address)) { peer.latency6 = receiveTime - sendTime; long expectedReceive = (peer.latency6 / 2) + sendTime; peer.offset = expectedReceive - remoteTime; } } peer.AddRemoteEndpoint(iPEndPoint); if (UdpMeshCommon.IsIPv4(iPEndPoint.Address) && !peer.usev4) { peer.contactV4 = iPEndPoint; peer.usev4 = true; } if (UdpMeshCommon.IsIPv6(iPEndPoint.Address) && !peer.usev6) { peer.contactV6 = iPEndPoint; peer.usev6 = true; } } }
private void HandleClientInfo(byte[] inputData, int inputDataLength, Guid serverGuid, IPEndPoint serverEndpoint) { lock (guidData) { int readPos = 24; if (inputDataLength - readPos < 17) { return; } Array.Copy(inputData, readPos, guidData, 0, 16); Guid receiveID = new Guid(guidData); if (!clients.ContainsKey(receiveID)) { clients.Add(receiveID, new UdpPeer(receiveID)); } UdpPeer client = clients[receiveID]; readPos += 16; int v4Num = inputData[readPos]; readPos++; for (int i = 0; i < v4Num; i++) { Array.Copy(inputData, readPos, tempClientAddress4, 0, 4); IPAddress ip = new IPAddress(tempClientAddress4); readPos += 4; Array.Copy(inputData, readPos, tempClientPort, 0, 2); UdpMeshCommon.FlipEndian(ref tempClientPort); int port = BitConverter.ToUInt16(tempClientPort, 0); client.AddRemoteEndpoint(new IPEndPoint(ip, port)); readPos += 2; } if (inputDataLength - readPos < 1) { return; } int v6Num = inputData[readPos]; readPos++; for (int i = 0; i < v6Num; i++) { Array.Copy(inputData, readPos, tempClientAddress6, 0, 16); IPAddress ip = new IPAddress(tempClientAddress6); readPos += 16; Array.Copy(inputData, readPos, tempClientPort, 0, 2); UdpMeshCommon.FlipEndian(ref tempClientPort); int port = BitConverter.ToUInt16(tempClientPort, 0); client.AddRemoteEndpoint(new IPEndPoint(ip, port)); readPos += 2; } } }
private void HandleClientInfo(byte[] inputData, Guid serverGuid, IPEndPoint serverEndpoint) { int readPos = 24; if (inputData.Length - readPos < 17) { return; } byte[] guidData = new byte[16]; Array.Copy(inputData, readPos, guidData, 0, 16); Guid receiveID = new Guid(guidData); if (!clients.ContainsKey(receiveID)) { clients.Add(receiveID, new UdpPeer(receiveID)); } UdpPeer client = clients[receiveID]; readPos += 16; int v4Num = inputData[readPos]; readPos++; for (int i = 0; i < v4Num; i++) { if (inputData.Length - readPos < 6) { return; } Array.Copy(inputData, readPos, tempClientAddress4, 0, 4); IPAddress ip = new IPAddress(tempClientAddress4); readPos += 4; Array.Copy(inputData, readPos, tempClientPort, 0, 2); UdpMeshCommon.FlipEndian(ref tempClientPort); int port = BitConverter.ToUInt16(tempClientPort, 0); client.AddRemoteEndpoint(new IPEndPoint(ip, port)); readPos += 2; } if (inputData.Length - readPos < 1) { return; } int v6Num = inputData[readPos]; readPos++; for (int i = 0; i < v6Num; i++) { if (inputData.Length - readPos < 18) { return; } Array.Copy(inputData, readPos, tempClientAddress6, 0, 16); IPAddress ip = new IPAddress(tempClientAddress6); readPos += 16; Array.Copy(inputData, readPos, tempClientPort, 0, 2); UdpMeshCommon.FlipEndian(ref tempClientPort); int port = BitConverter.ToUInt16(tempClientPort, 0); client.AddRemoteEndpoint(new IPEndPoint(ip, port)); readPos += 2; } /* * DebugLog("Updated endpoints for " + receiveID); * foreach (IPEndPoint endPoint in client.remoteEndpoints) * { * DebugLog(endPoint); * }1 * DebugLog("==="); */ }
private void HandleHeartBeat(byte[] inputData, Guid clientGuid, IPEndPoint iPEndPoint) { if (inputData.Length != 32) { return; } UdpPeer peer = GetPeer(clientGuid); if (peer == null) { return; } peer.lastReceiveTime = DateTime.UtcNow.Ticks; byte[] replyBytes = new byte[16]; byte[] currentTime = BitConverter.GetBytes(DateTime.UtcNow.Ticks); UdpMeshCommon.FlipEndian(ref currentTime); Array.Copy(inputData, 24, replyBytes, 0, 8); Array.Copy(currentTime, 0, replyBytes, 8, 8); byte[] replyMessage = UdpMeshCommon.GetPayload(-202, replyBytes); if (UdpMeshCommon.IsIPv4(iPEndPoint.Address)) { UdpMeshCommon.Send(clientSocketv4, replyMessage, iPEndPoint); if (!peer.usev4) { byte[] notifyServerOfEndpoint = new byte[23]; Array.Copy(clientGuid.ToByteArray(), 0, notifyServerOfEndpoint, 0, 16); notifyServerOfEndpoint[16] = 4; byte[] endpointBytes = iPEndPoint.Address.GetAddressBytes(); if (endpointBytes.Length == 4) { Array.Copy(endpointBytes, 0, notifyServerOfEndpoint, 17, 4); } if (endpointBytes.Length == 16) { Array.Copy(endpointBytes, 12, notifyServerOfEndpoint, 17, 4); } byte[] portBytes = BitConverter.GetBytes((UInt16)iPEndPoint.Port); UdpMeshCommon.FlipEndian(ref portBytes); Array.Copy(portBytes, 0, notifyServerOfEndpoint, 21, 2); byte[] notifyServerOfEndpointPayload = UdpMeshCommon.GetPayload(-103, notifyServerOfEndpoint); UdpMeshCommon.Send(clientSocketv4, notifyServerOfEndpointPayload, serverEndpointv4); } } if (UdpMeshCommon.IsIPv6(iPEndPoint.Address)) { UdpMeshCommon.Send(clientSocketv6, replyMessage, iPEndPoint); if (!peer.usev6) { byte[] notifyServerOfEndpoint = new byte[35]; Array.Copy(clientGuid.ToByteArray(), 0, notifyServerOfEndpoint, 0, 16); notifyServerOfEndpoint[16] = 6; byte[] endpointBytes = iPEndPoint.Address.GetAddressBytes(); Array.Copy(endpointBytes, 0, notifyServerOfEndpoint, 17, 16); byte[] portBytes = BitConverter.GetBytes((UInt16)iPEndPoint.Port); UdpMeshCommon.FlipEndian(ref portBytes); Array.Copy(portBytes, 0, notifyServerOfEndpoint, 33, 2); byte[] notifyServerOfEndpointPayload = UdpMeshCommon.GetPayload(-103, notifyServerOfEndpoint); UdpMeshCommon.Send(clientSocketv6, notifyServerOfEndpointPayload, serverEndpointv6); } } }
private void ClientReport(byte[] inputData, Guid guid, IPEndPoint endpoint) { List <IPEndPoint> newEndpoints = new List <IPEndPoint>(); lock (tempClientPort) { int readPos = 24; if (inputData.Length - readPos < 1) { return; } int v4Num = inputData[readPos]; readPos++; for (int i = 0; i < v4Num; i++) { if (inputData.Length - readPos < 6) { return; } Array.Copy(inputData, readPos, tempClientAddress4, 0, 4); IPAddress ip = new IPAddress(tempClientAddress4); readPos += 4; Array.Copy(inputData, readPos, tempClientPort, 0, 2); UdpMeshCommon.FlipEndian(ref tempClientPort); int port = BitConverter.ToUInt16(tempClientPort, 0); newEndpoints.Add(new IPEndPoint(ip, port)); readPos += 2; } if (inputData.Length - readPos < 1) { return; } int v6Num = inputData[readPos]; readPos++; for (int i = 0; i < v6Num; i++) { if (inputData.Length - readPos < 18) { return; } Array.Copy(inputData, readPos, tempClientAddress6, 0, 16); IPAddress ip = new IPAddress(tempClientAddress6); readPos += 16; Array.Copy(inputData, readPos, tempClientPort, 0, 2); UdpMeshCommon.FlipEndian(ref tempClientPort); int port = BitConverter.ToUInt16(tempClientPort, 0); newEndpoints.Add(new IPEndPoint(ip, port)); readPos += 2; } lock (clients) { if (!clients.ContainsKey(guid)) { clients.Add(guid, new UdpPeer(guid)); connectedGuidBytes = null; } UdpPeer client = clients[guid]; if (UdpMeshCommon.IsIPv4(endpoint.Address)) { client.usev4 = true; client.contactV4 = endpoint; } if (UdpMeshCommon.IsIPv6(endpoint.Address)) { client.usev6 = true; client.contactV6 = endpoint; } client.AddRemoteEndpoint(endpoint); foreach (IPEndPoint tempEndPoint in newEndpoints) { client.AddRemoteEndpoint(tempEndPoint); } client.lastReceiveTime = DateTime.UtcNow.Ticks; } } }
public void SendMessageToClient(Guid clientGuid, int type, byte[] data, int length) { lock (sendBuffer) { if (type < 0) { throw new IndexOutOfRangeException("Implementers must use positive ID's"); } UdpPeer peer = GetPeer(clientGuid); if (peer == null) { return; } int sendBufferLength = UdpMeshCommon.GetPayload(type, data, length, sendBuffer); //We can use v4 or v6, let's select the lowest latency if (peer.usev4 && peer.usev6 && clientSocketv4 != null && clientSocketv6 != null) { if (peer.latency4 < peer.latency6) { UdpMeshCommon.Send(clientSocketv4, sendBuffer, sendBufferLength, peer.contactV4); } else { UdpMeshCommon.Send(clientSocketv6, sendBuffer, sendBufferLength, peer.contactV6); } return; } //Have to use V6, only v6 contact if (peer.usev6 && !peer.usev4 && clientSocketv6 != null) { UdpMeshCommon.Send(clientSocketv6, sendBuffer, sendBufferLength, peer.contactV6); return; } //Have to use V6, only v4 contact if (peer.usev4 && !peer.usev6 && clientSocketv4 != null) { UdpMeshCommon.Send(clientSocketv4, sendBuffer, sendBufferLength, peer.contactV4); return; } //We currently have no contact and must send through the server to establish contact. int relayBufferLength = 40 + sendBufferLength; //Initialise header if this is the first run, we can use the relayBuffer as it is still free. if (relayHeader == null) { int relayHeaderLength = UdpMeshCommon.GetPayload(-102, null, 0, relayBuffer); relayHeader = new byte[relayHeaderLength]; Array.Copy(relayBuffer, 0, relayHeader, 0, relayHeaderLength); } Array.Copy(relayHeader, 0, relayBuffer, 0, relayHeader.Length); byte[] destination = clientGuid.ToByteArray(); Array.Copy(destination, 0, relayBuffer, 24, 16); Array.Copy(sendBuffer, 0, relayBuffer, 40, sendBufferLength); if (connectedv6 && clientSocketv6 != null) { UdpMeshCommon.Send(clientSocketv6, relayBuffer, relayBufferLength, serverEndpointv6); return; } if (connectedv4 && clientSocketv4 != null) { UdpMeshCommon.Send(clientSocketv4, relayBuffer, relayBufferLength, serverEndpointv4); return; } } }
private void HandleHeartBeat(byte[] inputData, int inputDataLength, Guid clientGuid, IPEndPoint iPEndPoint) { lock (buildBuffer) { lock (sendBuffer) { if (inputDataLength != 32) { return; } UdpPeer peer = GetPeer(clientGuid); if (peer == null) { return; } peer.lastReceiveTime = DateTime.UtcNow.Ticks; byte[] currentTime = BitConverter.GetBytes(DateTime.UtcNow.Ticks); UdpMeshCommon.FlipEndian(ref currentTime); Array.Copy(inputData, 24, heartbeatReplyBytes, 0, 8); Array.Copy(currentTime, 0, heartbeatReplyBytes, 8, 8); int length = UdpMeshCommon.GetPayload(-202, heartbeatReplyBytes, heartbeatReplyBytes.Length, sendBuffer); if (UdpMeshCommon.IsIPv4(iPEndPoint.Address)) { UdpMeshCommon.Send(clientSocketv4, sendBuffer, length, iPEndPoint); } if (UdpMeshCommon.IsIPv6(iPEndPoint.Address)) { UdpMeshCommon.Send(clientSocketv6, sendBuffer, length, iPEndPoint); } if (UdpMeshCommon.IsIPv4(iPEndPoint.Address)) { if (!peer.usev4) { Array.Copy(clientGuid.ToByteArray(), 0, buildBuffer, 0, 16); buildBuffer[16] = 4; byte[] endpointBytes = iPEndPoint.Address.GetAddressBytes(); if (endpointBytes.Length == 4) { Array.Copy(endpointBytes, 0, buildBuffer, 17, 4); } if (endpointBytes.Length == 16) { Array.Copy(endpointBytes, 12, buildBuffer, 17, 4); } byte[] portBytes = BitConverter.GetBytes((UInt16)iPEndPoint.Port); UdpMeshCommon.FlipEndian(ref portBytes); Array.Copy(portBytes, 0, buildBuffer, 21, 2); int sendLength = UdpMeshCommon.GetPayload(-103, buildBuffer, 25, sendBuffer); UdpMeshCommon.Send(clientSocketv4, sendBuffer, sendLength, serverEndpointv4); } } if (UdpMeshCommon.IsIPv6(iPEndPoint.Address)) { if (!peer.usev6) { Array.Copy(clientGuid.ToByteArray(), 0, buildBuffer, 0, 16); buildBuffer[16] = 6; byte[] endpointBytes = iPEndPoint.Address.GetAddressBytes(); Array.Copy(endpointBytes, 0, buildBuffer, 17, 16); byte[] portBytes = BitConverter.GetBytes((UInt16)iPEndPoint.Port); UdpMeshCommon.FlipEndian(ref portBytes); Array.Copy(portBytes, 0, buildBuffer, 33, 2); int sendLength = UdpMeshCommon.GetPayload(-103, buildBuffer, 35, sendBuffer); UdpMeshCommon.Send(clientSocketv6, sendBuffer, sendLength, serverEndpointv6); } } } } }