From ceea5918a237391291a48995fdf2bd0922c5cf35 Mon Sep 17 00:00:00 2001 From: csoler Date: Sat, 9 Oct 2021 01:08:23 +0200 Subject: [PATCH 01/31] added base network layer for friend server. Not working yet. --- src/rsitems/rsserviceids.h | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/rsitems/rsserviceids.h b/src/rsitems/rsserviceids.h index ead349e32..693a1b149 100644 --- a/src/rsitems/rsserviceids.h +++ b/src/rsitems/rsserviceids.h @@ -49,7 +49,8 @@ enum class RsServiceType : uint16_t GXS_TUNNEL = 0x0028, BANLIST = 0x0101, STATUS = 0x0102, - NXS = 0x0200, + FRIEND_SERVER = 0x0103, + NXS = 0x0200, GXSID = 0x0211, PHOTO = 0x0212, WIKI = 0x0213, @@ -109,6 +110,8 @@ RS_DEPRECATED_FOR(RsServiceType) const uint16_t RS_SERVICE_TYPE_DISTANT_CHAT = RS_DEPRECATED_FOR(RsServiceType) const uint16_t RS_SERVICE_TYPE_GXS_TUNNEL = 0x0028; RS_DEPRECATED_FOR(RsServiceType) const uint16_t RS_SERVICE_TYPE_BANLIST = 0x0101; RS_DEPRECATED_FOR(RsServiceType) const uint16_t RS_SERVICE_TYPE_STATUS = 0x0102; +RS_DEPRECATED_FOR(RsServiceType) const uint16_t RS_SERVICE_TYPE_FRIEND_SERVER = 0x0103; + /// Rs Network Exchange Service RS_DEPRECATED_FOR(RsServiceType) const uint16_t RS_SERVICE_TYPE_NXS = 0x0200; RS_DEPRECATED_FOR(RsServiceType) const uint16_t RS_SERVICE_GXS_TYPE_GXSID = 0x0211; From 26aff9da62111572f495c8242dc661cbb1953210 Mon Sep 17 00:00:00 2001 From: csoler Date: Wed, 13 Oct 2021 22:50:09 +0200 Subject: [PATCH 02/31] added empty rsFriendServer struct and basic UI functionality --- src/libretroshare.pro | 1 + src/retroshare/rsfriendserver.h | 20 ++++++++++++++++++++ 2 files changed, 21 insertions(+) create mode 100644 src/retroshare/rsfriendserver.h diff --git a/src/libretroshare.pro b/src/libretroshare.pro index da5f25ba4..caaabd0b7 100644 --- a/src/libretroshare.pro +++ b/src/libretroshare.pro @@ -145,6 +145,7 @@ PUBLIC_HEADERS = retroshare/rsdisc.h \ retroshare/rsrtt.h \ retroshare/rsconfig.h \ retroshare/rsversion.h \ + retroshare/rsfriendserver.h \ retroshare/rsservicecontrol.h \ retroshare/rsgxsdistsync.h diff --git a/src/retroshare/rsfriendserver.h b/src/retroshare/rsfriendserver.h new file mode 100644 index 000000000..cb516c1df --- /dev/null +++ b/src/retroshare/rsfriendserver.h @@ -0,0 +1,20 @@ +#include +#include +#include "util/rstime.h" + +class RsFriendServer +{ +public: + void start() {} + void stop() {} + + void checkServerAddress_async(const std::string&,uint16_t, const std::function& callback) + { + std::this_thread::sleep_for(std::chrono::seconds(1)); + callback(true); + } + void setServerAddress(const std::string&,uint16_t) {} + void setFriendsToRequest(uint32_t) {} +}; + +extern RsFriendServer *rsFriendServer; From 6cd9b1aece4c99a4ac255faa9cd3fd178c3b5cba Mon Sep 17 00:00:00 2001 From: csoler Date: Tue, 19 Oct 2021 23:24:50 +0200 Subject: [PATCH 03/31] implemented multiple clients in Friend Server --- src/retroshare/rsfriendserver.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/retroshare/rsfriendserver.h b/src/retroshare/rsfriendserver.h index cb516c1df..6b343eb0e 100644 --- a/src/retroshare/rsfriendserver.h +++ b/src/retroshare/rsfriendserver.h @@ -8,10 +8,10 @@ public: void start() {} void stop() {} - void checkServerAddress_async(const std::string&,uint16_t, const std::function& callback) + void checkServerAddress_async(const std::string& addr,uint16_t, const std::function& callback) { std::this_thread::sleep_for(std::chrono::seconds(1)); - callback(true); + callback(addr,true); } void setServerAddress(const std::string&,uint16_t) {} void setFriendsToRequest(uint32_t) {} From 2bfd203d6189beab3f8843f7fb9b355fb328a65b Mon Sep 17 00:00:00 2001 From: csoler Date: Wed, 20 Oct 2021 23:06:25 +0200 Subject: [PATCH 04/31] added missing comment in pqi_base --- src/pqi/pqi_base.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/pqi/pqi_base.h b/src/pqi/pqi_base.h index 51980b501..72d5d540b 100644 --- a/src/pqi/pqi_base.h +++ b/src/pqi/pqi_base.h @@ -280,7 +280,8 @@ public: * Sends data to a prescribed location (implementation dependent) *@param data what will be sent *@param len the size of data pointed to in memory - */ + *@returns total number of bytes actually sent + */ virtual int senddata(void *data, int len) = 0; /** From 20ba6088ed611c52d1d1365214490207f2a34848 Mon Sep 17 00:00:00 2001 From: csoler Date: Sun, 24 Oct 2021 17:41:23 +0200 Subject: [PATCH 05/31] moved part of the code to libretroshare/src/friend_server --- src/friend_server/fsbio.cc | 133 +++++++++++++++++++++++++++++++++ src/friend_server/fsbio.h | 35 +++++++++ src/friend_server/fsclient.cc | 77 +++++++++++++++++++ src/friend_server/fsclient.h | 13 ++++ src/friend_server/fsitem.h | 118 +++++++++++++++++++++++++++++ src/friend_server/fsmanager.cc | 0 src/friend_server/fsmanager.h | 0 src/libretroshare.pro | 8 ++ 8 files changed, 384 insertions(+) create mode 100644 src/friend_server/fsbio.cc create mode 100644 src/friend_server/fsbio.h create mode 100644 src/friend_server/fsclient.cc create mode 100644 src/friend_server/fsclient.h create mode 100644 src/friend_server/fsitem.h create mode 100644 src/friend_server/fsmanager.cc create mode 100644 src/friend_server/fsmanager.h diff --git a/src/friend_server/fsbio.cc b/src/friend_server/fsbio.cc new file mode 100644 index 000000000..4104c3c0d --- /dev/null +++ b/src/friend_server/fsbio.cc @@ -0,0 +1,133 @@ +FsBioInterface::FsBioInterface(int socket) + : mCLintConnt(socket) +{ + mTotalReadBytes=0; + mTotalBufferBytes=0; +} + +int FsBioInterface::tick() +{ + std::cerr << "ticking FsNetworkInterface" << std::endl; + + // 2 - read incoming data pending on existing connections + + char inBuffer[1025]; + memset(inBuffer,0,1025); + + int readbytes = read(mCLintConnt, inBuffer, sizeof(inBuffer)); + + if(readbytes == 0) + { + std::cerr << "Reached END of the stream!" << std::endl; + return 0; + } + if(readbytes < 0) + { + if(errno != EWOULDBLOCK && errno != EAGAIN) + RsErr() << "read() failed. Errno=" << errno ; + + return false; + } + + std::cerr << "clintConnt: " << mCLintConnt << ", readbytes: " << readbytes << std::endl; + + //::close(clintConnt); + + // display some debug info + + if(readbytes > 0) + { + RsDbg() << "Received the following bytes: " << RsUtil::BinToHex( reinterpret_cast(inBuffer),readbytes,50) << std::endl; + //RsDbg() << "Received the following bytes: " << std::string(inBuffer,readbytes) << std::endl; + + void *ptr = malloc(readbytes); + + if(!ptr) + throw std::runtime_error("Cannot allocate memory! Go buy some RAM!"); + + memcpy(ptr,inBuffer,readbytes); + + in_buffer.push_back(std::make_pair(ptr,readbytes)); + mTotalBufferBytes += readbytes; + mTotalReadBytes += readbytes; + + std::cerr << "Socket: " << mCLintConnt << ". Total read: " << mTotalReadBytes << ". Buffer size: " << mTotalBufferBytes << std::endl ; + } + + return true; +} + +int FsBioInterface::readdata(void *data, int len) +{ + // read incoming bytes in the buffer + + int total_len = 0; + + while(total_len < len) + { + if(in_buffer.empty()) + { + mTotalBufferBytes -= total_len; + return total_len; + } + + // If the remaining buffer is too large, chop of the beginning of it. + + if(total_len + in_buffer.front().second > len) + { + memcpy(&(static_cast(data)[total_len]),in_buffer.front().first,len - total_len); + + void *ptr = malloc(in_buffer.front().second - (len - total_len)); + memcpy(ptr,&(static_cast(in_buffer.front().first)[len - total_len]),in_buffer.front().second - (len - total_len)); + + free(in_buffer.front().first); + in_buffer.front().first = ptr; + in_buffer.front().second -= len-total_len; + + mTotalBufferBytes -= len; + return len; + } + else // copy everything + { + memcpy(&(static_cast(data)[total_len]),in_buffer.front().first,in_buffer.front().second); + + total_len += in_buffer.front().second; + + free(in_buffer.front().first); + in_buffer.pop_front(); + } + } + mTotalBufferBytes -= len; + return len; +} + +int FsBioInterface::senddata(void *data, int len) +{ +// int written = write(mCLintConnt, data, len); +// return written; + return len; +} +int FsBioInterface::netstatus() +{ + return 1; // dummy response. +} +int FsBioInterface::isactive() +{ + return mCLintConnt > 0; +} +bool FsBioInterface::moretoread(uint32_t /* usec */) +{ + return mTotalBufferBytes > 0; +} +bool FsBioInterface::cansend(uint32_t) +{ + return isactive(); +} + +int FsBioInterface::close() +{ + RsDbg() << "Stopping network interface" << std::endl; + return 1; +} + + diff --git a/src/friend_server/fsbio.h b/src/friend_server/fsbio.h new file mode 100644 index 000000000..2e872d48d --- /dev/null +++ b/src/friend_server/fsbio.h @@ -0,0 +1,35 @@ +class FsBioInterface: public BinInterface +{ +public: + FsBioInterface(int socket); + + // Implements BinInterface methods + + int tick() override; + + int senddata(void *data, int len) override; + int readdata(void *data, int len) override; + + int netstatus() override; + int isactive() override; + bool moretoread(uint32_t usec) override; + bool cansend(uint32_t usec) override; + + int close() override; + + /** + * If hashing data + **/ + RsFileHash gethash() override { return RsFileHash() ; } + uint64_t bytecount() override { return mTotalReadBytes; } + + bool bandwidthLimited() override { return false; } + +private: + int mCLintConnt; + uint32_t mTotalReadBytes; + uint32_t mTotalBufferBytes; + + std::list > in_buffer; +}; + diff --git a/src/friend_server/fsclient.cc b/src/friend_server/fsclient.cc new file mode 100644 index 000000000..6ee8518af --- /dev/null +++ b/src/friend_server/fsclient.cc @@ -0,0 +1,77 @@ +FsClient::FsClient(const std::string& address) + : mServerAddress(address) +{ +} + +bool FsClient::sendItem(RsItem *item) +{ + // open a connection + + int CreateSocket = 0,n = 0; + char dataReceived[1024]; + struct sockaddr_in ipOfServer; + + memset(dataReceived, '0' ,sizeof(dataReceived)); + + if((CreateSocket = socket(AF_INET, SOCK_STREAM, 0))< 0) + { + printf("Socket not created \n"); + return 1; + } + + ipOfServer.sin_family = AF_INET; + ipOfServer.sin_port = htons(2017); + ipOfServer.sin_addr.s_addr = inet_addr("127.0.0.1"); + + if(connect(CreateSocket, (struct sockaddr *)&ipOfServer, sizeof(ipOfServer))<0) + { + printf("Connection failed due to port and ip problems, or server is not available\n"); + return false; + } + + // Serialise the item and send it. + + uint32_t size = RsSerialiser::MAX_SERIAL_SIZE; + RsTemporaryMemory data(size); + + if(!data) + { + RsErr() << "Cannot allocate memory to send item!" << std::endl; + return false; + } + + FsSerializer *fss = new FsSerializer; + RsSerialiser rss; + rss.addSerialType(fss); + + FsSerializer().serialise(item,data,&size); + + // TODO: we should write in multiple chunks just in case the socket is not fully ready + write(CreateSocket,data,size); + + // Now attempt to read and deserialize anything that comes back from that connexion + + FsBioInterface bio(CreateSocket); + pqistreamer pqi(&rss,RsPeerId(),&bio,BIN_FLAGS_READABLE); + pqithreadstreamer p(&pqi,&rss,RsPeerId(),&bio,BIN_FLAGS_READABLE); + p.start(); + + while(true) + { + RsItem *item = p.GetItem(); + + if(!item) + { + rstime::rs_usleep(1000*200); + continue; + } + + std::cerr << "Got a response item: " << std::endl; + std::cerr << *item << std::endl; + } + + return 0; + + // if ok, stream the item through it +} + diff --git a/src/friend_server/fsclient.h b/src/friend_server/fsclient.h new file mode 100644 index 000000000..6e79ed1b3 --- /dev/null +++ b/src/friend_server/fsclient.h @@ -0,0 +1,13 @@ +// This class runs a client connection to the friend server. It opens a socket at each connection. + +class FsClient +{ +public: + FsClient(const std::string& address); + + bool sendItem(RsItem *item); + +private: + std::string mServerAddress; +}; + diff --git a/src/friend_server/fsitem.h b/src/friend_server/fsitem.h new file mode 100644 index 000000000..4714178af --- /dev/null +++ b/src/friend_server/fsitem.h @@ -0,0 +1,118 @@ +#include "serialiser/rsserial.h" +#include "serialiser/rsserializer.h" + +#include "rsitems/rsitem.h" +#include "rsitems/rsserviceids.h" +#include "rsitems/itempriorities.h" + +const uint8_t RS_PKT_SUBTYPE_FS_CLIENT_PUBLISH = 0x01 ; +const uint8_t RS_PKT_SUBTYPE_FS_CLIENT_REMOVE = 0x02 ; +const uint8_t RS_PKT_SUBTYPE_FS_SERVER_RESPONSE = 0x03 ; +const uint8_t RS_PKT_SUBTYPE_FS_SERVER_ENCRYPTED_RESPONSE = 0x04 ; + +class RsFriendServerItem: public RsItem +{ +public: + RsFriendServerItem(uint8_t item_subtype) : RsItem(RS_PKT_VERSION_SERVICE,RS_SERVICE_TYPE_FRIEND_SERVER,item_subtype) + { + setPriorityLevel(QOS_PRIORITY_DEFAULT) ; + } + virtual ~RsFriendServerItem() {} + virtual void clear() override {} +}; + +class RsFriendServerClientPublishItem: public RsFriendServerItem +{ +public: + RsFriendServerClientPublishItem() : RsFriendServerItem(RS_PKT_SUBTYPE_FS_CLIENT_PUBLISH) {} + + void serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx) override + { + RS_SERIAL_PROCESS(n_requested_friends); + RS_SERIAL_PROCESS(long_invite); + } + virtual void clear() override + { + long_invite = std::string(); + n_requested_friends=0; + } + + // specific members for that item + + uint32_t n_requested_friends; + std::string long_invite; +}; + +class RsFriendServerClientRemoveItem: public RsFriendServerItem +{ +public: + RsFriendServerClientRemoveItem() : RsFriendServerItem(RS_PKT_SUBTYPE_FS_CLIENT_REMOVE) {} + + void serial_process(RsGenericSerializer::SerializeJob /* j */,RsGenericSerializer::SerializeContext& /* ctx */) + { + } +}; +class RsFriendServerEncryptedServerResponseItem: public RsFriendServerItem +{ +public: + RsFriendServerEncryptedServerResponseItem() : RsFriendServerItem(RS_PKT_SUBTYPE_FS_SERVER_ENCRYPTED_RESPONSE) {} + + void serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx) override + { + RsTypeSerializer::RawMemoryWrapper prox(bin_data, bin_len); + RsTypeSerializer::serial_process(j, ctx, prox, "data"); + } + + virtual void clear() override + { + free(bin_data); + bin_len = 0; + bin_data = nullptr; + } + // + + void *bin_data; + uint32_t bin_len; +}; + +class RsFriendServerServerResponseItem: public RsFriendServerItem +{ +public: + RsFriendServerServerResponseItem() : RsFriendServerItem(RS_PKT_SUBTYPE_FS_SERVER_RESPONSE) {} + + void serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx) override + { + RS_SERIAL_PROCESS(friend_invites); + } + + virtual void clear() override + { + friend_invites.clear(); + } + // specific members for that item + + std::map friend_invites; +}; + +struct FsSerializer : RsServiceSerializer +{ + FsSerializer(RsSerializationFlags flags = RsSerializationFlags::NONE): RsServiceSerializer(RS_SERVICE_TYPE_FRIEND_SERVER, flags) {} + + virtual RsItem *create_item(uint16_t service_id,uint8_t item_sub_id) const + { + if(service_id != static_cast(RsServiceType::FRIEND_SERVER)) + return nullptr; + + switch(item_sub_id) + { + case RS_PKT_SUBTYPE_FS_CLIENT_REMOVE: return new RsFriendServerClientRemoveItem(); + case RS_PKT_SUBTYPE_FS_CLIENT_PUBLISH: return new RsFriendServerClientPublishItem(); + case RS_PKT_SUBTYPE_FS_SERVER_RESPONSE: return new RsFriendServerServerResponseItem(); + case RS_PKT_SUBTYPE_FS_SERVER_ENCRYPTED_RESPONSE: return new RsFriendServerEncryptedServerResponseItem(); + default: + RsErr() << "Unknown subitem type " << item_sub_id << " in FsSerialiser" ; + return nullptr; + } + + } +}; diff --git a/src/friend_server/fsmanager.cc b/src/friend_server/fsmanager.cc new file mode 100644 index 000000000..e69de29bb diff --git a/src/friend_server/fsmanager.h b/src/friend_server/fsmanager.h new file mode 100644 index 000000000..e69de29bb diff --git a/src/libretroshare.pro b/src/libretroshare.pro index caaabd0b7..d6f0397df 100644 --- a/src/libretroshare.pro +++ b/src/libretroshare.pro @@ -404,6 +404,10 @@ HEADERS += pqi/authssl.h \ pqi/pqinetstatebox.h \ pqi/p3servicecontrol.h +SOURCES += friend_server/fsclient.h \ + friend_server/fsbio.h \ + friend_server/fsmanager.h + HEADERS += rsserver/p3face.h \ rsserver/p3history.h \ rsserver/p3msgs.h \ @@ -569,6 +573,10 @@ SOURCES += pqi/authgpg.cc \ pqi/pqinetstatebox.cc \ pqi/p3servicecontrol.cc +SOURCES += friend_server/fsclient.cc \ + friend_server/fsbio.cc \ + friend_server/fsmanager.cc + SOURCES += rsserver/p3face-config.cc \ rsserver/p3face-server.cc \ rsserver/p3face-info.cc \ From 8074dab32ab1bae5e7d0fced3a156d3ff19a5827 Mon Sep 17 00:00:00 2001 From: csoler Date: Sun, 24 Oct 2021 20:01:19 +0200 Subject: [PATCH 06/31] fixed compilation --- src/friend_server/fsbio.cc | 27 +++++++++++++++++++++++++++ src/friend_server/fsbio.h | 24 ++++++++++++++++++++++++ src/friend_server/fsclient.cc | 27 +++++++++++++++++++++++++++ src/friend_server/fsclient.h | 25 +++++++++++++++++++++++++ src/friend_server/fsitem.h | 24 ++++++++++++++++++++++++ src/libretroshare.pro | 1 + src/retroshare/rsfriendserver.h | 32 +++++++++++++++++++++++--------- 7 files changed, 151 insertions(+), 9 deletions(-) diff --git a/src/friend_server/fsbio.cc b/src/friend_server/fsbio.cc index 4104c3c0d..517738225 100644 --- a/src/friend_server/fsbio.cc +++ b/src/friend_server/fsbio.cc @@ -1,3 +1,28 @@ +/******************************************************************************* + * libretroshare/src/file_sharing: fsbio.cc * + * * + * libretroshare: retroshare core library * + * * + * Copyright 2021 by retroshare team * + * * + * This program is free software: you can redistribute it and/or modify * + * it under the terms of the GNU Lesser General Public License as * + * published by the Free Software Foundation, either version 3 of the * + * License, or (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public License * + * along with this program. If not, see . * + * * + ******************************************************************************/ + +#include "util/rsprint.h" +#include "fsbio.h" + FsBioInterface::FsBioInterface(int socket) : mCLintConnt(socket) { @@ -111,10 +136,12 @@ int FsBioInterface::netstatus() { return 1; // dummy response. } + int FsBioInterface::isactive() { return mCLintConnt > 0; } + bool FsBioInterface::moretoread(uint32_t /* usec */) { return mTotalBufferBytes > 0; diff --git a/src/friend_server/fsbio.h b/src/friend_server/fsbio.h index 2e872d48d..446ad29f8 100644 --- a/src/friend_server/fsbio.h +++ b/src/friend_server/fsbio.h @@ -1,3 +1,27 @@ +/******************************************************************************* + * libretroshare/src/file_sharing: fsbio.h * + * * + * libretroshare: retroshare core library * + * * + * Copyright 2021 by retroshare team * + * * + * This program is free software: you can redistribute it and/or modify * + * it under the terms of the GNU Lesser General Public License as * + * published by the Free Software Foundation, either version 3 of the * + * License, or (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public License * + * along with this program. If not, see . * + * * + ******************************************************************************/ + +#include "pqi/pqi_base.h" + class FsBioInterface: public BinInterface { public: diff --git a/src/friend_server/fsclient.cc b/src/friend_server/fsclient.cc index 6ee8518af..c332aee24 100644 --- a/src/friend_server/fsclient.cc +++ b/src/friend_server/fsclient.cc @@ -1,3 +1,30 @@ +/******************************************************************************* + * libretroshare/src/file_sharing: fsclient.cc * + * * + * libretroshare: retroshare core library * + * * + * Copyright 2021 by retroshare team * + * * + * This program is free software: you can redistribute it and/or modify * + * it under the terms of the GNU Lesser General Public License as * + * published by the Free Software Foundation, either version 3 of the * + * License, or (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public License * + * along with this program. If not, see . * + * * + ******************************************************************************/ + +#include "pqi/pqithreadstreamer.h" + +#include "fsclient.h" +#include "fsbio.h" + FsClient::FsClient(const std::string& address) : mServerAddress(address) { diff --git a/src/friend_server/fsclient.h b/src/friend_server/fsclient.h index 6e79ed1b3..c29a10671 100644 --- a/src/friend_server/fsclient.h +++ b/src/friend_server/fsclient.h @@ -1,3 +1,28 @@ +/******************************************************************************* + * libretroshare/src/file_sharing: fsclient.h * + * * + * libretroshare: retroshare core library * + * * + * Copyright 2021 by retroshare team * + * * + * This program is free software: you can redistribute it and/or modify * + * it under the terms of the GNU Lesser General Public License as * + * published by the Free Software Foundation, either version 3 of the * + * License, or (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public License * + * along with this program. If not, see . * + * * + ******************************************************************************/ + +#include +#include "fsitem.h" + // This class runs a client connection to the friend server. It opens a socket at each connection. class FsClient diff --git a/src/friend_server/fsitem.h b/src/friend_server/fsitem.h index 4714178af..3ca7e50d5 100644 --- a/src/friend_server/fsitem.h +++ b/src/friend_server/fsitem.h @@ -1,3 +1,27 @@ +/******************************************************************************* + * libretroshare/src/file_sharing: fsitem.h * + * * + * libretroshare: retroshare core library * + * * + * Copyright 2021 by retroshare team * + * * + * This program is free software: you can redistribute it and/or modify * + * it under the terms of the GNU Lesser General Public License as * + * published by the Free Software Foundation, either version 3 of the * + * License, or (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public License * + * along with this program. If not, see . * + * * + ******************************************************************************/ + +#pragma once + #include "serialiser/rsserial.h" #include "serialiser/rsserializer.h" diff --git a/src/libretroshare.pro b/src/libretroshare.pro index d6f0397df..f8d01a613 100644 --- a/src/libretroshare.pro +++ b/src/libretroshare.pro @@ -406,6 +406,7 @@ HEADERS += pqi/authssl.h \ SOURCES += friend_server/fsclient.h \ friend_server/fsbio.h \ + friend_server/fsitem.h \ friend_server/fsmanager.h HEADERS += rsserver/p3face.h \ diff --git a/src/retroshare/rsfriendserver.h b/src/retroshare/rsfriendserver.h index 6b343eb0e..9ce4b25ef 100644 --- a/src/retroshare/rsfriendserver.h +++ b/src/retroshare/rsfriendserver.h @@ -2,19 +2,33 @@ #include #include "util/rstime.h" +// The Friend Server component of Retroshare automatically adds/removes some friends so that the +// +// The current strategy is: +// +// - if total nb of friends < S +// request new friends to the FS +// - if total nb of friends >= S +// do not request anymore (and unpublish the key), but keep the friends already here +// +// Possible states: +// - not started +// - maintain friend list +// - actively request friends +// +// The friend server internally keeps track of which friends have been added using the friend server. +// It's important to keep the ones that are already connected because they may count on us. +// Friends supplied by the FS who never connected for a few days should be removed automatically. + class RsFriendServer { public: - void start() {} - void stop() {} + virtual void start() =0; + virtual void stop() =0; - void checkServerAddress_async(const std::string& addr,uint16_t, const std::function& callback) - { - std::this_thread::sleep_for(std::chrono::seconds(1)); - callback(addr,true); - } - void setServerAddress(const std::string&,uint16_t) {} - void setFriendsToRequest(uint32_t) {} + virtual void checkServerAddress_async(const std::string& addr,uint16_t, const std::function& callback) =0; + virtual void setServerAddress(const std::string&,uint16_t) =0; + virtual void setFriendsToRequest(uint32_t) =0; }; extern RsFriendServer *rsFriendServer; From 69c47e6538cde3f4b5fe3e14032519770b9aef4b Mon Sep 17 00:00:00 2001 From: csoler Date: Fri, 29 Oct 2021 21:44:30 +0200 Subject: [PATCH 07/31] added logic to stop/start FriendServer from GUI --- src/friend_server/fsmanager.cc | 44 +++++++++++++++++++++++++++++++++ src/friend_server/fsmanager.h | 41 ++++++++++++++++++++++++++++++ src/retroshare/rsfriendserver.h | 4 +-- src/rsserver/rsinit.cc | 4 +++ 4 files changed, 91 insertions(+), 2 deletions(-) diff --git a/src/friend_server/fsmanager.cc b/src/friend_server/fsmanager.cc index e69de29bb..7abaca3d4 100644 --- a/src/friend_server/fsmanager.cc +++ b/src/friend_server/fsmanager.cc @@ -0,0 +1,44 @@ +#include "fsmanager.h" + +RsFriendServer *rsFriendServer = nullptr; + +void FriendServerManager::startServer() +{ + if(!isRunning()) + { + std::cerr << "Starting Friend Server Manager." << std::endl; + RsTickingThread::start() ; + } +} +void FriendServerManager::stopServer() +{ + if(isRunning() && !shouldStop()) + { + std::cerr << "Stopping Friend Server Manager." << std::endl; + RsTickingThread::askForStop() ; + } +} +void FriendServerManager::checkServerAddress_async(const std::string& addr,uint16_t, const std::function& callback) +{ +#warning TODO + std::this_thread::sleep_for(std::chrono::seconds(1)); + + callback(addr,true); +} + +void FriendServerManager::setServerAddress(const std::string& addr,uint16_t port) +{ + mServerAddress = addr; + mServerPort = port; +} + +void FriendServerManager::setFriendsToRequest(uint32_t n) +{ + mFriendsToRequest = n; +} + +void FriendServerManager::threadTick() +{ + std::cerr << "Ticking FriendServerManager..." << std::endl; + std::this_thread::sleep_for(std::chrono::seconds(2)); +} diff --git a/src/friend_server/fsmanager.h b/src/friend_server/fsmanager.h index e69de29bb..df98173c6 100644 --- a/src/friend_server/fsmanager.h +++ b/src/friend_server/fsmanager.h @@ -0,0 +1,41 @@ +#include + +#include "util/rsthreads.h" +#include "retroshare/rsfriendserver.h" +#include "retroshare/rspeers.h" + +struct FriendServerPeerInfo +{ + enum FriendServerPeerStatus: uint8_t + { + UNKNOWN = 0x00, + LOCALLY_ACCEPTED = 0x01, + HAS_ACCEPTED_ME = 0x02, + ALREADY_CONNECTED = 0x03 + }; + + uint32_t status ; +}; + +class FriendServerManager: public RsFriendServer, public RsTickingThread +{ +public: + virtual void startServer() override ; + virtual void stopServer() override ; + + virtual void checkServerAddress_async(const std::string& addr,uint16_t, const std::function& callback) override ; + virtual void setServerAddress(const std::string&,uint16_t) override ; + virtual void setFriendsToRequest(uint32_t) override ; + +protected: + virtual void threadTick() override; + +private: + uint32_t mFriendsToRequest; + + // encode the current list of friends obtained through the friendserver and their status + + std::map mPeers; + std::string mServerAddress ; + uint16_t mServerPort; +}; diff --git a/src/retroshare/rsfriendserver.h b/src/retroshare/rsfriendserver.h index 9ce4b25ef..c8fa446b0 100644 --- a/src/retroshare/rsfriendserver.h +++ b/src/retroshare/rsfriendserver.h @@ -23,8 +23,8 @@ class RsFriendServer { public: - virtual void start() =0; - virtual void stop() =0; + virtual void startServer() =0; + virtual void stopServer() =0; virtual void checkServerAddress_async(const std::string& addr,uint16_t, const std::function& callback) =0; virtual void setServerAddress(const std::string&,uint16_t) =0; diff --git a/src/rsserver/rsinit.cc b/src/rsserver/rsinit.cc index 8449a9e3e..ebfad8fa5 100644 --- a/src/rsserver/rsinit.cc +++ b/src/rsserver/rsinit.cc @@ -48,6 +48,7 @@ #include "retroshare/rsversion.h" #include "rsserver/rsloginhandler.h" #include "rsserver/rsaccounts.h" +#include "friend_server/fsmanager.h" #include #include @@ -1170,6 +1171,9 @@ int RsServer::StartupRetroShare() serviceCtrl->setServiceServer(pqih) ; + // setup friend server + rsFriendServer = new FriendServerManager(); + /****** New Ft Server **** !!! */ ftServer *ftserver = new ftServer(mPeerMgr, serviceCtrl); ftserver->setConfigDirectory(RsAccounts::AccountDirectory()); From 86a9a27f85c5bb37d81bae164d398ccf396eb15c Mon Sep 17 00:00:00 2001 From: csoler Date: Sat, 30 Oct 2021 15:50:28 +0200 Subject: [PATCH 08/31] added basic communication between FriendServer and its clients --- src/friend_server/fsclient.cc | 53 +++++++++++++++++++++++--- src/friend_server/fsclient.h | 6 +-- src/friend_server/fsmanager.cc | 66 +++++++++++++++++++++++++++++++++ src/friend_server/fsmanager.h | 7 ++++ src/retroshare/rsfriendserver.h | 4 ++ 5 files changed, 127 insertions(+), 9 deletions(-) diff --git a/src/friend_server/fsclient.cc b/src/friend_server/fsclient.cc index c332aee24..2f486122f 100644 --- a/src/friend_server/fsclient.cc +++ b/src/friend_server/fsclient.cc @@ -21,19 +21,60 @@ ******************************************************************************/ #include "pqi/pqithreadstreamer.h" +#include "retroshare/rspeers.h" #include "fsclient.h" #include "fsbio.h" -FsClient::FsClient(const std::string& address) - : mServerAddress(address) +bool FsClient::requestFriends(const std::string& address,uint16_t port,uint32_t reqs,std::map& friend_certificates) { + // send our own certificate to publish and expects response frmo the server , decrypts it and reutnrs friend list + + RsFriendServerClientPublishItem *pitem = new RsFriendServerClientPublishItem(); + + pitem->n_requested_friends = reqs; + pitem->long_invite = rsPeers->GetRetroshareInvite(); + + std::list response; + + sendItem(address,port,pitem,response); + + // now decode the response + + friend_certificates.clear(); + + for(auto item:response) + { + auto *encrypted_response_item = dynamic_cast(item); + + if(!encrypted_response_item) + { + delete item; + continue; + } + + // For now, also handle unencrypted response items. Will be disabled in production + + auto *response_item = dynamic_cast(item); + + if(!response_item) + { + delete item; + continue; + } + + for(const auto& it:response_item->friend_invites) + friend_certificates.insert(it); + } + return friend_certificates.size(); } -bool FsClient::sendItem(RsItem *item) +bool FsClient::sendItem(const std::string& address,uint16_t port,RsItem *item,std::list& response) { // open a connection + RsDbg() << "Sending item to friend server at \"" << address << ":" << port ; + int CreateSocket = 0,n = 0; char dataReceived[1024]; struct sockaddr_in ipOfServer; @@ -47,8 +88,8 @@ bool FsClient::sendItem(RsItem *item) } ipOfServer.sin_family = AF_INET; - ipOfServer.sin_port = htons(2017); - ipOfServer.sin_addr.s_addr = inet_addr("127.0.0.1"); + ipOfServer.sin_port = htons(port); + ipOfServer.sin_addr.s_addr = inet_addr(address.c_str()); if(connect(CreateSocket, (struct sockaddr *)&ipOfServer, sizeof(ipOfServer))<0) { @@ -89,7 +130,7 @@ bool FsClient::sendItem(RsItem *item) if(!item) { - rstime::rs_usleep(1000*200); + std::this_thread::sleep_for(std::chrono::milliseconds(200)); continue; } diff --git a/src/friend_server/fsclient.h b/src/friend_server/fsclient.h index c29a10671..76af44a43 100644 --- a/src/friend_server/fsclient.h +++ b/src/friend_server/fsclient.h @@ -28,11 +28,11 @@ class FsClient { public: - FsClient(const std::string& address); + FsClient() {} - bool sendItem(RsItem *item); + bool requestFriends(const std::string& address,uint16_t port,uint32_t reqs,std::map& friend_certificates); private: - std::string mServerAddress; + bool sendItem(const std::string &address, uint16_t port, RsItem *item, std::list &response); }; diff --git a/src/friend_server/fsmanager.cc b/src/friend_server/fsmanager.cc index 7abaca3d4..ca520bb4f 100644 --- a/src/friend_server/fsmanager.cc +++ b/src/friend_server/fsmanager.cc @@ -1,7 +1,24 @@ +#include #include "fsmanager.h" +#include "fsclient.h" RsFriendServer *rsFriendServer = nullptr; +static const rstime_t MIN_DELAY_BETWEEN_FS_REQUESTS = 30; +static const rstime_t MAX_DELAY_BETWEEN_FS_REQUESTS = 3600; +static const uint32_t DEFAULT_FRIENDS_TO_REQUEST = 10; + +static const std::string DEFAULT_FRIEND_SERVER_ADDRESS = "127.0.0.1"; +static const uint16_t DEFAULT_FRIEND_SERVER_PORT = 2017; + +FriendServerManager::FriendServerManager() +{ + mLastFriendReqestCampain = 0; + mFriendsToRequest = DEFAULT_FRIENDS_TO_REQUEST; + + mServerAddress = DEFAULT_FRIEND_SERVER_ADDRESS; + mServerPort = DEFAULT_FRIEND_SERVER_PORT; +} void FriendServerManager::startServer() { if(!isRunning()) @@ -41,4 +58,53 @@ void FriendServerManager::threadTick() { std::cerr << "Ticking FriendServerManager..." << std::endl; std::this_thread::sleep_for(std::chrono::seconds(2)); + + // Check for requests. Compute how much to wait based on how many friends we have already + + std::vector friends; + rsPeers->getPgpFriendList(friends); + + // log-scale interpolation of the delay between two requests. + + if(mFriendsToRequest == 0 || mFriendsToRequest < friends.size()) + { + RsErr() << "No friends to request! This is unexpected. Returning." << std::endl; + return; + } + + // This formula makes RS wait much longuer between two requests to the server when the number of friends is close the + // wanted number + // Delay for 0 friends: 30 secs. + // Delay for 1 friends: 30 secs. + // Delay for 2 friends: 32 secs. + // Delay for 3 friends: 35 secs. + // Delay for 4 friends: 44 secs. + // Delay for 5 friends: 66 secs. + // Delay for 6 friends: 121 secs. + // Delay for 7 friends: 258 secs. + // Delay for 8 friends: 603 secs. + // Delay for 9 friends: 1466 secs. + + RsDbg() << friends.size() << " friends already, " << mFriendsToRequest << " friends to request"; + + double s = (friends.size() < mFriendsToRequest)? ( (mFriendsToRequest - friends.size())/(double)mFriendsToRequest) : 1.0; + rstime_t delay_for_request = MIN_DELAY_BETWEEN_FS_REQUESTS + (int)floor(exp(-1*s + log(MAX_DELAY_BETWEEN_FS_REQUESTS)*(1.0-s))); + + std::cerr << "Delay for " << friends.size() << " friends: " << delay_for_request << " secs." << std::endl; + + rstime_t now = time(nullptr); + + if(mLastFriendReqestCampain + delay_for_request < now) + { + std::cerr << "Requesting new friends to friend server..." << std::endl; + + std::map friend_certificates; + FsClient().requestFriends(mServerAddress,mServerPort,mFriendsToRequest,friend_certificates); // blocking call + + std::cerr << "Got the following list of friend certificates:" << std::endl; + + for(const auto& it:friend_certificates) + std::cerr << it.first << " : " << it.second << std::endl; + } } + diff --git a/src/friend_server/fsmanager.h b/src/friend_server/fsmanager.h index df98173c6..ef5887afa 100644 --- a/src/friend_server/fsmanager.h +++ b/src/friend_server/fsmanager.h @@ -15,11 +15,14 @@ struct FriendServerPeerInfo }; uint32_t status ; + rstime_t received_TS; }; class FriendServerManager: public RsFriendServer, public RsTickingThread { public: + FriendServerManager(); + virtual void startServer() override ; virtual void stopServer() override ; @@ -27,11 +30,15 @@ public: virtual void setServerAddress(const std::string&,uint16_t) override ; virtual void setFriendsToRequest(uint32_t) override ; + virtual uint32_t friendsToRequest() override { return mFriendsToRequest ; } + virtual uint16_t friendsServerPort() override { return mServerPort ; } + virtual std::string friendsServerAddress() override { return mServerAddress ; } protected: virtual void threadTick() override; private: uint32_t mFriendsToRequest; + rstime_t mLastFriendReqestCampain; // encode the current list of friends obtained through the friendserver and their status diff --git a/src/retroshare/rsfriendserver.h b/src/retroshare/rsfriendserver.h index c8fa446b0..df9951cee 100644 --- a/src/retroshare/rsfriendserver.h +++ b/src/retroshare/rsfriendserver.h @@ -29,6 +29,10 @@ public: virtual void checkServerAddress_async(const std::string& addr,uint16_t, const std::function& callback) =0; virtual void setServerAddress(const std::string&,uint16_t) =0; virtual void setFriendsToRequest(uint32_t) =0; + + virtual uint32_t friendsToRequest() =0; + virtual uint16_t friendsServerPort() =0; + virtual std::string friendsServerAddress() =0; }; extern RsFriendServer *rsFriendServer; From 8273f344ca0dd85b0e3400331ff7fe858d7d2b1f Mon Sep 17 00:00:00 2001 From: csoler Date: Sun, 31 Oct 2021 12:01:07 +0100 Subject: [PATCH 09/31] fixed debug output in pqistreamer --- src/pqi/pqistreamer.cc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/pqi/pqistreamer.cc b/src/pqi/pqistreamer.cc index db38bfde2..96b91dae6 100644 --- a/src/pqi/pqistreamer.cc +++ b/src/pqi/pqistreamer.cc @@ -683,7 +683,7 @@ int pqistreamer::handleoutgoing_locked() outSentBytes_locked(mPkt_wpending_size); // this is the only time where we know exactly what was sent. #ifdef DEBUG_TRANSFERS - std::cerr << "pqistreamer::handleoutgoing_locked() Sent Packet len: " << mPkt_wpending_size << " @ " << RsUtil::AccurateTimeString(); + std::cerr << "pqistreamer::handleoutgoing_locked() Sent Packet len: " << mPkt_wpending_size << " @ " << getCurrentTS(); std::cerr << std::endl; #endif @@ -693,7 +693,7 @@ int pqistreamer::handleoutgoing_locked() mPkt_wpending = NULL; mPkt_wpending_size = 0 ; - sent = true; + sent = true; } } #ifdef DEBUG_PQISTREAMER From 0396307c4c96a346ca99fc5a18c3038040811bf5 Mon Sep 17 00:00:00 2001 From: csoler Date: Sun, 31 Oct 2021 12:01:44 +0100 Subject: [PATCH 10/31] added missing override in pqithreadstreamer --- src/pqi/pqithreadstreamer.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/pqi/pqithreadstreamer.h b/src/pqi/pqithreadstreamer.h index 7ba1690c8..5b6fa3763 100644 --- a/src/pqi/pqithreadstreamer.h +++ b/src/pqi/pqithreadstreamer.h @@ -31,8 +31,8 @@ public: pqithreadstreamer(PQInterface *parent, RsSerialiser *rss, const RsPeerId& peerid, BinInterface *bio_in, int bio_flagsin); // from pqistreamer - virtual bool RecvItem(RsItem *item); - virtual int tick(); + virtual bool RecvItem(RsItem *item) override; + virtual int tick() override; protected: void threadTick() override; /// @see RsTickingThread From 6049b378193361f2346f90f8f43328828bca5d63 Mon Sep 17 00:00:00 2001 From: csoler Date: Sun, 31 Oct 2021 12:02:09 +0100 Subject: [PATCH 11/31] fixed basic incoming communication at server side --- src/friend_server/fsbio.cc | 18 ++++++++++-------- src/friend_server/fsbio.h | 1 + src/friend_server/fsclient.cc | 20 ++++++++++++++++---- 3 files changed, 27 insertions(+), 12 deletions(-) diff --git a/src/friend_server/fsbio.cc b/src/friend_server/fsbio.cc index 517738225..ecff610ea 100644 --- a/src/friend_server/fsbio.cc +++ b/src/friend_server/fsbio.cc @@ -24,7 +24,7 @@ #include "fsbio.h" FsBioInterface::FsBioInterface(int socket) - : mCLintConnt(socket) + : mCLintConnt(socket),mIsActive(true) { mTotalReadBytes=0; mTotalBufferBytes=0; @@ -43,21 +43,22 @@ int FsBioInterface::tick() if(readbytes == 0) { - std::cerr << "Reached END of the stream!" << std::endl; - return 0; + RsDbg() << "Reached END of the stream!" << std::endl; + RsDbg() << "Closing!" << std::endl; + + mIsActive = false; + return mTotalBufferBytes; } if(readbytes < 0) { if(errno != EWOULDBLOCK && errno != EAGAIN) RsErr() << "read() failed. Errno=" << errno ; - return false; + return mTotalBufferBytes; } std::cerr << "clintConnt: " << mCLintConnt << ", readbytes: " << readbytes << std::endl; - //::close(clintConnt); - // display some debug info if(readbytes > 0) @@ -79,7 +80,7 @@ int FsBioInterface::tick() std::cerr << "Socket: " << mCLintConnt << ". Total read: " << mTotalReadBytes << ". Buffer size: " << mTotalBufferBytes << std::endl ; } - return true; + return mTotalBufferBytes; } int FsBioInterface::readdata(void *data, int len) @@ -134,7 +135,7 @@ int FsBioInterface::senddata(void *data, int len) } int FsBioInterface::netstatus() { - return 1; // dummy response. + return mIsActive; // dummy response. } int FsBioInterface::isactive() @@ -154,6 +155,7 @@ bool FsBioInterface::cansend(uint32_t) int FsBioInterface::close() { RsDbg() << "Stopping network interface" << std::endl; + mIsActive = false; return 1; } diff --git a/src/friend_server/fsbio.h b/src/friend_server/fsbio.h index 446ad29f8..6b2ed06bd 100644 --- a/src/friend_server/fsbio.h +++ b/src/friend_server/fsbio.h @@ -51,6 +51,7 @@ public: private: int mCLintConnt; + bool mIsActive; uint32_t mTotalReadBytes; uint32_t mTotalBufferBytes; diff --git a/src/friend_server/fsclient.cc b/src/friend_server/fsclient.cc index 2f486122f..377055505 100644 --- a/src/friend_server/fsclient.cc +++ b/src/friend_server/fsclient.cc @@ -117,7 +117,7 @@ bool FsClient::sendItem(const std::string& address,uint16_t port,RsItem *item,st // TODO: we should write in multiple chunks just in case the socket is not fully ready write(CreateSocket,data,size); - // Now attempt to read and deserialize anything that comes back from that connexion + // Now attempt to read and deserialize anything that comes back from that connexion until it gets closed by the server. FsBioInterface bio(CreateSocket); pqistreamer pqi(&rss,RsPeerId(),&bio,BIN_FLAGS_READABLE); @@ -128,14 +128,26 @@ bool FsClient::sendItem(const std::string& address,uint16_t port,RsItem *item,st { RsItem *item = p.GetItem(); - if(!item) + if(item) + { + response.push_back(item); + std::cerr << "Got a response item: " << std::endl; + std::cerr << *item << std::endl; + } + else { std::this_thread::sleep_for(std::chrono::milliseconds(200)); continue; } - std::cerr << "Got a response item: " << std::endl; - std::cerr << *item << std::endl; + if(!bio.isactive()) // socket has probably closed + { + RsDbg() << "(client side) Socket has been closed by server. Killing pqistreamer and closing socket." ; + p.fullstop(); + + close(CreateSocket); + CreateSocket=0; + } } return 0; From d0c89ea34ab5a57699217f62551c68200f3f7acb Mon Sep 17 00:00:00 2001 From: csoler Date: Sun, 31 Oct 2021 16:46:06 +0100 Subject: [PATCH 12/31] fixed two-ways communication between RS and friend server --- src/friend_server/fsbio.cc | 8 +++---- src/friend_server/fsclient.cc | 42 +++++++++++++++++++++++----------- src/friend_server/fsclient.h | 14 ++++++++++-- src/friend_server/fsmanager.cc | 2 ++ 4 files changed, 47 insertions(+), 19 deletions(-) diff --git a/src/friend_server/fsbio.cc b/src/friend_server/fsbio.cc index ecff610ea..8d6933a76 100644 --- a/src/friend_server/fsbio.cc +++ b/src/friend_server/fsbio.cc @@ -43,10 +43,10 @@ int FsBioInterface::tick() if(readbytes == 0) { - RsDbg() << "Reached END of the stream!" << std::endl; - RsDbg() << "Closing!" << std::endl; + RsDbg() << "Reached END of the stream!" ; + RsDbg() << "Closing!" ; - mIsActive = false; + close(); return mTotalBufferBytes; } if(readbytes < 0) @@ -140,7 +140,7 @@ int FsBioInterface::netstatus() int FsBioInterface::isactive() { - return mCLintConnt > 0; + return mIsActive ; } bool FsBioInterface::moretoread(uint32_t /* usec */) diff --git a/src/friend_server/fsclient.cc b/src/friend_server/fsclient.cc index 377055505..9b2459b7c 100644 --- a/src/friend_server/fsclient.cc +++ b/src/friend_server/fsclient.cc @@ -113,20 +113,24 @@ bool FsClient::sendItem(const std::string& address,uint16_t port,RsItem *item,st rss.addSerialType(fss); FsSerializer().serialise(item,data,&size); + write(CreateSocket,data,size); // shouldn't we use the pqistreamer in R/W mode instead? - // TODO: we should write in multiple chunks just in case the socket is not fully ready - write(CreateSocket,data,size); + RsDbg() << "Item sent. Waiting for response..." ; // Now attempt to read and deserialize anything that comes back from that connexion until it gets closed by the server. FsBioInterface bio(CreateSocket); - pqistreamer pqi(&rss,RsPeerId(),&bio,BIN_FLAGS_READABLE); - pqithreadstreamer p(&pqi,&rss,RsPeerId(),&bio,BIN_FLAGS_READABLE); + pqithreadstreamer p(this,&rss,RsPeerId(),&bio,BIN_FLAGS_READABLE | BIN_FLAGS_NO_DELETE); p.start(); + uint32_t ss; + p.SendItem(item,ss); + while(true) { - RsItem *item = p.GetItem(); + p.tick(); + + RsItem *item = GetItem(); if(item) { @@ -134,11 +138,6 @@ bool FsClient::sendItem(const std::string& address,uint16_t port,RsItem *item,st std::cerr << "Got a response item: " << std::endl; std::cerr << *item << std::endl; } - else - { - std::this_thread::sleep_for(std::chrono::milliseconds(200)); - continue; - } if(!bio.isactive()) // socket has probably closed { @@ -147,11 +146,28 @@ bool FsClient::sendItem(const std::string& address,uint16_t port,RsItem *item,st close(CreateSocket); CreateSocket=0; + break; } + + std::this_thread::sleep_for(std::chrono::milliseconds(200)); } - return 0; - - // if ok, stream the item through it + return true; } +bool FsClient::RecvItem(RsItem *item) +{ + mIncomingItems.push_back(item); + return true; +} + +RsItem *FsClient::GetItem() +{ + if(mIncomingItems.empty()) + return nullptr; + + RsItem *item = mIncomingItems.front(); + mIncomingItems.pop_front(); + + return item; +} diff --git a/src/friend_server/fsclient.h b/src/friend_server/fsclient.h index 76af44a43..a14fc82ef 100644 --- a/src/friend_server/fsclient.h +++ b/src/friend_server/fsclient.h @@ -22,17 +22,27 @@ #include #include "fsitem.h" +#include "pqi/pqi_base.h" // This class runs a client connection to the friend server. It opens a socket at each connection. -class FsClient +class FsClient: public PQInterface { public: - FsClient() {} + FsClient() :PQInterface(RsPeerId()) {} bool requestFriends(const std::string& address,uint16_t port,uint32_t reqs,std::map& friend_certificates); +protected: + // Implements PQInterface + + bool RecvItem(RsItem *item) override; + int SendItem(RsItem *) override { RsErr() << "FsClient::SendItem() called although it should not." ; return 0;} + RsItem *GetItem() override; + private: bool sendItem(const std::string &address, uint16_t port, RsItem *item, std::list &response); + + std::list mIncomingItems; }; diff --git a/src/friend_server/fsmanager.cc b/src/friend_server/fsmanager.cc index ca520bb4f..876ae8170 100644 --- a/src/friend_server/fsmanager.cc +++ b/src/friend_server/fsmanager.cc @@ -96,6 +96,8 @@ void FriendServerManager::threadTick() if(mLastFriendReqestCampain + delay_for_request < now) { + mLastFriendReqestCampain = now; + std::cerr << "Requesting new friends to friend server..." << std::endl; std::map friend_certificates; From a00340d02f1e71d13dc16c03eab7792934bb5b9b Mon Sep 17 00:00:00 2001 From: csoler Date: Sun, 31 Oct 2021 18:00:43 +0100 Subject: [PATCH 13/31] fixed memory error --- src/friend_server/fsclient.cc | 17 +++++++++++------ src/friend_server/fsmanager.cc | 4 ++-- 2 files changed, 13 insertions(+), 8 deletions(-) diff --git a/src/friend_server/fsclient.cc b/src/friend_server/fsclient.cc index 9b2459b7c..b5f385d65 100644 --- a/src/friend_server/fsclient.cc +++ b/src/friend_server/fsclient.cc @@ -109,8 +109,8 @@ bool FsClient::sendItem(const std::string& address,uint16_t port,RsItem *item,st } FsSerializer *fss = new FsSerializer; - RsSerialiser rss; - rss.addSerialType(fss); + RsSerialiser *rss = new RsSerialiser(); // deleted by ~pqistreamer() + rss->addSerialType(fss); FsSerializer().serialise(item,data,&size); write(CreateSocket,data,size); // shouldn't we use the pqistreamer in R/W mode instead? @@ -119,8 +119,9 @@ bool FsClient::sendItem(const std::string& address,uint16_t port,RsItem *item,st // Now attempt to read and deserialize anything that comes back from that connexion until it gets closed by the server. - FsBioInterface bio(CreateSocket); - pqithreadstreamer p(this,&rss,RsPeerId(),&bio,BIN_FLAGS_READABLE | BIN_FLAGS_NO_DELETE); + FsBioInterface *bio = new FsBioInterface(CreateSocket); // deleted by ~pqistreamer() + + pqithreadstreamer p(this,rss,RsPeerId(),bio,BIN_FLAGS_READABLE | BIN_FLAGS_NO_DELETE | BIN_FLAGS_NO_CLOSE); p.start(); uint32_t ss; @@ -139,13 +140,17 @@ bool FsClient::sendItem(const std::string& address,uint16_t port,RsItem *item,st std::cerr << *item << std::endl; } - if(!bio.isactive()) // socket has probably closed + if(!bio->isactive()) // socket has probably closed { - RsDbg() << "(client side) Socket has been closed by server. Killing pqistreamer and closing socket." ; + RsDbg() << "(client side) Socket has been closed by server."; + RsDbg() << " Stopping/killing pqistreamer" ; p.fullstop(); + RsDbg() << " Closing socket." ; close(CreateSocket); CreateSocket=0; + + RsDbg() << " Exiting loop." ; break; } diff --git a/src/friend_server/fsmanager.cc b/src/friend_server/fsmanager.cc index 876ae8170..199bb99d7 100644 --- a/src/friend_server/fsmanager.cc +++ b/src/friend_server/fsmanager.cc @@ -4,9 +4,9 @@ RsFriendServer *rsFriendServer = nullptr; -static const rstime_t MIN_DELAY_BETWEEN_FS_REQUESTS = 30; +static const rstime_t MIN_DELAY_BETWEEN_FS_REQUESTS = 30; static const rstime_t MAX_DELAY_BETWEEN_FS_REQUESTS = 3600; -static const uint32_t DEFAULT_FRIENDS_TO_REQUEST = 10; +static const uint32_t DEFAULT_FRIENDS_TO_REQUEST = 10; static const std::string DEFAULT_FRIEND_SERVER_ADDRESS = "127.0.0.1"; static const uint16_t DEFAULT_FRIEND_SERVER_PORT = 2017; From bad11515b1498c9dcd279a23cc5b5bad267372b1 Mon Sep 17 00:00:00 2001 From: csoler Date: Mon, 1 Nov 2021 09:16:41 +0100 Subject: [PATCH 14/31] send/recv PGP public key and short invite --- src/friend_server/fsclient.cc | 14 ++++++++++++-- src/friend_server/fsitem.h | 10 +++++++--- 2 files changed, 19 insertions(+), 5 deletions(-) diff --git a/src/friend_server/fsclient.cc b/src/friend_server/fsclient.cc index b5f385d65..5548168a2 100644 --- a/src/friend_server/fsclient.cc +++ b/src/friend_server/fsclient.cc @@ -33,10 +33,20 @@ bool FsClient::requestFriends(const std::string& address,uint16_t port,uint32_t RsFriendServerClientPublishItem *pitem = new RsFriendServerClientPublishItem(); pitem->n_requested_friends = reqs; - pitem->long_invite = rsPeers->GetRetroshareInvite(); + + std::string pgp_base64_string,pgp_base64_checksum,short_invite; + rsPeers->GetPGPBase64StringAndCheckSum(rsPeers->getGPGOwnId(),pgp_base64_string,pgp_base64_checksum); + + if(!rsPeers->getShortInvite(short_invite,RsPeerId(),RetroshareInviteFlags::RADIX_FORMAT | RetroshareInviteFlags::DNS)) + { + RsErr() << "Cannot request own short invite! Something's very wrong." ; + return false; + } + + pitem->pgp_public_key_b64 = pgp_base64_string; + pitem->short_invite = short_invite; std::list response; - sendItem(address,port,pitem,response); // now decode the response diff --git a/src/friend_server/fsitem.h b/src/friend_server/fsitem.h index 3ca7e50d5..e3990b19f 100644 --- a/src/friend_server/fsitem.h +++ b/src/friend_server/fsitem.h @@ -26,6 +26,7 @@ #include "serialiser/rsserializer.h" #include "rsitems/rsitem.h" +#include "serialiser/rstlvbinary.h" #include "rsitems/rsserviceids.h" #include "rsitems/itempriorities.h" @@ -53,18 +54,21 @@ public: void serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx) override { RS_SERIAL_PROCESS(n_requested_friends); - RS_SERIAL_PROCESS(long_invite); + RS_SERIAL_PROCESS(short_invite); + RS_SERIAL_PROCESS(pgp_public_key_b64); } virtual void clear() override { - long_invite = std::string(); + pgp_public_key_b64.clear(); + short_invite.clear(); n_requested_friends=0; } // specific members for that item uint32_t n_requested_friends; - std::string long_invite; + std::string short_invite; + std::string pgp_public_key_b64; }; class RsFriendServerClientRemoveItem: public RsFriendServerItem From ad77d5e708713777acca691072f8fbb9b03bc952 Mon Sep 17 00:00:00 2001 From: csoler Date: Mon, 1 Nov 2021 10:47:07 +0100 Subject: [PATCH 15/31] moved static/parsing of radix parts of short invites into RsCertificate (more code should be moved static there) and fixed adding incoming keys to friend server --- src/pgp/rscertificate.cc | 135 +++++++++++++++++++++++++++++++ src/pgp/rscertificate.h | 17 ++++ src/rsserver/p3peers.cc | 170 ++++----------------------------------- 3 files changed, 168 insertions(+), 154 deletions(-) diff --git a/src/pgp/rscertificate.cc b/src/pgp/rscertificate.cc index f3007bb01..3f01b3d52 100644 --- a/src/pgp/rscertificate.cc +++ b/src/pgp/rscertificate.cc @@ -28,6 +28,7 @@ #include #include #include +#include #include "rscertificate.h" #include "util/rsstring.h" #include "util/stacktrace.h" @@ -621,6 +622,140 @@ bool RsCertificate::cleanRadix64(const std::string& instr,std::string& str,uint3 return true ; } +bool RsCertificate::decodeRadix64ShortInvite(const std::string& rsInvite, RsPeerDetails& details, uint32_t& err_code) +{ + err_code = 0; + std::vector bf = Radix64::decode(rsInvite); + size_t size = bf.size(); + + unsigned char* buf = bf.data(); + size_t total_s = 0; + bool CRC_ok = false ; // not checked yet + + while(total_s < size) + { + RsShortInviteFieldType ptag = RsShortInviteFieldType(buf[0]); + buf = &buf[1]; + + unsigned char *buf2 = buf; + uint32_t s = 0; + + try { s = PGPKeyParser::read_125Size(buf); } + catch (...) + { + err_code = CERTIFICATE_PARSING_ERROR_SIZE_ERROR; + return false; + } + + total_s += 1 + ( reinterpret_cast(buf) - reinterpret_cast(buf2) ); + + if(total_s > size) + { + err_code = CERTIFICATE_PARSING_ERROR_SIZE_ERROR; + return false; + } + + Dbg3() << __PRETTY_FUNCTION__ << " Read ptag: " + << static_cast(ptag) + << ", size " << s << ", total_s = " << total_s + << ", expected total = " << size << std::endl; + + switch(ptag) + { + case RsShortInviteFieldType::SSL_ID: + details.id = RsPeerId::fromBufferUnsafe(buf) ; + break; + + case RsShortInviteFieldType::PEER_NAME: + details.name = std::string((char*)buf,s); + break; + + case RsShortInviteFieldType::PGP_FINGERPRINT: + details.fpr = RsPgpFingerprint::fromBufferUnsafe(buf); + details.gpg_id = PGPHandler::pgpIdFromFingerprint(details.fpr); + break; + + case RsShortInviteFieldType::LOCATOR: + { + std::string locatorStr((char*)buf,s); + details.ipAddressList.push_back(locatorStr); + } + break; + + case RsShortInviteFieldType::DNS_LOCATOR: + details.extPort = (((int)buf[0]) << 8) + buf[1]; + details.dyndns = std::string((char*)&buf[2],s-2); + break; + + case RsShortInviteFieldType::LOC4_LOCATOR: + { + uint32_t t4Addr = (((uint32_t)buf[0]) << 24)+(((uint32_t)buf[1])<<16)+(((uint32_t)buf[2])<<8) + (uint32_t)buf[3]; + sockaddr_in tLocalAddr; + tLocalAddr.sin_addr.s_addr = t4Addr; + + details.localAddr = rs_inet_ntoa(tLocalAddr.sin_addr); + details.localPort = (((uint32_t)buf[4])<<8) + (uint32_t)buf[5]; + } + break; + + case RsShortInviteFieldType::EXT4_LOCATOR: + { + uint32_t t4Addr = (((uint32_t)buf[0]) << 24)+(((uint32_t)buf[1])<<16)+(((uint32_t)buf[2])<<8) + (uint32_t)buf[3]; + sockaddr_in tExtAddr; + tExtAddr.sin_addr.s_addr = t4Addr; + + details.extAddr = rs_inet_ntoa(tExtAddr.sin_addr); + details.extPort = (((uint32_t)buf[4])<<8) + (uint32_t)buf[5]; + } + break; + + case RsShortInviteFieldType::HIDDEN_LOCATOR: + details.hiddenType = (((uint32_t)buf[0]) << 24)+(((uint32_t)buf[1])<<16)+(((uint32_t)buf[2])<<8) + (uint32_t)buf[3]; + details.hiddenNodePort = (((uint32_t)buf[4]) << 8)+ (uint32_t)buf[5]; + details.isHiddenNode = true; + details.hiddenNodeAddress = std::string((char*)&buf[6],s-6); + break; + + case RsShortInviteFieldType::CHECKSUM: + { + if(s != 3 || total_s+3 != size) // make sure the checksum is the last section + { + err_code = CERTIFICATE_PARSING_ERROR_INVALID_CHECKSUM_SECTION; + return false; + } + uint32_t computed_crc = PGPKeyManagement::compute24bitsCRC(bf.data(),size-5); + uint32_t certificate_crc = static_cast( buf[0] + (buf[1] << 8) + (buf[2] << 16) ); + + if(computed_crc != certificate_crc) + { + err_code = CERTIFICATE_PARSING_ERROR_CHECKSUM_ERROR; + return false; + } + CRC_ok = true; + break; + } + + } + + buf = &buf[s]; + total_s += s; + } + + if(details.id.isNull()) + { + err_code = CERTIFICATE_PARSING_ERROR_MISSING_LOCATION_ID; + return false; + } + if(!CRC_ok) + { + err_code = CERTIFICATE_PARSING_ERROR_CHECKSUM_ERROR; + return false; + } + + return true; +} + + diff --git a/src/pgp/rscertificate.h b/src/pgp/rscertificate.h index 1ba3db633..17a7e4cb8 100644 --- a/src/pgp/rscertificate.h +++ b/src/pgp/rscertificate.h @@ -36,6 +36,21 @@ struct RsPeerDetails; class RsCertificate { public: + enum class RsShortInviteFieldType : uint8_t + { + SSL_ID = 0x00, + PEER_NAME = 0x01, + LOCATOR = 0x02, + PGP_FINGERPRINT = 0x03, + CHECKSUM = 0x04, + + /* The following will be deprecated, and ported to LOCATOR when generic transport layer will be implemented */ + HIDDEN_LOCATOR = 0x90, + DNS_LOCATOR = 0x91, + EXT4_LOCATOR = 0x92, // external IPv4 address + LOC4_LOCATOR = 0x93 // local IPv4 address + }; + typedef enum { RS_CERTIFICATE_OLD_FORMAT, RS_CERTIFICATE_RADIX, RS_CERTIFICATE_SHORT_RADIX } Format; /** @@ -64,6 +79,8 @@ public: ~RsCertificate(); + static bool decodeRadix64ShortInvite(const std::string& short_invite_b64,RsPeerDetails& det,uint32_t& error_code); + /// Convert to certificate radix string std::string toStdString() const; diff --git a/src/rsserver/p3peers.cc b/src/rsserver/p3peers.cc index c44877fc5..eeed8aa3d 100644 --- a/src/rsserver/p3peers.cc +++ b/src/rsserver/p3peers.cc @@ -48,6 +48,7 @@ #include "pqi/authssl.h" +typedef RsCertificate::RsShortInviteFieldType RsShortInviteFieldType; // locally in this file to avoid renaming everything. RsPeers *rsPeers = NULL; @@ -1159,22 +1160,6 @@ bool p3Peers::GetPGPBase64StringAndCheckSum( return true; } -enum class RsShortInviteFieldType : uint8_t -{ - SSL_ID = 0x00, - PEER_NAME = 0x01, - LOCATOR = 0x02, - PGP_FINGERPRINT = 0x03, - CHECKSUM = 0x04, - - /* The following will be deprecated, and ported to LOCATOR when generic - * trasport layer will be implemented */ - HIDDEN_LOCATOR = 0x90, - DNS_LOCATOR = 0x91, - EXT4_LOCATOR = 0x92, // external IPv4 address - LOC4_LOCATOR = 0x93 // local IPv4 address -}; - static void addPacketHeader(RsShortInviteFieldType ptag, size_t size, unsigned char *& buf, uint32_t& offset, uint32_t& buf_size) { // Check that the buffer has sufficient size. If not, increase it. @@ -1351,136 +1336,23 @@ bool p3Peers::getShortInvite(std::string& invite, const RsPeerId& _sslId, Retros bool p3Peers::parseShortInvite(const std::string& inviteStrUrl, RsPeerDetails& details, uint32_t &err_code ) { - if(inviteStrUrl.empty()) - { - RsErr() << __PRETTY_FUNCTION__ << " can't parse empty invite" - << std::endl; - return false; - } - std::string rsInvite = inviteStrUrl; + if(inviteStrUrl.empty()) + { + RsErr() << __PRETTY_FUNCTION__ << " can't parse empty invite" + << std::endl; + return false; + } + std::string rsInvite = inviteStrUrl; - RsUrl inviteUrl(inviteStrUrl); + RsUrl inviteUrl(inviteStrUrl); - if(inviteUrl.hasQueryK("rsInvite")) - rsInvite = *inviteUrl.getQueryV("rsInvite"); + if(inviteUrl.hasQueryK("rsInvite")) + rsInvite = *inviteUrl.getQueryV("rsInvite"); - std::vector bf = Radix64::decode(rsInvite); - size_t size = bf.size(); + if(!RsCertificate::decodeRadix64ShortInvite(rsInvite, details, err_code)) + return false; - unsigned char* buf = bf.data(); - size_t total_s = 0; - bool CRC_ok = false ; // not checked yet - - while(total_s < size) - { - RsShortInviteFieldType ptag = RsShortInviteFieldType(buf[0]); - buf = &buf[1]; - - unsigned char *buf2 = buf; - uint32_t s = 0; - - try { s = PGPKeyParser::read_125Size(buf); } - catch (...) - { - err_code = CERTIFICATE_PARSING_ERROR_SIZE_ERROR; - return false; - } - - total_s += 1 + ( reinterpret_cast(buf) - reinterpret_cast(buf2) ); - - if(total_s > size) - { - err_code = CERTIFICATE_PARSING_ERROR_SIZE_ERROR; - return false; - } - - Dbg3() << __PRETTY_FUNCTION__ << " Read ptag: " - << static_cast(ptag) - << ", size " << s << ", total_s = " << total_s - << ", expected total = " << size << std::endl; - - switch(ptag) - { - case RsShortInviteFieldType::SSL_ID: - details.id = RsPeerId::fromBufferUnsafe(buf) ; - break; - - case RsShortInviteFieldType::PEER_NAME: - details.name = std::string((char*)buf,s); - break; - - case RsShortInviteFieldType::PGP_FINGERPRINT: - details.fpr = RsPgpFingerprint::fromBufferUnsafe(buf); - details.gpg_id = PGPHandler::pgpIdFromFingerprint(details.fpr); - break; - - case RsShortInviteFieldType::LOCATOR: - { - std::string locatorStr((char*)buf,s); - details.ipAddressList.push_back(locatorStr); - } - break; - - case RsShortInviteFieldType::DNS_LOCATOR: - details.extPort = (((int)buf[0]) << 8) + buf[1]; - details.dyndns = std::string((char*)&buf[2],s-2); - break; - - case RsShortInviteFieldType::LOC4_LOCATOR: - { - uint32_t t4Addr = (((uint32_t)buf[0]) << 24)+(((uint32_t)buf[1])<<16)+(((uint32_t)buf[2])<<8) + (uint32_t)buf[3]; - sockaddr_in tLocalAddr; - tLocalAddr.sin_addr.s_addr = t4Addr; - - details.localAddr = rs_inet_ntoa(tLocalAddr.sin_addr); - details.localPort = (((uint32_t)buf[4])<<8) + (uint32_t)buf[5]; - } - break; - - case RsShortInviteFieldType::EXT4_LOCATOR: - { - uint32_t t4Addr = (((uint32_t)buf[0]) << 24)+(((uint32_t)buf[1])<<16)+(((uint32_t)buf[2])<<8) + (uint32_t)buf[3]; - sockaddr_in tExtAddr; - tExtAddr.sin_addr.s_addr = t4Addr; - - details.extAddr = rs_inet_ntoa(tExtAddr.sin_addr); - details.extPort = (((uint32_t)buf[4])<<8) + (uint32_t)buf[5]; - } - break; - - case RsShortInviteFieldType::HIDDEN_LOCATOR: - details.hiddenType = (((uint32_t)buf[0]) << 24)+(((uint32_t)buf[1])<<16)+(((uint32_t)buf[2])<<8) + (uint32_t)buf[3]; - details.hiddenNodePort = (((uint32_t)buf[4]) << 8)+ (uint32_t)buf[5]; - details.isHiddenNode = true; - details.hiddenNodeAddress = std::string((char*)&buf[6],s-6); - break; - - case RsShortInviteFieldType::CHECKSUM: - { - if(s != 3 || total_s+3 != size) // make sure the checksum is the last section - { - err_code = CERTIFICATE_PARSING_ERROR_INVALID_CHECKSUM_SECTION; - return false; - } - uint32_t computed_crc = PGPKeyManagement::compute24bitsCRC(bf.data(),size-5); - uint32_t certificate_crc = static_cast( buf[0] + (buf[1] << 8) + (buf[2] << 16) ); - - if(computed_crc != certificate_crc) - { - err_code = CERTIFICATE_PARSING_ERROR_CHECKSUM_ERROR; - return false; - } - CRC_ok = true; - break; - } - - } - - buf = &buf[s]; - total_s += s; - } - - // now check if the PGP key is available. If so, add it in the PeerDetails: + // Also check if the PGP key is available. If so, add it in the PeerDetails: RsPeerDetails pgp_det ; if(getGPGDetails(PGPHandler::pgpIdFromFingerprint(details.fpr),pgp_det) && pgp_det.fpr == details.fpr) @@ -1497,23 +1369,13 @@ bool p3Peers::parseShortInvite(const std::string& inviteStrUrl, RsPeerDetails& d else details.skip_pgp_signature_validation = true; - if(!CRC_ok) - { - err_code = CERTIFICATE_PARSING_ERROR_CHECKSUM_ERROR; - return false; - } if(details.gpg_id.isNull()) { err_code = CERTIFICATE_PARSING_ERROR_MISSING_PGP_FINGERPRINT; return false; } - if(details.id.isNull()) - { - err_code = CERTIFICATE_PARSING_ERROR_MISSING_LOCATION_ID; - return false; - } - err_code = CERTIFICATE_PARSING_ERROR_NO_ERROR; - return true; + err_code = CERTIFICATE_PARSING_ERROR_NO_ERROR; + return true; } bool p3Peers::acceptInvite( const std::string& invite, From 692f790545fda3442f4757459e8402a148fb4b17 Mon Sep 17 00:00:00 2001 From: csoler Date: Mon, 1 Nov 2021 16:14:13 +0100 Subject: [PATCH 16/31] added nonce system for safe peer removal --- src/friend_server/fsitem.h | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/src/friend_server/fsitem.h b/src/friend_server/fsitem.h index e3990b19f..d523f5726 100644 --- a/src/friend_server/fsitem.h +++ b/src/friend_server/fsitem.h @@ -76,10 +76,23 @@ class RsFriendServerClientRemoveItem: public RsFriendServerItem public: RsFriendServerClientRemoveItem() : RsFriendServerItem(RS_PKT_SUBTYPE_FS_CLIENT_REMOVE) {} - void serial_process(RsGenericSerializer::SerializeJob /* j */,RsGenericSerializer::SerializeContext& /* ctx */) + void serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx) { + RS_SERIAL_PROCESS(peer_id); + RS_SERIAL_PROCESS(nonce); } + + // Peer ID for the peer to remove. + + RsPeerId peer_id; + + // Nonce that was returned by the server after the last client request. Should match in order to proceed. This prevents + // a malicious actor from removing peers from the server. Since the nonce is sent through Tor tunnels, it cannot be known by + // anyone else than the client. + + uint64_t nonce; }; + class RsFriendServerEncryptedServerResponseItem: public RsFriendServerItem { public: From b5b70180949be07772adb2f724c86b87826e94c4 Mon Sep 17 00:00:00 2001 From: csoler Date: Mon, 1 Nov 2021 22:01:59 +0100 Subject: [PATCH 17/31] added response system from friend server --- src/friend_server/fsitem.h | 3 +++ src/pgp/pgphandler.cc | 14 +++++++++----- 2 files changed, 12 insertions(+), 5 deletions(-) diff --git a/src/friend_server/fsitem.h b/src/friend_server/fsitem.h index d523f5726..ca6d4d076 100644 --- a/src/friend_server/fsitem.h +++ b/src/friend_server/fsitem.h @@ -123,15 +123,18 @@ public: void serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx) override { + RS_SERIAL_PROCESS(nonce); RS_SERIAL_PROCESS(friend_invites); } virtual void clear() override { friend_invites.clear(); + nonce = 0; } // specific members for that item + uint64_t nonce; std::map friend_invites; }; diff --git a/src/pgp/pgphandler.cc b/src/pgp/pgphandler.cc index b1e96b00b..b0ffd31cd 100644 --- a/src/pgp/pgphandler.cc +++ b/src/pgp/pgphandler.cc @@ -1926,7 +1926,10 @@ bool PGPHandler::locked_syncPublicKeyring() #else if(-1 == stat64(_pubring_path.c_str(), &buf)) #endif + { std::cerr << "PGPHandler::syncDatabase(): can't stat file " << _pubring_path << ". Can't sync public keyring." << std::endl; + buf.st_mtime = 0; + } if(_pubring_last_update_time < buf.st_mtime) { @@ -1968,12 +1971,13 @@ bool PGPHandler::locked_syncTrustDatabase() librs::util::ConvertUtf8ToUtf16(_trustdb_path, wfullname); if(-1 == _wstati64(wfullname.c_str(), &buf)) #else - if(-1 == stat64(_trustdb_path.c_str(), &buf)) + if(-1 == stat64(_trustdb_path.c_str(), &buf)) #endif - { - std::cerr << "PGPHandler::syncDatabase(): can't stat file " << _trustdb_path << ". Will force write it." << std::endl; - _trustdb_changed = true ; // we force write of trust database if it does not exist. - } + { + std::cerr << "PGPHandler::syncDatabase(): can't stat file " << _trustdb_path << ". Will force write it." << std::endl; + _trustdb_changed = true ; // we force write of trust database if it does not exist. + buf.st_mtime = 0; + } if(_trustdb_last_update_time < buf.st_mtime) { From ccc74f698ddaf49cf0f75100d50d0d308fb9b8e1 Mon Sep 17 00:00:00 2001 From: csoler Date: Thu, 4 Nov 2021 14:24:19 +0100 Subject: [PATCH 18/31] added debug output and fixed one bug in pqistreamer --- src/friend_server/fsbio.cc | 11 +++-- src/friend_server/fsclient.cc | 79 ++++++++++++++++++++++------------- src/friend_server/fsclient.h | 1 + src/friend_server/fsitem.h | 23 ++++++++++ src/pqi/pqistreamer.cc | 13 ++++-- 5 files changed, 90 insertions(+), 37 deletions(-) diff --git a/src/friend_server/fsbio.cc b/src/friend_server/fsbio.cc index 8d6933a76..6668a59c9 100644 --- a/src/friend_server/fsbio.cc +++ b/src/friend_server/fsbio.cc @@ -129,9 +129,14 @@ int FsBioInterface::readdata(void *data, int len) int FsBioInterface::senddata(void *data, int len) { -// int written = write(mCLintConnt, data, len); -// return written; - return len; + // shouldn't we better send in multiple packets, similarly to how we read? + + RsDbg() << "FsBioInterface: sending data packet of size " << len ; + + int written = write(mCLintConnt, data, len); + RsDbg() << "FsBioInterface: done."; + + return written; } int FsBioInterface::netstatus() { diff --git a/src/friend_server/fsclient.cc b/src/friend_server/fsclient.cc index 5548168a2..e76e75d71 100644 --- a/src/friend_server/fsclient.cc +++ b/src/friend_server/fsclient.cc @@ -55,30 +55,35 @@ bool FsClient::requestFriends(const std::string& address,uint16_t port,uint32_t for(auto item:response) { - auto *encrypted_response_item = dynamic_cast(item); + // auto *encrypted_response_item = dynamic_cast(item); - if(!encrypted_response_item) - { - delete item; - continue; - } + // if(!encrypted_response_item) + // { + // delete item; + // continue; + // } // For now, also handle unencrypted response items. Will be disabled in production auto *response_item = dynamic_cast(item); - if(!response_item) - { - delete item; - continue; - } + if(response_item) + handleServerResponse(response_item); - for(const auto& it:response_item->friend_invites) - friend_certificates.insert(it); + delete item; } return friend_certificates.size(); } +void FsClient::handleServerResponse(RsFriendServerServerResponseItem *item) +{ + std::cerr << "Received a response item from server: " << std::endl; + std::cerr << *item << std::endl; + + // for(const auto& it:response_item->friend_invites) + // friend_certificates.insert(it); +} + bool FsClient::sendItem(const std::string& address,uint16_t port,RsItem *item,std::list& response) { // open a connection @@ -131,42 +136,56 @@ bool FsClient::sendItem(const std::string& address,uint16_t port,RsItem *item,st FsBioInterface *bio = new FsBioInterface(CreateSocket); // deleted by ~pqistreamer() - pqithreadstreamer p(this,rss,RsPeerId(),bio,BIN_FLAGS_READABLE | BIN_FLAGS_NO_DELETE | BIN_FLAGS_NO_CLOSE); + pqithreadstreamer p(this,rss,RsPeerId(),bio,BIN_FLAGS_READABLE | BIN_FLAGS_WRITEABLE | BIN_FLAGS_NO_CLOSE); p.start(); uint32_t ss; p.SendItem(item,ss); + bool should_close = false; while(true) { - p.tick(); + p.tick(); // ticks bio RsItem *item = GetItem(); + RsDbg() << "Ticking for response..."; + if(item) { response.push_back(item); std::cerr << "Got a response item: " << std::endl; std::cerr << *item << std::endl; + + if(dynamic_cast(item) != nullptr) + { + RsDbg() << "End of transmission. " ; + should_close = true; + break; + } + + if(!bio->isactive()) // socket has probably closed + { + RsDbg() << "(client side) Socket has been closed by server."; + should_close =true; + break; + } } - - if(!bio->isactive()) // socket has probably closed - { - RsDbg() << "(client side) Socket has been closed by server."; - RsDbg() << " Stopping/killing pqistreamer" ; - p.fullstop(); - - RsDbg() << " Closing socket." ; - close(CreateSocket); - CreateSocket=0; - - RsDbg() << " Exiting loop." ; - break; - } - std::this_thread::sleep_for(std::chrono::milliseconds(200)); } + if(should_close) + { + RsDbg() << " Stopping/killing pqistreamer" ; + p.fullstop(); + + RsDbg() << " Closing socket." ; + close(CreateSocket); + CreateSocket=0; + + RsDbg() << " Exiting loop." ; + } + return true; } diff --git a/src/friend_server/fsclient.h b/src/friend_server/fsclient.h index a14fc82ef..4c17c142d 100644 --- a/src/friend_server/fsclient.h +++ b/src/friend_server/fsclient.h @@ -42,6 +42,7 @@ protected: private: bool sendItem(const std::string &address, uint16_t port, RsItem *item, std::list &response); + void handleServerResponse(RsFriendServerServerResponseItem *item); std::list mIncomingItems; }; diff --git a/src/friend_server/fsitem.h b/src/friend_server/fsitem.h index ca6d4d076..95522b550 100644 --- a/src/friend_server/fsitem.h +++ b/src/friend_server/fsitem.h @@ -34,6 +34,7 @@ const uint8_t RS_PKT_SUBTYPE_FS_CLIENT_PUBLISH = 0x01 ; const uint8_t RS_PKT_SUBTYPE_FS_CLIENT_REMOVE = 0x02 ; const uint8_t RS_PKT_SUBTYPE_FS_SERVER_RESPONSE = 0x03 ; const uint8_t RS_PKT_SUBTYPE_FS_SERVER_ENCRYPTED_RESPONSE = 0x04 ; +const uint8_t RS_PKT_SUBTYPE_FS_SERVER_STATUS = 0x05 ; class RsFriendServerItem: public RsItem { @@ -71,6 +72,27 @@ public: std::string pgp_public_key_b64; }; +class RsFriendServerStatusItem: public RsFriendServerItem +{ +public: + RsFriendServerStatusItem() : RsFriendServerItem(RS_PKT_SUBTYPE_FS_SERVER_STATUS) {} + + void serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx) override + { + RS_SERIAL_PROCESS(status); + } + + enum ConnectionStatus: uint8_t + { + UNKNOWN = 0x00, + END_OF_TRANSMISSION = 0x01 + }; + + // specific members for that item + + ConnectionStatus status; +}; + class RsFriendServerClientRemoveItem: public RsFriendServerItem { public: @@ -152,6 +174,7 @@ struct FsSerializer : RsServiceSerializer case RS_PKT_SUBTYPE_FS_CLIENT_REMOVE: return new RsFriendServerClientRemoveItem(); case RS_PKT_SUBTYPE_FS_CLIENT_PUBLISH: return new RsFriendServerClientPublishItem(); case RS_PKT_SUBTYPE_FS_SERVER_RESPONSE: return new RsFriendServerServerResponseItem(); + case RS_PKT_SUBTYPE_FS_SERVER_STATUS: return new RsFriendServerStatusItem(); case RS_PKT_SUBTYPE_FS_SERVER_ENCRYPTED_RESPONSE: return new RsFriendServerEncryptedServerResponseItem(); default: RsErr() << "Unknown subitem type " << item_sub_id << " in FsSerialiser" ; diff --git a/src/pqi/pqistreamer.cc b/src/pqi/pqistreamer.cc index 96b91dae6..6e01b8e71 100644 --- a/src/pqi/pqistreamer.cc +++ b/src/pqi/pqistreamer.cc @@ -357,6 +357,7 @@ int pqistreamer::status() // this method is overloaded by pqiqosstreamer void pqistreamer::locked_storeInOutputQueue(void *ptr,int,int) { + RsDbg() << "Storing packet " << std::hex << ptr << std::dec << " in outqueue."; mOutPkts.push_back(ptr); } @@ -375,9 +376,9 @@ int pqistreamer::queue_outpqi_locked(RsItem *pqi,uint32_t& pktsize) if(ptr == NULL) return 0 ; -#ifdef DEBUG_PQISTREAMER +//#ifdef DEBUG_PQISTREAMER std::cerr << "pqistreamer::queue_outpqi() serializing packet with packet size : " << pktsize << std::endl; -#endif +//#endif /*******************************************************************************************/ // keep info for stats for a while. Only keep the items for the last two seconds. sec n is ongoing and second n-1 @@ -521,7 +522,7 @@ int pqistreamer::handleoutgoing_locked() { /* if we are not active - clear anything in the queues. */ locked_clear_out_queue() ; -#ifdef DEBUG_PACKET_SLICING +#ifdef DEBUG_PACKET_SLICING std::cerr << "(II) Switching off packet slicing." << std::endl; #endif mAcceptsPacketSlicing = false ; @@ -1430,8 +1431,12 @@ void *pqistreamer::locked_pop_out_data(uint32_t /*max_slice_size*/, uint32_t &si { res = *(mOutPkts.begin()); mOutPkts.pop_front(); + + // In pqistreamer, we do not split outgoing packets. For now only pqiQoSStreamer supports packet slicing. + size = getRsItemSize(res); + #ifdef DEBUG_TRANSFERS - std::cerr << "pqistreamer::locked_pop_out_data() getting next pkt from mOutPkts queue"; + std::cerr << "pqistreamer::locked_pop_out_data() getting next pkt " << std::hex << res << std::dec << " from mOutPkts queue"; std::cerr << std::endl; #endif } From 1328ba7c934393e3de288a650e1757e68ec605b8 Mon Sep 17 00:00:00 2001 From: csoler Date: Thu, 4 Nov 2021 20:52:38 +0100 Subject: [PATCH 19/31] use recv(...,MSG_DONTWAIT), since read() may return multiple times the same data apparently --- src/friend_server/fsbio.cc | 2 +- src/friend_server/fsclient.cc | 5 ++++- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/src/friend_server/fsbio.cc b/src/friend_server/fsbio.cc index 6668a59c9..e5be9389b 100644 --- a/src/friend_server/fsbio.cc +++ b/src/friend_server/fsbio.cc @@ -39,7 +39,7 @@ int FsBioInterface::tick() char inBuffer[1025]; memset(inBuffer,0,1025); - int readbytes = read(mCLintConnt, inBuffer, sizeof(inBuffer)); + ssize_t readbytes = recv(mCLintConnt, inBuffer, sizeof(inBuffer),MSG_DONTWAIT); if(readbytes == 0) { diff --git a/src/friend_server/fsclient.cc b/src/friend_server/fsclient.cc index e76e75d71..e9bc3d325 100644 --- a/src/friend_server/fsclient.cc +++ b/src/friend_server/fsclient.cc @@ -157,6 +157,8 @@ bool FsClient::sendItem(const std::string& address,uint16_t port,RsItem *item,st std::cerr << "Got a response item: " << std::endl; std::cerr << *item << std::endl; + should_close = true; // always close the socket after one packet + if(dynamic_cast(item) != nullptr) { RsDbg() << "End of transmission. " ; @@ -171,7 +173,8 @@ bool FsClient::sendItem(const std::string& address,uint16_t port,RsItem *item,st break; } } - std::this_thread::sleep_for(std::chrono::milliseconds(200)); + else + std::this_thread::sleep_for(std::chrono::milliseconds(200)); } if(should_close) From 65015b8bbf8deac1d91b1c630fbfccfc67929c42 Mon Sep 17 00:00:00 2001 From: csoler Date: Fri, 5 Nov 2021 16:52:00 +0100 Subject: [PATCH 20/31] first part of peer sorting in friend server --- src/friend_server/fsbio.cc | 6 ++---- src/retroshare/rsids.h | 9 +++++++++ 2 files changed, 11 insertions(+), 4 deletions(-) diff --git a/src/friend_server/fsbio.cc b/src/friend_server/fsbio.cc index e5be9389b..313e073d7 100644 --- a/src/friend_server/fsbio.cc +++ b/src/friend_server/fsbio.cc @@ -32,8 +32,6 @@ FsBioInterface::FsBioInterface(int socket) int FsBioInterface::tick() { - std::cerr << "ticking FsNetworkInterface" << std::endl; - // 2 - read incoming data pending on existing connections char inBuffer[1025]; @@ -57,7 +55,7 @@ int FsBioInterface::tick() return mTotalBufferBytes; } - std::cerr << "clintConnt: " << mCLintConnt << ", readbytes: " << readbytes << std::endl; + RsDbg() << "clintConnt: " << mCLintConnt << ", readbytes: " << readbytes ; // display some debug info @@ -77,7 +75,7 @@ int FsBioInterface::tick() mTotalBufferBytes += readbytes; mTotalReadBytes += readbytes; - std::cerr << "Socket: " << mCLintConnt << ". Total read: " << mTotalReadBytes << ". Buffer size: " << mTotalBufferBytes << std::endl ; + RsDbg() << "Socket: " << mCLintConnt << ". Total read: " << mTotalReadBytes << ". Buffer size: " << mTotalBufferBytes ; } return mTotalBufferBytes; diff --git a/src/retroshare/rsids.h b/src/retroshare/rsids.h index d38ee4518..c7fec6725 100644 --- a/src/retroshare/rsids.h +++ b/src/retroshare/rsids.h @@ -168,6 +168,15 @@ struct t_RsGenericIdType return ret; } + inline Id_t operator^ (const Id_t& fp) const + { + Id_t ret; + for(uint32_t i=0; i < ID_SIZE_IN_BYTES; ++i) + ret.bytes[i] = bytes[i] ^ fp.bytes[i]; + return ret; + } + + inline bool isNull() const { for(uint32_t i=0; i < SIZE_IN_BYTES; ++i) From 9e6ea189302cc7fb85e0d3cf20d62ffb678d6195 Mon Sep 17 00:00:00 2001 From: csoler Date: Sat, 6 Nov 2021 17:49:31 +0100 Subject: [PATCH 21/31] added sorting of peers (part 2/2) --- src/friend_server/fsclient.cc | 4 ++-- src/pqi/pqistreamer.cc | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/friend_server/fsclient.cc b/src/friend_server/fsclient.cc index e9bc3d325..860b7a0c3 100644 --- a/src/friend_server/fsclient.cc +++ b/src/friend_server/fsclient.cc @@ -148,9 +148,9 @@ bool FsClient::sendItem(const std::string& address,uint16_t port,RsItem *item,st p.tick(); // ticks bio RsItem *item = GetItem(); - +#ifdef DEBUG_FSCLIENT RsDbg() << "Ticking for response..."; - +#endif if(item) { response.push_back(item); diff --git a/src/pqi/pqistreamer.cc b/src/pqi/pqistreamer.cc index 6e01b8e71..d3e02c632 100644 --- a/src/pqi/pqistreamer.cc +++ b/src/pqi/pqistreamer.cc @@ -376,9 +376,9 @@ int pqistreamer::queue_outpqi_locked(RsItem *pqi,uint32_t& pktsize) if(ptr == NULL) return 0 ; -//#ifdef DEBUG_PQISTREAMER +#ifdef DEBUG_PQISTREAMER std::cerr << "pqistreamer::queue_outpqi() serializing packet with packet size : " << pktsize << std::endl; -//#endif +#endif /*******************************************************************************************/ // keep info for stats for a while. Only keep the items for the last two seconds. sec n is ongoing and second n-1 From a4a7f154d7b7c57ef7309eaf489cd9d57f4fbc68 Mon Sep 17 00:00:00 2001 From: csoler Date: Sun, 7 Nov 2021 15:16:07 +0100 Subject: [PATCH 22/31] avoid sending packet slicing probes to the serializer in pqistreamer --- src/pqi/pqistreamer.cc | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/pqi/pqistreamer.cc b/src/pqi/pqistreamer.cc index d3e02c632..7f5a42301 100644 --- a/src/pqi/pqistreamer.cc +++ b/src/pqi/pqistreamer.cc @@ -803,11 +803,14 @@ start_packet_read: if(!memcmp(block,PACKET_SLICING_PROBE_BYTES,8)) { - mAcceptsPacketSlicing = !DISABLE_PACKET_SLICING; + mAcceptsPacketSlicing = !DISABLE_PACKET_SLICING; #ifdef DEBUG_PACKET_SLICING std::cerr << "(II) Enabling packet slicing!" << std::endl; #endif - } + mReading_state = reading_state_initial ; // restart at state 1. + mFailed_read_attempts = 0 ; + return 0; + } } continue_packet: { From 766b5b1bfd85dcd6420d47b391f2336b849a89d6 Mon Sep 17 00:00:00 2001 From: csoler Date: Sun, 7 Nov 2021 15:16:24 +0100 Subject: [PATCH 23/31] fixed two-ways communication between client and server --- src/friend_server/fsclient.cc | 45 +++++++++++------------------------ 1 file changed, 14 insertions(+), 31 deletions(-) diff --git a/src/friend_server/fsclient.cc b/src/friend_server/fsclient.cc index 860b7a0c3..8e809337a 100644 --- a/src/friend_server/fsclient.cc +++ b/src/friend_server/fsclient.cc @@ -127,12 +127,8 @@ bool FsClient::sendItem(const std::string& address,uint16_t port,RsItem *item,st RsSerialiser *rss = new RsSerialiser(); // deleted by ~pqistreamer() rss->addSerialType(fss); - FsSerializer().serialise(item,data,&size); - write(CreateSocket,data,size); // shouldn't we use the pqistreamer in R/W mode instead? - - RsDbg() << "Item sent. Waiting for response..." ; - - // Now attempt to read and deserialize anything that comes back from that connexion until it gets closed by the server. +// FsSerializer().serialise(item,data,&size); +// write(CreateSocket,data,size); // shouldn't we use the pqistreamer in R/W mode instead? FsBioInterface *bio = new FsBioInterface(CreateSocket); // deleted by ~pqistreamer() @@ -141,7 +137,10 @@ bool FsClient::sendItem(const std::string& address,uint16_t port,RsItem *item,st uint32_t ss; p.SendItem(item,ss); - bool should_close = false; + + RsDbg() << "Item sent. Waiting for response..." ; + + // Now attempt to read and deserialize anything that comes back from that connexion until it gets closed by the server. while(true) { @@ -157,37 +156,21 @@ bool FsClient::sendItem(const std::string& address,uint16_t port,RsItem *item,st std::cerr << "Got a response item: " << std::endl; std::cerr << *item << std::endl; - should_close = true; // always close the socket after one packet - - if(dynamic_cast(item) != nullptr) - { - RsDbg() << "End of transmission. " ; - should_close = true; - break; - } - - if(!bio->isactive()) // socket has probably closed - { - RsDbg() << "(client side) Socket has been closed by server."; - should_close =true; - break; - } + RsDbg() << "End of transmission. " ; + break; } else std::this_thread::sleep_for(std::chrono::milliseconds(200)); } - if(should_close) - { - RsDbg() << " Stopping/killing pqistreamer" ; - p.fullstop(); + RsDbg() << " Stopping/killing pqistreamer" ; + p.fullstop(); - RsDbg() << " Closing socket." ; - close(CreateSocket); - CreateSocket=0; + RsDbg() << " Closing socket." ; + close(CreateSocket); + CreateSocket=0; - RsDbg() << " Exiting loop." ; - } + RsDbg() << " Exiting loop." ; return true; } From a9d2a05b59e511ad3c6876fb545314cd59bf50c2 Mon Sep 17 00:00:00 2001 From: csoler Date: Wed, 10 Nov 2021 23:36:23 +0100 Subject: [PATCH 24/31] improved checking of short invite / pgp key in friend server. Added a key parsing method in PGPKeyManagement --- src/crypto/hashstream.cc | 7 +++++- src/pgp/pgpkeyutil.cc | 54 ++++++++++++++++++++++++++++++++++++++++ src/pgp/pgpkeyutil.h | 14 ++++++++++- 3 files changed, 73 insertions(+), 2 deletions(-) diff --git a/src/crypto/hashstream.cc b/src/crypto/hashstream.cc index 1d3c46b75..e1c39a60c 100644 --- a/src/crypto/hashstream.cc +++ b/src/crypto/hashstream.cc @@ -54,7 +54,12 @@ namespace librs return Sha1CheckSum(h); } - + template<> + HashStream& operator<<(HashStream& u,const std::pair& p) + { + EVP_DigestUpdate(u.mdctx,p.first,p.second) ; + return u; + } template<> HashStream& operator<<(HashStream& u,const std::string& s) { diff --git a/src/pgp/pgpkeyutil.cc b/src/pgp/pgpkeyutil.cc index 76b332edf..105556ebb 100644 --- a/src/pgp/pgpkeyutil.cc +++ b/src/pgp/pgpkeyutil.cc @@ -21,6 +21,7 @@ *******************************************************************************/ #include #include +#include #include "pgpkeyutil.h" #include @@ -181,6 +182,59 @@ uint32_t PGPKeyManagement::compute24bitsCRC(unsigned char *octets, size_t len) return crc & 0xFFFFFFL; } +bool PGPKeyManagement::parsePGPPublicKey(const unsigned char *keydata, size_t keylen, PGPKeyInfo& info) +{ +#ifdef DEBUG_PGPUTIL + std::cerr << "Total size: " << keylen << std::endl; +#endif + unsigned char *data = (unsigned char*)keydata; + + uint8_t packet_tag; + uint32_t packet_length ; + + PGPKeyParser::read_packetHeader(data,packet_tag,packet_length) ; + +#ifdef DEBUG_PGPUTIL + std::cerr << "Packet tag : " << (int)packet_tag << ", length=" << packet_length << std::endl; +#endif + if(packet_tag != PGPKeyParser::PGP_PACKET_TAG_PUBLIC_KEY) + { + std::cerr << "(EE) Parsing error in PGP public key. Expected a public key tag (6). Found " << (int)packet_tag << " instead." << std::endl; + return false; + } + librs::crypto::HashStream H(librs::crypto::HashStream::SHA1); + + H << (uint8_t)0x99; // RFC_4880 + + std::cerr << "Packet length = " << packet_length << std::endl; + + H << (uint8_t)(packet_length >> 8); + H << (uint8_t)(packet_length); + H << std::make_pair(data,packet_length) ; + + auto hash = H.hash(); + + memcpy(info.fingerprint, hash.toByteArray(),hash.SIZE_IN_BYTES); + + data += packet_length; + + // Read user ID. + + PGPKeyParser::read_packetHeader(data,packet_tag,packet_length) ; + + if(packet_tag != PGPKeyParser::PGP_PACKET_TAG_USER_ID) + { + std::cerr << "(EE) Parsing error in PGP public key. Expected a user ID key tag (13). Found " << (int)packet_tag << " instead." << std::endl; + return false; + } + + info.user_id.clear(); + + for(uint32_t i=0;i Date: Sun, 14 Nov 2021 23:31:40 +0100 Subject: [PATCH 25/31] created independent tcpsocket class to be used also in TorManager --- src/friend_server/{fsbio.cc => socketbio.cc} | 139 ++++++++++++++++--- src/friend_server/{fsbio.h => socketbio.h} | 19 ++- src/friend_server/tcpsocket.cc | 75 ++++++++++ src/friend_server/tcpsocket.h | 41 ++++++ src/libretroshare.pro | 10 +- 5 files changed, 263 insertions(+), 21 deletions(-) rename src/friend_server/{fsbio.cc => socketbio.cc} (61%) rename src/friend_server/{fsbio.h => socketbio.h} (82%) create mode 100644 src/friend_server/tcpsocket.cc create mode 100644 src/friend_server/tcpsocket.h diff --git a/src/friend_server/fsbio.cc b/src/friend_server/socketbio.cc similarity index 61% rename from src/friend_server/fsbio.cc rename to src/friend_server/socketbio.cc index 313e073d7..9caa45d56 100644 --- a/src/friend_server/fsbio.cc +++ b/src/friend_server/socketbio.cc @@ -24,16 +24,43 @@ #include "fsbio.h" FsBioInterface::FsBioInterface(int socket) - : mCLintConnt(socket),mIsActive(true) + : mCLintConnt(socket),mIsActive(socket!=0) { mTotalReadBytes=0; - mTotalBufferBytes=0; + mTotalInBufferBytes=0; + mTotalWrittenBytes=0; + mTotalOutBufferBytes=0; } +void FsBioInterface::setSocket(int s) +{ + if(mIsActive != 0) + { + RsErr() << "Changing socket to active FsBioInterface! Canceling all pending R/W data." ; + close(); + } + mCLintConnt = s; + mIsActive = (s!=0); +} int FsBioInterface::tick() { + if(!mIsActive) + { + RsErr() << "Ticking a non active FsBioInterface!" ; + return 0; + } // 2 - read incoming data pending on existing connections + int res=0; + + res += read_pending(); + res += write_pending(); + + return res; +} + +int FsBioInterface::read_pending() +{ char inBuffer[1025]; memset(inBuffer,0,1025); @@ -45,14 +72,14 @@ int FsBioInterface::tick() RsDbg() << "Closing!" ; close(); - return mTotalBufferBytes; + return mTotalInBufferBytes; } if(readbytes < 0) { if(errno != EWOULDBLOCK && errno != EAGAIN) RsErr() << "read() failed. Errno=" << errno ; - return mTotalBufferBytes; + return mTotalInBufferBytes; } RsDbg() << "clintConnt: " << mCLintConnt << ", readbytes: " << readbytes ; @@ -72,15 +99,80 @@ int FsBioInterface::tick() memcpy(ptr,inBuffer,readbytes); in_buffer.push_back(std::make_pair(ptr,readbytes)); - mTotalBufferBytes += readbytes; + mTotalInBufferBytes += readbytes; mTotalReadBytes += readbytes; - RsDbg() << "Socket: " << mCLintConnt << ". Total read: " << mTotalReadBytes << ". Buffer size: " << mTotalBufferBytes ; + RsDbg() << "Socket: " << mCLintConnt << ". Total read: " << mTotalReadBytes << ". Buffer size: " << mTotalInBufferBytes ; } - - return mTotalBufferBytes; + return mTotalInBufferBytes; } +int FsBioInterface::write_pending() +{ + if(out_buffer.empty()) + return mTotalOutBufferBytes; + + auto& p = out_buffer.front(); + int written = write(mCLintConnt, p.first, p.second); + + if(written < 0) + { + if(errno != EWOULDBLOCK && errno != EAGAIN) + RsErr() << "write() failed. Errno=" << errno ; + + return mTotalOutBufferBytes; + } + + if(written == 0) + { + RsErr() << "write() failed. Nothing sent."; + return mTotalOutBufferBytes; + } + + RsDbg() << "clintConnt: " << mCLintConnt << ", written: " << written ; + + // display some debug info + + RsDbg() << "Sent the following bytes: " << RsUtil::BinToHex( reinterpret_cast(p.first),written,50) << std::endl; + + if(written < p.second) + { + void *ptr = malloc(p.second - written); + + if(!ptr) + throw std::runtime_error("Cannot allocate memory! Go buy some RAM!"); + + memcpy(ptr,static_cast(p.first) + written,p.second - written); + free(p.first); + + out_buffer.front().first = ptr; + out_buffer.front().second = p.second - written; + } + else + { + free(p.first); + out_buffer.pop_front(); + } + + mTotalOutBufferBytes -= written; + mTotalWrittenBytes += written; + + return mTotalOutBufferBytes; +} + +FsBioInterface::~FsBioInterface() +{ + clean(); +} + +void FsBioInterface::clean() +{ + for(auto p:in_buffer) free(p.first); + for(auto p:out_buffer) free(p.first); + + in_buffer.clear(); + out_buffer.clear(); +} int FsBioInterface::readdata(void *data, int len) { // read incoming bytes in the buffer @@ -91,7 +183,7 @@ int FsBioInterface::readdata(void *data, int len) { if(in_buffer.empty()) { - mTotalBufferBytes -= total_len; + mTotalInBufferBytes -= total_len; return total_len; } @@ -108,7 +200,7 @@ int FsBioInterface::readdata(void *data, int len) in_buffer.front().first = ptr; in_buffer.front().second -= len-total_len; - mTotalBufferBytes -= len; + mTotalInBufferBytes -= len; return len; } else // copy everything @@ -121,7 +213,7 @@ int FsBioInterface::readdata(void *data, int len) in_buffer.pop_front(); } } - mTotalBufferBytes -= len; + mTotalInBufferBytes -= len; return len; } @@ -129,12 +221,24 @@ int FsBioInterface::senddata(void *data, int len) { // shouldn't we better send in multiple packets, similarly to how we read? - RsDbg() << "FsBioInterface: sending data packet of size " << len ; + if(len == 0) + { + RsErr() << "Calling FsBioInterface::senddata() with null size or null data pointer"; + return 0; + } + void *ptr = malloc(len); - int written = write(mCLintConnt, data, len); - RsDbg() << "FsBioInterface: done."; + if(!ptr) + { + RsErr() << "Cannot allocate data of size " << len ; + return 0; + } - return written; + memcpy(ptr,data,len); + out_buffer.push_back(std::make_pair(ptr,len)); + + mTotalOutBufferBytes += len; + return len; } int FsBioInterface::netstatus() { @@ -148,7 +252,7 @@ int FsBioInterface::isactive() bool FsBioInterface::moretoread(uint32_t /* usec */) { - return mTotalBufferBytes > 0; + return mTotalInBufferBytes > 0; } bool FsBioInterface::cansend(uint32_t) { @@ -159,6 +263,9 @@ int FsBioInterface::close() { RsDbg() << "Stopping network interface" << std::endl; mIsActive = false; + mCLintConnt = 0; + clean(); + return 1; } diff --git a/src/friend_server/fsbio.h b/src/friend_server/socketbio.h similarity index 82% rename from src/friend_server/fsbio.h rename to src/friend_server/socketbio.h index 6b2ed06bd..697719d74 100644 --- a/src/friend_server/fsbio.h +++ b/src/friend_server/socketbio.h @@ -26,12 +26,19 @@ class FsBioInterface: public BinInterface { public: FsBioInterface(int socket); + ~FsBioInterface(); // Implements BinInterface methods int tick() override; + // Schedule data to be sent at the next tick(). The caller keeps memory ownership. + // int senddata(void *data, int len) override; + + // Obtains new data from the interface. "data" needs to be initialized for room + // to len bytes. The returned value is the actual size of what was read. + // int readdata(void *data, int len) override; int netstatus() override; @@ -49,12 +56,22 @@ public: bool bandwidthLimited() override { return false; } +protected: + void setSocket(int s); + void clean(); + private: + int read_pending(); + int write_pending(); + int mCLintConnt; bool mIsActive; uint32_t mTotalReadBytes; - uint32_t mTotalBufferBytes; + uint32_t mTotalInBufferBytes; + uint32_t mTotalWrittenBytes; + uint32_t mTotalOutBufferBytes; std::list > in_buffer; + std::list > out_buffer; }; diff --git a/src/friend_server/tcpsocket.cc b/src/friend_server/tcpsocket.cc new file mode 100644 index 000000000..19b69d1b2 --- /dev/null +++ b/src/friend_server/tcpsocket.cc @@ -0,0 +1,75 @@ +#include +#include +#include +#include +#include + +#include "tcpsocket.h" + +TcpSocket::TcpSocket(const std::string& tcp_address,uint16_t tcp_port) + :FsBioInterface(0),mState(DISCONNECTED),mConnectAddress(tcp_address),mConnectPort(tcp_port),mSocket(0) +{ +} +int TcpSocket::connect() +{ + int CreateSocket = 0; + char dataReceived[1024]; + struct sockaddr_in ipOfServer; + + memset(dataReceived, '0' ,sizeof(dataReceived)); + + if((CreateSocket = socket(AF_INET, SOCK_STREAM, 0))< 0) + { + printf("Socket not created \n"); + return false; + } + + ipOfServer.sin_family = AF_INET; + ipOfServer.sin_port = htons(mConnectPort); + ipOfServer.sin_addr.s_addr = inet_addr(mConnectAddress.c_str()); + + if(::connect(mSocket, (struct sockaddr *)&ipOfServer, sizeof(ipOfServer))<0) + { + printf("Connection failed due to port and ip problems, or server is not available\n"); + return false; + } + mState = CONNECTED; + setSocket(mSocket); + + return true; +} + +int TcpSocket::close() +{ + FsBioInterface::close(); + + return !::close(mSocket); +} + +ThreadedTcpSocket::ThreadedTcpSocket(const std::string& tcp_address,uint16_t tcp_port) + : TcpSocket(tcp_address,tcp_port) +{ +} + +void ThreadedTcpSocket::run() +{ + if(!connect()) + { + RsErr() << "Cannot connect socket to " << connectAddress() << ":" << connectPort() ; + return ; + } + + while(connectionState() == CONNECTED) + { + tick(); + std::this_thread::sleep_for(std::chrono::milliseconds(200)); + } + RsWarn() << "Connection to " << connectAddress() << ":" << connectPort() << " is now closed."; +} + +ThreadedTcpSocket::~ThreadedTcpSocket() +{ + fullstop(); // fully wait for stopping. + + close(); +} diff --git a/src/friend_server/tcpsocket.h b/src/friend_server/tcpsocket.h new file mode 100644 index 000000000..f35cefb71 --- /dev/null +++ b/src/friend_server/tcpsocket.h @@ -0,0 +1,41 @@ +#include +#include "util/rsthreads.h" +#include "friend_server/fsbio.h" + +class TcpSocket: public FsBioInterface +{ +public: + TcpSocket(const std::string& tcp_address,uint16_t tcp_port); + + enum State: uint8_t { + UNKNOWN = 0x00, + DISCONNECTED = 0x01, + CONNECTED = 0x02 + }; + + // Return 1 when OK, 0 otherwise. + int connect(); + + // Returns 1 when OK, 0 otherwise. + int close(); + + State connectionState() const { return mState; } + const std::string& connectAddress() const { return mConnectAddress ; } + uint16_t connectPort() const { return mConnectPort ; } + +private: + State mState; + std::string mConnectAddress; + uint16_t mConnectPort; + int mSocket; +}; + +class ThreadedTcpSocket: public TcpSocket, public RsThread +{ +public: + ThreadedTcpSocket(const std::string& tcp_address,uint16_t tcp_port); + virtual ~ThreadedTcpSocket(); + + virtual void run() override; +}; + diff --git a/src/libretroshare.pro b/src/libretroshare.pro index c87076e32..8eda33e22 100644 --- a/src/libretroshare.pro +++ b/src/libretroshare.pro @@ -156,6 +156,7 @@ rs_webui { } HEADERS += plugins/pluginmanager.h \ + friend_server/socketbio.h \ plugins/dlfcn_win32.h \ rsitems/rspluginitems.h \ util/i2pcommon.h \ @@ -404,9 +405,10 @@ HEADERS += pqi/authssl.h \ pqi/p3servicecontrol.h SOURCES += friend_server/fsclient.h \ - friend_server/fsbio.h \ friend_server/fsitem.h \ - friend_server/fsmanager.h + friend_server/fsmanager.h \ + friend_server/socketbio.cc \ + friend_server/tcpsocket.h HEADERS += rsserver/p3face.h \ rsserver/p3history.h \ @@ -572,8 +574,8 @@ SOURCES += pqi/authgpg.cc \ pqi/p3servicecontrol.cc SOURCES += friend_server/fsclient.cc \ - friend_server/fsbio.cc \ - friend_server/fsmanager.cc + friend_server/fsmanager.cc \ + friend_server/tcpsocket.cc SOURCES += rsserver/p3face-config.cc \ rsserver/p3face-server.cc \ From b5a57133b3afd128e3dca8813b4bcdc7594d2d8f Mon Sep 17 00:00:00 2001 From: csoler Date: Tue, 16 Nov 2021 22:19:27 +0100 Subject: [PATCH 26/31] changed names SocketBioInterface->RsFdBinInterface and TcpSocket->RsTcpSocket (more consistent). Moved them to pqi/ --- src/friend_server/fsclient.cc | 4 +-- src/libretroshare.pro | 12 +++---- .../socketbio.cc => pqi/pqifdbin.cc} | 32 +++++++++---------- .../socketbio.h => pqi/pqifdbin.h} | 6 ++-- .../tcpsocket.cc => pqi/rstcpsocket.cc} | 20 ++++++------ .../tcpsocket.h => pqi/rstcpsocket.h} | 12 +++---- 6 files changed, 43 insertions(+), 43 deletions(-) rename src/{friend_server/socketbio.cc => pqi/pqifdbin.cc} (91%) rename src/{friend_server/socketbio.h => pqi/pqifdbin.h} (96%) rename src/{friend_server/tcpsocket.cc => pqi/rstcpsocket.cc} (72%) rename src/{friend_server/tcpsocket.h => pqi/rstcpsocket.h} (67%) diff --git a/src/friend_server/fsclient.cc b/src/friend_server/fsclient.cc index 8e809337a..adc294d0c 100644 --- a/src/friend_server/fsclient.cc +++ b/src/friend_server/fsclient.cc @@ -24,7 +24,7 @@ #include "retroshare/rspeers.h" #include "fsclient.h" -#include "fsbio.h" +#include "pqi/pqifdbin.h" bool FsClient::requestFriends(const std::string& address,uint16_t port,uint32_t reqs,std::map& friend_certificates) { @@ -130,7 +130,7 @@ bool FsClient::sendItem(const std::string& address,uint16_t port,RsItem *item,st // FsSerializer().serialise(item,data,&size); // write(CreateSocket,data,size); // shouldn't we use the pqistreamer in R/W mode instead? - FsBioInterface *bio = new FsBioInterface(CreateSocket); // deleted by ~pqistreamer() + RsFdBinInterface *bio = new RsFdBinInterface(CreateSocket); // deleted by ~pqistreamer() pqithreadstreamer p(this,rss,RsPeerId(),bio,BIN_FLAGS_READABLE | BIN_FLAGS_WRITEABLE | BIN_FLAGS_NO_CLOSE); p.start(); diff --git a/src/libretroshare.pro b/src/libretroshare.pro index 8eda33e22..e79a5e82e 100644 --- a/src/libretroshare.pro +++ b/src/libretroshare.pro @@ -156,7 +156,6 @@ rs_webui { } HEADERS += plugins/pluginmanager.h \ - friend_server/socketbio.h \ plugins/dlfcn_win32.h \ rsitems/rspluginitems.h \ util/i2pcommon.h \ @@ -366,6 +365,8 @@ HEADERS += pqi/authssl.h \ pqi/authgpg.h \ pgp/pgphandler.h \ pgp/pgpkeyutil.h \ + pqi/pqifdbin.h \ + pqi/rstcpsocket.h \ pgp/rscertificate.h \ pgp/pgpauxutils.h \ pqi/p3cfgmgr.h \ @@ -406,9 +407,7 @@ HEADERS += pqi/authssl.h \ SOURCES += friend_server/fsclient.h \ friend_server/fsitem.h \ - friend_server/fsmanager.h \ - friend_server/socketbio.cc \ - friend_server/tcpsocket.h + friend_server/fsmanager.h HEADERS += rsserver/p3face.h \ rsserver/p3history.h \ @@ -548,6 +547,8 @@ SOURCES += pqi/authgpg.cc \ pqi/p3cfgmgr.cc \ pqi/p3peermgr.cc \ pqi/p3linkmgr.cc \ + pqi/pqifdbin.cc \ + pqi/rstcpsocket.cc \ pqi/p3netmgr.cc \ pqi/p3notify.cc \ pqi/pqiqos.cc \ @@ -574,8 +575,7 @@ SOURCES += pqi/authgpg.cc \ pqi/p3servicecontrol.cc SOURCES += friend_server/fsclient.cc \ - friend_server/fsmanager.cc \ - friend_server/tcpsocket.cc + friend_server/fsmanager.cc SOURCES += rsserver/p3face-config.cc \ rsserver/p3face-server.cc \ diff --git a/src/friend_server/socketbio.cc b/src/pqi/pqifdbin.cc similarity index 91% rename from src/friend_server/socketbio.cc rename to src/pqi/pqifdbin.cc index 9caa45d56..68798bf3d 100644 --- a/src/friend_server/socketbio.cc +++ b/src/pqi/pqifdbin.cc @@ -21,10 +21,10 @@ ******************************************************************************/ #include "util/rsprint.h" -#include "fsbio.h" +#include "pqi/pqifdbin.h" -FsBioInterface::FsBioInterface(int socket) - : mCLintConnt(socket),mIsActive(socket!=0) +RsFdBinInterface::RsFdBinInterface(int file_descriptor) + : mCLintConnt(file_descriptor),mIsActive(file_descriptor!=0) { mTotalReadBytes=0; mTotalInBufferBytes=0; @@ -32,7 +32,7 @@ FsBioInterface::FsBioInterface(int socket) mTotalOutBufferBytes=0; } -void FsBioInterface::setSocket(int s) +void RsFdBinInterface::setSocket(int s) { if(mIsActive != 0) { @@ -42,7 +42,7 @@ void FsBioInterface::setSocket(int s) mCLintConnt = s; mIsActive = (s!=0); } -int FsBioInterface::tick() +int RsFdBinInterface::tick() { if(!mIsActive) { @@ -59,7 +59,7 @@ int FsBioInterface::tick() return res; } -int FsBioInterface::read_pending() +int RsFdBinInterface::read_pending() { char inBuffer[1025]; memset(inBuffer,0,1025); @@ -107,7 +107,7 @@ int FsBioInterface::read_pending() return mTotalInBufferBytes; } -int FsBioInterface::write_pending() +int RsFdBinInterface::write_pending() { if(out_buffer.empty()) return mTotalOutBufferBytes; @@ -160,12 +160,12 @@ int FsBioInterface::write_pending() return mTotalOutBufferBytes; } -FsBioInterface::~FsBioInterface() +RsFdBinInterface::~RsFdBinInterface() { clean(); } -void FsBioInterface::clean() +void RsFdBinInterface::clean() { for(auto p:in_buffer) free(p.first); for(auto p:out_buffer) free(p.first); @@ -173,7 +173,7 @@ void FsBioInterface::clean() in_buffer.clear(); out_buffer.clear(); } -int FsBioInterface::readdata(void *data, int len) +int RsFdBinInterface::readdata(void *data, int len) { // read incoming bytes in the buffer @@ -217,7 +217,7 @@ int FsBioInterface::readdata(void *data, int len) return len; } -int FsBioInterface::senddata(void *data, int len) +int RsFdBinInterface::senddata(void *data, int len) { // shouldn't we better send in multiple packets, similarly to how we read? @@ -240,26 +240,26 @@ int FsBioInterface::senddata(void *data, int len) mTotalOutBufferBytes += len; return len; } -int FsBioInterface::netstatus() +int RsFdBinInterface::netstatus() { return mIsActive; // dummy response. } -int FsBioInterface::isactive() +int RsFdBinInterface::isactive() { return mIsActive ; } -bool FsBioInterface::moretoread(uint32_t /* usec */) +bool RsFdBinInterface::moretoread(uint32_t /* usec */) { return mTotalInBufferBytes > 0; } -bool FsBioInterface::cansend(uint32_t) +bool RsFdBinInterface::cansend(uint32_t) { return isactive(); } -int FsBioInterface::close() +int RsFdBinInterface::close() { RsDbg() << "Stopping network interface" << std::endl; mIsActive = false; diff --git a/src/friend_server/socketbio.h b/src/pqi/pqifdbin.h similarity index 96% rename from src/friend_server/socketbio.h rename to src/pqi/pqifdbin.h index 697719d74..4c532b436 100644 --- a/src/friend_server/socketbio.h +++ b/src/pqi/pqifdbin.h @@ -22,11 +22,11 @@ #include "pqi/pqi_base.h" -class FsBioInterface: public BinInterface +class RsFdBinInterface: public BinInterface { public: - FsBioInterface(int socket); - ~FsBioInterface(); + RsFdBinInterface(int file_descriptor); + ~RsFdBinInterface(); // Implements BinInterface methods diff --git a/src/friend_server/tcpsocket.cc b/src/pqi/rstcpsocket.cc similarity index 72% rename from src/friend_server/tcpsocket.cc rename to src/pqi/rstcpsocket.cc index 19b69d1b2..25f830914 100644 --- a/src/friend_server/tcpsocket.cc +++ b/src/pqi/rstcpsocket.cc @@ -4,13 +4,13 @@ #include #include -#include "tcpsocket.h" +#include "rstcpsocket.h" -TcpSocket::TcpSocket(const std::string& tcp_address,uint16_t tcp_port) - :FsBioInterface(0),mState(DISCONNECTED),mConnectAddress(tcp_address),mConnectPort(tcp_port),mSocket(0) +RsTcpSocket::RsTcpSocket(const std::string& tcp_address,uint16_t tcp_port) + :RsFdBinInterface(0),mState(DISCONNECTED),mConnectAddress(tcp_address),mConnectPort(tcp_port),mSocket(0) { } -int TcpSocket::connect() +int RsTcpSocket::connect() { int CreateSocket = 0; char dataReceived[1024]; @@ -39,19 +39,19 @@ int TcpSocket::connect() return true; } -int TcpSocket::close() +int RsTcpSocket::close() { - FsBioInterface::close(); + RsFdBinInterface::close(); return !::close(mSocket); } -ThreadedTcpSocket::ThreadedTcpSocket(const std::string& tcp_address,uint16_t tcp_port) - : TcpSocket(tcp_address,tcp_port) +RsThreadedTcpSocket::RsThreadedTcpSocket(const std::string& tcp_address,uint16_t tcp_port) + : RsTcpSocket(tcp_address,tcp_port) { } -void ThreadedTcpSocket::run() +void RsThreadedTcpSocket::run() { if(!connect()) { @@ -67,7 +67,7 @@ void ThreadedTcpSocket::run() RsWarn() << "Connection to " << connectAddress() << ":" << connectPort() << " is now closed."; } -ThreadedTcpSocket::~ThreadedTcpSocket() +RsThreadedTcpSocket::~RsThreadedTcpSocket() { fullstop(); // fully wait for stopping. diff --git a/src/friend_server/tcpsocket.h b/src/pqi/rstcpsocket.h similarity index 67% rename from src/friend_server/tcpsocket.h rename to src/pqi/rstcpsocket.h index f35cefb71..bdc127f91 100644 --- a/src/friend_server/tcpsocket.h +++ b/src/pqi/rstcpsocket.h @@ -1,11 +1,11 @@ #include #include "util/rsthreads.h" -#include "friend_server/fsbio.h" +#include "pqi/pqifdbin.h" -class TcpSocket: public FsBioInterface +class RsTcpSocket: public RsFdBinInterface { public: - TcpSocket(const std::string& tcp_address,uint16_t tcp_port); + RsTcpSocket(const std::string& tcp_address,uint16_t tcp_port); enum State: uint8_t { UNKNOWN = 0x00, @@ -30,11 +30,11 @@ private: int mSocket; }; -class ThreadedTcpSocket: public TcpSocket, public RsThread +class RsThreadedTcpSocket: public RsTcpSocket, public RsThread { public: - ThreadedTcpSocket(const std::string& tcp_address,uint16_t tcp_port); - virtual ~ThreadedTcpSocket(); + RsThreadedTcpSocket(const std::string& tcp_address,uint16_t tcp_port); + virtual ~RsThreadedTcpSocket(); virtual void run() override; }; From 933807ee34182506ff4e3decbc405a2b42599711 Mon Sep 17 00:00:00 2001 From: csoler Date: Sun, 2 Jan 2022 20:41:47 +0100 Subject: [PATCH 27/31] made friend server to use tor hidden service to listen to connections --- src/rsserver/rsinit.cc | 6 ++++++ src/tor/TorManager.cpp | 2 ++ 2 files changed, 8 insertions(+) diff --git a/src/rsserver/rsinit.cc b/src/rsserver/rsinit.cc index 6e448fd73..2417cd69e 100644 --- a/src/rsserver/rsinit.cc +++ b/src/rsserver/rsinit.cc @@ -1940,6 +1940,12 @@ int RsServer::StartupRetroShare() std::string RsInit::executablePath() { + if(rsInitConfig->mainExecutablePath.empty()) + { + RsErr() << "Main executable path not set! Plz call RsInit::InitRetroShare(conf) with conf.main_executable_path = argv[0]"; + assert(false); + } + return rsInitConfig->mainExecutablePath; } bool RsInit::startAutoTor() diff --git a/src/tor/TorManager.cpp b/src/tor/TorManager.cpp index 0b0f59cef..7fa275c5a 100644 --- a/src/tor/TorManager.cpp +++ b/src/tor/TorManager.cpp @@ -142,6 +142,8 @@ std::string TorManager::torDataDirectory() const void TorManager::setTorDataDirectory(const std::string &path) { + assert(RsDirUtil::checkCreateDirectory(std::string(path))); + d->dataDir = path; if (!d->dataDir.empty() && !ByteArray(d->dataDir).endsWith('/')) From efe6d5042785df7a7b37fb0b5194f16105d70511 Mon Sep 17 00:00:00 2001 From: csoler Date: Sun, 9 Jan 2022 15:22:47 +0100 Subject: [PATCH 28/31] detached proxy negociation code from pqisslproxy so as to use it in FriendServer as well --- src/friend_server/fsclient.cc | 3 - src/libretroshare.pro | 2 + src/pqi/pqiproxy.cc | 467 ++++++++++++++++++++++++++++++++ src/pqi/pqiproxy.h | 70 +++++ src/pqi/pqisslproxy.cc | 496 +--------------------------------- src/pqi/pqisslproxy.h | 40 +-- 6 files changed, 564 insertions(+), 514 deletions(-) create mode 100644 src/pqi/pqiproxy.cc create mode 100644 src/pqi/pqiproxy.h diff --git a/src/friend_server/fsclient.cc b/src/friend_server/fsclient.cc index ccdd9a019..1da758250 100644 --- a/src/friend_server/fsclient.cc +++ b/src/friend_server/fsclient.cc @@ -127,9 +127,6 @@ bool FsClient::sendItem(const std::string& address,uint16_t port,RsItem *item,st RsSerialiser *rss = new RsSerialiser(); // deleted by ~pqistreamer() rss->addSerialType(fss); -// FsSerializer().serialise(item,data,&size); -// write(CreateSocket,data,size); // shouldn't we use the pqistreamer in R/W mode instead? - RsFdBinInterface *bio = new RsFdBinInterface(CreateSocket,true); // deleted by ~pqistreamer() pqithreadstreamer p(this,rss,RsPeerId(),bio,BIN_FLAGS_READABLE | BIN_FLAGS_WRITEABLE | BIN_FLAGS_NO_CLOSE); diff --git a/src/libretroshare.pro b/src/libretroshare.pro index bc4e6beb5..49c16227f 100644 --- a/src/libretroshare.pro +++ b/src/libretroshare.pro @@ -399,6 +399,7 @@ HEADERS += pqi/authssl.h \ pqi/pqissl.h \ pqi/pqissllistener.h \ pqi/pqisslpersongrp.h \ + pqi/pqiproxy.h \ pqi/pqisslproxy.h \ pqi/pqistore.h \ pqi/pqistreamer.h \ @@ -571,6 +572,7 @@ SOURCES += pqi/authgpg.cc \ pqi/pqissl.cc \ pqi/pqissllistener.cc \ pqi/pqisslpersongrp.cc \ + pqi/pqiproxy.cc \ pqi/pqisslproxy.cc \ pqi/pqistore.cc \ pqi/pqistreamer.cc \ diff --git a/src/pqi/pqiproxy.cc b/src/pqi/pqiproxy.cc new file mode 100644 index 000000000..2f18cc1a3 --- /dev/null +++ b/src/pqi/pqiproxy.cc @@ -0,0 +1,467 @@ +#include "util/rsdebug.h" +#include "util/rsnet.h" + +#include "pqi/pqiproxy.h" + +//#define PROXY_DEBUG 1 + +int pqiproxyconnection::proxy_negotiate_connection(int sockfd) +{ + int ret = 0; + switch(mProxyState) + { + case PROXY_STATE_INIT: + ret = Proxy_Send_Method(sockfd); // checks basic conn, sends Method when able. + break; + + case PROXY_STATE_WAITING_METHOD_RESPONSE: + ret = Proxy_Send_Address(sockfd); // waits for Method Response, send Address when able. + break; + + case PROXY_STATE_WAITING_SOCKS_RESPONSE: + ret = Proxy_Connection_Complete(sockfd); // wait for ACK. + break; + + case PROXY_STATE_CONNECTION_COMPLETE: + +#ifdef PROXY_DEBUG + std::cerr << "pqisslproxy::Basic_Connection_Complete() COMPLETED"; + std::cerr << std::endl; +#endif + + return 1; + + case PROXY_STATE_FAILED: + +#ifdef PROXY_DEBUG + std::cerr << "pqisslproxy::Basic_Connection_Complete() FAILED"; + std::cerr << std::endl; +#endif + + return -1; + } + + +#ifdef PROXY_DEBUG + std::cerr << "pqisslproxy::Basic_Connection_Complete() IN PROGRESS"; + std::cerr << std::endl; +#endif + + // In Progress. + return 0; +} + + +int pqiproxyconnection::Proxy_Send_Method(int sockfd) +{ + +#ifdef PROXY_DEBUG + std::cerr << "pqisslproxy::Proxy_Send_Method() Basic complete, sending Method"; + std::cerr << std::endl; +#endif + + /* send hello to proxy server */ + char method_hello_data[3] = { 0x05, 0x01, 0x00 }; // [ Ver | nMethods (1) | No Auth Method ] + + int sent = send(sockfd, method_hello_data, 3, 0); + if (sent != 3) + { + +#ifdef PROXY_DEBUG + std::cerr << "pqisslproxy::Proxy_Send_Method() Send Failure"; + std::cerr << std::endl; +#endif + return -1; + } + +#ifdef PROXY_DEBUG + std::cerr << "pqisslproxy::Proxy_Send_Method() Send Method Okay"; + std::cerr << std::endl; +#endif + + mProxyState = PROXY_STATE_WAITING_METHOD_RESPONSE; + + return 1; +} + +int pqiproxyconnection::Proxy_Method_Response(int sockfd) +{ + +#ifdef PROXY_DEBUG + std::cerr << "pqisslproxy::Proxy_Method_Response()"; + std::cerr << std::endl; +#endif + + /* get response from proxy server */ + + char method_response[2]; + + /* + first it was: + + int recvd = recv(sockfd, method_response, 2, MSG_WAITALL); + + this does not work on windows, because the socket is in nonblocking mode + the winsock reference says about the recv function and MSG_WAITALL: + + "Note that if the underlying transport does not support MSG_WAITALL, + or if the socket is in a non-blocking mode, then this call will fail with WSAEOPNOTSUPP." + + now it is a two step process: + + int recvd = recv(sockfd, method_response, 2, MSG_PEEK); // test how many bytes are in the input queue + if (enaugh bytes available){ + recvd = recv(sockfd, method_response, 2, 0); + } + + this does not work on windows: + if ((recvd == -1) && (errno == EAGAIN)) return TRY_AGAIN_LATER; + + instead have to do: + if ((recvd == -1) && (WSAGetLastError() == WSAEWOULDBLOCK)) return TRY_AGAIN_LATER; + */ + + // test how many bytes can be read from the queue + int recvd = recv(sockfd, method_response, 2, MSG_PEEK); + if (recvd != 2) + { +#ifdef WINDOWS_SYS + if ((recvd == -1) && (WSAGetLastError() == WSAEWOULDBLOCK)) + { +#ifdef PROXY_DEBUG + std::cerr << "pqisslproxy::Proxy_Method_Response() waiting for more data (windows)"; + std::cerr << std::endl; +#endif + return 0; + } +#endif + if ((recvd == -1) && (errno == EAGAIN)) + { + +#ifdef PROXY_DEBUG + std::cerr << "pqisslproxy::Proxy_Method_Response() EAGAIN"; + std::cerr << std::endl; +#endif + + return 0; + } + else if (recvd == -1) + { +#ifdef PROXY_DEBUG + std::cerr << "pqisslproxy::Proxy_Method_Response() recv error peek"; + std::cerr << std::endl; +#endif + return -1; + } + else + { +#ifdef PROXY_DEBUG + std::cerr << "pqisslproxy::Proxy_Method_Response() waiting for more data"; + std::cerr << std::endl; +#endif + return 0; + } + } + + // read the bytes + recvd = recv(sockfd, method_response, 2, 0); + if (recvd != 2) + { +#ifdef PROXY_DEBUG + std::cerr << "pqisslproxy::Proxy_Method_Response() recv error"; + std::cerr << std::endl; +#endif + return -1; + } + + // does it make sense? + if (method_response[0] != 0x05) + { + + // Error. +#ifdef PROXY_DEBUG + std::cerr << "pqisslproxy::Proxy_Method_Response() Error response[0] != 0x05. Is: "; + std::cerr << (uint32_t) method_response[0]; + std::cerr << std::endl; +#endif + return -1; + } + + if (method_response[1] != 0x00) + { + +#ifdef PROXY_DEBUG + std::cerr << "pqisslproxy::Proxy_Method_Response() Error response[0] != 0x00. Is: "; + std::cerr << (uint32_t) method_response[1]; + std::cerr << std::endl; +#endif + // Error. + return -1; + } + + +#ifdef PROXY_DEBUG + std::cerr << "pqisslproxy::Proxy_Method_Response() Response Okay"; + std::cerr << std::endl; +#endif + + return 1; +} + +#define MAX_SOCKS_REQUEST_LEN 262 // 4 + 1 + 255 + 2. + +int pqiproxyconnection::Proxy_Send_Address(int sockfd) +{ + +#ifdef PROXY_DEBUG + std::cerr << "pqisslproxy::Proxy_Send_Address() Checking Method Response"; + std::cerr << std::endl; +#endif + + // Check Method Response. + int ret = Proxy_Method_Response(sockfd); + if (ret != 1) + { + return ret; // Method Response not complete. + } + + char socks_request[MAX_SOCKS_REQUEST_LEN] = + { 0x05, // SOCKS VERSION. + 0x01, // CONNECT (Tor doesn't support BIND or UDP). + 0x00, // RESERVED. + 0x03, // ADDRESS TYPE (Domain Name) + 0x00, // Length of Domain name... the rest is variable so can't hard code it! + }; + + /* get the length of the domain name, pack so we can't overflow uint8_t */ + uint8_t len = mDomainAddress.length(); + socks_request[4] = len; + for(int i = 0; i < len; i++) + { + socks_request[5 + i] = mDomainAddress[i]; + } + + /* now add the port, being careful with packing */ + uint16_t net_port = htons(mRemotePort); + socks_request[5 + len] = ((uint8_t *) &net_port)[0]; + socks_request[5 + len + 1] = ((uint8_t *) &net_port)[1]; + + int pkt_len = 5 + len + 2; + +#ifdef PROXY_DEBUG + std::cerr << "pqisslproxy::Proxy_Send_Address() Sending String: "; + for(int i = 0; i < pkt_len; i++) + std::cerr << (uint32_t) socks_request[i]; + std::cerr << std::endl; +#endif + int sent = send(sockfd, socks_request, pkt_len, 0); + if (sent != pkt_len) + { + +#ifdef PROXY_DEBUG + std::cerr << "pqisslproxy::Proxy_Send_Address() Send Error"; + std::cerr << std::endl; +#endif + + return -1; + } + + +#ifdef PROXY_DEBUG + std::cerr << "pqisslproxy::Proxy_Send_Address() Sent Okay"; + std::cerr << std::endl; +#endif + + mProxyState = PROXY_STATE_WAITING_SOCKS_RESPONSE; + return 1; +} + +int pqiproxyconnection::Proxy_Connection_Complete(int sockfd) +{ + /* get response from proxy server */ + /* response is similar format to request - with variable length data */ + + char socks_response[MAX_SOCKS_REQUEST_LEN]; + + // test how many bytes can be read + int recvd = recv(sockfd, socks_response, 5, MSG_PEEK); + if (recvd != 5) + { +#ifdef WINDOWS_SYS + if ((recvd == -1) && (WSAGetLastError() == WSAEWOULDBLOCK)) + { +#ifdef PROXY_DEBUG + std::cerr << "pqisslproxy::Proxy_Connection_Complete() waiting for more data (windows)"; + std::cerr << std::endl; +#endif + return 0; + } +#endif + if ((recvd == -1) && (errno == EAGAIN)) + { +#ifdef PROXY_DEBUG + std::cerr << "pqisslproxy::Proxy_Connection_Complete() EAGAIN"; + std::cerr << std::endl; +#endif + return 0; + } + else if (recvd == -1) + { +#ifdef PROXY_DEBUG + std::cerr << "pqisslproxy::Proxy_Connection_Complete() recv error peek"; + std::cerr << std::endl; +#endif + return -1; + } + else + { +#ifdef PROXY_DEBUG + std::cerr << "pqisslproxy::Proxy_Connection_Complete() waiting for more data"; + std::cerr << std::endl; +#endif + return 0; + } + } + + // read the bytes + recvd = recv(sockfd, socks_response, 5, 0); + if (recvd != 5) + { +#ifdef PROXY_DEBUG + std::cerr << "pqisslproxy::Proxy_Connection_Complete() recv error"; + std::cerr << std::endl; +#endif + return -1; + } + + // error checking. + if (socks_response[0] != 0x05) + { + +#ifdef PROXY_DEBUG + std::cerr << "pqisslproxy::Proxy_Connection_Complete() ERROR socks_response[0] != 0x05. is: "; + std::cerr << (uint32_t) socks_response[0]; + std::cerr << std::endl; +#endif + + // error. + return -1; + } + + if (socks_response[1] != 0x00) + { + +#ifdef PROXY_DEBUG + std::cerr << "pqisslproxy::Proxy_Connection_Complete() ERROR socks_response[1] != 0x00. is: "; + std::cerr << (uint32_t) socks_response[1]; + std::cerr << std::endl; +#endif + + // connection failed. + return -1; + } + + int address_bytes = 0; + switch(socks_response[3]) // Address Type. + { + case 0x01: + // IPv4 4 address bytes. + address_bytes = 4; +#ifdef PROXY_DEBUG + std::cerr << "pqisslproxy::Proxy_Connection_Complete() IPv4 Address Type"; + std::cerr << std::endl; +#endif + break; + case 0x04: + // IPv6 16 address bytes. + address_bytes = 16; +#ifdef PROXY_DEBUG + std::cerr << "pqisslproxy::Proxy_Connection_Complete() IPv6 Address Type"; + std::cerr << std::endl; +#endif + break; + case 0x03: + // Variable address bytes - specified in next byte. + address_bytes = 1 + socks_response[4]; +#ifdef PROXY_DEBUG + std::cerr << "pqisslproxy::Proxy_Connection_Complete() Domain Address Type. len: " << address_bytes; + std::cerr << std::endl; +#endif + break; + default: + // unknown error. +#ifdef PROXY_DEBUG + std::cerr << "pqisslproxy::Proxy_Connection_Complete() ERROR Unknown Address Type"; + std::cerr << std::endl; +#endif + return -1; + break; + } + + + // test how many bytes can be read + recvd = recv(sockfd, &(socks_response[5]), address_bytes + 1, MSG_PEEK); // address_bytes - 1 + 2... + if (recvd != address_bytes + 1) + { +#ifdef WINDOWS_SYS + if((recvd == -1) && (WSAGetLastError() == WSAEWOULDBLOCK)) + { +#ifdef PROXY_DEBUG + std::cerr << "pqisslproxy::Proxy_Connection_Complete() waiting for more data(2) (windows)"; + std::cerr << std::endl; +#endif + return 0; + } +#endif + if ((recvd == -1) && (errno == EAGAIN)) + { +#ifdef PROXY_DEBUG + std::cerr << "pqisslproxy::Proxy_Connection_Complete() ERROR EAGAIN at end."; + std::cerr << std::endl; +#endif + // Waiting - shouldn't happen. + return 0; + } + else if (recvd == -1) + { +#ifdef PROXY_DEBUG + std::cerr << "pqisslproxy::Proxy_Connection_Complete() ERROR recving(2)"; + std::cerr << std::endl; +#endif + return -1; + } + else + { +#ifdef PROXY_DEBUG + std::cerr << "pqisslproxy::Proxy_Connection_Complete() waiting for more data(2)"; + std::cerr << std::endl; +#endif + return 0; + } + } + + // read the bytes + recvd = recv(sockfd, &(socks_response[5]), address_bytes + 1, 0); // address_bytes - 1 + 2... + if (recvd != address_bytes + 1) + { +#ifdef PROXY_DEBUG + std::cerr << "pqisslproxy::Proxy_Connection_Complete() recv error (2)"; + std::cerr << std::endl; +#endif + return -1; + } + +#ifdef PROXY_DEBUG + std::cerr << "pqisslproxy::Proxy_Connection_Complete() Received String: "; + for(int i = 0; i < 4 + address_bytes + 2; i++) + std::cerr << (uint32_t) socks_response[i]; + std::cerr << std::endl; +#endif + + // should print address. + // if we get here - connection is good!. + mProxyState = PROXY_STATE_CONNECTION_COMPLETE; + return 1; + +} + diff --git a/src/pqi/pqiproxy.h b/src/pqi/pqiproxy.h new file mode 100644 index 000000000..121139817 --- /dev/null +++ b/src/pqi/pqiproxy.h @@ -0,0 +1,70 @@ +/******************************************************************************* + * libretroshare/src/pqi: pqiproxy.h * + * * + * libretroshare: retroshare core library * + * * + * Copyright 2004-2013 by Robert Fernie. * + * Copyright 2004-2021 by retroshare team * + * * + * This program is free software: you can redistribute it and/or modify * + * it under the terms of the GNU Lesser General Public License as * + * published by the Free Software Foundation, either version 3 of the * + * License, or (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public License * + * along with this program. If not, see . * + * * + *******************************************************************************/ + +#pragma once + +#include + +class pqiproxyconnection +{ +public: + enum ProxyState: uint8_t { + PROXY_STATE_FAILED = 0x00, + PROXY_STATE_INIT = 0x01, + PROXY_STATE_WAITING_METHOD_RESPONSE = 0x02, + PROXY_STATE_WAITING_SOCKS_RESPONSE = 0x03, + PROXY_STATE_CONNECTION_COMPLETE = 0x04 + }; + + /*! + * \brief proxy_negotiate_connection + * Negotiate the connection with the proxy that is connected with openned socket sockfd. The caller needs to + * connect the socket *before* trying to call proxy_negotiate_connection(). The function must be called as many times as + * necessary until it returns 1 (success) or -1 (error) in which case the socket needs to be closed. + * \return + * -1 : error. The socket must be closed as soon as possible. + * 0 : in progress. The function needs to be called again asap. + * 1 : proxy connection is fully negociated. Client can send data to the socket. + */ + int proxy_negotiate_connection(int sockfd); + + void setRemotePort(uint16_t v) { mRemotePort = v; } + void setRemoteAddress(const std::string& s) { mDomainAddress = s; } + + ProxyState proxyConnectionState() const { return mProxyState ; } + + void proxy_init() { mProxyState = PROXY_STATE_INIT; } +private: + + ProxyState mProxyState; + + std::string mDomainAddress; + uint16_t mRemotePort; + + // These are the internal steps in setting up the Proxy Connection. + int Proxy_Send_Method(int sockfd); + int Proxy_Method_Response(int sockfd); + int Proxy_Send_Address(int sockfd); + int Proxy_Connection_Complete(int sockfd); +}; + diff --git a/src/pqi/pqisslproxy.cc b/src/pqi/pqisslproxy.cc index 1c61bef78..750c366fa 100644 --- a/src/pqi/pqisslproxy.cc +++ b/src/pqi/pqisslproxy.cc @@ -38,12 +38,6 @@ static struct RsLog::logInfo pqisslproxyzoneInfo = {RsLog::Default, "pqisslproxy // #define PROXY_DEBUG 1 // #define PROXY_DEBUG_LOG 1 -#define PROXY_STATE_FAILED 0 -#define PROXY_STATE_INIT 1 -#define PROXY_STATE_WAITING_METHOD_RESPONSE 2 -#define PROXY_STATE_WAITING_SOCKS_RESPONSE 3 -#define PROXY_STATE_CONNECTION_COMPLETE 4 - pqisslproxy::pqisslproxy(pqissllistener *l, PQInterface *parent, p3LinkMgr *lm) :pqissl(l, parent, lm) { @@ -74,7 +68,7 @@ int pqisslproxy::Initiate_Connection() rslog(RSL_DEBUG_BASIC, pqisslproxyzone, "pqisslproxy::Initiate_Connection() Connection to Proxy"); /* init proxy state */ - mProxyState = PROXY_STATE_INIT; + proxy_init(); /* call standard Init_Conn() */ return pqissl::Initiate_Connection(); @@ -98,486 +92,18 @@ int pqisslproxy::Basic_Connection_Complete() return -1; } - int ret = 0; - switch(mProxyState) - { - case PROXY_STATE_INIT: - ret = Proxy_Send_Method(); // checks basic conn, sends Method when able. - break; + int ret; - case PROXY_STATE_WAITING_METHOD_RESPONSE: - ret = Proxy_Send_Address(); // waits for Method Response, send Address when able. - break; + if(proxyConnectionState() == PROXY_STATE_INIT && 1!=(ret=pqissl::Basic_Connection_Complete())) + return ret; // basic connection not complete. - case PROXY_STATE_WAITING_SOCKS_RESPONSE: - ret = Proxy_Connection_Complete(); // wait for ACK. - break; + ret = proxy_negotiate_connection(sockfd); - case PROXY_STATE_CONNECTION_COMPLETE: + if(ret < 0) + reset_locked(); -#ifdef PROXY_DEBUG - std::cerr << "pqisslproxy::Basic_Connection_Complete() COMPLETED"; - std::cerr << std::endl; -#endif - - return 1; - - case PROXY_STATE_FAILED: - -#ifdef PROXY_DEBUG - std::cerr << "pqisslproxy::Basic_Connection_Complete() FAILED"; - std::cerr << std::endl; -#endif - - reset_locked(); - return -1; - } - - if (ret < 0) - { - -#ifdef PROXY_DEBUG - std::cerr << "pqisslproxy::Basic_Connection_Complete() FAILED(2)"; - std::cerr << std::endl; -#endif - reset_locked(); - return -1; // FAILURE. - } - - -#ifdef PROXY_DEBUG - std::cerr << "pqisslproxy::Basic_Connection_Complete() IN PROGRESS"; - std::cerr << std::endl; -#endif - - // In Progress. - return 0; -} - - -int pqisslproxy::Proxy_Send_Method() -{ - -#ifdef PROXY_DEBUG - std::cerr << "pqisslproxy::Proxy_Send_Method() Checking pqissl::Basic_Connection_Complete()"; - std::cerr << std::endl; -#endif - - int ret = pqissl::Basic_Connection_Complete(); - if (ret != 1) - { - return ret; // basic connection not complete. - } - -#ifdef PROXY_DEBUG - std::cerr << "pqisslproxy::Proxy_Send_Method() Basic complete, sending Method"; - std::cerr << std::endl; -#endif - - /* send hello to proxy server */ - char method_hello_data[3] = { 0x05, 0x01, 0x00 }; // [ Ver | nMethods (1) | No Auth Method ] - - int sent = send(sockfd, method_hello_data, 3, 0); - if (sent != 3) - { - -#ifdef PROXY_DEBUG - std::cerr << "pqisslproxy::Proxy_Send_Method() Send Failure"; - std::cerr << std::endl; -#endif - return -1; - } - -#ifdef PROXY_DEBUG - std::cerr << "pqisslproxy::Proxy_Send_Method() Send Method Okay"; - std::cerr << std::endl; -#endif - - mProxyState = PROXY_STATE_WAITING_METHOD_RESPONSE; - - return 1; -} - -int pqisslproxy::Proxy_Method_Response() -{ - -#ifdef PROXY_DEBUG - std::cerr << "pqisslproxy::Proxy_Method_Response()"; - std::cerr << std::endl; -#endif - - /* get response from proxy server */ - - char method_response[2]; - - /* - first it was: - - int recvd = recv(sockfd, method_response, 2, MSG_WAITALL); - - this does not work on windows, because the socket is in nonblocking mode - the winsock reference says about the recv function and MSG_WAITALL: - - "Note that if the underlying transport does not support MSG_WAITALL, - or if the socket is in a non-blocking mode, then this call will fail with WSAEOPNOTSUPP." - - now it is a two step process: - - int recvd = recv(sockfd, method_response, 2, MSG_PEEK); // test how many bytes are in the input queue - if (enaugh bytes available){ - recvd = recv(sockfd, method_response, 2, 0); - } - - this does not work on windows: - if ((recvd == -1) && (errno == EAGAIN)) return TRY_AGAIN_LATER; - - instead have to do: - if ((recvd == -1) && (WSAGetLastError() == WSAEWOULDBLOCK)) return TRY_AGAIN_LATER; - */ - - // test how many bytes can be read from the queue - int recvd = recv(sockfd, method_response, 2, MSG_PEEK); - if (recvd != 2) - { -#ifdef WINDOWS_SYS - if ((recvd == -1) && (WSAGetLastError() == WSAEWOULDBLOCK)) - { -#ifdef PROXY_DEBUG - std::cerr << "pqisslproxy::Proxy_Method_Response() waiting for more data (windows)"; - std::cerr << std::endl; -#endif - return 0; - } -#endif - if ((recvd == -1) && (errno == EAGAIN)) - { - -#ifdef PROXY_DEBUG - std::cerr << "pqisslproxy::Proxy_Method_Response() EAGAIN"; - std::cerr << std::endl; -#endif - - return 0; - } - else if (recvd == -1) - { -#ifdef PROXY_DEBUG - std::cerr << "pqisslproxy::Proxy_Method_Response() recv error peek"; - std::cerr << std::endl; -#endif - return -1; - } - else - { -#ifdef PROXY_DEBUG - std::cerr << "pqisslproxy::Proxy_Method_Response() waiting for more data"; - std::cerr << std::endl; -#endif - return 0; - } - } - - // read the bytes - recvd = recv(sockfd, method_response, 2, 0); - if (recvd != 2) - { -#ifdef PROXY_DEBUG - std::cerr << "pqisslproxy::Proxy_Method_Response() recv error"; - std::cerr << std::endl; -#endif - return -1; - } - - // does it make sense? - if (method_response[0] != 0x05) - { - - // Error. -#ifdef PROXY_DEBUG - std::cerr << "pqisslproxy::Proxy_Method_Response() Error response[0] != 0x05. Is: "; - std::cerr << (uint32_t) method_response[0]; - std::cerr << std::endl; -#endif - return -1; - } - - if (method_response[1] != 0x00) - { - -#ifdef PROXY_DEBUG - std::cerr << "pqisslproxy::Proxy_Method_Response() Error response[0] != 0x00. Is: "; - std::cerr << (uint32_t) method_response[1]; - std::cerr << std::endl; -#endif - // Error. - return -1; - } - - -#ifdef PROXY_DEBUG - std::cerr << "pqisslproxy::Proxy_Method_Response() Response Okay"; - std::cerr << std::endl; -#endif - - return 1; -} - -#define MAX_SOCKS_REQUEST_LEN 262 // 4 + 1 + 255 + 2. - -int pqisslproxy::Proxy_Send_Address() -{ - -#ifdef PROXY_DEBUG - std::cerr << "pqisslproxy::Proxy_Send_Address() Checking Method Response"; - std::cerr << std::endl; -#endif - - // Check Method Response. - int ret = Proxy_Method_Response(); - if (ret != 1) - { - return ret; // Method Response not complete. - } - - char socks_request[MAX_SOCKS_REQUEST_LEN] = - { 0x05, // SOCKS VERSION. - 0x01, // CONNECT (Tor doesn't support BIND or UDP). - 0x00, // RESERVED. - 0x03, // ADDRESS TYPE (Domain Name) - 0x00, // Length of Domain name... the rest is variable so can't hard code it! - }; - - /* get the length of the domain name, pack so we can't overflow uint8_t */ - uint8_t len = mDomainAddress.length(); - socks_request[4] = len; - for(int i = 0; i < len; i++) - { - socks_request[5 + i] = mDomainAddress[i]; - } - - /* now add the port, being careful with packing */ - uint16_t net_port = htons(mRemotePort); - socks_request[5 + len] = ((uint8_t *) &net_port)[0]; - socks_request[5 + len + 1] = ((uint8_t *) &net_port)[1]; - - int pkt_len = 5 + len + 2; - -#ifdef PROXY_DEBUG - std::cerr << "pqisslproxy::Proxy_Send_Address() Sending String: "; - for(int i = 0; i < pkt_len; i++) - std::cerr << (uint32_t) socks_request[i]; - std::cerr << std::endl; -#endif - int sent = send(sockfd, socks_request, pkt_len, 0); - if (sent != pkt_len) - { - -#ifdef PROXY_DEBUG - std::cerr << "pqisslproxy::Proxy_Send_Address() Send Error"; - std::cerr << std::endl; -#endif - - return -1; - } - - -#ifdef PROXY_DEBUG - std::cerr << "pqisslproxy::Proxy_Send_Address() Sent Okay"; - std::cerr << std::endl; -#endif - - mProxyState = PROXY_STATE_WAITING_SOCKS_RESPONSE; - return 1; -} - -int pqisslproxy::Proxy_Connection_Complete() -{ - /* get response from proxy server */ - /* response is similar format to request - with variable length data */ - - char socks_response[MAX_SOCKS_REQUEST_LEN]; - - // test how many bytes can be read - int recvd = recv(sockfd, socks_response, 5, MSG_PEEK); - if (recvd != 5) - { -#ifdef WINDOWS_SYS - if ((recvd == -1) && (WSAGetLastError() == WSAEWOULDBLOCK)) - { -#ifdef PROXY_DEBUG - std::cerr << "pqisslproxy::Proxy_Connection_Complete() waiting for more data (windows)"; - std::cerr << std::endl; -#endif - return 0; - } -#endif - if ((recvd == -1) && (errno == EAGAIN)) - { -#ifdef PROXY_DEBUG - std::cerr << "pqisslproxy::Proxy_Connection_Complete() EAGAIN"; - std::cerr << std::endl; -#endif - return 0; - } - else if (recvd == -1) - { -#ifdef PROXY_DEBUG - std::cerr << "pqisslproxy::Proxy_Connection_Complete() recv error peek"; - std::cerr << std::endl; -#endif - return -1; - } - else - { -#ifdef PROXY_DEBUG - std::cerr << "pqisslproxy::Proxy_Connection_Complete() waiting for more data"; - std::cerr << std::endl; -#endif - return 0; - } - } - - // read the bytes - recvd = recv(sockfd, socks_response, 5, 0); - if (recvd != 5) - { -#ifdef PROXY_DEBUG - std::cerr << "pqisslproxy::Proxy_Connection_Complete() recv error"; - std::cerr << std::endl; -#endif - return -1; - } - - // error checking. - if (socks_response[0] != 0x05) - { - -#ifdef PROXY_DEBUG - std::cerr << "pqisslproxy::Proxy_Connection_Complete() ERROR socks_response[0] != 0x05. is: "; - std::cerr << (uint32_t) socks_response[0]; - std::cerr << std::endl; -#endif - - // error. - return -1; - } - - if (socks_response[1] != 0x00) - { - -#ifdef PROXY_DEBUG - std::cerr << "pqisslproxy::Proxy_Connection_Complete() ERROR socks_response[1] != 0x00. is: "; - std::cerr << (uint32_t) socks_response[1]; - std::cerr << std::endl; -#endif - - // connection failed. - return -1; - } - - int address_bytes = 0; - switch(socks_response[3]) // Address Type. - { - case 0x01: - // IPv4 4 address bytes. - address_bytes = 4; -#ifdef PROXY_DEBUG - std::cerr << "pqisslproxy::Proxy_Connection_Complete() IPv4 Address Type"; - std::cerr << std::endl; -#endif - break; - case 0x04: - // IPv6 16 address bytes. - address_bytes = 16; -#ifdef PROXY_DEBUG - std::cerr << "pqisslproxy::Proxy_Connection_Complete() IPv6 Address Type"; - std::cerr << std::endl; -#endif - break; - case 0x03: - // Variable address bytes - specified in next byte. - address_bytes = 1 + socks_response[4]; -#ifdef PROXY_DEBUG - std::cerr << "pqisslproxy::Proxy_Connection_Complete() Domain Address Type. len: " << address_bytes; - std::cerr << std::endl; -#endif - break; - default: - // unknown error. -#ifdef PROXY_DEBUG - std::cerr << "pqisslproxy::Proxy_Connection_Complete() ERROR Unknown Address Type"; - std::cerr << std::endl; -#endif - return -1; - break; - } - - - // test how many bytes can be read - recvd = recv(sockfd, &(socks_response[5]), address_bytes + 1, MSG_PEEK); // address_bytes - 1 + 2... - if (recvd != address_bytes + 1) - { -#ifdef WINDOWS_SYS - if((recvd == -1) && (WSAGetLastError() == WSAEWOULDBLOCK)) - { -#ifdef PROXY_DEBUG - std::cerr << "pqisslproxy::Proxy_Connection_Complete() waiting for more data(2) (windows)"; - std::cerr << std::endl; -#endif - return 0; - } -#endif - if ((recvd == -1) && (errno == EAGAIN)) - { -#ifdef PROXY_DEBUG - std::cerr << "pqisslproxy::Proxy_Connection_Complete() ERROR EAGAIN at end."; - std::cerr << std::endl; -#endif - // Waiting - shouldn't happen. - return 0; - } - else if (recvd == -1) - { -#ifdef PROXY_DEBUG - std::cerr << "pqisslproxy::Proxy_Connection_Complete() ERROR recving(2)"; - std::cerr << std::endl; -#endif - return -1; - } - else - { -#ifdef PROXY_DEBUG - std::cerr << "pqisslproxy::Proxy_Connection_Complete() waiting for more data(2)"; - std::cerr << std::endl; -#endif - return 0; - } - } - - // read the bytes - recvd = recv(sockfd, &(socks_response[5]), address_bytes + 1, 0); // address_bytes - 1 + 2... - if (recvd != address_bytes + 1) - { -#ifdef PROXY_DEBUG - std::cerr << "pqisslproxy::Proxy_Connection_Complete() recv error (2)"; - std::cerr << std::endl; -#endif - return -1; - } - -#ifdef PROXY_DEBUG - std::cerr << "pqisslproxy::Proxy_Connection_Complete() Received String: "; - for(int i = 0; i < 4 + address_bytes + 2; i++) - std::cerr << (uint32_t) socks_response[i]; - std::cerr << std::endl; -#endif - - // should print address. - // if we get here - connection is good!. - mProxyState = PROXY_STATE_CONNECTION_COMPLETE; - return 1; - -} + return ret; + } bool pqisslproxy::connect_parameter(uint32_t type, const std::string &value) { @@ -591,7 +117,7 @@ bool pqisslproxy::connect_parameter(uint32_t type, const std::string &value) #ifdef PROXY_DEBUG_LOG rslog(RSL_WARNING, pqisslproxyzone, out); #endif - mDomainAddress = value; + setRemoteAddress(value); #ifdef PROXY_DEBUG std::cerr << out << std::endl; #endif @@ -614,7 +140,7 @@ bool pqisslproxy::connect_parameter(uint32_t type, uint32_t value) #ifdef PROXY_DEBUG_LOG rslog(RSL_WARNING, pqisslproxyzone, out); #endif - mRemotePort = value; + setRemotePort(value); #ifdef PROXY_DEBUG std::cerr << out << std::endl; #endif diff --git a/src/pqi/pqisslproxy.h b/src/pqi/pqisslproxy.h index dc34295ad..7071f4dfb 100644 --- a/src/pqi/pqisslproxy.h +++ b/src/pqi/pqisslproxy.h @@ -24,6 +24,7 @@ // operating system specific network header. #include "pqi/pqinetwork.h" +#include "pqi/pqiproxy.h" #include #include @@ -39,40 +40,27 @@ * fns declared here are different -> all others are identical. */ -class pqisslproxy: public pqissl +class pqisslproxy: public pqissl, public pqiproxyconnection { public: - pqisslproxy(pqissllistener *l, PQInterface *parent, p3LinkMgr *lm); -virtual ~pqisslproxy(); + pqisslproxy(pqissllistener *l, PQInterface *parent, p3LinkMgr *lm); + virtual ~pqisslproxy(); - // NetInterface. Is the same. - // BinInterface. Is the same. + // NetInterface. Is the same. + // BinInterface. Is the same. -virtual bool connect_parameter(uint32_t type, const std::string &value); -virtual bool connect_parameter(uint32_t type, uint32_t value); + virtual bool connect_parameter(uint32_t type, const std::string &value); + virtual bool connect_parameter(uint32_t type, uint32_t value); protected: -//Initiate is the same - except it uses the Proxy Address rather than the Peer Address. -// minor tweaks to setup data state. -virtual int Initiate_Connection(); + //Initiate is the same - except it uses the Proxy Address rather than the Peer Address. + // minor tweaks to setup data state. + virtual int Initiate_Connection(); -// The real overloading is done in Basic Connection Complete. -// Instead of just checking for an open socket, we need to communicate with the SOCKS5 proxy. -virtual int Basic_Connection_Complete(); - -// These are the internal steps in setting up the Proxy Connection. -virtual int Proxy_Send_Method(); -virtual int Proxy_Method_Response(); -virtual int Proxy_Send_Address(); -virtual int Proxy_Connection_Complete(); - -private: - - uint32_t mProxyState; - - std::string mDomainAddress; - uint16_t mRemotePort; + // The real overloading is done in Basic Connection Complete. + // Instead of just checking for an open socket, we need to communicate with the SOCKS5 proxy. + virtual int Basic_Connection_Complete(); }; #endif // MRK_PQI_SSL_PROXY_HEADER From e574b54235db95495bf8e975dec9949e76637ab1 Mon Sep 17 00:00:00 2001 From: csoler Date: Sun, 9 Jan 2022 17:06:10 +0100 Subject: [PATCH 29/31] fixed proxy init --- src/pqi/pqiproxy.cc | 20 +++++++++++--------- src/pqi/pqisslproxy.cc | 20 ++++++++++---------- 2 files changed, 21 insertions(+), 19 deletions(-) diff --git a/src/pqi/pqiproxy.cc b/src/pqi/pqiproxy.cc index 2f18cc1a3..1fd8fccec 100644 --- a/src/pqi/pqiproxy.cc +++ b/src/pqi/pqiproxy.cc @@ -20,7 +20,9 @@ int pqiproxyconnection::proxy_negotiate_connection(int sockfd) case PROXY_STATE_WAITING_SOCKS_RESPONSE: ret = Proxy_Connection_Complete(sockfd); // wait for ACK. - break; + + if(ret < 1) + break; case PROXY_STATE_CONNECTION_COMPLETE: @@ -41,6 +43,8 @@ int pqiproxyconnection::proxy_negotiate_connection(int sockfd) return -1; } + if(ret < 0) + return -1; #ifdef PROXY_DEBUG std::cerr << "pqisslproxy::Basic_Connection_Complete() IN PROGRESS"; @@ -225,21 +229,19 @@ int pqiproxyconnection::Proxy_Send_Address(int sockfd) return ret; // Method Response not complete. } - char socks_request[MAX_SOCKS_REQUEST_LEN] = - { 0x05, // SOCKS VERSION. - 0x01, // CONNECT (Tor doesn't support BIND or UDP). - 0x00, // RESERVED. - 0x03, // ADDRESS TYPE (Domain Name) - 0x00, // Length of Domain name... the rest is variable so can't hard code it! + char socks_request[MAX_SOCKS_REQUEST_LEN] = { + 0x05, // SOCKS VERSION. + 0x01, // CONNECT (Tor doesn't support BIND or UDP). + 0x00, // RESERVED. + 0x03, // ADDRESS TYPE (Domain Name) + 0x00, // Length of Domain name... the rest is variable so can't hard code it! }; /* get the length of the domain name, pack so we can't overflow uint8_t */ uint8_t len = mDomainAddress.length(); socks_request[4] = len; for(int i = 0; i < len; i++) - { socks_request[5 + i] = mDomainAddress[i]; - } /* now add the port, being careful with packing */ uint16_t net_port = htons(mRemotePort); diff --git a/src/pqi/pqisslproxy.cc b/src/pqi/pqisslproxy.cc index 750c366fa..3c22b04c5 100644 --- a/src/pqi/pqisslproxy.cc +++ b/src/pqi/pqisslproxy.cc @@ -78,19 +78,19 @@ int pqisslproxy::Initiate_Connection() /********* VERY DIFFERENT **********/ int pqisslproxy::Basic_Connection_Complete() { - rslog(RSL_DEBUG_BASIC, pqisslproxyzone, - "pqisslproxy::Basic_Connection_Complete()..."); + rslog(RSL_DEBUG_BASIC, pqisslproxyzone, + "pqisslproxy::Basic_Connection_Complete()..."); #ifdef PROXY_DEBUG - std::cerr << "pqisslproxy::Basic_Connection_Complete() STATE: " << mProxyState; - std::cerr << std::endl; + std::cerr << "pqisslproxy::Basic_Connection_Complete() STATE: " << mProxyState; + std::cerr << std::endl; #endif - if (CheckConnectionTimeout()) - { - // calls reset. - return -1; - } + if (CheckConnectionTimeout()) + { + // calls reset. + return -1; + } int ret; @@ -103,7 +103,7 @@ int pqisslproxy::Basic_Connection_Complete() reset_locked(); return ret; - } +} bool pqisslproxy::connect_parameter(uint32_t type, const std::string &value) { From 89dd126b156d0b7b4c0398abfb4534f41a1c15f9 Mon Sep 17 00:00:00 2001 From: csoler Date: Sun, 9 Jan 2022 17:46:51 +0100 Subject: [PATCH 30/31] fixed FriendServer client to use Tor proxy --- src/friend_server/fsclient.cc | 44 +++++++++++++++++++++------------ src/friend_server/fsclient.h | 9 +++++-- src/friend_server/fsmanager.cc | 19 +++++++++++--- src/friend_server/fsmanager.h | 3 +++ src/pqi/pqiproxy.cc | 2 +- src/pqi/pqiproxy.h | 4 ++- src/pqi/pqisslproxy.cc | 2 +- src/retroshare/rsfriendserver.h | 1 + 8 files changed, 59 insertions(+), 25 deletions(-) diff --git a/src/friend_server/fsclient.cc b/src/friend_server/fsclient.cc index 1da758250..4104b0e6a 100644 --- a/src/friend_server/fsclient.cc +++ b/src/friend_server/fsclient.cc @@ -25,8 +25,11 @@ #include "fsclient.h" #include "pqi/pqifdbin.h" +#include "pqi/pqiproxy.h" -bool FsClient::requestFriends(const std::string& address,uint16_t port,uint32_t reqs,std::map& friend_certificates) +bool FsClient::requestFriends(const std::string& address,uint16_t port, + const std::string& proxy_address,uint16_t proxy_port, + uint32_t reqs,std::map& friend_certificates) { // send our own certificate to publish and expects response frmo the server , decrypts it and reutnrs friend list @@ -47,7 +50,7 @@ bool FsClient::requestFriends(const std::string& address,uint16_t port,uint32_t pitem->short_invite = short_invite; std::list response; - sendItem(address,port,pitem,response); + sendItem(address,port,proxy_address,proxy_port,pitem,response); // now decode the response @@ -84,11 +87,13 @@ void FsClient::handleServerResponse(RsFriendServerServerResponseItem *item) // friend_certificates.insert(it); } -bool FsClient::sendItem(const std::string& address,uint16_t port,RsItem *item,std::list& response) +bool FsClient::sendItem(const std::string& server_address,uint16_t server_port, + const std::string& proxy_address,uint16_t proxy_port, + RsItem *item,std::list& response) { // open a connection - RsDbg() << "Sending item to friend server at \"" << address << ":" << port ; + RsDbg() << "Sending item to friend server at \"" << server_address << ":" << server_port << " through proxy " << proxy_address << ":" << proxy_port; int CreateSocket = 0; char dataReceived[1024]; @@ -103,26 +108,33 @@ bool FsClient::sendItem(const std::string& address,uint16_t port,RsItem *item,st } ipOfServer.sin_family = AF_INET; - ipOfServer.sin_port = htons(port); - ipOfServer.sin_addr.s_addr = inet_addr(address.c_str()); + ipOfServer.sin_port = htons(proxy_port); + ipOfServer.sin_addr.s_addr = inet_addr(proxy_address.c_str()); if(connect(CreateSocket, (struct sockaddr *)&ipOfServer, sizeof(ipOfServer))<0) { - printf("Connection failed due to port and ip problems, or server is not available\n"); + printf("Connection to proxy failed due to port and ip problems, or proxy is not available\n"); return false; } + // Now connect to the proxy + + int ret=0; + pqiproxyconnection proxy; + proxy.setRemoteAddress(server_address); + proxy.setRemotePort(server_port); + + while(1 != (ret = proxy.proxy_negociate_connection(CreateSocket))) + if(ret < 0) + { + RsErr() << "FriendServer client: Connection problem to the proxy!" ; + return false; + } + else + std::this_thread::sleep_for(std::chrono::milliseconds(200)); + // Serialise the item and send it. - uint32_t size = RsSerialiser::MAX_SERIAL_SIZE; - RsTemporaryMemory data(size); - - if(!data) - { - RsErr() << "Cannot allocate memory to send item!" << std::endl; - return false; - } - FsSerializer *fss = new FsSerializer; RsSerialiser *rss = new RsSerialiser(); // deleted by ~pqistreamer() rss->addSerialType(fss); diff --git a/src/friend_server/fsclient.h b/src/friend_server/fsclient.h index 4c17c142d..b682a8bc4 100644 --- a/src/friend_server/fsclient.h +++ b/src/friend_server/fsclient.h @@ -31,7 +31,9 @@ class FsClient: public PQInterface public: FsClient() :PQInterface(RsPeerId()) {} - bool requestFriends(const std::string& address,uint16_t port,uint32_t reqs,std::map& friend_certificates); + bool requestFriends(const std::string& address, uint16_t port, + const std::string &proxy_address, uint16_t proxy_port, + uint32_t reqs, std::map& friend_certificates); protected: // Implements PQInterface @@ -41,7 +43,10 @@ protected: RsItem *GetItem() override; private: - bool sendItem(const std::string &address, uint16_t port, RsItem *item, std::list &response); + bool sendItem(const std::string &server_address, uint16_t server_port, + const std::string &proxy_address, uint16_t proxy_port, + RsItem *item, std::list &response); + void handleServerResponse(RsFriendServerServerResponseItem *item); std::list mIncomingItems; diff --git a/src/friend_server/fsmanager.cc b/src/friend_server/fsmanager.cc index 199bb99d7..ff6571ef7 100644 --- a/src/friend_server/fsmanager.cc +++ b/src/friend_server/fsmanager.cc @@ -8,15 +8,17 @@ static const rstime_t MIN_DELAY_BETWEEN_FS_REQUESTS = 30; static const rstime_t MAX_DELAY_BETWEEN_FS_REQUESTS = 3600; static const uint32_t DEFAULT_FRIENDS_TO_REQUEST = 10; -static const std::string DEFAULT_FRIEND_SERVER_ADDRESS = "127.0.0.1"; +static const std::string DEFAULT_PROXY_ADDRESS = "127.0.0.1"; static const uint16_t DEFAULT_FRIEND_SERVER_PORT = 2017; +static const uint16_t DEFAULT_PROXY_PORT = 9050; FriendServerManager::FriendServerManager() { mLastFriendReqestCampain = 0; mFriendsToRequest = DEFAULT_FRIENDS_TO_REQUEST; - mServerAddress = DEFAULT_FRIEND_SERVER_ADDRESS; + mProxyAddress = DEFAULT_PROXY_ADDRESS; + mProxyPort = DEFAULT_PROXY_PORT; mServerPort = DEFAULT_FRIEND_SERVER_PORT; } void FriendServerManager::startServer() @@ -48,7 +50,11 @@ void FriendServerManager::setServerAddress(const std::string& addr,uint16_t port mServerAddress = addr; mServerPort = port; } - +void FriendServerManager::setProxyAddress(const std::string& addr,uint16_t port) +{ + mProxyAddress = addr; + mProxyPort = port; +} void FriendServerManager::setFriendsToRequest(uint32_t n) { mFriendsToRequest = n; @@ -59,6 +65,11 @@ void FriendServerManager::threadTick() std::cerr << "Ticking FriendServerManager..." << std::endl; std::this_thread::sleep_for(std::chrono::seconds(2)); + if(mServerAddress.empty()) + { + RsErr() << "No friend server address has been setup. This is probably a bug."; + return; + } // Check for requests. Compute how much to wait based on how many friends we have already std::vector friends; @@ -101,7 +112,7 @@ void FriendServerManager::threadTick() std::cerr << "Requesting new friends to friend server..." << std::endl; std::map friend_certificates; - FsClient().requestFriends(mServerAddress,mServerPort,mFriendsToRequest,friend_certificates); // blocking call + FsClient().requestFriends(mServerAddress,mServerPort,mProxyAddress,mProxyPort,mFriendsToRequest,friend_certificates); // blocking call std::cerr << "Got the following list of friend certificates:" << std::endl; diff --git a/src/friend_server/fsmanager.h b/src/friend_server/fsmanager.h index ef5887afa..583a5febc 100644 --- a/src/friend_server/fsmanager.h +++ b/src/friend_server/fsmanager.h @@ -28,6 +28,7 @@ public: virtual void checkServerAddress_async(const std::string& addr,uint16_t, const std::function& callback) override ; virtual void setServerAddress(const std::string&,uint16_t) override ; + virtual void setProxyAddress(const std::string&,uint16_t) override ; virtual void setFriendsToRequest(uint32_t) override ; virtual uint32_t friendsToRequest() override { return mFriendsToRequest ; } @@ -45,4 +46,6 @@ private: std::map mPeers; std::string mServerAddress ; uint16_t mServerPort; + std::string mProxyAddress ; + uint16_t mProxyPort; }; diff --git a/src/pqi/pqiproxy.cc b/src/pqi/pqiproxy.cc index 1fd8fccec..008466847 100644 --- a/src/pqi/pqiproxy.cc +++ b/src/pqi/pqiproxy.cc @@ -5,7 +5,7 @@ //#define PROXY_DEBUG 1 -int pqiproxyconnection::proxy_negotiate_connection(int sockfd) +int pqiproxyconnection::proxy_negociate_connection(int sockfd) { int ret = 0; switch(mProxyState) diff --git a/src/pqi/pqiproxy.h b/src/pqi/pqiproxy.h index 121139817..6862342bb 100644 --- a/src/pqi/pqiproxy.h +++ b/src/pqi/pqiproxy.h @@ -36,6 +36,8 @@ public: PROXY_STATE_CONNECTION_COMPLETE = 0x04 }; + pqiproxyconnection() : mProxyState(PROXY_STATE_INIT) {} + /*! * \brief proxy_negotiate_connection * Negotiate the connection with the proxy that is connected with openned socket sockfd. The caller needs to @@ -46,7 +48,7 @@ public: * 0 : in progress. The function needs to be called again asap. * 1 : proxy connection is fully negociated. Client can send data to the socket. */ - int proxy_negotiate_connection(int sockfd); + int proxy_negociate_connection(int sockfd); void setRemotePort(uint16_t v) { mRemotePort = v; } void setRemoteAddress(const std::string& s) { mDomainAddress = s; } diff --git a/src/pqi/pqisslproxy.cc b/src/pqi/pqisslproxy.cc index 3c22b04c5..8ae2b162d 100644 --- a/src/pqi/pqisslproxy.cc +++ b/src/pqi/pqisslproxy.cc @@ -97,7 +97,7 @@ int pqisslproxy::Basic_Connection_Complete() if(proxyConnectionState() == PROXY_STATE_INIT && 1!=(ret=pqissl::Basic_Connection_Complete())) return ret; // basic connection not complete. - ret = proxy_negotiate_connection(sockfd); + ret = proxy_negociate_connection(sockfd); if(ret < 0) reset_locked(); diff --git a/src/retroshare/rsfriendserver.h b/src/retroshare/rsfriendserver.h index df9951cee..80bf2a029 100644 --- a/src/retroshare/rsfriendserver.h +++ b/src/retroshare/rsfriendserver.h @@ -28,6 +28,7 @@ public: virtual void checkServerAddress_async(const std::string& addr,uint16_t, const std::function& callback) =0; virtual void setServerAddress(const std::string&,uint16_t) =0; + virtual void setProxyAddress(const std::string&,uint16_t) =0; virtual void setFriendsToRequest(uint32_t) =0; virtual uint32_t friendsToRequest() =0; From 432164ea4c25cfdb9f6bc4e095b50510ce12955b Mon Sep 17 00:00:00 2001 From: csoler Date: Mon, 10 Jan 2022 17:48:33 +0100 Subject: [PATCH 31/31] added ifdef and option to enable/disable embeded friend server --- src/libretroshare.pro | 24 ++++++++++++++++-------- src/rsserver/rsinit.cc | 5 +++++ 2 files changed, 21 insertions(+), 8 deletions(-) diff --git a/src/libretroshare.pro b/src/libretroshare.pro index 49c16227f..585c9af67 100644 --- a/src/libretroshare.pro +++ b/src/libretroshare.pro @@ -147,7 +147,6 @@ PUBLIC_HEADERS = retroshare/rsdisc.h \ retroshare/rsrtt.h \ retroshare/rsconfig.h \ retroshare/rsversion.h \ - retroshare/rsfriendserver.h \ retroshare/rsservicecontrol.h \ retroshare/rsgxsdistsync.h @@ -409,10 +408,6 @@ HEADERS += pqi/authssl.h \ pqi/pqinetstatebox.h \ pqi/p3servicecontrol.h -SOURCES += friend_server/fsclient.h \ - friend_server/fsitem.h \ - friend_server/fsmanager.h - HEADERS += rsserver/p3face.h \ rsserver/p3history.h \ rsserver/p3msgs.h \ @@ -582,9 +577,6 @@ SOURCES += pqi/authgpg.cc \ pqi/pqinetstatebox.cc \ pqi/p3servicecontrol.cc -SOURCES += friend_server/fsclient.cc \ - friend_server/fsmanager.cc - SOURCES += rsserver/p3face-config.cc \ rsserver/p3face-server.cc \ rsserver/p3face-info.cc \ @@ -842,6 +834,22 @@ wikipoos { rsitems/rswikiitems.cc \ } +# Friend server + +rs_efs { + DEFINES *= RS_EMBEDED_FRIEND_SERVER + + HEADERS += friend_server/fsclient.h \ + friend_server/fsitem.h \ + friend_server/fsmanager.h \ + retroshare/rsfriendserver.h + + SOURCES += friend_server/fsclient.cc \ + friend_server/fsmanager.cc +} + +# The Wire + gxsthewire { DEFINES *= RS_USE_WIRE diff --git a/src/rsserver/rsinit.cc b/src/rsserver/rsinit.cc index 2417cd69e..5729b552c 100644 --- a/src/rsserver/rsinit.cc +++ b/src/rsserver/rsinit.cc @@ -51,7 +51,10 @@ #include "retroshare/rsversion.h" #include "rsserver/rsloginhandler.h" #include "rsserver/rsaccounts.h" + +#ifdef RS_EMBEDED_FRIEND_SERVER #include "friend_server/fsmanager.h" +#endif #include #include @@ -1176,8 +1179,10 @@ int RsServer::StartupRetroShare() serviceCtrl->setServiceServer(pqih) ; +#ifdef RS_EMBEDED_FRIEND_SERVER // setup friend server rsFriendServer = new FriendServerManager(); +#endif /****** New Ft Server **** !!! */ ftServer *ftserver = new ftServer(mPeerMgr, serviceCtrl);