mirror of
https://github.com/RetroShare/RetroShare.git
synced 2025-08-17 02:21:03 -04:00
Merge pull request #2495 from csoler/v0.6-FriendServer
V0.6 friend server
This commit is contained in:
commit
b847caa11b
41 changed files with 3009 additions and 688 deletions
|
@ -54,7 +54,12 @@ namespace librs
|
|||
|
||||
return Sha1CheckSum(h);
|
||||
}
|
||||
|
||||
template<>
|
||||
HashStream& operator<<(HashStream& u,const std::pair<unsigned char *,uint32_t>& p)
|
||||
{
|
||||
EVP_DigestUpdate(u.mdctx,p.first,p.second) ;
|
||||
return u;
|
||||
}
|
||||
template<>
|
||||
HashStream& operator<<(HashStream& u,const std::string& s)
|
||||
{
|
||||
|
|
202
libretroshare/src/friend_server/fsclient.cc
Normal file
202
libretroshare/src/friend_server/fsclient.cc
Normal file
|
@ -0,0 +1,202 @@
|
|||
/*******************************************************************************
|
||||
* libretroshare/src/file_sharing: fsclient.cc *
|
||||
* *
|
||||
* libretroshare: retroshare core library *
|
||||
* *
|
||||
* Copyright 2021 by retroshare team <retroshare.project@gmail.com> *
|
||||
* *
|
||||
* This program is free software: you can redistribute it and/or modify *
|
||||
* it under the terms of the GNU Lesser General Public License as *
|
||||
* published by the Free Software Foundation, either version 3 of the *
|
||||
* License, or (at your option) any later version. *
|
||||
* *
|
||||
* This program is distributed in the hope that it will be useful, *
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
||||
* GNU Lesser General Public License for more details. *
|
||||
* *
|
||||
* You should have received a copy of the GNU Lesser General Public License *
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>. *
|
||||
* *
|
||||
******************************************************************************/
|
||||
|
||||
#include "pqi/pqithreadstreamer.h"
|
||||
#include "retroshare/rspeers.h"
|
||||
|
||||
#include "fsclient.h"
|
||||
#include "pqi/pqifdbin.h"
|
||||
#include "pqi/pqiproxy.h"
|
||||
|
||||
bool FsClient::requestFriends(const std::string& address,uint16_t port,
|
||||
const std::string& proxy_address,uint16_t proxy_port,
|
||||
uint32_t reqs,std::map<std::string,bool>& 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;
|
||||
|
||||
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<RsItem*> response;
|
||||
sendItem(address,port,proxy_address,proxy_port,pitem,response);
|
||||
|
||||
// now decode the response
|
||||
|
||||
friend_certificates.clear();
|
||||
|
||||
for(auto item:response)
|
||||
{
|
||||
// auto *encrypted_response_item = dynamic_cast<RsFriendServerEncryptedServerResponseItem*>(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<RsFriendServerServerResponseItem*>(item);
|
||||
|
||||
if(response_item)
|
||||
handleServerResponse(response_item);
|
||||
|
||||
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& server_address,uint16_t server_port,
|
||||
const std::string& proxy_address,uint16_t proxy_port,
|
||||
RsItem *item,std::list<RsItem*>& response)
|
||||
{
|
||||
// open a connection
|
||||
|
||||
RsDbg() << "Sending item to friend server at \"" << server_address << ":" << server_port << " through proxy " << proxy_address << ":" << proxy_port;
|
||||
|
||||
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 1;
|
||||
}
|
||||
|
||||
ipOfServer.sin_family = AF_INET;
|
||||
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 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.
|
||||
|
||||
FsSerializer *fss = new FsSerializer;
|
||||
RsSerialiser *rss = new RsSerialiser(); // deleted by ~pqistreamer()
|
||||
rss->addSerialType(fss);
|
||||
|
||||
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);
|
||||
p.start();
|
||||
|
||||
uint32_t ss;
|
||||
p.SendItem(item,ss);
|
||||
|
||||
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)
|
||||
{
|
||||
p.tick(); // ticks bio
|
||||
|
||||
RsItem *item = GetItem();
|
||||
#ifdef DEBUG_FSCLIENT
|
||||
RsDbg() << "Ticking for response...";
|
||||
#endif
|
||||
if(item)
|
||||
{
|
||||
response.push_back(item);
|
||||
std::cerr << "Got a response item: " << std::endl;
|
||||
std::cerr << *item << std::endl;
|
||||
|
||||
RsDbg() << "End of transmission. " ;
|
||||
break;
|
||||
}
|
||||
else
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(200));
|
||||
}
|
||||
|
||||
RsDbg() << " Stopping/killing pqistreamer" ;
|
||||
p.fullstop();
|
||||
|
||||
RsDbg() << " Closing socket." ;
|
||||
close(CreateSocket);
|
||||
CreateSocket=0;
|
||||
|
||||
RsDbg() << " Exiting loop." ;
|
||||
|
||||
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;
|
||||
}
|
54
libretroshare/src/friend_server/fsclient.h
Normal file
54
libretroshare/src/friend_server/fsclient.h
Normal file
|
@ -0,0 +1,54 @@
|
|||
/*******************************************************************************
|
||||
* libretroshare/src/file_sharing: fsclient.h *
|
||||
* *
|
||||
* libretroshare: retroshare core library *
|
||||
* *
|
||||
* Copyright 2021 by retroshare team <retroshare.project@gmail.com> *
|
||||
* *
|
||||
* This program is free software: you can redistribute it and/or modify *
|
||||
* it under the terms of the GNU Lesser General Public License as *
|
||||
* published by the Free Software Foundation, either version 3 of the *
|
||||
* License, or (at your option) any later version. *
|
||||
* *
|
||||
* This program is distributed in the hope that it will be useful, *
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
||||
* GNU Lesser General Public License for more details. *
|
||||
* *
|
||||
* You should have received a copy of the GNU Lesser General Public License *
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>. *
|
||||
* *
|
||||
******************************************************************************/
|
||||
|
||||
#include <string>
|
||||
#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: public PQInterface
|
||||
{
|
||||
public:
|
||||
FsClient() :PQInterface(RsPeerId()) {}
|
||||
|
||||
bool requestFriends(const std::string& address, uint16_t port,
|
||||
const std::string &proxy_address, uint16_t proxy_port,
|
||||
uint32_t reqs, std::map<std::string,bool>& 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 &server_address, uint16_t server_port,
|
||||
const std::string &proxy_address, uint16_t proxy_port,
|
||||
RsItem *item, std::list<RsItem *> &response);
|
||||
|
||||
void handleServerResponse(RsFriendServerServerResponseItem *item);
|
||||
|
||||
std::list<RsItem*> mIncomingItems;
|
||||
};
|
||||
|
185
libretroshare/src/friend_server/fsitem.h
Normal file
185
libretroshare/src/friend_server/fsitem.h
Normal file
|
@ -0,0 +1,185 @@
|
|||
/*******************************************************************************
|
||||
* libretroshare/src/file_sharing: fsitem.h *
|
||||
* *
|
||||
* libretroshare: retroshare core library *
|
||||
* *
|
||||
* Copyright 2021 by retroshare team <retroshare.project@gmail.com> *
|
||||
* *
|
||||
* This program is free software: you can redistribute it and/or modify *
|
||||
* it under the terms of the GNU Lesser General Public License as *
|
||||
* published by the Free Software Foundation, either version 3 of the *
|
||||
* License, or (at your option) any later version. *
|
||||
* *
|
||||
* This program is distributed in the hope that it will be useful, *
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
||||
* GNU Lesser General Public License for more details. *
|
||||
* *
|
||||
* You should have received a copy of the GNU Lesser General Public License *
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>. *
|
||||
* *
|
||||
******************************************************************************/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "serialiser/rsserial.h"
|
||||
#include "serialiser/rsserializer.h"
|
||||
|
||||
#include "rsitems/rsitem.h"
|
||||
#include "serialiser/rstlvbinary.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 ;
|
||||
const uint8_t RS_PKT_SUBTYPE_FS_SERVER_STATUS = 0x05 ;
|
||||
|
||||
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(short_invite);
|
||||
RS_SERIAL_PROCESS(pgp_public_key_b64);
|
||||
}
|
||||
virtual void clear() override
|
||||
{
|
||||
pgp_public_key_b64.clear();
|
||||
short_invite.clear();
|
||||
n_requested_friends=0;
|
||||
}
|
||||
|
||||
// specific members for that item
|
||||
|
||||
uint32_t n_requested_friends;
|
||||
std::string short_invite;
|
||||
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:
|
||||
RsFriendServerClientRemoveItem() : RsFriendServerItem(RS_PKT_SUBTYPE_FS_CLIENT_REMOVE) {}
|
||||
|
||||
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:
|
||||
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(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<std::string,bool> 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<uint16_t>(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_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" ;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
}
|
||||
};
|
123
libretroshare/src/friend_server/fsmanager.cc
Normal file
123
libretroshare/src/friend_server/fsmanager.cc
Normal file
|
@ -0,0 +1,123 @@
|
|||
#include <cmath>
|
||||
#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_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;
|
||||
|
||||
mProxyAddress = DEFAULT_PROXY_ADDRESS;
|
||||
mProxyPort = DEFAULT_PROXY_PORT;
|
||||
mServerPort = DEFAULT_FRIEND_SERVER_PORT;
|
||||
}
|
||||
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<void (const std::string& address,bool result_status)>& 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::setProxyAddress(const std::string& addr,uint16_t port)
|
||||
{
|
||||
mProxyAddress = addr;
|
||||
mProxyPort = 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));
|
||||
|
||||
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<RsPgpId> 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)
|
||||
{
|
||||
mLastFriendReqestCampain = now;
|
||||
|
||||
std::cerr << "Requesting new friends to friend server..." << std::endl;
|
||||
|
||||
std::map<std::string,bool> friend_certificates;
|
||||
FsClient().requestFriends(mServerAddress,mServerPort,mProxyAddress,mProxyPort,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;
|
||||
}
|
||||
}
|
||||
|
51
libretroshare/src/friend_server/fsmanager.h
Normal file
51
libretroshare/src/friend_server/fsmanager.h
Normal file
|
@ -0,0 +1,51 @@
|
|||
#include <map>
|
||||
|
||||
#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 ;
|
||||
rstime_t received_TS;
|
||||
};
|
||||
|
||||
class FriendServerManager: public RsFriendServer, public RsTickingThread
|
||||
{
|
||||
public:
|
||||
FriendServerManager();
|
||||
|
||||
virtual void startServer() override ;
|
||||
virtual void stopServer() override ;
|
||||
|
||||
virtual void checkServerAddress_async(const std::string& addr,uint16_t, const std::function<void (const std::string& address,bool result_status)>& 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 ; }
|
||||
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
|
||||
|
||||
std::map<RsPeerId, FriendServerPeerInfo> mPeers;
|
||||
std::string mServerAddress ;
|
||||
uint16_t mServerPort;
|
||||
std::string mProxyAddress ;
|
||||
uint16_t mProxyPort;
|
||||
};
|
|
@ -391,6 +391,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 \
|
||||
|
@ -559,6 +560,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 \
|
||||
|
@ -825,6 +827,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
|
||||
|
||||
|
|
|
@ -1642,7 +1642,10 @@ bool OpenPGPSDKHandler::locked_syncPublicKeyring()
|
|||
#else
|
||||
if(-1 == stat64(_pubring_path.c_str(), &buf))
|
||||
#endif
|
||||
{
|
||||
RsErr() << "OpenPGPSDKHandler::syncDatabase(): can't stat file " << _pubring_path << ". Can't sync public keyring." ;
|
||||
buf.st_mtime = 0;
|
||||
}
|
||||
|
||||
if(_pubring_last_update_time < buf.st_mtime)
|
||||
{
|
||||
|
|
|
@ -357,12 +357,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
|
||||
{
|
||||
RsErr() << "PGPHandler::syncDatabase(): can't stat file " << _trustdb_path << ". Will force write it." ;
|
||||
_trustdb_changed = true ; // we force write of trust database if it does not exist.
|
||||
}
|
||||
{
|
||||
RsErr() << "PGPHandler::syncDatabase(): can't stat file " << _trustdb_path << ". Will force write it." ;
|
||||
_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)
|
||||
{
|
||||
|
|
|
@ -21,6 +21,7 @@
|
|||
*******************************************************************************/
|
||||
#include <stdint.h>
|
||||
#include <util/radix64.h>
|
||||
#include <crypto/hashstream.h>
|
||||
#include "pgpkeyutil.h"
|
||||
|
||||
#include <iostream>
|
||||
|
@ -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<packet_length;++i)
|
||||
info.user_id += (char)(data[i]);
|
||||
|
||||
return true ;
|
||||
}
|
||||
bool PGPKeyManagement::parseSignature(const unsigned char *signature, size_t sign_len, PGPSignatureInfo& info)
|
||||
{
|
||||
unsigned char *data = (unsigned char *)signature ;
|
||||
|
|
|
@ -81,6 +81,16 @@ public:
|
|||
uint8_t hash_algorithm ;
|
||||
};
|
||||
|
||||
class PGPKeyInfo
|
||||
{
|
||||
public:
|
||||
PGPKeyInfo() {}
|
||||
|
||||
std::string user_id;
|
||||
unsigned char fingerprint[20];
|
||||
};
|
||||
|
||||
|
||||
// This class handles GPG keys. For now we only clean them from signatures, but
|
||||
// in the future, we might cache them to avoid unnecessary calls to gpgme.
|
||||
//
|
||||
|
@ -107,6 +117,8 @@ class PGPKeyManagement
|
|||
static uint32_t compute24bitsCRC(unsigned char *data,size_t len) ;
|
||||
|
||||
static bool parseSignature(const unsigned char *signature, size_t sign_len, PGPSignatureInfo& info) ;
|
||||
|
||||
static bool parsePGPPublicKey(const unsigned char *keydata, size_t keylen, PGPKeyInfo& info);
|
||||
};
|
||||
|
||||
// This class handles the parsing of PGP packet headers under various (old and new) formats.
|
||||
|
@ -126,7 +138,7 @@ class PGPKeyParser
|
|||
static uint64_t read_KeyID(unsigned char *& data) ;
|
||||
static uint32_t read_125Size(unsigned char *& data) ;
|
||||
static uint32_t read_partialBodyLength(unsigned char *& data) ;
|
||||
static void read_packetHeader(unsigned char *& data,uint8_t& packet_tag,uint32_t& packet_length) ;
|
||||
static void read_packetHeader(unsigned char *&data, uint8_t& packet_tag, uint32_t& packet_length) ;
|
||||
|
||||
// These functions write, and indicate how many bytes where written.
|
||||
//
|
||||
|
|
|
@ -28,6 +28,7 @@
|
|||
#include <retroshare/rspeers.h>
|
||||
#include <util/radix64.h>
|
||||
#include <pgp/pgpkeyutil.h>
|
||||
#include <pgp/pgphandler.h>
|
||||
#include "rscertificate.h"
|
||||
#include "util/rsstring.h"
|
||||
#include "util/stacktrace.h"
|
||||
|
@ -619,6 +620,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<uint8_t> 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<size_t>(buf) - reinterpret_cast<size_t>(buf2) );
|
||||
|
||||
if(total_s > size)
|
||||
{
|
||||
err_code = CERTIFICATE_PARSING_ERROR_SIZE_ERROR;
|
||||
return false;
|
||||
}
|
||||
|
||||
Dbg3() << __PRETTY_FUNCTION__ << " Read ptag: "
|
||||
<< static_cast<uint32_t>(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<uint32_t>( 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;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
||||
/**
|
||||
|
|
|
@ -236,6 +236,7 @@ int RsFdBinInterface::readline(void *data, int len)
|
|||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int RsFdBinInterface::readdata(void *data, int len)
|
||||
{
|
||||
// read incoming bytes in the buffer
|
||||
|
|
469
libretroshare/src/pqi/pqiproxy.cc
Normal file
469
libretroshare/src/pqi/pqiproxy.cc
Normal file
|
@ -0,0 +1,469 @@
|
|||
#include "util/rsdebug.h"
|
||||
#include "util/rsnet.h"
|
||||
|
||||
#include "pqi/pqiproxy.h"
|
||||
|
||||
//#define PROXY_DEBUG 1
|
||||
|
||||
int pqiproxyconnection::proxy_negociate_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.
|
||||
|
||||
if(ret < 1)
|
||||
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;
|
||||
}
|
||||
|
||||
if(ret < 0)
|
||||
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;
|
||||
|
||||
}
|
||||
|
72
libretroshare/src/pqi/pqiproxy.h
Normal file
72
libretroshare/src/pqi/pqiproxy.h
Normal file
|
@ -0,0 +1,72 @@
|
|||
/*******************************************************************************
|
||||
* libretroshare/src/pqi: pqiproxy.h *
|
||||
* *
|
||||
* libretroshare: retroshare core library *
|
||||
* *
|
||||
* Copyright 2004-2013 by Robert Fernie. *
|
||||
* Copyright 2004-2021 by retroshare team <retroshare.project@gmail.com> *
|
||||
* *
|
||||
* This program is free software: you can redistribute it and/or modify *
|
||||
* it under the terms of the GNU Lesser General Public License as *
|
||||
* published by the Free Software Foundation, either version 3 of the *
|
||||
* License, or (at your option) any later version. *
|
||||
* *
|
||||
* This program is distributed in the hope that it will be useful, *
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
||||
* GNU Lesser General Public License for more details. *
|
||||
* *
|
||||
* You should have received a copy of the GNU Lesser General Public License *
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>. *
|
||||
* *
|
||||
*******************************************************************************/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <string>
|
||||
|
||||
class pqiproxyconnection
|
||||
{
|
||||
public:
|
||||
enum ProxyState: uint8_t {
|
||||
PROXY_STATE_FAILED = 0x00,
|
||||
PROXY_STATE_INIT = 0x01,
|
||||
PROXY_STATE_WAITING_METHOD_RESPONSE = 0x02,
|
||||
PROXY_STATE_WAITING_SOCKS_RESPONSE = 0x03,
|
||||
PROXY_STATE_CONNECTION_COMPLETE = 0x04
|
||||
};
|
||||
|
||||
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
|
||||
* 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_negociate_connection(int sockfd);
|
||||
|
||||
void setRemotePort(uint16_t v) { mRemotePort = v; }
|
||||
void setRemoteAddress(const std::string& s) { mDomainAddress = s; }
|
||||
|
||||
ProxyState proxyConnectionState() const { return mProxyState ; }
|
||||
|
||||
void proxy_init() { mProxyState = PROXY_STATE_INIT; }
|
||||
private:
|
||||
|
||||
ProxyState mProxyState;
|
||||
|
||||
std::string mDomainAddress;
|
||||
uint16_t mRemotePort;
|
||||
|
||||
// These are the internal steps in setting up the Proxy Connection.
|
||||
int Proxy_Send_Method(int sockfd);
|
||||
int Proxy_Method_Response(int sockfd);
|
||||
int Proxy_Send_Address(int sockfd);
|
||||
int Proxy_Connection_Complete(int sockfd);
|
||||
};
|
||||
|
|
@ -38,12 +38,6 @@ static struct RsLog::logInfo pqisslproxyzoneInfo = {RsLog::Default, "pqisslproxy
|
|||
// #define PROXY_DEBUG 1
|
||||
// #define PROXY_DEBUG_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();
|
||||
|
@ -84,499 +78,31 @@ 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;
|
||||
}
|
||||
|
||||
int ret = 0;
|
||||
switch(mProxyState)
|
||||
{
|
||||
case PROXY_STATE_INIT:
|
||||
ret = Proxy_Send_Method(); // checks basic conn, sends Method when able.
|
||||
break;
|
||||
|
||||
case PROXY_STATE_WAITING_METHOD_RESPONSE:
|
||||
ret = Proxy_Send_Address(); // waits for Method Response, send Address when able.
|
||||
break;
|
||||
|
||||
case PROXY_STATE_WAITING_SOCKS_RESPONSE:
|
||||
ret = Proxy_Connection_Complete(); // 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
|
||||
|
||||
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)
|
||||
if (CheckConnectionTimeout())
|
||||
{
|
||||
#ifdef PROXY_DEBUG
|
||||
std::cerr << "pqisslproxy::Proxy_Method_Response() recv error";
|
||||
std::cerr << std::endl;
|
||||
#endif
|
||||
// calls reset.
|
||||
return -1;
|
||||
}
|
||||
|
||||
// does it make sense?
|
||||
if (method_response[0] != 0x05)
|
||||
{
|
||||
int ret;
|
||||
|
||||
// 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(proxyConnectionState() == PROXY_STATE_INIT && 1!=(ret=pqissl::Basic_Connection_Complete()))
|
||||
return ret; // basic connection not complete.
|
||||
|
||||
if (method_response[1] != 0x00)
|
||||
{
|
||||
ret = proxy_negociate_connection(sockfd);
|
||||
|
||||
#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;
|
||||
if(ret < 0)
|
||||
reset_locked();
|
||||
|
||||
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)
|
|||
rs_sprintf(out, "pqisslproxy::connect_parameter() Peer: %s DOMAIN_ADDRESS: %s", PeerId().toStdString().c_str(), value.c_str());
|
||||
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
|
||||
|
|
|
@ -24,6 +24,7 @@
|
|||
|
||||
// operating system specific network header.
|
||||
#include "pqi/pqinetwork.h"
|
||||
#include "pqi/pqiproxy.h"
|
||||
|
||||
#include <string>
|
||||
#include <map>
|
||||
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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 ;
|
||||
|
@ -683,7 +684,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 +694,7 @@ int pqistreamer::handleoutgoing_locked()
|
|||
mPkt_wpending = NULL;
|
||||
mPkt_wpending_size = 0 ;
|
||||
|
||||
sent = true;
|
||||
sent = true;
|
||||
}
|
||||
}
|
||||
#ifdef DEBUG_PQISTREAMER
|
||||
|
@ -802,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:
|
||||
{
|
||||
|
@ -1430,8 +1434,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
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
39
libretroshare/src/retroshare/rsfriendserver.h
Normal file
39
libretroshare/src/retroshare/rsfriendserver.h
Normal file
|
@ -0,0 +1,39 @@
|
|||
#include <functional>
|
||||
#include <thread>
|
||||
#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:
|
||||
virtual void startServer() =0;
|
||||
virtual void stopServer() =0;
|
||||
|
||||
virtual void checkServerAddress_async(const std::string& addr,uint16_t, const std::function<void (const std::string& address,bool result_status)>& 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;
|
||||
virtual uint16_t friendsServerPort() =0;
|
||||
virtual std::string friendsServerAddress() =0;
|
||||
};
|
||||
|
||||
extern RsFriendServer *rsFriendServer;
|
|
@ -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)
|
||||
|
|
|
@ -54,7 +54,8 @@ enum class RsServiceType : uint16_t
|
|||
|
||||
BANLIST = 0x0101,
|
||||
STATUS = 0x0102,
|
||||
NXS = 0x0200,
|
||||
FRIEND_SERVER = 0x0103,
|
||||
NXS = 0x0200,
|
||||
GXSID = 0x0211,
|
||||
PHOTO = 0x0212,
|
||||
WIKI = 0x0213,
|
||||
|
@ -115,6 +116,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;
|
||||
|
|
|
@ -48,6 +48,7 @@
|
|||
|
||||
#include "pqi/authssl.h"
|
||||
|
||||
typedef RsCertificate::RsShortInviteFieldType RsShortInviteFieldType; // locally in this file to avoid renaming everything.
|
||||
|
||||
RsPeers *rsPeers = NULL;
|
||||
|
||||
|
@ -1162,22 +1163,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.
|
||||
|
@ -1373,136 +1358,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<uint8_t> 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<size_t>(buf) - reinterpret_cast<size_t>(buf2) );
|
||||
|
||||
if(total_s > size)
|
||||
{
|
||||
err_code = CERTIFICATE_PARSING_ERROR_SIZE_ERROR;
|
||||
return false;
|
||||
}
|
||||
|
||||
Dbg3() << __PRETTY_FUNCTION__ << " Read ptag: "
|
||||
<< static_cast<uint32_t>(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<uint32_t>( 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)
|
||||
|
@ -1519,23 +1391,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,
|
||||
|
|
|
@ -52,6 +52,10 @@
|
|||
#include "rsserver/rsloginhandler.h"
|
||||
#include "rsserver/rsaccounts.h"
|
||||
|
||||
#ifdef RS_EMBEDED_FRIEND_SERVER
|
||||
#include "friend_server/fsmanager.h"
|
||||
#endif
|
||||
|
||||
#include <list>
|
||||
#include <string>
|
||||
|
||||
|
@ -1175,6 +1179,11 @@ 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);
|
||||
ftserver->setConfigDirectory(RsAccounts::AccountDirectory());
|
||||
|
@ -1936,6 +1945,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()
|
||||
|
|
|
@ -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('/'))
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue