Example #1
0
 /// <summary>
 /// Gracefully stops communication on the socket and then closes it.
 /// </summary>
 /// <remarks>
 /// <note>
 /// This method is safe to call when the socket is already shut down or closed.
 /// </note>
 /// </remarks>
 public void ShutdownAndClose()
 {
     lock (syncLock)
     {
         if (isTcp)
         {
             sock.ShutdownAndClose();
         }
         else
         {
             sock.Close();
         }
     }
 }
Example #2
0
        /// <summary>
        /// Closes the channel if it's currently open.
        /// </summary>
        public void Close()
        {
            using (TimedLock.Lock(router.SyncRoot))
            {
                try
                {
                    if (sock != null)
                    {
                        try
                        {
                            if (sock.Connected)
                            {
                                router.Trace(2, "TCP: Close", "LocalEP=" + localEP.NetEP.ToString() + " remoteEP=" + remoteEP.NetEP.ToString(), null);
                            }

                            sock.ShutdownAndClose();
                        }
                        catch
                        {
                        }

                        connected = false;
                        sendQueue.Clear();

                        sending = false;
                        sendMsg = null;
                        sendBuf = null;
                        sendPos = 0;
                        cbSend  = 0;

                        recvHeader = false;
                        recvBuf    = null;
                        recvPos    = 0;
                    }
                }
                catch
                {
                }
            }
        }
Example #3
0
            public void Close()
            {
                if (sock == null)
                {
                    return;
                }

                using (TimedLock.Lock(transport))
                {
                    sock.ShutdownAndClose();
                    sock = null;
                }
            }
Example #4
0
        /// <summary>
        /// Handles completion of the response reception.
        /// </summary>
        /// <param name="ar">The async result.</param>
        private void OnResponseReceived(IAsyncResult ar)
        {
            var httpAR = (HttpAsyncResult)ar.AsyncState;
            int cbRecv;

            using (TimedLock.Lock(this))
            {
                try
                {
                    // Pump the received data into the response parser,
                    // signalling completion when we have the entire message.

                    cbRecv = sock.EndReceive(ar);

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

                    if (httpAR.Response.Parse(httpAR.Buffer, cbRecv))
                    {
                        httpAR.Response.EndParse();
                        httpAR.Notify();
                        return;
                    }

                    if (cbRecv == 0)
                    {
                        sock.ShutdownAndClose();
                        return;
                    }

                    // Continue receiving response data

                    httpAR.Buffer = new byte[HttpStack.BlockSize];
                    sock.BeginReceive(httpAR.Buffer, 0, HttpStack.BlockSize, SocketFlags.None, onResponseRecv, httpAR);
                }
                catch (Exception e)
                {
                    httpAR.Notify(e);
                }
            }
        }
Example #5
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 #6
0
        /// <summary>
        /// Asynchronously transmits the message passed to the destination
        /// indicated by the <see paramref="remoteEP" /> parameter.
        /// </summary>
        /// <param name="remoteEP">The destination SIP endpoint's <see cref="NetworkBinding" />.</param>
        /// <param name="message">The <see cref="SipMessage" /> to be transmitted.</param>
        /// <remarks>
        /// Note that this method will go to some lengths to send the message
        /// down an existing connection to this endpoint.
        /// </remarks>
        /// <exception cref="SipTransportException">Thrown if the remote endpoint rejected the message or timed out.</exception>
        public void Send(NetworkBinding remoteEP, SipMessage message)
        {
            string         key = remoteEP.ToString();
            EnhancedSocket sock;
            Connection     con;

            using (TimedLock.Lock(this))
            {
                if (listener == null)
                {
                    throw new ObjectDisposedException("Transport is closed.");
                }

                if (disabled)
                {
                    return;
                }

                if ((traceMode & SipTraceMode.Send) != 0)
                {
                    SipHelper.Trace(string.Format("TCP: sending to {0}", remoteEP), message);
                }

                // Send the message down an existing connection to this
                // endpoint (if there is one).

                if (connections.TryGetValue(key, out con))
                {
                    con.Send(message);
                    return;
                }
            }

            // Otherwise establish a connection to the endpoint and transmit
            // the message.  Note that I'm establishing the connection outside
            // of the lock so processing on other connections can continue
            // while the connection is established.

            try
            {
                sock = new EnhancedSocket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
                sock.Connect(remoteEP);
            }
            catch (SocketException e)
            {
                switch ((SocketError)e.ErrorCode)
                {
                case SocketError.ConnectionAborted:
                case SocketError.ConnectionRefused:
                case SocketError.ConnectionReset:
                case SocketError.HostDown:
                case SocketError.HostNotFound:
                case SocketError.HostUnreachable:

                    throw new SipTransportException(SipTransportException.ErrorType.Rejected, e.Message, e);

                case SocketError.TimedOut:

                    throw new SipTransportException(SipTransportException.ErrorType.Timeout, e.Message, e);

                default:

                    throw;
                }
            }

            using (TimedLock.Lock(this))
            {
                if (listener == null)
                {
                    // Transport must have been closed while we were outside of the lock.

                    sock.ShutdownAndClose();
                    throw new ObjectDisposedException("Transport is closed.");
                }

                if (connections.TryGetValue(key, out con))
                {
                    // Another connection to this endpoint must have been established
                    // while we were outside of the lock.  Close the new socket and
                    // use the existing connection.

                    sock.ShutdownAndClose();

                    con.Send(message);
                    return;
                }

                // Add the new connection to the collection and then
                // send the message.

                con = new Connection(this, sock, remoteEP);
                connections.Add(key, con);
                con.Send(message);
            }
        }