Exemplo n.º 1
0
 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);
 }
Exemplo n.º 2
0
 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);
 }
Exemplo n.º 3
0
        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);
            }
        }
Exemplo n.º 4
0
        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
                });
            }
        }
Exemplo n.º 5
0
        void EstablishPeerConnection(object connectionObject)
        {
            SocketState accpetedConnection = (SocketState)connectionObject;

            SocketState foreignConnection = null;

            Endpoint foreignConnectionEndpoint = null;
            string   stickeySessionKey         = _route.Name + ":" + _route.Endpoints.ConnectionPattern + ":" + ((IPEndPoint)accpetedConnection.Socket.RemoteEndPoint).Address.ToString();

            if (_route.UseStickySessions)
            {
                lock (_stickySessionCache)
                {
                    if (_stickySessionCache.Contains(stickeySessionKey))
                    {
                        var cacheItem = (StickySession)_stickySessionCache[stickeySessionKey];

                        foreignConnectionEndpoint = (from o in _route.Endpoints.List
                                                     where o.Address == cacheItem.DestinationAddress && o.Port == cacheItem.DestinationPort
                                                     select o).FirstOrDefault();
                    }
                }
            }

            //Attempt to connect to the same address as we did last time.
            if (foreignConnectionEndpoint != null)
            {
                if ((foreignConnection = Connect(foreignConnectionEndpoint.Address, foreignConnectionEndpoint.Port)) != null)
                {
                    //Success.
                }
            }

            //If not using sticky sessions, of if we failed to connect to the previously successful host - then take the connection pattern into account.
            if (foreignConnection == null)
            {
                if (_route.Endpoints.ConnectionPattern == ConnectionPattern.FailOver)
                {
                    foreach (var remotePeer in _route.Endpoints.List)
                    {
                        if (remotePeer.Enabled)
                        {
                            if ((foreignConnection = Connect(remotePeer.Address, remotePeer.Port)) != null)
                            {
                                foreignConnectionEndpoint = remotePeer;
                                break;
                            }
                        }
                    }
                }
                else if (_route.Endpoints.ConnectionPattern == ConnectionPattern.Balanced)
                {
                    throw new NotImplementedException();
                }
                else if (_route.Endpoints.ConnectionPattern == ConnectionPattern.RoundRobbin)
                {
                    if (_lastRoundRobinIndex >= _route.Endpoints.List.Count)
                    {
                        _lastRoundRobinIndex = 0;
                    }

                    int startIndex = _lastRoundRobinIndex++;

                    if (startIndex >= _route.Endpoints.List.Count)
                    {
                        startIndex = 0;
                    }

                    for (int i = startIndex; i < _route.Endpoints.List.Count; i++)
                    {
                        var remotePeer = _route.Endpoints.List[i];
                        if (remotePeer.Enabled)
                        {
                            if ((foreignConnection = Connect(remotePeer.Address, remotePeer.Port)) != null)
                            {
                                foreignConnectionEndpoint = remotePeer;
                                break;
                            }
                        }
                    }
                }
                else
                {
                    throw new NotImplementedException();
                }
            }

            if (foreignConnection == null)
            {
                CleanupConnection(accpetedConnection);
                return;
            }

            if (_route.UseStickySessions)
            {
                lock (_stickySessionCache)
                {
                    var stickySession = new StickySession()
                    {
                        DestinationAddress = foreignConnectionEndpoint.Address,
                        DestinationPort    = foreignConnectionEndpoint.Port
                    };

                    _stickySessionCache.Add(stickeySessionKey, stickySession, new CacheItemPolicy()
                    {
                        SlidingExpiration = new TimeSpan(0, 0, _route.StickySessionCacheExpiration)
                    });
                }
            }

            accpetedConnection.Peer = foreignConnection;
            foreignConnection.Peer  = accpetedConnection;

            lock (_connections)
            {
                _connections.Add(accpetedConnection);
                _connections.Add(foreignConnection);
            }

            WaitForData(accpetedConnection);
            WaitForData(foreignConnection);
        }
