Esempio n. 1
0
        // This method is called by I/O Completed() when an asynchronous send completes.
        // If all of the data has been sent, then this method calls StartReceive
        //to start another receive op on the socket to read any additional
        // data sent from the client. If all of the data has NOT been sent, then it
        //calls StartSend to send more data.
        private void ProcessSend(SocketAsyncEventArgs receiveSendEventArgs)
        {
            DataHolderToken token = (DataHolderToken)receiveSendEventArgs.UserToken;

            if (receiveSendEventArgs.SocketError == SocketError.Success)
            {
                token.sendBytesRemainingCount = token.sendBytesRemainingCount - receiveSendEventArgs.BytesTransferred;

                if (token.sendBytesRemainingCount == 0)
                {
                    // If we are within this if-statement, then all the bytes in
                    // the message have been sent.
                    token.Reset();
                    CloseClientSocket(receiveSendEventArgs);
                }
                else
                {
                    // If some of the bytes in the message have NOT been sent,
                    // then we will need to post another send operation, after we store
                    // a count of how many bytes that we sent in this send op.
                    token.bytesSentAlreadyCount += receiveSendEventArgs.BytesTransferred;
                    // So let's loop back to StartSend().
                    StartSend(receiveSendEventArgs);
                }
            }
            else
            {
                // We'll just close the socket if there was a
                // socket error when receiving data from the client.
                token.Reset();
                CloseClientSocket(receiveSendEventArgs);
            }
        }
Esempio n. 2
0
        /// <summary>
        /// Initializes the server by preallocating reusable buffers and context objects.  These objects do not
        /// need to be preallocated or reused, by is done this way to illustrate how the API can easily be used
        /// to create reusable objects to increase server performance.
        /// </summary>
        public void InitServer()
        {
            // Allocates one large byte buffer which all I/O operations use a piece of.  This gaurds
            // against memory fragmentation
            bufferManager.InitBuffer();

            //Allocate the pool of accept operation EventArgs objects
            //which do not need a buffer
            for (int i = 0; i < maxSimultaneousAcceptOps; i++)
            {
                SocketAsyncEventArgs acceptEventArgs = new SocketAsyncEventArgs();
                acceptEventArgs.Completed += new EventHandler <SocketAsyncEventArgs>(AcceptEventArg_Completed);

                poolOfAcceptEventArgs.Push(acceptEventArgs);
            }

            //Allocate the pool of receive/send operation EventArgs objects
            //which DO need a buffer
            for (int i = 0; i < numberOfEventArgsForRecSend; i++)
            {
                SocketAsyncEventArgs sendReceiveEventArgs = new SocketAsyncEventArgs();
                bufferManager.SetBuffer(sendReceiveEventArgs);

                sendReceiveEventArgs.Completed += new EventHandler <SocketAsyncEventArgs>(IO_Completed);

                DataHolderToken token = new DataHolderToken(sendReceiveEventArgs.Offset, receiveBufferSize);
                sendReceiveEventArgs.UserToken = token;

                poolOfRecSendEventArgs.Push(sendReceiveEventArgs);
            }
        }
Esempio n. 3
0
        string[] getCommandsFromArgs(SocketAsyncEventArgs e)
        {
            DataHolderToken token = (DataHolderToken)e.UserToken;

            string[] req       = token.httpRequest.Split(new char[] { '?' }, 2); //Strip off "?"
            string[] cmd_stack = req[0].Split(new char[] { '/' });
            string[] command   = cmd_stack[0].Split(new char[] { ' ' }, 2);
            return(command);
        }
