Example #1
0
        /// <summary>
        /// Handles completion of the request transmission.
        /// </summary>
        /// <param name="ar">The async result.</param>
        private void OnRequestSent(IAsyncResult ar)
        {
            var httpAR = (HttpAsyncResult)ar.AsyncState;

            using (TimedLock.Lock(this))
            {
                try
                {
                    sock.EndSendAll(ar);

                    // The request was sent successfully so start receiving
                    // the response.

                    httpAR.Response = new HttpResponse(cbContentMax);
                    httpAR.Buffer   = new byte[HttpStack.BlockSize];

                    httpAR.Response.BeginParse();
                    sock.BeginReceive(httpAR.Buffer, 0, HttpStack.BlockSize, SocketFlags.None, onResponseRecv, httpAR);
                }
                catch (Exception e)
                {
                    httpAR.Notify(e);
                }
            }
        }
Example #2
0
        /// <summary>
        /// Called by the socket listener when an inbound socket is accepted.
        /// </summary>
        /// <param name="sock">The accepted socket.</param>
        /// <param name="endPoint">The endpoint the socket was accepted from.</param>
        private void OnAccept(EnhancedSocket sock, IPEndPoint endPoint)
        {
            var httpState = new HttpAsyncState();
            var recvBuf   = new byte[RecvBlockSize];

            using (TimedLock.Lock(syncLock))
            {
                if (connections.Count >= maxConnections)
                {
                    sock.AsyncSendClose(new HttpResponse(HttpStatus.ServiceUnavailable, "Server is too busy").Serialize(SendBlockSize));
                    return;
                }

                connections.Add(sock, sock);
            }

            httpState.FirstRequest = true;
            httpState.Request      = new HttpRequest();
            httpState.Socket       = sock;
            httpState.Buffer       = recvBuf;
            httpState.RecvSize     = 0;

            httpState.Request.BeginParse(((IPEndPoint)sock.LocalEndPoint).Port);
            sock.BeginReceive(recvBuf, 0, recvBuf.Length, SocketFlags.None, onRecv, httpState);
        }
Example #3
0
            public int Receive(byte[] buf)
            {
                Reset();
                sock.BeginReceive(buf, 0, buf.Length, SocketFlags.None, onRecvBuf, null);
                asyncEvent.WaitOne(MaxWaitTime, false);
                Verify();

                return(cbTransfer);
            }
Example #4
0
        /// <summary>
        /// Initiates the reception of a message.
        /// </summary>
        private void BeginReceive()
        {
            try
            {
                using (TimedLock.Lock(router.SyncRoot))
                {
                    SetLastAccess();

                    recvHeader = true;
                    recvBuf    = new byte[MsgRouter.FrameHeaderSize];
                    recvPos    = 0;
                    cbRecv     = MsgRouter.FrameHeaderSize;

                    sock.BeginReceive(recvBuf, recvPos, cbRecv, SocketFlags.None, onReceive, null);
                }
            }
            catch (Exception e)
            {
                TraceException(e);
                router.OnTcpClose(this);
                Close();
                throw;
            }
        }
Example #5
0
            private SipMessage message;                         // The message we're receiving contents for

            public Connection(SipTcpTransport transport, EnhancedSocket sock, IPEndPoint remoteEP)
            {
                this.transport   = transport;
                this.sock        = sock;
                this.remoteEP    = remoteEP;
                this.sendQueue   = new Queue <SipMessage>();
                this.onSend      = new AsyncCallback(OnSend);
                this.onRecv      = new AsyncCallback(OnReceive);
                this.sendPending = false;

                this.headerBuf  = new byte[MaxHeaderSize];
                this.contentBuf = null;
                this.cbRecv     = 0;

                sock.BeginReceive(headerBuf, 0, headerBuf.Length, SocketFlags.None, onRecv, null);
            }
Example #6
0
        /// <summary>
        /// Initiates reception the next chunk of received data up to a specified maxinum number of bytes.
        /// </summary>
        /// <param name="buffer">The destination buffer.</param>
        /// <param name="offset">Index where the first received byte is to be written.</param>
        /// <param name="count">Number of bytes to be received.</param>
        /// <param name="callback">The delegate to be called when the operation completes (or <c>null</c>).</param>
        /// <param name="state">Application specific state.</param>
        /// <returns>
        /// An <see cref="IAsyncResult" /> instance to be used to track the progress of the
        /// operation and to eventually be passed to the <see cref="EndReceive" /> method.
        /// </returns>
        /// <exception cref="InvalidOperationException">Thrown if the socket is not connected or if another receive operation is already pending.</exception>
        /// <exception cref="ArgumentNullException">Thrown if <paramref name="buffer" /> is <c>null</c>.</exception>
        /// <exception cref="IndexOutOfRangeException">Thrown if <paramref name="offset" /> and <paramref name="count" /> specify bytes outside of the <paramref name="buffer" />.</exception>
        /// <remarks>
        /// <note>
        /// Only one receive operation may be pending per socket for both TCP and UDP connections.
        /// </note>
        /// <note>
        /// All successful calls to <see cref="BeginReceive" /> must eventually be followed by a call to <see cref="EndReceive" />.
        /// </note>
        /// <note>
        /// For TCP connections, the operation will be considered to have completed when some number of bytes
        /// between one and the specified <paramref name="count" /> have been received from the remote endpoint
        /// or the remote endpoint has gracefully closed the connection.  For UDP connections, the operation will
        /// be considered to be complete when the next packet is received, regardless of size.  Note that the
        /// buffer size specified by <paramref name="count" /> must be large enough to hold the next received
        /// UDP packet.
        /// </note>
        /// </remarks>
        public IAsyncResult BeginReceive(byte[] buffer, int offset, int count, AsyncCallback callback, object state)
        {
            if (buffer == null)
            {
                throw new ArgumentNullException("buffer");
            }

            if (offset < 0 || count < 0 || offset + count > buffer.Length + 1)
            {
                throw new IndexOutOfRangeException(string.Format("[LiteSocket.Send: offset={0}] and [count={1}] is not valid for buffer of length [{2}].", offset, count, buffer.Length));
            }

            lock (syncLock)
            {
                if (!Connected)
                {
                    throw new InvalidOperationException("Socket is not connected.");
                }

                if (receivePending)
                {
                    throw new InvalidOperationException("LiteSocket.Receive: Another receive operation is already pending on this socket.");
                }

                try
                {
                    receivePending = true;

                    return(sock.BeginReceive(buffer, offset, count, SocketFlags.None, callback, state));
                }
                catch
                {
                    receivePending = false;
                    throw;
                }
            }
        }
Example #7
0
        /// <summary>
        /// Handles socket receive completions.
        /// </summary>
        /// <param name="ar"></param>
        private void OnReceive(IAsyncResult ar)
        {
            HttpAsyncState httpState = (HttpAsyncState)ar.AsyncState;
            HttpRequest    request   = httpState.Request;
            EnhancedSocket sock      = httpState.Socket;

            byte[]       recvBuf = httpState.Buffer;
            int          cbRecv;
            HttpResponse response;
            bool         closeCon;
            bool         close;
            bool         firstRequest;

            try
            {
                cbRecv = sock.EndReceive(ar);
            }
            catch
            {
                using (TimedLock.Lock(syncLock))
                    connections.Remove(sock);

                sock.Close();
                return;
            }

            if (cbRecv == 0)
            {
                using (TimedLock.Lock(syncLock))
                    connections.Remove(sock);

                sock.ShutdownAndClose();
                return;
            }

            if (perfBytesRecv != null)
            {
                perfBytesRecv.IncrementBy(cbRecv);
            }

            httpState.RecvSize += cbRecv;
            if (httpState.RecvSize > cbQueryMax)
            {
                // The request is too large so respond with a HttpStatus.RequestEntityTooLarge
                // and close the socket.

                response = new HttpResponse(HttpStatus.RequestEntityTooLarge);
                sock.AsyncSendClose(response.Serialize(SendBlockSize));

                using (TimedLock.Lock(syncLock))
                    connections.Remove(sock);

                return;
            }

            if (!request.Parse(recvBuf, cbRecv))
            {
                recvBuf          = new byte[RecvBlockSize];
                httpState.Buffer = recvBuf;
                sock.BeginReceive(recvBuf, 0, recvBuf.Length, SocketFlags.None, onRecv, httpState);
                return;
            }

            // We have a complete request so process it.

            request.EndParse();

            firstRequest           = httpState.FirstRequest;
            httpState.FirstRequest = false;

            try
            {
                sock.AppState = this;   // Indicate that we're processing a request

                closeCon = false;
                for (int i = 0; i < modules.Length; i++)
                {
                    response = modules[i].OnRequest(this, request, firstRequest, out close);
                    closeCon = closeCon || close;

                    if (response != null)
                    {
                        BlockArray blocks;

                        // Make sure the response version is reasonable

                        if (request.HttpVersion < response.HttpVersion)
                        {
                            response.HttpVersion = request.HttpVersion;
                        }

                        // Truncate any content data for HEAD requests

                        if (request.Method == "HEAD")
                        {
                            response.Content = null;
                            if (response["Content-Length"] != null)
                            {
                                response["Content-Length"] = "0";
                            }
                        }

                        blocks = response.Serialize(SendBlockSize);
                        if (perfBytesSent != null)
                        {
                            perfBytesSent.IncrementBy(blocks.Size);
                        }

                        if (closeCon)
                        {
                            sock.AsyncSendClose(blocks);

                            using (TimedLock.Lock(syncLock))
                                connections.Remove(sock);
                        }
                        else
                        {
                            sock.BeginSendAll(blocks, SocketFlags.None, onSend, httpState);
                        }

                        break;
                    }
                }
            }
            finally
            {
                sock.AppState = null;   // Indicate that we're done processing the request
            }
        }
