Communication state between two hosts
Inheritance: IDisposable
Beispiel #1
0
        internal HttpStatusLine(HttpSocket hs)
        {
            string line;
            do
                line = hs.ReadAsciiLine().Trim();
            while (line.Length == 0);
            string[] items = line.Split(sp,
                StringSplitOptions.RemoveEmptyEntries);
            // Note: the status line has three items: the HTTP protocol
            // version, the status code, and the reason phrase.
            // Only the reason phrase may be empty.
            if (items.Length < 2)
                throw new HttpProtocolBroken("Unrecognized status line '" +
                    line + "'");

            ProtocolVersion = ParserHelper.ParseProtocolVersion(
                items[0]);

            string code = items[1];
            if (code.Length != 3 ||
                !char.IsDigit(code[0])) // we only test the first character
                throw new HttpProtocolBroken("Invalid status code '" +
                    code + "'");

            //string Reason = rest of the string; // we don't need it

            StatusCode = int.Parse(code);
            StatusLine = line;
        }
Beispiel #2
0
        /// <summary>
        /// Transfer data from this socket to the destination socket
        /// until this socket closes
        /// </summary>
        /// <returns>The number of bytes sent</returns>
        public uint TunnelDataTo(HttpSocket dest, System.Threading.CancellationToken cancelToken)
        {
            uint total_sent = 0;

            try
            {
                if (AvailableData == 0)
                {
                    ReadRaw();
                }
                while (AvailableData > 0 && !cancelToken.IsCancellationRequested)
                {
                    uint sent = dest.WriteBinary(Buffer, BufferPosition,
                                                 AvailableData);
                    if (sent < AvailableData)
                    {
                        throw new IoBroken();
                    }
                    total_sent += sent;
                    ReadRaw();
                }
            }
            catch (SocketException) { /* ignore */ }

            return(total_sent);
        }
Beispiel #3
0
 internal void SendTo(HttpSocket hs)
 {
     hs.WriteAsciiLine(HeadersInOrder);
     // Note: HeadersInOrder contains one trailing newline, so
     // WriteAsciiLine() will send two newlines (which is what we
     // want).
 }
Beispiel #4
0
        /// <summary>
        /// Transfer data from this socket to the destination socket
        /// until this socket closes
        /// </summary>
        /// <returns>The number of bytes sent</returns>
        public uint TunnelDataTo(HttpSocket dest)
        {
            uint total_sent = 0;

            try
            {
                if (AvailableData == 0)
                {
                    ReadRaw();
                }
                while (AvailableData > 0)
                {
                    uint sent = dest.WriteBinary(Buffer, BufferPosition,
                                                 AvailableData);
                    if (sent < AvailableData)
                    {
                        throw new IoBroken();
                    }
                    total_sent += sent;
                    ReadRaw();
                }
            }
            catch (SocketException) { /* ignore */ }

            return(total_sent);
        }
Beispiel #5
0
 /// <summary>
 /// Close broken sockets
 /// </summary>
 /// <remarks>
 /// This function is called regularly to clean up the list of
 /// connected sockets.
 /// </remarks>
 void CheckSockets(object eventState)
 {
     try
     {
         lock (ConnectedSockets)
         {
             foreach (var kv in ConnectedSockets)
             {
                 try
                 {
                     int        id    = kv.Key;
                     HttpSocket state = kv.Value;
                     if (state == null || state.IsSocketDead())
                     {
                         ConnectedSockets.Remove(id);
                     }
                 }
                 catch (Exception e)
                 {
                     log.Error(e);
                 }
             }
         }
     }
     catch { }
 }
Beispiel #6
0
 /// <summary>
 /// Read <c>nb_bytes</c> bytes from the socket,
 /// and send it to the destination socket
 /// </summary>
 /// <returns>The number of bytes sent</returns>
 public uint TunnelDataTo(HttpSocket dest, uint nb_bytes)
 {
     return(TunnelDataTo((byte[] b, uint o, uint s) =>
     {
         if (dest.WriteBinary(b, o, s) < s)
         {
             throw new IoBroken();
         }
     }, nb_bytes));
 }
