00001 /* 00002 * Copyright (C) 2009, Edmundo Albuquerque de Souza e Silva. 00003 * 00004 * This file may be distributed under the terms of the Q Public License 00005 * as defined by Trolltech AS of Norway and appearing in the file 00006 * LICENSE.QPL included in the packaging of this file. 00007 * 00008 * THIS FILE IS PROVIDED AS IS WITH NO WARRANTY OF ANY KIND, INCLUDING 00009 * THE WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR 00010 * PURPOSE. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, 00011 * INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING 00012 * FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, 00013 * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION 00014 * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 00015 * 00016 * Thanks: Jose Renato Santos 00017 * 00018 */ 00019 00020 /////////////////////////////////////////////////////////////////// 00021 // NetMgr.h: headers for NetMgr.cpp (to be RioNet in future?) 00022 /////////////////////////////////////////////////////////////////// 00023 00024 #ifndef __NETMGR_H_ 00025 #define __NETMGR_H_ 00026 00027 #ifdef WINDOWS 00028 // Windows implementation 00029 #else 00030 // Linux implementation 00031 #include <pthread.h> 00032 #include <string> 00033 #endif 00034 00035 #include "../interface/RioInterfaceTypes.h" 00036 #include "RioSemaphore.h" 00037 00038 00039 #define FRAGMENTSIZE 1500 // Velox (Telemar) - max size PPP/OE 00040 00041 using std::string; 00042 00043 class BufferStream; 00044 class RioNeti; 00045 class NetBuf; 00046 00047 class CLogRotation; 00048 00049 class NetMgr 00050 { 00051 public: 00052 /** 00053 * NetMgr tem o parametro serverInstance por default igual a false. 00054 * Indica se esta instancia da NetMgr foi criada no servidor (true) ou 00055 * nao, se foi criada no cliente (false). 00056 */ 00057 NetMgr( bool serverInstance = false ); 00058 00059 ~NetMgr(); 00060 00061 // Mudanca da funcao Start para passar mais dois parametros para o 00062 // controle do fluxo do servidor: MaxClientsCredits - numero maximo de 00063 // creditos para as tranferencias de fragmentos entre os clientes; 00064 // MaxNetworkCredits numero maximo de creditos para as tranferencias 00065 // dos fragmentos pela rede; e NetworkRate que define a taxa maxima de 00066 // transferencia dos dados. Estes novos parametros sao repassados para 00067 // a classe RioNeti, e um valor 0 em MaxClientsCledits, 00068 // MaxNetworkCredits ou NetworkRate (os valores default) indica que nao 00069 // queremos usar o controle de fluxo (por exemplo, quando a classe for 00070 // criada pelo cliente). 00071 #ifdef RIO_DEBUG_FILE 00072 // Mais um novo parametro foi adicionado a funcao Start se a opcao 00073 // RIO_DEBUG_FILE for usada: RioNetiLogPath, que informa o nome do 00074 // arquivo com o log da RioNeti. Ele foi colocado antes dos parametro e 00075 // do controle de fluxo e dos parametros devString e usleepInterval 00076 // porque estes parametros nao sao sempre usados. O valor default deste 00077 // parametro e NULL e, neste caso, o log sera armazenado do diretorio 00078 // do programa que executou a Start esta executando e tera o seguinte 00079 // nome: 00080 // RIOClientEmul_<maquina>.<dominio>.log se um dos clientes (riosh ou 00081 // riommclient) executou a funcao. 00082 // RIOServerEmul_<maquina>.<dominio>.log se o servidor de despacho 00083 // executou a funcao. 00084 // RIOStorageEmul_<maquina>.<dominio>.log se o servidor de armazenamento 00085 // executou a funcao. 00086 int Start( int port, int maxdiskl, int maxpktl, 00087 const char *RioNetiLogPath = NULL, 00088 unsigned int MaxCreditsClients = 0, 00089 unsigned int MaxNetworkCredits = 0, 00090 unsigned int NetworkRate = 0 ); 00091 #else 00092 int Start( int port, int maxdiskl, int maxpktl, 00093 unsigned int MaxCreditsClients = 0, 00094 unsigned int MaxNetworkCredits = 0, 00095 unsigned int NetworkRate = 0 ); 00096 #endif 00097 int Stop(); 00098 void getmyaddrport( int *ipaddr, int *port, int server = 0); 00099 void getalladdrport( int **ipaddr, int **port ); 00100 int getipaddr(); 00101 00102 /** 00103 * Este metodo nao esta sendo usado em lugar nenhum do codigo 00104 */ 00105 void SetCmdProc(cmdcallback_t cmdproc, void *cmdparm); 00106 00107 void SendCmd( int ipadr, int port, int reqid, char *cmdp, int cmdl, 00108 callback_t callback, void *callbackparm ); 00109 void SendResult(int ipadr, int port, int reqid, int result); 00110 // O novo parametro VideoRate foi adicionado. Ele define, caso 00111 // estejamos enviando trafego em tempo real (os videos) a taxa de 00112 // transmissao do video em Kbps. Como ele somente e usado pelo servidor 00113 // de armazenamento, ele possui um valor default de 0, para que nao 00114 // seja necessario alterarmos o codigo do cliente e do servidor de 00115 // despacho. 00116 void SendBlock( int ipadr, int port, int reqid, char *bufadr, 00117 int buflen, callback_t callback, void *callbackparm, 00118 int StreamTraffic, unsigned int VideoRate = 0 ); 00119 int ExpectBlock( char *buf, int len, 00120 callback_t callback, void *callbackparm, 00121 int sendack = 1 ); 00122 int CancelExpect(int reqid, int result); 00123 void TellId( int ipadr, int port, int reqid, 00124 int tellip, int tellport, int tellreqid, 00125 callback_t callback, void *callbackparm ); 00126 void GetBlock( int ipadr, int port, int reqid, 00127 char *bufadr, int buflen, 00128 callback_t callback, void *callbackparm ); 00129 int ExpectTellId( char *buf, int len, 00130 callback_t callback, void *callbackparm ); 00131 00132 // following generally useful for debugging even outside NetMgr 00133 // (but hide name in class) 00134 static void dumppkt(const char *, char *, int); 00135 00136 bool SetMulticastSocket( unsigned short multicastport, 00137 char* multicast_addr, 00138 void *callback = 0, 00139 BufferStream *buffer_stream = 0, 00140 int enable_join = 1); 00141 void LeaveGroup( unsigned short multicastport ); 00142 void LeaveAllGroups( void ); 00143 int FreeBlock( unsigned int block_id, RioStreamType traffic ); 00144 int FreePendentBlocks( bool useCache, int nBuffers ); 00145 bool thereAreFragments( RioBlock block ); 00146 void Getmyaddr( int *my_address, int *my_port ); 00147 00148 #ifdef RIO_DEBUG2 00149 void printDebug( short debugCode, string message = "" ); 00150 #endif 00151 00152 /** 00153 * CreateKeepaliveThread funcao para criar a thread usada para enviar 00154 * periodicamente mensagens Fake aos servidores para garantir que os 00155 * mapeamentos nao serao expirados por timeout. 00156 * @param ServerAddress ponteiro para um vetor com os enderecos dos 00157 * servidores. 00158 * Cada endereco e composto pelo IP do servidor e pela porta UDP usada 00159 * por ele. 00160 * @param ServerAddressSize tamanho do vetor com os enderecos dos 00161 * servidores. 00162 * @return 0 se a thread foi criada com sucesso, e diferente de 0 se 00163 * algum erro ocorreu ao criar a thread. 00164 */ 00165 int CreateKeepaliveThread( void ); 00166 /** 00167 * IsBehindNAT esta funcao retorna true se o cliente estiver atras de um 00168 * NAT, caso a funcao RequestMapping tenha sido chamada pelo cliente 00169 * para obter o mapeamento, e false caso o cliente nao esteja atras do 00170 * NAT ou se a funcao RequestMapping nao tenha sido chamada. 00171 * @return true se o cliente esta atras de NAT, ou false se ele nao esta 00172 * atras de NAT ou se a funcao RequestMapping nao foi chamada. 00173 */ 00174 bool IsBehindNAT(); 00175 00176 /** 00177 * RequestMultipleMappings faz requisicao a outros objetos NetMgr, 00178 * pedindo o mapeamento, isto e, o endereco IP e a porta visivel por 00179 * este objeto. Os outros objetos estao executando em maquinas com 00180 * endereco IP e porta dados no primeiro parametro da funcao. Esta 00181 * funcao deve ser chamada apos a inicializacao do socket, isto e, 00182 * somente apos a funcao Start ter sido executada. A funcao de callback 00183 * passada como parametro e chamada apos um mapeamento ter sido 00184 * recebido. 00185 * @param addr vetor de enderecos IP e portas dos objetos NetMgr. 00186 * @param size quantidades de objetos NetMgr. 00187 */ 00188 void RequestMultipleMappings( struct sockaddr_in *addr, 00189 int size ); 00190 /** 00191 * RequestMapping faz uma requisicao a um outro objeto NetMgr, pedindo o 00192 * mapeamento, isto e, o endereco IP e a porta visivel por este objeto. 00193 * O outro objeto esta executando em uma maquina com endereco IP e porta 00194 * dados pelos parametros da funcao. Esta funcao deve ser chamada apos a 00195 * inicializacao do socket, isto e, somente apos a funcao Start ter sido 00196 * executada. A funcao de callback passada como parametro e chamada apos 00197 * um mapeamento ter sido recebido. 00198 * @param ipaddr endereco IP do objeto NetMgr. 00199 * @param port porta do objeto NetMgr. 00200 */ 00201 void RequestMapping( int ipaddr, int port ); 00202 00203 /** 00204 * Funcao para definir o objeto (do tipo CLogRotation) a ser usado para 00205 * armazenas as estatisticas de envio de pacotes. 00206 * @param LogRotation ponteiro para um objeto do tipo CLogRotation. 00207 */ 00208 void setLogRotation( CLogRotation *LogRotation ); 00209 /** 00210 * Nova chamada para usar a funcao ExpectCmd da RioNeti. 00211 * @param callback callback a ser chamada quando o objeto NetBuf criado 00212 * for removido. 00213 * @param callbackparm parametro a ser passado a callback. 00214 * @param cmdcallback callback a ser chamada quando recebermos a 00215 * resposta com o tamanho do arquivo de busca e o identificador deste 00216 * arquivo. 00217 * @return Identificador do NetBuf usado para receber a mensagem com 00218 * o tamanho do arquivo de busca e o identificador deste arquivo. 00219 */ 00220 int ExpectCmd( callback_t callback, void *callbackparm, 00221 cmdcallback_t cmdcallback ); 00222 /** 00223 * Esta funcao, que antes era private na RioNeti, agora passou a ser 00224 * public para permitir que enviemos um erro para cancelar um pedido 00225 * pendende. Isso ocorrera quando, ao cliente solicitar uma busca nos 00226 * logs do servidor, pedir ou um bloco que um arquivo com os resultados 00227 * de uma busca cuja identificacao nao existe, ou se pedir um bloco 00228 * invalido deste arquivo. A funcao foi criada na NetMgr para permitir 00229 * acessarmos a funcao correspondente da RioNeti. 00230 * @param ipaddr endereco IP para onde deveremos enviar o codigo de 00231 * erro. 00232 * @param port porta para onde deveremos enviar o codigo de erro. 00233 * @param reqid identificacao do NetBuf que desejamos enviar o erro. 00234 * @param result codigo de erro a ser enviado. 00235 */ 00236 void SendRst( int ipaddr, int port, int reqid, int result ); 00237 00238 private: 00239 RioNeti *d_neti; 00240 cmdcallback_t d_cmdproc; 00241 void *d_cmdparm; 00242 int d_myip; 00243 int d_myport; 00244 int d_seq; 00245 00246 bool serverInstance; 00247 00248 CSemaphore *m_semalidmap; /* Semaforo para bloquear a funcao 00249 Connect ate os campos m_ipaddrmap, 00250 m_ipportmap e m_behindnat da classe 00251 RioNeti se tornarem validos. */ 00252 00253 static void mycmdproc(void *cmdparm, char *cmdp, int cmdl); 00254 static void getblockcbx(void *parm, int result); 00255 static void getblockcb1(void *parm, int result); 00256 static void getblockcb2(void *parm, int result); 00257 static void sendresultcb(void *parm, int result); 00258 static void expecttellcom(void *parm); 00259 static void expecttellcmplt(void *parm, int result); 00260 static void expecttellsend(void *parm, int result); 00261 static void expecttellcmd(void *parm, char *pktp, int pktl); 00262 00263 /** 00264 * CallbackRequestMapping: funcao callback usada para liberar o semaforo 00265 * quando a operacao de pedido de mapeamento ao servidor (iniciada pela 00266 * chamada a funcao RequestMapping da classe NetMgr) estiver finalizada. 00267 * Ela e chamada quando a mensagem de requisicao e corretamente enviada 00268 * e quando o ACK desta mensagem, com o mapeamento, chega com sucesso ao 00269 * cliente. 00270 * @param param ponteiro para a instancia do objeto da classe NetMgr 00271 * bloqueado na funcao RequestMapping. 00272 * @param result nao e usado pela implementacao da callback, mas e 00273 * necessario defini-lo pois todas as callbacks devem ter a mesma 00274 * interface. 00275 */ 00276 static void CallbackRequestMapping( void *param, int result ); 00277 00278 #ifdef WINDOWS 00279 // Windows implementation 00280 HANDLE d_seqlock; 00281 #else 00282 // Linux implementation 00283 pthread_mutex_t d_seqlock; 00284 #endif 00285 }; 00286 #endif // __NETMGR_H_