mirror of
https://github.com/RetroShare/RetroShare.git
synced 2024-10-01 02:35:48 -04:00
add i2psam3
This commit is contained in:
parent
42bc295d1a
commit
10189ba4d0
@ -157,7 +157,7 @@ rs_webui {
|
|||||||
|
|
||||||
HEADERS += plugins/pluginmanager.h \
|
HEADERS += plugins/pluginmanager.h \
|
||||||
plugins/dlfcn_win32.h \
|
plugins/dlfcn_win32.h \
|
||||||
rsitems/rspluginitems.h \
|
rsitems/rspluginitems.h \
|
||||||
util/i2pcommon.h \
|
util/i2pcommon.h \
|
||||||
util/rsinitedptr.h
|
util/rsinitedptr.h
|
||||||
|
|
||||||
@ -1014,6 +1014,31 @@ rs_broadcast_discovery {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
rs_sam3 {
|
||||||
|
SOURCES += \
|
||||||
|
services/autoproxy/p3i2psam3.cpp \
|
||||||
|
pqi/pqissli2psam3.cpp \
|
||||||
|
|
||||||
|
HEADERS += \
|
||||||
|
services/autoproxy/p3i2psam3.h \
|
||||||
|
pqi/pqissli2psam3.h \
|
||||||
|
}
|
||||||
|
|
||||||
|
rs_sam3_libsam3 {
|
||||||
|
DUMMYQMAKECOMPILERINPUT = FORCE
|
||||||
|
libsam3.name = Generating libsam3.
|
||||||
|
libsam3.input = DUMMYQMAKECOMPILERINPUT
|
||||||
|
libsam3.output = $$clean_path($${LIBSAM3_BUILD_PATH}/libsam3.a)
|
||||||
|
libsam3.CONFIG += target_predeps combine
|
||||||
|
libsam3.variable_out = PRE_TARGETDEPS
|
||||||
|
libsam3.commands = \
|
||||||
|
cd $${RS_SRC_PATH} && \
|
||||||
|
cp -r $${LIBSAM3_SRC_PATH}/* $${LIBSAM3_BUILD_PATH} && \
|
||||||
|
cd $${LIBSAM3_BUILD_PATH} && \
|
||||||
|
$(MAKE) build
|
||||||
|
QMAKE_EXTRA_COMPILERS += libsam3
|
||||||
|
}
|
||||||
|
|
||||||
###########################################################################################################
|
###########################################################################################################
|
||||||
# OLD CONFIG OPTIONS.
|
# OLD CONFIG OPTIONS.
|
||||||
# Not used much - but might be useful one day.
|
# Not used much - but might be useful one day.
|
||||||
|
@ -1742,6 +1742,7 @@ bool pqissl::moretoread(uint32_t usec)
|
|||||||
{
|
{
|
||||||
rslog(RSL_ALERT, pqisslzone,
|
rslog(RSL_ALERT, pqisslzone,
|
||||||
"pqissl::moretoread() Select ERROR!");
|
"pqissl::moretoread() Select ERROR!");
|
||||||
|
RS_WARN(errno);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
304
libretroshare/src/pqi/pqissli2psam3.cpp
Normal file
304
libretroshare/src/pqi/pqissli2psam3.cpp
Normal file
@ -0,0 +1,304 @@
|
|||||||
|
#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;
|
||||||
|
}
|
53
libretroshare/src/pqi/pqissli2psam3.h
Normal file
53
libretroshare/src/pqi/pqissli2psam3.h
Normal file
@ -0,0 +1,53 @@
|
|||||||
|
#ifndef PQISSLI2PSAM3_H
|
||||||
|
#define PQISSLI2PSAM3_H
|
||||||
|
|
||||||
|
#include "pqi/pqissl.h"
|
||||||
|
#include "services/autoproxy/rsautoproxymonitor.h"
|
||||||
|
#include "services/autoproxy/p3i2psam3.h"
|
||||||
|
|
||||||
|
// Use a state machine as the whole pqi code is designed around them and some operation (like lookup) might be blocking
|
||||||
|
enum class pqisslSam3State : uint8_t {
|
||||||
|
NONE = 0,
|
||||||
|
DO_LOOKUP,
|
||||||
|
WAIT_LOOKUP,
|
||||||
|
DO_CONNECT,
|
||||||
|
WAIT_CONNECT,
|
||||||
|
DONE
|
||||||
|
};
|
||||||
|
|
||||||
|
class pqissli2psam3 : public pqissl, public autoProxyCallback
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
pqissli2psam3(pqissllistener *l, PQInterface *parent, p3LinkMgr *lm);
|
||||||
|
|
||||||
|
// NetInterface interface
|
||||||
|
public:
|
||||||
|
bool connect_parameter(uint32_t type, const std::string &value);
|
||||||
|
|
||||||
|
// pqissl interface
|
||||||
|
protected:
|
||||||
|
int Initiate_Connection();
|
||||||
|
int net_internal_close(int fd);
|
||||||
|
|
||||||
|
// autoProxyCallback interface
|
||||||
|
public:
|
||||||
|
void taskFinished(taskTicket *&ticket);
|
||||||
|
|
||||||
|
private:
|
||||||
|
bool setupSocket();
|
||||||
|
|
||||||
|
private:
|
||||||
|
pqisslSam3State mState;
|
||||||
|
std::string mI2pAddrB32;
|
||||||
|
std::string mI2pAddrLong;
|
||||||
|
|
||||||
|
// samSession *mSs;
|
||||||
|
#ifdef RS_USE_I2P_SAM3_I2PSAM
|
||||||
|
int mConn;
|
||||||
|
#endif
|
||||||
|
#ifdef RS_USE_I2P_SAM3_LIBSAM3
|
||||||
|
Sam3Connection *mConn;
|
||||||
|
#endif
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // PQISSLI2PSAM3_H
|
@ -186,8 +186,8 @@ public:
|
|||||||
virtual int finaliseConnection(int fd, SSL *ssl, const RsPeerId& peerId,
|
virtual int finaliseConnection(int fd, SSL *ssl, const RsPeerId& peerId,
|
||||||
const sockaddr_storage &raddr);
|
const sockaddr_storage &raddr);
|
||||||
|
|
||||||
|
RS_SET_CONTEXT_DEBUG_LEVEL(2)
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::map<RsPeerId, pqissl*> listenaddr;
|
std::map<RsPeerId, pqissl*> listenaddr;
|
||||||
|
|
||||||
RS_SET_CONTEXT_DEBUG_LEVEL(2)
|
|
||||||
};
|
};
|
||||||
|
@ -46,7 +46,7 @@ static struct RsLog::logInfo pqipersongrpzoneInfo = {RsLog::Default, "pqipersong
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include "pqi/pqisslproxy.h"
|
#include "pqi/pqisslproxy.h"
|
||||||
#include "pqi/pqissli2pbob.h"
|
#include "pqi/pqissli2psam3.h"
|
||||||
|
|
||||||
pqilistener * pqisslpersongrp::locked_createListener(const struct sockaddr_storage &laddr)
|
pqilistener * pqisslpersongrp::locked_createListener(const struct sockaddr_storage &laddr)
|
||||||
{
|
{
|
||||||
@ -74,26 +74,26 @@ pqiperson * pqisslpersongrp::locked_createPerson(const RsPeerId& id, pqilistener
|
|||||||
std::cerr << std::endl;
|
std::cerr << std::endl;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// Use pqicI2PBOB for I2P
|
// Use pqicI2P for I2P
|
||||||
pqiconnect *pqicSOCKSProxy, *pqicI2PBOB;
|
pqiconnect *pqicSOCKSProxy, *pqicI2P;
|
||||||
{
|
{
|
||||||
pqisslproxy *pqis = new pqisslproxy((pqissllistener *) listener, pqip, mLinkMgr);
|
pqisslproxy *pqis = new pqisslproxy((pqissllistener *) listener, pqip, mLinkMgr);
|
||||||
RsSerialiser *rss = new RsSerialiser();
|
RsSerialiser *rss = new RsSerialiser();
|
||||||
rss->addSerialType(new RsRawSerialiser());
|
rss->addSerialType(new RsRawSerialiser());
|
||||||
pqicSOCKSProxy = new pqiconnect(pqip, rss, pqis);
|
pqicSOCKSProxy = new pqiconnect(pqip, rss, pqis);
|
||||||
}
|
}
|
||||||
if (rsAutoProxyMonitor::instance()->isEnabled(autoProxyType::I2PBOB))
|
|
||||||
|
if (rsAutoProxyMonitor::instance()->isEnabled(autoProxyType::I2PSAM3))
|
||||||
{
|
{
|
||||||
pqissli2pbob *pqis = new pqissli2pbob((pqissllistener *) listener, pqip, mLinkMgr);
|
pqissli2psam3 *pqis = new pqissli2psam3((pqissllistener *) listener, pqip, mLinkMgr);
|
||||||
RsSerialiser *rss = new RsSerialiser();
|
RsSerialiser *rss = new RsSerialiser();
|
||||||
rss->addSerialType(new RsRawSerialiser());
|
rss->addSerialType(new RsRawSerialiser());
|
||||||
|
|
||||||
pqicI2PBOB = new pqiconnect(pqip, rss, pqis);
|
pqicI2P = new pqiconnect(pqip, rss, pqis);
|
||||||
} else {
|
} else {
|
||||||
pqicI2PBOB = pqicSOCKSProxy;
|
pqicI2P = pqicSOCKSProxy;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* first select type based on peer */
|
/* first select type based on peer */
|
||||||
uint32_t typePeer = mPeerMgr->getHiddenType(id);
|
uint32_t typePeer = mPeerMgr->getHiddenType(id);
|
||||||
switch (typePeer) {
|
switch (typePeer) {
|
||||||
@ -101,7 +101,7 @@ pqiperson * pqisslpersongrp::locked_createPerson(const RsPeerId& id, pqilistener
|
|||||||
pqip -> addChildInterface(PQI_CONNECT_HIDDEN_TOR_TCP, pqicSOCKSProxy);
|
pqip -> addChildInterface(PQI_CONNECT_HIDDEN_TOR_TCP, pqicSOCKSProxy);
|
||||||
break;
|
break;
|
||||||
case RS_HIDDEN_TYPE_I2P:
|
case RS_HIDDEN_TYPE_I2P:
|
||||||
pqip -> addChildInterface(PQI_CONNECT_HIDDEN_I2P_TCP, pqicI2PBOB);
|
pqip -> addChildInterface(PQI_CONNECT_HIDDEN_I2P_TCP, pqicI2P);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
/* peer is not a hidden one but we are */
|
/* peer is not a hidden one but we are */
|
||||||
@ -109,7 +109,7 @@ pqiperson * pqisslpersongrp::locked_createPerson(const RsPeerId& id, pqilistener
|
|||||||
uint32_t typeOwn = mPeerMgr->getHiddenType(AuthSSL::getAuthSSL()->OwnId());
|
uint32_t typeOwn = mPeerMgr->getHiddenType(AuthSSL::getAuthSSL()->OwnId());
|
||||||
switch (typeOwn) {
|
switch (typeOwn) {
|
||||||
case RS_HIDDEN_TYPE_I2P:
|
case RS_HIDDEN_TYPE_I2P:
|
||||||
pqip -> addChildInterface(PQI_CONNECT_HIDDEN_I2P_TCP, pqicI2PBOB);
|
pqip -> addChildInterface(PQI_CONNECT_HIDDEN_I2P_TCP, pqicI2P);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
/* this case shouldn't happen! */
|
/* this case shouldn't happen! */
|
||||||
|
@ -195,7 +195,7 @@ public:
|
|||||||
/*
|
/*
|
||||||
* Setup Hidden Location;
|
* Setup Hidden Location;
|
||||||
*/
|
*/
|
||||||
static void SetHiddenLocation(const std::string& hiddenaddress, uint16_t port, bool useBob);
|
static void SetHiddenLocation(const std::string& hiddenaddress, uint16_t port, bool useI2p);
|
||||||
|
|
||||||
static bool LoadPassword(const std::string& passwd) ;
|
static bool LoadPassword(const std::string& passwd) ;
|
||||||
|
|
||||||
|
@ -43,7 +43,7 @@
|
|||||||
|
|
||||||
class p3heartbeat;
|
class p3heartbeat;
|
||||||
class p3discovery2;
|
class p3discovery2;
|
||||||
class p3I2pBob;
|
class p3I2pSam3;
|
||||||
|
|
||||||
/* GXS Classes - just declare the classes.
|
/* GXS Classes - just declare the classes.
|
||||||
so we don't have to totally recompile to switch */
|
so we don't have to totally recompile to switch */
|
||||||
@ -161,8 +161,8 @@ public:
|
|||||||
p3ChatService *chatSrv;
|
p3ChatService *chatSrv;
|
||||||
p3StatusService *mStatusSrv;
|
p3StatusService *mStatusSrv;
|
||||||
p3GxsTunnelService *mGxsTunnels;
|
p3GxsTunnelService *mGxsTunnels;
|
||||||
#ifdef RS_USE_I2P_BOB
|
#ifdef RS_USE_I2P_SAM3
|
||||||
p3I2pBob *mI2pBob;
|
p3I2pSam3 *mI2pSam3;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// This list contains all threaded services. It will be used to shut them down properly.
|
// This list contains all threaded services. It will be used to shut them down properly.
|
||||||
|
@ -170,7 +170,7 @@ struct RsInitConfig
|
|||||||
std::string hiddenNodeAddress;
|
std::string hiddenNodeAddress;
|
||||||
uint16_t hiddenNodePort;
|
uint16_t hiddenNodePort;
|
||||||
|
|
||||||
bool hiddenNodeI2PBOB;
|
bool hiddenNodeI2P;
|
||||||
|
|
||||||
/* Logging */
|
/* Logging */
|
||||||
bool haveLogFile;
|
bool haveLogFile;
|
||||||
@ -664,13 +664,13 @@ void RsInit::setAutoLogin(bool autoLogin){
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Setup Hidden Location; */
|
/* Setup Hidden Location; */
|
||||||
void RsInit::SetHiddenLocation(const std::string& hiddenaddress, uint16_t port, bool useBob)
|
void RsInit::SetHiddenLocation(const std::string& hiddenaddress, uint16_t port, bool useI2p)
|
||||||
{
|
{
|
||||||
/* parse the bugger (todo) */
|
/* parse the bugger (todo) */
|
||||||
rsInitConfig->hiddenNodeSet = true;
|
rsInitConfig->hiddenNodeSet = true;
|
||||||
rsInitConfig->hiddenNodeAddress = hiddenaddress;
|
rsInitConfig->hiddenNodeAddress = hiddenaddress;
|
||||||
rsInitConfig->hiddenNodePort = port;
|
rsInitConfig->hiddenNodePort = port;
|
||||||
rsInitConfig->hiddenNodeI2PBOB = useBob;
|
rsInitConfig->hiddenNodeI2P = useI2p;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -718,6 +718,7 @@ RsGRouter *rsGRouter = NULL ;
|
|||||||
#endif // def RS_USE_LIBUPNP
|
#endif // def RS_USE_LIBUPNP
|
||||||
|
|
||||||
#include "services/autoproxy/p3i2pbob.h"
|
#include "services/autoproxy/p3i2pbob.h"
|
||||||
|
#include "services/autoproxy/p3i2psam3.h"
|
||||||
#include "services/autoproxy/rsautoproxymonitor.h"
|
#include "services/autoproxy/rsautoproxymonitor.h"
|
||||||
|
|
||||||
#include "services/p3gxsreputation.h"
|
#include "services/p3gxsreputation.h"
|
||||||
@ -923,9 +924,9 @@ int RsServer::StartupRetroShare()
|
|||||||
mNetMgr->setManagers(mPeerMgr, mLinkMgr);
|
mNetMgr->setManagers(mPeerMgr, mLinkMgr);
|
||||||
|
|
||||||
rsAutoProxyMonitor *autoProxy = rsAutoProxyMonitor::instance();
|
rsAutoProxyMonitor *autoProxy = rsAutoProxyMonitor::instance();
|
||||||
#ifdef RS_USE_I2P_BOB
|
#ifdef RS_USE_I2P_SAM3
|
||||||
mI2pBob = new p3I2pBob(mPeerMgr);
|
mI2pSam3 = new p3I2pSam3(mPeerMgr);
|
||||||
autoProxy->addProxy(autoProxyType::I2PBOB, mI2pBob);
|
autoProxy->addProxy(autoProxyType::I2PSAM3, mI2pSam3);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
//load all the SSL certs as friends
|
//load all the SSL certs as friends
|
||||||
@ -1655,8 +1656,9 @@ int RsServer::StartupRetroShare()
|
|||||||
mConfigMgr->addConfiguration("wire.cfg", wire_ns);
|
mConfigMgr->addConfiguration("wire.cfg", wire_ns);
|
||||||
#endif
|
#endif
|
||||||
#endif //RS_ENABLE_GXS
|
#endif //RS_ENABLE_GXS
|
||||||
#ifdef RS_USE_I2P_BOB
|
#ifdef RS_USE_I2P_SAM3
|
||||||
mConfigMgr->addConfiguration("I2PBOB.cfg", mI2pBob);
|
// to make migration easiert, SAM will use BOBs configuration, as they are compatible / the same.
|
||||||
|
mConfigMgr->addConfiguration("I2PBOB.cfg", mI2pSam3);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
mPluginsManager->addConfigurations(mConfigMgr) ;
|
mPluginsManager->addConfigurations(mConfigMgr) ;
|
||||||
@ -1709,34 +1711,33 @@ int RsServer::StartupRetroShare()
|
|||||||
{
|
{
|
||||||
std::cout << "RsServer::StartupRetroShare setting up hidden locations" << std::endl;
|
std::cout << "RsServer::StartupRetroShare setting up hidden locations" << std::endl;
|
||||||
|
|
||||||
if (rsInitConfig->hiddenNodeI2PBOB) {
|
if (rsInitConfig->hiddenNodeI2P) {
|
||||||
std::cout << "RsServer::StartupRetroShare setting up BOB" << std::endl;
|
std::cout << "RsServer::StartupRetroShare setting up SAMv3" << std::endl;
|
||||||
|
|
||||||
// we need a local port!
|
// we need a local port!
|
||||||
mNetMgr->checkNetAddress();
|
mNetMgr->checkNetAddress();
|
||||||
|
|
||||||
// add i2p proxy
|
// add i2p proxy
|
||||||
// bob will use this address
|
|
||||||
sockaddr_storage i2pInstance;
|
sockaddr_storage i2pInstance;
|
||||||
sockaddr_storage_ipv4_aton(i2pInstance, rsInitConfig->hiddenNodeAddress.c_str());
|
sockaddr_storage_ipv4_aton(i2pInstance, rsInitConfig->hiddenNodeAddress.c_str());
|
||||||
mPeerMgr->setProxyServerAddress(RS_HIDDEN_TYPE_I2P, i2pInstance);
|
mPeerMgr->setProxyServerAddress(RS_HIDDEN_TYPE_I2P, i2pInstance);
|
||||||
|
|
||||||
std::string addr; // will be set by auto proxy service
|
std::string addr; // will be set by auto proxy service
|
||||||
uint16_t port = rsInitConfig->hiddenNodePort; // unused by bob
|
uint16_t port; // unused by SAM
|
||||||
|
|
||||||
bool r = autoProxy->initialSetup(autoProxyType::I2PBOB, addr, port);
|
bool r = autoProxy->initialSetup(autoProxyType::I2PSAM3, addr, port);
|
||||||
|
|
||||||
if (r && !addr.empty()) {
|
if (r && !addr.empty()) {
|
||||||
mPeerMgr->setupHiddenNode(addr, port);
|
mPeerMgr->setupHiddenNode(addr, port);
|
||||||
|
|
||||||
// now enable bob
|
// now enable SAM
|
||||||
bobSettings bs;
|
samSettings ss;
|
||||||
autoProxy->taskSync(autoProxyType::I2PBOB, autoProxyTask::getSettings, &bs);
|
autoProxy->taskSync(autoProxyType::I2PSAM3, autoProxyTask::getSettings, &ss);
|
||||||
bs.enable = true;
|
ss.enable = true;
|
||||||
autoProxy->taskSync(autoProxyType::I2PBOB, autoProxyTask::setSettings, &bs);
|
autoProxy->taskSync(autoProxyType::I2PSAM3, autoProxyTask::setSettings, &ss);
|
||||||
} else {
|
} else {
|
||||||
std::cerr << "RsServer::StartupRetroShare failed to receive keys" << std::endl;
|
std::cerr << "RsServer::StartupRetroShare failed to receive keys" << std::endl;
|
||||||
/// TODO add notify for failed bob setup
|
/// TODO add notify for failed i2p setup
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
mPeerMgr->setupHiddenNode(rsInitConfig->hiddenNodeAddress, rsInitConfig->hiddenNodePort);
|
mPeerMgr->setupHiddenNode(rsInitConfig->hiddenNodeAddress, rsInitConfig->hiddenNodePort);
|
||||||
@ -1758,19 +1759,17 @@ int RsServer::StartupRetroShare()
|
|||||||
if (rsInitConfig->hiddenNodeSet) {
|
if (rsInitConfig->hiddenNodeSet) {
|
||||||
// newly created location
|
// newly created location
|
||||||
// mNetMgr->checkNetAddress() will setup ports for us
|
// mNetMgr->checkNetAddress() will setup ports for us
|
||||||
|
|
||||||
|
#if 0 // this was used for BOB but is not requires for SAMv3
|
||||||
// trigger updates for auto proxy services
|
// trigger updates for auto proxy services
|
||||||
std::vector<autoProxyType::autoProxyType_enum> types;
|
std::vector<autoProxyType::autoProxyType_enum> types;
|
||||||
|
|
||||||
// i2p bob need to rebuild its command map
|
|
||||||
types.push_back(autoProxyType::I2PBOB);
|
|
||||||
|
|
||||||
rsAutoProxyMonitor::taskSync(types, autoProxyTask::reloadConfig);
|
rsAutoProxyMonitor::taskSync(types, autoProxyTask::reloadConfig);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
/**************************************************************************/
|
/**************************************************************************/
|
||||||
/* startup (stuff dependent on Ids/peers is after this point) */
|
/* startup (stuff dependent on Ids/peers is after this point) */
|
||||||
/**************************************************************************/
|
/**************************************************************************/
|
||||||
|
|
||||||
autoProxy->startAll();
|
autoProxy->startAll();
|
||||||
|
|
||||||
pqih->init_listener();
|
pqih->init_listener();
|
||||||
@ -1803,8 +1802,8 @@ int RsServer::StartupRetroShare()
|
|||||||
/**************************************************************************/
|
/**************************************************************************/
|
||||||
|
|
||||||
// auto proxy threads
|
// auto proxy threads
|
||||||
#ifdef RS_USE_I2P_BOB
|
#ifdef RS_USE_I2P_SAM3
|
||||||
startServiceThread(mI2pBob, "I2P-BOB");
|
startServiceThread(mI2pSam3, "I2P-SAM3");
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef RS_ENABLE_GXS
|
#ifdef RS_ENABLE_GXS
|
||||||
|
894
libretroshare/src/services/autoproxy/p3i2psam3.cpp
Normal file
894
libretroshare/src/services/autoproxy/p3i2psam3.cpp
Normal file
@ -0,0 +1,894 @@
|
|||||||
|
#include "p3i2psam3.h"
|
||||||
|
|
||||||
|
#ifdef RS_USE_I2P_SAM3_LIBSAM3
|
||||||
|
#include <libsam3.h>
|
||||||
|
#endif
|
||||||
|
#ifdef RS_USE_I2P_SAM3_I2PSAM
|
||||||
|
#include "util/i2psam.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include "pqi/p3peermgr.h"
|
||||||
|
#include "rsitems/rsconfigitems.h"
|
||||||
|
|
||||||
|
|
||||||
|
static const std::string kConfigKeySAM3Enable = "SAM3_ENABLE";
|
||||||
|
|
||||||
|
static const std::string kConfigKeyDestPriv = "DEST_PRIV";
|
||||||
|
|
||||||
|
static const std::string kConfigKeyInLength = "IN_LENGTH";
|
||||||
|
static const std::string kConfigKeyInQuantity = "IN_QUANTITY";
|
||||||
|
static const std::string kConfigKeyInVariance = "IN_VARIANCE";
|
||||||
|
static const std::string kConfigKeyInBackupQuantity = "IN_BACKUPQUANTITY";
|
||||||
|
|
||||||
|
static const std::string kConfigKeyOutLength = "OUT_LENGTH";
|
||||||
|
static const std::string kConfigKeyOutQuantity = "OUT_QUANTITY";
|
||||||
|
static const std::string kConfigKeyOutVariance = "OUT_VARIANCE";
|
||||||
|
static const std::string kConfigKeyOutBackupQuantity = "OUT_BACKUPQUANTITY";
|
||||||
|
|
||||||
|
#ifdef RS_I2P_SAM3_BOB_COMPAT
|
||||||
|
// used for migration from BOB to SAM
|
||||||
|
static const std::string kConfigKeyBOBEnable = "BOB_ENABLE";
|
||||||
|
static const std::string kConfigKeyBOBKey = "BOB_KEY";
|
||||||
|
static const std::string kConfigKeyBOBAddr = "BOB_ADDR";
|
||||||
|
#endif
|
||||||
|
|
||||||
|
static constexpr bool kDefaultSAM3Enable = false;
|
||||||
|
|
||||||
|
RS_SET_CONTEXT_DEBUG_LEVEL(4)
|
||||||
|
|
||||||
|
// copy from i2psam.cpp
|
||||||
|
//#define I2P_DESTINATION_SIZE 516
|
||||||
|
|
||||||
|
static void inline doSleep(std::chrono::duration<long, std::ratio<1,1000>> timeToSleepMS) {
|
||||||
|
std::this_thread::sleep_for(timeToSleepMS);
|
||||||
|
}
|
||||||
|
|
||||||
|
p3I2pSam3::p3I2pSam3(p3PeerMgr *peerMgr) :
|
||||||
|
mConfigLoaded(false), mPeerMgr(peerMgr), mPending(), mLock("p3i2p-sam3")
|
||||||
|
#ifdef RS_USE_I2P_SAM3_LIBSAM3
|
||||||
|
, mLockSam3Access("p3i2p-sam3-access")
|
||||||
|
#endif
|
||||||
|
{
|
||||||
|
RS_DBG4();
|
||||||
|
|
||||||
|
// set defaults
|
||||||
|
mSetting.initDefault();
|
||||||
|
mSetting.enable = kDefaultSAM3Enable;
|
||||||
|
mSetting.session = nullptr;
|
||||||
|
|
||||||
|
libsam3_debug = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool p3I2pSam3::isEnabled()
|
||||||
|
{
|
||||||
|
RS_STACK_MUTEX(mLock);
|
||||||
|
return mSetting.enable;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool p3I2pSam3::initialSetup(std::string &addr, uint16_t &/*port*/)
|
||||||
|
{
|
||||||
|
RS_DBG4();
|
||||||
|
|
||||||
|
RS_STACK_MUTEX(mLock);
|
||||||
|
|
||||||
|
if (!mSetting.address.publicKey.empty() || !mSetting.address.privateKey.empty())
|
||||||
|
RS_DBG("overwriting keys!");
|
||||||
|
|
||||||
|
bool success = generateKey(mSetting.address.publicKey, mSetting.address.privateKey);
|
||||||
|
|
||||||
|
if (!success) {
|
||||||
|
RS_DBG("failed to retrieve keys");
|
||||||
|
return false;
|
||||||
|
} else {
|
||||||
|
std::string s, c;
|
||||||
|
i2p::getKeyTypes(mSetting.address.publicKey, s, c);
|
||||||
|
RS_INFO("received key", s, c);
|
||||||
|
|
||||||
|
IndicateConfigChanged();
|
||||||
|
}
|
||||||
|
|
||||||
|
addr = mSetting.address.base32 = i2p::keyToBase32Addr(mSetting.address.publicKey);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void p3I2pSam3::processTaskAsync(taskTicket *ticket)
|
||||||
|
{
|
||||||
|
RS_DBG4();
|
||||||
|
|
||||||
|
switch (ticket->task) {
|
||||||
|
case autoProxyTask::stop: [[fallthrough]];
|
||||||
|
case autoProxyTask::start: [[fallthrough]];
|
||||||
|
case autoProxyTask::receiveKey: [[fallthrough]];
|
||||||
|
case autoProxyTask::lookupKey: [[fallthrough]];
|
||||||
|
case autoProxyTask::proxyStatusCheck: [[fallthrough]];
|
||||||
|
case autoProxyTask::establishConnection: [[fallthrough]];
|
||||||
|
case autoProxyTask::closeConnection:
|
||||||
|
{
|
||||||
|
RS_STACK_MUTEX(mLock);
|
||||||
|
mPending.push(ticket);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case autoProxyTask::status: [[fallthrough]];
|
||||||
|
case autoProxyTask::getSettings: [[fallthrough]];
|
||||||
|
case autoProxyTask::setSettings: [[fallthrough]];
|
||||||
|
case autoProxyTask::getErrorInfo: [[fallthrough]];
|
||||||
|
case autoProxyTask::reloadConfig:
|
||||||
|
// These are supposed to be sync!
|
||||||
|
RS_DBG("unknown task or sync one!");
|
||||||
|
rsAutoProxyMonitor::taskError(ticket);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void p3I2pSam3::processTaskSync(taskTicket *ticket)
|
||||||
|
{
|
||||||
|
// RS_DBG4();
|
||||||
|
|
||||||
|
const bool data = !!ticket->data;
|
||||||
|
|
||||||
|
switch (ticket->task) {
|
||||||
|
case autoProxyTask::status:
|
||||||
|
{
|
||||||
|
samStatus *ss = static_cast<struct samStatus *>(ticket->data);
|
||||||
|
RS_STACK_MUTEX(mLock);
|
||||||
|
ss->state = mState;
|
||||||
|
if (mSetting.session)
|
||||||
|
ss->sessionName = mSetting.session->channel;
|
||||||
|
else
|
||||||
|
ss->sessionName = "none";
|
||||||
|
}
|
||||||
|
rsAutoProxyMonitor::taskDone(ticket, autoProxyStatus::ok);
|
||||||
|
|
||||||
|
break;
|
||||||
|
case autoProxyTask::getSettings:
|
||||||
|
// check if everything needed is set
|
||||||
|
if (!data) {
|
||||||
|
RS_DBG("autoProxyTask::getSettings data is missing");
|
||||||
|
rsAutoProxyMonitor::taskError(ticket);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// get settings
|
||||||
|
{
|
||||||
|
RS_STACK_MUTEX(mLock);
|
||||||
|
*static_cast<struct samSettings *>(ticket->data) = mSetting;
|
||||||
|
}
|
||||||
|
|
||||||
|
// finish task
|
||||||
|
rsAutoProxyMonitor::taskDone(ticket, autoProxyStatus::ok);
|
||||||
|
break;
|
||||||
|
case autoProxyTask::setSettings:
|
||||||
|
// check if everything needed is set
|
||||||
|
if (!data) {
|
||||||
|
RS_DBG("autoProxyTask::setSettings data is missing");
|
||||||
|
rsAutoProxyMonitor::taskError(ticket);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// set settings
|
||||||
|
{
|
||||||
|
RS_STACK_MUTEX(mLock);
|
||||||
|
mSetting = *static_cast<struct samSettings *>(ticket->data);
|
||||||
|
updateSettings_locked();
|
||||||
|
}
|
||||||
|
|
||||||
|
// finish task
|
||||||
|
rsAutoProxyMonitor::taskDone(ticket, autoProxyStatus::ok);
|
||||||
|
break;
|
||||||
|
case autoProxyTask::getErrorInfo:
|
||||||
|
#ifdef RS_USE_I2P_SAM3_LIBSAM3
|
||||||
|
*static_cast<std::string *>(ticket->data) = mSetting.session->error;
|
||||||
|
rsAutoProxyMonitor::taskDone(ticket, autoProxyStatus::ok);
|
||||||
|
#else
|
||||||
|
rsAutoProxyMonitor::taskError(ticket);
|
||||||
|
#endif
|
||||||
|
break;
|
||||||
|
case autoProxyTask::reloadConfig:
|
||||||
|
{
|
||||||
|
RS_STACK_MUTEX(mLock);
|
||||||
|
updateSettings_locked();
|
||||||
|
}
|
||||||
|
rsAutoProxyMonitor::taskDone(ticket, autoProxyStatus::ok);
|
||||||
|
break;
|
||||||
|
case autoProxyTask::stop:
|
||||||
|
#if 0 // doesn't seem to work, socket stays "CLOSE_WAIT"
|
||||||
|
// there can be a case where libsam3 will block forever because for some reason it does not detect that the socket it has is dead
|
||||||
|
// as a workaroung kill it from here
|
||||||
|
if (mState == samStatus::samState::connectSession || mState == samStatus::samState::connectForward) {
|
||||||
|
// lock should be held by the main thread
|
||||||
|
if (!mTmpSession) {
|
||||||
|
// now it's getting weird
|
||||||
|
RS_WARN("session is nullptr but mState says it is connecting.");
|
||||||
|
// no break! just ignore for now ...
|
||||||
|
} else {
|
||||||
|
// just close it from here, libsam3 is not thread safe.
|
||||||
|
// a bit of a hack but should do the trick
|
||||||
|
// sam3CloseSession(mSetting.session);
|
||||||
|
sam3tcpDisconnect(mTmpSession->fd);
|
||||||
|
// no break! continue as usual to keep everything in line
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
[[fallthrough]];
|
||||||
|
case autoProxyTask::start: [[fallthrough]];
|
||||||
|
case autoProxyTask::receiveKey: [[fallthrough]];
|
||||||
|
case autoProxyTask::lookupKey: [[fallthrough]];
|
||||||
|
case autoProxyTask::proxyStatusCheck: [[fallthrough]];
|
||||||
|
case autoProxyTask::establishConnection: [[fallthrough]];
|
||||||
|
case autoProxyTask::closeConnection:
|
||||||
|
// These are supposed to be async!
|
||||||
|
RS_WARN("unknown task or async one!");
|
||||||
|
rsAutoProxyMonitor::taskError(ticket);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void p3I2pSam3::threadTick()
|
||||||
|
{
|
||||||
|
// {
|
||||||
|
// RS_STACK_MUTEX(mLock);
|
||||||
|
// Dbg4() << __PRETTY_FUNCTION__ << " mPending: " << mPending.size() << std::endl;
|
||||||
|
// }
|
||||||
|
|
||||||
|
if(mPending.empty()) {
|
||||||
|
// sleep outisde of lock!
|
||||||
|
doSleep(std::chrono::milliseconds(250));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// get task
|
||||||
|
taskTicket *tt = nullptr;
|
||||||
|
{
|
||||||
|
RS_STACK_MUTEX(mLock);
|
||||||
|
tt = mPending.front();
|
||||||
|
mPending.pop();
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (tt->task) {
|
||||||
|
case autoProxyTask::stop:
|
||||||
|
mState = samStatus::samState::offline;
|
||||||
|
stopForwarding();
|
||||||
|
stopSession();
|
||||||
|
rsAutoProxyMonitor::taskDone(tt, autoProxyStatus::offline);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case autoProxyTask::start:
|
||||||
|
{
|
||||||
|
if (!mSetting.enable) {
|
||||||
|
rsAutoProxyMonitor::taskDone(tt, autoProxyStatus::disabled);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// create main session
|
||||||
|
mState = samStatus::samState::connectSession;
|
||||||
|
bool ret = startSession();
|
||||||
|
if (!ret) {
|
||||||
|
mState = samStatus::samState::offline;
|
||||||
|
|
||||||
|
rsAutoProxyMonitor::taskError(tt);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// start forwarding
|
||||||
|
mState = samStatus::samState::connectForward;
|
||||||
|
ret = startForwarding();
|
||||||
|
|
||||||
|
// finish ticket
|
||||||
|
if (ret) {
|
||||||
|
mState = samStatus::samState::online;
|
||||||
|
rsAutoProxyMonitor::taskDone(tt, autoProxyStatus::online);
|
||||||
|
} else {
|
||||||
|
mState = samStatus::samState::offline;
|
||||||
|
rsAutoProxyMonitor::taskError(tt);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case autoProxyTask::receiveKey:
|
||||||
|
{
|
||||||
|
i2p::address *addr = static_cast<i2p::address *>(tt->data);
|
||||||
|
if (generateKey(addr->publicKey, addr->privateKey)) {
|
||||||
|
addr->base32 = i2p::keyToBase32Addr(addr->publicKey);
|
||||||
|
rsAutoProxyMonitor::taskDone(tt, autoProxyStatus::ok);
|
||||||
|
} else {
|
||||||
|
rsAutoProxyMonitor::taskError(tt);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case autoProxyTask::lookupKey:
|
||||||
|
lookupKey(tt);
|
||||||
|
#ifdef RS_USE_I2P_SAM3_I2PSAM
|
||||||
|
// artificially delay following operations as i2psam uses time(null) as rng seed
|
||||||
|
doSleep(std::chrono::seconds(1));
|
||||||
|
#endif
|
||||||
|
break;
|
||||||
|
|
||||||
|
case autoProxyTask::proxyStatusCheck:
|
||||||
|
{
|
||||||
|
// TODO better detection of status
|
||||||
|
bool ok;
|
||||||
|
#ifdef RS_USE_I2P_SAM3_I2PSAM
|
||||||
|
ok = !mSetting.session->isSick();
|
||||||
|
#endif
|
||||||
|
#ifdef RS_USE_I2P_SAM3_LIBSAM3
|
||||||
|
ok = !!mSetting.session->fd;
|
||||||
|
ok &= !!mSetting.session->fwd_fd;
|
||||||
|
#endif // RS_USE_I2P_SAM3_LIBSAM3
|
||||||
|
*static_cast<bool*>(tt->data) = ok;
|
||||||
|
rsAutoProxyMonitor::taskDone(tt, ok ? autoProxyStatus::ok : autoProxyStatus::error);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case autoProxyTask::establishConnection:
|
||||||
|
establishConnection(tt);
|
||||||
|
break;
|
||||||
|
case autoProxyTask::closeConnection:
|
||||||
|
closeConnection(tt);
|
||||||
|
break;
|
||||||
|
case autoProxyTask::status: [[fallthrough]];
|
||||||
|
case autoProxyTask::getSettings: [[fallthrough]];
|
||||||
|
case autoProxyTask::setSettings: [[fallthrough]];
|
||||||
|
case autoProxyTask::getErrorInfo: [[fallthrough]];
|
||||||
|
case autoProxyTask::reloadConfig:
|
||||||
|
RS_ERR("unable to handle! This is a bug! task:", tt->task);
|
||||||
|
rsAutoProxyMonitor::taskError(tt);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
tt = nullptr;
|
||||||
|
|
||||||
|
// give i2p backend some time
|
||||||
|
doSleep(std::chrono::milliseconds(100));
|
||||||
|
}
|
||||||
|
|
||||||
|
RsSerialiser *p3I2pSam3::setupSerialiser()
|
||||||
|
{
|
||||||
|
RsSerialiser* rsSerialiser = new RsSerialiser();
|
||||||
|
rsSerialiser->addSerialType(new RsGeneralConfigSerialiser());
|
||||||
|
|
||||||
|
return rsSerialiser;
|
||||||
|
}
|
||||||
|
|
||||||
|
#define addKVS(_key, _value) \
|
||||||
|
kv.key = _key;\
|
||||||
|
kv.value = _value;\
|
||||||
|
vitem->tlvkvs.pairs.push_back(kv);
|
||||||
|
|
||||||
|
#define addKVSInt(_key, _value) \
|
||||||
|
kv.key = _key;\
|
||||||
|
rs_sprintf(kv.value, "%d", _value);\
|
||||||
|
vitem->tlvkvs.pairs.push_back(kv);
|
||||||
|
|
||||||
|
bool p3I2pSam3::saveList(bool &cleanup, std::list<RsItem *> &lst)
|
||||||
|
{
|
||||||
|
RS_DBG4();
|
||||||
|
|
||||||
|
cleanup = true;
|
||||||
|
RsConfigKeyValueSet *vitem = new RsConfigKeyValueSet;
|
||||||
|
RsTlvKeyValue kv;
|
||||||
|
|
||||||
|
RS_STACK_MUTEX(mLock);
|
||||||
|
addKVS(kConfigKeySAM3Enable, mSetting.enable ? "TRUE" : "FALSE")
|
||||||
|
addKVS(kConfigKeyDestPriv, mSetting.address.privateKey);
|
||||||
|
|
||||||
|
addKVSInt(kConfigKeyInLength, mSetting.inLength)
|
||||||
|
addKVSInt(kConfigKeyInQuantity, mSetting.inQuantity)
|
||||||
|
addKVSInt(kConfigKeyInVariance, mSetting.inVariance)
|
||||||
|
addKVSInt(kConfigKeyInBackupQuantity, mSetting.inBackupQuantity)
|
||||||
|
|
||||||
|
addKVSInt(kConfigKeyOutLength, mSetting.outLength)
|
||||||
|
addKVSInt(kConfigKeyOutQuantity, mSetting.outQuantity)
|
||||||
|
addKVSInt(kConfigKeyOutVariance, mSetting.outVariance)
|
||||||
|
addKVSInt(kConfigKeyOutBackupQuantity, mSetting.outBackupQuantity)
|
||||||
|
|
||||||
|
#ifdef RS_I2P_SAM3_BOB_COMPAT
|
||||||
|
// these allow SAMv3 users to switch back to BOB
|
||||||
|
// remove after some time
|
||||||
|
addKVS(kConfigKeyBOBEnable, mSetting.enable ? "TRUE" : "FALSE")
|
||||||
|
addKVS(kConfigKeyBOBKey, mSetting.address.privateKey)
|
||||||
|
addKVS(kConfigKeyBOBAddr, mSetting.address.base32)
|
||||||
|
#endif
|
||||||
|
lst.push_back(vitem);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
#undef addKVS
|
||||||
|
#undef addKVSUInt
|
||||||
|
|
||||||
|
#define getKVSUInt(_kit, _key, _value) \
|
||||||
|
else if (_kit->key == _key) {\
|
||||||
|
std::istringstream is(_kit->value);\
|
||||||
|
int tmp;\
|
||||||
|
is >> tmp;\
|
||||||
|
_value = (int8_t)tmp;\
|
||||||
|
}
|
||||||
|
|
||||||
|
bool p3I2pSam3::loadList(std::list<RsItem *> &load)
|
||||||
|
{
|
||||||
|
RS_DBG4();
|
||||||
|
|
||||||
|
std::string priv;
|
||||||
|
priv.clear();
|
||||||
|
|
||||||
|
for(std::list<RsItem*>::const_iterator it = load.begin(); it!=load.end(); ++it) {
|
||||||
|
RsConfigKeyValueSet *vitem = dynamic_cast<RsConfigKeyValueSet*>(*it);
|
||||||
|
if(vitem != NULL) {
|
||||||
|
RS_STACK_MUTEX(mLock);
|
||||||
|
for(std::list<RsTlvKeyValue>::const_iterator kit = vitem->tlvkvs.pairs.begin(); kit != vitem->tlvkvs.pairs.end(); ++kit) {
|
||||||
|
if (kit->key == kConfigKeySAM3Enable)
|
||||||
|
mSetting.enable = kit->value == "TRUE";
|
||||||
|
else if (kit->key == kConfigKeyDestPriv)
|
||||||
|
priv = kit->value;
|
||||||
|
getKVSUInt(kit, kConfigKeyInLength, mSetting.inLength)
|
||||||
|
getKVSUInt(kit, kConfigKeyInQuantity, mSetting.inQuantity)
|
||||||
|
getKVSUInt(kit, kConfigKeyInVariance, mSetting.inVariance)
|
||||||
|
getKVSUInt(kit, kConfigKeyInBackupQuantity, mSetting.inBackupQuantity)
|
||||||
|
|
||||||
|
getKVSUInt(kit, kConfigKeyOutLength, mSetting.outLength)
|
||||||
|
getKVSUInt(kit, kConfigKeyOutQuantity, mSetting.outQuantity)
|
||||||
|
getKVSUInt(kit, kConfigKeyOutVariance, mSetting.outVariance)
|
||||||
|
getKVSUInt(kit, kConfigKeyOutBackupQuantity, mSetting.outBackupQuantity)
|
||||||
|
|
||||||
|
#ifdef RS_I2P_SAM3_BOB_COMPAT
|
||||||
|
// import BOB settings
|
||||||
|
else if (kit->key == kConfigKeyBOBEnable)
|
||||||
|
mSetting.enable = kit->value == "TRUE";
|
||||||
|
else if (kit->key == kConfigKeyBOBKey) {
|
||||||
|
// don't overwirte, just import when not set already!
|
||||||
|
if (priv.empty())
|
||||||
|
priv = kit->value;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
else
|
||||||
|
RS_INFO("unknown key:", kit->key);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
delete vitem;
|
||||||
|
}
|
||||||
|
|
||||||
|
// get the pub key
|
||||||
|
std::string pub = i2p::publicKeyFromPrivate(priv);
|
||||||
|
if (pub.empty() || priv.empty())
|
||||||
|
RS_DBG("no destination to load");
|
||||||
|
else {
|
||||||
|
RS_STACK_MUTEX(mLock);
|
||||||
|
|
||||||
|
mSetting.address.publicKey = pub;
|
||||||
|
mSetting.address.privateKey = priv;
|
||||||
|
mSetting.address.base32 = i2p::keyToBase32Addr(pub);
|
||||||
|
}
|
||||||
|
|
||||||
|
RS_STACK_MUTEX(mLock);
|
||||||
|
mConfigLoaded = true;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
#undef getKVSUInt
|
||||||
|
|
||||||
|
bool p3I2pSam3::startSession()
|
||||||
|
{
|
||||||
|
RS_DBG4();
|
||||||
|
|
||||||
|
constexpr size_t len = 8;
|
||||||
|
const std::string location = RsRandom::alphaNumeric(len);
|
||||||
|
const std::string nick = "RetroShare-" + location;
|
||||||
|
|
||||||
|
std::vector<std::string> params;
|
||||||
|
{
|
||||||
|
RS_STACK_MUTEX(mLock);
|
||||||
|
|
||||||
|
// length
|
||||||
|
params.push_back(i2p::makeOption("inbound.length", mSetting.inLength));
|
||||||
|
params.push_back(i2p::makeOption("outbound.length", mSetting.outLength));
|
||||||
|
// variance
|
||||||
|
params.push_back(i2p::makeOption("inbound.lengthVariance", + mSetting.inVariance));
|
||||||
|
params.push_back(i2p::makeOption("outbound.lengthVariance", + mSetting.outVariance));
|
||||||
|
// quantity
|
||||||
|
params.push_back(i2p::makeOption("inbound.quantity", + mSetting.inQuantity));
|
||||||
|
params.push_back(i2p::makeOption("outbound.quantity", + mSetting.outQuantity));
|
||||||
|
// backup quantity
|
||||||
|
params.push_back(i2p::makeOption("inbound.backupQuantity", + mSetting.inBackupQuantity));
|
||||||
|
params.push_back(i2p::makeOption("outbound.backupQuantity", + mSetting.outBackupQuantity));
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string paramsStr;
|
||||||
|
for (auto &&p : params)
|
||||||
|
paramsStr.append(p + " ");
|
||||||
|
// keep trailing space for easier extending when necessary
|
||||||
|
|
||||||
|
#ifdef RS_USE_I2P_SAM3_I2PSAM
|
||||||
|
if(mSetting.session) {
|
||||||
|
RS_STACK_MUTEX(mLock);
|
||||||
|
|
||||||
|
delete mSetting.session; // stopForwardingAll(); is called in destructor
|
||||||
|
mSetting.session = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
SAM::StreamSession *session;
|
||||||
|
|
||||||
|
if(!mSetting.address.privateKey.empty()) {
|
||||||
|
Dbg3() << __PRETTY_FUNCTION__ << " with destination" << std::endl;
|
||||||
|
session = new SAM::StreamSession(nick, SAM_DEFAULT_ADDRESS, SAM_DEFAULT_PORT, mSetting.address.privateKey, paramsStr);
|
||||||
|
} else {
|
||||||
|
Dbg3() << __PRETTY_FUNCTION__ << " without destination" << std::endl;
|
||||||
|
session = new SAM::StreamSession(nick, SAM_DEFAULT_ADDRESS, SAM_DEFAULT_PORT, SAM_GENERATE_MY_DESTINATION, paramsStr, "DSA_SHA1");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!session || session->isSick()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* i2psam is sometimes unable to reliable read the public key, which is crucial to base32 address generation
|
||||||
|
* (due to the fact that is assumes it's length wrongly)
|
||||||
|
*
|
||||||
|
* The following are attempts to reliable receive our public key
|
||||||
|
*/
|
||||||
|
|
||||||
|
const auto dest = session->getMyDestination();
|
||||||
|
// auto copy = dest;
|
||||||
|
std::string pubKey1 = dest.pub;
|
||||||
|
std::string pubKey2(dest.pub);
|
||||||
|
i2p::validatePubkeyFromPrivKey(pubKey2, dest.priv);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* pubkeys:
|
||||||
|
* 1: from initial call (== dest.pub)
|
||||||
|
* 2: from parsing (was == dest.pub
|
||||||
|
*/
|
||||||
|
Dbg3() << __PRETTY_FUNCTION__ << " figuring out our pubKey: p1 " << pubKey1 << std::endl;
|
||||||
|
Dbg3() << __PRETTY_FUNCTION__ << " figuring out our pubKey: p2 " << pubKey2 << std::endl;
|
||||||
|
if (pubKey1 == pubKey2) {
|
||||||
|
// unchanged
|
||||||
|
Dbg3() << __PRETTY_FUNCTION__ << " figuring out our pubKey: p1 == p2" << std::endl;
|
||||||
|
} else {
|
||||||
|
// parsed pub key is different, prefer parsed one
|
||||||
|
pubKey1 = pubKey2;
|
||||||
|
Dbg3() << __PRETTY_FUNCTION__ << " figuring out our pubKey: p1 != p2" << std::endl;
|
||||||
|
}
|
||||||
|
SAM::FullDestination dest2(pubKey1, dest.priv, true);
|
||||||
|
|
||||||
|
// populate settings
|
||||||
|
RS_STACK_MUTEX(mLock);
|
||||||
|
mSetting.session = session;
|
||||||
|
if (!mSetting.address.publicKey.empty() && mSetting.address.publicKey != dest2.pub)
|
||||||
|
// This should be ok for non hidden locations. This should be a problem for hidden i2p locations...
|
||||||
|
RsDbg() << __PRETTY_FUNCTION__ << " public key changed! Yet unsure if this is ok or a problem" << std::endl;
|
||||||
|
mSetting.address.publicKey = dest2.pub;
|
||||||
|
mSetting.address.base32 = i2p::keyToBase32Addr(dest2.pub);
|
||||||
|
// do not overwrite the private key, if any!!
|
||||||
|
|
||||||
|
#endif
|
||||||
|
#ifdef RS_USE_I2P_SAM3_LIBSAM3
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
if (mSetting.session) {
|
||||||
|
stopSession();
|
||||||
|
}
|
||||||
|
|
||||||
|
auto session = new Sam3Session();
|
||||||
|
|
||||||
|
// add nick
|
||||||
|
paramsStr.append("inbound.nickname=" + nick); // leading space is already there
|
||||||
|
|
||||||
|
{
|
||||||
|
RS_STACK_MUTEX(mLockSam3Access);
|
||||||
|
|
||||||
|
if(!mSetting.address.privateKey.empty()) {
|
||||||
|
RS_DBG3("with destination");
|
||||||
|
ret = sam3CreateSilentSession(session, SAM3_HOST_DEFAULT, SAM3_PORT_DEFAULT, mSetting.address.privateKey.c_str(), Sam3SessionType::SAM3_SESSION_STREAM, Sam3SigType::EdDSA_SHA512_Ed25519, paramsStr.c_str());
|
||||||
|
} else {
|
||||||
|
RS_DBG("without destination");
|
||||||
|
ret = sam3CreateSilentSession(session, SAM3_HOST_DEFAULT, SAM3_PORT_DEFAULT, SAM3_DESTINATION_TRANSIENT, Sam3SessionType::SAM3_SESSION_STREAM, Sam3SigType::EdDSA_SHA512_Ed25519, paramsStr.c_str());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ret != 0) {
|
||||||
|
delete session;
|
||||||
|
session = nullptr;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
#if 0 // this check is useless. For non i2p hidden locations the public key is temporal anyway and for i2p hidden ones, it is part of the (fixed) private key.
|
||||||
|
if (!mSetting.address.publicKey.empty() && mSetting.address.publicKey != session->pubkey)
|
||||||
|
// This should be ok for non hidden locations. This should be a problem for hidden i2p locations...
|
||||||
|
RS_DBG("public key changed! Yet unsure if this is ok or a problem. Should be fine for non i2p hidden locations or clear net.");
|
||||||
|
#endif
|
||||||
|
/*
|
||||||
|
* Note: sam3CreateSession will issue a name looup of "ME" to receive its public key, thus it is always correct.
|
||||||
|
* No need to use i2p::publicKeyFromPrivate()
|
||||||
|
*/
|
||||||
|
RS_STACK_MUTEX(mLock);
|
||||||
|
mSetting.session = session;
|
||||||
|
mSetting.address.publicKey = session->pubkey;
|
||||||
|
mSetting.address.base32 = i2p::keyToBase32Addr(session->pubkey);
|
||||||
|
// do not overwrite the private key, if any!!
|
||||||
|
#endif
|
||||||
|
|
||||||
|
RS_DBG1("nick:", nick, "address:", mSetting.address.base32);
|
||||||
|
RS_DBG2(" myDestination.pub ", mSetting.address.publicKey);
|
||||||
|
RS_DBG2(" myDestination.priv", mSetting.address.privateKey);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool p3I2pSam3::startForwarding()
|
||||||
|
{
|
||||||
|
RS_DBG4();
|
||||||
|
|
||||||
|
if(mSetting.address.privateKey.empty()) {
|
||||||
|
RS_DBG3("no private key set");
|
||||||
|
// IMPORANT: return true here!
|
||||||
|
// since there is no forward session for non hidden nodes, this funtion is successfull by doing nothing
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!mSetting.session) {
|
||||||
|
RS_WARN("no session found!");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
peerState ps;
|
||||||
|
mPeerMgr->getOwnNetStatus(ps);
|
||||||
|
|
||||||
|
#ifdef RS_USE_I2P_SAM3_I2PSAM
|
||||||
|
auto ret = mSetting.session->forward(sockaddr_storage_iptostring(ps.localaddr).c_str(), sockaddr_storage_port(ps.localaddr), true);
|
||||||
|
if (!ret.isOk)
|
||||||
|
RsDbg() << __PRETTY_FUNCTION__ << " forward failed" << std::endl;
|
||||||
|
else
|
||||||
|
Dbg2() << __PRETTY_FUNCTION__ << " forward successfull" << std::endl;
|
||||||
|
|
||||||
|
return ret.isOk;
|
||||||
|
#endif
|
||||||
|
#ifdef RS_USE_I2P_SAM3_LIBSAM3
|
||||||
|
RS_STACK_MUTEX(mLockSam3Access);
|
||||||
|
|
||||||
|
int ret = sam3StreamForward(mSetting.session, sockaddr_storage_iptostring(ps.localaddr).c_str(), sockaddr_storage_port(ps.localaddr));
|
||||||
|
|
||||||
|
if (ret < 0) {
|
||||||
|
RS_DBG("forward failed, due to", mSetting.session->error);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void p3I2pSam3::stopSession()
|
||||||
|
{
|
||||||
|
RS_DBG4();
|
||||||
|
|
||||||
|
{
|
||||||
|
RS_STACK_MUTEX(mLock);
|
||||||
|
if (!mSetting.session)
|
||||||
|
return;
|
||||||
|
#ifdef RS_USE_I2P_SAM3_I2PSAM
|
||||||
|
// TODO cleanup sockets
|
||||||
|
delete mSetting.session; // will stop forwarding, too
|
||||||
|
#endif
|
||||||
|
#ifdef RS_USE_I2P_SAM3_LIBSAM3
|
||||||
|
// swap connections
|
||||||
|
mInvalidConnections = mValidConnections;
|
||||||
|
mValidConnections.clear();
|
||||||
|
|
||||||
|
RS_STACK_MUTEX(mLockSam3Access);
|
||||||
|
sam3CloseSession(mSetting.session);
|
||||||
|
delete mSetting.session;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
mSetting.session = nullptr;
|
||||||
|
mState = samStatus::samState::offline;
|
||||||
|
}
|
||||||
|
|
||||||
|
// At least i2pd doesn't like to instantaniously stop and (re)start a session, wait here just a little bit.
|
||||||
|
// Not ideal but does the trick.
|
||||||
|
// (This happens when using the "restart" button in the settings.)
|
||||||
|
doSleep(std::chrono::seconds(10));
|
||||||
|
}
|
||||||
|
|
||||||
|
void p3I2pSam3::stopForwarding()
|
||||||
|
{
|
||||||
|
// nothing to do here, forwarding is stop when closing the seassion
|
||||||
|
}
|
||||||
|
|
||||||
|
bool p3I2pSam3::generateKey(std::string &pub, std::string &priv)
|
||||||
|
{
|
||||||
|
RS_DBG4();
|
||||||
|
|
||||||
|
pub.clear();
|
||||||
|
priv.clear();
|
||||||
|
|
||||||
|
#ifdef RS_USE_I2P_SAM3_I2PSAM
|
||||||
|
auto ss = new SAM::StreamSession("RS-destgen");
|
||||||
|
auto ret = ss->destGenerate();
|
||||||
|
if (!ret.isOk)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
auto dest = ret.value;
|
||||||
|
pub = std::string(dest.pub);
|
||||||
|
priv = std::string(dest.priv);
|
||||||
|
|
||||||
|
#endif
|
||||||
|
#ifdef RS_USE_I2P_SAM3_LIBSAM3
|
||||||
|
// The session is only usef for transporting the data
|
||||||
|
Sam3Session ss;
|
||||||
|
|
||||||
|
if (0 > sam3GenerateKeys(&ss, SAM3_HOST_DEFAULT, SAM3_PORT_DEFAULT, Sam3SigType::EdDSA_SHA512_Ed25519)) {
|
||||||
|
RS_DBG("got error:", ss.error);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
pub = std::string(ss.pubkey);
|
||||||
|
priv = std::string(ss.privkey);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
RS_DBG2("publuc key / address", pub);
|
||||||
|
RS_DBG2("private key", priv);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void p3I2pSam3::lookupKey(taskTicket *ticket)
|
||||||
|
{
|
||||||
|
// this can be called independend of the main SAM session!
|
||||||
|
|
||||||
|
auto addr = static_cast<i2p::address*>(ticket->data);
|
||||||
|
if (addr->base32.empty()) {
|
||||||
|
RS_ERR("lookupKey: called with empty address");
|
||||||
|
rsAutoProxyMonitor::taskError(ticket);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
#ifdef RS_USE_I2P_SAM3_I2PSAM
|
||||||
|
auto sam = mSetting.session;
|
||||||
|
RsThread::async([ticket, sam]()
|
||||||
|
#endif
|
||||||
|
#ifdef RS_USE_I2P_SAM3_LIBSAM3
|
||||||
|
RsThread::async([ticket]()
|
||||||
|
#endif
|
||||||
|
{
|
||||||
|
auto addr = static_cast<i2p::address*>(ticket->data);
|
||||||
|
|
||||||
|
#ifdef RS_USE_I2P_SAM3_I2PSAM
|
||||||
|
auto r = sam->namingLookup(addr->base32);
|
||||||
|
if (!r.isOk) {
|
||||||
|
// get error
|
||||||
|
RsDbg() << __PRETTY_FUNCTION__ << " key: " << addr->base32 << std::endl;
|
||||||
|
RsDbg() << __PRETTY_FUNCTION__ << " got error!" << std::endl;
|
||||||
|
rsAutoProxyMonitor::taskError(ticket);
|
||||||
|
} else {
|
||||||
|
addr->publicKey = r.value;
|
||||||
|
rsAutoProxyMonitor::taskDone(ticket, autoProxyStatus::ok);
|
||||||
|
Dbg1() << __PRETTY_FUNCTION__ << " success " << std::endl;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
#ifdef RS_USE_I2P_SAM3_LIBSAM3
|
||||||
|
// The session is only usef for transporting the data
|
||||||
|
Sam3Session ss;
|
||||||
|
int ret = sam3NameLookup(&ss, SAM3_HOST_DEFAULT, SAM3_PORT_DEFAULT, addr->base32.c_str());
|
||||||
|
if (ret < 0) {
|
||||||
|
// get error
|
||||||
|
RS_DBG("key:", addr->base32);
|
||||||
|
RS_DBG("got error:", ss.error);
|
||||||
|
rsAutoProxyMonitor::taskError(ticket);
|
||||||
|
} else {
|
||||||
|
addr->publicKey = ss.destkey;
|
||||||
|
rsAutoProxyMonitor::taskDone(ticket, autoProxyStatus::ok);
|
||||||
|
RS_DBG1("success");
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
void p3I2pSam3::establishConnection(taskTicket *ticket)
|
||||||
|
{
|
||||||
|
if (mState != samStatus::samState::online || !mSetting.session) {
|
||||||
|
RS_WARN("no session found!");
|
||||||
|
rsAutoProxyMonitor::taskError(ticket);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
samEstablishConnectionWrapper *wrapper = static_cast<samEstablishConnectionWrapper*>(ticket->data);
|
||||||
|
if (wrapper->address.publicKey.empty()) {
|
||||||
|
RS_ERR("no public key given");
|
||||||
|
rsAutoProxyMonitor::taskError(ticket);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
RsThread::async([ticket, this]() {
|
||||||
|
auto wrapper = static_cast<samEstablishConnectionWrapper*>(ticket->data);
|
||||||
|
#ifdef RS_USE_I2P_SAM3_I2PSAM
|
||||||
|
auto r = this->mSetting.session->connect(wrapper->address.publicKey.c_str(), false); // silent=true is broken!
|
||||||
|
if (!r.isOk) {
|
||||||
|
// get error
|
||||||
|
RsDbg() << __PRETTY_FUNCTION__ << " got error!" << std::endl;
|
||||||
|
rsAutoProxyMonitor::taskError(ticket);
|
||||||
|
} else {
|
||||||
|
// extract socket
|
||||||
|
wrapper->socket = r.value.get()->release();
|
||||||
|
Dbg1() << __PRETTY_FUNCTION__ << " success " << std::endl;
|
||||||
|
rsAutoProxyMonitor::taskDone(ticket, autoProxyStatus::ok);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
#ifdef RS_USE_I2P_SAM3_LIBSAM3
|
||||||
|
struct Sam3Connection *connection;
|
||||||
|
{
|
||||||
|
auto l = this->mLockSam3Access;
|
||||||
|
RS_STACK_MUTEX(l);
|
||||||
|
connection = sam3StreamConnect(this->mSetting.session, wrapper->address.publicKey.c_str());
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!connection) {
|
||||||
|
// get error
|
||||||
|
RS_DBG("got error:", this->mSetting.session->error);
|
||||||
|
rsAutoProxyMonitor::taskError(ticket);
|
||||||
|
} else {
|
||||||
|
wrapper->connection = connection;
|
||||||
|
{
|
||||||
|
auto l = this->mLockSam3Access;
|
||||||
|
RS_STACK_MUTEX(l);
|
||||||
|
this->mValidConnections.push_back(connection);
|
||||||
|
}
|
||||||
|
RS_DBG1("success");
|
||||||
|
rsAutoProxyMonitor::taskDone(ticket, autoProxyStatus::ok);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
void p3I2pSam3::closeConnection(taskTicket *ticket)
|
||||||
|
{
|
||||||
|
Sam3Connection *con = static_cast<Sam3Connection*>(ticket->data);
|
||||||
|
|
||||||
|
if (mState == samStatus::samState::offline || !mSetting.session) {
|
||||||
|
// no session found, sam was likel stopped
|
||||||
|
} else {
|
||||||
|
RS_STACK_MUTEX(mLock);
|
||||||
|
|
||||||
|
bool callClose = true;
|
||||||
|
// search in current connections
|
||||||
|
auto it = std::find(mValidConnections.begin(), mValidConnections.end(), con);
|
||||||
|
if (it != mValidConnections.end()) {
|
||||||
|
mValidConnections.erase(it);
|
||||||
|
} else {
|
||||||
|
// search in old connections
|
||||||
|
it = std::find(mInvalidConnections.begin(), mInvalidConnections.end(), con);
|
||||||
|
if (it != mInvalidConnections.end()) {
|
||||||
|
// old connection, just ignore. *should* be freed already
|
||||||
|
callClose = false;
|
||||||
|
con = nullptr;
|
||||||
|
} else {
|
||||||
|
// weird
|
||||||
|
RS_WARN("could'n find connection!");
|
||||||
|
|
||||||
|
// best thing we can do here
|
||||||
|
callClose = false;
|
||||||
|
con = nullptr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (callClose) {
|
||||||
|
RS_STACK_MUTEX(mLockSam3Access);
|
||||||
|
sam3CloseConnection(con);
|
||||||
|
con = nullptr; // freed by above call
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (con) {
|
||||||
|
delete con;
|
||||||
|
con = nullptr;
|
||||||
|
}
|
||||||
|
ticket->data = nullptr;
|
||||||
|
rsAutoProxyMonitor::taskDone(ticket, autoProxyStatus::ok);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
void p3I2pSam3::updateSettings_locked()
|
||||||
|
{
|
||||||
|
RS_DBG4();
|
||||||
|
IndicateConfigChanged();
|
||||||
|
|
||||||
|
#if 0 // TODO recreat session when active, can we just recreat it?
|
||||||
|
if (mSs) {
|
||||||
|
stopSession();
|
||||||
|
startSession();
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
128
libretroshare/src/services/autoproxy/p3i2psam3.h
Normal file
128
libretroshare/src/services/autoproxy/p3i2psam3.h
Normal file
@ -0,0 +1,128 @@
|
|||||||
|
#ifndef P3I2PSAM3_H
|
||||||
|
#define P3I2PSAM3_H
|
||||||
|
|
||||||
|
#include <queue>
|
||||||
|
#include <list>
|
||||||
|
|
||||||
|
#include "services/autoproxy/rsautoproxymonitor.h"
|
||||||
|
#include "pqi/p3cfgmgr.h"
|
||||||
|
#include "util/i2pcommon.h"
|
||||||
|
#include "util/rsthreads.h"
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This class implements I2P SAMv3 (Simple Anonymous Messaging) to allow RS
|
||||||
|
* to automatically setup tunnel to and from I2P.
|
||||||
|
* SAMv3 is a simple text-based interface: https://geti2p.net/de/docs/api/samv3
|
||||||
|
*
|
||||||
|
* For the actual SAM commands / low level stuff libsam3 (https://github.com/i2p/libsam3)
|
||||||
|
* is used with some minor adjustments, for exmaple, the FORWARD session is always silent.
|
||||||
|
*
|
||||||
|
* SAM in a nutshell works like this:
|
||||||
|
* 1) setup main/control session which configures everything (destination ID, tunnel number, hops number, and so on)
|
||||||
|
* 2) setup a forward session, so that I2P will establish a connection to RS for each incoming connection to our i2p destination
|
||||||
|
* 3a) query/lookup the destination (public key) for a given i2p address
|
||||||
|
* 3b) connect to the given destination
|
||||||
|
*
|
||||||
|
* An established connection (both incoming or outgoing) are then handed over to RS.
|
||||||
|
* The lifetime of a session (and its subordinates connections) is bound to their tcp socket. When the socket closes, the session is closed, too.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
class p3PeerMgr;
|
||||||
|
|
||||||
|
// typedef samSession is used to unify access to the session independent of the underlying library
|
||||||
|
#ifdef RS_USE_I2P_SAM3_I2PSAM
|
||||||
|
namespace SAM {
|
||||||
|
class StreamSession;
|
||||||
|
class I2pSocket;
|
||||||
|
}
|
||||||
|
|
||||||
|
typedef SAM::StreamSession samSession;
|
||||||
|
#endif
|
||||||
|
#ifdef RS_USE_I2P_SAM3_LIBSAM3
|
||||||
|
class Sam3Session;
|
||||||
|
class Sam3Connection;
|
||||||
|
|
||||||
|
typedef Sam3Session samSession;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
struct samSettings : i2p::settings {
|
||||||
|
samSession *session;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct samEstablishConnectionWrapper {
|
||||||
|
i2p::address address;
|
||||||
|
#ifdef RS_USE_I2P_SAM3_I2PSAM
|
||||||
|
int socket;
|
||||||
|
#endif
|
||||||
|
#ifdef RS_USE_I2P_SAM3_LIBSAM3
|
||||||
|
Sam3Connection *connection;
|
||||||
|
#endif
|
||||||
|
};
|
||||||
|
|
||||||
|
struct samStatus {
|
||||||
|
std::string sessionName;
|
||||||
|
enum samState {
|
||||||
|
offline,
|
||||||
|
connectSession,
|
||||||
|
connectForward,
|
||||||
|
online
|
||||||
|
} state; // the name is kinda redundant ...
|
||||||
|
};
|
||||||
|
|
||||||
|
class p3I2pSam3 : public RsTickingThread, public p3Config, public autoProxyService
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
p3I2pSam3(p3PeerMgr *peerMgr);
|
||||||
|
|
||||||
|
// autoProxyService interface
|
||||||
|
public:
|
||||||
|
bool isEnabled();
|
||||||
|
bool initialSetup(std::string &addr, uint16_t &port);
|
||||||
|
void processTaskAsync(taskTicket *ticket);
|
||||||
|
void processTaskSync(taskTicket *ticket);
|
||||||
|
|
||||||
|
// RsTickingThread interface
|
||||||
|
public:
|
||||||
|
void threadTick(); /// @see RsTickingThread
|
||||||
|
|
||||||
|
// p3Config interface
|
||||||
|
protected:
|
||||||
|
RsSerialiser *setupSerialiser();
|
||||||
|
bool saveList(bool &cleanup, std::list<RsItem *> &);
|
||||||
|
bool loadList(std::list<RsItem *> &load);
|
||||||
|
|
||||||
|
private:
|
||||||
|
bool startSession();
|
||||||
|
bool startForwarding();
|
||||||
|
void stopSession();
|
||||||
|
void stopForwarding();
|
||||||
|
|
||||||
|
bool generateKey(std::string &pub, std::string &priv);
|
||||||
|
void lookupKey(taskTicket *ticket);
|
||||||
|
void establishConnection(taskTicket *ticket);
|
||||||
|
void closeConnection(taskTicket *ticket);
|
||||||
|
void updateSettings_locked();
|
||||||
|
|
||||||
|
bool mConfigLoaded;
|
||||||
|
|
||||||
|
samSettings mSetting;
|
||||||
|
p3PeerMgr *mPeerMgr;
|
||||||
|
std::queue<taskTicket *> mPending;
|
||||||
|
|
||||||
|
// Used to report the state to the gui
|
||||||
|
// (Since the create session call/will can block and there is no easy way from outside the main thread to see
|
||||||
|
// what is going on, it is easier to store the current state in an extra variable independen from the main thread)
|
||||||
|
samStatus::samState mState;
|
||||||
|
|
||||||
|
// used to keep track of connections, libsam3 does it internally but it can be unreliable since pointers are shared
|
||||||
|
std::list<Sam3Connection *> mValidConnections, mInvalidConnections;
|
||||||
|
|
||||||
|
// mutex
|
||||||
|
RsMutex mLock;
|
||||||
|
#ifdef RS_USE_I2P_SAM3_LIBSAM3
|
||||||
|
RsMutex mLockSam3Access; // libsam3 is not thread safe! (except for key lookup)
|
||||||
|
#endif
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // P3I2PSAM3_H
|
@ -329,14 +329,22 @@ autoProxyService *rsAutoProxyMonitor::lookUpService(autoProxyType::autoProxyType
|
|||||||
|
|
||||||
bool rsAutoProxyMonitor::isAsyncTask(autoProxyTask::autoProxyTask_enum t)
|
bool rsAutoProxyMonitor::isAsyncTask(autoProxyTask::autoProxyTask_enum t)
|
||||||
{
|
{
|
||||||
|
// Explicit list all values, so that missing ones will be detected by the compiler.
|
||||||
switch (t) {
|
switch (t) {
|
||||||
case autoProxyTask::start:
|
case autoProxyTask::start: [[fallthrough]];
|
||||||
case autoProxyTask::stop:
|
case autoProxyTask::stop: [[fallthrough]];
|
||||||
case autoProxyTask::receiveKey:
|
case autoProxyTask::receiveKey: [[fallthrough]];
|
||||||
|
case autoProxyTask::lookupKey: [[fallthrough]];
|
||||||
|
case autoProxyTask::establishConnection: [[fallthrough]];
|
||||||
|
case autoProxyTask::closeConnection:
|
||||||
return true;
|
return true;
|
||||||
break;
|
case autoProxyTask::status: [[fallthrough]];
|
||||||
default:
|
case autoProxyTask::getSettings: [[fallthrough]];
|
||||||
break;
|
case autoProxyTask::setSettings: [[fallthrough]];
|
||||||
|
case autoProxyTask::getErrorInfo: [[fallthrough]];
|
||||||
|
case autoProxyTask::reloadConfig: [[fallthrough]];
|
||||||
|
case autoProxyTask::proxyStatusCheck:
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -31,23 +31,27 @@ class autoProxyCallback;
|
|||||||
|
|
||||||
namespace autoProxyType {
|
namespace autoProxyType {
|
||||||
enum autoProxyType_enum {
|
enum autoProxyType_enum {
|
||||||
I2PBOB
|
// I2PBOB,
|
||||||
|
I2PSAM3
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace autoProxyTask {
|
namespace autoProxyTask {
|
||||||
enum autoProxyTask_enum {
|
enum autoProxyTask_enum {
|
||||||
/* async tasks */
|
/* async tasks */
|
||||||
start, ///< start up proxy
|
start, ///< start up proxy
|
||||||
stop, ///< shut down proxy
|
stop, ///< shut down proxy
|
||||||
receiveKey, ///< renew proxy key (if any)
|
receiveKey, ///< renew proxy key (if any)
|
||||||
proxyStatusCheck, ///< use to check if the proxy is still running
|
lookupKey, ///< look up a base32 addr
|
||||||
|
proxyStatusCheck, ///< use to check if the proxy is still running
|
||||||
|
establishConnection, ///< create a connection to a given public key or base32 address
|
||||||
|
closeConnection, ///< closes a connection
|
||||||
/* sync tasks */
|
/* sync tasks */
|
||||||
status, ///< get status from auto proxy
|
status, ///< get status from auto proxy
|
||||||
getSettings, ///< get setting from auto proxy
|
getSettings, ///< get setting from auto proxy
|
||||||
setSettings, ///< set setting of auto proxy
|
setSettings, ///< set setting of auto proxy
|
||||||
reloadConfig, ///< signal config reload/rebuild
|
reloadConfig, ///< signal config reload/rebuild
|
||||||
getErrorInfo ///< get error information from auto proxy
|
getErrorInfo ///< get error information from auto proxy
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -90,6 +90,15 @@ rs_broadcast_discovery {
|
|||||||
win32-g++|win32-clang-g++:dLibs *= wsock32
|
win32-g++|win32-clang-g++:dLibs *= wsock32
|
||||||
}
|
}
|
||||||
|
|
||||||
|
rs_sam3_libsam3 {
|
||||||
|
LIBSAM3_SRC_PATH=$$clean_path($${RS_SRC_PATH}/supportlibs/libsam3/)
|
||||||
|
LIBSAM3_BUILD_PATH=$$clean_path($${RS_BUILD_PATH}/supportlibs/libsam3/)
|
||||||
|
INCLUDEPATH *= $$clean_path($${LIBSAM3_SRC_PATH}/src/libsam3/)
|
||||||
|
DEPENDPATH *= $$clean_path($${LIBSAM3_BUILD_PATH})
|
||||||
|
QMAKE_LIBDIR *= $$clean_path($${LIBSAM3_BUILD_PATH})
|
||||||
|
LIBS *= -L$$clean_path($${LIBSAM3_BUILD_PATH}) -lsam3
|
||||||
|
}
|
||||||
|
|
||||||
static {
|
static {
|
||||||
sLibs *= $$mLibs
|
sLibs *= $$mLibs
|
||||||
} else {
|
} else {
|
||||||
|
@ -50,7 +50,7 @@ std::string publicKeyFromPrivate(std::string const &priv)
|
|||||||
* https://geti2p.net/spec/common-structures#keysandcert
|
* https://geti2p.net/spec/common-structures#keysandcert
|
||||||
* https://geti2p.net/spec/common-structures#certificate
|
* https://geti2p.net/spec/common-structures#certificate
|
||||||
*/
|
*/
|
||||||
if (priv.length() < 884) // base64 ( = 663 bytes = KeyCert + priv Keys)
|
if (priv.empty() || priv.length() < 884) // base64 ( = 663 bytes = KeyCert + priv Keys)
|
||||||
return std::string();
|
return std::string();
|
||||||
|
|
||||||
// creat a copy to work on, need to convert it to standard base64
|
// creat a copy to work on, need to convert it to standard base64
|
||||||
@ -163,6 +163,9 @@ std::string publicKeyFromPrivate(std::string const &priv)
|
|||||||
|
|
||||||
bool getKeyTypes(const std::string &key, std::string &signingKey, std::string &cryptoKey)
|
bool getKeyTypes(const std::string &key, std::string &signingKey, std::string &cryptoKey)
|
||||||
{
|
{
|
||||||
|
if (key.length() < 522) // base64 (391 bytes = 384 bytes + 7 bytes = KeysAndCert + Certificate)
|
||||||
|
return false;
|
||||||
|
|
||||||
// creat a copy to work on, need to convert it to standard base64
|
// creat a copy to work on, need to convert it to standard base64
|
||||||
auto key_copy(key);
|
auto key_copy(key);
|
||||||
std::replace(key_copy.begin(), key_copy.end(), '~', '/');
|
std::replace(key_copy.begin(), key_copy.end(), '~', '/');
|
||||||
@ -225,7 +228,7 @@ bool getKeyTypes(const std::string &key, std::string &signingKey, std::string &c
|
|||||||
// now convert to string (this would be easier with c++17)
|
// now convert to string (this would be easier with c++17)
|
||||||
#define HELPER(a, b, c) \
|
#define HELPER(a, b, c) \
|
||||||
case static_cast<typename std::underlying_type<a>::type>(a::c): \
|
case static_cast<typename std::underlying_type<a>::type>(a::c): \
|
||||||
b = "c"; \
|
b = #c; \
|
||||||
break;
|
break;
|
||||||
|
|
||||||
switch (signingKeyType) {
|
switch (signingKeyType) {
|
||||||
|
@ -210,7 +210,7 @@ std::string publicKeyFromPrivate(const std::string &priv);
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief getKeyTypes returns the name of the utilized algorithms used by the key
|
* @brief getKeyTypes returns the name of the utilized algorithms used by the key
|
||||||
* @param key public key (private works, too)
|
* @param key public key
|
||||||
* @param signingKey name of the signing key, e.g. DSA_SHA1
|
* @param signingKey name of the signing key, e.g. DSA_SHA1
|
||||||
* @param cryptoKey name of the crpyto key, e.g. ElGamal
|
* @param cryptoKey name of the crpyto key, e.g. ElGamal
|
||||||
* @return true on success, false otherwise
|
* @return true on success, false otherwise
|
||||||
|
@ -19,5 +19,5 @@
|
|||||||
TEMPLATE = subdirs
|
TEMPLATE = subdirs
|
||||||
|
|
||||||
SUBDIRS += \
|
SUBDIRS += \
|
||||||
VOIP \
|
VOIP \
|
||||||
FeedReader
|
FeedReader
|
||||||
|
@ -539,12 +539,12 @@ void GenCertDialog::genPerson()
|
|||||||
std::string hl = ui.hiddenaddr_input->text().toStdString();
|
std::string hl = ui.hiddenaddr_input->text().toStdString();
|
||||||
uint16_t port = ui.hiddenport_spinBox->value();
|
uint16_t port = ui.hiddenport_spinBox->value();
|
||||||
|
|
||||||
bool useBob = ui.cbUseBob->isChecked();
|
bool useI2p = ui.cbUseBob->isChecked();
|
||||||
|
|
||||||
if (useBob && hl.empty())
|
if (useI2p && hl.empty())
|
||||||
hl = "127.0.0.1";
|
hl = "127.0.0.1";
|
||||||
|
|
||||||
RsInit::SetHiddenLocation(hl, port, useBob); /* parses it */
|
RsInit::SetHiddenLocation(hl, port, useI2p); /* parses it */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -6,8 +6,8 @@
|
|||||||
<rect>
|
<rect>
|
||||||
<x>0</x>
|
<x>0</x>
|
||||||
<y>0</y>
|
<y>0</y>
|
||||||
<width>712</width>
|
<width>726</width>
|
||||||
<height>502</height>
|
<height>579</height>
|
||||||
</rect>
|
</rect>
|
||||||
</property>
|
</property>
|
||||||
<layout class="QVBoxLayout" name="ServerPageVLayout">
|
<layout class="QVBoxLayout" name="ServerPageVLayout">
|
||||||
@ -908,9 +908,9 @@ If you have issues connecting over Tor check the Tor logs too.</string>
|
|||||||
</item>
|
</item>
|
||||||
</layout>
|
</layout>
|
||||||
</widget>
|
</widget>
|
||||||
<widget class="QWidget" name="hiddenServiceTabI2PBOB">
|
<widget class="QWidget" name="hiddenServiceTabI2P">
|
||||||
<attribute name="title">
|
<attribute name="title">
|
||||||
<string>Automatic I2P/BOB</string>
|
<string>Automatic I2P</string>
|
||||||
</attribute>
|
</attribute>
|
||||||
<layout class="QVBoxLayout" name="hiddenServiceTabI2PBOBVLayout">
|
<layout class="QVBoxLayout" name="hiddenServiceTabI2PBOBVLayout">
|
||||||
<item>
|
<item>
|
||||||
@ -918,7 +918,7 @@ If you have issues connecting over Tor check the Tor logs too.</string>
|
|||||||
<item>
|
<item>
|
||||||
<widget class="QCheckBox" name="cb_enableBob">
|
<widget class="QCheckBox" name="cb_enableBob">
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>Enable I2P BOB - changing this requires a restart to fully take effect</string>
|
<string>Enable I2P SAMv3 - changing this requires a restart to fully take effect</string>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
@ -950,7 +950,7 @@ If you have issues connecting over Tor check the Tor logs too.</string>
|
|||||||
<item>
|
<item>
|
||||||
<widget class="QGroupBox" name="gbBob">
|
<widget class="QGroupBox" name="gbBob">
|
||||||
<property name="title">
|
<property name="title">
|
||||||
<string>I2P Basic Open Bridge</string>
|
<string>I2P Simple Anonymous Messaging</string>
|
||||||
</property>
|
</property>
|
||||||
<layout class="QVBoxLayout" name="gbBobVLayout">
|
<layout class="QVBoxLayout" name="gbBobVLayout">
|
||||||
<item>
|
<item>
|
||||||
@ -990,6 +990,12 @@ If you have issues connecting over Tor check the Tor logs too.</string>
|
|||||||
</item>
|
</item>
|
||||||
<item>
|
<item>
|
||||||
<widget class="QSpinBox" name="hiddenpage_proxyPort_i2p_2">
|
<widget class="QSpinBox" name="hiddenpage_proxyPort_i2p_2">
|
||||||
|
<property name="enabled">
|
||||||
|
<bool>false</bool>
|
||||||
|
</property>
|
||||||
|
<property name="toolTip">
|
||||||
|
<string>Not required for SAMv3</string>
|
||||||
|
</property>
|
||||||
<property name="minimum">
|
<property name="minimum">
|
||||||
<number>10</number>
|
<number>10</number>
|
||||||
</property>
|
</property>
|
||||||
@ -1016,7 +1022,7 @@ If you have issues connecting over Tor check the Tor logs too.</string>
|
|||||||
<string><html><head/><body><p>This led is green when the port listen on the left is active on your computer. It does not</p><p>mean that your Retroshare traffic transits though I2P. It will do so only if </p><p>you connect to Hidden nodes, or if you are running a Hidden node yourself.</p></body></html></string>
|
<string><html><head/><body><p>This led is green when the port listen on the left is active on your computer. It does not</p><p>mean that your Retroshare traffic transits though I2P. It will do so only if </p><p>you connect to Hidden nodes, or if you are running a Hidden node yourself.</p></body></html></string>
|
||||||
</property>
|
</property>
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>BOB accessible</string>
|
<string>SAM accessible</string>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
@ -1304,6 +1310,13 @@ If you have issues connecting over Tor check the Tor logs too.</string>
|
|||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QLabel" name="samKeyInfo">
|
||||||
|
<property name="text">
|
||||||
|
<string notr="true"><key info></string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
</layout>
|
</layout>
|
||||||
</item>
|
</item>
|
||||||
</layout>
|
</layout>
|
||||||
@ -1359,7 +1372,7 @@ If you have issues connecting over Tor check the Tor logs too.</string>
|
|||||||
<item>
|
<item>
|
||||||
<widget class="QLabel" name="lBobStatus">
|
<widget class="QLabel" name="lBobStatus">
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>BOB status</string>
|
<string>SAM status</string>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
|
@ -140,11 +140,6 @@ rs_macos10.15:CONFIG -= rs_macos10.11
|
|||||||
CONFIG *= no_rs_jsonapi
|
CONFIG *= no_rs_jsonapi
|
||||||
rs_jsonapi:CONFIG -= no_rs_jsonapi
|
rs_jsonapi:CONFIG -= no_rs_jsonapi
|
||||||
|
|
||||||
# Disable i2p BOB support for automatically setting up an i2p tunnel for RS
|
|
||||||
# "CONFIG+=no_rs_bob"
|
|
||||||
CONFIG *= rs_bob
|
|
||||||
no_rs_bob:CONFIG -= rs_bob
|
|
||||||
|
|
||||||
# To enable channel indexing append the following assignation to qmake command
|
# To enable channel indexing append the following assignation to qmake command
|
||||||
# line "CONFIG+=rs_deep_channels_index"
|
# line "CONFIG+=rs_deep_channels_index"
|
||||||
CONFIG *= no_rs_deep_channels_index
|
CONFIG *= no_rs_deep_channels_index
|
||||||
@ -209,6 +204,10 @@ no_rs_dh_init_check:CONFIG -= rs_dh_init_check
|
|||||||
# many exported symbols.
|
# many exported symbols.
|
||||||
retroshare_plugins:win32:CONFIG *= libretroshare_shared
|
retroshare_plugins:win32:CONFIG *= libretroshare_shared
|
||||||
|
|
||||||
|
CONFIG+=rs_sam3
|
||||||
|
CONFIG+=rs_sam3_libsam3
|
||||||
|
#CONFIG+=rs_sam3_i2psam
|
||||||
|
|
||||||
# Specify host precompiled jsonapi-generator path, appending the following
|
# Specify host precompiled jsonapi-generator path, appending the following
|
||||||
# assignation to qmake command line
|
# assignation to qmake command line
|
||||||
# 'JSONAPI_GENERATOR_EXE=/myBuildDir/jsonapi-generator'. Required for JSON API
|
# 'JSONAPI_GENERATOR_EXE=/myBuildDir/jsonapi-generator'. Required for JSON API
|
||||||
@ -559,10 +558,6 @@ rs_webui {
|
|||||||
DEFINES *= RS_WEBUI
|
DEFINES *= RS_WEBUI
|
||||||
}
|
}
|
||||||
|
|
||||||
rs_bob {
|
|
||||||
DEFINES *= RS_USE_I2P_BOB
|
|
||||||
}
|
|
||||||
|
|
||||||
rs_deep_channels_index:DEFINES *= RS_DEEP_CHANNEL_INDEX
|
rs_deep_channels_index:DEFINES *= RS_DEEP_CHANNEL_INDEX
|
||||||
|
|
||||||
rs_deep_files_index:DEFINES *= RS_DEEP_FILES_INDEX
|
rs_deep_files_index:DEFINES *= RS_DEEP_FILES_INDEX
|
||||||
@ -576,6 +571,14 @@ rs_broadcast_discovery:DEFINES *= RS_BROADCAST_DISCOVERY
|
|||||||
|
|
||||||
no_rs_dh_init_check:DEFINES *= RS_DISABLE_DIFFIE_HELLMAN_INIT_CHECK
|
no_rs_dh_init_check:DEFINES *= RS_DISABLE_DIFFIE_HELLMAN_INIT_CHECK
|
||||||
|
|
||||||
|
rs_sam3: {
|
||||||
|
DEFINES *= RS_USE_I2P_SAM3
|
||||||
|
# this allows a downgrade from a SAMv3 build to a BOB build, can be removed in the future
|
||||||
|
DEFINES *= RS_I2P_SAM3_BOB_COMPAT
|
||||||
|
}
|
||||||
|
rs_sam3_libsam3: DEFINES *= RS_USE_I2P_SAM3_LIBSAM3
|
||||||
|
rs_sam3_i2psam: DEFINES *= RS_USE_I2P_SAM3_I2PSAM
|
||||||
|
|
||||||
debug {
|
debug {
|
||||||
rs_mutex_debug:DEFINES *= RS_MUTEX_DEBUG
|
rs_mutex_debug:DEFINES *= RS_MUTEX_DEBUG
|
||||||
|
|
||||||
|
@ -26,6 +26,10 @@
|
|||||||
#include <sys/sysinfo.h>
|
#include <sys/sysinfo.h>
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
|
|
||||||
|
#ifdef WINDOWS_SYS
|
||||||
|
#include <winsock.h>
|
||||||
|
#endif // WINDOWS_SYS
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
int libsam3_debug = 0;
|
int libsam3_debug = 0;
|
||||||
|
|
||||||
@ -100,6 +104,11 @@ int sam3tcpConnectIP(uint32_t ip, int port) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
//
|
//
|
||||||
|
// Set this for all outgoing SAM connections. Most SAM commands should be answered rather fast except CREATE SESSION maybe.
|
||||||
|
// This should be enough to let SAM establish a session.
|
||||||
|
sam3tcpSetTimeoutSend(fd, 5 * 60 * 1000);
|
||||||
|
sam3tcpSetTimeoutReceive(fd, 5 * 60 * 1000);
|
||||||
|
//
|
||||||
setsockopt(fd, SOL_SOCKET, SO_KEEPALIVE, &val, sizeof(val));
|
setsockopt(fd, SOL_SOCKET, SO_KEEPALIVE, &val, sizeof(val));
|
||||||
//
|
//
|
||||||
if (connect(fd, (struct sockaddr *)&addr, sizeof(struct sockaddr_in)) < 0) {
|
if (connect(fd, (struct sockaddr *)&addr, sizeof(struct sockaddr_in)) < 0) {
|
||||||
@ -152,8 +161,13 @@ int sam3tcpConnect(const char *hostname, int port, uint32_t *ip) {
|
|||||||
// <0: error; 0: ok
|
// <0: error; 0: ok
|
||||||
int sam3tcpDisconnect(int fd) {
|
int sam3tcpDisconnect(int fd) {
|
||||||
if (fd >= 0) {
|
if (fd >= 0) {
|
||||||
shutdown(fd, SHUT_RDWR);
|
#ifndef WINDOWS_SYS // ie UNIX
|
||||||
return close(fd);
|
shutdown(fd, SHUT_RDWR);
|
||||||
|
return close(fd);
|
||||||
|
#else
|
||||||
|
return closesocket(fd);
|
||||||
|
#endif
|
||||||
|
|
||||||
}
|
}
|
||||||
//
|
//
|
||||||
return -1;
|
return -1;
|
||||||
|
Loading…
Reference in New Issue
Block a user