Example #8
0
            private void OnReceive(IAsyncResult ar)
            {
                List <SipMessage> received = null;

                try
                {
                    using (TimedLock.Lock(transport))
                    {
                        int       cb;
                        int       pos;
                        int       cbContents;
                        SipHeader contentLength;
                        byte[]    packet;

                        try
                        {
                            if (sock == null)
                            {
                                return;
                            }

                            if (contentBuf == null)
                            {
                                // We're reading a message envelope.

                                // Read packets into headerBuf until we can find the CRLFCRLF
                                // sequence marking the end of the message headers.

                                cb = sock.EndReceive(ar);
                                if (cb == 0)
                                {
                                    // The socket has been closed on by the remote element.

                                    CloseAndRemove();
                                    return;
                                }

                                cbRecv += cb;

tryAgain:

                                // Remove any leading CR or LF characters by shifting the
                                // buffer contents.  I know this isn't super efficient but
                                // we'll probably never actually see packets with this
                                // in the wild.

                                for (pos = 0; pos < cbRecv; pos++)
                                {
                                    if (headerBuf[pos] != 0x0D && headerBuf[pos] != 0x0A)
                                    {
                                        break;
                                    }
                                }

                                if (pos != 0)
                                {
                                    if (pos == cbRecv)
                                    {
                                        // No data remaining in the buffer

                                        cbRecv = 0;
                                        sock.BeginReceive(headerBuf, 0, headerBuf.Length, SocketFlags.None, onRecv, null);
                                        return;
                                    }

                                    Array.Copy(headerBuf, pos, headerBuf, 0, headerBuf.Length - pos);
                                    cbRecv -= pos;
                                }

                                // Scan the message for the CRLFCRLF sequence terminating the
                                // message envelope.

                                pos = Helper.IndexOf(headerBuf, CRLFCRLF, 0, cbRecv);
                                if (pos != -1)
                                {
                                    // We've got the message envelope

                                    pos += 4;   // Advance past the CRLFCRLF

                                    // Parse the message headers and then get the Content-Length header

                                    packet = Helper.Extract(headerBuf, 0, pos);

                                    try
                                    {
                                        message = SipMessage.Parse(packet, false);
                                    }
                                    catch (Exception e)
                                    {
                                        SipHelper.Trace(string.Format("TCP: UNPARSABLE message received  from {0}: [{1}]", remoteEP, e.Message), Helper.FromUTF8(packet));
                                        throw;
                                    }

                                    contentLength = message[SipHeader.ContentLength];

                                    if (contentLength == null || !int.TryParse(contentLength.Text, out cbContents) || cbContents < 0)
                                    {
                                        var e = new SipException("Malformed SIP message: Invalid or missing [Content-Length] header from streaming transport.");

                                        e.Transport      = "TCP";
                                        e.BadPacket      = packet;
                                        e.SourceEndpoint = remoteEP;
                                        throw e;
                                    }

                                    if (cbContents > MaxContentSize)
                                    {
                                        var e = new SipException("Invalid SIP message: [Content-Length={0}] exceeds [{1}].", cbContents, MaxContentSize);

                                        e.Transport      = "TCP";
                                        e.BadPacket      = packet;
                                        e.SourceEndpoint = remoteEP;
                                        throw e;
                                    }

                                    if (pos + cbContents <= cbRecv)
                                    {
                                        // We already have the message contents, so extract the contents,
                                        // add them to the message, and then queue the message for delivery
                                        // once we leave the lock.

                                        message.Contents = Helper.Extract(headerBuf, pos, cbContents);

                                        if (received == null)
                                        {
                                            received = new List <SipMessage>();
                                        }

                                        received.Add(message);
                                        message = null;

                                        // Shift any remaining data to the left in headerBuf,
                                        // adjust cbRecv, and the loop to look for another
                                        // message.

                                        pos += cbContents;
                                        cb   = cbRecv - pos; // Bytes remaining in the buffer

                                        if (cb == 0)
                                        {
                                            // No more data left in the buffer

                                            cbRecv = 0;
                                            sock.BeginReceive(headerBuf, 0, headerBuf.Length, SocketFlags.None, onRecv, null);
                                            return;
                                        }

                                        Array.Copy(headerBuf, pos, headerBuf, 0, cb);
                                        cbRecv = cb;
                                        goto tryAgain;
                                    }

                                    // We don't have all of the message contents, so allocate a buffer for
                                    // the contents, copy what we have already into this buffer, and then
                                    // initiate a receive operation to read the remaining data.

                                    contentBuf = new byte[cbContents];
                                    cbRecv     = cbRecv - pos; // Content bytes remaining in the buffer

                                    Array.Copy(headerBuf, pos, contentBuf, 0, cbRecv);
                                    sock.BeginReceiveAll(contentBuf, cbRecv, cbContents - cbRecv, SocketFlags.None, onRecv, null);
                                    return;
                                }

                                // Throw an error if the header buffer is full and we still haven't
                                // found the end of the envelope.

                                if (cbRecv >= headerBuf.Length)
                                {
                                    var e = new SipException("Malformed SIP message: Read [{0}] bytes and have not yet encountered end of headers.", headerBuf.Length);

                                    e.Transport      = "TCP";
                                    e.SourceEndpoint = remoteEP;
                                    throw e;
                                }

                                // Continue receiving header data.

                                sock.BeginReceive(headerBuf, cbRecv, headerBuf.Length - cbRecv, SocketFlags.None, onRecv, null);
                            }
                            else
                            {
                                // We're in the process of reading the message contents.
                                // Complete the contents receive operation and queue the
                                // message for delivery after we leave the lock.

                                sock.EndReceiveAll(ar);
                                message.Contents = contentBuf;

                                if (received == null)
                                {
                                    received = new List <SipMessage>();
                                }

                                received.Add(message);

                                // Reset and start reading the next message envelope.

                                message    = null;
                                contentBuf = null;
                                cbRecv     = 0;

                                sock.BeginReceive(headerBuf, 0, headerBuf.Length, SocketFlags.None, onRecv, null);
                            }
                        }
                        catch (SocketException)
                        {
                            CloseAndRemove();
                        }
                        catch (Exception e)
                        {
                            SysLog.LogException(e);
                            CloseAndRemove();
                        }
                    }
                }
                finally
                {
                    // Deliver any queued messages (outside of the lock)

                    if (received != null)
                    {
                        foreach (var message in received)
                        {
                            message.SourceTransport = transport;
                            message.RemoteEndpoint  = remoteEP;

                            if ((transport.traceMode & SipTraceMode.Receive) != 0)
                            {
                                SipHelper.Trace(string.Format("TCP: received from {0}", remoteEP), message);
                            }

                            transport.router.Route(transport, message);
                        }
                    }
                }
            }