Beispiel #7
0
 /// <summary>
 /// Tunnel a HTTP-chunked blob of data
 /// </summary>
 /// <param name="dest">The destination socket</param>
 /// <remarks>
 /// The tunneling stops when the last chunk, identified by a
 /// size of 0, arrives. The optional trailing entities are also
 /// transmitted (but otherwise ignored).
 /// </remarks>
 public void TunnelChunkedDataTo(HttpSocket dest)
 {
     TunnelChunkedDataTo(dest, (byte[] b, uint o, uint s) =>
     {
         if (dest.WriteBinary(b, o, s) < s)
         {
             throw new IoBroken();
         }
     });
 }
Beispiel #8
0
        /// <summary>
        /// Parse a HTTP header after sending it through the TCP channel
        /// </summary>
        /// <returns>A parsed version of <param>rq_line</param></returns>
        /// <remarks>
        /// This method must be called between Setup() and TearDown().
        /// </remarks>
        public static HttpRequestLine ParseHttpRequestLine(string rq_line)
        {
            byte[] to_send = System.Text.Encoding.ASCII.GetBytes(rq_line);

            var es = new EchoSocket(bUseIPv6, to_send);
            using (var hs = new HttpSocket(es.socket))
            {
                es.socket.Shutdown(SocketShutdown.Send);
                return new HttpRequestLine(hs);
            }
        }
Beispiel #9
0
        /// <summary>
        /// Parse a HTTP header after sending it through the TCP channel
        /// </summary>
        /// <returns>A parsed version of <param>header</param></returns>
        /// <remarks>
        /// This method must be called between Setup() and TearDown().
        /// </remarks>
        public static HttpHeaders ParseHttpHeaders(string header)
        {
            byte[] to_send = System.Text.Encoding.ASCII.GetBytes(header);

            var es = new EchoSocket(bUseIPv6, to_send);
            using (var hs = new HttpSocket(es.socket))
            {
                es.socket.Shutdown(SocketShutdown.Send);
                return new TrotiNet.HttpHeaders(hs);
            }
        }
Beispiel #10
0
        /// <summary>
        /// Send a message through the TCP channel, and expect it to
        /// return unchanged
        /// </summary>
        /// <remarks>
        /// Useful for testing I/O levels 1 and 2.
        /// This method must be called between Setup() and TearDown().
        /// </remarks>
        public static void DoMsgRoundTrip(string msg_send, string msg_expect)
        {
            byte[] to_send = System.Text.Encoding.ASCII.GetBytes(msg_send);

            using (var hs = new HttpSocket(
                new EchoSocket(bUseIPv6, to_send).socket))
            {
                var msg_receive = hs.ReadAsciiLine();
                Assert.AreEqual(msg_expect, msg_receive);
                hs.CloseSocket();
            }
        }
Beispiel #11
0
        /// <summary>
        /// Remove the socket contained in the given state object
        /// from the connected array list and hash table, then close the
        /// socket
        /// </summary>
        virtual protected void CloseSocket(HttpSocket state)
        {
            HttpSocket actual_state;
            lock (ConnectedSockets)
            {
                if (!ConnectedSockets.TryGetValue(state.id, out actual_state))
                    return;

                System.Diagnostics.Debug.Assert(actual_state == state);
                ConnectedSockets.Remove(state.id);
            }

            state.CloseSocket();
        }