Exemplo n.º 6
0
        public static List <PacketEnvelope> DissasemblePacketData(Router router, SocketState state, bool compress, bool encrypt, string encryptPacketKey, string keySalt)
        {
            List <PacketEnvelope> envelopes = new List <PacketEnvelope>();

            try
            {
                if (state.PayloadBuilderLength + state.BytesReceived >= state.PayloadBuilder.Length)
                {
                    Array.Resize(ref state.PayloadBuilder, state.PayloadBuilderLength + state.BytesReceived);
                }

                Buffer.BlockCopy(state.Buffer, 0, state.PayloadBuilder, state.PayloadBuilderLength, state.BytesReceived);

                state.PayloadBuilderLength = state.PayloadBuilderLength + state.BytesReceived;

                while (state.PayloadBuilderLength > Constants.PayloadHeaderSize) //[PayloadSize] and [CRC16]
                {
                    Byte[] payloadDelimiterBytes = new Byte[4];
                    Byte[] payloadSizeBytes      = new Byte[4];
                    Byte[] expectedCrc16Bytes    = new Byte[2];

                    Buffer.BlockCopy(state.PayloadBuilder, 0, payloadDelimiterBytes, 0, payloadDelimiterBytes.Length);
                    Buffer.BlockCopy(state.PayloadBuilder, 4, payloadSizeBytes, 0, payloadSizeBytes.Length);
                    Buffer.BlockCopy(state.PayloadBuilder, 8, expectedCrc16Bytes, 0, expectedCrc16Bytes.Length);

                    int    payloadDelimiter = BitConverter.ToInt32(payloadDelimiterBytes, 0);
                    int    grossPayloadSize = BitConverter.ToInt32(payloadSizeBytes, 0);
                    UInt16 expectedCrc16    = BitConverter.ToUInt16(expectedCrc16Bytes, 0);

                    if (payloadDelimiter != Constants.PayloadDelimiter)
                    {
                        SkipPacket(ref state);
                        //throw new Exception("Malformed payload packet, invalid delimiter.");
                        router.Stats.PacketMalformedCount++;
                        continue;
                    }

                    if (grossPayloadSize < Constants.DefaultMinMsgSize || grossPayloadSize > Constants.DefaultMaxMsgSize)
                    {
                        SkipPacket(ref state);
                        //throw new Exception("Malformed payload packet, invalid length.");
                        router.Stats.PacketSizeExceededCount++;
                        continue;
                    }

                    if (state.PayloadBuilderLength < grossPayloadSize)
                    {
                        //We have data in the buffer, but it's not enough to make up
                        //  the entire message (fragmented packet) so we will break and wait on more data.
                        router.Stats.PacketFragmentCount++;
                        break;
                    }

                    UInt16 actualCrc16 = Crc16.ComputeChecksum(state.PayloadBuilder, Constants.PayloadHeaderSize, grossPayloadSize - Constants.PayloadHeaderSize);

                    if (actualCrc16 != expectedCrc16)
                    {
                        SkipPacket(ref state);
                        //throw new Exception("Malformed payload packet, invalid CRC.");
                        router.Stats.PacketCrcFailureCount++;
                        continue;
                    }

                    int    netPayloadSize = grossPayloadSize - Constants.PayloadHeaderSize;
                    byte[] payloadBytes   = new byte[netPayloadSize];

                    Buffer.BlockCopy(state.PayloadBuilder, Constants.PayloadHeaderSize, payloadBytes, 0, netPayloadSize);

                    if (encrypt)
                    {
                        payloadBytes = Decrypt(encryptPacketKey, keySalt, payloadBytes);
                    }

                    if (compress)
                    {
                        payloadBytes = Unzip(payloadBytes);
                    }

                    envelopes.Add((PacketEnvelope)Serialization.ByteArrayToObject(payloadBytes));

                    //Zero out the consumed portion of the payload buffer - more for fun than anything else.
                    Array.Clear(state.PayloadBuilder, 0, grossPayloadSize);

                    Buffer.BlockCopy(state.PayloadBuilder, grossPayloadSize, state.PayloadBuilder, 0, state.PayloadBuilderLength - grossPayloadSize);
                    state.PayloadBuilderLength -= grossPayloadSize;
                }
            }
            catch (Exception ex)
            {
                //TODO: allow this to be logged.
            }

            return(envelopes);
        }