async Task <P2PSettings> MatchingRequest(string url, StunResult ret, CancellationToken token) { var json = $"{{\"endpoint\":\"{ret.EndPoint}\",\"local_endpoint\":\"{ret.LocalEndPoint}\", \"nattype\": \"{ret.NatType}\"}}"; var content = new StringContent(json); using (var client = new HttpClient()) { var response = await client.PostAsync(url, content, token); if (response.StatusCode == HttpStatusCode.OK) { json = await response.Content.ReadAsStringAsync(); var res = Json.From <Response>(json); return(new P2PSettings { SelfId = res.id, Peers = res.peers.Select(x => x.Create()).ToArray() }); } else if (response.StatusCode == HttpStatusCode.RequestTimeout) { throw new Exception("Matching Timeout"); } } throw new Exception("Matching fail"); }
/// <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); }