Beispiel #12
0
        internal HttpRequestLine(HttpSocket hs)
        {
            string line;
            do
                line = hs.ReadAsciiLine().Trim();
            while (line.Length == 0);

            string[] items = line.Split(sp,
                StringSplitOptions.RemoveEmptyEntries);
            if (items.Length != 3)
                throw new HttpProtocolBroken("Unrecognized request line '" +
                    line + "'");

            RequestLine = line;
            Method = items[0];
            URI = items[1];
            ProtocolVersion = ParserHelper.ParseProtocolVersion(items[2]);
        }
        /// <summary>
        /// Close broken sockets
        /// </summary>
        /// <remarks>
        /// This function is called regularly to clean up the list of
        /// connected sockets.
        /// </remarks>
        void CheckSockets(object eventState)
        {
            Console.WriteLine("Starting Clean Sockets: {0}", ConnectedSockets.Count);

            try
            {
                lock (ConnectedSockets)
                {
                    var toRemove = new List <int>();

                    foreach (var kv in ConnectedSockets)
                    {
                        try
                        {
                            int        id    = kv.Key;
                            HttpSocket state = kv.Value;

                            if (DateTime.Now - state.CreationTime > TimeSpan.FromMinutes(10))
                            {
                                //Console.WriteLine("Closing Old Socket: {0} {1}", id, state.CreationTime);
                                state.CloseSocket();
                            }

                            if (state == null || state.IsSocketDead())
                            {
                                toRemove.Add(id);
                            }
                        }
                        catch (Exception e)
                        {
                            log.Error(e);
                        }
                    }

                    foreach (var id in toRemove)
                    {
                        ConnectedSockets.Remove(id);
                    }
                }
            }
            catch { }

            Console.WriteLine("Finished Clean Sockets: {0}", ConnectedSockets.Count);
        }
        internal HttpRequestLine(HttpSocket hs)
        {
            string line;

            do
            {
                line = hs.ReadAsciiLine().Trim();
            }while (line.Length == 0);

            string[] items = line.Split(sp,
                                        StringSplitOptions.RemoveEmptyEntries);
            if (items.Length != 3)
            {
                throw new HttpProtocolBroken("Unrecognized request line '" +
                                             line + "'");
            }

            RequestLine     = line;
            Method          = items[0];
            URI             = items[1];
            ProtocolVersion = ParserHelper.ParseProtocolVersion(items[2]);
        }
        internal HttpStatusLine(HttpSocket hs)
        {
            string line;

            do
            {
                line = hs.ReadAsciiLine().Trim();
            }while (line.Length == 0);
            string[] items = line.Split(sp,
                                        StringSplitOptions.RemoveEmptyEntries);
            // Note: the status line has three items: the HTTP protocol
            // version, the status code, and the reason phrase.
            // Only the reason phrase may be empty.
            if (items.Length < 2)
            {
                throw new HttpProtocolBroken("Unrecognized status line '" +
                                             line + "'");
            }

            ProtocolVersion = ParserHelper.ParseProtocolVersion(
                items[0]);

            string code = items[1];

            if (code.Length != 3 ||
                !char.IsDigit(code[0])) // we only test the first character
            {
                throw new HttpProtocolBroken("Invalid status code '" +
                                             code + "'");
            }

            //string Reason = rest of the string; // we don't need it

            StatusCode = int.Parse(code);
            StatusLine = line;
        }
Beispiel #16
0
        /* Helper function */
        void TunnelChunkedDataTo(HttpSocket dest, MessagePacketHandler mph)
        {
            // (RFC 2616, sections 3.6.1, 19.4.6)
            while (true)
            {
                string chunk_header = ReadAsciiLine();
                if (chunk_header.Length == 0)
                    throw new HttpProtocolBroken(
                        "Expected chunk header missing");
                int sc = chunk_header.IndexOfAny(c_ChunkSizeEnd);
                string hexa_size;
                if (sc > -1)
                    // We have chunk extensions: ignore them
                    hexa_size = chunk_header.Substring(0, sc);
                else
                    hexa_size = chunk_header;
                uint size;
                try
                {
                    size = Convert.ToUInt32(hexa_size, 16);
                }
                catch
                {
                    string s = chunk_header.Length > 20
                        ? (chunk_header.Substring(0, 17) + "...")
                        : chunk_header;
                    throw new HttpProtocolBroken(
                        "Could not parse chunk size in: " + s);
                }

                if (dest != null)
                    dest.WriteAsciiLine(chunk_header);
                if (size == 0)
                    break;
                TunnelDataTo(mph, size);
                // Read/write one more CRLF
                string new_line = ReadAsciiLine();
                System.Diagnostics.Debug.Assert(new_line.Length == 0);
                if (dest != null)
                    dest.WriteAsciiLine(new_line);
            }
            string line;
            do
            {
                // Tunnel any trailing entity headers
                line = ReadAsciiLine();
                if (dest != null)
                    dest.WriteAsciiLine(line);
            } while (line.Length != 0);
        }
