private void SendPacketEnvelope(SocketState connection, PacketEnvelope envelope) { byte[] sendBuffer = Packetizer.AssembleMessagePacket(envelope, connection.UseCompression, false, null, null); Stats.BytesSent += (UInt64)sendBuffer.Length; connection.Socket.Send(sendBuffer, sendBuffer.Length, SocketFlags.None); }
void ProcessReceivedData(SocketState connection, byte[] buffer, int bufferSize) { string sharedSecretString = connection.Peer.IsEncryptionNegotationComplete ? connection.Peer.KeyNegotiator.SharedSecretString : null; string commonSalt = null; if (connection.Peer.IsIncomming && connection.Peer.IsEncryptionNegotationComplete) { commonSalt = _route.BindingPreSharedKey; } else if (connection.Peer.IsOutgoing && connection.Peer.IsEncryptionNegotationComplete) { commonSalt = _route.EndpointPreSharedKey; } if (_route.TrafficType == TrafficType.Http) { HttpHeaderType httpHeaderType = HttpHeaderType.None; string httpHeader = null; string httpRequestVerb = string.Empty; if (connection.HttpHeaderBuilder != string.Empty) { //This is a continuation of a previously received fragmented header. httpHeader = (connection.HttpHeaderBuilder ?? string.Empty) + Encoding.UTF8.GetString(buffer); httpHeaderType = HttpUtility.IsHttpHeader(httpHeader, out httpRequestVerb); } else { httpHeaderType = HttpUtility.IsHttpHeader(buffer, bufferSize, out httpRequestVerb); if (httpHeaderType != HttpHeaderType.None) { httpHeader = Encoding.UTF8.GetString(buffer); } } if (httpHeaderType != HttpHeaderType.None) { string lineBreak = ""; int endOfHeaderPos = HttpUtility.GetHttpHeaderEnd(httpHeader, out lineBreak); if (endOfHeaderPos < 0) { throw new NotSupportedException(); //Not sure what to do yet. } if (endOfHeaderPos > bufferSize) { throw new InvalidOperationException(); //Not sure what to do yet. } httpHeader = httpHeader.Substring(0, endOfHeaderPos).Trim(new char[] { '\r', '\n', ' ', '\0' }); httpHeader = ApplyHttpHeaderRules(httpHeader, httpHeaderType, httpRequestVerb, lineBreak); httpHeader += lineBreak + lineBreak; //Terminate the header. int contentLength = bufferSize - (endOfHeaderPos - connection.HttpHeaderBuilder.Length); connection.HttpHeaderBuilder = string.Empty; byte[] fullReponse = new byte[httpHeader.Length + contentLength]; Buffer.BlockCopy(System.Text.Encoding.UTF8.GetBytes(httpHeader), 0, fullReponse, 0, httpHeader.Length); if (contentLength > 0) { Buffer.BlockCopy(buffer, endOfHeaderPos, fullReponse, httpHeader.Length, contentLength); } if (connection.Peer.UsePackets) { //Console.WriteLine("--Send:{0}, Packet: {1}", route.Name, Encoding.UTF8.GetString(fullReponse.Take(fullReponse.Length).ToArray())); byte[] sendBuffer = Packetizer.AssembleMessagePacket(fullReponse, fullReponse.Length, connection.Peer.UseCompression, connection.Peer.UseEncryption, sharedSecretString, commonSalt); Stats.BytesSent += (UInt64)sendBuffer.Length; connection.Peer.Socket.Send(sendBuffer, sendBuffer.Length, SocketFlags.None); WaitForData(connection); } else { //Console.WriteLine("--Send:{0}, Raw: {1}", route.Name, Encoding.UTF8.GetString(fullReponse.Take(fullReponse.Length).ToArray())); Stats.BytesSent += (UInt64)fullReponse.Length; connection.Peer.Socket.Send(fullReponse, fullReponse.Length, SocketFlags.None); } return; } } if (connection.Peer.UsePackets) { //Console.WriteLine("--Send:{0}, Packet: {1}", route.Name, Encoding.UTF8.GetString(buffer.Take(bufferSize).ToArray())); byte[] sendBuffer = Packetizer.AssembleMessagePacket(buffer, bufferSize, connection.Peer.UseCompression, connection.Peer.UseEncryption, sharedSecretString, commonSalt); Stats.BytesSent += (UInt64)sendBuffer.Length; connection.Peer.Socket.Send(sendBuffer, sendBuffer.Length, SocketFlags.None); } else { //Console.WriteLine("--Send:{0}, Raw: {1}", route.Name, Encoding.UTF8.GetString(buffer.Take(bufferSize).ToArray())); Stats.BytesSent += (UInt64)bufferSize; connection.Peer.Socket.Send(buffer, bufferSize, SocketFlags.None); } }
private void SendPacketEnvelope(SocketState connection, PacketEnvelope envelope, string encryptionKey, string salt) { byte[] sendBuffer = Packetizer.AssembleMessagePacket(envelope, connection.UseCompression, true, encryptionKey, salt); Stats.BytesSent += (UInt64)sendBuffer.Length; connection.Socket.Send(sendBuffer, sendBuffer.Length, SocketFlags.None); }
private void OnDataReceived(IAsyncResult asyn) { SocketState connection = null; try { connection = (SocketState)asyn.AsyncState; connection.BytesReceived = connection.Socket.EndReceive(asyn); if (connection.BytesReceived == 0) { CleanupConnection(connection); return; } string sharedSecretString = connection.IsEncryptionNegotationComplete ? connection.KeyNegotiator.SharedSecretString : null; string commonSalt = null; if (connection.IsIncomming && connection.IsEncryptionNegotationComplete) { commonSalt = _route.BindingPreSharedKey; } else if (connection.IsOutgoing && connection.IsEncryptionNegotationComplete) { commonSalt = _route.EndpointPreSharedKey; } if (connection.UsePackets) { //Console.WriteLine("--Recv:{0}, Packet: {1}", route.Name, Encoding.UTF8.GetString(connection.Buffer.Take(connection.BytesReceived).ToArray())); List <PacketEnvelope> envelopes = Packetizer.DissasemblePacketData(this, connection, connection.UseCompression, connection.IsEncryptionNegotationComplete, sharedSecretString, commonSalt); foreach (var envelope in envelopes) { if (envelope.Label == null) { if (connection.IsTunnelNegotationComplete) { //Console.WriteLine("--Recv: {0} {1}", envelope.Payload.Length, Encoding.UTF8.GetString(envelope.Payload.Take(envelope.Payload.Length).ToArray())); ProcessReceivedData(connection, envelope.Payload, envelope.Payload.Length); } else { Stats.DroppedPreNegotiatePacket++; //Console.WriteLine("--Dropped packet, tunnel negotation is not yet complete", route.Name); } } else { ProcessPeerCommand(connection, envelope); } } } else { //Console.WriteLine("--Recv:{0}, Raw: {1}", route.Name, Encoding.UTF8.GetString(connection.Buffer.Take(connection.BytesReceived).ToArray())); //If we are supposed to use encryption, nut its not been initialized then we need to wait before processing the received data. //This is because we do not yet have the information required to decrypt it. //Try a spin lock first, then start sleeping. if (connection.IsTunnelNegotationComplete == false) { WaitForData(connection); int spinCount = _route.SpinLockCount; DateTime?startTime = null; while (connection.IsTunnelNegotationComplete == false) { //TODO: This needs to timeout. if (spinCount == 0) { startTime = DateTime.Now; } else if (startTime != null) { if ((DateTime.Now - ((DateTime)startTime)).TotalMilliseconds > _route.EncryptionInitilizationTimeoutMs) { break; } Thread.Sleep(1); } spinCount--; } } if (connection.IsTunnelNegotationComplete) { ProcessReceivedData(connection, connection.Buffer, connection.BytesReceived); } else { Stats.DroppedPreNegotiateRawData++; Console.WriteLine("--Dropped Raw Data Segment", _route.Name); } } WaitForData(connection); } catch (ObjectDisposedException) { if (connection != null) { CleanupConnection(connection); } return; } catch (SocketException) { if (connection != null) { CleanupConnection(connection); } return; } catch (Exception ex) { Singletons.EventLog.WriteEvent(new EventLogging.EventPayload { Severity = EventLogging.Severity.Error, CustomText = "Failed to process received data.", Exception = ex }); } }