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 // RioNeti.h: headers for RioNeti.cpp 00022 // Internet UDP interface layer under NetMgr.cpp (in future called RioNet.cpp) 00023 ////////////////////////////////////////////////////////////////////////////// 00024 00025 #ifndef __RIOINET_H_ 00026 #define __RIOINET_H_ 00027 00028 #include <stdlib.h> 00029 #include <stddef.h> 00030 #include <assert.h> 00031 #include <errno.h> 00032 #include <stdio.h> 00033 #include <iostream> 00034 #include <time.h> 00035 #include <signal.h> 00036 #include <sys/types.h> 00037 #include <memory.h> 00038 #include <sys/stat.h> 00039 #include <fcntl.h> 00040 00041 /* Simulation */ 00042 #include <fstream> 00043 00044 #include <queue> 00045 #include <map> 00046 00047 #ifdef WINDOWS 00048 /* Windows implementation */ 00049 #include <winsock2.h> 00050 #define Req 8 // Used in variable reqarray 00051 #else 00052 /* Linux implementation */ 00053 #include <sys/time.h> 00054 #include <sys/socket.h> 00055 #include <netinet/in.h> 00056 #include <unistd.h> 00057 #include <arpa/inet.h> 00058 #include <sys/ioctl.h> 00059 #include <netdb.h> 00060 #include <pthread.h> 00061 #include <limits.h> 00062 #endif 00063 00064 #include "NetMgr.h" /* needs callback_t & cmdcallback_t */ 00065 #include "td4types.h" 00066 #include "td4list.h" 00067 #include "BufferStream.h" 00068 #include "RioInterfaceTypes.h" 00069 #include "RioError.h" 00070 #include "StreamControl.h" // Unidade com a classe de controle de fluxo. 00071 #include "RioSemaphore.h" 00072 #include "LogRotation.h" // Unidade com a classe que controla os logs. No caso 00073 // da classe RioNeti, este log armazenara os dados 00074 // enviados 00075 00076 using namespace std; 00077 00078 #define MONITORPORT 42376 00079 #define STORAGEPORT 42377 00080 00081 #define MULTICAST_SOCKETS 2 ///Informa o n�mero de sockets multicasts do vetor 00082 ///multicastInfo. 00083 00084 #define CHUNK_INTERVAL 270 00085 00086 #define RESULT_NETIREQT_SEARCH_NULL_REFERENCE 0x01 00087 #define RESULT_NETIREQT_SEARCH_EMPTY_LIST 0x02 00088 #define RESULT_NETIREQT_SEARCH_NOT_FOUND 0x03 00089 #define RESULT_NETIREQT_SEARCH_FOUND 0x00 00090 00091 #define RESULT_NETIREQT_INSERT_ALREADY_EXIST 0x01 00092 #define RESULT_NETIREQT_INSERT_ERROR 0x02 00093 #define RESULT_NETIREQT_INSERT_OK 0x00 00094 00095 #define RESULT_NETIREQT_REMOVE_ERROR 0x02 00096 #define RESULT_NETIREQT_REMOVE_NOT_FOUND 0x03 00097 #define RESULT_NETIREQT_REMOVE_OK 0x00 00098 00099 // Constante que define o intervalo entre dois blocos de mensagens Fake usadas 00100 // para manter ativos os enderecos (IP, porta) dos servidores associados ao 00101 // mapeamento, se estivermos atras de NAT. 00102 #define FAKEMSGINTERVAL 3000000 00103 00104 struct MulticastInfo 00105 { 00106 int socket; 00107 struct sockaddr_in myaddr_in; 00108 struct sockaddr_in remoteaddr_in; 00109 00110 //isConnected[i] diz se multicastInfo[i].socket est� conectado 00111 bool isConnected; 00112 }; 00113 00114 class BufferStream; 00115 00116 class RioNetiReqIdItemData 00117 { 00118 private: 00119 int p_reqid; 00120 int l_reqid; 00121 char *buf; 00122 00123 public: 00124 RioNetiReqIdItemData( int p_reqid = 0, int l_reqid = 0 ); 00125 00126 void SetPreqid( int p_reqid ); 00127 void SetLreqid( int l_reqid ); 00128 void SetBuf( char *buf ); 00129 int GetPreqid(); 00130 int GetLreqid(); 00131 char *GetBuf(); 00132 }; 00133 00134 class RioNetiReqIdItem : public RioNetiReqIdItemData 00135 { 00136 private: 00137 RioNetiReqIdItem *next; 00138 00139 public: 00140 RioNetiReqIdItem( int p_reqid = 0, int l_reqid = 0 ); 00141 RioNetiReqIdItem *GetNext(); 00142 00143 void SetNext( RioNetiReqIdItem *next ); 00144 }; 00145 00146 class RioNetiReqIdTable 00147 { 00148 protected: 00149 RioNetiReqIdItem *first; 00150 void SetFirst( RioNetiReqIdItem *first ); 00151 00152 public: 00153 RioNetiReqIdTable(); 00154 RioNetiReqIdItem *GetFirst(); 00155 00156 int Insert( RioNetiReqIdItem *item ); 00157 int Remove( int p_reqid ); 00158 00159 /** 00160 * Search varre a tabela de requisi��es multicasts procurando o elemento que 00161 * tenha o p_reqid igual ao p_reqid fornecido como par�metro. Retorna em 00162 * current um ponteiro para este item e em previous um ponteiro para o item 00163 * anterior da lista. 00164 */ 00165 int Search( int p_reqid, RioNetiReqIdItem **current, 00166 RioNetiReqIdItem **previous ); 00167 00168 /** 00169 * SearchL varre a tabela de requisi��es multicasts procurando o elemento que 00170 * tenha o l_reqid igual ao l_reqid fornecido como par�metro. Retorna em 00171 * current um ponteiro para este item e em previous um ponteiro para o item 00172 * anterior da lista. 00173 */ 00174 int SearchL( int l_reqid, RioNetiReqIdItem **current, 00175 RioNetiReqIdItem **previous ); 00176 }; 00177 00178 // Nova estrutura usada para obter os mapeamentos. 00179 00180 struct NATMappingInfo 00181 { 00182 int reqid; 00183 int IP; 00184 int port; 00185 bool IsEnabled; 00186 }; 00187 00188 class RioNeti 00189 { 00190 /* This whole class only used by NetMgr (RioNet) */ 00191 enum call_type 00192 { 00193 TYPE_RST, 00194 TYPE_CMD, 00195 TYPE_RESULT, 00196 TYPE_ACK, 00197 TYPE_FRAG, 00198 TYPE_FRAGACK, 00199 TYPE_TIMEOUT, 00200 TYPE_CANCEL, 00201 TYPE_SENDMAP, 00202 TYPE_MAPACK 00203 }; 00204 00205 private: 00206 unsigned int numPkts; 00207 pthread_t mThread; 00208 int m_debug; 00209 RioNetiReqIdTable *reqid_table; /*reqid_table � a tabela que cont�m 00210 informa��es dos blocos multicasts 00211 em processo de recebimento. Quando 00212 um fragmento multicast novo chega, 00213 um registro para ele � criado nesta 00214 tabela. Este registro � removido 00215 assim que o �ltimo fragmento deste 00216 bloco chega ou quando a FreeBlock � 00217 chamada para recuperar estes 00218 fragmentos que j� chegaram.*/ 00219 BufferStream *buffer_stream; 00220 callback_t callback; 00221 RioCallBackTransport *callback_transport; 00222 00223 bool serverInstance; 00224 00225 /* This Matrix associate Multicast reqid with local reqid */ 00226 int max_in_set; 00227 00228 struct MulticastInfo multicastInfo[ MULTICAST_SOCKETS ]; 00229 pthread_mutex_t socketMulticastMutex; //este mutex protege a struct 00230 //multicastInfo contra acessos concorrentes 00231 //evitando incoer�ncias durante manipula��o de 00232 //seu conte�do e manipula��o dos sockets dos 00233 //quais armazena informa��es. 00234 struct sockaddr_in myAddress; 00235 00236 #ifdef WINDOWS 00237 /* Windows implementation */ 00238 /* Variables initialized in RioNeti.cpp */ 00239 static const int DEBUG_CNT; 00240 static const int DEBUG_FRAG; 00241 static const int DEBUG_TIM; 00242 static const int DEBUG_DATA; 00243 static const int DEBUG_CMDS; 00244 static const int DEBUG_MISC; 00245 static const int DEBUG_MORE; 00246 static const int DEBUG_TIMEOUT; 00247 SOCKET m_sock; 00248 HANDLE m_thread; 00249 HANDLE HashMutex; 00250 HANDLE m_buf_lock; 00251 HANDLE m_dns_lock; 00252 HANDLE m_time; 00253 00254 // Variaveis da implementacao TCP 00255 HANDLE m_TcpLock; // Lock das estruturas TCP 00256 HANDLE m_TcpServerThread; // ID da Thread do servidor TCP 00257 00258 SYSTEMTIME pSystemTime; 00259 static const int TimeShift; 00260 static const int XM_REQBITS; 00261 static const int XM_REQNUM; 00262 static const int XM_REQMASK; 00263 #else 00264 /* Linux implementation */ 00265 static const int DEBUG_CNT = (1 << 0); 00266 static const int DEBUG_FRAG = (1 << 2); 00267 static const int DEBUG_TIM = (1 << 3); 00268 static const int DEBUG_DATA = (1 << 4); 00269 static const int DEBUG_CMDS = (1 << 5); 00270 static const int DEBUG_MISC = (1 << 6); 00271 static const int DEBUG_MORE = (1 << 8); 00272 static const int DEBUG_TIMEOUT = (1 << 10); 00273 int m_sock; 00274 pthread_t m_thread; 00275 pthread_mutex_t HashMutex; 00276 pthread_mutex_t m_buf_lock; 00277 pthread_mutex_t m_dns_lock; 00278 00279 // Variaveis da implementacao TCP 00280 pthread_mutex_t m_TcpLock; // Lock das estruturas TCP 00281 pthread_t m_TcpServerThread; // ID da Thread do servidor TCP 00282 00283 static const int TimeShift = 10; 00284 static const int XM_REQBITS = 8; 00285 static const int XM_REQNUM = (1 << XM_REQBITS); 00286 static const int XM_REQMASK = (XM_REQNUM-1); 00287 #endif 00288 00289 int m_ipaddr; /* my IP address in net byte order */ 00290 int m_ipport; /* my port in net byte order */ 00291 int *m_ipaddrmap; /* my NAT IP addresses in net byte order 00292 */ 00293 int *m_ipportmap; /* my NAT ports in net byte order */ 00294 bool m_behindnat; /* Define se o cliente esta ou nao atras 00295 de um NAT. */ 00296 pthread_t m_threadmap; /* Identificacao da thread usada para 00297 manter ativos os mapeamentos dos 00298 servidores usados pelo NAT. */ 00299 struct NATMappingInfo *m_MappingInfo; /* Vetor usado para sabermos a 00300 qual servidor esta associado 00301 um mapeamento retornado ao 00302 cliente. */ 00303 unsigned int m_MappingInfoSize; /* Numero de entradas no 00304 vetor m_MappingInfo. */ 00305 00306 int m_maxpktl; /* max UDP pkt size of other! */ 00307 int m_maxdiskl; /* max disk block size */ 00308 int m_threadstop; 00309 int m_toaddrl; 00310 int m_fraddrl; 00311 cmdcallback_t m_cmdproc; 00312 void *m_cmdparm; 00313 struct sockaddr_in m_fraddr; 00314 struct sockaddr_in m_toaddr; 00315 int cnt_sndpkt; 00316 int cnt_rcvpkt; 00317 int cnt_retry; 00318 int cnt_rst1; 00319 int cnt_rst2; 00320 int cnt_rcvfragack; 00321 int cnt_rcvfragacknc; 00322 int err_dupfrag; 00323 int err_overfrag; 00324 int err_pktsize; 00325 int err_pktmagic; 00326 int err_pktnoreq; 00327 int err_pktcmd; 00328 int err_pktfmt; 00329 int xm_rstsec; 00330 int xm_rstip; 00331 int xm_rstport; 00332 int xm_rstreqid; 00333 NetBuf *m_cmpltf; /* completion queue */ 00334 NetBuf *m_cmpltl; 00335 NetBuf *m_outqf; /* output queue */ 00336 NetBuf *m_outql; 00337 struct timeval xm_now; /* current time */ 00338 struct timeval next; /* time next timer event */ 00339 fd_set *writefdsp; /* @ writefds or NULL */ 00340 fd_set readfds; /* select read bits */ 00341 fd_set writefds; /* select write bits */ 00342 NetBuf *mbc_free; /* free buffer list */ 00343 int mbc_num; /* number to get at once */ 00344 int reqseq; 00345 NetBuf *reqarray[ XM_REQNUM ]; 00346 00347 //o seguinte membro estático também deve ser declarados no arquivo 00348 //RioNeti.cpp, fora da classe RioNeti 00349 #ifdef RIO_DEBUG_FILE 00350 static ofstream m_log; 00351 #else 00352 static debugCerr m_log; 00353 #endif 00354 //para contabilizar fragmentos atrasados 00355 #ifdef RIO_EMUL 00356 int atrasados; 00357 #endif 00358 00359 struct Log_Arrival 00360 { 00361 int Block; 00362 struct timeval block_arrival; 00363 }; 00364 00365 // Nova variavel para armazenar o ponteiro para a classe que faz 00366 // o controle de fluxo 00367 CStreamControl *m_StreamControl; 00368 00369 // Nova variavel usada para armazenas o trafego enviado por um objeto 00370 // da classe RioNeti. 00371 CLogRotation *m_LogRotation; 00372 00373 void HashMutexLock( string msg = "" ); 00374 void HashMutexUnlock( string msg = "" ); 00375 00376 /* Delayed output queue functions */ 00377 void iOutAdd( NetBuf *nbp, void ( *outrtn )( NetBuf * ) ); 00378 void iOutAddTop( NetBuf *nbp, void ( *outrtn )(NetBuf * ) ); 00379 void iOutRmv( NetBuf *nbp ); 00380 00381 /* Reqid hash table functions */ 00382 void iHashNew( NetBuf *nbp ); 00383 void iHashRmv( NetBuf *nbp ); 00384 NetBuf *iHashFind( int reqid ); 00385 NetBuf *iHashFindRst( int ip, int port, int reqid ); 00386 void prtHash( const char * ); 00387 void SetTTLValue ( int socket, char ttl ); 00388 void SetLoopBack ( int socket, char loop ); 00389 00390 /** 00391 * JoinGroup envia uma mensagem pra rede (roteadores) informando que o 00392 * socket multicast de �ndice sockIndex deseja entrar no grupo multicast 00393 * indicado em multicastInfo[sockIndex].myaddr_in. 00394 * Nota: Este m�todo n�o precisa usar SocketMulticastLock() nem 00395 * SocketMulticastUnlock() pois est� sendo chamado pela SetMulticastSocket() 00396 * que j� faz as respectivas chamadas. 00397 * @param sockIndex indice que indica a posicao do socket no vetor 00398 * multicastInfo a ser manipulado. 00399 * @param group_addr endere�o no grupo a que este socket deve se unir. 00400 */ 00401 void JoinGroup ( int sockIndex, char* group_addr ); 00402 NetBuf *pSend( int ipadr, int port, int reqid, call_type type ); 00403 void qSend( NetBuf *nbp ); 00404 // A funcao iSend sera alterada para chamar ou a funcao nbSend, que 00405 // contera o codigo original da iSend, caso o objeto m_StreamControl 00406 // para o controle do fluxo nao tenha sido criado, ou chamara a funcao 00407 // Put do objeto m_StreamControl caso o controle de fluxo esteja ativo. 00408 // Neste caso, posteriormente a funcao nbSend sera chamada pela thread 00409 // que controla o fluxo de saida do objeto m_StreamControl, fazendo 00410 // com que o objeto NetBuf seja efetivamente enviado pela rede. 00411 /** 00412 * iSend funcao para enviar um objeto NetBuf pela rede. Se o trafego ao qual o 00413 * objeto NetBuf pertence for de tempo real, e se foi definido um objeto para 00414 * controlar o fluxo de saida de objetos NetBuf, o objeto sera repassado para 00415 * o objeto m_StreamControl que controla o controle de fluxo. O objeto, neste 00416 * caso, sera enviado (via funcao scSend) respeitando-se o limite de trafego 00417 * do cliente e do servidor. Em caso contrario, a funcao nbSend (a antiga funcao 00418 * iSend) e chamada para enviar imediatamente o objeto NetBuf. 00419 * @param nbp ponteiro para o objeto NetBuf a ser enviado. 00420 * @result valor diferente de 0: ocorreu um erro ao enviar o objeto NetBuf. 00421 */ 00422 int iSend( NetBuf *nbp ); 00423 00424 static void fSend( NetBuf *nbp ); 00425 static void gSend( NetBuf *nbp ); 00426 static void iSendFrag( NetBuf *nbp ); 00427 void iSendFragBuild( NetBuf *nbp, int fragnum ); 00428 int iSendFragNext( NetBuf *nbp); 00429 static void iSendFragAck( NetBuf *nbp ); 00430 void iSendAck( int ipaddr, int port, int reqid ); 00431 00432 /** 00433 * qComplete chama a CallBack do cliente indiretamente: seta vari�veis que a 00434 * NetMgrThread fica analisando continuamente em um loop de forma que a 00435 * NetMgrThread perceba que o bloco j� est� pronto para ser executado e, 00436 * consequentemente, chame a CallBack do cliente. 00437 * Coment�rio antigo: queue to run " user" level completion routine (w/o 00438 * lock held) // caller holds hash lock 00439 */ 00440 void qComplete( NetBuf *nbp, int result ); 00441 00442 int iRetry( NetBuf *nbp ); 00443 00444 /* Mutex handlers functions*/ 00445 /** 00446 * SocketMulticastLock trava o mutex socketMulticastMutex. 00447 * @param msg � usado apenas no modo RIO_DEBUG2 para facilitar depura��es de 00448 * clientes travados em mutex's. 00449 */ 00450 void SocketMulticastLock( string msg = "" ); 00451 00452 /** 00453 * SocketMulticastUnlock destrava o mutex socketMulticastMutex. 00454 * @param msg � usado apenas no modo RIO_DEBUG2 para facilitar depura��es de 00455 * clientes travados em mutex's. 00456 */ 00457 void SocketMulticastUnlock( string msg = "" ); 00458 00459 /* Timing functions */ 00460 /* Timing intervals are in units of 1 >> TimeShift seconds */ 00461 void iTimeNew( NetBuf *nbp, int interval ); 00462 void iTimeRmv( NetBuf *nbp ); 00463 NetBuf *mbget(); 00464 void mbfree( NetBuf *bf ); 00465 static void CleanupNetMgrThread( void * ); 00466 static void *NetMgrThreadEp( void *parm ); 00467 void NetMgrThread( void ); 00468 void restartreq( NetBuf * ); 00469 void procpkt( NetBuf **rcvbuf, 00470 RioStreamType traffic = UNICASTTRAFFIC ); 00471 void procpktrst( char *pktp, int pktl ); 00472 void procpktfrag( char *pktp, int pktl, 00473 RioStreamType traffic = UNICASTTRAFFIC ); 00474 void procpktfragack( char *pktp, int pktl ); 00475 static void sendcmdcb( NetBuf *nbp, int type, char *cmdp, int cmdl ); 00476 static void sendblockcb( NetBuf *nbp, int type, char *cmdp, int cmdl ); 00477 static void expectblockcb( NetBuf *nbp, int type, char *cmdp, 00478 int cmdl ); 00479 static void dummyusercb( void *parm, int result ); 00480 void dispsockopt( int ); 00481 void mucksockopt(int fd ); 00482 void prtcnt(); 00483 void prttim( const char *s ); 00484 void mbinit( int num ); 00485 void mbterm(); 00486 static void procretry( struct td4_tim * ); 00487 int FindMulticastReqid( int multicastreqid ); 00488 int InsertMulticastReqid( int multicastreqid, 00489 int localreqid ); 00490 int DeleteMulticastReqid( int localreqid ); 00491 DQUEUE(NetBuf) xm_timeq; 00492 int findNetInterface(); 00493 00494 // Funcao com o codigo da thread para enviar a intervalos fixos de 00495 // tempo (definido pela constante FAKEMSGINTERVAL), mensagens Fake 00496 // usadas para manter ativos os enderecos (IP, porta) dos servidores 00497 // associados ao mapeamento, se estivermos atras de NAT. 00498 /** 00499 * KeepaliveMapNAT funcao para a thread usada para enviar periodicamente 00500 * mensagens Fake aos servidores para garantir que os mapeamentos nao 00501 * serao expirados. 00502 * @param Param o parametro da thread que e um ponteiro para um objeto da 00503 * classe RioNeti executando o codigo da thread. 00504 */ 00505 static void *KeepaliveMapNAT( void * ); 00506 00507 // Funcao que envia um ACK especial ao cliente em resposta a mensagem 00508 // enviada pela chamada a funcao RequestMapping, que contém o IP e a 00509 // porta pela qual esta mensagem foi enviada. Usado para obter o 00510 // mapeamento do cliente se este estiver atras de um NAT. 00511 /** 00512 * iSendMapAck Envia um ACK de uma requisicao por mapeamento para o IP ipaddr 00513 * e a porta port. 00514 * Nota: esta funcao foi baseada no codigo da funcao iSendAck. 00515 * @param ipaddr endereco IP do objeto RioNeti para o qual desejamos enviar o 00516 * ACK. 00517 * @param port porta do objeto RioNeti para o qual desejamos enviar o ACK. 00518 * @param reqid identificador para a requisicao (como devemos inicializar 00519 */ 00520 void iSendMapAck( int ipaddr, int port, int reqid ); 00521 00522 public: 00523 RioNeti( bool serverInstance ); 00524 ~RioNeti(); 00525 00526 // Mudanca da funcao Start para passar mais dois parametros para o 00527 // controle do fluxo do servidor: MaxClientsCredits - numero maximo de 00528 // creditos para as tranferencias de fragmentos entre os clientes; 00529 // MaxNetworkCredits numero maximo de creditos para as tranferencias 00530 // dos fragmentos pela rede; e NetworkRate que define a taxa maxima de 00531 // transferencia dos dados. Um valor 0 em MaxClientsCledits, 00532 // MaxNetworkCredits ou NetworkRate (os valores default) indica que nao 00533 // queremos usar o controle de fluxo. 00534 #ifdef RIO_DEBUG_FILE 00535 // Mais um novo parametro foi adicionado a funcao Start se a opcao 00536 // RIO_DEBUG_FILE for usada: RioNetiLogPath, que informa o nome do 00537 // arquivo com o log da RioNeti. Ele foi colocado antes dos parametro e 00538 // do controle de fluxo e dos parametros devString e usleepInterval 00539 // porque estes parametros nao sao sempre usados. O valor default deste 00540 // parametro e NULL e, neste caso, o log sera armazenado do diretorio 00541 // do programa que executou a Start esta executando e tera o seguinte 00542 // nome: 00543 // RIOClientEmul_<maquina>.<dominio>.log se um dos clientes (riosh ou 00544 // riommclient) executou a funcao. 00545 // RIOServerEmul_<maquina>.<dominio>.log se o servidor de despacho 00546 // executou a funcao. 00547 // RIOStorageEmul_<maquina>.<dominio>.log se o servidor de armazenamento 00548 // executou a funcao. 00549 int Start( int port, int maxdiskl, int maxpktl, 00550 const char *RioNetiLogPath, 00551 unsigned int MaxClientsCredits, 00552 unsigned int MaxNetworkCredits, 00553 unsigned int NetworkRate ); 00554 #else 00555 int Start( int port, int maxdiskl, int maxpktl, 00556 unsigned int MaxClientsCredits, 00557 unsigned int MaxNetworkCredits, 00558 unsigned int NetworkRate ); 00559 #endif 00560 int Stop(); 00561 void allocMappingVectors( int size ); 00562 void getmyaddrport( int *ipaddr, int *port, int server = 0 ); 00563 void getalladdrport( int **ipaddr, int **port ); 00564 int getipaddr(); 00565 00566 /** 00567 *Este m�todo n�o est� sendo usado em lugar nenhum do c�digo 00568 */ 00569 void SetCmdProc( cmdcallback_t cmdproc, void *cmdparm ); 00570 00571 /** 00572 * SendCmd -- send a command to target ip/port multiple of these can be in 00573 * progress to the same target. The order of arrival at the target is NOT 00574 * specified and they can be duplicated too (so one SendCmd can result 00575 * in multiple ones being processed at the other side). 00576 */ 00577 void SendCmd( int ipadr, int port, int reqid, char *cmdp, 00578 int cmdl, callback_t callback, 00579 void *callbackparm ); 00580 // O novo parametro VideoRate foi adicionado. Ele define, caso 00581 // estejamos enviando trafego em tempo real (os videos) a taxa de 00582 // transmissao do video em Kbps. Como ele nao e usado por todas as 00583 // funcoes da NetMgr, ele possui um valor default de 0. 00584 // 00585 // Mais um parametro novo foi adicionado, com o valor default de NULL: 00586 // caso o valor passado seja diferente de NULL, o ponteiro para um 00587 // numero inteiro ira armazenar a reqid do NetBuf usado para copiar o 00588 // bloco. Este reqid sera usado para cancelar o envio do bloco se o 00589 // servidor de armazenamento deixar de funcionar. 00590 void SendData( int ipadr, int port, int reqid, char *bufadr, 00591 int buflen, callback_t callback, 00592 void *callbackparm, int StreamTraffic, 00593 unsigned int VideoRate = 0, 00594 unsigned int *sendreqid = NULL ); 00595 00596 /** 00597 * ExpectData - Establish an endpoint here for data to be sent to. 00598 * Returns the request id for this expecting endpoint. The callback 00599 * routine will be called once the data is in buf or if the operation 00600 * fails. 00601 * (could return whole endpoint info - ip, port, reqid, {?auth?}). 00602 * 00603 * There is no timeout on an ExpectData. The caller can use 00604 * CancelExpect to terminate an expect which isn't needed anymore. 00605 * 00606 * ### there is a timing window where a cancel expect could 00607 * cancel the wrong endpoint (endpoint ends normally 00608 * and a new one is created with the same reqid just 00609 * as a cancelexpect is done on the old == new reqid). 00610 * @bufadr eh um ponteiro para a regiao de memoria onde deve ser gravado o 00611 * bloco quando ele chegar. 00612 * @buflen eh o tamanho do buffer apontado pelo parametro bufadr 00613 * @param callback eh um ponteiro para a callback do cliente. 00614 * @param callbackparm eh um ponteiro para a RioRequest do cliente relativa a 00615 * este bloco. 00616 */ 00617 int ExpectData( char *buf, int len, callback_t callback, 00618 void *callbackparm, RioStreamType traffic, 00619 int sendack = 1 ); 00620 int ExpectCmd( callback_t callback, void *callbackparm, 00621 cmdcallback_t cmdcallback ); 00622 int CancelExpect( int reqid, int result ); 00623 void SendResult( int ipadr, int port, int reqid, int result, 00624 callback_t callback, 00625 void *callbackparm ); 00626 /** 00627 * Esta funcao, que antes era private, agora passou a ser public para 00628 * permitir que enviemos um erro para cancelar um pedido pendende. Isso 00629 * ocorrera quando, ao cliente solicitar uma busca nos logs do servidor, 00630 * pedir ou um bloco que um arquivo com os resultados de uma busca cuja 00631 * identificacao nao existe, ou se pedir um bloco invalido deste 00632 * arquivo. 00633 * @param ipaddr endereco IP para onde deveremos enviar o codigo de 00634 * erro. 00635 * @param port porta para onde deveremos enviar o codigo de erro. 00636 * @param reqid identificacao do NetBuf que desejamos enviar o erro. 00637 * @param result codigo de erro a ser enviado. 00638 */ 00639 void SendRst( int ipaddr, int port, int reqid, int result ); 00640 00641 /** 00642 * CreateMulticastSocket fecha o socket multicast indicado por sockIndex e abre um 00643 * novo socket multicast. Neste ponto n�o � dado FD_SET nem FD_CLR pois a 00644 * NetMgrThread faz isto antes de chamar select no seu loop. 00645 * Nota 1: Quem seta o socket com os atributos devidos � participa��o no grupo 00646 * multicast � o m�todo JoinGroup, que � chamado pelo m�todo 00647 * SetMulticastSocket, ambos desta mesma classe. 00648 * Nota 2: Este m�todo n�o precisa usar SocketMulticastLock() nem 00649 * SocketMulticastUnlock() pois est� sendo chamado pela SetMulticastSocket() 00650 * que j� faz as respectivas chamadas. 00651 * @param sockIndex indice de uma posicao livre no vetor multicastInfo a ser 00652 * usado para a criacao deste novo socket multicast. 00653 */ 00654 void CreateMulticastSocket( int sockIndex ); 00655 00656 /** 00657 * SetMulticastSocket cria um novo socket multicast com as informa��es 00658 * recebidas nos par�metros multicastport e multicast_addr. Para isto, 00659 * SetMulticastSocket varre a lista multicastInfo procurando uma posi��o 00660 * livre para criar o novo socket. Se uma posi��o livre n�o for encontrada, 00661 * este m�todo n�o cria o novo socket e retorna false. 00662 * Este m�todo � chamado na CommMulticastStream no momento em que recebe uma 00663 * mensagem do tipo MSGCODE_IP, que informa ao cliente que ele deve passar a 00664 * escutar um determinado fluxo multicast (JOIN_THIS). 00665 * @param multicastport n�mero da porta multicast a ser associada ao socket 00666 * que ser� criado. 00667 * @param multicast_addr ip multicast a ser associada ao socket que ser� 00668 * criado. 00669 * @param callback ponteiro para a fun��o de callback do cliente a ser 00670 * executada quando o bloco chega. Por default � igual a NULL. 00671 * @param buffer_stream ponteiro para a buffer_stream, respons�vel pela 00672 * armazenagem e acesso aos blocos da stream de v�deo gravados no disco. Por 00673 * default � igual a NULL. 00674 * Por default: *callback = 0, *buffer_stream = 0 e enable_join = 1. 00675 */ 00676 bool SetMulticastSocket( unsigned short multicastport, 00677 char* multicast_addr, 00678 void *callback = 0, 00679 BufferStream *buffer_stream = 0, 00680 int enable_join = 1 ); 00681 00682 /** 00683 * LeaveGroup descobre a qual membro da matriz multicastInfo o par�metro 00684 * multicastport est� associado e fecha o socket respectivo, limpando os 00685 * demais membros desta estrutura. 00686 */ 00687 void LeaveGroup( unsigned short multicastport ); 00688 00689 void LeaveAllGroups( void ); 00690 00691 /** 00692 * FreeBlock recupera os fragmentos dispon�veis do bloco indicado pelo par�metro 00693 * block_id para exibi��o imediata no cliente. Liberado o bloco, a callback do 00694 * cliente � chamada e o bloco � gravado no PlayOutBuffer para uso do player e, 00695 * caso a op��o usecache esteja habilitada, o bloco � gravado na cache (no 00696 * disco). 00697 * @param block_id � a identifica��o do bloco cujos fragmentos, caso existam, 00698 * ser�o liberados. 00699 * @param traffic indica se o bloco a ser recuperado � relativo a um tr�fego 00700 * multicast(traffic == MULTICASTTRAFFIC) ou unicast(traffic == UNICASTTRAFFIC). 00701 * @return retorna o tamanho em bytes do bloco recuperado. 00702 */ 00703 int FreeBlock( unsigned int block_id, RioStreamType traffic ); 00704 00705 /** 00706 * FreePendentBlocks procura por blocos que come�aram a ser recebidos h� 00707 * bastante tempo mas que por perdas na rede n�o foram completamente 00708 * recebidos. Cada um destes blocos ser� liberado para uso independente do 00709 * n�mero de fragmentos que tenham chegado. Isto � feito para diminuir o 00710 * consumo de mem�ria. Em ambientes com muitas perdas e clientes altamente 00711 * interativos muitos blocos ficam pendentes pois os clientes interagem antes 00712 * de precisar deles e, portanto, n�o chamam a FreeBlock para tais blocos, 00713 * que ficam ocupando a mem�ria eternamente por estarem na lista de requisi��es 00714 * pendentes (tabela da NetBuf). Como os blocos com perdas nao sao gravados 00715 * na cache, entao todos os blocos que a FreePendentBlocks encontrar como 00716 * pendetes com tempo maximo de tolerancia excedido serao descartados. 00717 * @param usecache Informa se o cliente est� ou n�o usando cache em disco. 00718 * @param nbuffers Informa o tamanho do PlayOutBuffer do cliente. 00719 * @param traffic Informa se o bloco a ser recuperado � fruto de uma 00720 * requisi��o unicast ou multicast. Esta ionforma��o � �til para a 00721 * FreeBlock. 00722 * @return Retorno o total de bytes liberados/recuperados/descartados por este 00723 * m�todo. 00724 */ 00725 int FreePendentBlocks( bool useCache, int nBuffers ); 00726 00727 /** 00728 * thereAreFragments verifica se existem fragmentos do bloco block_id e retorna 00729 * true caso encontre algum fragmento para este bloco ou false caso contr�rio. 00730 * @param block_id indica o bloco que se quer recuperar os fragmentos. 00731 * @param traffic indica se o bloco foi requisitado em um pedido unicast ou 00732 * multicast. Dependendo da origem do pedido, o bloco � recuperado de uma ou 00733 * outra forma. 00734 * @return retorna true caso encontre algum fragmento para o bloco block_id ou 00735 * false caso n�o encontre nenhum fragmento para este bloco. 00736 */ 00737 bool thereAreFragments( RioBlock block ); 00738 #ifdef RIO_DEBUG2 00739 /** 00740 * printDebug foi criado para que se possa exibir na tela conte�do de vari�veis 00741 * membros e outros dados das classes RioNeti, RioObject, NetMgr e RioStream, 00742 * j� que a RioMMVideo n�o tem acesso direto aos respectivos dados destas 00743 * classes. 00744 */ 00745 void printDebug( short debugCode, string message = "" ); 00746 #endif 00747 00748 // Funcao para criar a thread descrita no codigo da classe, usada para 00749 // evitar que os enderecos associados a um mapeamento expirem. 00750 /** 00751 * CreateKeepaliveThread funcao para criar a thread usada para enviar 00752 * periodicamente mensagens Fake aos servidores para garantir que os 00753 * mapeamentos nao serao expirados por timeout. 00754 * @return 0 se a thread foi criada com sucesso, e diferente de 0 se 00755 * algum erro ocorreu ao criar a thread. 00756 */ 00757 int CreateKeepaliveThread( void ); 00758 00759 // Funcao que retorna true se o cliente estiver atras de NAT (somente 00760 // se a funcao RequestMapping for usada). 00761 /** 00762 * IsBehindNAT esta funcao retorna true se o cliente estiver atras de um NAT, 00763 * caso a funcao RequestMapping tenha sido chamada pelo cliente para obter o 00764 * mapeamento, e false caso o cliente nao esteja atras do NAT ou se a funcao 00765 * RequestMapping nao tenha sido chamada. 00766 * @return true se o cliente esta atras de NAT, ou false se ele nao esta atras 00767 * de NAT ou se a funcao RequestMapping nao foi chamada. 00768 */ 00769 bool IsBehindNAT(); 00770 00771 /** 00772 * RequestMapping faz uma requisicao a um outro objeto RioNeti, pedindo o 00773 * mapeamento, isto e, o endereco IP e a porta visivel por este objeto. 00774 * O outro objeto esta executando em uma maquina com endereco IP e porta dados 00775 * pelos parametros da funcao. Esta funcao deve ser chamada apos a 00776 * inicializacao do socket, isto e, somente apos a funcao Start ter sido 00777 * executada. A funcao de callback passada como parametro e chamada apos um 00778 * mapeamento ter sido recebido. 00779 * Nota: esta funcao foi baseada no codigo da funcao SendResult. 00780 * @param ipaddr endereco IP do objeto RioNeti. 00781 * @param port porta do objeto RioNeti. 00782 * @param callback funcao de callback a ser chamada quando a requisicao for 00783 * completada com sucesso e um mapeamento for retornado. 00784 * @param callbackparm parametro passado quando a callback e chamada. 00785 */ 00786 void RequestMapping( int ipaddr, int port, int server, 00787 callback_t callback, 00788 void *callbackparm ); 00789 00790 // Esta funcao e a antiga funcao iSend que envia o objeto NetBuf 00791 // especificado pelo primeiro parametro pela rede ou, se este primeiro 00792 // parametro for NULL, o objeto especificado pelos quatro outros 00793 // parametros. Neste ultimo caso, usado pelo objeto StreamControl de 00794 // controle do fluxo, o parametro FragmentData e um ponteiro para os 00795 // dados do fragmento a serem enviados, o FragmentSize e o tamanho 00796 // destes dados, o IP e o endereco para o qual deve ser enviado o 00797 // fragmento, e Port e a porta neste endereco para a qual devemos 00798 // enviar o fragmento. 00799 /** 00800 * nbSend funcao para enviar um objeto NetBuf pela rede (antiga funcao iSend), 00801 * se rp for diferente de NULL, e o fragmento dado pelos parametros de 2 ate 00802 * 5, se rp for igual a NULL. 00803 * @param rp ponteiro para o objeto NetBuf a ser enviado (caso seja diferente 00804 * de NULL). 00805 * @param FragmentData ponteiro para os dados do fragmento. Este parametro 00806 * tambem e somente usado pelo objeto de controle de fluxo. O valor default e 00807 * NULL, e isso indicara que as informacoes, passadas pelos parametros 00808 * FragmentData, FragmentSize, IP e Port deverao, como ocorria na funcao iSend 00809 * original, serem obtidos pelos campos nb_sendp, nb_sendl, nb_toipaddr e 00810 * nb_toipport do objeto NetBuf (que devera ser diferente de NULL). 00811 * @param FragmentSize tamanho dos dados passados pelo parametro 00812 * FragmentData. Tambem e somente usado pelo objeto de controle de fluxo, e o 00813 * seu valor default e de 0. 00814 * @param IP endereco IP para onde o fragmento deve ser enviado. Assim como 00815 * o parametro anterior, o valor default deste parametro e 0 e ele tambem e 00816 * usado pelo controle de fluxo. 00817 * @param Port porta no endereco IP acima para o qual o fragmento deve ser 00818 * enviado. Assim como antes, o valor defaulr sera de 0, e este parametro 00819 * somente sera usado pelo controle de fluxo. 00820 * @result valor diferente de 0: ocorreu um erro ao enviar o objeto NetBuf. 00821 */ 00822 int nbSend( NetBuf *rp, char *FragmentData = NULL, 00823 int FragmentSize = 0, int IP = 0, int Port = 0 ); 00824 /** 00825 * Funcao para definir o objeto (do tipo CLogRotation) a ser usado para 00826 * armazenas as estatisticas de envio de pacotes. 00827 * @param LogRotation ponteiro para um objeto do tipo CLogRotation. 00828 */ 00829 void setLogRotation( CLogRotation *LogRotation ); 00830 /** 00831 * Funcao para cancelar o pedido de um bloco, removendo ele das filas 00832 * internas e chamando a callback do cliente. 00833 * @param reqid identificador do bloco (o NetBuf). 00834 * @param result erro a ser passado a callback. 00835 * @returntrue se o cancelamento foi feito com sucesso, e fase caso a 00836 * reqid esteja associada a um bloco que nao existe. 00837 */ 00838 bool CancelCopyBlock( int reqid, int result ); 00839 }; 00840 00841 /* NetBuf only used internally in RioNeti (all private). */ 00842 class NetBuf /* Network buffer */ 00843 { 00844 #ifdef WINDOWS 00845 /* Windows implementation */ 00846 NetBuf() 00847 { 00848 const int RQ_BURSTSTART = 4; 00849 const int RQ_BURSTMIN = 4; 00850 const int RQ_BURSTMAX = 20; 00851 const int RQ_ACKEVERY = 4; 00852 const int RQ_MAXACKLIST = 10; 00853 }; 00854 00855 static const int RQ_BURSTSTART; 00856 static const int RQ_BURSTMIN; 00857 static const int RQ_BURSTMAX; 00858 static const int RQ_MAXACKLIST; /* max frag #'s in fragack */ 00859 static const int RQ_ACKEVERY; 00860 u16 rq_fraglist[10]; 00861 #else 00862 /* Linux implementation */ 00863 NetBuf(); 00864 static const int RQ_BURSTSTART = 4; 00865 static const int RQ_BURSTMIN = 4; 00866 static const int RQ_BURSTMAX = 20; 00867 static const int RQ_MAXACKLIST = 10; /* max frag #'s in fragack */ 00868 static const int RQ_ACKEVERY = 4; 00869 u16 rq_fraglist[RQ_MAXACKLIST]; 00870 #endif 00871 00872 NetBuf *nb_link; /* hash collision link (& other link) */ 00873 int nb_reqid; /* hash key (request id) */ 00874 struct timeval nb_tiwhen; /* timer event time */ 00875 /* Sending */ 00876 int rq_fragsh; /* high frag sent */ 00877 int rq_fragburst; /* num of frags to send in burst */ 00878 int rq_burstcnt; /* frags left to send in burst */ 00879 NetBuf *nb_outnext; /* next on output queue (or 0) */ 00880 int rq_fraglistn; /* index into fraglist past last used */ 00881 00882 /* Receiving (& common) */ 00883 int nb_sendack; /* 1 if send ack */ 00884 int nb_hisreqid; /* other sides reqid */ 00885 time_t nb_frag0arrive; /* hour of fragment 0 arriving */ 00886 bool nb_unicastRequested; /* true if this block cames from an 00887 unicast request or false if it cames 00888 from a multicast request*/ 00889 int rq_maxpktl; /* max pkt size (includes IP UDP 00890 hdrs)*/ 00891 int rq_fraglen0; /* max frag 0 len */ 00892 int rq_fraglen; /* max frag len (all but last) */ 00893 int rq_fragmax; /* exact # of fragments needed */ 00894 int rq_fraghav; /* fragments already have */ 00895 int rq_fragDiscarded; /* fragments discarded by RioNeti */ 00896 int rq_fraghigh; /* highest frag # have */ 00897 int rq_fraglow; /* highest contig frag # have */ 00898 int rq_needack; /* need to send ack if > 0 */ 00899 int rq_fragackseq; /* next fragack seq to use */ 00900 int rq_retry; /* current retry count (cnts down)*/ 00901 int rq_retryfrag; /* last fraghav on timeout */ 00902 int rq_retrytim; /* retry time out */ 00903 char rq_bits[256]; /* fraq rcvd bytes */ 00904 u32 nb_result; 00905 RioNeti *nb_rioneti; 00906 char *nb_blockp; /* user supplied @ block tgt */ 00907 int nb_blockl; /* and user supplied len */ 00908 int nb_toipaddr; /* to IP addr (net order) */ 00909 int nb_toipport; /* to IP port (net order) */ 00910 char *nb_bufp; /* @ buf for send/receive */ 00911 int nb_bufl; /* length of buf */ 00912 int nb_recvl; /* received length */ 00913 char *nb_datap; 00914 char *nb_datalm; 00915 char *nb_sendp; 00916 int nb_sendl; /* send length */ 00917 char nb_buf[FRAGMENTSIZE]; /* buf for data */ 00918 void *nb_userparm; 00919 callback_t nb_usercall; 00920 cmdcallback_t nb_usercmd; 00921 00922 ~NetBuf() {}; 00923 DQUEUE( NetBuf ) nb_tidq; /* timer event queue */ 00924 void ( *nb_outrtn )( NetBuf * ); // delayed output rtn (0 if not on q) 00925 00926 /* following called when pkt arrives, timer, or complete/fails */ 00927 /* with hash lock held (and must not release) */ 00928 #ifdef WINDOWS 00929 /* Windows implementation */ 00930 void (*nb_callback)(NetBuf *, int type, char *pkt, int pktl); 00931 #else 00932 /* Linux implementation */ 00933 void (*nb_callback)(struct NetBuf *, int type, char *pkt, int pktl); 00934 #endif 00935 00936 unsigned long long int nb_timebetweencredits; // Tempo (em microsegundos) 00937 // entre as atualizacoes de 00938 // creditos. 00939 // Nova parte publica que define as funcoes para extrair as informacoes 00940 // do objeto NetBuf usadas pela classe StreamControl para o controle de 00941 // fluxo. 00942 public: 00943 // Funcao para obter os valores dos campos nb_toipaddr e nb_toipport. 00944 /** 00945 * GetIPAndPort retorna o ip (o campo nb_toipaddr) e a porta (o campo 00946 * nb_toipport). 00947 * @param ip ponteiro para o inteiro que armazenara o endereco IP. 00948 * @param port ponteiro para o inteiro que armazenara a porta. 00949 */ 00950 void GetIPAndPort( int *ip, int *port ); 00951 00952 // Funcao para obter o tempo entre as atualizacoes de creditos. 00953 /** 00954 * GetTimeBetweenCredits retorna o tempo entre as atualizacoes do credito do cliente 00955 * (do campo nb_timebetweencredits da classe). 00956 * @return tempo entre as atualizacoes de credito. 00957 */ 00958 unsigned long long int GetTimeBetweenCredits(); 00959 00960 // Funcao para obter as informacoes do fragmento. 00961 /** 00962 * GetFragmentInfo copia e retorna as informacoes de um fragmento do objeto 00963 * NetBuf. 00964 * @param FragmentData ponteiro para um ponteiro que armazenara uma copia dos 00965 * dados a serem enviados. 00966 * @param FragmentSize ponteiro que armazenara o tamanho dos dados a serem 00967 * enviados 00968 * @return valor diferente de 0 se ocorrer erro de alocacao de memoria. 00969 */ 00970 int GetFragmentInfo( char **FragmentData, int *FragmentSize ); 00971 00972 friend class RioNeti; 00973 }; 00974 00975 #endif // _RIOINET_H__