Beispiel #17
0
 /// <summary>
 /// Read <c>nb_bytes</c> bytes from the socket,
 /// and send it to the destination socket
 /// </summary>
 /// <returns>The number of bytes sent</returns>
 public uint TunnelDataTo(HttpSocket dest, uint nb_bytes)
 {
     return TunnelDataTo((byte[] b, uint o, uint s) =>
     {
         if (dest.WriteBinary(b, o, s) < s)
             throw new IoBroken();
     }, nb_bytes);
 }
Beispiel #18
0
        /// <summary>
        /// Transfer data from this socket to the destination socket
        /// until this socket closes
        /// </summary>
        /// <returns>The number of bytes sent</returns>
        public uint TunnelDataTo(HttpSocket dest)
        {
            uint total_sent = 0;

            try
            {
                if (AvailableData == 0)
                    ReadRaw();
                while (AvailableData > 0)
                {
                    uint sent = dest.WriteBinary(Buffer, BufferPosition,
                        AvailableData);
                    if (sent < AvailableData)
                        throw new IoBroken();
                    total_sent += sent;
                    ReadRaw();
                }
            }
            catch (SocketException) { /* ignore */ }

            return total_sent;
        }
Beispiel #19
0
 /// <summary>
 /// Tunnel a HTTP-chunked blob of data
 /// </summary>
 /// <param name="dest">The destination socket</param>
 /// <remarks>
 /// The tunneling stops when the last chunk, identified by a
 /// size of 0, arrives. The optional trailing entities are also
 /// transmitted (but otherwise ignored).
 /// </remarks>
 public void TunnelChunkedDataTo(HttpSocket dest)
 {
     TunnelChunkedDataTo(dest, (byte[] b, uint o, uint s) =>
         {
             if (dest.WriteBinary(b, o, s) < s)
                 throw new IoBroken();
         });
 }
Beispiel #20
0
 /// <summary>
 /// Static constructor with <c>PrintEchoPrefix = false</c>
 /// </summary>
 public static AbstractProxyLogic CreateMirrorProxy(HttpSocket socketBP)
 {
     return new ProxyDummyEcho(socketBP, false);
 }
Beispiel #21
0
 /// <summary>
 /// Common constructor for proxies; one proxy instance is created
 /// per client connection
 /// </summary>
 /// <param name="socketBP">Client socket</param>
 protected AbstractProxyLogic(HttpSocket socketBP)
 {
     System.Diagnostics.Debug.Assert(socketBP != null);
     SocketBP = socketBP;
     SocketPS = null;
 }
