mirror of
https://github.com/RetroShare/RetroShare.git
synced 2024-10-01 02:35:48 -04:00
c7adb4907c
git-svn-id: http://svn.code.sf.net/p/retroshare/code/trunk@937 b45a01b8-16f6-495d-af2f-9b41ad6348cc
822 lines
19 KiB
C++
822 lines
19 KiB
C++
/*
|
|
* libretroshare/src/dht: opendht.cc
|
|
*
|
|
* Interface with OpenDHT for RetroShare.
|
|
*
|
|
* Copyright 2007-2008 by Robert Fernie.
|
|
*
|
|
* This library is free software; you can redistribute it and/or
|
|
* modify it under the terms of the GNU Library General Public
|
|
* License Version 2 as published by the Free Software Foundation.
|
|
*
|
|
* This library 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
|
|
* Library General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU Library General Public
|
|
* License along with this library; if not, write to the Free Software
|
|
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
|
|
* USA.
|
|
*
|
|
* Please report all bugs and problems to "retroshare@lunamutt.com".
|
|
*
|
|
*/
|
|
|
|
#include "dht/opendht.h"
|
|
#include "dht/opendhtstr.h"
|
|
#include "dht/b64.h"
|
|
#include <fstream>
|
|
#include <sstream>
|
|
|
|
#include <sys/time.h>
|
|
#include <time.h>
|
|
#include "util/rsnet.h"
|
|
#include "util/rsprint.h"
|
|
|
|
const std::string openDHT_Client = "Retroshare V0.4";
|
|
const std::string openDHT_Agent = "RS-HTTP-V0.4";
|
|
|
|
#define MAX_DHT_PEER_FAILS 2 /* then discard */
|
|
#define MAX_DHT_TOTAL_FAILS 10 /* in a row -> think we're not connected! */
|
|
#define MAX_DHT_ATTEMPTS 10 /* attempts per search/publish */
|
|
#define MIN_DHT_SERVERS 5
|
|
|
|
/****
|
|
* #define OPENDHT_DEBUG 1
|
|
****/
|
|
|
|
bool OpenDHTClient::checkServerFile(std::string filename)
|
|
{
|
|
#ifdef OPENDHT_DEBUG
|
|
std::cerr << "OpenDHTClient::checkServerFile(" << filename << ")" << std::endl;
|
|
#endif
|
|
|
|
/* open the file */
|
|
std::ifstream file(filename.c_str());
|
|
|
|
if (file.fail())
|
|
{
|
|
#ifdef OPENDHT_DEBUG
|
|
std::cerr << "OpenDHTClient::checkServerFile() Open Failed" << std::endl;
|
|
#endif
|
|
return false;
|
|
}
|
|
|
|
/* get the first line */
|
|
std::string line;
|
|
getline(file, line);
|
|
char day[16], month[16];
|
|
int date;
|
|
char day2[16], month2[16];
|
|
int date2;
|
|
|
|
if (3 != sscanf(line.c_str(), "%15s %15s %d", day, month, &date))
|
|
{
|
|
#ifdef OPENDHT_DEBUG
|
|
std::cerr << "OpenDHTClient::checkServerFile() failed file TS parse";
|
|
std::cerr << std::endl;
|
|
#endif
|
|
return false;
|
|
}
|
|
|
|
#ifdef OPENDHT_DEBUG
|
|
std::cerr << "OpenDHTClient::checkServerFile() file TS month: ";
|
|
std::cerr << month << " date: " << date << std::endl;
|
|
#endif
|
|
|
|
/* store current timestamp */
|
|
struct tm result;
|
|
time_t now = time(NULL);
|
|
char nowstr[1023];
|
|
|
|
asctime_r(gmtime_r(&now, &result), nowstr);
|
|
|
|
if (3 != sscanf(nowstr, "%15s %15s %d", day2, month2, &date2))
|
|
{
|
|
#ifdef OPENDHT_DEBUG
|
|
std::cerr << "OpenDHTClient::checkServerFile() failed now TS parse";
|
|
std::cerr << std::endl;
|
|
#endif
|
|
return false;
|
|
}
|
|
|
|
#ifdef OPENDHT_DEBUG
|
|
std::cerr << "OpenDHTClient::checkServerFile() current TS month: ";
|
|
std::cerr << month2 << " date: " << date2 << std::endl;
|
|
#endif
|
|
|
|
/* if month is different */
|
|
if (0 != strcmp(month, month2))
|
|
{
|
|
#ifdef OPENDHT_DEBUG
|
|
std::cerr << "OpenDHTClient::checkServerFile() different MONTHS fail";
|
|
std::cerr << std::endl;
|
|
#endif
|
|
return false;
|
|
}
|
|
|
|
/* if month is different */
|
|
int delta = abs(date-date2);
|
|
if (delta > 2)
|
|
{
|
|
#ifdef OPENDHT_DEBUG
|
|
std::cerr << "OpenDHTClient::checkServerFile() fail - large DATE diff: " << delta;
|
|
std::cerr << std::endl;
|
|
#endif
|
|
return false;
|
|
}
|
|
|
|
#ifdef OPENDHT_DEBUG
|
|
std::cerr << "OpenDHTClient::checkServerFile() file is up-to-date!";
|
|
std::cerr << std::endl;
|
|
#endif
|
|
|
|
return true;
|
|
}
|
|
|
|
|
|
|
|
bool OpenDHTClient::loadServers(std::string filename)
|
|
{
|
|
/* open the file */
|
|
std::ifstream file(filename.c_str());
|
|
|
|
|
|
return loadServers(file);
|
|
}
|
|
|
|
bool OpenDHTClient::loadServers(std::istream &instr)
|
|
{
|
|
|
|
std::string line;
|
|
char number[1024];
|
|
char ipaddr[1024];
|
|
char dnsname[1024];
|
|
|
|
dhtMutex.lock(); /**** LOCK ****/
|
|
mServers.clear();
|
|
dhtMutex.unlock(); /**** UNLOCK ****/
|
|
|
|
/* chew first line */
|
|
instr.ignore(1024, '\n');
|
|
|
|
while((!instr.eof()) && (!instr.fail()))
|
|
{
|
|
line = "";
|
|
getline(instr, line);
|
|
|
|
if (3 == sscanf(line.c_str(), "%1023s %1023s %1023s", number, ipaddr, dnsname))
|
|
{
|
|
dhtServer srv;
|
|
srv.host = dnsname;
|
|
srv.port = 5851;
|
|
srv.failed = 0;
|
|
srv.ts = 0;
|
|
srv.addr.sin_addr.s_addr = 0;
|
|
srv.addr.sin_port = 0;
|
|
|
|
#ifdef OPENDHT_DEBUG
|
|
std::cerr << "Read Server: " << dnsname << std::endl;
|
|
#endif
|
|
|
|
dhtMutex.lock(); /**** LOCK ****/
|
|
mServers[dnsname] = srv;
|
|
dhtMutex.unlock(); /**** UNLOCK ****/
|
|
|
|
}
|
|
else
|
|
{
|
|
|
|
#ifdef OPENDHT_DEBUG
|
|
std::cerr << "Failed to Read Server" << std::endl;
|
|
#endif
|
|
}
|
|
|
|
dhtMutex.lock(); /**** LOCK ****/
|
|
mDHTFailCount = 0;
|
|
dhtMutex.unlock(); /**** UNLOCK ****/
|
|
}
|
|
|
|
dhtMutex.lock(); /**** LOCK ****/
|
|
uint32_t count = mServers.size();
|
|
dhtMutex.unlock(); /**** UNLOCK ****/
|
|
|
|
return (count >= MIN_DHT_SERVERS);
|
|
}
|
|
|
|
/******* refresh Servers from WebPage ******/
|
|
|
|
bool OpenDHTClient::loadServersFromWeb(std::string storename)
|
|
{
|
|
|
|
#ifdef OPENDHT_DEBUG
|
|
std::cerr << "OpenDHTClient::loadServersFromWeb()" << std::endl;
|
|
#endif
|
|
|
|
std::string response;
|
|
if (!openDHT_getDHTList(response))
|
|
{
|
|
#ifdef OPENDHT_DEBUG
|
|
std::cerr << "OpenDHTClient::loadServersFromWeb() Web GET failed" << std::endl;
|
|
#endif
|
|
return false;
|
|
}
|
|
|
|
std::string::size_type i;
|
|
if (std::string::npos == (i = response.find("\r\n\r\n")))
|
|
{
|
|
#ifdef OPENDHT_DEBUG
|
|
std::cerr << "OpenDHTClient::loadServersFromWeb() Failed to Find Content" << std::endl;
|
|
#endif
|
|
return false;
|
|
}
|
|
|
|
/* now step past 4 chars */
|
|
i += 4;
|
|
|
|
std::string content(response, i, response.length() - i);
|
|
|
|
#ifdef OPENDHT_DEBUG
|
|
std::cerr << "OpenDHTClient::loadServersFromWeb() Content:" << std::endl;
|
|
std::cerr << content << std::endl;
|
|
std::cerr << "<== OpenDHTClient::loadServersFromWeb() Content" << std::endl;
|
|
#endif
|
|
|
|
std::istringstream iss(content);
|
|
|
|
if (loadServers(iss))
|
|
{
|
|
#ifdef OPENDHT_DEBUG
|
|
std::cerr << "OpenDHTClient::loadServersFromWeb() Saving WebData to: ";
|
|
std::cerr << storename << std::endl;
|
|
#endif
|
|
/* save the data to file - replacing old data */
|
|
std::ofstream ofstr(storename.c_str());
|
|
ofstr << content;
|
|
ofstr.close();
|
|
|
|
return true;
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
bool OpenDHTClient::getServer(std::string &host, uint16_t &port, struct sockaddr_in &addr)
|
|
{
|
|
/* randomly choose one */
|
|
dhtMutex.lock(); /**** LOCK ****/
|
|
|
|
#ifndef WINDOWS_SYS
|
|
#else
|
|
|
|
/* WINDOWS don't randomise properly so we'll do it ourselves...
|
|
*/
|
|
|
|
uint32_t randomize = timeGetTime();
|
|
srand(randomize);
|
|
#endif
|
|
|
|
uint32_t len = mServers.size();
|
|
uint32_t rnd = len * (rand() / (RAND_MAX + 1.0));
|
|
|
|
if (len < 1)
|
|
{
|
|
#ifdef OPENDHT_DEBUG
|
|
std::cerr << "OpenDHTClient::getServer() No Servers available!" << std::endl;
|
|
#endif
|
|
dhtMutex.unlock(); /**** UNLOCK ****/
|
|
return false;
|
|
}
|
|
|
|
std::map<std::string, dhtServer>::const_iterator it;
|
|
uint32_t i = 0;
|
|
for(it = mServers.begin(); (it != mServers.end()) && (i < rnd); it++, i++);
|
|
|
|
if (it == mServers.end())
|
|
{
|
|
#ifdef OPENDHT_DEBUG
|
|
std::cerr << "OpenDHTClient::getServer() Error getting Server!" << std::endl;
|
|
#endif
|
|
dhtMutex.unlock(); /**** UNLOCK ****/
|
|
return false;
|
|
}
|
|
|
|
host = (it->second).host;
|
|
port = (it->second).port;
|
|
|
|
time_t now = time(NULL);
|
|
|
|
if (now - (it->second).ts < 3600)
|
|
{
|
|
addr = (it->second).addr;
|
|
}
|
|
else
|
|
{
|
|
addr.sin_addr.s_addr = 0;
|
|
}
|
|
|
|
dhtMutex.unlock(); /**** UNLOCK ****/
|
|
|
|
return true;
|
|
}
|
|
|
|
|
|
bool OpenDHTClient::setServerIp(std::string host, struct sockaddr_in addr)
|
|
{
|
|
dhtMutex.lock(); /**** LOCK ****/
|
|
|
|
std::map<std::string, dhtServer>::iterator it;
|
|
it = mServers.find(host);
|
|
if (it == mServers.end())
|
|
{
|
|
dhtMutex.unlock(); /**** UNLOCK ****/
|
|
#ifdef OPENDHT_DEBUG
|
|
std::cerr << "OpenDHTClient::setServerIp() Error finding Server!" << std::endl;
|
|
#endif
|
|
return false;
|
|
}
|
|
|
|
(it -> second).addr = addr;
|
|
(it -> second).ts = time(NULL);
|
|
(it -> second).failed = 0;
|
|
|
|
mDHTFailCount = 0;
|
|
|
|
dhtMutex.unlock(); /**** UNLOCK ****/
|
|
|
|
return true;
|
|
}
|
|
|
|
|
|
void OpenDHTClient::setServerFailed(std::string host)
|
|
{
|
|
dhtMutex.lock(); /**** LOCK ****/
|
|
|
|
std::map<std::string, dhtServer>::iterator it;
|
|
it = mServers.find(host);
|
|
if (it == mServers.end())
|
|
{
|
|
#ifdef OPENDHT_DEBUG
|
|
std::cerr << "OpenDHTClient::setServerFailed() Error finding Server!" << std::endl;
|
|
#endif
|
|
dhtMutex.unlock(); /**** UNLOCK ****/
|
|
return;
|
|
}
|
|
|
|
mDHTFailCount++;
|
|
if (mDHTFailCount > MAX_DHT_TOTAL_FAILS) /* might be not connected to Internet */
|
|
{
|
|
#ifdef OPENDHT_DEBUG
|
|
std::cerr << "OpenDHTClient::setServerFailed() Probably not connected!" << std::endl;
|
|
#endif
|
|
dhtMutex.unlock(); /**** UNLOCK ****/
|
|
return;
|
|
}
|
|
|
|
/* up the fail count on this one */
|
|
(it -> second).failed++;
|
|
|
|
if ((it -> second).failed > MAX_DHT_PEER_FAILS)
|
|
{
|
|
#ifdef OPENDHT_DEBUG
|
|
std::cerr << "OpenDHTClient::setServerFailed() fail count high -> removing: ";
|
|
std::cerr << host << " from list" << std::endl;
|
|
#endif
|
|
/* remove from list */
|
|
mServers.erase(it);
|
|
}
|
|
|
|
dhtMutex.unlock(); /**** UNLOCK ****/
|
|
return;
|
|
}
|
|
|
|
bool OpenDHTClient::dhtActive()
|
|
{
|
|
dhtMutex.lock(); /**** LOCK ****/
|
|
|
|
bool ok = (mDHTFailCount <= MAX_DHT_TOTAL_FAILS) &&
|
|
(mServers.size() > MIN_DHT_SERVERS);
|
|
|
|
dhtMutex.unlock(); /**** UNLOCK ****/
|
|
|
|
return ok;
|
|
}
|
|
|
|
bool OpenDHTClient::publishKey(std::string key, std::string value, uint32_t ttl)
|
|
{
|
|
/* create request */
|
|
#ifdef OPENDHT_DEBUG
|
|
std::cerr << "OpenDHTClient::openDHT_publishKey() key: 0x" << RsUtil::BinToHex(key) << " value: 0x" << RsUtil::BinToHex(value);
|
|
std::cerr << std::endl;
|
|
#endif
|
|
std::string putmsg = createOpenDHT_put(key, value, ttl, openDHT_Client);
|
|
std::string response;
|
|
|
|
for(uint16_t i = 0; (!openDHT_sendMessage(putmsg, response)); i++)
|
|
{
|
|
if (i > MAX_DHT_ATTEMPTS)
|
|
{
|
|
#ifdef OPENDHT_DEBUG
|
|
std::cerr << "OpenDHTClient::openDHT_publishKey() Failed -> Giving Up";
|
|
std::cerr << std::endl;
|
|
#endif
|
|
return false;
|
|
}
|
|
|
|
#ifdef OPENDHT_DEBUG
|
|
std::cerr << "OpenDHTClient::openDHT_publishKey() Failed -> reattempting";
|
|
std::cerr << std::endl;
|
|
#endif
|
|
}
|
|
|
|
/* check response */
|
|
return true;
|
|
}
|
|
|
|
|
|
bool OpenDHTClient::searchKey(std::string key, std::list<std::string> &values)
|
|
{
|
|
#ifdef OPENDHT_DEBUG
|
|
std::cerr << "OpenDHTClient::openDHT_searchKey() key: 0x" << RsUtil::BinToHex(key);
|
|
std::cerr << std::endl;
|
|
#endif
|
|
|
|
/* create request */
|
|
std::string getmsg = createOpenDHT_get(key, 1024, openDHT_Client);
|
|
std::string response;
|
|
|
|
for(uint16_t i = 0; (!openDHT_sendMessage(getmsg, response)); i++)
|
|
{
|
|
if (i > MAX_DHT_ATTEMPTS)
|
|
{
|
|
#ifdef OPENDHT_DEBUG
|
|
std::cerr << "OpenDHTClient::openDHT_searchKey() Failed -> Giving Up";
|
|
std::cerr << std::endl;
|
|
#endif
|
|
return false;
|
|
}
|
|
#ifdef OPENDHT_DEBUG
|
|
std::cerr << "OpenDHTClient::openDHT_searchKey() Failed -> reattempting";
|
|
std::cerr << std::endl;
|
|
#endif
|
|
}
|
|
|
|
#ifdef OPENDHT_DEBUG
|
|
std::cerr << "Parsing expression :$$$$$$$$$-" << response << "-$$$$$$$$" << std::endl ;
|
|
#endif
|
|
|
|
/* search through the response for <base64> ... </base64> */
|
|
|
|
std::string::size_type start = 0;
|
|
std::string::size_type loc = 0;
|
|
std::string::size_type end = 0;
|
|
|
|
while(1)
|
|
{
|
|
loc = response.find("<base64>", start);
|
|
if (loc == std::string::npos)
|
|
return true; /* finished */
|
|
#ifdef OPENDHT_DEBUG
|
|
std::cerr << "found loc=" << loc << std::endl ;
|
|
#endif
|
|
loc += 8; /* shift to end of <base64> */
|
|
|
|
end = response.find("</base64>", loc);
|
|
if (end == std::string::npos)
|
|
return true; /* finished */
|
|
#ifdef OPENDHT_DEBUG
|
|
std::cerr << "found end=" << end << std::endl ;
|
|
#endif
|
|
|
|
std::string value = response.substr(loc, end-loc);
|
|
#ifdef OPENDHT_DEBUG
|
|
std::cerr << "found value=" << value << std::endl ;
|
|
#endif
|
|
|
|
/* clear out whitespace */
|
|
for(std::string::size_type i = 0; i < value.length();)
|
|
{
|
|
if (isspace(value[i]))
|
|
{
|
|
value.erase(i,1);
|
|
#ifdef OPENDHT_DEBUG
|
|
std::cerr << "Cleanup Result:" << value << ":END:" << std::endl;
|
|
#endif
|
|
}
|
|
else
|
|
{
|
|
i++;
|
|
}
|
|
}
|
|
|
|
if (value.length() > 0)
|
|
{
|
|
std::string result = convertFromBase64(value);
|
|
values.push_back(result);
|
|
#ifdef OPENDHT_DEBUG
|
|
std::cerr << "openDHT_searchKey() Value:" << value << ":END:" << std::endl;
|
|
std::cerr << "openDHT_searchKey() Result: 0x" << RsUtil::BinToHex(result) << ":END:" << std::endl;
|
|
#endif
|
|
}
|
|
|
|
/* the answer should be between loc and end */
|
|
start = end + 9;
|
|
}
|
|
|
|
/* parse response */
|
|
return true;
|
|
}
|
|
|
|
|
|
bool OpenDHTClient::openDHT_sendMessage(std::string msg, std::string &response)
|
|
{
|
|
struct sockaddr_in addr;
|
|
std::string host;
|
|
uint16_t port;
|
|
|
|
if (!getServer(host, port, addr))
|
|
{
|
|
#ifdef OPENDHT_DEBUG
|
|
std::cerr << "OpenDHTClient::openDHT_sendMessage() Failed to get Server";
|
|
std::cerr << std::endl;
|
|
#endif
|
|
return false;
|
|
}
|
|
|
|
if (addr.sin_addr.s_addr == 0)
|
|
{
|
|
/* lookup the address */
|
|
addr.sin_port = htons(port);
|
|
if (LookupDNSAddr(host, addr) &&
|
|
(addr.sin_addr.s_addr != 0))
|
|
{
|
|
/* update the IP addr if necessary */
|
|
setServerIp(host, addr);
|
|
}
|
|
else
|
|
{
|
|
/* no address */
|
|
#ifdef OPENDHT_DEBUG
|
|
std::cerr << "OpenDHTClient::openDHT_sendMessage()";
|
|
std::cerr << " ERROR: No Address";
|
|
std::cerr << std::endl;
|
|
#endif
|
|
setServerFailed(host);
|
|
|
|
return false;
|
|
}
|
|
}
|
|
|
|
#ifdef OPENDHT_DEBUG
|
|
std::cerr << "OpenDHTClient::openDHT_sendMessage()";
|
|
std::cerr << " Connecting to:" << host << ":" << port;
|
|
std::cerr << " (" << inet_ntoa(addr.sin_addr) << ":" << ntohs(addr.sin_port) << ")";
|
|
std::cerr << std::endl;
|
|
#endif
|
|
|
|
/* create request */
|
|
std::string putheader = createHttpHeader(host, port, openDHT_Agent, msg.length());
|
|
|
|
/* open a socket */
|
|
int sockfd = unix_socket(PF_INET, SOCK_STREAM, 0);
|
|
|
|
/* connect */
|
|
int err = unix_connect(sockfd, (struct sockaddr *) &addr, sizeof(addr));
|
|
if (err)
|
|
{
|
|
unix_close(sockfd);
|
|
#ifdef OPENDHT_DEBUG
|
|
std::cerr << "OpenDHTClient::openDHT_sendMessage()";
|
|
std::cerr << " ERROR: Failed to Connect";
|
|
std::cerr << std::endl;
|
|
#endif
|
|
|
|
setServerFailed(host);
|
|
|
|
return false;
|
|
}
|
|
|
|
#ifdef OPENDHT_DEBUG
|
|
std::cerr << "HTTP message *******************" << std::endl;
|
|
std::cerr << putheader;
|
|
std::cerr << msg;
|
|
std::cerr << std::endl;
|
|
std::cerr << "HTTP message *******************" << std::endl;
|
|
#endif
|
|
|
|
/* send data */
|
|
int sendsize = strlen(putheader.c_str());
|
|
int size = send(sockfd, putheader.c_str(), sendsize, 0);
|
|
if (sendsize != size)
|
|
{
|
|
unix_close(sockfd);
|
|
#ifdef OPENDHT_DEBUG
|
|
std::cerr << "OpenDHTClient::openDHT_sendMessage()";
|
|
std::cerr << " ERROR: Failed to Send(1)";
|
|
std::cerr << std::endl;
|
|
#endif
|
|
|
|
setServerFailed(host);
|
|
|
|
return false;
|
|
}
|
|
#ifdef OPENDHT_DEBUG
|
|
std::cerr << "OpenDHTClient::openDHT_sendMessage()";
|
|
std::cerr << " Send(1):" << size;
|
|
std::cerr << std::endl;
|
|
#endif
|
|
|
|
sendsize = strlen(msg.c_str());
|
|
size = send(sockfd, msg.c_str(), sendsize, 0);
|
|
if (sendsize != size)
|
|
{
|
|
unix_close(sockfd);
|
|
#ifdef OPENDHT_DEBUG
|
|
std::cerr << "OpenDHTClient::openDHT_sendMessage()";
|
|
std::cerr << " ERROR: Failed to Send(2)";
|
|
std::cerr << std::endl;
|
|
#endif
|
|
|
|
setServerFailed(host);
|
|
|
|
return false;
|
|
}
|
|
|
|
#ifdef OPENDHT_DEBUG
|
|
std::cerr << "OpenDHTClient::openDHT_sendMessage()";
|
|
std::cerr << " Send(2):" << size;
|
|
std::cerr << std::endl;
|
|
#endif
|
|
|
|
/* now wait for the response */
|
|
/********************************** WINDOWS/UNIX SPECIFIC PART ******************/
|
|
#ifndef WINDOWS_SYS
|
|
sleep(1);
|
|
#else
|
|
Sleep(1000);
|
|
#endif
|
|
/********************************** WINDOWS/UNIX SPECIFIC PART ******************/
|
|
|
|
int recvsize = 51200; /* 50kb */
|
|
char *inbuf = (char *) malloc(recvsize);
|
|
uint32_t idx = 0;
|
|
while(0 < (size = recv(sockfd, &(inbuf[idx]), recvsize - idx, 0)))
|
|
{
|
|
#ifdef OPENDHT_DEBUG
|
|
std::cerr << "OpenDHTClient::openDHT_sendMessage()";
|
|
std::cerr << " Recvd Chunk:" << size;
|
|
std::cerr << std::endl;
|
|
#endif
|
|
idx += size;
|
|
}
|
|
|
|
#ifdef OPENDHT_DEBUG
|
|
std::cerr << "OpenDHTClient::openDHT_sendMessage()";
|
|
std::cerr << " Recvd Msg:" << idx;
|
|
#endif
|
|
|
|
response = std::string(inbuf, idx);
|
|
free(inbuf);
|
|
|
|
/* print it out */
|
|
#ifdef OPENDHT_DEBUG
|
|
std::cerr << "HTTP What We Sent ***************" << std::endl;
|
|
std::cerr << putheader;
|
|
std::cerr << msg;
|
|
std::cerr << std::endl;
|
|
std::cerr << "HTTP response *******************" << std::endl;
|
|
std::cerr << response;
|
|
std::cerr << std::endl;
|
|
std::cerr << "HTTP response *******************" << std::endl;
|
|
#endif
|
|
|
|
unix_close(sockfd);
|
|
|
|
return true;
|
|
}
|
|
|
|
bool OpenDHTClient::openDHT_getDHTList(std::string &response)
|
|
{
|
|
struct sockaddr_in addr;
|
|
std::string host = "www.opendht.org";
|
|
uint16_t port = 80;
|
|
|
|
sockaddr_clear(&addr);
|
|
|
|
/* lookup the address */
|
|
addr.sin_family = AF_INET;
|
|
addr.sin_port = htons(port);
|
|
if (!LookupDNSAddr(host, addr))
|
|
{
|
|
/* no address */
|
|
#ifdef OPENDHT_DEBUG
|
|
std::cerr << "OpenDHTClient::openDHT_getDHTList()";
|
|
std::cerr << " ERROR: No Address";
|
|
std::cerr << std::endl;
|
|
#endif
|
|
|
|
return false;
|
|
}
|
|
|
|
#ifdef OPENDHT_DEBUG
|
|
std::cerr << "OpenDHTClient::openDHT_getDHTList()";
|
|
std::cerr << " Connecting to:" << host << ":" << port;
|
|
std::cerr << " (" << inet_ntoa(addr.sin_addr) << ":" << ntohs(addr.sin_port) << ")";
|
|
std::cerr << std::endl;
|
|
#endif
|
|
|
|
/* create request */
|
|
std::string putheader = createHttpHeaderGET(host, port, "servers.txt", openDHT_Agent, 0);
|
|
|
|
/* open a socket */
|
|
int sockfd = unix_socket(PF_INET, SOCK_STREAM, 0);
|
|
|
|
/* connect */
|
|
int err = unix_connect(sockfd, (struct sockaddr *) &addr, sizeof(addr));
|
|
if (err)
|
|
{
|
|
unix_close(sockfd);
|
|
#ifdef OPENDHT_DEBUG
|
|
std::cerr << "OpenDHTClient::openDHT_getDHTList()";
|
|
std::cerr << " ERROR: Failed to Connect";
|
|
std::cerr << std::endl;
|
|
#endif
|
|
|
|
return false;
|
|
}
|
|
|
|
#ifdef OPENDHT_DEBUG
|
|
std::cerr << "HTTP message *******************" << std::endl;
|
|
std::cerr << putheader;
|
|
std::cerr << std::endl;
|
|
std::cerr << "HTTP message *******************" << std::endl;
|
|
#endif
|
|
|
|
/* send data */
|
|
int sendsize = strlen(putheader.c_str());
|
|
int size = send(sockfd, putheader.c_str(), sendsize, 0);
|
|
if (sendsize != size)
|
|
{
|
|
unix_close(sockfd);
|
|
#ifdef OPENDHT_DEBUG
|
|
std::cerr << "OpenDHTClient::openDHT_getDHTList()";
|
|
std::cerr << " ERROR: Failed to Send(1)";
|
|
std::cerr << std::endl;
|
|
#endif
|
|
|
|
return false;
|
|
}
|
|
#ifdef OPENDHT_DEBUG
|
|
std::cerr << "OpenDHTClient::openDHT_getDHTList()";
|
|
std::cerr << " Send(1):" << size;
|
|
std::cerr << std::endl;
|
|
#endif
|
|
|
|
/* now wait for the response */
|
|
/********************************** WINDOWS/UNIX SPECIFIC PART ******************/
|
|
#ifndef WINDOWS_SYS
|
|
sleep(1);
|
|
#else
|
|
Sleep(1000);
|
|
#endif
|
|
/********************************** WINDOWS/UNIX SPECIFIC PART ******************/
|
|
|
|
int recvsize = 51200; /* 50kb */
|
|
char *inbuf = (char *) malloc(recvsize);
|
|
uint32_t idx = 0;
|
|
while(0 < (size = recv(sockfd, &(inbuf[idx]), recvsize - idx, 0)))
|
|
{
|
|
#ifdef OPENDHT_DEBUG
|
|
std::cerr << "OpenDHTClient::openDHT_getDHTList()";
|
|
std::cerr << " Recvd Chunk:" << size;
|
|
std::cerr << std::endl;
|
|
#endif
|
|
idx += size;
|
|
}
|
|
|
|
#ifdef OPENDHT_DEBUG
|
|
std::cerr << "OpenDHTClient::openDHT_getDHTList()";
|
|
std::cerr << " Recvd Msg:" << idx;
|
|
#endif
|
|
|
|
response = std::string(inbuf, idx);
|
|
free(inbuf);
|
|
|
|
/* print it out */
|
|
#ifdef OPENDHT_DEBUG
|
|
std::cerr << "HTTP response *******************" << std::endl;
|
|
std::cerr << response;
|
|
std::cerr << std::endl;
|
|
std::cerr << "HTTP response *******************" << std::endl;
|
|
#endif
|
|
|
|
unix_close(sockfd);
|
|
|
|
return true;
|
|
}
|
|
|
|
|