private void BtnSend_Click(object sender, RoutedEventArgs e) { if (UdpSocket != null) { CommPacket oCommPacket = new CommPacket() { PacketID = int.Parse(TxtProtocolID.Text), Content = TxtProtoclContet.Text, }; UdpSocket.UserToken.SendAsync(oCommPacket); } }
private void ProcessUdpPacket(CommPacket packet, IPEndPoint ep) { PeerData peer = null; if (packet is UdpConnectingConfirmation) { AddPeerToDictionaries(NewPeer); if (ReceivedConfirmation != null) { ReceivedConfirmation.Set(); } } else if (packet is UdpNewPeerPacket) { UdpNewPeerPacket newPeerPacket = packet as UdpNewPeerPacket; if (newPeerPacket.RecipientIsNew && AwaitingExternalConnection) { AwaitingExternalConnection = false; AddPeersToDictionaries(newPeerPacket.Peers); StartDriver(newPeerPacket.SubnetworkData, newPeerPacket.SubnetworkIP, newPeerPacket.Name); OnConnected(this, null); UdpConnectingConfirmation confirmPacket = new UdpConnectingConfirmation(); SendPacket <UdpConnectingConfirmation>(confirmPacket, ep); Thread.Sleep(100); NegotiateKey(PeersRxSupport[ep], null); } else { if (newPeerPacket.Peers != null && !newPeerPacket.RecipientIsNew) { if (newPeerPacket.Peers.Length != 0) { AddPeerToDictionaries(newPeerPacket.Peers[0]); NegotiateKey(peer, null); } } } } else if (packet is UdpKeyNegotiationPacket) { if (!PeersRxSupport.TryGetValue(ep, out peer)) { peer = NewPeer; } NegotiateKey(peer, packet as UdpKeyNegotiationPacket); } else if (packet is UdpGoodbye) { RemovePeerFromDictionaries(PeersRxSupport[ep], "goodbye"); } else if (packet is UdpHeartbeat) { if (PeersRxSupport.TryGetValue(ep, out peer)) { peer.Heartbeat(); } } }
private void ForwardStreamNew(Stream source, Stream destination, byte[] buffer, CommPacketDirection direction) { var rawVerbs = new string[] { "GET", "HEAD", "POST", "PUT", "DELETE", "TRACE", "CONNECT" }; byte[][] verbs = rawVerbs.Select(cur => Encoding.UTF8.GetBytes(cur).Take(2).ToArray()).ToArray(); Regex requestLinePattern = new Regex($"^({string.Join("|", rawVerbs)}) [^ ]+ HTTP/1.1$"); Regex contentLengthPattern = new Regex($"^Content-Length: ([0-9]+)$"); Regex chunkedPattern = new Regex($"^Transfer-Encoding: chunked$"); Regex statusLinePattern = new Regex($"^HTTP/1.1 ([0-9]+) (.*)$"); Regex websocketPlanet = new Regex("GET /([0-9]+)/websocket/game HTTP/1.1"); Regex udpPortPattern = new Regex("\"udpPort\"\\:([0-9]+)\\,"); try { destination = new BufferedStream(destination); } catch { return; } new Thread(() => { MemoryStream ms = null; try { bool isWebSocket = false; while (true) { try { destination.Flush(); } catch { Kill(direction == CommPacketDirection.ServerToClient); } if (!m_connectionInstance.IsConnectionOpen) { break; } //if (ms != null) //{ // ms.Position = 0; // messagecache[direction].Enqueue(ms); //} //while (messagecache[direction].Count > 10) //{ // messagecache[direction].Dequeue(); //} ms = new MemoryStream(); StreamWriter sw = null; bool ReadBytes(int count) { int offset = 0; while (offset < count) { int bytesRead = 0; try { bytesRead = source.Read(buffer, offset, count - offset); } catch { Kill(direction == CommPacketDirection.ClientToServer); } if (bytesRead == 0) { return(false); } offset += bytesRead; } return(true); } string ReadLine() { List <byte> result = new List <byte>(); byte?prevByte = null; while (true) { byte[] readBuffer = new byte[1]; if (source.Read(readBuffer, 0, 1) != 1) { return(null); } result.Add(readBuffer[0]); if (prevByte == '\r' && readBuffer[0] == '\n') { break; } prevByte = readBuffer[0]; } return(Encoding.UTF8.GetString(result.ToArray()).TrimEnd('\r', '\n')); } void DoHttpHeadersContentAndForward() { List <string> headers = new List <string>(); ulong contentLength = 0; bool chunked = false; string curLine = null; while ((curLine = ReadLine()) != null && curLine != string.Empty) { sw.WriteLine(curLine); curLine = curLine.Trim(); Match m = contentLengthPattern.Match(curLine); if (m.Success) { contentLength = Convert.ToUInt64(m.Groups[1].Value); } m = chunkedPattern.Match(curLine); if (m.Success) { chunked = true; } headers.Add(curLine.ToLower()); } sw.WriteLine(); sw.Flush(); if (curLine == null) { throw new Exception("HTTP unexpected end of stream while reading headers"); } if (chunked && contentLength > 0) { throw new Exception("Chunked content with length not supported"); } void DoReadLength(ulong curLength) { while (curLength > 0) { int bytesRead = 0; try { bytesRead = source.Read(buffer, 0, Math.Min(buffer.Length, (int)Math.Min(int.MaxValue, curLength))); } catch { Kill(direction == CommPacketDirection.ClientToServer); } if (bytesRead == 0) { throw new Exception("HTTP unexpected end of stream while reading content"); } ms.Write(buffer, 0, bytesRead); curLength -= (ulong)bytesRead; } } DoReadLength(contentLength); if (chunked) { bool lastChunk = false; while (!lastChunk && (curLine = ReadLine()) != null && curLine != string.Empty) { sw.WriteLine(curLine); sw.Flush(); var length = ulong.Parse(curLine.Trim()); if (length > 0) { DoReadLength(length); } else { lastChunk = true; } curLine = ReadLine(); if (curLine == null || curLine.Length != 0) { throw new Exception("HTTP protocol failure"); } sw.WriteLine(); sw.Flush(); } } ms.Position = 0; if (!headers.Contains("content-type: application/json".ToLower())) { DestinationWrite(destination, ms.ToArray(), (int)ms.Length, direction); } else { var orgLength = ms.Length; string entireMessage = new StreamReader(ms).ReadToEnd(); ForwardHttpData(destination, entireMessage, direction); } } void forwardWebsocketFrame() { WsFrame frame = null; try { frame = new WsFrame(buffer, 2, source); } catch { } var worldData = frame?.Messages.FirstOrDefault(cur => cur.ApiId.HasValue && cur.ApiId.Value == 0); if (worldData != null) { string theJson = Encoding.UTF8.GetString(worldData.Buffer, 0, worldData.Buffer.Length); Match m = udpPortPattern.Match(theJson); if (m.Success && planetStringName != null) { int serverPort = Convert.ToInt32(m.Groups[1].Value); if (serverPort.ToString().Length != 4) { throw new Exception("Length change of udpPort"); } if (!planetPorts.ContainsKey(planetStringName)) { //throw new Exception($"Planet dictionary does not contain {planetStringName}"); } else { planetPorts[planetStringName].RemotePort = serverPort; theJson = udpPortPattern.Replace(theJson, $"\"udpPort\":{planetPorts[planetStringName].LocalPort},"); byte[] sendData = Encoding.UTF8.GetBytes(theJson); if (sendData.Length != worldData.Buffer.Length) { throw new Exception("JSON length error"); } worldData.Buffer = sendData; } } } if (planetStringName != null) { frame?.Messages.AddRange(GetOutgoingMessages(planetStringName, direction)); } try { frame?.Send(destination); } catch { Kill(direction == CommPacketDirection.ServerToClient); } //if (frame.readStream.Length != frame.writeStream.Length) //{ // throw new Exception("frame length mismatch."); //} //if (!frame.readStream.ToArray().SequenceEqual(frame.writeStream.ToArray())) //{ // throw new Exception("frame data mismatch."); //} if (frame == null) { frame = new WsFrame() { Messages = new List <WsMessage> { new WsMessage(24, null, Encoding.UTF8.GetBytes("Frame decoding failure!")), }, }; } try { websocketDataQueue[direction].Add(frame); } catch { } if (ProxyUiWindow.Instance.GetDataContext <ProxyUiWindowViewModel>().CaptureEnabled) { var parentPacket = new CommPacket { Data = frame.HeaderBytes, Direction = direction, Id = Guid.NewGuid(), Instance = m_connectionInstance, ParentPacket = null, Header = "Websocket Frame", }; foreach (var curMessage in frame.Messages) { var headerPacket = new CommPacket { Data = BitConverter.GetBytes((ushort)(curMessage.Buffer.Length + 1)).Concat(new byte[] { curMessage.ApiId ?? 0 }).ToArray(), Direction = direction, Id = Guid.NewGuid(), Instance = m_connectionInstance, ParentPacket = parentPacket, Header = $"Websocket Message[0x{curMessage.ApiId ?? 0:X2}]", }; var payloadPacket = new CommPacket { Data = curMessage.Buffer, Direction = direction, Id = Guid.NewGuid(), Instance = m_connectionInstance, ParentPacket = parentPacket, Header = $"Websocket Payload", }; headerPacket.ChildPackets.Add(payloadPacket); parentPacket.ChildPackets.Add(headerPacket); } ; ProxyUiWindow.Instance.GetDataContext <ProxyUiWindowViewModel>().SendBytesToUi(m_connectionInstance, parentPacket); } } if (!ReadBytes(2)) { // Connection terminated waiting for new message. This is fine. break; } if (direction == CommPacketDirection.ClientToServer) { if (!verbs.Any(cur => cur[0] == buffer[0] && cur[1] == buffer[1]) && !isWebSocket) { isWebSocket = true; ProxyManagerWindow.Instance.Dispatcher.BeginInvoke(new Action(() => { m_connectionInstance.Parent.Instances.Remove(m_connectionInstance); var wsg = ComponentEngine.Instance.GetComponent <TcpComponent>().websocketGroup; m_connectionInstance.Parent = wsg; wsg.Instances.Add(m_connectionInstance); })); } if (!isWebSocket) { // GET /index.html HTTP/1.1 sw = new StreamWriter(ms); string requestLine = (Encoding.UTF8.GetString(buffer, 0, 2) + ReadLine()).Trim(); sw.WriteLine(requestLine); if (!requestLinePattern.IsMatch(requestLine)) { throw new Exception("HTTP request line invalid"); } Match m = websocketPlanet.Match(requestLine); if (m.Success) { var newVal = Convert.ToInt32(m.Groups[1].Value); if (planetId != -1) { if (planetId != newVal) { throw new Exception("Multiple planets detected on a single stream"); } } else { planetId = newVal; planetStringName = planetLookup.Where(cur => cur.Value.Value == newVal).FirstOrDefault().Key; planetDisplayName = planetLookup[planetStringName].Key; } } DoHttpHeadersContentAndForward(); } else { forwardWebsocketFrame(); } } else { if ((buffer[0] != 'H' || buffer[1] != 'T') && !isWebSocket) { isWebSocket = true; ProxyManagerWindow.Instance.Dispatcher.BeginInvoke(new Action(() => { m_connectionInstance.Parent.Instances.Remove(m_connectionInstance); var wsg = ComponentEngine.Instance.GetComponent <TcpComponent>().websocketGroup; m_connectionInstance.Parent = wsg; wsg.Instances.Add(m_connectionInstance); })); } if (!isWebSocket) { // HTTP/1.1 200 OK sw = new StreamWriter(ms); string statusLine = (Encoding.UTF8.GetString(buffer, 0, 2) + ReadLine()).Trim(); sw.WriteLine(statusLine); if (!statusLinePattern.IsMatch(statusLine)) { throw new Exception("HTTP status line invalid"); } DoHttpHeadersContentAndForward(); } else { forwardWebsocketFrame(); } } } Kill(direction == CommPacketDirection.ClientToServer); } catch (Exception) { //MainWindow.Instance.Dispatcher.Invoke(new Action(() => //{ // MessageBox.Show($"4 Fatal error: {ex.Message}"); //})); Kill(direction == CommPacketDirection.ClientToServer); } }).Start(); }