E-MailRelay

- Main Page
- Namespaces
- Classes
- Files

- File List
- File Members

gsocks.cpp
Go to the documentation of this file.
1 //
2 // Copyright (C) 2001-2018 Graeme Walker <graeme_walker@users.sourceforge.net>
3 //
4 // This program is free software: you can redistribute it and/or modify
5 // it under the terms of the GNU General Public License as published by
6 // the Free Software Foundation, either version 3 of the License, or
7 // (at your option) any later version.
8 //
9 // This program is distributed in the hope that it will be useful,
10 // but WITHOUT ANY WARRANTY; without even the implied warranty of
11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 // GNU General Public License for more details.
13 //
14 // You should have received a copy of the GNU General Public License
15 // along with this program. If not, see <http://www.gnu.org/licenses/>.
16 // ===
17 //
18 // gsocks.cpp
19 //
20
21 #include "gdef.h"
22 #include "gsocks.h"
23 #include "gassert.h"
24
25 GNet::Socks::Socks( const Location & location ) :
26 m_request_offset(0U)
27 {
28 if( location.socks() )
29 {
30 unsigned int far_port = location.socksFarPort() ;
31 if( !Address::validPort(far_port) )
32 throw SocksError( "invalid port" ) ;
33
34 m_request = buildPdu( location.socksFarHost() , far_port ) ;
35 m_request_offset = 0U ;
36 }
37 }
38
39 std::string GNet::Socks::buildPdu( const std::string & far_host , unsigned int far_port )
40 {
41 g_port_t far_port_n = htons( static_cast<g_port_t>(far_port) ) ;
42 g_port_t far_port_lo = far_port_n & 0xffU ;
43 g_port_t far_port_hi = (far_port_n>>8U) & g_port_t(0xffU) ;
44
45 std::string userid ; // TODO - socks userid
46 std::string data ;
47 data.append( 1U , 4 ) ; // version 4
48 data.append( 1U , 1 ) ; // connect request
49 data.append( 1U , static_cast<char>(far_port_lo) ) ;
50 data.append( 1U , static_cast<char>(far_port_hi) ) ;
51 data.append( 1U , 0 ) ; // invalid ipv4
52 data.append( 1U , 0 ) ; // invalid ipv4
53 data.append( 1U , 0 ) ; // invalid ipv4
54 data.append( 1U , 1 ) ; // invalid ipv4
55 data.append( userid ) ;
56 data.append( 1U , 0 ) ; // NUL terminator
57 data.append( far_host ) ;
58 data.append( 1U , 0 ) ; // NUL terminator
59
60 return data ;
61 }
62
63 bool GNet::Socks::send( G::ReadWrite & io )
64 {
65 if( m_request_offset >= m_request.size() )
66 return true ;
67
68 const char * p = m_request.data() + m_request_offset ;
69 size_t n = m_request.size() - m_request_offset ;
70
71 ssize_t rc = io.write( p , n ) ;
72 if( rc < 0 && !io.eWouldBlock() )
73 {
74 throw SocksError( "socket write error" ) ;
75 }
76 else if( rc < 0 || static_cast<size_t>(rc) < n )
77 {
78 size_t nsent = rc < 0 ? size_t(0U) : static_cast<size_t>(rc) ;
79 m_request_offset += nsent ;
80 return false ;
81 }
82 else
83 {
84 m_request_offset = m_request.size() ;
85 return true ;
86 }
87 }
88
89 bool GNet::Socks::read( G::ReadWrite & io )
90 {
91 char buffer[8] ;
92 ssize_t rc = io.read( buffer , sizeof(buffer) ) ;
93 if( rc == 0 )
94 {
95 throw SocksError( "disconnected" ) ;
96 }
97 else if( rc == -1 && !io.eWouldBlock() )
98 {
99 throw SocksError( "socket read error" ) ;
100 }
101 else if( rc < 0 )
102 {
103 return false ; // go again
104 }
105 else
106 {
107 G_ASSERT( rc >= 1 && rc <= 8 ) ;
108 m_response.append( buffer , static_cast<size_t>(rc) ) ;
109 }
110
111 if( m_response.size() >= 8U )
112 {
113 G_ASSERT( m_response.size() == 8U ) ;
114 if( m_response[0] != 0 )
115 {
116 throw SocksError( "invalid response" ) ;
117 }
118 else if( m_response[1] != 'Z' )
119 {
120 throw SocksError( "request rejected" ) ;
121 }
122 return true ;
123 }
124 else
125 {
126 return false ;
127 }
128 }
129
130 /// \file gsocks.cpp
G::ReadWrite
An abstract interface for reading and writing from a non-blocking i/o channel.
Definition: greadwrite.h:49
G::ReadWrite::write
virtual ssize_type write(const char *buf, size_type len)=0
Sends data.
GNet::Location::socks
bool socks() const
Returns true if a socks location.
Definition: glocation.cpp:180
GNet::Socks::send
bool send(G::ReadWrite &)
Sends the connect-request pdu. Returns true if fully sent.
Definition: gsocks.cpp:63
GNet::Socks::read
bool read(G::ReadWrite &)
Reads the response.
Definition: gsocks.cpp:89
G::ReadWrite::eWouldBlock
virtual bool eWouldBlock()=0
See read() and write().
G::ReadWrite::read
virtual ssize_type read(char *buffer, size_type buffer_length)=0
Reads data.
GNet::Socks::Socks
Socks(const Location &)
Constructor.
Definition: gsocks.cpp:25
GNet::Location
A class that holds a host/service name pair and the preferred address family (if any), and also the results of a name-to-address lookup, ie.
Definition: glocation.h:50
gassert.h
GNet::Location::socksFarHost
std::string socksFarHost() const
Returns the port for the socks far server.
Definition: glocation.cpp:190
GNet::Address::validPort
static bool validPort(unsigned int n)
Returns true if the port number is within the valid range.
Definition: gaddress_ipv4.cpp:174
GNet::Location::socksFarPort
unsigned int socksFarPort() const
Returns the port number for the socks far server.
Definition: glocation.cpp:185
gsocks.h