Esempio n. 4
0
        /// <summary>
        /// This method is invoked when an asynchronous receive operation completes. If the
        /// remote host closed the connection, then the socket is closed.  If data was received then
        /// the data is echoed back to the client.
        /// </summary>
        private void ProcessReceive(SocketAsyncEventArgs receiveSendEventArgs)
        {
            DataHolderToken token = (DataHolderToken)receiveSendEventArgs.UserToken;

            //If there was a socket error, close the connection
            if (receiveSendEventArgs.SocketError != SocketError.Success)
            {
                token.Reset();
                CloseClientSocket(receiveSendEventArgs);

                //Jump out of the ProcessReceive method.
                return;
            }

            // If no data was received, close the connection. This is a NORMAL
            // situation that shows when the client has finished sending data.
            if (receiveSendEventArgs.BytesTransferred == 0)
            {
                token.Reset();
                CloseClientSocket(receiveSendEventArgs);
                return;
            }

            //Assume that all of the bytes transfered is the received message
            token.dataMessageReceived = new Byte[receiveSendEventArgs.BytesTransferred];
            Buffer.BlockCopy(receiveSendEventArgs.Buffer, token.receiveBufferOffset, token.dataMessageReceived, 0, receiveSendEventArgs.BytesTransferred);

            // Decode the byte array received in the token
            //string sBuffer = Encoding.ASCII.GetString(bReceive);
            string sBuffer = Encoding.UTF8.GetString(token.dataMessageReceived);

            //At present we will only deal with GET type
            if (sBuffer.Substring(0, 3) != "GET")
            {
                token.Reset();
                CloseClientSocket(receiveSendEventArgs);
            }
            else
            {
                // Look for HTTP request
                int iStartPos = sBuffer.IndexOf("HTTP", 1);

                // Get the HTTP text and version e.g. it will return "HTTP/1.1"
                sHttpVersion = sBuffer.Substring(iStartPos, 8);

                // Extract the Requested Type and Requested file/directory
                String sRequest = sBuffer.Substring(5, iStartPos - 1 - 5);

                sRequest = HttpUtility.UrlDecode(sRequest);

                token.httpRequest = sRequest.TrimEnd();

                StartSendRequest(receiveSendEventArgs);
            }
        }
Esempio n. 5
0
        //Post a send.
        private void StartSend(SocketAsyncEventArgs receiveSendEventArgs)
        {
            DataHolderToken token = (DataHolderToken)receiveSendEventArgs.UserToken;
            int             count = 0;

            try
            {
                //The number of bytes to send depends on whether the message is larger than
                //the buffer or not. If it is larger than the buffer, then we will have
                //to post more than one send operation. If it is less than or equal to the
                //size of the send buffer, then we can accomplish it in one send op.
                if (token.sendBytesRemainingCount <= (receiveBufferSize + settings.send_buffer_size))
                {
                    count = token.sendBytesRemainingCount;
                    receiveSendEventArgs.SetBuffer(token.sendBufferOffset, count);
                    //Copy the bytes to the buffer associated with this SAEA object.
                    Buffer.BlockCopy(token.dataToSend, token.bytesSentAlreadyCount, receiveSendEventArgs.Buffer, token.sendBufferOffset, token.sendBytesRemainingCount);
                }
                else
                {
                    logger.Write("Exceeded buffer size in StartSend method, total size = " + token.sendBytesRemainingCount);
                    //We cannot try to set the buffer any larger than its size.
                    //So since receiveSendToken.sendBytesRemainingCount > BufferSize, we just
                    //set it to the maximum size, to send the most data possible.
                    count = receiveBufferSize + settings.send_buffer_size;
                    receiveSendEventArgs.SetBuffer(token.sendBufferOffset, count);
                    //Copy the bytes to the buffer associated with this SAEA object.
                    Buffer.BlockCopy(token.dataToSend, token.bytesSentAlreadyCount, receiveSendEventArgs.Buffer, token.sendBufferOffset, receiveBufferSize);
                }

                //post asynchronous send operation
                bool willRaiseEvent = receiveSendEventArgs.AcceptSocket.SendAsync(receiveSendEventArgs);

                if (!willRaiseEvent)
                {
                    ProcessSend(receiveSendEventArgs);
                }
            }
            catch (Exception e)
            {
                logger.Write("Exception in SetBuffer in StartSend method of HttpServer.cs, offset=" + token.sendBufferOffset +
                             ", count=" + count + ", Buffer=" + receiveSendEventArgs.Buffer + ": " + e.Message);
                token.Reset();
                CloseClientSocket(receiveSendEventArgs);
            }
        }
