mirror of
https://github.com/RetroShare/RetroShare.git
synced 2025-02-24 17:00:27 -05:00
305 lines
7.0 KiB
C++
305 lines
7.0 KiB
C++
![]() |
#include "pqissli2psam3.h"
|
||
|
|
||
|
#ifdef RS_USE_I2P_SAM3_I2PSAM
|
||
|
#include "util/i2psam.h"
|
||
|
#endif
|
||
|
#ifdef RS_USE_I2P_SAM3_LIBSAM3
|
||
|
#include <libsam3.h>
|
||
|
#endif
|
||
|
|
||
|
RS_SET_CONTEXT_DEBUG_LEVEL(2)
|
||
|
|
||
|
static constexpr int pqiDone = 1;
|
||
|
static constexpr int pqiWait = 0;
|
||
|
static constexpr int pqiError = -1;
|
||
|
|
||
|
pqissli2psam3::pqissli2psam3(pqissllistener *l, PQInterface *parent, p3LinkMgr *lm)
|
||
|
: pqissl(l, parent, lm), mState(pqisslSam3State::NONE), mI2pAddrB32(), mI2pAddrLong()
|
||
|
{
|
||
|
RS_DBG4();
|
||
|
mConn = nullptr;
|
||
|
}
|
||
|
|
||
|
bool pqissli2psam3::connect_parameter(uint32_t type, const std::string &value)
|
||
|
{
|
||
|
RS_DBG4();
|
||
|
|
||
|
if (type == NET_PARAM_CONNECT_DOMAIN_ADDRESS)
|
||
|
{
|
||
|
RS_DBG1("got addr:", value);
|
||
|
RS_STACK_MUTEX(mSslMtx);
|
||
|
mI2pAddrB32 = value;
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
return pqissl::connect_parameter(type, value);
|
||
|
}
|
||
|
|
||
|
int pqissli2psam3::Initiate_Connection()
|
||
|
{
|
||
|
RS_DBG4();
|
||
|
|
||
|
if(waiting != WAITING_DELAY)
|
||
|
{
|
||
|
RS_ERR("Already Attempt in Progress!");
|
||
|
return pqiError;
|
||
|
}
|
||
|
|
||
|
switch (mState) {
|
||
|
case(pqisslSam3State::NONE):
|
||
|
RS_DBG2("NONE");
|
||
|
{
|
||
|
if(mConn) {
|
||
|
// how did we end up here?
|
||
|
#ifdef RS_USE_I2P_SAM3_I2PSAM
|
||
|
unix_close(mConn);
|
||
|
#endif
|
||
|
#ifdef RS_USE_I2P_SAM3_LIBSAM3
|
||
|
sam3CloseConnection(mConn);
|
||
|
#endif
|
||
|
}
|
||
|
mConn = 0;
|
||
|
// get SAM session
|
||
|
mConn = 0;
|
||
|
samSettings ss;
|
||
|
ss.session = nullptr;
|
||
|
rsAutoProxyMonitor::taskSync(autoProxyType::I2PSAM3, autoProxyTask::getSettings, static_cast<void*>(&ss));
|
||
|
|
||
|
#ifdef RS_USE_I2P_SAM3_I2PSAM
|
||
|
if (!!ss.session && !ss.session->isSick()) {
|
||
|
#endif
|
||
|
#ifdef RS_USE_I2P_SAM3_LIBSAM3
|
||
|
if (!!ss.session) {
|
||
|
#endif
|
||
|
RS_DBG3("NONE->DO_LOOKUP");
|
||
|
mState = pqisslSam3State::DO_LOOKUP;
|
||
|
} else {
|
||
|
RS_DBG3("NONE->DO_LOOKUP NOPE", ss.session);
|
||
|
}
|
||
|
}
|
||
|
break;
|
||
|
case(pqisslSam3State::DO_LOOKUP):
|
||
|
RS_DBG1("DO_LOOKUP");
|
||
|
|
||
|
if (!mI2pAddrLong.empty()) {
|
||
|
// skip lookup, it is highly unlikely/impossible for a public key to change (isn't it?)
|
||
|
mState = pqisslSam3State::WAIT_LOOKUP;
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
{
|
||
|
i2p::address *addr = new i2p::address;
|
||
|
addr->clear();
|
||
|
addr->base32 = mI2pAddrB32;
|
||
|
rsAutoProxyMonitor::taskAsync(autoProxyType::I2PSAM3, autoProxyTask::lookupKey, this, static_cast<void*>(addr));
|
||
|
}
|
||
|
mState = pqisslSam3State::WAIT_LOOKUP;
|
||
|
break;
|
||
|
case(pqisslSam3State::DO_CONNECT):
|
||
|
RS_DBG2("DO_CONNECT");
|
||
|
|
||
|
{
|
||
|
auto wrapper = new samEstablishConnectionWrapper();
|
||
|
wrapper->address.clear();
|
||
|
wrapper->address.publicKey = mI2pAddrLong;
|
||
|
#ifdef RS_USE_I2P_SAM3_I2PSAM
|
||
|
wrapper->socket = 0;
|
||
|
#endif
|
||
|
#ifdef RS_USE_I2P_SAM3_LIBSAM3
|
||
|
wrapper->connection = nullptr;
|
||
|
#endif
|
||
|
rsAutoProxyMonitor::taskAsync(autoProxyType::I2PSAM3, autoProxyTask::establishConnection, this, static_cast<void*>(wrapper));
|
||
|
}
|
||
|
mState = pqisslSam3State::WAIT_CONNECT;
|
||
|
break;
|
||
|
case(pqisslSam3State::DONE):
|
||
|
RS_DBG2("DONE");
|
||
|
|
||
|
if (setupSocket())
|
||
|
return pqiDone;
|
||
|
return pqiError;
|
||
|
|
||
|
/* waiting */
|
||
|
case(pqisslSam3State::WAIT_LOOKUP):
|
||
|
RS_DBG3("WAIT_LOOKUP");
|
||
|
break;
|
||
|
case(pqisslSam3State::WAIT_CONNECT):
|
||
|
RS_DBG3("WAIT_CONNECT");
|
||
|
break;
|
||
|
}
|
||
|
return pqiWait;
|
||
|
}
|
||
|
|
||
|
int pqissli2psam3::net_internal_close(int fd)
|
||
|
{
|
||
|
RS_DBG4();
|
||
|
|
||
|
// sanity check
|
||
|
#ifdef RS_USE_I2P_SAM3_I2PSAM
|
||
|
if (mConn && fd != mConn) {
|
||
|
#endif
|
||
|
#ifdef RS_USE_I2P_SAM3_LIBSAM3
|
||
|
if (mConn && fd != mConn->fd) {
|
||
|
#endif
|
||
|
// this should never happen!
|
||
|
//#ifdef RS_USE_I2P_SAM3_I2PSAM
|
||
|
// unix_close(mConn);
|
||
|
//#endif
|
||
|
//#ifdef RS_USE_I2P_SAM3_LIBSAM3
|
||
|
RS_ERR("fd != mConn");
|
||
|
// sam3CloseConnection(mConn);
|
||
|
//#endif
|
||
|
}
|
||
|
|
||
|
// now to the actuall closing
|
||
|
int ret = pqissl::net_internal_close(fd);
|
||
|
// int ret = 0;
|
||
|
//#ifdef RS_USE_I2P_SAM3_LIBSAM3
|
||
|
// if (mConn)
|
||
|
// ret = sam3CloseConnection(mConn);
|
||
|
//#endif
|
||
|
rsAutoProxyMonitor::taskAsync(autoProxyType::I2PSAM3, autoProxyTask::closeConnection, this, mConn),
|
||
|
|
||
|
// finally cleanup
|
||
|
mConn = 0;
|
||
|
mState = pqisslSam3State::NONE;
|
||
|
|
||
|
return ret;
|
||
|
}
|
||
|
|
||
|
void pqissli2psam3::taskFinished(taskTicket *&ticket)
|
||
|
{
|
||
|
RS_DBG4();
|
||
|
|
||
|
switch (ticket->task) {
|
||
|
case autoProxyTask::lookupKey:
|
||
|
{
|
||
|
auto addr = static_cast<i2p::address*>(ticket->data);
|
||
|
|
||
|
RS_STACK_MUTEX(mSslMtx);
|
||
|
if (ticket->result == autoProxyStatus::ok) {
|
||
|
mI2pAddrLong = addr->publicKey;
|
||
|
mState = pqisslSam3State::DO_CONNECT;
|
||
|
} else {
|
||
|
waiting = WAITING_FAIL_INTERFACE;
|
||
|
}
|
||
|
|
||
|
delete addr;
|
||
|
ticket->data = nullptr;
|
||
|
addr = nullptr;
|
||
|
}
|
||
|
break;
|
||
|
case autoProxyTask::establishConnection:
|
||
|
{
|
||
|
auto wrapper = static_cast<struct samEstablishConnectionWrapper*>(ticket->data);
|
||
|
|
||
|
RS_STACK_MUTEX(mSslMtx);
|
||
|
if (ticket->result == autoProxyStatus::ok) {
|
||
|
#ifdef RS_USE_I2P_SAM3_I2PSAM
|
||
|
mConn = wrapper->socket;
|
||
|
#endif
|
||
|
#ifdef RS_USE_I2P_SAM3_LIBSAM3
|
||
|
mConn = wrapper->connection;
|
||
|
#endif
|
||
|
mState = pqisslSam3State::DONE;
|
||
|
} else {
|
||
|
waiting = WAITING_FAIL_INTERFACE;
|
||
|
}
|
||
|
|
||
|
delete wrapper;
|
||
|
ticket->data = nullptr;
|
||
|
wrapper = nullptr;
|
||
|
}
|
||
|
break;
|
||
|
case autoProxyTask::closeConnection:
|
||
|
// nothing to do here
|
||
|
break;
|
||
|
default:
|
||
|
RS_WARN("unkown task", ticket->task);
|
||
|
}
|
||
|
|
||
|
// clean up!
|
||
|
delete ticket;
|
||
|
ticket = nullptr;
|
||
|
}
|
||
|
|
||
|
bool pqissli2psam3::setupSocket()
|
||
|
{
|
||
|
/*
|
||
|
* This function contains the generis part from pqissl::Initiate_Connection()
|
||
|
*/
|
||
|
int err;
|
||
|
#ifdef RS_USE_I2P_SAM3_I2PSAM
|
||
|
int osock = mConn;
|
||
|
#endif
|
||
|
#ifdef RS_USE_I2P_SAM3_LIBSAM3
|
||
|
int osock = mConn->fd;
|
||
|
#endif
|
||
|
|
||
|
err = unix_fcntl_nonblock(osock);
|
||
|
if (err < 0)
|
||
|
{
|
||
|
RS_ERR("Cannot make socket NON-Blocking:", err);
|
||
|
|
||
|
waiting = WAITING_FAIL_INTERFACE;
|
||
|
net_internal_close(osock);
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
#ifdef WINDOWS_SYS
|
||
|
/* Set TCP buffer size for Windows systems */
|
||
|
|
||
|
int sockbufsize = 0;
|
||
|
int size = sizeof(int);
|
||
|
|
||
|
err = getsockopt(osock, SOL_SOCKET, SO_RCVBUF, (char *)&sockbufsize, &size);
|
||
|
#ifdef PQISSL_DEBUG
|
||
|
if (err == 0) {
|
||
|
std::cerr << "pqissl::Initiate_Connection: Current TCP receive buffer size " << sockbufsize << std::endl;
|
||
|
} else {
|
||
|
std::cerr << "pqissl::Initiate_Connection: Error getting TCP receive buffer size. Error " << err << std::endl;
|
||
|
}
|
||
|
#endif
|
||
|
|
||
|
sockbufsize = 0;
|
||
|
|
||
|
err = getsockopt(osock, SOL_SOCKET, SO_SNDBUF, (char *)&sockbufsize, &size);
|
||
|
#ifdef PQISSL_DEBUG
|
||
|
if (err == 0) {
|
||
|
std::cerr << "pqissl::Initiate_Connection: Current TCP send buffer size " << sockbufsize << std::endl;
|
||
|
} else {
|
||
|
std::cerr << "pqissl::Initiate_Connection: Error getting TCP send buffer size. Error " << err << std::endl;
|
||
|
}
|
||
|
#endif
|
||
|
|
||
|
sockbufsize = WINDOWS_TCP_BUFFER_SIZE;
|
||
|
|
||
|
err = setsockopt(osock, SOL_SOCKET, SO_RCVBUF, (char *)&sockbufsize, sizeof(sockbufsize));
|
||
|
#ifdef PQISSL_DEBUG
|
||
|
if (err == 0) {
|
||
|
std::cerr << "pqissl::Initiate_Connection: TCP receive buffer size set to " << sockbufsize << std::endl;
|
||
|
} else {
|
||
|
std::cerr << "pqissl::Initiate_Connection: Error setting TCP receive buffer size. Error " << err << std::endl;
|
||
|
}
|
||
|
#endif
|
||
|
|
||
|
err = setsockopt(osock, SOL_SOCKET, SO_SNDBUF, (char *)&sockbufsize, sizeof(sockbufsize));
|
||
|
#ifdef PQISSL_DEBUG
|
||
|
if (err == 0) {
|
||
|
std::cerr << "pqissl::Initiate_Connection: TCP send buffer size set to " << sockbufsize << std::endl;
|
||
|
} else {
|
||
|
std::cerr << "pqissl::Initiate_Connection: Error setting TCP send buffer size. Error " << err << std::endl;
|
||
|
}
|
||
|
#endif
|
||
|
#endif // WINDOWS_SYS
|
||
|
|
||
|
|
||
|
mTimeoutTS = time(NULL) + mConnectTimeout;
|
||
|
//std::cerr << "Setting Connect Timeout " << mConnectTimeout << " Seconds into Future " << std::endl;
|
||
|
|
||
|
waiting = WAITING_SOCK_CONNECT;
|
||
|
sockfd = osock;
|
||
|
|
||
|
return true;
|
||
|
}
|