mirror of
https://github.com/RetroShare/RetroShare.git
synced 2024-12-28 17:09:34 -05:00
detached proxy negociation code from pqisslproxy so as to use it in FriendServer as well
This commit is contained in:
parent
896762b948
commit
2456dbb2a0
@ -127,9 +127,6 @@ bool FsClient::sendItem(const std::string& address,uint16_t port,RsItem *item,st
|
|||||||
RsSerialiser *rss = new RsSerialiser(); // deleted by ~pqistreamer()
|
RsSerialiser *rss = new RsSerialiser(); // deleted by ~pqistreamer()
|
||||||
rss->addSerialType(fss);
|
rss->addSerialType(fss);
|
||||||
|
|
||||||
// FsSerializer().serialise(item,data,&size);
|
|
||||||
// write(CreateSocket,data,size); // shouldn't we use the pqistreamer in R/W mode instead?
|
|
||||||
|
|
||||||
RsFdBinInterface *bio = new RsFdBinInterface(CreateSocket,true); // deleted by ~pqistreamer()
|
RsFdBinInterface *bio = new RsFdBinInterface(CreateSocket,true); // deleted by ~pqistreamer()
|
||||||
|
|
||||||
pqithreadstreamer p(this,rss,RsPeerId(),bio,BIN_FLAGS_READABLE | BIN_FLAGS_WRITEABLE | BIN_FLAGS_NO_CLOSE);
|
pqithreadstreamer p(this,rss,RsPeerId(),bio,BIN_FLAGS_READABLE | BIN_FLAGS_WRITEABLE | BIN_FLAGS_NO_CLOSE);
|
||||||
|
@ -399,6 +399,7 @@ HEADERS += pqi/authssl.h \
|
|||||||
pqi/pqissl.h \
|
pqi/pqissl.h \
|
||||||
pqi/pqissllistener.h \
|
pqi/pqissllistener.h \
|
||||||
pqi/pqisslpersongrp.h \
|
pqi/pqisslpersongrp.h \
|
||||||
|
pqi/pqiproxy.h \
|
||||||
pqi/pqisslproxy.h \
|
pqi/pqisslproxy.h \
|
||||||
pqi/pqistore.h \
|
pqi/pqistore.h \
|
||||||
pqi/pqistreamer.h \
|
pqi/pqistreamer.h \
|
||||||
@ -571,6 +572,7 @@ SOURCES += pqi/authgpg.cc \
|
|||||||
pqi/pqissl.cc \
|
pqi/pqissl.cc \
|
||||||
pqi/pqissllistener.cc \
|
pqi/pqissllistener.cc \
|
||||||
pqi/pqisslpersongrp.cc \
|
pqi/pqisslpersongrp.cc \
|
||||||
|
pqi/pqiproxy.cc \
|
||||||
pqi/pqisslproxy.cc \
|
pqi/pqisslproxy.cc \
|
||||||
pqi/pqistore.cc \
|
pqi/pqistore.cc \
|
||||||
pqi/pqistreamer.cc \
|
pqi/pqistreamer.cc \
|
||||||
|
467
libretroshare/src/pqi/pqiproxy.cc
Normal file
467
libretroshare/src/pqi/pqiproxy.cc
Normal file
@ -0,0 +1,467 @@
|
|||||||
|
#include "util/rsdebug.h"
|
||||||
|
#include "util/rsnet.h"
|
||||||
|
|
||||||
|
#include "pqi/pqiproxy.h"
|
||||||
|
|
||||||
|
//#define PROXY_DEBUG 1
|
||||||
|
|
||||||
|
int pqiproxyconnection::proxy_negotiate_connection(int sockfd)
|
||||||
|
{
|
||||||
|
int ret = 0;
|
||||||
|
switch(mProxyState)
|
||||||
|
{
|
||||||
|
case PROXY_STATE_INIT:
|
||||||
|
ret = Proxy_Send_Method(sockfd); // checks basic conn, sends Method when able.
|
||||||
|
break;
|
||||||
|
|
||||||
|
case PROXY_STATE_WAITING_METHOD_RESPONSE:
|
||||||
|
ret = Proxy_Send_Address(sockfd); // waits for Method Response, send Address when able.
|
||||||
|
break;
|
||||||
|
|
||||||
|
case PROXY_STATE_WAITING_SOCKS_RESPONSE:
|
||||||
|
ret = Proxy_Connection_Complete(sockfd); // wait for ACK.
|
||||||
|
break;
|
||||||
|
|
||||||
|
case PROXY_STATE_CONNECTION_COMPLETE:
|
||||||
|
|
||||||
|
#ifdef PROXY_DEBUG
|
||||||
|
std::cerr << "pqisslproxy::Basic_Connection_Complete() COMPLETED";
|
||||||
|
std::cerr << std::endl;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
case PROXY_STATE_FAILED:
|
||||||
|
|
||||||
|
#ifdef PROXY_DEBUG
|
||||||
|
std::cerr << "pqisslproxy::Basic_Connection_Complete() FAILED";
|
||||||
|
std::cerr << std::endl;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef PROXY_DEBUG
|
||||||
|
std::cerr << "pqisslproxy::Basic_Connection_Complete() IN PROGRESS";
|
||||||
|
std::cerr << std::endl;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// In Progress.
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int pqiproxyconnection::Proxy_Send_Method(int sockfd)
|
||||||
|
{
|
||||||
|
|
||||||
|
#ifdef PROXY_DEBUG
|
||||||
|
std::cerr << "pqisslproxy::Proxy_Send_Method() Basic complete, sending Method";
|
||||||
|
std::cerr << std::endl;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* send hello to proxy server */
|
||||||
|
char method_hello_data[3] = { 0x05, 0x01, 0x00 }; // [ Ver | nMethods (1) | No Auth Method ]
|
||||||
|
|
||||||
|
int sent = send(sockfd, method_hello_data, 3, 0);
|
||||||
|
if (sent != 3)
|
||||||
|
{
|
||||||
|
|
||||||
|
#ifdef PROXY_DEBUG
|
||||||
|
std::cerr << "pqisslproxy::Proxy_Send_Method() Send Failure";
|
||||||
|
std::cerr << std::endl;
|
||||||
|
#endif
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef PROXY_DEBUG
|
||||||
|
std::cerr << "pqisslproxy::Proxy_Send_Method() Send Method Okay";
|
||||||
|
std::cerr << std::endl;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
mProxyState = PROXY_STATE_WAITING_METHOD_RESPONSE;
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int pqiproxyconnection::Proxy_Method_Response(int sockfd)
|
||||||
|
{
|
||||||
|
|
||||||
|
#ifdef PROXY_DEBUG
|
||||||
|
std::cerr << "pqisslproxy::Proxy_Method_Response()";
|
||||||
|
std::cerr << std::endl;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* get response from proxy server */
|
||||||
|
|
||||||
|
char method_response[2];
|
||||||
|
|
||||||
|
/*
|
||||||
|
first it was:
|
||||||
|
|
||||||
|
int recvd = recv(sockfd, method_response, 2, MSG_WAITALL);
|
||||||
|
|
||||||
|
this does not work on windows, because the socket is in nonblocking mode
|
||||||
|
the winsock reference says about the recv function and MSG_WAITALL:
|
||||||
|
|
||||||
|
"Note that if the underlying transport does not support MSG_WAITALL,
|
||||||
|
or if the socket is in a non-blocking mode, then this call will fail with WSAEOPNOTSUPP."
|
||||||
|
|
||||||
|
now it is a two step process:
|
||||||
|
|
||||||
|
int recvd = recv(sockfd, method_response, 2, MSG_PEEK); // test how many bytes are in the input queue
|
||||||
|
if (enaugh bytes available){
|
||||||
|
recvd = recv(sockfd, method_response, 2, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
this does not work on windows:
|
||||||
|
if ((recvd == -1) && (errno == EAGAIN)) return TRY_AGAIN_LATER;
|
||||||
|
|
||||||
|
instead have to do:
|
||||||
|
if ((recvd == -1) && (WSAGetLastError() == WSAEWOULDBLOCK)) return TRY_AGAIN_LATER;
|
||||||
|
*/
|
||||||
|
|
||||||
|
// test how many bytes can be read from the queue
|
||||||
|
int recvd = recv(sockfd, method_response, 2, MSG_PEEK);
|
||||||
|
if (recvd != 2)
|
||||||
|
{
|
||||||
|
#ifdef WINDOWS_SYS
|
||||||
|
if ((recvd == -1) && (WSAGetLastError() == WSAEWOULDBLOCK))
|
||||||
|
{
|
||||||
|
#ifdef PROXY_DEBUG
|
||||||
|
std::cerr << "pqisslproxy::Proxy_Method_Response() waiting for more data (windows)";
|
||||||
|
std::cerr << std::endl;
|
||||||
|
#endif
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
if ((recvd == -1) && (errno == EAGAIN))
|
||||||
|
{
|
||||||
|
|
||||||
|
#ifdef PROXY_DEBUG
|
||||||
|
std::cerr << "pqisslproxy::Proxy_Method_Response() EAGAIN";
|
||||||
|
std::cerr << std::endl;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
else if (recvd == -1)
|
||||||
|
{
|
||||||
|
#ifdef PROXY_DEBUG
|
||||||
|
std::cerr << "pqisslproxy::Proxy_Method_Response() recv error peek";
|
||||||
|
std::cerr << std::endl;
|
||||||
|
#endif
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
#ifdef PROXY_DEBUG
|
||||||
|
std::cerr << "pqisslproxy::Proxy_Method_Response() waiting for more data";
|
||||||
|
std::cerr << std::endl;
|
||||||
|
#endif
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// read the bytes
|
||||||
|
recvd = recv(sockfd, method_response, 2, 0);
|
||||||
|
if (recvd != 2)
|
||||||
|
{
|
||||||
|
#ifdef PROXY_DEBUG
|
||||||
|
std::cerr << "pqisslproxy::Proxy_Method_Response() recv error";
|
||||||
|
std::cerr << std::endl;
|
||||||
|
#endif
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// does it make sense?
|
||||||
|
if (method_response[0] != 0x05)
|
||||||
|
{
|
||||||
|
|
||||||
|
// Error.
|
||||||
|
#ifdef PROXY_DEBUG
|
||||||
|
std::cerr << "pqisslproxy::Proxy_Method_Response() Error response[0] != 0x05. Is: ";
|
||||||
|
std::cerr << (uint32_t) method_response[0];
|
||||||
|
std::cerr << std::endl;
|
||||||
|
#endif
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (method_response[1] != 0x00)
|
||||||
|
{
|
||||||
|
|
||||||
|
#ifdef PROXY_DEBUG
|
||||||
|
std::cerr << "pqisslproxy::Proxy_Method_Response() Error response[0] != 0x00. Is: ";
|
||||||
|
std::cerr << (uint32_t) method_response[1];
|
||||||
|
std::cerr << std::endl;
|
||||||
|
#endif
|
||||||
|
// Error.
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef PROXY_DEBUG
|
||||||
|
std::cerr << "pqisslproxy::Proxy_Method_Response() Response Okay";
|
||||||
|
std::cerr << std::endl;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
#define MAX_SOCKS_REQUEST_LEN 262 // 4 + 1 + 255 + 2.
|
||||||
|
|
||||||
|
int pqiproxyconnection::Proxy_Send_Address(int sockfd)
|
||||||
|
{
|
||||||
|
|
||||||
|
#ifdef PROXY_DEBUG
|
||||||
|
std::cerr << "pqisslproxy::Proxy_Send_Address() Checking Method Response";
|
||||||
|
std::cerr << std::endl;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Check Method Response.
|
||||||
|
int ret = Proxy_Method_Response(sockfd);
|
||||||
|
if (ret != 1)
|
||||||
|
{
|
||||||
|
return ret; // Method Response not complete.
|
||||||
|
}
|
||||||
|
|
||||||
|
char socks_request[MAX_SOCKS_REQUEST_LEN] =
|
||||||
|
{ 0x05, // SOCKS VERSION.
|
||||||
|
0x01, // CONNECT (Tor doesn't support BIND or UDP).
|
||||||
|
0x00, // RESERVED.
|
||||||
|
0x03, // ADDRESS TYPE (Domain Name)
|
||||||
|
0x00, // Length of Domain name... the rest is variable so can't hard code it!
|
||||||
|
};
|
||||||
|
|
||||||
|
/* get the length of the domain name, pack so we can't overflow uint8_t */
|
||||||
|
uint8_t len = mDomainAddress.length();
|
||||||
|
socks_request[4] = len;
|
||||||
|
for(int i = 0; i < len; i++)
|
||||||
|
{
|
||||||
|
socks_request[5 + i] = mDomainAddress[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
/* now add the port, being careful with packing */
|
||||||
|
uint16_t net_port = htons(mRemotePort);
|
||||||
|
socks_request[5 + len] = ((uint8_t *) &net_port)[0];
|
||||||
|
socks_request[5 + len + 1] = ((uint8_t *) &net_port)[1];
|
||||||
|
|
||||||
|
int pkt_len = 5 + len + 2;
|
||||||
|
|
||||||
|
#ifdef PROXY_DEBUG
|
||||||
|
std::cerr << "pqisslproxy::Proxy_Send_Address() Sending String: ";
|
||||||
|
for(int i = 0; i < pkt_len; i++)
|
||||||
|
std::cerr << (uint32_t) socks_request[i];
|
||||||
|
std::cerr << std::endl;
|
||||||
|
#endif
|
||||||
|
int sent = send(sockfd, socks_request, pkt_len, 0);
|
||||||
|
if (sent != pkt_len)
|
||||||
|
{
|
||||||
|
|
||||||
|
#ifdef PROXY_DEBUG
|
||||||
|
std::cerr << "pqisslproxy::Proxy_Send_Address() Send Error";
|
||||||
|
std::cerr << std::endl;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef PROXY_DEBUG
|
||||||
|
std::cerr << "pqisslproxy::Proxy_Send_Address() Sent Okay";
|
||||||
|
std::cerr << std::endl;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
mProxyState = PROXY_STATE_WAITING_SOCKS_RESPONSE;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int pqiproxyconnection::Proxy_Connection_Complete(int sockfd)
|
||||||
|
{
|
||||||
|
/* get response from proxy server */
|
||||||
|
/* response is similar format to request - with variable length data */
|
||||||
|
|
||||||
|
char socks_response[MAX_SOCKS_REQUEST_LEN];
|
||||||
|
|
||||||
|
// test how many bytes can be read
|
||||||
|
int recvd = recv(sockfd, socks_response, 5, MSG_PEEK);
|
||||||
|
if (recvd != 5)
|
||||||
|
{
|
||||||
|
#ifdef WINDOWS_SYS
|
||||||
|
if ((recvd == -1) && (WSAGetLastError() == WSAEWOULDBLOCK))
|
||||||
|
{
|
||||||
|
#ifdef PROXY_DEBUG
|
||||||
|
std::cerr << "pqisslproxy::Proxy_Connection_Complete() waiting for more data (windows)";
|
||||||
|
std::cerr << std::endl;
|
||||||
|
#endif
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
if ((recvd == -1) && (errno == EAGAIN))
|
||||||
|
{
|
||||||
|
#ifdef PROXY_DEBUG
|
||||||
|
std::cerr << "pqisslproxy::Proxy_Connection_Complete() EAGAIN";
|
||||||
|
std::cerr << std::endl;
|
||||||
|
#endif
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
else if (recvd == -1)
|
||||||
|
{
|
||||||
|
#ifdef PROXY_DEBUG
|
||||||
|
std::cerr << "pqisslproxy::Proxy_Connection_Complete() recv error peek";
|
||||||
|
std::cerr << std::endl;
|
||||||
|
#endif
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
#ifdef PROXY_DEBUG
|
||||||
|
std::cerr << "pqisslproxy::Proxy_Connection_Complete() waiting for more data";
|
||||||
|
std::cerr << std::endl;
|
||||||
|
#endif
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// read the bytes
|
||||||
|
recvd = recv(sockfd, socks_response, 5, 0);
|
||||||
|
if (recvd != 5)
|
||||||
|
{
|
||||||
|
#ifdef PROXY_DEBUG
|
||||||
|
std::cerr << "pqisslproxy::Proxy_Connection_Complete() recv error";
|
||||||
|
std::cerr << std::endl;
|
||||||
|
#endif
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// error checking.
|
||||||
|
if (socks_response[0] != 0x05)
|
||||||
|
{
|
||||||
|
|
||||||
|
#ifdef PROXY_DEBUG
|
||||||
|
std::cerr << "pqisslproxy::Proxy_Connection_Complete() ERROR socks_response[0] != 0x05. is: ";
|
||||||
|
std::cerr << (uint32_t) socks_response[0];
|
||||||
|
std::cerr << std::endl;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// error.
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (socks_response[1] != 0x00)
|
||||||
|
{
|
||||||
|
|
||||||
|
#ifdef PROXY_DEBUG
|
||||||
|
std::cerr << "pqisslproxy::Proxy_Connection_Complete() ERROR socks_response[1] != 0x00. is: ";
|
||||||
|
std::cerr << (uint32_t) socks_response[1];
|
||||||
|
std::cerr << std::endl;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// connection failed.
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int address_bytes = 0;
|
||||||
|
switch(socks_response[3]) // Address Type.
|
||||||
|
{
|
||||||
|
case 0x01:
|
||||||
|
// IPv4 4 address bytes.
|
||||||
|
address_bytes = 4;
|
||||||
|
#ifdef PROXY_DEBUG
|
||||||
|
std::cerr << "pqisslproxy::Proxy_Connection_Complete() IPv4 Address Type";
|
||||||
|
std::cerr << std::endl;
|
||||||
|
#endif
|
||||||
|
break;
|
||||||
|
case 0x04:
|
||||||
|
// IPv6 16 address bytes.
|
||||||
|
address_bytes = 16;
|
||||||
|
#ifdef PROXY_DEBUG
|
||||||
|
std::cerr << "pqisslproxy::Proxy_Connection_Complete() IPv6 Address Type";
|
||||||
|
std::cerr << std::endl;
|
||||||
|
#endif
|
||||||
|
break;
|
||||||
|
case 0x03:
|
||||||
|
// Variable address bytes - specified in next byte.
|
||||||
|
address_bytes = 1 + socks_response[4];
|
||||||
|
#ifdef PROXY_DEBUG
|
||||||
|
std::cerr << "pqisslproxy::Proxy_Connection_Complete() Domain Address Type. len: " << address_bytes;
|
||||||
|
std::cerr << std::endl;
|
||||||
|
#endif
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
// unknown error.
|
||||||
|
#ifdef PROXY_DEBUG
|
||||||
|
std::cerr << "pqisslproxy::Proxy_Connection_Complete() ERROR Unknown Address Type";
|
||||||
|
std::cerr << std::endl;
|
||||||
|
#endif
|
||||||
|
return -1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// test how many bytes can be read
|
||||||
|
recvd = recv(sockfd, &(socks_response[5]), address_bytes + 1, MSG_PEEK); // address_bytes - 1 + 2...
|
||||||
|
if (recvd != address_bytes + 1)
|
||||||
|
{
|
||||||
|
#ifdef WINDOWS_SYS
|
||||||
|
if((recvd == -1) && (WSAGetLastError() == WSAEWOULDBLOCK))
|
||||||
|
{
|
||||||
|
#ifdef PROXY_DEBUG
|
||||||
|
std::cerr << "pqisslproxy::Proxy_Connection_Complete() waiting for more data(2) (windows)";
|
||||||
|
std::cerr << std::endl;
|
||||||
|
#endif
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
if ((recvd == -1) && (errno == EAGAIN))
|
||||||
|
{
|
||||||
|
#ifdef PROXY_DEBUG
|
||||||
|
std::cerr << "pqisslproxy::Proxy_Connection_Complete() ERROR EAGAIN at end.";
|
||||||
|
std::cerr << std::endl;
|
||||||
|
#endif
|
||||||
|
// Waiting - shouldn't happen.
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
else if (recvd == -1)
|
||||||
|
{
|
||||||
|
#ifdef PROXY_DEBUG
|
||||||
|
std::cerr << "pqisslproxy::Proxy_Connection_Complete() ERROR recving(2)";
|
||||||
|
std::cerr << std::endl;
|
||||||
|
#endif
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
#ifdef PROXY_DEBUG
|
||||||
|
std::cerr << "pqisslproxy::Proxy_Connection_Complete() waiting for more data(2)";
|
||||||
|
std::cerr << std::endl;
|
||||||
|
#endif
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// read the bytes
|
||||||
|
recvd = recv(sockfd, &(socks_response[5]), address_bytes + 1, 0); // address_bytes - 1 + 2...
|
||||||
|
if (recvd != address_bytes + 1)
|
||||||
|
{
|
||||||
|
#ifdef PROXY_DEBUG
|
||||||
|
std::cerr << "pqisslproxy::Proxy_Connection_Complete() recv error (2)";
|
||||||
|
std::cerr << std::endl;
|
||||||
|
#endif
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef PROXY_DEBUG
|
||||||
|
std::cerr << "pqisslproxy::Proxy_Connection_Complete() Received String: ";
|
||||||
|
for(int i = 0; i < 4 + address_bytes + 2; i++)
|
||||||
|
std::cerr << (uint32_t) socks_response[i];
|
||||||
|
std::cerr << std::endl;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// should print address.
|
||||||
|
// if we get here - connection is good!.
|
||||||
|
mProxyState = PROXY_STATE_CONNECTION_COMPLETE;
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
70
libretroshare/src/pqi/pqiproxy.h
Normal file
70
libretroshare/src/pqi/pqiproxy.h
Normal file
@ -0,0 +1,70 @@
|
|||||||
|
/*******************************************************************************
|
||||||
|
* libretroshare/src/pqi: pqiproxy.h *
|
||||||
|
* *
|
||||||
|
* libretroshare: retroshare core library *
|
||||||
|
* *
|
||||||
|
* Copyright 2004-2013 by Robert Fernie. *
|
||||||
|
* Copyright 2004-2021 by retroshare team <retroshare.project@gmail.com> *
|
||||||
|
* *
|
||||||
|
* This program is free software: you can redistribute it and/or modify *
|
||||||
|
* it under the terms of the GNU Lesser General Public License as *
|
||||||
|
* published by the Free Software Foundation, either version 3 of the *
|
||||||
|
* License, or (at your option) any later version. *
|
||||||
|
* *
|
||||||
|
* This program is distributed in the hope that it will be useful, *
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
||||||
|
* GNU Lesser General Public License for more details. *
|
||||||
|
* *
|
||||||
|
* You should have received a copy of the GNU Lesser General Public License *
|
||||||
|
* along with this program. If not, see <https://www.gnu.org/licenses/>. *
|
||||||
|
* *
|
||||||
|
*******************************************************************************/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
class pqiproxyconnection
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
enum ProxyState: uint8_t {
|
||||||
|
PROXY_STATE_FAILED = 0x00,
|
||||||
|
PROXY_STATE_INIT = 0x01,
|
||||||
|
PROXY_STATE_WAITING_METHOD_RESPONSE = 0x02,
|
||||||
|
PROXY_STATE_WAITING_SOCKS_RESPONSE = 0x03,
|
||||||
|
PROXY_STATE_CONNECTION_COMPLETE = 0x04
|
||||||
|
};
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief proxy_negotiate_connection
|
||||||
|
* Negotiate the connection with the proxy that is connected with openned socket sockfd. The caller needs to
|
||||||
|
* connect the socket *before* trying to call proxy_negotiate_connection(). The function must be called as many times as
|
||||||
|
* necessary until it returns 1 (success) or -1 (error) in which case the socket needs to be closed.
|
||||||
|
* \return
|
||||||
|
* -1 : error. The socket must be closed as soon as possible.
|
||||||
|
* 0 : in progress. The function needs to be called again asap.
|
||||||
|
* 1 : proxy connection is fully negociated. Client can send data to the socket.
|
||||||
|
*/
|
||||||
|
int proxy_negotiate_connection(int sockfd);
|
||||||
|
|
||||||
|
void setRemotePort(uint16_t v) { mRemotePort = v; }
|
||||||
|
void setRemoteAddress(const std::string& s) { mDomainAddress = s; }
|
||||||
|
|
||||||
|
ProxyState proxyConnectionState() const { return mProxyState ; }
|
||||||
|
|
||||||
|
void proxy_init() { mProxyState = PROXY_STATE_INIT; }
|
||||||
|
private:
|
||||||
|
|
||||||
|
ProxyState mProxyState;
|
||||||
|
|
||||||
|
std::string mDomainAddress;
|
||||||
|
uint16_t mRemotePort;
|
||||||
|
|
||||||
|
// These are the internal steps in setting up the Proxy Connection.
|
||||||
|
int Proxy_Send_Method(int sockfd);
|
||||||
|
int Proxy_Method_Response(int sockfd);
|
||||||
|
int Proxy_Send_Address(int sockfd);
|
||||||
|
int Proxy_Connection_Complete(int sockfd);
|
||||||
|
};
|
||||||
|
|
@ -38,12 +38,6 @@ static struct RsLog::logInfo pqisslproxyzoneInfo = {RsLog::Default, "pqisslproxy
|
|||||||
// #define PROXY_DEBUG 1
|
// #define PROXY_DEBUG 1
|
||||||
// #define PROXY_DEBUG_LOG 1
|
// #define PROXY_DEBUG_LOG 1
|
||||||
|
|
||||||
#define PROXY_STATE_FAILED 0
|
|
||||||
#define PROXY_STATE_INIT 1
|
|
||||||
#define PROXY_STATE_WAITING_METHOD_RESPONSE 2
|
|
||||||
#define PROXY_STATE_WAITING_SOCKS_RESPONSE 3
|
|
||||||
#define PROXY_STATE_CONNECTION_COMPLETE 4
|
|
||||||
|
|
||||||
pqisslproxy::pqisslproxy(pqissllistener *l, PQInterface *parent, p3LinkMgr *lm)
|
pqisslproxy::pqisslproxy(pqissllistener *l, PQInterface *parent, p3LinkMgr *lm)
|
||||||
:pqissl(l, parent, lm)
|
:pqissl(l, parent, lm)
|
||||||
{
|
{
|
||||||
@ -74,7 +68,7 @@ int pqisslproxy::Initiate_Connection()
|
|||||||
rslog(RSL_DEBUG_BASIC, pqisslproxyzone,
|
rslog(RSL_DEBUG_BASIC, pqisslproxyzone,
|
||||||
"pqisslproxy::Initiate_Connection() Connection to Proxy");
|
"pqisslproxy::Initiate_Connection() Connection to Proxy");
|
||||||
/* init proxy state */
|
/* init proxy state */
|
||||||
mProxyState = PROXY_STATE_INIT;
|
proxy_init();
|
||||||
|
|
||||||
/* call standard Init_Conn() */
|
/* call standard Init_Conn() */
|
||||||
return pqissl::Initiate_Connection();
|
return pqissl::Initiate_Connection();
|
||||||
@ -98,486 +92,18 @@ int pqisslproxy::Basic_Connection_Complete()
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
int ret = 0;
|
int ret;
|
||||||
switch(mProxyState)
|
|
||||||
{
|
|
||||||
case PROXY_STATE_INIT:
|
|
||||||
ret = Proxy_Send_Method(); // checks basic conn, sends Method when able.
|
|
||||||
break;
|
|
||||||
|
|
||||||
case PROXY_STATE_WAITING_METHOD_RESPONSE:
|
if(proxyConnectionState() == PROXY_STATE_INIT && 1!=(ret=pqissl::Basic_Connection_Complete()))
|
||||||
ret = Proxy_Send_Address(); // waits for Method Response, send Address when able.
|
return ret; // basic connection not complete.
|
||||||
break;
|
|
||||||
|
|
||||||
case PROXY_STATE_WAITING_SOCKS_RESPONSE:
|
ret = proxy_negotiate_connection(sockfd);
|
||||||
ret = Proxy_Connection_Complete(); // wait for ACK.
|
|
||||||
break;
|
|
||||||
|
|
||||||
case PROXY_STATE_CONNECTION_COMPLETE:
|
if(ret < 0)
|
||||||
|
reset_locked();
|
||||||
|
|
||||||
#ifdef PROXY_DEBUG
|
return ret;
|
||||||
std::cerr << "pqisslproxy::Basic_Connection_Complete() COMPLETED";
|
}
|
||||||
std::cerr << std::endl;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
return 1;
|
|
||||||
|
|
||||||
case PROXY_STATE_FAILED:
|
|
||||||
|
|
||||||
#ifdef PROXY_DEBUG
|
|
||||||
std::cerr << "pqisslproxy::Basic_Connection_Complete() FAILED";
|
|
||||||
std::cerr << std::endl;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
reset_locked();
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ret < 0)
|
|
||||||
{
|
|
||||||
|
|
||||||
#ifdef PROXY_DEBUG
|
|
||||||
std::cerr << "pqisslproxy::Basic_Connection_Complete() FAILED(2)";
|
|
||||||
std::cerr << std::endl;
|
|
||||||
#endif
|
|
||||||
reset_locked();
|
|
||||||
return -1; // FAILURE.
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
#ifdef PROXY_DEBUG
|
|
||||||
std::cerr << "pqisslproxy::Basic_Connection_Complete() IN PROGRESS";
|
|
||||||
std::cerr << std::endl;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// In Progress.
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
int pqisslproxy::Proxy_Send_Method()
|
|
||||||
{
|
|
||||||
|
|
||||||
#ifdef PROXY_DEBUG
|
|
||||||
std::cerr << "pqisslproxy::Proxy_Send_Method() Checking pqissl::Basic_Connection_Complete()";
|
|
||||||
std::cerr << std::endl;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
int ret = pqissl::Basic_Connection_Complete();
|
|
||||||
if (ret != 1)
|
|
||||||
{
|
|
||||||
return ret; // basic connection not complete.
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef PROXY_DEBUG
|
|
||||||
std::cerr << "pqisslproxy::Proxy_Send_Method() Basic complete, sending Method";
|
|
||||||
std::cerr << std::endl;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* send hello to proxy server */
|
|
||||||
char method_hello_data[3] = { 0x05, 0x01, 0x00 }; // [ Ver | nMethods (1) | No Auth Method ]
|
|
||||||
|
|
||||||
int sent = send(sockfd, method_hello_data, 3, 0);
|
|
||||||
if (sent != 3)
|
|
||||||
{
|
|
||||||
|
|
||||||
#ifdef PROXY_DEBUG
|
|
||||||
std::cerr << "pqisslproxy::Proxy_Send_Method() Send Failure";
|
|
||||||
std::cerr << std::endl;
|
|
||||||
#endif
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef PROXY_DEBUG
|
|
||||||
std::cerr << "pqisslproxy::Proxy_Send_Method() Send Method Okay";
|
|
||||||
std::cerr << std::endl;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
mProxyState = PROXY_STATE_WAITING_METHOD_RESPONSE;
|
|
||||||
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
int pqisslproxy::Proxy_Method_Response()
|
|
||||||
{
|
|
||||||
|
|
||||||
#ifdef PROXY_DEBUG
|
|
||||||
std::cerr << "pqisslproxy::Proxy_Method_Response()";
|
|
||||||
std::cerr << std::endl;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* get response from proxy server */
|
|
||||||
|
|
||||||
char method_response[2];
|
|
||||||
|
|
||||||
/*
|
|
||||||
first it was:
|
|
||||||
|
|
||||||
int recvd = recv(sockfd, method_response, 2, MSG_WAITALL);
|
|
||||||
|
|
||||||
this does not work on windows, because the socket is in nonblocking mode
|
|
||||||
the winsock reference says about the recv function and MSG_WAITALL:
|
|
||||||
|
|
||||||
"Note that if the underlying transport does not support MSG_WAITALL,
|
|
||||||
or if the socket is in a non-blocking mode, then this call will fail with WSAEOPNOTSUPP."
|
|
||||||
|
|
||||||
now it is a two step process:
|
|
||||||
|
|
||||||
int recvd = recv(sockfd, method_response, 2, MSG_PEEK); // test how many bytes are in the input queue
|
|
||||||
if (enaugh bytes available){
|
|
||||||
recvd = recv(sockfd, method_response, 2, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
this does not work on windows:
|
|
||||||
if ((recvd == -1) && (errno == EAGAIN)) return TRY_AGAIN_LATER;
|
|
||||||
|
|
||||||
instead have to do:
|
|
||||||
if ((recvd == -1) && (WSAGetLastError() == WSAEWOULDBLOCK)) return TRY_AGAIN_LATER;
|
|
||||||
*/
|
|
||||||
|
|
||||||
// test how many bytes can be read from the queue
|
|
||||||
int recvd = recv(sockfd, method_response, 2, MSG_PEEK);
|
|
||||||
if (recvd != 2)
|
|
||||||
{
|
|
||||||
#ifdef WINDOWS_SYS
|
|
||||||
if ((recvd == -1) && (WSAGetLastError() == WSAEWOULDBLOCK))
|
|
||||||
{
|
|
||||||
#ifdef PROXY_DEBUG
|
|
||||||
std::cerr << "pqisslproxy::Proxy_Method_Response() waiting for more data (windows)";
|
|
||||||
std::cerr << std::endl;
|
|
||||||
#endif
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
if ((recvd == -1) && (errno == EAGAIN))
|
|
||||||
{
|
|
||||||
|
|
||||||
#ifdef PROXY_DEBUG
|
|
||||||
std::cerr << "pqisslproxy::Proxy_Method_Response() EAGAIN";
|
|
||||||
std::cerr << std::endl;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
else if (recvd == -1)
|
|
||||||
{
|
|
||||||
#ifdef PROXY_DEBUG
|
|
||||||
std::cerr << "pqisslproxy::Proxy_Method_Response() recv error peek";
|
|
||||||
std::cerr << std::endl;
|
|
||||||
#endif
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
#ifdef PROXY_DEBUG
|
|
||||||
std::cerr << "pqisslproxy::Proxy_Method_Response() waiting for more data";
|
|
||||||
std::cerr << std::endl;
|
|
||||||
#endif
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// read the bytes
|
|
||||||
recvd = recv(sockfd, method_response, 2, 0);
|
|
||||||
if (recvd != 2)
|
|
||||||
{
|
|
||||||
#ifdef PROXY_DEBUG
|
|
||||||
std::cerr << "pqisslproxy::Proxy_Method_Response() recv error";
|
|
||||||
std::cerr << std::endl;
|
|
||||||
#endif
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
// does it make sense?
|
|
||||||
if (method_response[0] != 0x05)
|
|
||||||
{
|
|
||||||
|
|
||||||
// Error.
|
|
||||||
#ifdef PROXY_DEBUG
|
|
||||||
std::cerr << "pqisslproxy::Proxy_Method_Response() Error response[0] != 0x05. Is: ";
|
|
||||||
std::cerr << (uint32_t) method_response[0];
|
|
||||||
std::cerr << std::endl;
|
|
||||||
#endif
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (method_response[1] != 0x00)
|
|
||||||
{
|
|
||||||
|
|
||||||
#ifdef PROXY_DEBUG
|
|
||||||
std::cerr << "pqisslproxy::Proxy_Method_Response() Error response[0] != 0x00. Is: ";
|
|
||||||
std::cerr << (uint32_t) method_response[1];
|
|
||||||
std::cerr << std::endl;
|
|
||||||
#endif
|
|
||||||
// Error.
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
#ifdef PROXY_DEBUG
|
|
||||||
std::cerr << "pqisslproxy::Proxy_Method_Response() Response Okay";
|
|
||||||
std::cerr << std::endl;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
#define MAX_SOCKS_REQUEST_LEN 262 // 4 + 1 + 255 + 2.
|
|
||||||
|
|
||||||
int pqisslproxy::Proxy_Send_Address()
|
|
||||||
{
|
|
||||||
|
|
||||||
#ifdef PROXY_DEBUG
|
|
||||||
std::cerr << "pqisslproxy::Proxy_Send_Address() Checking Method Response";
|
|
||||||
std::cerr << std::endl;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// Check Method Response.
|
|
||||||
int ret = Proxy_Method_Response();
|
|
||||||
if (ret != 1)
|
|
||||||
{
|
|
||||||
return ret; // Method Response not complete.
|
|
||||||
}
|
|
||||||
|
|
||||||
char socks_request[MAX_SOCKS_REQUEST_LEN] =
|
|
||||||
{ 0x05, // SOCKS VERSION.
|
|
||||||
0x01, // CONNECT (Tor doesn't support BIND or UDP).
|
|
||||||
0x00, // RESERVED.
|
|
||||||
0x03, // ADDRESS TYPE (Domain Name)
|
|
||||||
0x00, // Length of Domain name... the rest is variable so can't hard code it!
|
|
||||||
};
|
|
||||||
|
|
||||||
/* get the length of the domain name, pack so we can't overflow uint8_t */
|
|
||||||
uint8_t len = mDomainAddress.length();
|
|
||||||
socks_request[4] = len;
|
|
||||||
for(int i = 0; i < len; i++)
|
|
||||||
{
|
|
||||||
socks_request[5 + i] = mDomainAddress[i];
|
|
||||||
}
|
|
||||||
|
|
||||||
/* now add the port, being careful with packing */
|
|
||||||
uint16_t net_port = htons(mRemotePort);
|
|
||||||
socks_request[5 + len] = ((uint8_t *) &net_port)[0];
|
|
||||||
socks_request[5 + len + 1] = ((uint8_t *) &net_port)[1];
|
|
||||||
|
|
||||||
int pkt_len = 5 + len + 2;
|
|
||||||
|
|
||||||
#ifdef PROXY_DEBUG
|
|
||||||
std::cerr << "pqisslproxy::Proxy_Send_Address() Sending String: ";
|
|
||||||
for(int i = 0; i < pkt_len; i++)
|
|
||||||
std::cerr << (uint32_t) socks_request[i];
|
|
||||||
std::cerr << std::endl;
|
|
||||||
#endif
|
|
||||||
int sent = send(sockfd, socks_request, pkt_len, 0);
|
|
||||||
if (sent != pkt_len)
|
|
||||||
{
|
|
||||||
|
|
||||||
#ifdef PROXY_DEBUG
|
|
||||||
std::cerr << "pqisslproxy::Proxy_Send_Address() Send Error";
|
|
||||||
std::cerr << std::endl;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
#ifdef PROXY_DEBUG
|
|
||||||
std::cerr << "pqisslproxy::Proxy_Send_Address() Sent Okay";
|
|
||||||
std::cerr << std::endl;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
mProxyState = PROXY_STATE_WAITING_SOCKS_RESPONSE;
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
int pqisslproxy::Proxy_Connection_Complete()
|
|
||||||
{
|
|
||||||
/* get response from proxy server */
|
|
||||||
/* response is similar format to request - with variable length data */
|
|
||||||
|
|
||||||
char socks_response[MAX_SOCKS_REQUEST_LEN];
|
|
||||||
|
|
||||||
// test how many bytes can be read
|
|
||||||
int recvd = recv(sockfd, socks_response, 5, MSG_PEEK);
|
|
||||||
if (recvd != 5)
|
|
||||||
{
|
|
||||||
#ifdef WINDOWS_SYS
|
|
||||||
if ((recvd == -1) && (WSAGetLastError() == WSAEWOULDBLOCK))
|
|
||||||
{
|
|
||||||
#ifdef PROXY_DEBUG
|
|
||||||
std::cerr << "pqisslproxy::Proxy_Connection_Complete() waiting for more data (windows)";
|
|
||||||
std::cerr << std::endl;
|
|
||||||
#endif
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
if ((recvd == -1) && (errno == EAGAIN))
|
|
||||||
{
|
|
||||||
#ifdef PROXY_DEBUG
|
|
||||||
std::cerr << "pqisslproxy::Proxy_Connection_Complete() EAGAIN";
|
|
||||||
std::cerr << std::endl;
|
|
||||||
#endif
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
else if (recvd == -1)
|
|
||||||
{
|
|
||||||
#ifdef PROXY_DEBUG
|
|
||||||
std::cerr << "pqisslproxy::Proxy_Connection_Complete() recv error peek";
|
|
||||||
std::cerr << std::endl;
|
|
||||||
#endif
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
#ifdef PROXY_DEBUG
|
|
||||||
std::cerr << "pqisslproxy::Proxy_Connection_Complete() waiting for more data";
|
|
||||||
std::cerr << std::endl;
|
|
||||||
#endif
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// read the bytes
|
|
||||||
recvd = recv(sockfd, socks_response, 5, 0);
|
|
||||||
if (recvd != 5)
|
|
||||||
{
|
|
||||||
#ifdef PROXY_DEBUG
|
|
||||||
std::cerr << "pqisslproxy::Proxy_Connection_Complete() recv error";
|
|
||||||
std::cerr << std::endl;
|
|
||||||
#endif
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
// error checking.
|
|
||||||
if (socks_response[0] != 0x05)
|
|
||||||
{
|
|
||||||
|
|
||||||
#ifdef PROXY_DEBUG
|
|
||||||
std::cerr << "pqisslproxy::Proxy_Connection_Complete() ERROR socks_response[0] != 0x05. is: ";
|
|
||||||
std::cerr << (uint32_t) socks_response[0];
|
|
||||||
std::cerr << std::endl;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// error.
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (socks_response[1] != 0x00)
|
|
||||||
{
|
|
||||||
|
|
||||||
#ifdef PROXY_DEBUG
|
|
||||||
std::cerr << "pqisslproxy::Proxy_Connection_Complete() ERROR socks_response[1] != 0x00. is: ";
|
|
||||||
std::cerr << (uint32_t) socks_response[1];
|
|
||||||
std::cerr << std::endl;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// connection failed.
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
int address_bytes = 0;
|
|
||||||
switch(socks_response[3]) // Address Type.
|
|
||||||
{
|
|
||||||
case 0x01:
|
|
||||||
// IPv4 4 address bytes.
|
|
||||||
address_bytes = 4;
|
|
||||||
#ifdef PROXY_DEBUG
|
|
||||||
std::cerr << "pqisslproxy::Proxy_Connection_Complete() IPv4 Address Type";
|
|
||||||
std::cerr << std::endl;
|
|
||||||
#endif
|
|
||||||
break;
|
|
||||||
case 0x04:
|
|
||||||
// IPv6 16 address bytes.
|
|
||||||
address_bytes = 16;
|
|
||||||
#ifdef PROXY_DEBUG
|
|
||||||
std::cerr << "pqisslproxy::Proxy_Connection_Complete() IPv6 Address Type";
|
|
||||||
std::cerr << std::endl;
|
|
||||||
#endif
|
|
||||||
break;
|
|
||||||
case 0x03:
|
|
||||||
// Variable address bytes - specified in next byte.
|
|
||||||
address_bytes = 1 + socks_response[4];
|
|
||||||
#ifdef PROXY_DEBUG
|
|
||||||
std::cerr << "pqisslproxy::Proxy_Connection_Complete() Domain Address Type. len: " << address_bytes;
|
|
||||||
std::cerr << std::endl;
|
|
||||||
#endif
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
// unknown error.
|
|
||||||
#ifdef PROXY_DEBUG
|
|
||||||
std::cerr << "pqisslproxy::Proxy_Connection_Complete() ERROR Unknown Address Type";
|
|
||||||
std::cerr << std::endl;
|
|
||||||
#endif
|
|
||||||
return -1;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// test how many bytes can be read
|
|
||||||
recvd = recv(sockfd, &(socks_response[5]), address_bytes + 1, MSG_PEEK); // address_bytes - 1 + 2...
|
|
||||||
if (recvd != address_bytes + 1)
|
|
||||||
{
|
|
||||||
#ifdef WINDOWS_SYS
|
|
||||||
if((recvd == -1) && (WSAGetLastError() == WSAEWOULDBLOCK))
|
|
||||||
{
|
|
||||||
#ifdef PROXY_DEBUG
|
|
||||||
std::cerr << "pqisslproxy::Proxy_Connection_Complete() waiting for more data(2) (windows)";
|
|
||||||
std::cerr << std::endl;
|
|
||||||
#endif
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
if ((recvd == -1) && (errno == EAGAIN))
|
|
||||||
{
|
|
||||||
#ifdef PROXY_DEBUG
|
|
||||||
std::cerr << "pqisslproxy::Proxy_Connection_Complete() ERROR EAGAIN at end.";
|
|
||||||
std::cerr << std::endl;
|
|
||||||
#endif
|
|
||||||
// Waiting - shouldn't happen.
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
else if (recvd == -1)
|
|
||||||
{
|
|
||||||
#ifdef PROXY_DEBUG
|
|
||||||
std::cerr << "pqisslproxy::Proxy_Connection_Complete() ERROR recving(2)";
|
|
||||||
std::cerr << std::endl;
|
|
||||||
#endif
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
#ifdef PROXY_DEBUG
|
|
||||||
std::cerr << "pqisslproxy::Proxy_Connection_Complete() waiting for more data(2)";
|
|
||||||
std::cerr << std::endl;
|
|
||||||
#endif
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// read the bytes
|
|
||||||
recvd = recv(sockfd, &(socks_response[5]), address_bytes + 1, 0); // address_bytes - 1 + 2...
|
|
||||||
if (recvd != address_bytes + 1)
|
|
||||||
{
|
|
||||||
#ifdef PROXY_DEBUG
|
|
||||||
std::cerr << "pqisslproxy::Proxy_Connection_Complete() recv error (2)";
|
|
||||||
std::cerr << std::endl;
|
|
||||||
#endif
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef PROXY_DEBUG
|
|
||||||
std::cerr << "pqisslproxy::Proxy_Connection_Complete() Received String: ";
|
|
||||||
for(int i = 0; i < 4 + address_bytes + 2; i++)
|
|
||||||
std::cerr << (uint32_t) socks_response[i];
|
|
||||||
std::cerr << std::endl;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// should print address.
|
|
||||||
// if we get here - connection is good!.
|
|
||||||
mProxyState = PROXY_STATE_CONNECTION_COMPLETE;
|
|
||||||
return 1;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
bool pqisslproxy::connect_parameter(uint32_t type, const std::string &value)
|
bool pqisslproxy::connect_parameter(uint32_t type, const std::string &value)
|
||||||
{
|
{
|
||||||
@ -591,7 +117,7 @@ bool pqisslproxy::connect_parameter(uint32_t type, const std::string &value)
|
|||||||
#ifdef PROXY_DEBUG_LOG
|
#ifdef PROXY_DEBUG_LOG
|
||||||
rslog(RSL_WARNING, pqisslproxyzone, out);
|
rslog(RSL_WARNING, pqisslproxyzone, out);
|
||||||
#endif
|
#endif
|
||||||
mDomainAddress = value;
|
setRemoteAddress(value);
|
||||||
#ifdef PROXY_DEBUG
|
#ifdef PROXY_DEBUG
|
||||||
std::cerr << out << std::endl;
|
std::cerr << out << std::endl;
|
||||||
#endif
|
#endif
|
||||||
@ -614,7 +140,7 @@ bool pqisslproxy::connect_parameter(uint32_t type, uint32_t value)
|
|||||||
#ifdef PROXY_DEBUG_LOG
|
#ifdef PROXY_DEBUG_LOG
|
||||||
rslog(RSL_WARNING, pqisslproxyzone, out);
|
rslog(RSL_WARNING, pqisslproxyzone, out);
|
||||||
#endif
|
#endif
|
||||||
mRemotePort = value;
|
setRemotePort(value);
|
||||||
#ifdef PROXY_DEBUG
|
#ifdef PROXY_DEBUG
|
||||||
std::cerr << out << std::endl;
|
std::cerr << out << std::endl;
|
||||||
#endif
|
#endif
|
||||||
|
@ -24,6 +24,7 @@
|
|||||||
|
|
||||||
// operating system specific network header.
|
// operating system specific network header.
|
||||||
#include "pqi/pqinetwork.h"
|
#include "pqi/pqinetwork.h"
|
||||||
|
#include "pqi/pqiproxy.h"
|
||||||
|
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <map>
|
#include <map>
|
||||||
@ -39,40 +40,27 @@
|
|||||||
* fns declared here are different -> all others are identical.
|
* fns declared here are different -> all others are identical.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
class pqisslproxy: public pqissl
|
class pqisslproxy: public pqissl, public pqiproxyconnection
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
pqisslproxy(pqissllistener *l, PQInterface *parent, p3LinkMgr *lm);
|
pqisslproxy(pqissllistener *l, PQInterface *parent, p3LinkMgr *lm);
|
||||||
virtual ~pqisslproxy();
|
virtual ~pqisslproxy();
|
||||||
|
|
||||||
// NetInterface. Is the same.
|
// NetInterface. Is the same.
|
||||||
// BinInterface. Is the same.
|
// BinInterface. Is the same.
|
||||||
|
|
||||||
virtual bool connect_parameter(uint32_t type, const std::string &value);
|
virtual bool connect_parameter(uint32_t type, const std::string &value);
|
||||||
virtual bool connect_parameter(uint32_t type, uint32_t value);
|
virtual bool connect_parameter(uint32_t type, uint32_t value);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
|
||||||
//Initiate is the same - except it uses the Proxy Address rather than the Peer Address.
|
//Initiate is the same - except it uses the Proxy Address rather than the Peer Address.
|
||||||
// minor tweaks to setup data state.
|
// minor tweaks to setup data state.
|
||||||
virtual int Initiate_Connection();
|
virtual int Initiate_Connection();
|
||||||
|
|
||||||
// The real overloading is done in Basic Connection Complete.
|
// The real overloading is done in Basic Connection Complete.
|
||||||
// Instead of just checking for an open socket, we need to communicate with the SOCKS5 proxy.
|
// Instead of just checking for an open socket, we need to communicate with the SOCKS5 proxy.
|
||||||
virtual int Basic_Connection_Complete();
|
virtual int Basic_Connection_Complete();
|
||||||
|
|
||||||
// These are the internal steps in setting up the Proxy Connection.
|
|
||||||
virtual int Proxy_Send_Method();
|
|
||||||
virtual int Proxy_Method_Response();
|
|
||||||
virtual int Proxy_Send_Address();
|
|
||||||
virtual int Proxy_Connection_Complete();
|
|
||||||
|
|
||||||
private:
|
|
||||||
|
|
||||||
uint32_t mProxyState;
|
|
||||||
|
|
||||||
std::string mDomainAddress;
|
|
||||||
uint16_t mRemotePort;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // MRK_PQI_SSL_PROXY_HEADER
|
#endif // MRK_PQI_SSL_PROXY_HEADER
|
||||||
|
Loading…
Reference in New Issue
Block a user