Esempio n. 6
0
        // Does the normal destroying of sockets after
        // we finish receiving and sending on a connection.
        private void CloseClientSocket(SocketAsyncEventArgs e)
        {
            DataHolderToken token = (DataHolderToken)e.UserToken;

            // do a shutdown before you close the socket
            try
            {
                e.AcceptSocket.Shutdown(SocketShutdown.Both);
            }
            // throws if socket was already closed
            catch (Exception)
            {
            }

            //This method closes the socket and releases all resources, both
            //managed and unmanaged. It internally calls Dispose.
            e.AcceptSocket.Close();

            //Make sure the new DataHolder has been created for the next connection.
            //If it has, then dataMessageReceived should be null.
            if (token.dataMessageReceived != null)
            {
                token.Reset();
            }

            // Put the SocketAsyncEventArg back into the pool,
            // to be used by another client. This
            poolOfRecSendEventArgs.Push(e);

            // decrement the counter keeping track of the total number of clients
            //connected to the server, for testing
            Interlocked.Decrement(ref numConnectedSockets);

            if (numConnectedSockets + 1 == maxConnections)
            {
                logger.Write("Number of connected sockets: " + numConnectedSockets + " / " + maxConnections);
            }

            //Release Semaphore so that its connection counter will be decremented.
            //This must be done AFTER putting the SocketAsyncEventArg back into the pool,
            //or you can run into problems.
            maxNumberAcceptedClients.Release();
        }
Esempio n. 7
0
        private void StartReceive(SocketAsyncEventArgs receiveSendEventArgs)
        {
            DataHolderToken token = (DataHolderToken)receiveSendEventArgs.UserToken;

            try
            {
                //Set the buffer for the receive operation.
                receiveSendEventArgs.SetBuffer(token.receiveBufferOffset, receiveBufferSize);

                // Post async receive operation on the socket.
                bool willRaiseEvent = receiveSendEventArgs.AcceptSocket.ReceiveAsync(receiveSendEventArgs);
                if (!willRaiseEvent)
                {
                    ProcessReceive(receiveSendEventArgs);
                }
            }
            catch (Exception e)
            {
                logger.Write("Exception in SetBuffer in StartReceive method of HttpServer.cs, offset=" + token.receiveBufferOffset +
                             ", count=" + receiveBufferSize + ", Buffer=" + receiveSendEventArgs.Buffer + ": " + e.Message);
                token.Reset();
                CloseClientSocket(receiveSendEventArgs);
            }
        }
Esempio n. 8
0
        /// <summary>
        /// Initializes the server by preallocating reusable buffers and context objects.  These objects do not 
        /// need to be preallocated or reused, by is done this way to illustrate how the API can easily be used
        /// to create reusable objects to increase server performance.
        /// </summary>
        public void InitServer()
        {
            // Allocates one large byte buffer which all I/O operations use a piece of.  This gaurds
            // against memory fragmentation
            bufferManager.InitBuffer();

            //Allocate the pool of accept operation EventArgs objects
            //which do not need a buffer
            for (int i = 0; i < maxSimultaneousAcceptOps; i++)
            {
                SocketAsyncEventArgs acceptEventArgs = new SocketAsyncEventArgs();
                acceptEventArgs.Completed += new EventHandler<SocketAsyncEventArgs>(AcceptEventArg_Completed);

                poolOfAcceptEventArgs.Push(acceptEventArgs);
            }

            //Allocate the pool of receive/send operation EventArgs objects
            //which DO need a buffer
            for (int i = 0; i < numberOfEventArgsForRecSend; i++)
            {
                SocketAsyncEventArgs sendReceiveEventArgs = new SocketAsyncEventArgs();
                bufferManager.SetBuffer(sendReceiveEventArgs);

                sendReceiveEventArgs.Completed += new EventHandler<SocketAsyncEventArgs>(IO_Completed);

                DataHolderToken token = new DataHolderToken(sendReceiveEventArgs.Offset, receiveBufferSize);
                sendReceiveEventArgs.UserToken = token;

                poolOfRecSendEventArgs.Push(sendReceiveEventArgs);
            }
        }
