Overview
Features
Download
Documentation
Community
Add-Ons & Services

[SOLVED] StreamSocket Help

Please post support and help requests here.

[SOLVED] StreamSocket Help

Postby Genesis » 20 Nov 2009, 11:10

Hi,

Hopefully someone here can help me. Please forgive me if this is something obvious as I have limited experience with both POCO and C++.

I have been writing a custom SOCKS 5 proxy server using POCO but have run into issues getting the main processing loop to function correctly. Currently I am using a client read, server write, server read, client write loop which I am converting across from a working Perl implementation of a SOCKS 5 server. I will post this implementation along with my C++ source so hopefully someone can spot something I have missed. Aside from the method I am using now, I have also tried using an event driven approach with SocketReactors but was unable to get this working either. For testing I have been using a socksified browser (Firefox) running through freecap which is displaying a simple HTML page. Using the Perl server the page loads correctly but using my implementation the page hangs until client.receiveBytes returns 0 and the underlying connection is closed. The browser then displays the actual "HTTP/1.1 200 OK" etc. content rather than the page content which should just be 1111. The output of both the Perl implementation and my implementation are the same as well as the number of bytes being sent/received.

The function I am having issues with is below. I should point out that this is part of a SocksServerConnection class extending the TCPServerConnection class:
Code: Select all
void startProxy(string host, int port)
    {
        int n = 0;
        int written = 0;
        char buffer[BUFFER_SIZE];
        SocketAddress addr(host, port);
        server.connect(addr);
        Poco::Timespan timeout(50000);

        cout << "Connected to: " << server.peerAddress().toString() << endl;

        while(true)
        {
            n = 0;
            memset(buffer, 0, BUFFER_SIZE);

            if(client.poll(timeout, Socket::SELECT_READ))
            {
                if((n = client.receiveBytes(buffer, BUFFER_SIZE)) == 0)
                {
                    cout << "client returned 0 bytes - closing connections" << endl;
                    return;
                }
                cout << "[" << host << ":" << port << "] read " << n << " bytes from client" << endl;
                cout << "\n[BYTES FROM CLIENT]:\n" << buffer << "|" << endl;

                written = 0;
                while(n > written)
                {
                    written += server.sendBytes(buffer, n);
                }
                cout << "[" << host << ":" << port << "] wrote " << written << " bytes to server" << endl;
            }

            n = 0;
            memset(buffer, 0, BUFFER_SIZE);

            if(server.poll(timeout, Socket::SELECT_READ))
            {
                if((n = server.receiveBytes(buffer, BUFFER_SIZE)) == 0)
                {
                    cout << "server returned 0 bytes - closing connections" << endl;
                    return;
                }
                cout << "[" << host << ":" << port << "] read " << n << " bytes from server" << endl;
                cout << "\n[BYTES FROM SERVER]:\n" << buffer << "|" << endl;

                written = 0;
                while(n > written)
                {
                    written = client.sendBytes(buffer, n);
                }
                cout << "[" << host << ":" << port << "] wrote " << written << " bytes to client" << endl;
            }
        }
    }


The Perl implementation I have been working off is as follows:
Code: Select all
sub socks_connect
{
 my($client, $host, $port) = @_;
 my $target = IO::Socket::INET->new(LocalHost => $local_host, PeerAddr => $host, PeerPort => $port, Proto => 'tcp', Type => SOCK_STREAM);

 unless($target) { return; }

 print "client requests connection to host $host:$port\n";

 $target->autoflush();
 while($client || $target)
 {
   my $rin = "";
   vec($rin, fileno($client), 1) = 1 if $client;
   vec($rin, fileno($target), 1) = 1 if $target;
   my($rout, $eout);
    $rout = $rin;
    $eout = $rin;
   select($rout, undef, $eout, 120);
   if (!$rout  &&  !$eout)
    { return; }
   my $cbuffer = "";
   my $tbuffer = "";
    print "[$host:$port] start rout:", unpack("h*", $rout), "\n";

    if ($client && vec($rout, fileno($client), 1))
    {
        print "[$host:$port] read from client\n";
        my $result = sysread($client, $tbuffer, 1024);
        if (!defined($result) || !$result) { return; }
        print "[BYTES FROM CLIENT]:\n$tbuffer|";

        while (my $len = length($tbuffer))
        {
            my $res = syswrite($target, $tbuffer, $len);
            print "[$host:$port] wrote $res bytes to target\n";
            if ($res > 0) { $tbuffer = substr($tbuffer, $res); } else { return; }
        }
    }

    if ($target && vec($rout, fileno($target), 1))
    {
        print "[$host:$port] read from server\n";
        my $result = sysread($target, $cbuffer, 1024);
        if (!defined($result) || !$result) { return; }
        print "[BYTES FROM SERVER]:\n$cbuffer|";

        while (my $len = length($cbuffer))
        {
            my $res = syswrite($client, $cbuffer, $len);
            print "[$host:$port] wrote $res bytes to client\n";
            if ($res > 0) { $cbuffer = substr($cbuffer, $res); } else { return; }
        }
    }
 }
}


Any help with this would be greatly appreciated.
Genesis
 
Posts: 8
Joined: 20 Nov 2009, 10:03

Re: [SOLVED] StreamSocket Help

Postby Genesis » 25 Nov 2009, 11:25

This issue has been solved.

It turns out I was writing to the client before calling startProxy without specifying the correct amount of bytes to write. This was causing further client writes to block.

e.g.:
Code: Select all
char buffer[256];
client.sendBytes(buffer, 256);


Where I should have been doing something like:
Code: Select all
char buffer[256];
client.sendBytes(buffer, strlen(buffer));
Genesis
 
Posts: 8
Joined: 20 Nov 2009, 10:03


Return to Support

Who is online

Users browsing this forum: No registered users and 1 guest