Beispiel #22
0
        /// <summary>
        /// Callback method for accepting new connections
        /// </summary>
        void AcceptCallback(IAsyncResult ar)
        {
            if (IsShuttingDown)
                return;

            // Have we really changed thread?
            if (ListeningThread.ManagedThreadId ==
                System.Threading.Thread.CurrentThread.ManagedThreadId)
            {
                // No! Give me a new thread!
                new Thread(() => AcceptCallback(ar)).Start();
                return;
            }

            // Get the socket that handles the client request
            Socket listener = (Socket)ar.AsyncState;
            Socket handler = listener.EndAccept(ar);

            // Signal the main thread to continue
            ListenThreadSwitch.Set();

            #if DEBUG_ACCEPT_CONNECTION
            log.Debug("\tAcceptCallback sent signal");
            #endif

            // Create the state object
            HttpSocket state = new HttpSocket(handler);
            state.id = ++LastClientId;

            lock (ConnectedSockets)
                ConnectedSockets[state.id] = state;

            AbstractProxyLogic proxy = null;
            try
            {
                proxy = OnClientStart(state);
            } catch (Exception e) { log.Error(e); }
            if (proxy == null)
            {
                CloseSocket(state);
                return;
            }

            // No need for asynchronous I/O from now on
            try
            {
                while (proxy.LogicLoop())
                    if (IsShuttingDown || state.IsSocketDead())
                        break;

                log.Debug("Shutting down socket");
            }
            catch (System.Net.Sockets.SocketException) { /* ignore */ }
            catch (TrotiNet.IoBroken) { /* ignore */ }
            catch (Exception e)
            {
                log.Error(e);
                log.Debug("Closing socket on error");
            }

            CloseSocket(state);
        }
Beispiel #23
0
 internal void SendTo(HttpSocket hs)
 {
     hs.WriteAsciiLine(RequestLine);
 }
 /// <summary>
 /// SocketBPからインスタンスを初期化。
 /// 接続(AcceptCallback)の都度インスタンスが生成される。
 /// </summary>
 /// <param name="clientSocket">Browser-Proxy間Socket。SocketBP。</param>
 public TransparentProxyLogic(HttpSocket clientSocket) : base(clientSocket) { }
Beispiel #25
0
 /// <summary>
 /// Common constructor for proxies; one proxy instance is created
 /// per client connection
 /// </summary>
 /// <param name="socketBP">Client socket</param>
 protected AbstractProxyLogic(HttpSocket socketBP)
 {
     System.Diagnostics.Debug.Assert(socketBP != null);
     SocketBP = socketBP;
     SocketPS = null;
 }
 /// <summary>
 /// TcpServerがインスタンスを生成する際に使用するメソッド。
 /// 接続(AcceptCallback)の都度呼び出され、インスタンスが生成される。
 /// </summary>
 /// <param name="clientSocket">Browser-Proxy間Socket。SocketBP。</param>
 /// <returns>ProxyLogicインスタンス。</returns>
 public new static TransparentProxyLogic CreateProxy(HttpSocket clientSocket)
     => new TransparentProxyLogic(clientSocket);
Beispiel #27
0
 /// <summary>
 /// Static constructor
 /// </summary>
 public static AbstractProxyLogic CreateProxy(HttpSocket socketBP)
 {
     return new ProxyLogic(socketBP);
 }
Beispiel #28
0
 /// <summary>
 /// Instantiate a transparent proxy
 /// </summary>
 /// <param name="socketBP">Client browser-proxy socket</param>
 public ProxyLogic(HttpSocket socketBP)
     : base(socketBP)
 {
 }
Beispiel #29
0
        /// <summary>
        /// Remove the socket contained in the given state object
        /// from the connected array list and hash table, then close the
        /// socket
        /// </summary>
        protected virtual void CloseSocket(HttpSocket state)
        {
            HttpSocket actual_state;
            lock (ConnectedSockets)
            {
                if (!ConnectedSockets.TryGetValue(state.id, out actual_state))
                    return;

                System.Diagnostics.Debug.Assert(actual_state == state);
                ConnectedSockets.Remove(state.id);
            }

            state.CloseSocket();
        }
 internal void SendTo(HttpSocket hs)
 {
     hs.WriteAsciiLine(RequestLine);
 }