Esempio n. 9
0
        void NewRequestThread(Object o)
        {
            SocketAsyncEventArgs e     = (SocketAsyncEventArgs)o;
            DataHolderToken      token = (DataHolderToken)e.UserToken;

            OpResult opResult = new OpResult(OpStatusCode.BadRequest);
            string   sCommand = "";
            string   sParam   = "";
            string   sBody    = "";

            try
            {
                // Show error for index
                if (token.httpRequest.Length == 0)
                {
                    sCommand = "<i>No command specified.</i>";
                    sParam   = "<i>No parameters specified.</i>";
                }
                else
                {
                    string[] req       = token.httpRequest.Split(new char[] { '?' }, 2); //Strip off "?"
                    string[] cmd_stack = req[0].Split(new char[] { '/' });
                    for (int idx = 0; idx < cmd_stack.Length; idx++)
                    {
                        string[] command = cmd_stack[idx].Split(new char[] { ' ' }, 2);
                        if (command.Length == 0)
                        {
                            return;
                        }
                        sCommand = command[0];
                        sParam   = (command.Length == 2 ? command[1] : string.Empty);

                        if (sCommand.Equals("help", StringComparison.InvariantCultureIgnoreCase))
                        {
                            opResult = remoteCommands.CommandListHTML(AddInModule.GetPortNumber(AddInModule.m_basePortNumber));
                        }
                        else if (sCommand.Equals("format", StringComparison.InvariantCultureIgnoreCase))
                        {
                            ICommand formatter = new customCmd(sBody);
                            opResult = formatter.Execute(sParam);
                            sBody    = "";
                        }
                        else if (token.opResult != null)
                        {
                            opResult = token.opResult;
                        }
                        else if (sCommand.Equals("server-settings"))
                        {
                            opResult = ExecuteSettingsCommand(sCommand, sParam);
                        }
                        else if (sCommand.Equals("music-clear-cache"))
                        {
                            startCacheBuildNow();
                            opResult            = new OpResult();
                            opResult.StatusCode = OpStatusCode.Success;
                            opResult.StatusText = "Cache cleared";
                        }
                        else
                        {
                            opResult = remoteCommands.Execute(sCommand, sParam, settings);
                        }
                    }
                }

                //Get bytes to send to browser
                if (opResult.isHelpFormat())
                {
                    string sTempBody = opResult.ToString();
                    if (sParam.Length == 0)
                    {
                        sParam = "<i>No parameters specified.</i>";
                    }
                    if (opResult.StatusCode != OpStatusCode.Ok && opResult.StatusCode != OpStatusCode.Success)
                    {
                        sTempBody = string.Format("<h1>ERROR<hr>Command: {0}<br>Params: {1}<br>Returned: {2} - {3}<hr>See <a href='help'>Help</a></h1>", sCommand, sParam, opResult.StatusCode, opResult.ToString());
                    }
                    else if (opResult.StatusCode != OpStatusCode.OkImage)
                    {
                        if (sTempBody.Length > 0)
                        {
                            if (sTempBody.TrimStart()[0] != '<')
                            {
                                sTempBody = "<pre>" + sTempBody + "</pre>";
                            }
                        }
                        else
                        {
                            sTempBody = string.Format("<h1>Ok<hr>Last Command: '{0}'<br>Params: {1}<br>Returned: {2}<hr>See <a href='help'>Help</a></h1>", sCommand, sParam, opResult.StatusCode);
                        }
                    }
                    if (sBody.Length > 0)
                    {
                        sBody += "<HR>";
                    }
                    sBody           += sTempBody;
                    token.dataToSend = GetPageDataToSend(string.Format("{0}\r\n", sBody));
                }
                else if (opResult.StatusCode != OpStatusCode.OkImage)
                {
                    token.dataToSend = GetPageJsonDataToSend(opResult.ToString());
                }
                else
                {
                    token.dataToSend = GetImageDataToSend(opResult);
                }
            }
            catch (Exception ex)
            {
                logger.Write("Exception in NewRequestThread: " + ex.Message);
                token.dataToSend = GetPageDataToSend(string.Format("<html><body>EXCEPTION: {0}<hr></body></html>", ex.Message));
                Trace.TraceError(ex.ToString());
            }

            //Set send operation variables
            token.sendBytesRemainingCount = token.dataToSend.Length;
            token.bytesSentAlreadyCount   = 0;

            StartSend(e);
        }
