コード例 #1
0
        private static void ForwardData(object args)
        {
            StreamsPair pair   = args as StreamsPair;
            HeyLogger   logger = pair.Logger;

            byte[] buffer = new byte[1024 * 1024];

            try
            {
                while (pair.StreamA.CanRead)
                {
                    int bytesRead = pair.StreamA.Read(buffer, 0, buffer.Length);
                    if (bytesRead == 0)
                    {
                        logger.WriteLine(String.Format("No more bytes to read from {0}.", pair.Label));
                        break;
                    }

                    pair.StreamB.Write(buffer, 0, bytesRead);
                    logger.WriteLine(String.Format("{0} bytes from {1}.", bytesRead, pair.Label));
                }
            }
            catch (IOException ex)
            {
                WriteLine(ConsoleColor.Red, pair.Label);
                logger.WriteLine(ex.ToString());
            }

            // TODO: Check this is right.
            // Tell the other side connections is being shutdown.
            pair.StreamB.Close();
        }
コード例 #2
0
        private static void OnAccept(IAsyncResult asyncResult)
        {
            HeyLogger logger         = new HeyLogger();
            Socket    socketListener = asyncResult.AsyncState as Socket;
            Socket    client         = socketListener.EndAccept(asyncResult);

            socketListener.BeginAccept(OnAccept, asyncResult.AsyncState);

            try
            {
                HeyHttpRequest request = new HeyHttpRequest(logger);

                // Client got connected.
                logger.WriteLine(String.Format("Connected: {0}", client.RemoteEndPoint));

                // Read HTTP headers.
                NetworkStream clientStream = new NetworkStream(client);
                MemoryStream  tempStream   = new MemoryStream();
                request.ReadHeaders(clientStream, tempStream);

                // Authentication.
                if (settings.AuthenticationRequired && !IsAuthenticated(request))
                {
                    Reply407AndClose(logger, clientStream);
                    return;
                }

                // Find server host name.
                logger.WriteLine(String.Format("Trying to connect to {0}", request.Host));

                // Get IP address for the given server hostname.
                IPHostEntry hostEntry = Dns.GetHostEntry(request.Host);
                if (hostEntry.AddressList.Length == 0)
                {
                    throw new Exception("Unknow server hostname.");
                }
                IPAddress address = hostEntry.AddressList[0];

                // Connect to server.
                Socket server = new Socket(address.AddressFamily, SocketType.Stream, ProtocolType.Tcp);
                server.Connect(new IPEndPoint(address, request.Port));

                logger.WriteLine(String.Format("Connected to {0}", request.Host));

                // Send cached data to server.
                NetworkStream serverStream = new NetworkStream(server);

                // When using the CONNECT method, proxy must send a HTTP response to client.
                // See "Tunneling TCP based protocols through Web proxy servers" internet-draft.
                if (request.Method == "CONNECT")
                {
                    HeyHttpResponse response = new HeyHttpResponse(logger);
                    response.Status = "200 Connection established";
                    response.Headers.Add("Proxy-agent: Happy-Sockets-Proxy/1.0");
                    response.CopyHeadersTo(clientStream);
                }
                else
                {
                    // Only forward headers when it is not a CONNECT request.
                    tempStream.Seek(0, SeekOrigin.Begin);
                    tempStream.CopyTo(serverStream);
                }

                // Forward data.
                ParameterizedThreadStart serverToClientStart = new ParameterizedThreadStart(ForwardData);
                Thread serverToClientThread = new Thread(serverToClientStart);
                serverToClientThread.Start(
                    new StreamsPair
                {
                    StreamA = serverStream,
                    StreamB = clientStream,
                    Label   = "server to client",
                    Logger  = logger
                });

                ParameterizedThreadStart clientToServerStart = new ParameterizedThreadStart(ForwardData);
                Thread clientToServerThread = new Thread(clientToServerStart);
                clientToServerThread.Start(
                    new StreamsPair
                {
                    StreamA = clientStream,
                    StreamB = serverStream,
                    Label   = "client to server",
                    Logger  = logger
                });

                //serverToClientThread.Join();
                //clientToServerThread.Join();

                // TODO: make sure streams do not go out of scope.
                // TODO: wait until threads end and ensure connections are close.
            }
            catch (SocketException ex)
            {
                WriteLine(ConsoleColor.Red, ex.Message);
                logger.WriteLine(ex.ToString());

                // We couldn't connect to the  server, terminate connection with the client.
                client.Close();
            }
            catch (IOException ex)
            {
                WriteLine(ConsoleColor.Red, ex.Message);
                logger.WriteLine(ex.ToString());

                // The client closed the connection, terminate the connection with the server.
                client.Close();
            }
            catch (Exception ex)
            {
                WriteLine(ConsoleColor.Red, ex.Message);
                logger.WriteLine(ex.ToString());
            }
        }