Beispiel #31
0
        /// <summary>
        /// Read and parse HTTP headers from a connected socket
        /// </summary>
        public HttpHeaders(HttpSocket source) : this()
        {
            StringBuilder sb = new StringBuilder(512);

            while (true)
            {
                var line = source.ReadAsciiLine();
                if (line.Length == 0)
                {
                    break;
                }
                sb.Append(line);
                sb.Append("\r\n"); // Note: if the header newline was
                // incorrectly formatted (i.e. LF instead of CRLF),
                // we correct it here. This is one point where our
                // proxy is not fully transparent.

                var iSplit = line.IndexOf(':');
                if (iSplit <= 0)
                {
                    throw new HttpProtocolBroken("No colon in HTTP header");
                }

                // Header names are case-insensitive, but only some header
                // values are.
                string HeaderName  = line.Substring(0, iSplit).Trim().ToLower();
                string HeaderValue = line.Substring(iSplit + 1).Trim();
                if (IsHeaderValueCaseInsensitive(HeaderName))
                {
                    HeaderValue = HeaderValue.ToLower();
                }

                string previous_value = null;
                if (Headers.TryGetValue(HeaderName, out previous_value))
                {
                    // Duplicate headers: concatenate them
                    // (RFC 2616, section 4.2)

                    // However, this should only occur if the value of that
                    // header is a comma-separated list. In the real world,
                    // it has been observed that headers with
                    // non-comma-separated values, such as Content-Length, *are*
                    // in some rare cases repeated, so we should not concatenate
                    // the values.
                    if (!HeaderName.Equals("content-length"))
                    {
                        Headers[HeaderName] = previous_value + "," + HeaderValue;
                    }
                }
                else
                {
                    Headers[HeaderName] = HeaderValue;
                }
            }

            HeadersInOrder = sb.ToString();

            // Parse a subset of the header values.
            // If headers are added, don't forget to update RemoveHeader
            // as well.
            Connection       = ParseMultipleStringValues("connection");
            ContentEncoding  = ParseStringValue("content-encoding");
            ContentLength    = ParseIntValue("content-length");
            Host             = ParseStringValue("host");
            ProxyConnection  = ParseMultipleStringValues("proxy-connection");
            Referer          = ParseStringValue("referer");
            TransferEncoding = ParseMultipleStringValues("transfer-encoding");
        }
Beispiel #32
0
        /// <summary>
        /// If necessary, connect the remote <c>SocketPS</c> socket
        /// to the given host and port
        /// </summary>
        /// <param name="hostname">Remote host name</param>
        /// <param name="port">Remote port</param>
        /// <remarks>
        /// If SocketPS is already connected to the right host and port,
        /// the socket is reused as is.
        /// </remarks>
        protected void Connect(string hostname, int port)
        {
            System.Diagnostics.Debug.Assert(!String.IsNullOrEmpty(hostname));
            System.Diagnostics.Debug.Assert(port > 0);

            if (DestinationHostName != null &&
                DestinationHostName.Equals(hostname) &&
                DestinationPort == port &&
                (SocketPS != null && !SocketPS.IsSocketDead()))
                // Nothing to do, just reuse the socket
                return;

            if (SocketPS != null)
            {
                log.Debug("Changing hostname/port from " +
                    DestinationHostName + ":" + DestinationPort +
                    " to " + hostname + ":" + port);

                // We have a socket connected to the wrong host (or port)
                SocketPS.CloseSocket();
                SocketPS = null;
            }

            IPAddress[] ips = Dns.GetHostAddresses(hostname);
            Socket socket = null;
            Exception e = null;
            foreach (var ip in ips)
            {
                try
                {
                    socket = new Socket(ip.AddressFamily, SocketType.Stream,
                        ProtocolType.Tcp);
                    socket.Connect(ip, port);
                    break;
                }
                catch (Exception ee)
                {
                    if (ip.Equals(IPAddress.IPv6Loopback))
                        // Do not log that
                        continue;

                    if (e == null)
                        e = ee;
                    if (socket != null)
                    {
                        socket.Close();
                        socket = null;
                    }

                    log.Error(ee);
                }
            }
            if (socket == null)
                throw e;

            // Checked up, and good to go
            SocketPS = new HttpSocket(socket);
            DestinationHostName = hostname;
            DestinationPort = port;

            log.Debug("SocketPS connected to " + hostname + ":" + port);
        }
