private void HandleReceive(IAsyncResult ar) { UdpClient receiveClient = (UdpClient)ar.AsyncState; try { IPEndPoint receiveAddr = null; byte[] receiveBytes = receiveClient.EndReceive(ar, ref receiveAddr); if (receiveBytes.Length >= 24) { UdpMeshCommon.ProcessBytes(receiveBytes, receiveAddr, callbacks); } } catch (Exception e) { if (!shutdown) { Console.WriteLine("Error receiving: " + e); } } if (!shutdown) { try { receiveClient.BeginReceive(HandleReceive, receiveClient); } catch (Exception e) { Console.WriteLine("Error restarting receive: " + e); error = true; } } }
public static Guid[] RequestRemoteIPv6(UdpClient client) { byte[] header = GetRequestBytes(); Guid[] retVal = new Guid[2]; retVal[0] = Guid.Empty; retVal[1] = Guid.Empty; if (stunServer1v4 == null) { SetStunServer(); } if (stunServer1v6 == null) { return(retVal); } try { retVal[0] = WriteGuid(header); UdpMeshCommon.Send(client, header, stunServer1v6); } catch { //Don't care } try { retVal[1] = WriteGuid(header); UdpMeshCommon.Send(client, header, stunServer2v6); } catch { //Don't care } return(retVal); }
private void SendClientsHello() { byte[] timeBytes = BitConverter.GetBytes(DateTime.UtcNow.Ticks); UdpMeshCommon.FlipEndian(ref timeBytes); byte[] sendBytes = UdpMeshCommon.GetPayload(-201, timeBytes); lock (clients) { foreach (UdpPeer peer in clients.Values) { if (peer.guid == UdpMeshCommon.GetMeshAddress()) { continue; } //Send to ipv4 if (peer.usev4) { UdpMeshCommon.Send(clientSocketv4, sendBytes, peer.contactV4); } else { foreach (IPEndPoint iPEndPoint in peer.remoteEndpoints) { if (UdpMeshCommon.IsIPv4(iPEndPoint.Address)) { string newContactString = iPEndPoint.ToString(); if (!contactedIPs.Contains(newContactString)) { contactedIPs.Add(newContactString); DebugLog("Attempting new contact v4: " + newContactString); } UdpMeshCommon.Send(clientSocketv4, sendBytes, iPEndPoint); } } } //Send to ipv6 if (peer.usev6) { UdpMeshCommon.Send(clientSocketv6, sendBytes, peer.contactV6); } else { foreach (IPEndPoint iPEndPoint in peer.remoteEndpoints) { if (UdpMeshCommon.IsIPv6(iPEndPoint.Address)) { string newContactString = iPEndPoint.ToString(); if (!contactedIPs.Contains(newContactString)) { contactedIPs.Add(newContactString); DebugLog("Attempting new contact v6: " + newContactString); } UdpMeshCommon.Send(clientSocketv6, sendBytes, iPEndPoint); } } } } } }
private void HandleRelayMessage(byte[] inputData, Guid serverGuid, IPEndPoint endPoint) { if (inputData.Length < 64) { return; } byte[] cropMessage = new byte[inputData.Length - 40]; Array.Copy(inputData, 40, cropMessage, 0, cropMessage.Length); UdpMeshCommon.ProcessBytes(cropMessage, null, callbacks); }
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; } }
private void ClientExternalReport(byte[] inputBytes, Guid guid, IPEndPoint iPEndPoint) { if (inputBytes.Length != 47 && inputBytes.Length != 59) { return; } byte type = inputBytes[40]; Guid onBehalfOf; lock (tempGuid) { Array.Copy(inputBytes, 24, tempGuid, 0, 16); onBehalfOf = new Guid(tempGuid); } lock (clients) { UdpPeer peer; if (clients.TryGetValue(onBehalfOf, out peer)) { IPAddress addr; int port; if (inputBytes.Length == 47 && type == 4) { lock (tempClientPort) { Array.Copy(inputBytes, 41, tempClientAddress4, 0, 4); addr = new IPAddress(tempClientAddress4); Array.Copy(inputBytes, 45, tempClientPort, 0, 2); UdpMeshCommon.FlipEndian(ref tempClientPort); port = BitConverter.ToUInt16(tempClientPort, 0); } IPEndPoint endPoint = new IPEndPoint(addr, port); peer.AddRemoteEndpoint(endPoint); } if (inputBytes.Length == 59 && type == 6) { lock (tempClientPort) { Array.Copy(inputBytes, 41, tempClientAddress6, 0, 16); addr = new IPAddress(tempClientAddress6); Array.Copy(inputBytes, 57, tempClientPort, 0, 2); UdpMeshCommon.FlipEndian(ref tempClientPort); port = BitConverter.ToUInt16(tempClientPort, 0); } IPEndPoint endPoint = new IPEndPoint(addr, port); peer.AddRemoteEndpoint(endPoint); } } } }
/// <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 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 RelayMessage(byte[] inputBytes, int inputBytesLength, Guid client, IPEndPoint endPoint) { //A valid message must contain 2 headers (24 bytes) and a destination GUID (16 bytes) if (inputBytesLength < 64) { return; } //Make sure client isn't relaying control messages lock (tempType) { Array.Copy(inputBytes, 60, tempType, 0, 4); UdpMeshCommon.FlipEndian(ref tempType); int relayType = BitConverter.ToInt32(tempType, 0); if (relayType < 0) { return; } } UdpPeer peer; lock (tempGuid) { Array.Copy(inputBytes, 24, tempGuid, 0, 16); Guid destinationGuid = new Guid(tempGuid); clients.TryGetValue(destinationGuid, out peer); } //Make sure client is connected if (peer == null) { return; } if (relayHeader == null) { relayHeader = new byte[24]; UdpMeshCommon.GetPayload(-3, null, 0, relayHeader); } Array.Copy(relayHeader, 0, inputBytes, 0, 24); if (peer.usev6) { UdpMeshCommon.Send(serverSocketv6, inputBytes, peer.contactV6); return; } if (peer.usev4) { UdpMeshCommon.Send(serverSocketv4, inputBytes, peer.contactV4); return; } }
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; } } }
/// <summary> /// Send FROM the server /// </summary> internal byte[] GetClientEndpointMessage() { if (!cacheOK) { cacheOK = true; List <IPEndPoint> v4end = new List <IPEndPoint>(); List <IPEndPoint> v6end = new List <IPEndPoint>(); foreach (IPEndPoint endPoint in remoteEndpoints) { if (endPoint.AddressFamily == AddressFamily.InterNetwork) { v4end.Add(endPoint); } if (endPoint.AddressFamily == AddressFamily.InterNetworkV6) { v6end.Add(endPoint); } } int cachedDataBuildLength = 18 + 6 * v4end.Count + 18 * v6end.Count; Array.Copy(guid.ToByteArray(), cachedDataBuild, 16); cachedDataBuild[16] = (Byte)v4end.Count; int writepos = 17; foreach (IPEndPoint endPoint in v4end) { byte[] addrBytes = endPoint.Address.GetAddressBytes(); Array.Copy(addrBytes, 0, cachedDataBuild, writepos, 4); writepos += 4; byte[] portBytes = BitConverter.GetBytes((ushort)endPoint.Port); UdpMeshCommon.FlipEndian(ref portBytes); Array.Copy(portBytes, 0, cachedDataBuild, writepos, 2); writepos += 2; } cachedDataBuild[writepos] = (Byte)v6end.Count; writepos++; foreach (IPEndPoint endPoint in v6end) { byte[] addrBytes = endPoint.Address.GetAddressBytes(); Array.Copy(addrBytes, 0, cachedDataBuild, writepos, 16); writepos += 16; byte[] portBytes = BitConverter.GetBytes((ushort)endPoint.Port); UdpMeshCommon.FlipEndian(ref portBytes); Array.Copy(portBytes, 0, cachedDataBuild, writepos, 2); writepos += 2; } cachedDataLength = UdpMeshCommon.GetPayload(-2, cachedDataBuild, cachedDataBuildLength, cachedData); } return(cachedData); }
private void HandleReceive(UdpClient receiveClient, bool isv6) { try { if (receiveClient.Client.Available == 0) { return; } byte[] buffer = v4buffer; EndPoint receiveAddrEndpoint = (EndPoint)anyV4; if (isv6) { buffer = v6buffer; receiveAddrEndpoint = (EndPoint)anyV6; } byte[] processBytes = buffer; int bytesRead = receiveClient.Client.ReceiveFrom(buffer, ref receiveAddrEndpoint); IPEndPoint receiveAddr = (IPEndPoint)receiveAddrEndpoint; bool process = true; if (bytesRead >= 24) { if (process) { try { if (!UdpMeshCommon.USE_BUFFERS) { processBytes = new byte[bytesRead]; Array.Copy(buffer, 0, processBytes, 0, bytesRead); } UdpMeshCommon.ProcessBytes(processBytes, bytesRead, receiveAddr, callbacks); } catch (Exception e) { DebugLog("Error processing message: " + e); } } } } catch (Exception e) { if (!shutdown) { Console.WriteLine("Error receiving: " + e); } } }
/// <summary> /// Sent TO the server /// </summary> internal byte[] GetServerEndpointMessage() { if (cachedData == null) { List <IPEndPoint> v4end = new List <IPEndPoint>(); List <IPEndPoint> v6end = new List <IPEndPoint>(); foreach (IPEndPoint endPoint in remoteEndpoints) { if (endPoint.AddressFamily == AddressFamily.InterNetwork) { v4end.Add(endPoint); } if (endPoint.AddressFamily == AddressFamily.InterNetworkV6) { v6end.Add(endPoint); } } cachedData = new byte[2 + 6 * v4end.Count + 18 * v6end.Count]; cachedData[0] = (Byte)v4end.Count; int writepos = 1; foreach (IPEndPoint endPoint in v4end) { byte[] addrBytes = endPoint.Address.GetAddressBytes(); Array.Copy(addrBytes, 0, cachedData, writepos, 4); writepos += 4; byte[] portBytes = BitConverter.GetBytes((ushort)endPoint.Port); UdpMeshCommon.FlipEndian(ref portBytes); Array.Copy(portBytes, 0, cachedData, writepos, 2); writepos += 2; } cachedData[writepos] = (Byte)v6end.Count; writepos++; foreach (IPEndPoint endPoint in v6end) { byte[] addrBytes = endPoint.Address.GetAddressBytes(); Array.Copy(addrBytes, 0, cachedData, writepos, 16); writepos += 16; byte[] portBytes = BitConverter.GetBytes((ushort)endPoint.Port); UdpMeshCommon.FlipEndian(ref portBytes); Array.Copy(portBytes, 0, cachedData, writepos, 2); writepos += 2; } cachedData = UdpMeshCommon.GetPayload(-101, cachedData); } return(cachedData); }
private void HandleRelayMessage(byte[] inputData, int inputDataLength, Guid serverGuid, IPEndPoint endPoint) { lock (relayBuffer) { if (inputDataLength < 64) { return; } byte[] relayData = relayBuffer; if (!UdpMeshCommon.USE_BUFFERS) { relayData = new byte[inputDataLength - 40]; } Array.Copy(inputData, 0, relayData, 0, inputDataLength - 40); UdpMeshCommon.ProcessBytes(relayData, inputDataLength - 40, null, callbacks); } }
private void SendServerInfo() { byte[] serverData = me.GetServerEndpointMessage(); if (serverEndpointv4 != null) { if (serverEndpointv4.Address != IPAddress.None) { UdpMeshCommon.Send(clientSocketv4, serverData, serverEndpointv4); } } if (serverEndpointv6 != null) { if (serverEndpointv6.Address != IPAddress.None) { UdpMeshCommon.Send(clientSocketv6, serverData, serverEndpointv6); } } }
private byte[] GetConnectedGuidBytes() { if (connectedGuidBytes == null) { lock (clients) { connectedGuidBytes = new byte[16 * clients.Count]; int writepos = 0; foreach (Guid guid in clients.Keys) { Array.Copy(guid.ToByteArray(), 0, connectedGuidBytes, writepos, 16); writepos = writepos + 16; } connectedGuidBytes = UdpMeshCommon.GetPayload(-1, connectedGuidBytes); } } return(connectedGuidBytes); }
private void SendClientsMeshState() { lock (clients) { byte[] sendGuidBytes = GetConnectedGuidBytes(); clientBytes.Clear(); foreach (UdpPeer client in clients.Values) { clientBytes.Add(client.GetClientEndpointMessage()); } foreach (KeyValuePair <Guid, UdpPeer> client in clients) { if ((client.Value.lastReceiveTime + CLIENT_TIMEOUT) < DateTime.UtcNow.Ticks) { removeList.Add(client.Key); continue; } if (serverSocketv4 != null && client.Value.usev4) { UdpMeshCommon.Send(serverSocketv4, sendGuidBytes, client.Value.contactV4); foreach (byte[] clientByte in clientBytes) { UdpMeshCommon.Send(serverSocketv4, clientByte, client.Value.contactV4); } } if (serverSocketv6 != null && client.Value.usev6) { UdpMeshCommon.Send(serverSocketv6, sendGuidBytes, client.Value.contactV6); foreach (byte[] clientByte in clientBytes) { UdpMeshCommon.Send(serverSocketv6, clientByte, client.Value.contactV6); } } } foreach (Guid client in removeList) { clients.Remove(client); connectedGuidBytes = null; } removeList.Clear(); } }
private void HandleServerReport(byte[] inputData, int inputDataLength, Guid serverGuid, IPEndPoint serverEndpoint) { lock (guidData) { if (UdpMeshCommon.IsIPv4(serverEndpoint.Address)) { connectedv4 = true; } if (UdpMeshCommon.IsIPv6(serverEndpoint.Address)) { connectedv6 = true; } int readPos = 24; lock (clients) { removeGuids.AddRange(clients.Keys); while (inputDataLength - readPos >= 16) { Array.Copy(inputData, readPos, guidData, 0, 16); readPos += 16; Guid newGuid = new Guid(guidData); if (!clients.ContainsKey(newGuid)) { clients.Add(newGuid, new UdpPeer(newGuid)); } if (removeGuids.Contains(newGuid)) { removeGuids.Remove(newGuid); } } foreach (Guid guid in removeGuids) { clients.Remove(guid); } removeGuids.Clear(); } } }
private byte[] GetConnectedGuidBytes() { lock (sendBuffer) { if (connectedGuidBytes == null) { lock (clients) { byte[] connectedGuidBytesBuild = new byte[16 * clients.Count]; int writepos = 0; foreach (Guid guid in clients.Keys) { Array.Copy(guid.ToByteArray(), 0, connectedGuidBytesBuild, writepos, 16); writepos = writepos + 16; } int connectedGuidBytesLength = UdpMeshCommon.GetPayload(-1, connectedGuidBytesBuild, connectedGuidBytesBuild.Length, sendBuffer); connectedGuidBytes = new byte[connectedGuidBytesLength]; Array.Copy(sendBuffer, 0, connectedGuidBytes, 0, connectedGuidBytesLength); } } return(connectedGuidBytes); } }
private static void SetStunServer() { IPAddress[] addrs1 = Dns.GetHostAddresses("stun1.l.google.com"); IPAddress[] addrs2 = Dns.GetHostAddresses("stun2.l.google.com"); foreach (IPAddress addr1 in addrs1) { if (UdpMeshCommon.IsIPv4(addr1)) { stunServer1v4 = new IPEndPoint(addr1, 19302); break; } } foreach (IPAddress addr2 in addrs2) { if (UdpMeshCommon.IsIPv4(addr2)) { stunServer2v4 = new IPEndPoint(addr2, 19302); break; } } foreach (IPAddress addr1 in addrs1) { if (UdpMeshCommon.IsIPv6(addr1)) { stunServer1v6 = new IPEndPoint(addr1, 19302); break; } } foreach (IPAddress addr2 in addrs2) { if (UdpMeshCommon.IsIPv6(addr2)) { stunServer2v6 = new IPEndPoint(addr2, 19302); break; } } }
/// <summary> /// Processes a received stun message. /// </summary> /// <returns>Stun result</returns> /// <param name="inputData">Input raw stun message</param> public static StunResult ProcessStun(byte[] inputData, int inputDataLength) { StunResult retVal = new StunResult(); if (inputDataLength < 20) { return(retVal); } byte[] messageShortBytes = new byte[2]; Array.Copy(inputData, 0, messageShortBytes, 0, 2); UdpMeshCommon.FlipEndian(ref messageShortBytes); int messageTypeCombined = BitConverter.ToInt16(messageShortBytes, 0); Array.Copy(inputData, 2, messageShortBytes, 0, 2); UdpMeshCommon.FlipEndian(ref messageShortBytes); int messageLength = BitConverter.ToInt16(messageShortBytes, 0); byte[] messageGuidBytes = new byte[16]; Array.Copy(inputData, 4, messageGuidBytes, 0, 16); retVal.messageGuid = new Guid(messageGuidBytes); int bytesToRead = messageLength; while (bytesToRead > 0) { if (bytesToRead < 4) { return(retVal); } Array.Copy(inputData, inputData.Length - bytesToRead, messageShortBytes, 0, 2); UdpMeshCommon.FlipEndian(ref messageShortBytes); int attrType = BitConverter.ToUInt16(messageShortBytes, 0); bytesToRead -= 2; Array.Copy(inputData, inputData.Length - bytesToRead, messageShortBytes, 0, 2); UdpMeshCommon.FlipEndian(ref messageShortBytes); int attrLength = BitConverter.ToUInt16(messageShortBytes, 0); bytesToRead -= 2; if (attrLength > 0) { byte[] attrBytes = new byte[attrLength]; Array.Copy(inputData, inputData.Length - bytesToRead, attrBytes, 0, attrLength); bytesToRead -= attrLength; if (attrType == 1 && attrBytes[1] == 1 && attrLength == 8) { Array.Copy(attrBytes, 2, messageShortBytes, 0, 2); UdpMeshCommon.FlipEndian(ref messageShortBytes); retVal.port = BitConverter.ToUInt16(messageShortBytes, 0); byte[] ipBytes = new byte[4]; Array.Copy(attrBytes, 4, ipBytes, 0, 4); retVal.remoteAddr = new IPAddress(ipBytes); retVal.success = true; } if (attrType == 1 && attrBytes[1] == 2 && attrLength == 20) { Array.Copy(attrBytes, 2, messageShortBytes, 0, 2); UdpMeshCommon.FlipEndian(ref messageShortBytes); retVal.port = BitConverter.ToUInt16(messageShortBytes, 0); byte[] ipBytes = new byte[16]; Array.Copy(attrBytes, 4, ipBytes, 0, 16); retVal.remoteAddr = new IPAddress(ipBytes); retVal.success = true; } if (attrType == 32 && attrBytes[1] == 1 && attrLength == 8) { Array.Copy(attrBytes, 2, messageShortBytes, 0, 2); //Xor with magic cookie XorBytes(messageShortBytes, messageGuidBytes); UdpMeshCommon.FlipEndian(ref messageShortBytes); retVal.port = BitConverter.ToUInt16(messageShortBytes, 0); byte[] ipBytes = new byte[4]; Array.Copy(attrBytes, 4, ipBytes, 0, 4); //Xor with magic cookie XorBytes(ipBytes, messageGuidBytes); retVal.remoteAddr = new IPAddress(ipBytes); retVal.success = true; } if (attrType == 32 && attrBytes[1] == 2 && attrLength == 20) { Array.Copy(attrBytes, 2, messageShortBytes, 0, 2); //Xor with magic cookie XorBytes(messageShortBytes, messageGuidBytes); UdpMeshCommon.FlipEndian(ref messageShortBytes); retVal.port = BitConverter.ToUInt16(messageShortBytes, 0); byte[] ipBytes = new byte[16]; Array.Copy(attrBytes, 4, ipBytes, 0, 16); //Xor with magic cookie XorBytes(ipBytes, messageGuidBytes); retVal.remoteAddr = new IPAddress(ipBytes); retVal.success = true; } } } if (callback != null) { callback(retVal); } return(retVal); }
public void Run() { try { clientSocketv4 = new UdpClient(0, AddressFamily.InterNetwork); } catch (Exception e) { DebugLog("Error setting up v4 socket: " + e); clientSocketv4 = null; } try { clientSocketv6 = new UdpClient(0, AddressFamily.InterNetworkV6); } catch (Exception e) { DebugLog("Error setting up v6 socket: " + e); clientSocketv6 = null; } if (clientSocketv4 != null) { clientSocketv4.BeginReceive(HandleReceive, clientSocketv4); } if (clientSocketv6 != null) { clientSocketv6.BeginReceive(HandleReceive, clientSocketv6); } if (clientSocketv4 != null) { int v4portNumber = ((IPEndPoint)clientSocketv4.Client.LocalEndPoint).Port; DebugLog("Listening on port v4:" + v4portNumber); foreach (IPAddress addr in myAddresses) { if (UdpMeshCommon.IsIPv4(addr)) { me.AddRemoteEndpoint(new IPEndPoint(addr, v4portNumber)); } } } if (clientSocketv6 != null) { int v6portNumber = ((IPEndPoint)clientSocketv6.Client.LocalEndPoint).Port; DebugLog("Listening on port v6:" + v6portNumber); foreach (IPAddress addr in myAddresses) { if (UdpMeshCommon.IsIPv6(addr)) { me.AddRemoteEndpoint(new IPEndPoint(addr, v6portNumber)); } } } while (!shutdown && !error && clientSocketv4 != null && clientSocketv6 != null) { //Restun every 5 minutes if ((DateTime.UtcNow.Ticks - receivedStun) > (TimeSpan.TicksPerMinute * 5)) { if (clientSocketv4 != null) { UdpStun.RequestRemoteIPv4(clientSocketv4); UdpStun.RequestRemoteIPv6(clientSocketv6); } } SendServerInfo(); SendClientsHello(); System.Threading.Thread.Sleep(10000); } Shutdown(); }
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 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); } } } } }
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); } } }