2007-11-14 22:18:48 -05:00
/*
* " $Id: pqihandler.cc,v 1.12 2007-03-31 09:41:32 rmf24 Exp $ "
*
* 3 P / PQI network interface for RetroShare .
*
* Copyright 2004 - 2006 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 "pqi/pqihandler.h"
# include <sstream>
2008-07-10 12:29:18 -04:00
# include "util/rsdebug.h"
2009-06-08 13:09:00 -04:00
# include <stdlib.h>
2007-11-14 22:18:48 -05:00
const int pqihandlerzone = 34283 ;
2008-04-03 08:51:28 -04:00
/****
# define DEBUG_TICK 1
# define RSITEM_DEBUG 1
* * * */
2007-11-14 22:18:48 -05:00
pqihandler : : pqihandler ( SecurityPolicy * Global )
{
2008-11-22 08:15:07 -05:00
RsStackMutex stack ( coreMtx ) ; /**************** LOCKED MUTEX ****************/
2007-11-14 22:18:48 -05:00
// The global security....
// if something is disabled here...
// cannot be enabled by module.
globsec = Global ;
{
std : : ostringstream out ;
out < < " New pqihandler() " < < std : : endl ;
out < < " Security Policy: " < < secpolicy_print ( globsec ) ;
out < < std : : endl ;
pqioutput ( PQL_DEBUG_BASIC , pqihandlerzone , out . str ( ) ) ;
}
// setup minimal total+individual rates.
rateIndiv_out = 0.01 ;
rateIndiv_in = 0.01 ;
rateMax_out = 0.01 ;
rateMax_in = 0.01 ;
return ;
}
int pqihandler : : tick ( )
{
2008-11-22 08:15:07 -05:00
int moreToTick = 0 ;
{ RsStackMutex stack ( coreMtx ) ; /**************** LOCKED MUTEX ****************/
2007-11-14 22:18:48 -05:00
// tick all interfaces...
2007-12-11 20:29:14 -05:00
std : : map < std : : string , SearchModule * > : : iterator it ;
2007-11-14 22:18:48 -05:00
for ( it = mods . begin ( ) ; it ! = mods . end ( ) ; it + + )
{
if ( 0 < ( ( it - > second ) - > pqi ) - > tick ( ) )
{
2008-04-03 08:51:28 -04:00
# ifdef DEBUG_TICK
std : : cerr < < " pqihandler::tick() moreToTick from mod() " < < std : : endl ;
# endif
2007-11-14 22:18:48 -05:00
moreToTick = 1 ;
}
}
// get the items, and queue them correctly
2008-11-22 08:15:07 -05:00
if ( 0 < locked_GetItems ( ) )
2007-11-14 22:18:48 -05:00
{
2008-04-03 08:51:28 -04:00
# ifdef DEBUG_TICK
std : : cerr < < " pqihandler::tick() moreToTick from GetItems() " < < std : : endl ;
# endif
2007-11-14 22:18:48 -05:00
moreToTick = 1 ;
}
2008-11-22 08:15:07 -05:00
} /****** UNLOCK ******/
2007-11-14 22:18:48 -05:00
UpdateRates ( ) ;
return moreToTick ;
}
int pqihandler : : status ( )
{
2007-12-11 20:29:14 -05:00
std : : map < std : : string , SearchModule * > : : iterator it ;
2008-11-22 08:15:07 -05:00
RsStackMutex stack ( coreMtx ) ; /**************** LOCKED MUTEX ****************/
2007-11-14 22:18:48 -05:00
{ // for output
std : : ostringstream out ;
out < < " pqihandler::status() Active Modules: " < < std : : endl ;
// display all interfaces...
for ( it = mods . begin ( ) ; it ! = mods . end ( ) ; it + + )
{
out < < " \t Module [ " < < it - > first < < " ] Pointer < " ;
out < < ( void * ) ( ( it - > second ) - > pqi ) < < " > " < < std : : endl ;
}
pqioutput ( PQL_DEBUG_BASIC , pqihandlerzone , out . str ( ) ) ;
} // end of output.
// status all interfaces...
for ( it = mods . begin ( ) ; it ! = mods . end ( ) ; it + + )
{
( ( it - > second ) - > pqi ) - > status ( ) ;
}
return 1 ;
}
2007-12-11 20:29:14 -05:00
bool pqihandler : : AddSearchModule ( SearchModule * mod )
2007-11-14 22:18:48 -05:00
{
2010-01-13 20:33:56 -05:00
//RsStackMutex stack(coreMtx); /**************** LOCKED MUTEX ****************/ This might be dangerous, but usefull for accepting new frinds right upon connection
2007-12-11 20:29:14 -05:00
// if peerid used -> error.
std : : map < std : : string , SearchModule * > : : iterator it ;
if ( mod - > peerid ! = mod - > pqi - > PeerId ( ) )
2007-11-14 22:18:48 -05:00
{
2007-12-11 20:29:14 -05:00
// ERROR!
std : : ostringstream out ;
out < < " ERROR peerid != PeerId! " < < std : : endl ;
pqioutput ( PQL_ALERT , pqihandlerzone , out . str ( ) ) ;
return false ;
2007-11-14 22:18:48 -05:00
}
2007-12-11 20:29:14 -05:00
if ( mod - > peerid = = " " )
2007-11-14 22:18:48 -05:00
{
2007-12-11 20:29:14 -05:00
// ERROR!
std : : ostringstream out ;
out < < " ERROR peerid == NULL " < < std : : endl ;
pqioutput ( PQL_ALERT , pqihandlerzone , out . str ( ) ) ;
return false ;
}
2007-11-14 22:18:48 -05:00
2007-12-11 20:29:14 -05:00
if ( mods . find ( mod - > peerid ) ! = mods . end ( ) )
{
// ERROR!
std : : ostringstream out ;
out < < " ERROR PeerId Module already exists! " < < std : : endl ;
pqioutput ( PQL_ALERT , pqihandlerzone , out . str ( ) ) ;
return false ;
2007-11-14 22:18:48 -05:00
}
// check security.
if ( mod - > sp = = NULL )
{
// create policy.
mod - > sp = secpolicy_create ( ) ;
}
// limit to what global security allows.
secpolicy_limit ( globsec , mod - > sp ) ;
// store.
2007-12-11 20:29:14 -05:00
mods [ mod - > peerid ] = mod ;
return true ;
2007-11-14 22:18:48 -05:00
}
2007-12-11 20:29:14 -05:00
bool pqihandler : : RemoveSearchModule ( SearchModule * mod )
2007-11-14 22:18:48 -05:00
{
2008-11-22 08:15:07 -05:00
RsStackMutex stack ( coreMtx ) ; /**************** LOCKED MUTEX ****************/
2007-12-11 20:29:14 -05:00
std : : map < std : : string , SearchModule * > : : iterator it ;
2007-11-14 22:18:48 -05:00
for ( it = mods . begin ( ) ; it ! = mods . end ( ) ; it + + )
{
if ( mod = = it - > second )
{
mods . erase ( it ) ;
2007-12-11 20:29:14 -05:00
return true ;
2007-11-14 22:18:48 -05:00
}
}
2007-12-11 20:29:14 -05:00
return false ;
2007-11-14 22:18:48 -05:00
}
// dummy output check
2008-11-22 08:15:07 -05:00
int pqihandler : : locked_checkOutgoingRsItem ( RsItem * item , int global )
2007-11-14 22:18:48 -05:00
{
pqioutput ( PQL_WARNING , pqihandlerzone ,
" pqihandler::checkOutgoingPQItem() NULL fn " ) ;
return 1 ;
}
// generalised output
2007-12-11 20:29:14 -05:00
int pqihandler : : HandleRsItem ( RsItem * item , int allowglobal )
2007-11-14 22:18:48 -05:00
{
2008-11-22 08:15:07 -05:00
RsStackMutex stack ( coreMtx ) ; /**************** LOCKED MUTEX ****************/
2007-12-11 20:29:14 -05:00
std : : map < std : : string , SearchModule * > : : iterator it ;
2007-11-14 22:18:48 -05:00
pqioutput ( PQL_DEBUG_BASIC , pqihandlerzone ,
2007-12-11 20:29:14 -05:00
" pqihandler::HandleRsItem() " ) ;
2007-11-14 22:18:48 -05:00
2007-12-11 20:29:14 -05:00
/* simplified to no global! */
if ( allowglobal )
2007-11-14 22:18:48 -05:00
{
2007-12-11 20:29:14 -05:00
/* error */
2007-11-14 22:18:48 -05:00
std : : ostringstream out ;
2007-12-11 20:29:14 -05:00
out < < " pqihandler::HandleSearchItem() " ;
out < < " Cannot send out Global RsItem " ;
pqioutput ( PQL_ALERT , pqihandlerzone , out . str ( ) ) ;
2009-12-13 16:59:26 -05:00
# ifdef DEBUG_TICK
std : : cerr < < out . str ( ) ;
# endif
2007-12-11 20:29:14 -05:00
delete item ;
return - 1 ;
}
2008-11-22 08:15:07 -05:00
if ( ! locked_checkOutgoingRsItem ( item , allowglobal ) )
2007-12-11 20:29:14 -05:00
{
std : : ostringstream out ;
out < < " pqihandler::HandleRsItem() checkOutgoingPQItem " ;
2007-11-14 22:18:48 -05:00
out < < " Failed on item: " < < std : : endl ;
2009-12-13 16:59:26 -05:00
# ifdef DEBUG_TICK
std : : cerr < < out . str ( ) ;
# endif
item - > print ( out ) ;
2007-11-14 22:18:48 -05:00
2007-12-11 20:29:14 -05:00
pqioutput ( PQL_ALERT , pqihandlerzone , out . str ( ) ) ;
2007-11-14 22:18:48 -05:00
delete item ;
return - 1 ;
}
2007-12-11 20:29:14 -05:00
pqioutput ( PQL_DEBUG_BASIC , pqihandlerzone ,
" pqihandler::HandleRsItem() Sending to One Channel " ) ;
2009-12-13 16:59:26 -05:00
# ifdef DEBUG_TICK
std : : cerr < < " pqihandler::HandleRsItem() Sending to One Channel " < < std : : endl ;
# endif
2007-11-14 22:18:48 -05:00
2007-12-11 20:29:14 -05:00
// find module.
if ( ( it = mods . find ( item - > PeerId ( ) ) ) = = mods . end ( ) )
{
std : : ostringstream out ;
out < < " pqihandler::HandleRsItem() Invalid chan! " ;
pqioutput ( PQL_DEBUG_BASIC , pqihandlerzone , out . str ( ) ) ;
2009-12-13 16:59:26 -05:00
# ifdef DEBUG_TICK
std : : cerr < < out . str ( ) ;
# endif
2007-11-14 22:18:48 -05:00
2007-12-11 20:29:14 -05:00
delete item ;
return - 1 ;
}
2007-11-14 22:18:48 -05:00
2007-12-11 20:29:14 -05:00
// check security... is output allowed.
if ( 0 < secpolicy_check ( ( it - > second ) - > sp , 0 , PQI_OUTGOING ) )
{
std : : ostringstream out ;
out < < " pqihandler::HandleRsItem() sending to chan: " ;
out < < it - > first < < std : : endl ;
pqioutput ( PQL_DEBUG_BASIC , pqihandlerzone , out . str ( ) ) ;
2009-12-13 16:59:26 -05:00
# ifdef DEBUG_TICK
std : : cerr < < out . str ( ) ;
# endif
2007-11-14 22:18:48 -05:00
2007-12-11 20:29:14 -05:00
// if yes send on item.
( ( it - > second ) - > pqi ) - > SendItem ( item ) ;
return 1 ;
2007-11-14 22:18:48 -05:00
}
else
{
2007-12-11 20:29:14 -05:00
std : : ostringstream out ;
out < < " pqihandler::HandleRsItem() " ;
out < < " Sec not approved " ;
pqioutput ( PQL_DEBUG_BASIC , pqihandlerzone , out . str ( ) ) ;
2009-12-13 16:59:26 -05:00
# ifdef DEBUG_TICK
std : : cerr < < out . str ( ) ;
# endif
2007-11-14 22:18:48 -05:00
delete item ;
2007-12-11 20:29:14 -05:00
return - 1 ;
2007-11-14 22:18:48 -05:00
}
// if successfully sent to at least one.
return 1 ;
}
2007-12-11 20:29:14 -05:00
int pqihandler : : SearchSpecific ( RsCacheRequest * ns )
2007-11-14 22:18:48 -05:00
{
2007-12-11 20:29:14 -05:00
return HandleRsItem ( ns , 0 ) ;
2007-11-14 22:18:48 -05:00
}
2007-12-11 20:29:14 -05:00
int pqihandler : : SendSearchResult ( RsCacheItem * ns )
2007-11-14 22:18:48 -05:00
{
2007-12-11 20:29:14 -05:00
return HandleRsItem ( ns , 0 ) ;
2007-11-14 22:18:48 -05:00
}
2007-12-11 20:29:14 -05:00
int pqihandler : : SendFileRequest ( RsFileRequest * ns )
2007-11-14 22:18:48 -05:00
{
2007-12-11 20:29:14 -05:00
return HandleRsItem ( ns , 0 ) ;
2007-11-14 22:18:48 -05:00
}
2007-12-11 20:29:14 -05:00
int pqihandler : : SendFileData ( RsFileData * ns )
2007-11-14 22:18:48 -05:00
{
2007-12-11 20:29:14 -05:00
return HandleRsItem ( ns , 0 ) ;
2007-11-14 22:18:48 -05:00
}
2007-12-11 20:29:14 -05:00
int pqihandler : : SendRsRawItem ( RsRawItem * ns )
2007-11-14 22:18:48 -05:00
{
pqioutput ( PQL_DEBUG_BASIC , pqihandlerzone ,
2007-12-11 20:29:14 -05:00
" pqihandler::SendRsRawItem() " ) ;
2009-12-13 16:59:26 -05:00
# ifdef DEBUG_TICK
std : : cerr < < " pqihandler::SendRsRawItem() " < < std : : endl ;
# endif
2007-12-11 20:29:14 -05:00
return HandleRsItem ( ns , 0 ) ;
2007-11-14 22:18:48 -05:00
}
2007-12-11 20:29:14 -05:00
2007-11-14 22:18:48 -05:00
// inputs. This is a very basic
// system that is completely biased and slow...
// someone please fix.
2008-11-22 08:15:07 -05:00
int pqihandler : : locked_GetItems ( )
2007-11-14 22:18:48 -05:00
{
2007-12-11 20:29:14 -05:00
std : : map < std : : string , SearchModule * > : : iterator it ;
2007-11-14 22:18:48 -05:00
2007-12-11 20:29:14 -05:00
RsItem * item ;
2007-11-14 22:18:48 -05:00
int count = 0 ;
// loop through modules....
for ( it = mods . begin ( ) ; it ! = mods . end ( ) ; it + + )
{
SearchModule * mod = ( it - > second ) ;
// check security... is output allowed.
if ( 0 < secpolicy_check ( ( it - > second ) - > sp ,
2008-02-07 11:18:34 -05:00
0 , PQI_INCOMING ) ) // PQI_ITEM_TYPE_ITEM, PQI_INCOMING))
2007-11-14 22:18:48 -05:00
{
// if yes... attempt to read.
while ( ( item = ( mod - > pqi ) - > GetItem ( ) ) ! = NULL )
{
2008-04-03 08:51:28 -04:00
# ifdef RSITEM_DEBUG
2007-11-14 22:18:48 -05:00
std : : ostringstream out ;
out < < " pqihandler::GetItems() Incoming Item " ;
out < < " from: " < < mod - > pqi < < std : : endl ;
item - > print ( out ) ;
pqioutput ( PQL_DEBUG_BASIC ,
pqihandlerzone , out . str ( ) ) ;
2008-04-03 08:51:28 -04:00
# endif
2007-11-14 22:18:48 -05:00
2007-12-11 20:29:14 -05:00
if ( item - > PeerId ( ) ! = ( mod - > pqi ) - > PeerId ( ) )
{
/* ERROR */
pqioutput ( PQL_ALERT ,
pqihandlerzone , " ERROR PeerIds dont match! " ) ;
item - > PeerId ( mod - > pqi - > PeerId ( ) ) ;
}
2008-11-22 08:15:07 -05:00
locked_SortnStoreItem ( item ) ;
2007-11-14 22:18:48 -05:00
count + + ;
}
}
else
{
// not allowed to recieve from here....
while ( ( item = ( mod - > pqi ) - > GetItem ( ) ) ! = NULL )
{
std : : ostringstream out ;
out < < " pqihandler::GetItems() Incoming Item " ;
out < < " from: " < < mod - > pqi < < std : : endl ;
item - > print ( out ) ;
out < < std : : endl ;
out < < " Item Not Allowed (Sec Pol). deleting! " ;
out < < std : : endl ;
pqioutput ( PQL_DEBUG_BASIC ,
pqihandlerzone , out . str ( ) ) ;
delete item ;
}
}
}
return count ;
}
2008-11-22 08:15:07 -05:00
void pqihandler : : locked_SortnStoreItem ( RsItem * item )
2007-11-14 22:18:48 -05:00
{
2007-12-11 20:29:14 -05:00
/* get class type / subtype out of the item */
uint8_t vers = item - > PacketVersion ( ) ;
uint8_t cls = item - > PacketClass ( ) ;
uint8_t type = item - > PacketType ( ) ;
uint8_t subtype = item - > PacketSubType ( ) ;
/* whole Version reserved for SERVICES/CACHES */
if ( vers = = RS_PKT_VERSION_SERVICE )
2007-11-14 22:18:48 -05:00
{
2007-12-11 20:29:14 -05:00
pqioutput ( PQL_DEBUG_BASIC , pqihandlerzone ,
" SortnStore -> Service " ) ;
in_service . push_back ( item ) ;
item = NULL ;
return ;
2007-11-14 22:18:48 -05:00
}
2007-12-11 20:29:14 -05:00
if ( vers ! = RS_PKT_VERSION1 )
2007-11-14 22:18:48 -05:00
{
pqioutput ( PQL_DEBUG_BASIC , pqihandlerzone ,
2007-12-11 20:29:14 -05:00
" SortnStore -> Invalid VERSION! Deleting! " ) ;
delete item ;
item = NULL ;
return ;
2007-11-14 22:18:48 -05:00
}
2007-12-11 20:29:14 -05:00
switch ( cls )
2007-11-14 22:18:48 -05:00
{
2007-12-11 20:29:14 -05:00
case RS_PKT_CLASS_BASE :
switch ( type )
{
case RS_PKT_TYPE_CACHE :
switch ( subtype )
{
case RS_PKT_SUBTYPE_CACHE_REQUEST :
pqioutput ( PQL_DEBUG_BASIC , pqihandlerzone ,
" SortnStore -> Cache Request " ) ;
in_search . push_back ( item ) ;
item = NULL ;
break ;
case RS_PKT_SUBTYPE_CACHE_ITEM :
pqioutput ( PQL_DEBUG_BASIC , pqihandlerzone ,
" SortnStore -> Cache Result " ) ;
in_result . push_back ( item ) ;
item = NULL ;
break ;
default :
break ; /* no match! */
}
break ;
case RS_PKT_TYPE_FILE :
switch ( subtype )
{
case RS_PKT_SUBTYPE_FI_REQUEST :
pqioutput ( PQL_DEBUG_BASIC , pqihandlerzone ,
" SortnStore -> File Request " ) ;
in_request . push_back ( item ) ;
item = NULL ;
break ;
case RS_PKT_SUBTYPE_FI_DATA :
pqioutput ( PQL_DEBUG_BASIC , pqihandlerzone ,
" SortnStore -> File Data " ) ;
in_data . push_back ( item ) ;
item = NULL ;
break ;
default :
break ; /* no match! */
}
break ;
default :
break ; /* no match! */
}
break ;
default :
pqioutput ( PQL_DEBUG_BASIC , pqihandlerzone ,
" SortnStore -> Unknown " ) ;
break ;
2007-11-14 22:18:48 -05:00
}
2007-12-11 20:29:14 -05:00
if ( item )
2007-11-14 22:18:48 -05:00
{
2007-12-11 20:29:14 -05:00
pqioutput ( PQL_DEBUG_BASIC , pqihandlerzone ,
" SortnStore -> Deleting Unsorted Item " ) ;
delete item ;
2007-11-14 22:18:48 -05:00
}
2007-12-11 20:29:14 -05:00
2007-11-14 22:18:48 -05:00
return ;
}
// much like the input stuff.
2007-12-11 20:29:14 -05:00
RsCacheItem * pqihandler : : GetSearchResult ( )
2007-11-14 22:18:48 -05:00
{
2008-11-22 08:15:07 -05:00
RsStackMutex stack ( coreMtx ) ; /**************** LOCKED MUTEX ****************/
2007-11-14 22:18:48 -05:00
if ( in_result . size ( ) ! = 0 )
{
2007-12-11 20:29:14 -05:00
RsCacheItem * fi = dynamic_cast < RsCacheItem * > ( in_result . front ( ) ) ;
if ( ! fi ) { delete in_result . front ( ) ; }
2007-11-14 22:18:48 -05:00
in_result . pop_front ( ) ;
return fi ;
}
return NULL ;
}
2007-12-11 20:29:14 -05:00
RsCacheRequest * pqihandler : : RequestedSearch ( )
2007-11-14 22:18:48 -05:00
{
2008-11-22 08:15:07 -05:00
RsStackMutex stack ( coreMtx ) ; /**************** LOCKED MUTEX ****************/
2007-12-11 20:29:14 -05:00
if ( in_search . size ( ) ! = 0 )
2007-11-14 22:18:48 -05:00
{
2007-12-11 20:29:14 -05:00
RsCacheRequest * fi = dynamic_cast < RsCacheRequest * > ( in_search . front ( ) ) ;
if ( ! fi ) { delete in_search . front ( ) ; }
in_search . pop_front ( ) ;
2007-11-14 22:18:48 -05:00
return fi ;
}
return NULL ;
}
2007-12-11 20:29:14 -05:00
RsFileRequest * pqihandler : : GetFileRequest ( )
2007-11-14 22:18:48 -05:00
{
2008-11-22 08:15:07 -05:00
RsStackMutex stack ( coreMtx ) ; /**************** LOCKED MUTEX ****************/
2007-12-11 20:29:14 -05:00
if ( in_request . size ( ) ! = 0 )
2007-11-14 22:18:48 -05:00
{
2007-12-11 20:29:14 -05:00
RsFileRequest * fi = dynamic_cast < RsFileRequest * > ( in_request . front ( ) ) ;
if ( ! fi ) { delete in_request . front ( ) ; }
in_request . pop_front ( ) ;
return fi ;
2007-11-14 22:18:48 -05:00
}
return NULL ;
}
2007-12-11 20:29:14 -05:00
RsFileData * pqihandler : : GetFileData ( )
2007-11-14 22:18:48 -05:00
{
2008-11-22 08:15:07 -05:00
RsStackMutex stack ( coreMtx ) ; /**************** LOCKED MUTEX ****************/
2007-12-11 20:29:14 -05:00
if ( in_data . size ( ) ! = 0 )
2007-11-14 22:18:48 -05:00
{
2007-12-11 20:29:14 -05:00
RsFileData * fi = dynamic_cast < RsFileData * > ( in_data . front ( ) ) ;
if ( ! fi ) { delete in_data . front ( ) ; }
in_data . pop_front ( ) ;
return fi ;
2007-11-14 22:18:48 -05:00
}
return NULL ;
}
2007-12-11 20:29:14 -05:00
RsRawItem * pqihandler : : GetRsRawItem ( )
2007-11-14 22:18:48 -05:00
{
2008-11-22 08:15:07 -05:00
RsStackMutex stack ( coreMtx ) ; /**************** LOCKED MUTEX ****************/
2007-12-11 20:29:14 -05:00
if ( in_service . size ( ) ! = 0 )
2007-11-14 22:18:48 -05:00
{
2007-12-11 20:29:14 -05:00
RsRawItem * fi = dynamic_cast < RsRawItem * > ( in_service . front ( ) ) ;
if ( ! fi ) { delete in_service . front ( ) ; }
in_service . pop_front ( ) ;
return fi ;
2007-11-14 22:18:48 -05:00
}
return NULL ;
}
static const float MIN_RATE = 0.01 ; // 10 B/s
// internal fn to send updates
int pqihandler : : UpdateRates ( )
{
2007-12-11 20:29:14 -05:00
std : : map < std : : string , SearchModule * > : : iterator it ;
2007-11-14 22:18:48 -05:00
int num_sm = mods . size ( ) ;
float avail_in = getMaxRate ( true ) ;
float avail_out = getMaxRate ( false ) ;
float used_bw_in = 0 ;
float used_bw_out = 0 ;
2008-11-22 08:15:07 -05:00
/* Lock once rates have been retrieved */
RsStackMutex stack ( coreMtx ) ; /**************** LOCKED MUTEX ****************/
2009-06-08 13:09:00 -04:00
int effectiveUploadsSm = 0 ;
int effectiveDownloadsSm = 0 ;
// loop through modules to get the used bandwith and the number of modules that are affectively transfering
//std::cerr << " Looping through modules" << std::endl;
2007-11-14 22:18:48 -05:00
for ( it = mods . begin ( ) ; it ! = mods . end ( ) ; it + + )
{
SearchModule * mod = ( it - > second ) ;
float crate_in = mod - > pqi - > getRate ( true ) ;
2009-06-08 13:09:00 -04:00
if ( crate_in > 0.01 * avail_in | | crate_in > 0.1 )
2007-11-14 22:18:48 -05:00
{
2009-06-08 13:09:00 -04:00
effectiveDownloadsSm + + ;
2007-11-14 22:18:48 -05:00
}
2009-06-08 13:09:00 -04:00
float crate_out = mod - > pqi - > getRate ( false ) ;
if ( crate_out > 0.01 * avail_out | | crate_out > 0.1 )
2007-11-14 22:18:48 -05:00
{
2009-06-08 13:09:00 -04:00
effectiveUploadsSm + + ;
2007-11-14 22:18:48 -05:00
}
2009-06-08 13:09:00 -04:00
used_bw_in + = crate_in ;
used_bw_out + = crate_out ;
2007-11-14 22:18:48 -05:00
}
2009-06-08 13:09:00 -04:00
// std::cerr << "Totals (In) Used B/W " << used_bw_in;
// std::cerr << " Available B/W " << avail_in;
// std::cerr << " Effective transfers " << effectiveDownloadsSm << std::endl;
// std::cerr << "Totals (Out) Used B/W " << used_bw_out;
// std::cerr << " Available B/W " << avail_out;
// std::cerr << " Effective transfers " << effectiveUploadsSm << std::endl;
2007-11-14 22:18:48 -05:00
2009-06-08 13:09:00 -04:00
locked_StoreCurrentRates ( used_bw_in , used_bw_out ) ;
2007-11-14 22:18:48 -05:00
2009-06-08 13:09:00 -04:00
//computing average rates for effective transfers
float max_in_effective = avail_in / num_sm ;
if ( effectiveDownloadsSm ! = 0 ) {
max_in_effective = avail_in / effectiveDownloadsSm ;
}
float max_out_effective = avail_out / num_sm ;
if ( effectiveUploadsSm ! = 0 ) {
max_out_effective = avail_out / effectiveUploadsSm ;
}
2007-11-14 22:18:48 -05:00
2009-06-08 13:09:00 -04:00
//modify the outgoing rates if bandwith is not used well
float rate_out_modifier = 0 ;
if ( used_bw_out / avail_out < 0.95 ) {
rate_out_modifier = 0.001 * avail_out ;
} else if ( used_bw_out / avail_out > 1.05 ) {
rate_out_modifier = - 0.001 * avail_out ;
}
if ( rate_out_modifier ! = 0 ) {
for ( it = mods . begin ( ) ; it ! = mods . end ( ) ; it + + )
{
SearchModule * mod = ( it - > second ) ;
mod - > pqi - > setMaxRate ( false , mod - > pqi - > getMaxRate ( false ) + rate_out_modifier ) ;
}
2007-11-14 22:18:48 -05:00
}
2009-06-08 13:09:00 -04:00
//modify the incoming rates if bandwith is not used well
float rate_in_modifier = 0 ;
if ( used_bw_in / avail_in < 0.95 ) {
rate_in_modifier = 0.001 * avail_in ;
} else if ( used_bw_in / avail_in > 1.05 ) {
rate_in_modifier = - 0.001 * avail_in ;
}
if ( rate_in_modifier ! = 0 ) {
for ( it = mods . begin ( ) ; it ! = mods . end ( ) ; it + + )
{
SearchModule * mod = ( it - > second ) ;
mod - > pqi - > setMaxRate ( true , mod - > pqi - > getMaxRate ( true ) + rate_in_modifier ) ;
}
}
2007-11-14 22:18:48 -05:00
2009-06-08 13:09:00 -04:00
//cap the rates
for ( it = mods . begin ( ) ; it ! = mods . end ( ) ; it + + )
2007-11-14 22:18:48 -05:00
{
2009-06-08 13:09:00 -04:00
SearchModule * mod = ( it - > second ) ;
if ( mod - > pqi - > getMaxRate ( false ) < max_out_effective ) {
mod - > pqi - > setMaxRate ( false , max_out_effective ) ;
2007-11-14 22:18:48 -05:00
}
2009-06-08 13:09:00 -04:00
if ( mod - > pqi - > getMaxRate ( false ) > avail_out ) {
mod - > pqi - > setMaxRate ( false , avail_out ) ;
}
if ( mod - > pqi - > getMaxRate ( true ) < max_in_effective ) {
mod - > pqi - > setMaxRate ( true , max_in_effective ) ;
}
if ( mod - > pqi - > getMaxRate ( true ) > avail_in ) {
mod - > pqi - > setMaxRate ( true , avail_in ) ;
2007-11-14 22:18:48 -05:00
}
}
2008-06-09 20:47:24 -04:00
2007-11-14 22:18:48 -05:00
return 1 ;
}
2008-06-09 20:47:24 -04:00
void pqihandler : : getCurrentRates ( float & in , float & out )
{
2008-11-22 08:15:07 -05:00
RsStackMutex stack ( coreMtx ) ; /**************** LOCKED MUTEX ****************/
2008-06-09 20:47:24 -04:00
in = rateTotal_in ;
out = rateTotal_out ;
}
2008-11-22 08:15:07 -05:00
void pqihandler : : locked_StoreCurrentRates ( float in , float out )
2008-06-09 20:47:24 -04:00
{
rateTotal_in = in ;
rateTotal_out = out ;
}
2007-11-14 22:18:48 -05:00