Beispiel #33
0
        /* Helper function */
        void TunnelChunkedDataTo(HttpSocket dest, MessagePacketHandler mph)
        {
            // (RFC 2616, sections 3.6.1, 19.4.6)
            while (true)
            {
                string chunk_header = ReadAsciiLine();
                if (chunk_header.Length == 0)
                {
                    throw new HttpProtocolBroken(
                              "Expected chunk header missing");
                }
                int    sc = chunk_header.IndexOfAny(c_ChunkSizeEnd);
                string hexa_size;
                if (sc > -1)
                {
                    // We have chunk extensions: ignore them
                    hexa_size = chunk_header.Substring(0, sc);
                }
                else
                {
                    hexa_size = chunk_header;
                }
                uint size;
                try
                {
                    size = Convert.ToUInt32(hexa_size, 16);
                }
                catch
                {
                    string s = chunk_header.Length > 20
                        ? (chunk_header.Substring(0, 17) + "...")
                        : chunk_header;
                    throw new HttpProtocolBroken(
                              "Could not parse chunk size in: " + s);
                }

                if (dest != null)
                {
                    dest.WriteAsciiLine(chunk_header);
                }
                if (size == 0)
                {
                    break;
                }
                TunnelDataTo(mph, size);
                // Read/write one more CRLF
                string new_line = ReadAsciiLine();
                System.Diagnostics.Debug.Assert(new_line.Length == 0);
                if (dest != null)
                {
                    dest.WriteAsciiLine(new_line);
                }
            }
            string line;

            do
            {
                // Tunnel any trailing entity headers
                line = ReadAsciiLine();
                if (dest != null)
                {
                    dest.WriteAsciiLine(line);
                }
            } while (line.Length != 0);
        }
Beispiel #34
0
 /// <summary>
 /// Instantiate a dummy proxy that echoes what it reads on the
 /// socket back to it
 /// </summary>
 /// <param name="socketBP">Client socket</param>
 /// <param name="PrintEchoPrefix">If true, the proxy will add an
 /// "Echo" prefix for each message</param>
 public ProxyDummyEcho(HttpSocket socketBP, bool PrintEchoPrefix)
     : base(socketBP)
 {
     bPrintEchoPrefix = PrintEchoPrefix;
 }
 internal void SendTo(HttpSocket hs)
 {
     hs.WriteAsciiLine(StatusLine);
 }
Beispiel #36
0
 /// <summary>
 /// Static constructor with <c>PrintEchoPrefix = true</c>
 /// </summary>
 public static AbstractProxyLogic CreateEchoProxy(HttpSocket socketBP)
 {
     return new ProxyDummyEcho(socketBP, true);
 }
Beispiel #37
0
        /// <summary>
        /// Callback method for accepting new connections
        /// </summary>
        void AcceptCallback(IAsyncResult ar)
        {
            // Have we really changed thread?
            if (ListeningThread.ManagedThreadId ==
                System.Threading.Thread.CurrentThread.ManagedThreadId)
            {
                // No! Give me a new thread!
                new Thread(() => AcceptCallback(ar)).Start();
                return;
            }

            if (IsShuttingDown)
                return;

            // Get the socket that handles the client request
            Socket listener = (Socket)ar.AsyncState;
            Socket handler = listener.EndAccept(ar);

            // Signal the main thread to continue
            ListenThreadSwitch.Set();

#if DEBUG_ACCEPT_CONNECTION
            log.Debug("\tAcceptCallback sent signal");
#endif

            // Create the state object
            HttpSocket state = new HttpSocket(handler);
            state.id = ++LastClientId;
            log.DebugFormat("Accepted connection: [S{0}] {1} -> {2}", state.id, handler.RemoteEndPoint, handler.LocalEndPoint);

            lock (ConnectedSockets)
                ConnectedSockets[state.id] = state;

            AbstractProxyLogic proxy = null;
            try
            {
                proxy = OnClientStart(state);
            } catch (Exception e) { log.Error(e); }
            if (proxy == null)
            {
                CloseSocket(state);
                return;
            }

            // No need for asynchronous I/O from now on
            try
            {
                while (proxy.LogicLoop())
                    if (IsShuttingDown || state.IsSocketDead())
                        break;

                log.Debug("Shutting down socket");
            }
            catch (System.Net.Sockets.SocketException) { /* ignore */ }
            catch (TrotiNet.IoBroken) { /* ignore */ }
            catch (Exception e)
            {
                log.Error(e);
                log.Debug("Closing socket on error");
            }

            CloseSocket(state);
        }
