2009-02-28 13:19:00 -05:00
|
|
|
/*
|
2009-03-12 16:08:02 -04:00
|
|
|
* libretroshare/src/services: p3turtle.cc
|
2009-02-28 13:19:00 -05:00
|
|
|
*
|
|
|
|
* Services for RetroShare.
|
|
|
|
*
|
2009-03-12 16:08:02 -04:00
|
|
|
* Copyright 2009 by Cyril Soler
|
2009-02-28 13:19:00 -05:00
|
|
|
*
|
|
|
|
* 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.
|
|
|
|
*
|
2009-03-12 16:08:02 -04:00
|
|
|
* Please report all bugs and problems to "csoler@users.sourceforge.net".
|
2009-02-28 13:19:00 -05:00
|
|
|
*
|
|
|
|
*/
|
|
|
|
|
2009-03-13 17:14:30 -04:00
|
|
|
#include <stdexcept>
|
2009-02-28 13:19:00 -05:00
|
|
|
|
|
|
|
#include "rsiface/rsiface.h"
|
|
|
|
#include "rsiface/rspeers.h"
|
2009-03-15 18:45:40 -04:00
|
|
|
#include "rsiface/rsfiles.h"
|
2009-02-28 13:19:00 -05:00
|
|
|
|
|
|
|
#include "pqi/p3authmgr.h"
|
|
|
|
#include "pqi/p3connmgr.h"
|
2009-03-13 17:14:30 -04:00
|
|
|
#include "pqi/pqinotify.h"
|
|
|
|
|
2009-03-12 16:08:02 -04:00
|
|
|
#include "p3turtle.h"
|
2009-02-28 13:19:00 -05:00
|
|
|
|
|
|
|
#include <iostream>
|
|
|
|
#include <errno.h>
|
|
|
|
#include <cmath>
|
|
|
|
|
|
|
|
#include <sstream>
|
|
|
|
|
|
|
|
#include "util/rsdebug.h"
|
|
|
|
#include "util/rsprint.h"
|
|
|
|
|
|
|
|
// Operating System specific includes.
|
|
|
|
#include "pqi/pqinetwork.h"
|
|
|
|
|
2009-03-12 17:07:00 -04:00
|
|
|
/* TURTLE FLAGS */
|
2009-02-28 13:19:00 -05:00
|
|
|
|
2009-03-12 16:08:02 -04:00
|
|
|
#define P3TURTLE_DEBUG 1
|
2009-02-28 13:19:00 -05:00
|
|
|
|
2009-03-13 17:14:30 -04:00
|
|
|
p3turtle::p3turtle(p3ConnectMgr *cm) :p3Service(RS_SERVICE_TYPE_TURTLE), mConnMgr(cm)
|
2009-02-28 13:19:00 -05:00
|
|
|
{
|
2009-03-12 16:08:02 -04:00
|
|
|
RsStackMutex stack(mTurtleMtx); /********** STACK LOCKED MTX ******/
|
2009-02-28 13:19:00 -05:00
|
|
|
|
2009-03-15 18:45:40 -04:00
|
|
|
srand48(time(NULL)) ;
|
2009-02-28 13:19:00 -05:00
|
|
|
addSerialType(new RsTurtleSerialiser());
|
|
|
|
}
|
|
|
|
|
|
|
|
int p3turtle::tick()
|
|
|
|
{
|
|
|
|
handleIncoming(); // handle incoming packets
|
2009-03-13 17:14:30 -04:00
|
|
|
// handleOutgoing(); // handle outgoing packets
|
2009-02-28 13:19:00 -05:00
|
|
|
|
2009-03-12 16:08:02 -04:00
|
|
|
// Clean every 10 sec.
|
|
|
|
time_t now = time(NULL) ;
|
|
|
|
|
|
|
|
if(now > 10+_last_clean_time)
|
|
|
|
{
|
2009-03-12 17:07:00 -04:00
|
|
|
autoWash() ; // clean old/unused tunnels and search requests.
|
2009-03-12 16:08:02 -04:00
|
|
|
_last_clean_time = now ;
|
|
|
|
}
|
2009-03-12 17:07:00 -04:00
|
|
|
|
|
|
|
return 0 ;
|
2009-03-12 16:08:02 -04:00
|
|
|
}
|
|
|
|
|
2009-03-12 17:07:00 -04:00
|
|
|
void p3turtle::autoWash()
|
2009-03-12 16:08:02 -04:00
|
|
|
{
|
|
|
|
RsStackMutex stack(mTurtleMtx); /********** STACK LOCKED MTX ******/
|
|
|
|
|
|
|
|
// look for tunnels and stored temportary info that have not been used for a while.
|
|
|
|
}
|
|
|
|
|
2009-03-13 17:14:30 -04:00
|
|
|
uint32_t p3turtle::generateRandomRequestId()
|
|
|
|
{
|
|
|
|
RsStackMutex stack(mTurtleMtx); /********** STACK LOCKED MTX ******/
|
|
|
|
|
|
|
|
return lrand48() ;
|
|
|
|
}
|
|
|
|
|
|
|
|
TurtleRequestId p3turtle::turtleSearch(const std::string& string_to_match)
|
2009-03-12 16:08:02 -04:00
|
|
|
{
|
|
|
|
// generate a new search id.
|
|
|
|
|
2009-03-12 17:07:00 -04:00
|
|
|
TurtleRequestId id = generateRandomRequestId() ;
|
2009-03-12 16:08:02 -04:00
|
|
|
|
2009-03-15 18:45:40 -04:00
|
|
|
// Form a request packet that simulates a request from us.
|
2009-03-12 16:08:02 -04:00
|
|
|
//
|
|
|
|
RsTurtleSearchRequestItem *item = new RsTurtleSearchRequestItem ;
|
|
|
|
|
2009-03-15 18:45:40 -04:00
|
|
|
#ifdef P3TURTLE_DEBUG
|
|
|
|
std::cerr << "performing search. OwnId = " << mConnMgr->getOwnId() << std::endl ;
|
|
|
|
#endif
|
|
|
|
while(mConnMgr->getOwnId() == "")
|
|
|
|
{
|
|
|
|
std::cerr << "... waitting for connect manager to form own id." << std::endl ;
|
|
|
|
sleep(1) ;
|
|
|
|
}
|
|
|
|
|
|
|
|
item->PeerId(mConnMgr->getOwnId()) ;
|
2009-03-12 16:08:02 -04:00
|
|
|
item->match_string = string_to_match ;
|
2009-03-12 17:07:00 -04:00
|
|
|
item->request_id = id ;
|
2009-03-12 16:08:02 -04:00
|
|
|
item->depth = 0 ;
|
|
|
|
|
|
|
|
// send it
|
|
|
|
|
|
|
|
handleSearchRequest(item) ;
|
|
|
|
|
|
|
|
delete item ;
|
2009-03-12 17:07:00 -04:00
|
|
|
|
|
|
|
return id ;
|
2009-02-28 13:19:00 -05:00
|
|
|
}
|
|
|
|
|
2009-03-13 17:14:30 -04:00
|
|
|
void p3turtle::turtleDownload(const std::string& file_hash)
|
|
|
|
{
|
|
|
|
pqiNotify *notify = getPqiNotify();
|
|
|
|
|
|
|
|
if (notify)
|
|
|
|
notify->AddSysMessage(0, RS_SYS_WARNING, std::string("Unimplemented"),std::string("turtle download is not yet implemented. Sorry"));
|
|
|
|
}
|
|
|
|
|
2009-02-28 13:19:00 -05:00
|
|
|
int p3turtle::handleIncoming()
|
|
|
|
{
|
2009-03-12 16:08:02 -04:00
|
|
|
#ifdef P3TURTLE_DEBUG
|
2009-03-15 18:45:40 -04:00
|
|
|
// std::cerr << "p3turtle::handleIncoming()";
|
|
|
|
// std::cerr << std::endl;
|
2009-02-28 13:19:00 -05:00
|
|
|
#endif
|
|
|
|
|
|
|
|
int nhandled = 0;
|
|
|
|
// While messages read
|
|
|
|
//
|
|
|
|
RsItem *item = NULL;
|
|
|
|
|
|
|
|
while(NULL != (item = recvItem()))
|
|
|
|
{
|
|
|
|
nhandled++;
|
|
|
|
|
2009-03-12 17:07:00 -04:00
|
|
|
switch(item->PacketSubType())
|
2009-02-28 13:19:00 -05:00
|
|
|
{
|
2009-03-12 17:07:00 -04:00
|
|
|
case RS_TURTLE_SUBTYPE_SEARCH_REQUEST: handleSearchRequest(dynamic_cast<RsTurtleSearchRequestItem *>(item)) ;
|
2009-02-28 13:19:00 -05:00
|
|
|
break ;
|
|
|
|
|
2009-03-12 17:07:00 -04:00
|
|
|
case RS_TURTLE_SUBTYPE_SEARCH_RESULT : handleSearchResult(dynamic_cast<RsTurtleSearchResultItem *>(item)) ;
|
2009-02-28 13:19:00 -05:00
|
|
|
break ;
|
|
|
|
|
|
|
|
// Here will also come handling of file transfer requests, tunnel digging/closing, etc.
|
|
|
|
default:
|
2009-03-12 17:07:00 -04:00
|
|
|
std::cerr << "p3turtle::handleIncoming: Unknown packet subtype " << item->PacketSubType() << std::endl ;
|
2009-02-28 13:19:00 -05:00
|
|
|
}
|
|
|
|
delete item;
|
|
|
|
}
|
|
|
|
|
|
|
|
return nhandled;
|
|
|
|
}
|
|
|
|
|
2009-03-12 16:08:02 -04:00
|
|
|
void p3turtle::handleSearchRequest(RsTurtleSearchRequestItem *item)
|
2009-02-28 13:19:00 -05:00
|
|
|
{
|
2009-03-13 17:14:30 -04:00
|
|
|
RsStackMutex stack(mTurtleMtx); /********** STACK LOCKED MTX ******/
|
2009-02-28 13:19:00 -05:00
|
|
|
// take a look at the item:
|
|
|
|
// - If the item destimation is
|
|
|
|
|
2009-03-12 16:08:02 -04:00
|
|
|
#ifdef P3TURTLE_DEBUG
|
2009-03-15 18:45:40 -04:00
|
|
|
std::cerr << "Received search request from peer " << item->PeerId() << ": " << std::endl ;
|
2009-03-12 17:07:00 -04:00
|
|
|
item->print(std::cerr,0) ;
|
2009-03-12 16:08:02 -04:00
|
|
|
#endif
|
2009-02-28 13:19:00 -05:00
|
|
|
// If the item contains an already handled search request, give up. This
|
|
|
|
// happens when the same search request gets relayed by different peers
|
|
|
|
//
|
|
|
|
if(requests_origins.find(item->request_id) != requests_origins.end())
|
2009-03-12 16:08:02 -04:00
|
|
|
{
|
|
|
|
#ifdef P3TURTLE_DEBUG
|
|
|
|
std::cerr << " This is a bouncing request. Ignoring and deleting it." << std::endl ;
|
|
|
|
#endif
|
2009-02-28 13:19:00 -05:00
|
|
|
return ;
|
2009-03-12 16:08:02 -04:00
|
|
|
}
|
2009-02-28 13:19:00 -05:00
|
|
|
|
|
|
|
// This is a new request. Let's add it to the request map, and forward it to
|
|
|
|
// open peers.
|
|
|
|
|
2009-03-12 17:07:00 -04:00
|
|
|
requests_origins[item->request_id] = item->PeerId() ;
|
2009-02-28 13:19:00 -05:00
|
|
|
|
2009-03-12 16:08:02 -04:00
|
|
|
// If it's not for us, perform a local search. If something found, forward the search result back.
|
2009-02-28 13:19:00 -05:00
|
|
|
|
2009-03-12 17:07:00 -04:00
|
|
|
if(item->PeerId() != mConnMgr->getOwnId())
|
2009-02-28 13:19:00 -05:00
|
|
|
{
|
2009-03-12 16:08:02 -04:00
|
|
|
#ifdef P3TURTLE_DEBUG
|
|
|
|
std::cerr << " Request not from us. Performing local search" << std::endl ;
|
|
|
|
#endif
|
2009-03-15 18:45:40 -04:00
|
|
|
std::list<TurtleFileInfo> result ;
|
2009-03-12 16:08:02 -04:00
|
|
|
performLocalSearch(item->match_string,result) ;
|
2009-02-28 13:19:00 -05:00
|
|
|
|
2009-03-12 16:08:02 -04:00
|
|
|
if(!result.empty())
|
|
|
|
{
|
|
|
|
// do something
|
2009-02-28 13:19:00 -05:00
|
|
|
|
2009-03-12 16:08:02 -04:00
|
|
|
// forward item back
|
|
|
|
RsTurtleSearchResultItem *res_item = new RsTurtleSearchResultItem ;
|
2009-02-28 13:19:00 -05:00
|
|
|
|
2009-03-12 16:08:02 -04:00
|
|
|
// perhaps we should chop search results items into several items of finite size ?
|
|
|
|
res_item->depth = 0 ;
|
|
|
|
res_item->result = result ;
|
|
|
|
res_item->request_id = item->request_id ;
|
2009-03-12 17:07:00 -04:00
|
|
|
res_item->PeerId(item->PeerId()) ; // send back to the same guy
|
2009-03-12 16:08:02 -04:00
|
|
|
|
|
|
|
#ifdef P3TURTLE_DEBUG
|
2009-03-15 18:45:40 -04:00
|
|
|
std::cerr << " " << result.size() << " matches found. Sending back to origin (" << res_item->PeerId() << ")." << std::endl ;
|
2009-03-12 16:08:02 -04:00
|
|
|
#endif
|
|
|
|
sendItem(res_item) ;
|
|
|
|
}
|
2009-02-28 13:19:00 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
// If search depth not too large, also forward this search request to all other peers.
|
|
|
|
//
|
|
|
|
if(item->depth < TURTLE_MAX_SEARCH_DEPTH)
|
2009-03-12 16:08:02 -04:00
|
|
|
{
|
|
|
|
std::list<std::string> onlineIds ;
|
|
|
|
mConnMgr->getOnlineList(onlineIds);
|
2009-03-15 18:45:40 -04:00
|
|
|
#ifdef P3TURTLE_DEBUG
|
|
|
|
std::cerr << " Looking for online peers" << std::endl ;
|
|
|
|
#endif
|
2009-03-12 16:08:02 -04:00
|
|
|
|
2009-03-12 17:07:00 -04:00
|
|
|
for(std::list<std::string>::const_iterator it(onlineIds.begin());it!=onlineIds.end();++it)
|
|
|
|
if(*it != item->PeerId())
|
2009-02-28 13:19:00 -05:00
|
|
|
{
|
2009-03-12 16:08:02 -04:00
|
|
|
#ifdef P3TURTLE_DEBUG
|
|
|
|
std::cerr << " Forwarding request to peer = " << *it << std::endl ;
|
|
|
|
#endif
|
2009-02-28 13:19:00 -05:00
|
|
|
// Copy current item and modify it.
|
2009-03-12 17:07:00 -04:00
|
|
|
RsTurtleSearchRequestItem *fwd_item = new RsTurtleSearchRequestItem(*item) ;
|
2009-02-28 13:19:00 -05:00
|
|
|
|
|
|
|
++(fwd_item->depth) ; // increase search depth
|
2009-03-12 17:07:00 -04:00
|
|
|
fwd_item->PeerId(*it) ;
|
2009-02-28 13:19:00 -05:00
|
|
|
|
|
|
|
sendItem(fwd_item) ;
|
|
|
|
}
|
2009-03-12 16:08:02 -04:00
|
|
|
}
|
|
|
|
#ifdef P3TURTLE_DEBUG
|
|
|
|
else
|
|
|
|
std::cout << " Dropping this item, as search depth is " << item->depth << std::endl ;
|
|
|
|
#endif
|
2009-02-28 13:19:00 -05:00
|
|
|
}
|
|
|
|
|
2009-03-12 17:07:00 -04:00
|
|
|
void p3turtle::handleSearchResult(RsTurtleSearchResultItem *item)
|
2009-02-28 13:19:00 -05:00
|
|
|
{
|
2009-03-13 17:14:30 -04:00
|
|
|
RsStackMutex stack(mTurtleMtx); /********** STACK LOCKED MTX ******/
|
2009-02-28 13:19:00 -05:00
|
|
|
// Find who actually sent the corresponding request.
|
|
|
|
//
|
|
|
|
std::map<TurtleRequestId,TurtlePeerId>::const_iterator it = requests_origins.find(item->request_id) ;
|
2009-03-12 16:08:02 -04:00
|
|
|
#ifdef P3TURTLE_DEBUG
|
|
|
|
std::cerr << "Received search result:" << std::endl ;
|
2009-03-12 17:07:00 -04:00
|
|
|
item->print(std::cerr,0) ;
|
2009-03-12 16:08:02 -04:00
|
|
|
#endif
|
2009-02-28 13:19:00 -05:00
|
|
|
if(it == requests_origins.end())
|
|
|
|
{
|
|
|
|
// This is an error: how could we receive a search result corresponding to a search item we
|
|
|
|
// have forwarded but that it not in the list ??
|
|
|
|
|
|
|
|
std::cerr << __PRETTY_FUNCTION__ << ": search result has no peer direction!" << std::endl ;
|
|
|
|
delete item ;
|
|
|
|
return ;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Is this result's target actually ours ?
|
|
|
|
|
2009-03-15 18:45:40 -04:00
|
|
|
++(item->depth) ; // increase depth
|
|
|
|
|
2009-03-12 17:07:00 -04:00
|
|
|
if(it->second == mConnMgr->getOwnId())
|
2009-02-28 13:19:00 -05:00
|
|
|
returnSearchResult(item) ; // Yes, so send upward.
|
|
|
|
else
|
|
|
|
{ // Nope, so forward it back.
|
2009-03-12 16:08:02 -04:00
|
|
|
#ifdef P3TURTLE_DEBUG
|
|
|
|
std::cerr << " Forwarding result back to " << it->second << std::endl;
|
|
|
|
#endif
|
2009-03-12 17:07:00 -04:00
|
|
|
RsTurtleSearchResultItem *fwd_item = new RsTurtleSearchResultItem(*item) ; // copy the item
|
2009-02-28 13:19:00 -05:00
|
|
|
|
|
|
|
// normally here, we should setup the forward adress, so that the owner's of the files found can be further reached by a tunnel.
|
|
|
|
|
2009-03-12 17:07:00 -04:00
|
|
|
fwd_item->PeerId(it->second) ;
|
2009-02-28 13:19:00 -05:00
|
|
|
|
|
|
|
sendItem(fwd_item) ;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2009-03-12 17:07:00 -04:00
|
|
|
std::ostream& RsTurtleSearchRequestItem::print(std::ostream& o, uint16_t)
|
2009-03-12 16:08:02 -04:00
|
|
|
{
|
2009-03-12 17:07:00 -04:00
|
|
|
o << "Search request:" << std::endl ;
|
2009-03-15 18:45:40 -04:00
|
|
|
o << " direct origin: \"" << PeerId() << "\"" << std::endl ;
|
2009-03-12 17:07:00 -04:00
|
|
|
o << " match string: \"" << match_string << "\"" << std::endl ;
|
|
|
|
o << " Req. Id: " << request_id << std::endl ;
|
|
|
|
o << " Depth : " << depth << std::endl ;
|
2009-03-12 16:08:02 -04:00
|
|
|
|
2009-03-12 17:07:00 -04:00
|
|
|
return o ;
|
2009-03-12 16:08:02 -04:00
|
|
|
}
|
|
|
|
|
2009-03-12 17:07:00 -04:00
|
|
|
std::ostream& RsTurtleSearchResultItem::print(std::ostream& o, uint16_t)
|
2009-03-12 16:08:02 -04:00
|
|
|
{
|
2009-03-12 17:07:00 -04:00
|
|
|
o << "Search result:" << std::endl ;
|
2009-03-12 16:08:02 -04:00
|
|
|
|
2009-03-15 18:45:40 -04:00
|
|
|
o << " Peer id: " << PeerId() << std::endl ;
|
2009-03-12 17:07:00 -04:00
|
|
|
o << " Depth : " << depth << std::endl ;
|
|
|
|
o << " Req. Id: " << request_id << std::endl ;
|
|
|
|
o << " Files:" << std::endl ;
|
2009-03-12 16:08:02 -04:00
|
|
|
|
2009-03-15 18:45:40 -04:00
|
|
|
for(std::list<TurtleFileInfo>::const_iterator it(result.begin());it!=result.end();++it)
|
|
|
|
o << " " << it->hash << " " << it->size << " " << it->name << std::endl ;
|
2009-03-12 17:07:00 -04:00
|
|
|
|
|
|
|
return o ;
|
2009-03-12 16:08:02 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
void p3turtle::returnSearchResult(RsTurtleSearchResultItem *item)
|
|
|
|
{
|
|
|
|
// just cout for now, but it should be notified to the gui
|
|
|
|
|
2009-03-15 18:45:40 -04:00
|
|
|
#ifdef P3TURTLE_DEBUG
|
|
|
|
std::cerr << " Returning result for search request " << item->request_id << " upwards." << std::endl ;
|
|
|
|
#endif
|
|
|
|
|
|
|
|
rsicontrol->getNotify().notifyTurtleSearchResult(item->request_id,item->result) ;
|
2009-03-12 16:08:02 -04:00
|
|
|
}
|
|
|
|
|
2009-02-28 13:19:00 -05:00
|
|
|
/************* from pqiMonitor *******************/
|
|
|
|
void p3turtle::statusChange(const std::list<pqipeer> &plist)
|
|
|
|
{
|
2009-03-12 16:08:02 -04:00
|
|
|
// Do we shutdown tunnels whne peers are down, or automatically find a new tunnel ?
|
|
|
|
// I'll see that later...
|
2009-02-28 13:19:00 -05:00
|
|
|
#ifdef TO_DO
|
|
|
|
/* get a list of all online peers */
|
|
|
|
std::list<std::string> onlineIds;
|
|
|
|
mConnMgr->getOnlineList(onlineIds);
|
|
|
|
|
|
|
|
std::list<pqipeer>::const_iterator pit;
|
|
|
|
/* if any have switched to 'connected' then we notify */
|
|
|
|
for(pit = plist.begin(); pit != plist.end(); pit++)
|
|
|
|
{
|
|
|
|
if ((pit->state & RS_PEER_S_FRIEND) &&
|
|
|
|
(pit->actions & RS_PEER_CONNECTED))
|
|
|
|
{
|
|
|
|
/* send our details to them */
|
|
|
|
sendOwnDetails(pit->id);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
2009-03-13 17:14:30 -04:00
|
|
|
#include "serialiser/rstlvbase.h"
|
|
|
|
#include "serialiser/rsbaseserial.h"
|
|
|
|
|
|
|
|
uint32_t RsTurtleSearchRequestItem::serial_size()
|
|
|
|
{
|
|
|
|
uint32_t s = 0 ;
|
|
|
|
|
|
|
|
s += 8 ; // header
|
|
|
|
s += GetTlvStringSize(match_string) ;
|
|
|
|
s += 4 ; // request_id
|
|
|
|
s += 2 ; // depth
|
|
|
|
|
|
|
|
return s ;
|
|
|
|
}
|
|
|
|
|
2009-03-15 18:45:40 -04:00
|
|
|
uint32_t RsTurtleSearchResultItem::serial_size()
|
|
|
|
{
|
|
|
|
uint32_t s = 0 ;
|
|
|
|
|
|
|
|
s += 8 ; // header
|
|
|
|
s += 4 ; // search request id
|
|
|
|
s += 2 ; // depth
|
|
|
|
s += 4 ; // number of results
|
|
|
|
|
|
|
|
for(std::list<TurtleFileInfo>::const_iterator it(result.begin());it!=result.end();++it)
|
|
|
|
{
|
|
|
|
s += 8 ; // file size
|
|
|
|
s += GetTlvStringSize(it->hash) ; // file hash
|
|
|
|
s += GetTlvStringSize(it->name) ; // file name
|
|
|
|
}
|
|
|
|
|
|
|
|
return s ;
|
|
|
|
}
|
|
|
|
|
|
|
|
RsItem *RsTurtleSerialiser::deserialise(void *data, uint32_t *size)
|
|
|
|
{
|
|
|
|
// look what we have...
|
|
|
|
|
|
|
|
/* get the type */
|
|
|
|
uint32_t rstype = getRsItemId(data);
|
|
|
|
#ifdef P3TURTLE_DEBUG
|
|
|
|
std::cerr << "p3turtle: deserialising packet: " << std::endl ;
|
|
|
|
#endif
|
|
|
|
if ((RS_PKT_VERSION_SERVICE != getRsItemVersion(rstype)) || (RS_SERVICE_TYPE_TURTLE != getRsItemService(rstype)))
|
|
|
|
{
|
|
|
|
#ifdef P3TURTLE_DEBUG
|
|
|
|
std::cerr << " Wrong type !!" << std::endl ;
|
|
|
|
#endif
|
|
|
|
return NULL; /* wrong type */
|
|
|
|
}
|
|
|
|
|
|
|
|
try
|
|
|
|
{
|
|
|
|
switch(getRsItemSubType(rstype))
|
|
|
|
{
|
|
|
|
case RS_TURTLE_SUBTYPE_SEARCH_REQUEST: return new RsTurtleSearchRequestItem(data,*size) ;
|
|
|
|
case RS_TURTLE_SUBTYPE_SEARCH_RESULT: return new RsTurtleSearchResultItem(data,*size) ;
|
|
|
|
|
|
|
|
default:
|
|
|
|
std::cerr << "Unknown packet type in RsTurtle!" << std::endl ;
|
|
|
|
return NULL ;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
catch(std::exception& e)
|
|
|
|
{
|
|
|
|
std::cerr << "Exception raised: " << e.what() << std::endl ;
|
|
|
|
return NULL ;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2009-03-13 17:14:30 -04:00
|
|
|
bool RsTurtleSearchRequestItem::serialize(void *data,uint32_t& pktsize)
|
|
|
|
{
|
|
|
|
uint32_t tlvsize = serial_size();
|
|
|
|
uint32_t offset = 0;
|
|
|
|
|
|
|
|
if (pktsize < tlvsize)
|
|
|
|
return false; /* not enough space */
|
|
|
|
|
|
|
|
pktsize = tlvsize;
|
|
|
|
|
|
|
|
bool ok = true;
|
|
|
|
|
|
|
|
ok &= setRsItemHeader(data,tlvsize,PacketId(), tlvsize);
|
|
|
|
|
|
|
|
/* skip the header */
|
|
|
|
offset += 8;
|
|
|
|
|
|
|
|
/* add mandatory parts first */
|
|
|
|
|
|
|
|
ok &= SetTlvString(data, tlvsize, &offset, TLV_TYPE_STR_VALUE, match_string);
|
|
|
|
ok &= setRawUInt32(data, tlvsize, &offset, request_id);
|
|
|
|
ok &= setRawUInt16(data, tlvsize, &offset, depth);
|
|
|
|
|
|
|
|
if (offset != tlvsize)
|
|
|
|
{
|
|
|
|
ok = false;
|
|
|
|
#ifdef RSSERIAL_DEBUG
|
|
|
|
std::cerr << "RsFileConfigSerialiser::serialiseTransfer() Size Error! " << std::endl;
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
|
|
return ok;
|
|
|
|
}
|
|
|
|
|
2009-03-15 18:45:40 -04:00
|
|
|
RsTurtleSearchRequestItem::RsTurtleSearchRequestItem(void *data,uint32_t pktsize)
|
|
|
|
: RsTurtleItem(RS_TURTLE_SUBTYPE_SEARCH_REQUEST)
|
2009-03-13 17:14:30 -04:00
|
|
|
{
|
2009-03-15 18:45:40 -04:00
|
|
|
#ifdef P3TURTLE_DEBUG
|
|
|
|
std::cerr << " type = search request" << std::endl ;
|
|
|
|
#endif
|
|
|
|
uint32_t offset = 8; // skip the header
|
|
|
|
uint32_t rssize = getRsItemSize(data);
|
|
|
|
bool ok = true ;
|
2009-03-13 17:14:30 -04:00
|
|
|
|
2009-03-15 18:45:40 -04:00
|
|
|
ok &= GetTlvString(data, pktsize, &offset, TLV_TYPE_STR_VALUE, match_string); // file hash
|
|
|
|
ok &= getRawUInt32(data, pktsize, &offset, &request_id);
|
|
|
|
ok &= getRawUInt16(data, pktsize, &offset, &depth);
|
2009-03-13 17:14:30 -04:00
|
|
|
|
2009-03-15 18:45:40 -04:00
|
|
|
if (offset != rssize)
|
|
|
|
throw std::runtime_error("Size error while deserializing.") ;
|
|
|
|
if (!ok)
|
|
|
|
throw std::runtime_error("Unknown error while deserializing.") ;
|
2009-03-13 17:14:30 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
bool RsTurtleSearchResultItem::serialize(void *data,uint32_t& pktsize)
|
|
|
|
{
|
|
|
|
uint32_t tlvsize = serial_size();
|
|
|
|
uint32_t offset = 0;
|
|
|
|
|
|
|
|
if (pktsize < tlvsize)
|
|
|
|
return false; /* not enough space */
|
|
|
|
|
|
|
|
pktsize = tlvsize;
|
|
|
|
|
|
|
|
bool ok = true;
|
|
|
|
|
|
|
|
ok &= setRsItemHeader(data,tlvsize,PacketId(), tlvsize);
|
|
|
|
|
|
|
|
/* skip the header */
|
|
|
|
offset += 8;
|
|
|
|
|
|
|
|
/* add mandatory parts first */
|
|
|
|
|
|
|
|
ok &= setRawUInt32(data, tlvsize, &offset, request_id);
|
2009-03-15 18:45:40 -04:00
|
|
|
ok &= setRawUInt16(data, tlvsize, &offset, depth);
|
2009-03-13 17:14:30 -04:00
|
|
|
ok &= setRawUInt32(data, tlvsize, &offset, result.size());
|
|
|
|
|
2009-03-15 18:45:40 -04:00
|
|
|
for(std::list<TurtleFileInfo>::const_iterator it(result.begin());it!=result.end();++it)
|
2009-03-13 17:14:30 -04:00
|
|
|
{
|
2009-03-15 18:45:40 -04:00
|
|
|
ok &= setRawUInt64(data, tlvsize, &offset, it->size); // file size
|
|
|
|
ok &= SetTlvString(data, tlvsize, &offset, TLV_TYPE_STR_HASH_SHA1, it->hash); // file hash
|
|
|
|
ok &= SetTlvString(data, tlvsize, &offset, TLV_TYPE_STR_NAME, it->name); // file name
|
2009-03-13 17:14:30 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
if (offset != tlvsize)
|
|
|
|
{
|
|
|
|
ok = false;
|
|
|
|
#ifdef RSSERIAL_DEBUG
|
|
|
|
std::cerr << "RsFileConfigSerialiser::serialiseTransfer() Size Error! " << std::endl;
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
|
|
return ok;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
RsTurtleSearchResultItem::RsTurtleSearchResultItem(void *data,uint32_t pktsize)
|
|
|
|
: RsTurtleItem(RS_TURTLE_SUBTYPE_SEARCH_RESULT)
|
|
|
|
{
|
2009-03-15 18:45:40 -04:00
|
|
|
#ifdef P3TURTLE_DEBUG
|
|
|
|
std::cerr << " type = search result" << std::endl ;
|
|
|
|
#endif
|
2009-03-13 17:14:30 -04:00
|
|
|
uint32_t offset = 8; // skip the header
|
|
|
|
uint32_t rssize = getRsItemSize(data);
|
|
|
|
|
|
|
|
/* add mandatory parts first */
|
|
|
|
|
|
|
|
bool ok = true ;
|
|
|
|
uint32_t s ;
|
|
|
|
ok &= getRawUInt32(data, pktsize, &offset, &request_id);
|
2009-03-15 18:45:40 -04:00
|
|
|
ok &= getRawUInt16(data, pktsize, &offset, &depth);
|
2009-03-13 17:14:30 -04:00
|
|
|
ok &= getRawUInt32(data, pktsize, &offset, &s) ;
|
2009-03-15 18:45:40 -04:00
|
|
|
#ifdef P3TURTLE_DEBUG
|
|
|
|
std::cerr << " reuqest_id=" << request_id << ", depth=" << depth << ", s=" << s << std::endl ;
|
|
|
|
#endif
|
2009-03-13 17:14:30 -04:00
|
|
|
|
|
|
|
result.clear() ;
|
|
|
|
|
|
|
|
for(uint i=0;i<s;++i)
|
|
|
|
{
|
2009-03-15 18:45:40 -04:00
|
|
|
TurtleFileInfo f ;
|
2009-03-13 17:14:30 -04:00
|
|
|
|
2009-03-15 18:45:40 -04:00
|
|
|
ok &= getRawUInt64(data, pktsize, &offset, &(f.size)); // file size
|
|
|
|
ok &= GetTlvString(data, pktsize, &offset, TLV_TYPE_STR_HASH_SHA1, f.hash); // file hash
|
|
|
|
ok &= GetTlvString(data, pktsize, &offset, TLV_TYPE_STR_NAME, f.name); // file name
|
2009-03-13 17:14:30 -04:00
|
|
|
|
2009-03-15 18:45:40 -04:00
|
|
|
result.push_back(f) ;
|
2009-03-13 17:14:30 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
if (offset != rssize)
|
|
|
|
throw std::runtime_error("Size error while deserializing.") ;
|
|
|
|
if (!ok)
|
|
|
|
throw std::runtime_error("Unknown error while deserializing.") ;
|
|
|
|
}
|
|
|
|
|
2009-03-15 18:45:40 -04:00
|
|
|
void p3turtle::performLocalSearch(const std::string& s,std::list<TurtleFileInfo>& result)
|
|
|
|
{
|
|
|
|
/* call to core */
|
|
|
|
std::list<FileDetail> initialResults;
|
|
|
|
std::list<std::string> words ;
|
|
|
|
|
|
|
|
// to do: split search string into words.
|
|
|
|
words.push_back(s) ;
|
|
|
|
|
|
|
|
// now, search!
|
|
|
|
rsFiles->SearchKeywords(words, initialResults,DIR_FLAGS_LOCAL);
|
|
|
|
|
|
|
|
result.clear() ;
|
|
|
|
|
|
|
|
for(std::list<FileDetail>::const_iterator it(initialResults.begin());it!=initialResults.end();++it)
|
|
|
|
{
|
|
|
|
TurtleFileInfo i ;
|
|
|
|
i.hash = it->hash ;
|
|
|
|
i.size = it->size ;
|
|
|
|
i.name = it->name ;
|
|
|
|
|
|
|
|
result.push_back(i) ;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|