internal HttpState(WebRequest request, byte[] outgoingData, object userState, HttpPollAction pollAction)
 {
     this.Request      = request;
     this.OutgoingData = outgoingData;
     this.UserState    = userState;
     this.PollAction   = pollAction;
 }
        private string GenerateURI(HttpPollAction pollAction)
        {
            StringBuilder stringBuilder = new StringBuilder();

            stringBuilder.Append("http://");
            stringBuilder.Append(gatewayIP);
            stringBuilder.Append("/gateway/gateway.dll?");

            switch (pollAction)
            {
            case HttpPollAction.Open:
                stringBuilder.Append("Action=open&");
                stringBuilder.Append("Server=NS&");
                stringBuilder.Append("IP=" + ConnectivitySettings.Host);
                break;

            case HttpPollAction.Poll:
                stringBuilder.Append("Action=poll&");
                if (useLifespan)
                {
                    stringBuilder.Append("Lifespan=3&");
                }
                stringBuilder.Append("SessionID=" + SessionID);
                break;

            case HttpPollAction.None:
                stringBuilder.Append("SessionID=" + SessionID);
                break;
            }

            return(stringBuilder.ToString());
        }
        public override void Send(byte[] outgoingData, object userState)
        {
            if (opened || (null != (outgoingData = GetOpenOrClosePacket(outgoingData))))
            {
                if (isWebRequestInProcess)
                {
                    lock (SyncObject)
                    {
                        sendingQueue.Enqueue(new QueueState(outgoingData, userState));
                        action = HttpPollAction.None;
                    }
                }
                else
                {
                    isWebRequestInProcess = true;
                    HttpPollAction oldAction = action;

                    lock (SyncObject)
                    {
                        action = HttpPollAction.None;

                        if (pollTimer.Enabled)
                        {
                            pollTimer.Stop();
                        }
                    }

                    HttpWebRequest request = (HttpWebRequest)WebRequest.Create(GenerateURI(oldAction));
                    ConnectivitySettings.SetupWebRequest(request);
                    request.Accept                    = "*/*";
                    request.Method                    = "POST";
                    request.KeepAlive                 = true;
                    request.AllowAutoRedirect         = false;
                    request.AllowWriteStreamBuffering = false;
                    request.ContentLength             = outgoingData.Length;
                    request.Headers.Add("Pragma", "no-cache");

                    // Set timeouts (10+40=50) = PNG average interval
                    request.Timeout          = 10000; // 10 seconds for GetRequestStream(). Timeout error occurs when the server is busy.
                    request.ReadWriteTimeout = 40000; // 40 seconds for Read()/Write(). PNG interval is 45-60, so timeout must be <= 40.

                    // Bypass msnp blockers
                    request.ContentType = "text/html; charset=UTF-8";
                    request.UserAgent   = @"Mozilla/5.0 (Windows NT 6.1) AppleWebKit/535.11 (KHTML, like Gecko) Chrome/17.0.963.65 Safari/535.11";
                    request.Headers.Add("X-Requested-Session-Content-Type", "text/html");

                    // Enable GZIP
                    request.AutomaticDecompression = Settings.EnableGzipCompressionForWebServices ? DecompressionMethods.GZip : DecompressionMethods.None;

                    // Don't block current thread.
                    HttpState httpState = new HttpState(request, outgoingData, userState, oldAction);
                    request.BeginGetRequestStream(EndGetRequestStreamCallback, httpState);
                }
            }
        }
        private byte[] GetOpenOrClosePacket(byte[] outgoingData)
        {
            if (outgoingData.Length > 4 && outgoingData[3] == ' ')
            {
                // Be fast...
                switch ((char)outgoingData[0])
                {
                case 'V':     // VER
                    openState[0] = (outgoingData[1] == 'E' && outgoingData[2] == 'R');
                    openCommand  = NetworkMessage.AppendArray(openCommand, outgoingData);
                    break;

                case 'C':     // CVR
                    openState[1] = (outgoingData[1] == 'V' && outgoingData[2] == 'R');
                    openCommand  = NetworkMessage.AppendArray(openCommand, outgoingData);
                    break;

                case 'U':     // USR
                    openState[2] = (outgoingData[1] == 'S' && outgoingData[2] == 'R');
                    openCommand  = NetworkMessage.AppendArray(openCommand, outgoingData);
                    break;

                case 'O':     // OUT
                    openState[3] = (outgoingData[1] == 'U' && outgoingData[2] == 'T');
                    // Don't buffer OUT packet
                    break;
                }
            }

            if (openState.Get(0) && openState.Get(1) && openState.Get(2))
            {
                opened = true;
                action = HttpPollAction.Open;
                return(openCommand);
            }
            else if (openState.Get(3))
            {
                // Special case, not connected, but the packet is OUT
                isWebRequestInProcess = false;
                // This fires Disconnected event (send only 1 OUT packet)
                if (isWebResponseHeadersProcessed)
                {
                    return(outgoingData);
                }
                else
                {
                    isWebResponseHeadersProcessed = false;
                    OnDisconnected();
                    return(null);
                }
            }

            return(null); // Connection has not been established yet
        }
        private void pollTimer_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
        {
            byte[]        buffer     = new byte[0];
            List <object> userStates = new List <object>();

            lock (SyncObject)
            {
                while (sendingQueue.Count > 0)
                {
                    QueueState queueState = sendingQueue.Dequeue();

                    if (queueState.UserState is Array)
                    {
                        foreach (object us in queueState.UserState as object[])
                        {
                            if (!userStates.Contains(us))
                            {
                                userStates.Add(us);
                            }
                        }
                    }
                    else
                    {
                        if (!userStates.Contains(queueState.UserState))
                        {
                            userStates.Add(queueState.UserState);
                        }
                    }

                    buffer = NetworkMessage.AppendArray(buffer, queueState.Data);

                    if (buffer.Length > MaxAllowedPacket)
                    {
                        break;
                    }
                }

                action = (buffer.Length > 0) ? HttpPollAction.None : HttpPollAction.Poll;
            }

            Send(buffer, userStates.ToArray());
        }
 internal HttpState(WebRequest request, byte[] outgoingData, object userState, HttpPollAction pollAction)
 {
     this.Request = request;
     this.OutgoingData = outgoingData;
     this.UserState = userState;
     this.PollAction = pollAction;
 }
        private void pollTimer_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
        {
            byte[] buffer = new byte[0];
            List<object> userStates = new List<object>();

            lock (SyncObject)
            {
                while (sendingQueue.Count > 0)
                {
                    QueueState queueState = sendingQueue.Dequeue();

                    if (queueState.UserState is Array)
                    {
                        foreach (object us in queueState.UserState as object[])
                        {
                            if (!userStates.Contains(us))
                                userStates.Add(us);
                        }
                    }
                    else
                    {
                        if (!userStates.Contains(queueState.UserState))
                            userStates.Add(queueState.UserState);
                    }

                    buffer = NetworkMessage.AppendArray(buffer, queueState.Data);

                    if (buffer.Length > MaxAllowedPacket)
                        break;
                }

                action = (buffer.Length > 0) ? HttpPollAction.None : HttpPollAction.Poll;
            }

            Send(buffer, userStates.ToArray());
        }
        private byte[] GetOpenOrClosePacket(byte[] outgoingData)
        {
            if (outgoingData.Length > 4 && outgoingData[3] == ' ')
            {
                // Be fast...
                switch ((char)outgoingData[0])
                {
                    case 'V': // VER
                        openState[0] = (outgoingData[1] == 'E' && outgoingData[2] == 'R');
                        openCommand = NetworkMessage.AppendArray(openCommand, outgoingData);
                        break;

                    case 'C': // CVR
                        openState[1] = (outgoingData[1] == 'V' && outgoingData[2] == 'R');
                        openCommand = NetworkMessage.AppendArray(openCommand, outgoingData);
                        break;

                    case 'U': // USR
                        openState[2] = (outgoingData[1] == 'S' && outgoingData[2] == 'R');
                        openCommand = NetworkMessage.AppendArray(openCommand, outgoingData);
                        break;

                    case 'O': // OUT
                        openState[3] = (outgoingData[1] == 'U' && outgoingData[2] == 'T');
                        // Don't buffer OUT packet
                        break;
                }
            }

            if (openState.Get(0) && openState.Get(1) && openState.Get(2))
            {
                opened = true;
                action = HttpPollAction.Open;
                return openCommand;
            }
            else if (openState.Get(3))
            {
                // Special case, not connected, but the packet is OUT
                isWebRequestInProcess = false;
                // This fires Disconnected event (send only 1 OUT packet)
                if (isWebResponseHeadersProcessed)
                {
                    return outgoingData;
                }
                else
                {
                    isWebResponseHeadersProcessed = false;
                    OnDisconnected();
                    return null;
                }
            }

            return null; // Connection has not been established yet
        }
        private string GenerateURI(HttpPollAction pollAction)
        {
            StringBuilder stringBuilder = new StringBuilder();

            stringBuilder.Append("http://");
            stringBuilder.Append(gatewayIP);
            stringBuilder.Append("/gateway/gateway.dll?");

            switch (pollAction)
            {
                case HttpPollAction.Open:
                    stringBuilder.Append("Action=open&");
                    stringBuilder.Append("Server=NS&");
                    stringBuilder.Append("IP=" + ConnectivitySettings.Host);
                    break;

                case HttpPollAction.Poll:
                    stringBuilder.Append("Action=poll&");
                    if (useLifespan)
                    {
                        stringBuilder.Append("Lifespan=3&");
                    }
                    stringBuilder.Append("SessionID=" + SessionID);
                    break;

                case HttpPollAction.None:
                    stringBuilder.Append("SessionID=" + SessionID);
                    break;
            }

            return stringBuilder.ToString();
        }
        public override void Send(byte[] outgoingData, object userState)
        {
            if (opened || (null != (outgoingData = GetOpenOrClosePacket(outgoingData))))
            {
                if (isWebRequestInProcess)
                {
                    lock (SyncObject)
                    {
                        sendingQueue.Enqueue(new QueueState(outgoingData, userState));
                        action = HttpPollAction.None;
                    }
                }
                else
                {
                    isWebRequestInProcess = true;
                    HttpPollAction oldAction = action;

                    lock (SyncObject)
                    {
                        action = HttpPollAction.None;

                        if (pollTimer.Enabled)
                        {
                            pollTimer.Stop();
                        }
                    }

                    HttpWebRequest request = (HttpWebRequest)WebRequest.Create(GenerateURI(oldAction));
                    ConnectivitySettings.SetupWebRequest(request);
                    request.Accept = "*/*";
                    request.Method = "POST";
                    request.KeepAlive = true;
                    request.AllowAutoRedirect = false;
                    request.AllowWriteStreamBuffering = false;
                    request.ContentLength = outgoingData.Length;
                    request.Headers.Add("Pragma", "no-cache");

                    // Set timeouts (10+40=50) = PNG average interval
                    request.Timeout = 10000; // 10 seconds for GetRequestStream(). Timeout error occurs when the server is busy.
                    request.ReadWriteTimeout = 40000; // 40 seconds for Read()/Write(). PNG interval is 45-60, so timeout must be <= 40.

                    // Bypass msnp blockers
                    request.ContentType = "text/html; charset=UTF-8";
                    request.UserAgent = @"Mozilla/5.0 (Windows NT 6.1) AppleWebKit/535.11 (KHTML, like Gecko) Chrome/17.0.963.65 Safari/535.11";
                    request.Headers.Add("X-Requested-Session-Content-Type", "text/html");

                    // Enable GZIP
                    request.AutomaticDecompression = Settings.EnableGzipCompressionForWebServices ? DecompressionMethods.GZip : DecompressionMethods.None;

                    // Don't block current thread.
                    HttpState httpState = new HttpState(request, outgoingData, userState, oldAction);
                    request.BeginGetRequestStream(EndGetRequestStreamCallback, httpState);
                }
            }
        }