Beispiel #38
0
        /// <summary>
        /// Transfer data from the socket to the specified packet handler with Async Mode
        /// This is Just For A SSL Tunneling
        /// </summary>
        /// <returns>The number of bytes sent</returns>
        public IAsyncResult TunnelDataAsyncTo(HttpSocket dest)
        {
            byte[] buffer = new byte[4096];
            IAsyncResult Result = LowLevelSocket.BeginReceive(buffer, 0, buffer.Length, SocketFlags.None, new AsyncCallback((ar) =>
                {
                    try
                    {
                        int Ret = (int)ar.AsyncState;

                        Ret = LowLevelSocket.EndReceive(ar);
                        if (Ret > 0)
                        {
                            dest.WriteBinary(buffer, 0, (uint)Ret);
                        }
                        else
                        {
                            CloseSocket();
                        }
                    }
                    catch {  }
                }), new int());
            return Result;
        }
Beispiel #39
0
        /// <summary>
        /// If necessary, connect the remote <c>SocketPS</c> socket
        /// to the given host and port
        /// </summary>
        /// <param name="hostname">Remote host name</param>
        /// <param name="port">Remote port</param>
        /// <remarks>
        /// If SocketPS is already connected to the right host and port,
        /// the socket is reused as is.
        /// </remarks>
        protected void Connect(string hostname, int port, bool secure)
        {
            System.Diagnostics.Debug.Assert(!String.IsNullOrEmpty(hostname));
            System.Diagnostics.Debug.Assert(port > 0);

            if (DestinationHostName != null &&
                DestinationHostName.Equals(hostname) &&
                DestinationPort == port &&
                (SocketPS != null && !SocketPS.IsSocketDead()))
            {
                // Nothing to do, just reuse the socket
                return;
            }

            if (SocketPS != null)
            {
                log.Debug("Changing hostname/port from " +
                          DestinationHostName + ":" + DestinationPort +
                          " to " + hostname + ":" + port);

                // We have a socket connected to the wrong host (or port)
                SocketPS.CloseSocket();
                SocketPS = null;
            }

            IPAddress[] ips    = Resolve(hostname);
            Socket      socket = null;
            Exception   e      = null;

            foreach (var ip in ips)
            {
                try
                {
                    socket = new Socket(ip.AddressFamily, SocketType.Stream, ProtocolType.Tcp);
                    socket.Connect(ip, port);
                    break;
                }
                catch (Exception ee)
                {
                    if (ip.Equals(IPAddress.IPv6Loopback))
                    {
                        // Do not log that
                        continue;
                    }

                    if (e == null)
                    {
                        e = ee;
                    }
                    if (socket != null)
                    {
                        socket.Close();
                        socket = null;
                    }

                    log.Error(ee);
                }
            }
            if (socket == null)
            {
                throw e;
            }

            // Checked up, and good to go
            SocketPS = new HttpSocket(socket);
            if (secure)
            {
                SocketPS.MakeSecureClient(hostname);
            }
            DestinationHostName = hostname;
            DestinationPort     = port;

            log.Debug("SocketPS connected to " + hostname + ":" + port);
        }
Beispiel #40
0
 internal void SendTo(HttpSocket hs)
 {
     hs.WriteAsciiLine(StatusLine);
 }