Esempio n. 10
0
        void StartSendRequestThread(Object o)
        {
            System.Threading.Thread.CurrentThread.CurrentUICulture = System.Threading.Thread.CurrentThread.CurrentCulture;

            SocketAsyncEventArgs e     = (SocketAsyncEventArgs)o;
            DataHolderToken      token = (DataHolderToken)e.UserToken;

            string[] command  = getCommandsFromArgs(e);
            string   sCommand = command[0];
            string   sParam   = (command.Length == 2 ? command[1] : string.Empty);

            Thread http_thread = new Thread(new ParameterizedThreadStart(NewRequestThread));

            http_thread.IsBackground = true;
            http_thread.SetApartmentState(ApartmentState.MTA);

            if (sCommand.Equals("music-list-playing") || sCommand.Equals("music-list-current") || sCommand.StartsWith("play") || sCommand.Equals("music-shuffle"))
            {
                RemotedWindowsMediaPlayer remotedPlayer = null;
                try
                {
                    //Only allow one thread at a time to access remoted player
                    waitHandle.WaitOne();

                    remotedPlayer = new RemotedWindowsMediaPlayer();
                    remotedPlayer.CreateControl();

                    token.opResult = new OpResult();
                    if (sCommand.Equals("music-list-playing"))
                    {
                        if (sParam != null && sParam.Length != 0)
                        {
                            string sIndex = sParam.Substring(sParam.IndexOf("index:") + "index:".Length);
                            if (remotedPlayer.setNowPlaying(Int16.Parse(sIndex)))
                            {
                                token.opResult.StatusCode = OpStatusCode.Success;
                                token.opResult.StatusText = "Current media set to index " + sIndex;
                            }
                            else
                            {
                                token.opResult.StatusCode = OpStatusCode.BadRequest;
                                token.opResult.StatusText = "Current playback item not set";
                            }
                        }
                        else
                        {
                            token.opResult.StatusCode = OpStatusCode.Success;
                            NowPlaying nowPlaying = new NowPlaying(remotedPlayer);
                            token.opResult.ContentObject = nowPlaying;
                        }
                    }
                    else if (sCommand.StartsWith("play"))
                    {
                        //For playrate and playstate-get commands
                        token.opResult = remoteCommands.Execute(remotedPlayer, sCommand, sParam);
                    }
                    else if (sCommand.Equals("music-shuffle"))
                    {
                        remotedPlayer.setShuffleMode();
                        token.opResult.StatusCode = OpStatusCode.Success;
                        token.opResult.StatusText = "Shuffle mode set to true";
                    }
                    else
                    {
                        //"music-list-current" command
                        token.opResult.StatusCode = OpStatusCode.Success;
                        CurrentState state = new CurrentState(remotedPlayer);
                        token.opResult.ContentObject = state;
                    }
                }
                catch (Exception c)
                {
                    logger.Write("Exception in StartSendRequestThread: " + c.Message);
                    token.opResult.StatusCode = OpStatusCode.Exception;
                    token.opResult.StatusText = c.Message;
                }
                finally
                {
                    if (remotedPlayer != null)
                    {
                        remotedPlayer.Dispose();
                    }
                    waitHandle.Set();
                }
            }

            http_thread.Start(e);
        }