#include <NetTcp.h>
Public Member Functions | |
CNetTcp (CNetInterface *NetInterface) | |
Construtor da classe, usado para criar um novo objeto da classe. | |
~CNetTcp () | |
Destrutor da classe, usado para deletar um objeto criado anteriormente. | |
RioResult | Start (SNetTcpConfig *NetConfig) |
Funcao para inicializar a classe. | |
RioResult | Stop () |
Funcao para parar o funcionamento do object (isto e, fechar todas as conexoes TCP e terminar todas as threads). | |
RioResult | SendData (int IP, int Port, char *Data, unsigned int DataSize, void *Param) |
Funcao para enviar dados para a maquina identificada nos parametros. | |
RioResult | GetIPAndPort (int *IP=NULL, int *Port=NULL, unsigned int Server=0) |
Funcao para retornar o par IP, Porta associada a uma conexao com o servidor definido pelo parametro server. | |
RioResult | GetAllIPsAndPorts (int **IPs, int **Ports) |
Funcao para retornar um ponteiro para o vetor interno que armazena os IPs e as portas. | |
RioResult | FindIPAndPort (int IP, int Port, bool *isFound) |
Funcao para verificar se um dado par IP, Porta esta ou nao associado a uma conexao do objeto desta classe. | |
void | setLogRotation (CLogRotation *LogRotation) |
Funcao para definir o objeto (do tipo CLogRotation) a ser usado para armazenar as estatisticas de envio de pacotes. | |
void | ProcessData (int IP, int Port, char *Data, unsigned int DataSize) |
Esta funcao e chamada pelo objeto de uma das classes de rede ao receber dados pela rede. | |
void | SendDataCompleted (int IP, int Port, void *Param) |
Esta Funcao sera chamada pelo objeto de uma das classes de rede quando os dados tiverem sido enviados para um endereco (com ou sem sucesso). | |
void | ProcessError (int IP, int Port, RioResult RioError, const char *Msg, EErrorType ErrorType, void *Param) |
Esta funcao e chamada quando algum erro ocorrer com a transferencia de dados. | |
void | ConnectionClosed (int IP, int Port, EClosedType ClosedType) |
Esta funcao e chamada pelo objeto de uma das classes de rede quando a conexao com o par IP, port for fechada. | |
Private Member Functions | |
void | GetKey (int IP, int Port, char *Key) |
Funcao para retornar a chave do mapa associada a um dado par IP,porta. | |
RioResult | NewConnection (int IP, int Port, int Socket, CTcpConnection **TcpConnection) |
Funcao para criar um novo objeto para uma nova conexao TCP. | |
RioResult | EnableConnection (CTcpConnection *TcpConnection) |
Funcao para habilitar o uso da conexao TCP passada como parametro. | |
CTcpConnection * | TcpAccept (int ClientSocket, int ClientIP, int ClientPort) |
Funcao executada, pelo servidor, para inicializar e, se nao ocorrer um erro, aceitar definitivamente uma conexao TCP criada com o cliente. | |
CTcpConnection * | TcpConnect (int ServerIP, int ServerPort, int *ClientIP, int *ClientPort) |
Funcao para estabelecer uma conexao TCP com um dos servidores. | |
void | TcpServerThread (void) |
Funcao que efetivamente executa o codigo da thread servidora do TCP, chamada pela funcao TcpServerThreadEp (esta funcao e usada para facilitar o acesso aos campos do objeto). | |
RioResult | CloseAllConnections () |
Funcao para fechar todas as conexoes TCP ativas, enviando ao outro lado da conexao uma mensagem de que a conexao foi finalizada. | |
RioResult | SendDataPrivate (CTcpConnection *TcpConnection, char *Data, unsigned int DataSize, void *Param) |
Funcao para enviar dados para a maquina identificada nos parametros. | |
Static Private Member Functions | |
static void * | TcpServerThreadEp (void *ThreadParam) |
Funcao que trata da execucao do codigo da thread servidora do TCP (somente para os servidores). | |
Private Attributes | |
bool | m_Started |
CNetInterface * | m_NetInterface |
pthread_t | m_TcpServerThreadId |
bool | m_ServerInstance |
bool | m_TcpServerStarted |
bool | m_CancelThreads |
CLogRotation * | m_LogRotation |
unsigned int | m_ReceiveTimeOut |
unsigned int | m_SendTimeOut |
time_t | m_ConnectionTimeOut |
int | m_TcpServerSocket |
int | m_IP |
int | m_TcpServerPort |
struct sockaddr_in * | m_ServerAddress |
int * | m_ClientIPAddress |
int * | m_ClientPorts |
unsigned int | m_AddressSize |
pthread_cond_t | m_Cond |
pthread_mutex_t | m_Mutex |
TTcpConnectionsMap | m_TcpConnectionsMap |
Definition at line 399 of file NetTcp.h.
CNetTcp::CNetTcp | ( | CNetInterface * | NetInterface | ) |
Construtor da classe, usado para criar um novo objeto da classe.
NetInterface | ponteiro para o objeto da classe CNetInterface responsavel pelo gerenciamento deste objeto. |
Definition at line 1992 of file NetTcp.cpp.
01993 { 01994 // Atribui o ponteiro para a classe de gerenciamento de rede. 01995 m_NetInterface = NetInterface; 01996 01997 #ifdef RIO_DEBUG1 01998 RioErr << "[CNetTcp - Construtor] Start" << endl; 01999 #endif 02000 02001 // Inicializa as variaveis da classe. 02002 m_ServerInstance = false; 02003 m_ReceiveTimeOut = 0; 02004 m_SendTimeOut = 0; 02005 m_ConnectionTimeOut = 0; 02006 m_TcpServerThreadId = 0; 02007 m_Started = false; 02008 m_TcpServerStarted = false; 02009 m_CancelThreads = false; 02010 m_LogRotation = NULL; 02011 m_TcpServerPort = 0; 02012 m_ServerAddress = NULL; 02013 m_AddressSize = 0; 02014 m_ClientIPAddress = NULL; 02015 m_ClientPorts = NULL; 02016 // m_TcpConnectionsMap nao precisa ser inicializado. 02017 02018 // Inicializa o mutex e as variaveis de condicao. 02019 pthread_mutex_init( &m_Mutex, NULL ); 02020 pthread_cond_init( &m_Cond, NULL ); 02021 02022 #ifdef RIO_DEBUG1 02023 RioErr << "[CNetTcp - Construtor] Finish" << endl; 02024 #endif 02025 }
CNetTcp::~CNetTcp | ( | ) |
Destrutor da classe, usado para deletar um objeto criado anteriormente.
Definition at line 2028 of file NetTcp.cpp.
02029 { 02030 #ifdef RIO_DEBUG1 02031 TCPLOG << "[CNetTcp - Destrutor] Start" << endl; 02032 #endif 02033 02034 // Para a classe (caso ainda nao tenha sido parada) 02035 if( m_Started ) 02036 Stop(); 02037 02038 // Destroi o mutex e as variaveis de condicao. 02039 pthread_mutex_destroy( &m_Mutex ); 02040 pthread_cond_destroy( &m_Cond ); 02041 02042 #ifdef RIO_DEBUG1 02043 TCPLOG << "[CNetTcp - Destrutor] Finish" << endl; 02044 #endif 02045 }
RioResult CNetTcp::CloseAllConnections | ( | ) | [private] |
Funcao para fechar todas as conexoes TCP ativas, enviando ao outro lado da conexao uma mensagem de que a conexao foi finalizada.
Definition at line 3459 of file NetTcp.cpp.
03460 { 03461 // Armazena o resultado das execucoes das funcoes do RIO. 03462 RioResult RioStatus; 03463 // Armazena um iterador para o hash (usado para ver se ja existe uma conexao 03464 // para o par IP, porta na hash). 03465 TTcpConnectionsIterator ConnectionIterator; 03466 // Armazena o ponteiro para o objeto da conexao TCP associada ao par DestIP, 03467 // DestPort (se achado). 03468 CTcpConnection *TcpConnection; 03469 03470 // Armazena o IP associado a conexao. 03471 int IP; 03472 // Armazena a porta associada a conexao. 03473 int Port; 03474 03475 #ifdef RIO_DEBUG2 03476 // Armazena o endereco IP para ser usado pela funca inet_ntoa. 03477 struct in_addr ip; 03478 #endif 03479 03480 #ifdef RIO_DEBUG1 03481 TCPLOG << "[CNetTcp - CloseAllConnections] Start" << endl; 03482 #endif 03483 03484 // Obtem acesso exclusivo a hash com as conexoes, para poder fechalas todas 03485 // a partir do envio de uma mensagem com tamanho 0 ao outro lado. 03486 pthread_mutex_lock( &m_Mutex ); 03487 03488 for( ConnectionIterator = m_TcpConnectionsMap.begin(); 03489 ConnectionIterator != m_TcpConnectionsMap.end(); ConnectionIterator++ ) 03490 { 03491 // Armazena o ponteiro do objeto, para facilitar o acesso. 03492 TcpConnection = ( *ConnectionIterator ).second; 03493 // Chama a funcao SendDataPrivate acima, para cada conexao, com o 03494 // tamanho 0, para informar que cada conexao esta sendo fechada por 03495 // este lado. 03496 // Obtem o par IP, porta associado ao objeto TcpConnection, 03497 RioStatus = TcpConnection->GetIpAndPort( &IP, &Port ); 03498 if( FAILED( RioStatus ) ) 03499 { 03500 #ifdef RIO_DEBUG2 03501 TCPLOG << "CNetTcp::CloseAllConnections erro 0x" << hex << RioStatus 03502 << dec << " (" << GetErrorDescription( RioStatus ) << ") ao " 03503 << "executar a funcao GetIpAndPort de um objeto do tipo " 03504 << "CTcpConnection." << endl; 03505 #endif 03506 03507 #ifdef RIO_DEBUG1 03508 TCPLOG << "[CNetTcp - CloseAllConnections] Finish1" << endl; 03509 #endif 03510 03511 return RioStatus; 03512 } 03513 03514 #ifdef RIO_DEBUG2 03515 // Guarda o IP e a porta associado ao stream para as impressoes de 03516 // depuracao (se RIO_DEBUG2 for usado). 03517 ip.s_addr = IP; 03518 03519 TCPLOG << "CNetTcp::CloseAllConnections tentando finalizar a " 03520 << "conexao TCP para o IP "<< inet_ntoa( ip ) << " e a " 03521 << "porta " << ntohs( Port ) << endl; 03522 #endif 03523 03524 // Envia a mensagem de termino (dados com o tamanho 0), para todos os 03525 // servidores em m_ServerAddress. 03526 RioStatus = SendDataPrivate( TcpConnection, NULL, 0, 03527 ( void * ) NULLTRANSFERID ); 03528 if( FAILED( RioStatus ) ) 03529 { 03530 #ifdef RIO_DEBUG2 03531 TCPLOG << "CNetTcp::CloseAllConnections erro ao finalizar a " 03532 << "conexao TCP para o IP "<< inet_ntoa( ip ) << " e a " 03533 << "porta " << ntohs( Port ) << endl; 03534 #endif 03535 03536 // Chama a funcao do objeto da classe CNetInterface que processa os 03537 // processa os erros. 03538 m_NetInterface->ProcessError( IP, Port, RioStatus, 03539 "CloseAllConnections-SendDataPrivate", 03540 SENDERROR, 03541 ( void * ) NULLTRANSFERID ); 03542 } 03543 } 03544 03545 // Espera ate que todas as conexoes terminem (isso somente ocorrera se a 03546 // hash de conexoes nao estiver vazia, ou seja, se enviamos alguma mensagem 03547 // de termino de conexao no laco acima. 03548 if( !m_TcpConnectionsMap.empty() ) 03549 pthread_cond_wait( &m_Cond, &m_Mutex ); 03550 03551 // Agora que todas as threads finalizaram, desbloqueamos o lock do TCP. 03552 pthread_mutex_unlock( &m_Mutex ); 03553 03554 #ifdef RIO_DEBUG1 03555 TCPLOG << "[CNetTcp - CloseAllConnections] Finish2" << endl; 03556 #endif 03557 03558 return S_OK; 03559 }
void CNetTcp::ConnectionClosed | ( | int | IP, | |
int | Port, | |||
EClosedType | ClosedType | |||
) |
Esta funcao e chamada pelo objeto de uma das classes de rede quando a conexao com o par IP, port for fechada.
Os motivos atuais, dados pelo tipo ClosedType, sao:
CONNECTIONCLOSED: a conexao foi fechada pelo outro lado. CONNECTIONTIMEOUT: a conexao foi fechada por timeout.
IP | endereco IP da maquina associada ao socket com o erro. | |
Port | porta associada ao socket com erro | |
timeout | se for true a conexao foi fechada por timeout e, se for false, a conexao foi fechada pelo outro lado da conexao. |
Definition at line 4453 of file NetTcp.cpp.
04454 { 04455 // Armazena a chave do mapa associado ao par IP, porta. 04456 char StreamKey[ MAXHASHKEYSIZE ]; 04457 // Armazena o ponteiro para a chave da entrada da hash removida, para a 04458 // removermos apos remover a entrada da hash. 04459 const char *StrKey; 04460 // Armazena um iterador para o hash (usado para ver se ja existe uma conexao 04461 // para o par IP, porta na hash). 04462 TTcpConnectionsIterator ConnectionIterator; 04463 04464 #ifdef RIO_DEBUG1 04465 TCPLOG << "[CNetTcp - ConnectionClosed] Start" << endl; 04466 #endif 04467 04468 // Inicializa o IP usado para i 04469 04470 // Verifica se o objeto foi inicializado. 04471 if( !m_Started ) 04472 { 04473 #ifdef RIO_DEBUG2 04474 TCPLOG << "CNetTcp::ConnectionClosed o objeto nao foi inicializado. " 04475 << "Nao foi possivel executar a funcao ConnectionClosed." 04476 << endl; 04477 #endif 04478 04479 #ifdef RIO_DEBUG1 04480 TCPLOG << "[CNetTcp - ConnectionClosed] Finish1" << endl; 04481 #endif 04482 04483 return; 04484 } 04485 04486 // Chama a funcao ConnectionClosed do objeto da classe CNetInterface. 04487 m_NetInterface->ConnectionClosed( IP, Port, ClosedType ); 04488 04489 // Determina a chave da hash associada a conexao que esta sendo fechada. 04490 GetKey( IP, Port, StreamKey ); 04491 04492 // Obtem acesso exclusivo a hash com as conexoes. 04493 pthread_mutex_lock( &m_Mutex ); 04494 04495 // Remove o objeto do hash com os pares IP, porta, para evitar que futuros 04496 // envios de dados possam ser colocados na fila de saida do socket do 04497 // objeto. 04498 ConnectionIterator = m_TcpConnectionsMap.find( StreamKey ); 04499 if( ConnectionIterator != m_TcpConnectionsMap.end() ) 04500 { 04501 // Armazena um ponteiro para a chave a ser removida. 04502 StrKey = ( *ConnectionIterator).first; 04503 // Remove a entrada da hash com a conexao que esta sendo fechada. 04504 m_TcpConnectionsMap.erase( ConnectionIterator ); 04505 // Remove a chave associada a entrada da hash. 04506 delete[] StrKey; 04507 // Se a hash se tornar vazia, entao deveremos enviar um sinal para a 04508 // variavel de condicao m_Cond, para desbloquear a thread principal, 04509 // caso estejamos finalizando o servidor e ela esteja bloqueada na 04510 // funcao CloseAllConnections (chamada pela funcao Stop). 04511 if( m_TcpConnectionsMap.empty() ) 04512 pthread_cond_signal( &m_Cond ); 04513 } 04514 #ifdef RIO_DEBUG2 04515 else 04516 { 04517 // Armazena uma copia do endereco IP (usado para depuracao de erro). 04518 in_addr ip; 04519 04520 // Inicializa a estrutura ip com a copia do IP para a impressao. 04521 ip.s_addr = IP; 04522 // Isso nao deveria ocorrer. Entao imprimimos um erro informando sobre 04523 // o problena. 04524 TCPLOG << "CNetTcp::ConnectionClosed O par IP " << inet_ntoa( ip ) 04525 << ", porta " << ntohs( Port ) << " nao foi achado na hash " 04526 << "m_TcpConnectionsMap com os objetos das conexoes TCP ativas!" 04527 << endl; 04528 } 04529 #endif 04530 04531 // Libera o acesso exclusivo a hash com as conexoes. 04532 pthread_mutex_unlock( &m_Mutex ); 04533 04534 #ifdef RIO_DEBUG1 04535 TCPLOG << "[CNetTcp - ConnectionClosed] Finish2" << endl; 04536 #endif 04537 }
RioResult CNetTcp::EnableConnection | ( | CTcpConnection * | TcpConnection | ) | [private] |
Funcao para habilitar o uso da conexao TCP passada como parametro.
A funcao colocara o objeto na fila de objetos, e depois chamara a funcao EnableConnection do objeto da conexao TCP passado como parametro.
TcpConnection | ponteiro para o objeto associado a conexao a ser habilitada. |
Definition at line 2153 of file NetTcp.cpp.
02154 { 02155 // Armazena a chave do mapa associado ao par IP, porta. 02156 char StreamKey[ MAXHASHKEYSIZE ]; 02157 // Armazena o ponteiro para chave a ser colocada na hash, 02158 char *AuxStr; 02159 // Armazena o endereco IP da conexao. 02160 int IP; 02161 // Armazena a porta da conexao 02162 int Port; 02163 // Armazena um iterador para o hash (usado para ver se ja existe uma conexao 02164 // para o par IP, porta na hash). 02165 TTcpConnectionsIterator ConnectionIterator; 02166 // Armazena o codigo de erro das funcoes do RIO. 02167 RioResult RioStatus; 02168 02169 #ifdef RIO_DEBUG2 02170 // Usado pelas funcoes de impressao. 02171 in_addr ip; 02172 #endif 02173 02174 #ifdef RIO_DEBUG1 02175 TCPLOG << "[CNetTcp - EnableConnection] Start" << endl; 02176 #endif 02177 02178 // Inicializa o valor de AuxStr. 02179 AuxStr = NULL; 02180 02181 // Obtem o par IP, porta associado ao objeto TcpConnection, 02182 RioStatus = TcpConnection->GetIpAndPort( &IP, &Port ); 02183 if( FAILED( RioStatus ) ) 02184 { 02185 #ifdef RIO_DEBUG2 02186 TCPLOG << "CNetTcp::EnableConnection erro 0x" << hex << RioStatus << dec 02187 << " (" << GetErrorDescription( RioStatus ) << ") ao executar a " 02188 << "funcao GetIpAndPort de um objeto do tipo CTcpConnection." 02189 << endl; 02190 #endif 02191 02192 #ifdef RIO_DEBUG1 02193 TCPLOG << "[CNetTcp - EnableConnection] Finish1" << endl; 02194 #endif 02195 02196 return RioStatus; 02197 } 02198 02199 #ifdef RIO_DEBUG2 02200 // Inicializa a estrutura usada para a impressao do endereco IP. 02201 ip.s_addr = IP; 02202 #endif 02203 02204 // Determina a chave da hash associada ao novo stream. 02205 GetKey( IP, Port, StreamKey ); 02206 02207 // Obtem acesso exclusivo aos dados da classe. 02208 pthread_mutex_lock( &m_Mutex ); 02209 02210 // Verifica se a chave ja esta na hash. 02211 ConnectionIterator = m_TcpConnectionsMap.find( StreamKey ); 02212 if( ConnectionIterator != m_TcpConnectionsMap.end() ) 02213 { 02214 #ifdef RIO_DEBUG2 02215 TCPLOG << "CNetTcp::EnableConnection a chave " << StreamKey << " (IP = " 02216 << inet_ntoa( ip ) << ", Port=" << ntohs( Port ) << "). Ja " 02217 << "existe na hash!" << endl; 02218 #endif 02219 02220 #ifdef RIO_DEBUG1 02221 TCPLOG << "[CNetTcp - EnableConnection] Finish2" << endl; 02222 #endif 02223 02224 return ERROR_NETTCP + ERROR_UNEXPECTED; 02225 } 02226 02227 // Coloca o stream na hash de streams 02228 try 02229 { 02230 #ifdef RIO_DEBUG2 02231 TCPLOG << "CNetTcp::EnableConnection Tentando inserir uma nova entrada " 02232 << "na hash m_TcpConnectionsMap com a chave " << StreamKey 02233 << " (IP = " << inet_ntoa( ip ) << ", Port=" << ntohs( Port ) 02234 << "). Tamanho atual da hash e de " << m_TcpConnectionsMap.size() 02235 << "." << endl; 02236 #endif 02237 02238 AuxStr = new char[ strlen( StreamKey ) + 1 ]; 02239 02240 strcpy( AuxStr, StreamKey ); 02241 02242 m_TcpConnectionsMap[ AuxStr ] = TcpConnection; 02243 02244 #ifdef RIO_DEBUG2 02245 TCPLOG << "CNetTcp::EnableConnection a nova entrada na hash " 02246 << "m_TcpConnectionsMap com a chave " << StreamKey << " (IP = " 02247 << inet_ntoa( ip ) << ", Port=" << ntohs( Port ) << ") foi " 02248 << "inserida com sucesso. Novo tamanho da hash e de " 02249 << m_TcpConnectionsMap.size() << "." << endl; 02250 #endif 02251 } 02252 catch( bad_alloc& ba ) 02253 { 02254 // Libera o acesso exclusivo aos dados da classe. 02255 pthread_mutex_unlock( &m_Mutex ); 02256 02257 // Verifica se o erro ocorreu ao colocar o elemento na hash. 02258 if( AuxStr != NULL ) 02259 delete[] AuxStr; 02260 02261 #ifdef RIO_DEBUG2 02262 TCPLOG << "CNetTcp::EnableConnection erro de alocacao de memoria (" 02263 << "bad_alloc, error = " << ba.what() << ") ao criar uma " 02264 << "entrada no mapa m_TcpStreamsMap para o novo stream com a " 02265 << "chave " << StreamKey << " (IP = " << inet_ntoa( ip ) 02266 << ", Port=" << ntohs( Port ) << ")." << endl; 02267 #endif 02268 02269 #ifdef RIO_DEBUG1 02270 TCPLOG << "[CNetTcp - EnableConnection] Finish2" << endl; 02271 #endif 02272 02273 return ERROR_NETTCP + ERROR_MEMORY; 02274 } 02275 02276 // Libera o acesso exclusivo aos dados da classe. 02277 pthread_mutex_unlock( &m_Mutex ); 02278 02279 // Habilita a nova conexao criada. 02280 RioStatus = TcpConnection->EnableConnection(); 02281 if( FAILED( RioStatus ) ) 02282 { 02283 #ifdef RIO_DEBUG2 02284 TCPLOG << "CNetTcp::EnableConnection erro 0x" << hex << RioStatus << dec 02285 << " (" << GetErrorDescription( RioStatus ) << ") ao executar a " 02286 << "funcao EnableConnection de um objeto do tipo CTcpConnection." 02287 << endl; 02288 #endif 02289 02290 #ifdef RIO_DEBUG1 02291 TCPLOG << "[CNetTcp - EnableConnection] Finish3" << endl; 02292 #endif 02293 02294 return RioStatus; 02295 } 02296 02297 #ifdef RIO_DEBUG1 02298 TCPLOG << "[CNetTcp - EnableConnection] Finish4" << endl; 02299 #endif 02300 02301 return S_OK; 02302 }
RioResult CNetTcp::FindIPAndPort | ( | int | IP, | |
int | Port, | |||
bool * | isFound | |||
) |
Funcao para verificar se um dado par IP, Porta esta ou nao associado a uma conexao do objeto desta classe.
IP | IP a ser verificado. | |
Port | Porta a ser verificada. | |
isFound | ponteiro para um valor booleando que sera true se o par IP, Porta esta associado a uma conexao, ou false em caso contrario. |
Definition at line 4258 of file NetTcp.cpp.
04259 { 04260 // Armazena a chave do mapa associado ao par IP, porta. 04261 char StreamKey[ MAXHASHKEYSIZE ]; 04262 // Armazena um iterador para o hash (usado para ver se ja existe uma conexao 04263 // para o par IP, porta na hash). 04264 TTcpConnectionsIterator ConnectionIterator; 04265 04266 #ifdef RIO_DEBUG1 04267 TCPLOG << "[CNetTcp - FindIPAndPort] Start" << endl; 04268 #endif 04269 04270 #ifdef RIO_DEBUG2 04271 struct in_addr ip; 04272 04273 ip.s_addr = IP; 04274 #endif 04275 04276 // Verifica se o objeto foi inicializado. 04277 if( !m_Started ) 04278 { 04279 #ifdef RIO_DEBUG2 04280 TCPLOG << "CNetTcp::FindIPAndPort o objeto nao foi inicializado. Nao " 04281 << "foi possivel verificar o par IP " << inet_ntoa( ip ) << " e " 04282 << "a porta " << ntohs( Port ) << "." << endl; 04283 #endif 04284 04285 #ifdef RIO_DEBUG1 04286 TCPLOG << "[CNetTcp - FindIPAndPort] Finish1" << endl; 04287 #endif 04288 04289 *isFound = false; 04290 04291 return ERROR_NETTCP + ERROR_NOT_STARTED; 04292 } 04293 04294 // Determina a chave da hash associada ao novo stream. 04295 GetKey( IP, Port, StreamKey ); 04296 04297 // Obtem acesso exclusivo a hash com as conexoes. 04298 pthread_mutex_lock( &m_Mutex ); 04299 04300 // Verifica se a chave (IP, Porta) esta na hash. 04301 ConnectionIterator = m_TcpConnectionsMap.find( StreamKey ); 04302 *isFound = ( ConnectionIterator != m_TcpConnectionsMap.end() ); 04303 04304 // Libera o acesso exclusivo a hash com as conexoes. 04305 pthread_mutex_unlock( &m_Mutex ); 04306 04307 #ifdef RIO_DEBUG2 04308 TCPLOG << "CNetTcp::FindIPAndPort Funcao executada com sucesso para o " 04309 << "IP " << inet_ntoa( ip ) << " e a porta " << ntohs( Port ) 04310 << "O par IP, porta " << ( ( *isFound ) ? "foi " : "nao foi " ) 04311 << "achado na hash com as conexoes TCP ativas!" << endl; 04312 #endif 04313 04314 #ifdef RIO_DEBUG1 04315 TCPLOG << "[CNetTcp - FindIPAndPort] Finish2" << endl; 04316 #endif 04317 04318 return S_OK; 04319 }
RioResult CNetTcp::GetAllIPsAndPorts | ( | int ** | IPs, | |
int ** | Ports | |||
) |
Funcao para retornar um ponteiro para o vetor interno que armazena os IPs e as portas.
Se for o cliente, retornaremos os ponteiros para os vetores com os IPs e as portas do cliente nos servidores e se for o servidor, retornaremos um ponteiro para m_TcpIP e para m_TcpServerPort.
IPs | ponteiro para armazenar o ponteiro para os endercos IPs. | |
Ports | ponteiro para armazenar o ponteiro para as portas. |
Definition at line 4199 of file NetTcp.cpp.
04200 { 04201 #ifdef RIO_DEBUG1 04202 TCPLOG << "[CNetTcp - GetAllIPsAndPorts] Start" << endl; 04203 #endif 04204 04205 // Verifica se o objeto foi inicializado. 04206 if( !m_Started ) 04207 { 04208 #ifdef RIO_DEBUG2 04209 TCPLOG << "CNetTcp::GetAllIPsAndPorts o objeto nao foi inicializado. " 04210 << "Nao foi possivel obter os IPs e as portas." << endl; 04211 #endif 04212 04213 #ifdef RIO_DEBUG1 04214 TCPLOG << "[CNetTcp - GetAllIPsAndPorts] Finish1" << endl; 04215 #endif 04216 04217 *IPs = NULL; 04218 *Ports = NULL; 04219 04220 return ERROR_NETTCP + ERROR_NOT_STARTED; 04221 } 04222 04223 // Verifica se e o cliente ou o servidor. 04224 if( m_ServerInstance ) 04225 { 04226 // No caso do servidor, estou retornando o ponteiro para os 04227 // inteiros m_IP e m_TcpServerPort. Sera que isso e o correto, 04228 // ou devemos retornar NULL e um erro (na RioNeti, esta funcao 04229 // parece estar sendo usada pelo cliente para obter os mapeamentos 04230 // do NAT). 04231 *IPs = &m_IP; 04232 *Ports = &m_TcpServerPort; 04233 } 04234 else 04235 { 04236 // No caso do cliente, retornamos os ponteiros para os vetores 04237 // m_ClientIPAddress e m_ClientPorts. 04238 *IPs = m_ClientIPAddress; 04239 *Ports = m_ClientPorts; 04240 } 04241 04242 #ifdef RIO_DEBUG2 04243 TCPLOG << "CNetTcp::GetAllIPsAndPorts funcao executada foi executada com " 04244 << "sucesso e obteve os dois ponteiros, um para o vetor interno com " 04245 << "os IPs (" << *IPs << ") e um outro para o vetor interno com as " 04246 << "portas (" << *Ports << ")." << endl; 04247 #endif 04248 04249 #ifdef RIO_DEBUG1 04250 TCPLOG << "[CNetTcp - GetAllIPsAndPorts] Finish2" << endl; 04251 #endif 04252 04253 return S_OK; 04254 }
RioResult CNetTcp::GetIPAndPort | ( | int * | IP = NULL , |
|
int * | Port = NULL , |
|||
unsigned int | Server = 0 | |||
) |
Funcao para retornar o par IP, Porta associada a uma conexao com o servidor definido pelo parametro server.
IP | ponteiro para armazenar o endereco IP associado ao servidor server. Se IP for NULL, o IP nao sera armazenado. | |
Port | ponteiro para armazenar a porta associado ao servidor server. Se Port for NULL, a porta nao sera armazenada. | |
Server | identificador do servidor (em geral, 0=dispatcher e 1,2,...=storages). Este parametro nao precisa ser passado e, neste caso, o seu valor default sera 0 (usar o dispatcher). se o objeto da classe estiver associado ao servidor, este parametro sera ignorado. |
Definition at line 4089 of file NetTcp.cpp.
04090 { 04091 #ifdef RIO_DEBUG2 04092 // Armazena uma copia do IP para ser usado pela funcao inet_ntoa. 04093 in_addr ip; 04094 #endif 04095 04096 #ifdef RIO_DEBUG1 04097 TCPLOG << "[CNetTcp - GetIPAndPort] Start" << endl; 04098 #endif 04099 04100 // Verifica se o objeto foi inicializado. 04101 if( !m_Started ) 04102 { 04103 #ifdef RIO_DEBUG2 04104 TCPLOG << "CNetTcp::GetIPAndPort o objeto nao foi inicializado. Nao " 04105 << "foi possivel obter o par IP, Porta."; 04106 if( m_ServerInstance ) 04107 TCPLOG << "." << endl; 04108 else 04109 TCPLOG << " associado ao servidor " << Server << "." << endl; 04110 #endif 04111 04112 #ifdef RIO_DEBUG1 04113 TCPLOG << "[CNetTcp - GetIPAndPort] Finish1" << endl; 04114 #endif 04115 04116 return ERROR_NETTCP + ERROR_NOT_STARTED; 04117 } 04118 04119 if( m_ServerInstance ) 04120 { 04121 // Se o objeto estiver associado ao servidor, entao deveremos retornar 04122 // os valores de m_IP e m_TcpServerPort. 04123 if( IP != NULL ) 04124 *IP = m_IP; 04125 if( Port != NULL ) 04126 *Port = m_TcpServerPort; 04127 04128 #ifdef RIO_DEBUG2 04129 TCPLOG << "CNetTcp::GetIPAndPort funcao executada com sucesso para um " 04130 << "objeto associadao a um servidor."; 04131 if( IP != NULL ) 04132 { 04133 ip.s_addr = *IP; 04134 TCPLOG << " O IP retornado sera " << inet_ntoa( ip ) << "."; 04135 } 04136 if( Port != NULL ) 04137 TCPLOG << " A porta retornada sera " << ntohs( *Port ) << "."; 04138 TCPLOG << endl; 04139 #endif 04140 04141 #ifdef RIO_DEBUG1 04142 TCPLOG << "[CNetTcp - GetIPAndPort] Finish2" << endl; 04143 #endif 04144 04145 return S_OK; 04146 } 04147 else 04148 { 04149 // Se for o cliente, deveremos antes verificar se o identificador do 04150 // servidor (Server) e valido. 04151 if( Server >= m_AddressSize ) 04152 { 04153 #ifdef RIO_DEBUG2 04154 TCPLOG << "CNetTcp::GetIPAndPort o identificador do servidor " 04155 << Server << " nao e valido. Deveria estar entre 0 e " 04156 << m_AddressSize - 1 << " (numero de servidores menos 1)." 04157 << endl; 04158 #endif 04159 04160 #ifdef RIO_DEBUG1 04161 TCPLOG << "[CNetTcp - GetIPAndPort] Finish3" << endl; 04162 #endif 04163 04164 return ERROR_NETTCP + ERROR_INVALID_PARAM; 04165 } 04166 04167 // Atribui o par IP, Porta associado ao servidor Server. 04168 if( IP != NULL ) 04169 *IP = m_ClientIPAddress[ Server ]; 04170 if( Port != NULL ) 04171 *Port = m_ClientPorts[ Server ]; 04172 04173 #ifdef RIO_DEBUG2 04174 ip.s_addr = *IP; 04175 TCPLOG << "CNetTcp::GetIPAndPort funcao executada com sucesso para " 04176 << "o servidor com o ID " << Server << "."; 04177 if( IP != NULL ) 04178 { 04179 ip.s_addr = *IP; 04180 TCPLOG << " O IP retornado sera " << inet_ntoa( ip ) << "."; 04181 } 04182 if( Port != NULL ) 04183 TCPLOG << " A porta retornada sera " << ntohs( *Port ) << "."; 04184 TCPLOG << endl; 04185 #endif 04186 04187 #ifdef RIO_DEBUG1 04188 TCPLOG << "[CNetTcp - GetIPAndPort] Finish4" << endl; 04189 #endif 04190 04191 return S_OK; 04192 } 04193 }
void CNetTcp::GetKey | ( | int | IP, | |
int | Port, | |||
char * | Key | |||
) | [private] |
Funcao para retornar a chave do mapa associada a um dado par IP,porta.
IP | endereco IP associado a conexao TCP. | |
Port | porta associada a conexao TCP. | |
Key | string para armazenar a chave (supomos que a string tem espaco suficiente para armazenar a string iii.iii.iii.iii.ppppp mais o terminador '' (22 bytes). A constante |
Definition at line 2048 of file NetTcp.cpp.
02049 { 02050 // A chave da hash sera uma string composta pelo endereco IP convertido para 02051 // a notacao de ".", mais um ".", mais a porta convertida para a notacao 02052 // decimal, e mais o terminador. O tamanho maximo que a string tera e de 02053 // 22 bytes: iii.iii.iii.iii.ppppp mais o terminador. 02054 02055 // Armazena o endereco IP para podermos usar a funcao inet_ntoa. 02056 in_addr ips; 02057 02058 #ifdef RIO_DEBUG1 02059 TCPLOG << "[CNetTcp - GetKey] Start" << endl; 02060 #endif 02061 02062 // Define o valor de ips com o valor de IP. 02063 ips.s_addr = IP; 02064 // Gera a chave usando as funcoes sprintf, inet_ntoa e ntohs. 02065 02066 sprintf( Key, "%s.%u", inet_ntoa( ips ), ( unsigned int ) ntohs( Port ) ); 02067 02068 #ifdef RIO_DEBUG2 02069 TCPLOG << "CNetTcp::GetKey Chave para o IP " << inet_ntoa( ips ) 02070 << " e porta " << ntohs( Port ) << ": " << Key << endl; 02071 #endif 02072 02073 #ifdef RIO_DEBUG1 02074 TCPLOG << "[CNetTcp - GetKey] Finish" << endl; 02075 #endif 02076 }
RioResult CNetTcp::NewConnection | ( | int | IP, | |
int | Port, | |||
int | Socket, | |||
CTcpConnection ** | TcpConnection | |||
) | [private] |
Funcao para criar um novo objeto para uma nova conexao TCP.
IP | endereco IP associado a conexao TCP. | |
Port | porta associada a conexao TCP. | |
Socket | socket associado a conexao TCP. | |
TcpConnetion | ponteiro para um ponteiro para um objeto do tipo CTcpConnection, que armazenara o ponteiro para o objeto deste tipo criado para a nova conexao TCP. |
Definition at line 2080 of file NetTcp.cpp.
02082 { 02083 // Armazena o erro retornado pelas funcoes do RIO. 02084 RioResult RioStatus; 02085 02086 #ifdef RIO_DEBUG2 02087 // Usado para imprimir o IP. 02088 in_addr ip; 02089 02090 ip.s_addr = IP; 02091 #endif 02092 02093 // Tenta criar um novo objeto para a nova conexao TCP. 02094 try 02095 { 02096 *TcpConnection = new CTcpConnection( this, m_ServerInstance ); 02097 } 02098 catch( bad_alloc& ba ) 02099 { 02100 #ifdef RIO_DEBUG2 02101 TCPLOG << "CNetTcp::NewConnection erro de alocacao de memoria " 02102 << "(bad_alloc, error = " << ba.what() << ") ao criar um objeto " 02103 << "para a nova conexao associada ao IP " << inet_ntoa( ip ) 02104 << ", a porta " << ntohs( Port ) << " e ao socket com a ID " 02105 << Socket << "." << endl; 02106 #endif 02107 02108 #ifdef RIO_DEBUG1 02109 TCPLOG << "[CNetTcp - NewConnection] Finish1" << endl; 02110 #endif 02111 02112 *TcpConnection = NULL; 02113 02114 return ERROR_NETTCP + ERROR_MEMORY; 02115 } 02116 02117 // Tenta inicializar o objeto que acabamos de criar. 02118 RioStatus = ( *TcpConnection )->Initialize( IP, Port, Socket, m_IP, 02119 m_ConnectionTimeOut, 02120 m_LogRotation ); 02121 if( FAILED( RioStatus ) ) 02122 { 02123 #ifdef RIO_DEBUG2 02124 TCPLOG << "CNetTcp::NewConnection erro 0x" << hex << RioStatus << dec 02125 << " (" << GetErrorDescription( RioStatus ) << ") ao " 02126 << "inicializar o objeto da nova conexao associada ao IP " 02127 << inet_ntoa( ip ) << ", a porta " << ntohs( Port ) << " e ao " 02128 << "socket com a ID " << Socket << "." << endl; 02129 #endif 02130 02131 #ifdef RIO_DEBUG1 02132 TCPLOG << "[CNetTcp - NewConnection] Finish2" << endl; 02133 #endif 02134 02135 // Delete o objeto. 02136 delete *TcpConnection; 02137 02138 *TcpConnection = NULL; 02139 02140 return RioStatus; 02141 } 02142 02143 #ifdef RIO_DEBUG1 02144 TCPLOG << "[CNetTcp - NewConnection] Finish3" << endl; 02145 #endif 02146 02147 return S_OK; 02148 }
void CNetTcp::ProcessData | ( | int | IP, | |
int | Port, | |||
char * | Data, | |||
unsigned int | DataSize | |||
) |
Esta funcao e chamada pelo objeto de uma das classes de rede ao receber dados pela rede.
IP | endereco IP da maquina que enviou os dados. | |
Port | porta a partir da qual o pacote foi enviado a partir da maquina que enviou estes dados | |
Data | Dados enviados. | |
DataSize | Tamanho dos dados. Obs: Um tamanho igual a 0 indicara que a conexao foi fechada pelo outro lado. Neste caso, a funcao devera fazer as tarefas necessarias para fechar a conexao associada aos dados. |
Definition at line 4356 of file NetTcp.cpp.
04357 { 04358 #ifdef RIO_DEBUG1 04359 TCPLOG << "[CNetTcp - ProcessData] Start" << endl; 04360 #endif 04361 04362 // Verifica se o objeto foi inicializado. 04363 if( !m_Started ) 04364 { 04365 #ifdef RIO_DEBUG2 04366 TCPLOG << "CNetTcp::ProcessData o objeto nao foi inicializado. Nao foi " 04367 << "possivel executar a funcao ProcessData." << endl; 04368 #endif 04369 04370 #ifdef RIO_DEBUG1 04371 TCPLOG << "[CNetTcp - ProcessData] Finish1" << endl; 04372 #endif 04373 04374 return; 04375 } 04376 04377 // Esta funcao somente chama a funcao ProcessData do objeto da classe 04378 // CNetInterface. 04379 m_NetInterface->ProcessData( IP, Port, Data, DataSize ); 04380 04381 #ifdef RIO_DEBUG1 04382 TCPLOG << "[CNetTcp - ProcessData] Finish2" << endl; 04383 #endif 04384 }
void CNetTcp::ProcessError | ( | int | IP, | |
int | Port, | |||
RioResult | RioError, | |||
const char * | Msg, | |||
EErrorType | ErrorType, | |||
void * | Param | |||
) |
Esta funcao e chamada quando algum erro ocorrer com a transferencia de dados.
IP | endereco IP da maquina associada ao socket com o erro. | |
Port | porta associada ao socket com erro | |
RioError | erro que ocorreu na transferencia dos dados. | |
Msg | Mensagem a ser impressa junto com o erro (usada para sabermos onde o erro foi gerado) | |
ErrorType | tipo do erro que foi gerado (se foi gerado por um recebimento de dados, por um envio de dados, ou por um outro motivo). | |
Param | parametro generico opcional passado a funcao. No nosso caso, quando nao NULL, contem o identificador da transferencia associada ao erro (isso somente e usado pelo envio dos dados, no recebimento, e passado sempre NULLTRANSFERID). |
Definition at line 4420 of file NetTcp.cpp.
04422 { 04423 #ifdef RIO_DEBUG1 04424 TCPLOG << "[CNetTcp - ProcessError] Start" << endl; 04425 #endif 04426 04427 // Verifica se o objeto foi inicializado. 04428 if( !m_Started ) 04429 { 04430 #ifdef RIO_DEBUG2 04431 TCPLOG << "CNetTcp::ProcessError o objeto nao foi inicializado. " 04432 << "Nao foi possivel executar a funcao ProcessError." << endl; 04433 #endif 04434 04435 #ifdef RIO_DEBUG1 04436 TCPLOG << "[CNetTcp - ProcessError] Finish1" << endl; 04437 #endif 04438 04439 return; 04440 } 04441 04442 // Esta funcao somente chama a funcao ProcessError do objeto da classe 04443 // CNetInterface. 04444 m_NetInterface->ProcessError( IP, Port, RioError, Msg, ErrorType, Param ); 04445 04446 #ifdef RIO_DEBUG1 04447 TCPLOG << "[CNetTcp - ProcessError] Finish2" << endl; 04448 #endif 04449 }
RioResult CNetTcp::SendData | ( | int | IP, | |
int | Port, | |||
char * | Data, | |||
unsigned int | DataSize, | |||
void * | Param | |||
) |
Funcao para enviar dados para a maquina identificada nos parametros.
Obs: Note que os pacotes recebidos serao repassados ao objeto da classe CNetInterface, usando a sua funcao ProcessData.
IP | endereco IP da maquina destino | |
Port | porta nesta maquina destino | |
Data | ponteiro para o endereco inicial da memoria onde estao armazenados os dados a serem enviados. | |
DataSize | tamanho em bytes dos dados. | |
Param | parametro a ser passado quando os dados forem enviados e a funcao SendDataCompleted do objeto da classe CNetInterface for chamado. |
Definition at line 3990 of file NetTcp.cpp.
03992 { 03993 // Armazena o erro retornado pelas funcoes dos objetos das classes 03994 // CTcpStreams e CNetTcp. 03995 RioResult RioStatus; 03996 // Armazena a chave do mapa associado ao par IP, porta. 03997 char StreamKey[ MAXHASHKEYSIZE ]; 03998 // Armazena um iterador para o hash (usado para ver se ja existe uma conexao 03999 // para o par IP, porta na hash). 04000 TTcpConnectionsIterator ConnectionIterator; 04001 // Armazena o ponteiro para o objeto da conexao TCP associada ao par DestIP, 04002 // DestPort (se achado). 04003 CTcpConnection *TcpConnection; 04004 04005 #ifdef RIO_DEBUG1 04006 TCPLOG << "[CNetTcp - SendData] Start" << endl; 04007 #endif 04008 04009 #ifdef RIO_DEBUG2 04010 struct in_addr ip; 04011 04012 ip.s_addr = DestIP; 04013 #endif 04014 04015 // Verifica se o objeto foi inicializado. 04016 if( !m_Started ) 04017 { 04018 #ifdef RIO_DEBUG2 04019 TCPLOG << "CNetTcp::SendData o objeto nao foi inicializado. Nao foi " 04020 << "possivel enviar o pacote para o IP " << inet_ntoa( ip ) 04021 << " e a porta " << ntohs( DestPort ) << endl; 04022 #endif 04023 04024 #ifdef RIO_DEBUG1 04025 TCPLOG << "[CNetTcp - SendData] Finish1" << endl; 04026 #endif 04027 04028 return ERROR_NETTCP + ERROR_NOT_STARTED; 04029 } 04030 04031 // Determina a chave da hash associada ao novo stream. 04032 GetKey( DestIP, DestPort, StreamKey ); 04033 04034 // Obtem acesso exclusivo a hash com as conexoes. 04035 pthread_mutex_lock( &m_Mutex ); 04036 04037 // Verifica se a chave (IP, Porta) esta na hash. 04038 ConnectionIterator = m_TcpConnectionsMap.find( StreamKey ); 04039 if( ConnectionIterator == m_TcpConnectionsMap.end() ) 04040 { 04041 // Libera o acesso exclusivo a hash com as conexoes. 04042 pthread_mutex_unlock( &m_Mutex ); 04043 04044 // Neste caso deveremos retornar um erro porque o par IP, porta nao foi 04045 // achado no mapa. 04046 #ifdef RIO_DEBUG2 04047 TCPLOG << "CNetTcp::SendData O par IP " << inet_ntoa( ip ) << ", porta " 04048 << ntohs( DestPort ) << " nao foi achado na hash " 04049 << "m_TcpConnectionsMap com os objetos das conexoes TCP ativas!" 04050 << endl; 04051 #endif 04052 04053 #ifdef RIO_DEBUG1 04054 TCPLOG << "[CNetTcp - SendData] Finish2" << endl; 04055 #endif 04056 04057 return ERROR_NETTCP + ERROR_HOST_NOTFOUND; 04058 } 04059 04060 // Armazena o ponteiro do objeto, para facilitar o acesso. 04061 TcpConnection = ( *ConnectionIterator ).second; 04062 04063 RioStatus = SendDataPrivate( TcpConnection, Data, DataSize, Param ); 04064 #ifdef RIO_DEBUG2 04065 if( FAILED( RioStatus ) ) 04066 TCPLOG << "CNetTcp::SendData erro 0x" << hex << RioStatus << dec << " (" 04067 << GetErrorDescription( RioStatus ) << ") ao executar a funcao " 04068 << "SendDataPrivate." << endl; 04069 #endif 04070 04071 // Libera o acesso exclusivo a hash com as conexoes. 04072 pthread_mutex_unlock( &m_Mutex ); 04073 04074 #ifdef RIO_DEBUG2 04075 TCPLOG << "CNetTcp::SendData dados colocados com sucesso no objeto " 04076 << "associado ao IP " << inet_ntoa( ip ) << ", a porta " 04077 << ntohs( DestPort ) << ", com a chave " << StreamKey << "." << endl; 04078 #endif 04079 04080 #ifdef RIO_DEBUG1 04081 TCPLOG << "[CNetTcp - SendData] Finish3" << endl; 04082 #endif 04083 04084 return RioStatus; 04085 }
void CNetTcp::SendDataCompleted | ( | int | IP, | |
int | Port, | |||
void * | Param | |||
) |
Esta Funcao sera chamada pelo objeto de uma das classes de rede quando os dados tiverem sido enviados para um endereco (com ou sem sucesso).
IP | endereco ip da maquina que enviou os dados. | |
Port | porta a partir da qual o pacote foi enviado a partir da maquina que enviou estes dados | |
Param | parametro passado quando os dados foram enviados. No nosso caso, ele e o identificador da transferencia usada para enviar os dados. |
Definition at line 4388 of file NetTcp.cpp.
04389 { 04390 #ifdef RIO_DEBUG1 04391 TCPLOG << "[CNetTcp - SendDataCompleted] Start" << endl; 04392 #endif 04393 04394 // Verifica se o objeto foi inicializado. 04395 if( !m_Started ) 04396 { 04397 #ifdef RIO_DEBUG2 04398 TCPLOG << "CNetTcp::SendDataCompleted o objeto nao foi inicializado. " 04399 << "Nao foi possivel executar a funcao SendDataCompleted." 04400 << endl; 04401 #endif 04402 04403 #ifdef RIO_DEBUG1 04404 TCPLOG << "[CNetTcp - SendDataCompleted] Finish1" << endl; 04405 #endif 04406 04407 return; 04408 } 04409 04410 // Esta funcao somente chama a funcao SendDataCompleted do objeto da classe 04411 // CNetInterface. 04412 m_NetInterface->SendDataCompleted( IP, Port, Param ); 04413 04414 #ifdef RIO_DEBUG1 04415 TCPLOG << "[CNetTcp - SendDataCompleted] Finish2" << endl; 04416 #endif 04417 }
RioResult CNetTcp::SendDataPrivate | ( | CTcpConnection * | TcpConnection, | |
char * | Data, | |||
unsigned int | DataSize, | |||
void * | Param | |||
) | [private] |
Funcao para enviar dados para a maquina identificada nos parametros.
Obs: Note que os pacotes recebidos serao repassados ao objeto da classe CNetInterface, usando a sua funcao ProcessData. Obs2: Esta funcao nao verifica se a classe esta inicializada (para fazer isso, usar a funcao SendData a seguir, que faz a verificacao e depois chama esta funcao.
TcpConnection | ponteiro para o objeto responsavel pela conexao TCP. | |
Data | ponteiro para o endereco inicial da memoria onde estao armazenados os dados a serem enviados. | |
DataSize | tamanho em bytes dos dados. | |
Param | parametro a ser passado quando os dados forem enviados e a funcao SendDataCompleted do objeto da classe CNetInterface for chamado. |
Definition at line 3377 of file NetTcp.cpp.
03379 { 03380 // Armazena o erro retornado pelas funcoes dos objetos das classes 03381 // CTcpStreams e CNetTcp. 03382 RioResult RioStatus; 03383 // Armazena o tamanho da fila com os dados a serem enviados. 03384 unsigned int SendDataSize; 03385 03386 #ifdef RIO_DEBUG1 03387 TCPLOG << "[CNetTcp - SendDataPrivate] Start" << endl; 03388 #endif 03389 03390 #ifdef RIO_DEBUG2 03391 // Armazena o IP da conexao. 03392 int IP; 03393 // Armazena a porta da conexao. 03394 int Port; 03395 // Armazena uma copia do IP, usada para impressao. 03396 struct in_addr ip; 03397 03398 // Obtem o par IP, porta associado ao objeto TcpConnection, 03399 RioStatus = TcpConnection->GetIpAndPort( &IP, &Port ); 03400 if( FAILED( RioStatus ) ) 03401 { 03402 #ifdef RIO_DEBUG2 03403 TCPLOG << "CNetTcp::SendDataPrivate erro 0x" << hex << RioStatus << dec 03404 << " (" << GetErrorDescription( RioStatus ) << ") ao executar a " 03405 << "funcao GetIpAndPort de um objeto do tipo CTcpConnection." 03406 << endl; 03407 #endif 03408 03409 #ifdef RIO_DEBUG1 03410 TCPLOG << "[CNetTcp - SendDataPrivate] Finish0" << endl; 03411 #endif 03412 03413 return RioStatus; 03414 } 03415 03416 // Inicializa o campo da estrutura ip, usada para impresao com o IP. 03417 ip.s_addr = IP; 03418 #endif 03419 03420 // Coloca os dados na fila do stream (sera que e necessario copiar os 03421 // dados?). 03422 RioStatus = TcpConnection->PutSendData( Data, DataSize, Param, 03423 &SendDataSize ); 03424 03425 if( FAILED( RioStatus ) ) 03426 { 03427 #ifdef RIO_DEBUG2 03428 TCPLOG << "CNetTcp::SendDataPrivate erro 0x" << hex << RioStatus 03429 << dec << " (" << GetErrorDescription( RioStatus ) << ") ao " 03430 << "executar a funcao PutSendData do objeto TcpConnection " 03431 << "(da classe CTcpConnection. Nao foi possivel enviar o " 03432 << "pacote para o IP " << inet_ntoa( ip ) << " e a porta " 03433 << ntohs( Port ) << endl; 03434 #endif 03435 03436 #ifdef RIO_DEBUG1 03437 TCPLOG << "[CNetTcp - SendDataPrivate] Finish1" << endl; 03438 #endif 03439 03440 return RioStatus; 03441 } 03442 03443 #ifdef RIO_DEBUG2 03444 TCPLOG << "CNetTcp::SendDataPrivate dados colocados com sucesso na " 03445 << "fila do objeto associado ao IP " << inet_ntoa( ip ) 03446 << " e a porta " << ntohs( Port ) << ", para serem " 03447 << "futuramente enviados." << endl; 03448 #endif 03449 03450 #ifdef RIO_DEBUG1 03451 TCPLOG << "[CNetTcp - SendDataPrivate] Finish2" << endl; 03452 #endif 03453 03454 return S_OK; 03455 }
void CNetTcp::setLogRotation | ( | CLogRotation * | LogRotation | ) |
Funcao para definir o objeto (do tipo CLogRotation) a ser usado para armazenar as estatisticas de envio de pacotes.
LogRotation | ponteiro para um objeto do tipo CLogRotation. |
Definition at line 4323 of file NetTcp.cpp.
04324 { 04325 #ifdef RIO_DEBUG1 04326 TCPLOG << "[CNetTcp - setLogRotation] Start" << endl; 04327 #endif 04328 04329 // Verifica se o objeto foi inicializado. 04330 if( !m_Started ) 04331 { 04332 #ifdef RIO_DEBUG2 04333 TCPLOG << "CNetTcp::setLogRotation o objeto nao foi inicializado. Nao " 04334 << "foi possivel setar o objeto de controle de logs." << endl; 04335 #endif 04336 04337 #ifdef RIO_DEBUG1 04338 TCPLOG << "[CNetTcp - setLogRotation] Finish1" << endl; 04339 #endif 04340 04341 return; 04342 } 04343 04344 // Altera o objeto usado para armazenar a estatistica dos pacotes que 04345 // foram enviados. 04346 m_LogRotation = LogRotation; 04347 04348 #ifdef RIO_DEBUG1 04349 TCPLOG << "[CNetTcp - setLogRotation] Finish2" << endl; 04350 #endif 04351 04352 }
RioResult CNetTcp::Start | ( | SNetTcpConfig * | NetConfig | ) |
Funcao para inicializar a classe.
Esta funcao deve ser chamada antes de a classe poder ser usada.
NetConfig | estrutura com as configuracoes do objeto (veja as estruturas acima). |
Definition at line 3563 of file NetTcp.cpp.
03564 { 03565 #ifdef RIO_DEBUG1 03566 TCPLOG << "[CNetTcp - Start] Start" << endl; 03567 #endif 03568 03569 // Verifica se o objeto ja foi inicializado. 03570 if( m_Started ) 03571 { 03572 #ifdef RIO_DEBUG2 03573 TCPLOG << "CNetTcp::Start o objeto ja foi inicializado." << endl; 03574 #endif 03575 03576 #ifdef RIO_DEBUG1 03577 TCPLOG << "[CNetTcp - Start] Finish1" << endl; 03578 #endif 03579 03580 return ERROR_NETTCP + ERROR_STARTED; 03581 } 03582 03583 // Inicializa os campos comuns ao servidor e ao cliente. 03584 m_ReceiveTimeOut = NetConfig->ReceiveTimeOut; 03585 m_SendTimeOut = NetConfig->SendTimeOut; 03586 m_ConnectionTimeOut = NetConfig->ConnectionTimeOut; 03587 m_ServerInstance = NetConfig->isServer; 03588 m_IP = NetConfig->HostIP; 03589 03590 // Agora temos as configuracoes que dependem do cliente e do servidor. 03591 if( m_ServerInstance ) 03592 { 03593 // No caso do servidor, precisamos criar a thread responsavel por criar 03594 // novas conexoes TCP, usando a porta NetConfig->ServerPort. 03595 03596 // Armazena os atributos da thread do servidor. 03597 pthread_attr_t attribTcpServerThread; 03598 // Armazena uma copia da variavel m_TcpServerStarted (para evitar 03599 // criarmos um comando else ao verificarmos se a thread do servidor 03600 // inicializou corretamente). 03601 bool TcpServerStarted; 03602 03603 // Inicializa as variaveis usadas pelo servidor (mas nao pelo cliente). 03604 m_TcpServerPort = NetConfig->ServerPort; 03605 m_LogRotation = NetConfig->LogRotation; 03606 03607 // Inicializa as variaves usadas pelo cliente com valores invalidos 03608 // (para indicar que elas nao estao sendo usadas). 03609 m_ClientIPAddress = NULL; 03610 m_ClientPorts = NULL; 03611 m_ServerAddress = NULL; 03612 m_AddressSize = 0; 03613 03614 // Inicializa a thread servidora do TCP. 03615 // Configura e cria a thread servidora do TCP. 03616 pthread_attr_init( &attribTcpServerThread ); 03617 pthread_attr_setstacksize( &attribTcpServerThread, 03618 2 * PTHREAD_STACK_MIN ); 03619 03620 // Obtem o lock usado para esperar pela inicializacao da thread 03621 // servidora do TCP. 03622 pthread_mutex_lock( &m_Mutex ); 03623 03624 // Cria a thread usada para gerenciar as transferencias de dados. 03625 if ( pthread_create( &m_TcpServerThreadId, &attribTcpServerThread, 03626 TcpServerThreadEp, this ) != 0 ) 03627 { 03628 // Libera o mutex obtido anteriormente. 03629 pthread_mutex_unlock( &m_Mutex ); 03630 03631 #ifdef RIO_DEBUG2 03632 TCPLOG << "CNetTcp::Start erro " << errno << " (" 03633 << strerror( errno ) << ") ao criar a thread " 03634 << "TcpServerThread." << endl; 03635 #endif 03636 03637 #ifdef RIO_DEBUG1 03638 TCPLOG << "[CNetTcp - Start] Finish2" << endl; 03639 #endif 03640 03641 return ERROR_NETTCP + ERROR_CREATE_THREAD; 03642 } 03643 03644 #ifdef RIO_DEBUG2 03645 TCPLOG << "CNetTcp::Start antes de esperar a therad servidora do TCP " 03646 << "inicializar (com ou sem sucesso)." << endl; 03647 #endif 03648 03649 // Espera pela thread do servidor ser inicializada (corretamente ou 03650 // nao). 03651 pthread_cond_wait( &m_Cond, &m_Mutex ); 03652 03653 #ifdef RIO_DEBUG2 03654 TCPLOG << "CNetTcp::Start depois de esperar a therad servidora do TCP " 03655 << "inicializar. A thread " 03656 << ( ( m_TcpServerStarted ) ? "iniciazou" : "nao inicializou" ) 03657 << " corretamente!" << endl; 03658 #endif 03659 03660 // Copia o valor de m_TcpServerStarted para a variavel local 03661 // TcpServerStarted. 03662 TcpServerStarted = m_TcpServerStarted; 03663 03664 // Libera o mutex obtido anteriormente. 03665 pthread_mutex_unlock( &m_Mutex ); 03666 03667 if( !TcpServerStarted ) 03668 { 03669 #ifdef RIO_DEBUG2 03670 TCPLOG << "CNetTcp::Start erro ao inicializar a thread " 03671 << "TcpServerThread." << endl; 03672 #endif 03673 03674 // Desbloqueia e espera a thread de recebimento terminar (talvez 03675 // seja melhor cancelar a thread, mas nao tenho certeza). 03676 m_CancelThreads = true; 03677 03678 #ifdef RIO_DEBUG1 03679 TCPLOG << "[CNetTcp - Start] Finish3" << endl; 03680 #endif 03681 03682 return ERROR_NETTCP + ERROR_SOCKET_CONNECT; 03683 } 03684 } 03685 else 03686 { 03687 // No caso do cliente, precisamos abrir uma conexao TCP com cada 03688 // servidor cujos pares IP, porta sao dados no vetor 03689 // NetConfig->ServerAddress. 03690 03691 // Armazena o objeto criado para cada conexao TCP. 03692 CTcpConnection *TcpConnection; 03693 03694 // Armazena o par IP, Porta associado ao cliente, retornado pela 03695 // funcao TcpConnect. 03696 int IP, Port; 03697 03698 // Armazena o retorno da funcao send (para terminar a conexao). 03699 RioResult RioStatus; 03700 03701 // Variavel booleana usada para verificarmos se a conexao TCP do 03702 // servidor foi criada. 03703 bool isDispatcherConnectionCreated; 03704 03705 // Variavel booleana usada para verificarmos se a conexao TCP do 03706 // storage foi criada. 03707 bool isStorageConnectionCreated; 03708 03709 // Inicializa as variaves usadas pelo servidor com valores invalidos 03710 // (para indicar que elas nao estao sendo usadas). 03711 m_TcpServerPort = 0; 03712 m_TcpServerThreadId = 0; 03713 03714 // Inicializa as variaveis usadas para detectar o minimo de conexoes 03715 // TCP necessarias (uma conexao com o dispatcher e uma conexao com pelo 03716 // menos um storage). 03717 isDispatcherConnectionCreated = false; 03718 isStorageConnectionCreated = false; 03719 03720 // Inicializa os campos com os servidores aos quais o cliente deve 03721 // se conectar. 03722 m_ServerAddress = NetConfig->ServerAddress; 03723 m_AddressSize = NetConfig->ServerAddressSize; 03724 03725 // Tenta alocar os vetores que receberao os pares IP, Porta associados 03726 // as conexoes dos clientes. 03727 try 03728 { 03729 m_ClientIPAddress = new int[ m_AddressSize ]; 03730 } 03731 catch( bad_alloc& ba ) 03732 { 03733 // Nao conseguimos alocar o vetor que armazenata os IPs usados pelas 03734 // conexoes do cliente. 03735 #ifdef RIO_DEBUG2 03736 TCPLOG << "CNetTcp::Start erro de alocacao de memoria (bad_alloc," 03737 << "error = " << ba.what() << ") ao criar a estrutura " 03738 << "m_ClientIPAddress." << endl; 03739 #endif 03740 03741 #ifdef RIO_DEBUG1 03742 TCPLOG << "[CNetTcp - Start] Finish4" << endl; 03743 #endif 03744 03745 return ERROR_NETTCP + ERROR_MEMORY; 03746 03747 } 03748 03749 // Tenta alocar os vetores que receberao as portas associados as 03750 // conexoes dos clientes. 03751 try 03752 { 03753 m_ClientPorts = new int[ m_AddressSize ]; 03754 } 03755 catch( bad_alloc& ba ) 03756 { 03757 // Nao conseguimos alocar o vetor que armazenata as portas usadas 03758 // pelas conexoes do cliente. Logo, devemos deletar o vetor com os 03759 // IPs alocados anteriormente. 03760 delete[] m_ClientIPAddress; 03761 03762 #ifdef RIO_DEBUG2 03763 TCPLOG << "CNetTcp::Start erro de alocacao de memoria (bad_alloc," 03764 << "error = " << ba.what() << ") ao criar a estrutura " 03765 << "m_ClientPorts." << endl; 03766 #endif 03767 03768 #ifdef RIO_DEBUG1 03769 TCPLOG << "[CNetTcp - Start] Finish5" << endl; 03770 #endif 03771 03772 return ERROR_NETTCP + ERROR_MEMORY; 03773 03774 } 03775 03776 // Tentamos abrir as conexoes TCP com os servidores. 03777 for( unsigned int i = 0; i < m_AddressSize; i++ ) 03778 { 03779 // Tenta conectar ao servidor (dispatcher ou storage) da posicao i 03780 // do vetor com o endereco dos servidores. 03781 TcpConnection = TcpConnect( m_ServerAddress[ i ].sin_addr.s_addr, 03782 m_ServerAddress[ i ].sin_port, 03783 &IP, &Port ); 03784 if( TcpConnection == NULL ) 03785 { 03786 // Nao conseguimos nos conectar no servidor da posicao i. 03787 03788 #ifdef RIO_DEBUG2 03789 TCPLOG << "CNetTcp::Start erro ao criar a conexao TCP para o IP" 03790 << inet_ntoa( m_ServerAddress[ i ].sin_addr ) 03791 << " a a porta " 03792 << ntohs( m_ServerAddress[ i ].sin_port ) << endl; 03793 #endif 03794 03795 // No caso de erro, fazemos o IP = -1 e a porta = 0. 03796 m_ClientIPAddress[ i ] = -1; 03797 m_ClientPorts[ i ] = 0; 03798 } 03799 else 03800 { 03801 // Salva o par IP, Porta da conexao do cliente com o servidor da 03802 // posicao i do vetor m_ServerAddress. 03803 m_ClientIPAddress[ i ] = IP; 03804 m_ClientPorts[ i ] = Port; 03805 03806 // Inicializamos as variaveis para indicarmos se a conexao TCP 03807 // com o servidor (se i for igual a 0) ou pelo menos uma das 03808 // conexoes com o storage (se i for diferente de 0) foi criada 03809 // com sucesso. 03810 if( i == 0 ) 03811 isDispatcherConnectionCreated = true; 03812 else 03813 isStorageConnectionCreated = true; 03814 } 03815 03816 #ifdef RIO_DEBUG2 03817 // Imprime o IP e a porta associada a nova conexao. 03818 in_addr ip; 03819 // Define primeiramente o IP do servidor. 03820 if( ( m_ClientIPAddress[ i ] != -1 ) && 03821 ( m_ClientPorts[ i ] != 0 ) ) 03822 { 03823 TCPLOG << "CNetTcp::Start o cliente estabeleceu uma conexao " 03824 << "TCP com o servidor da posicao " << i << " do vetor " 03825 << "cujo IP e igual a " 03826 << inet_ntoa( m_ServerAddress[ i ].sin_addr ) 03827 << " e cuja porta e igual a " 03828 << ntohs( m_ServerAddress[ i ].sin_port ); 03829 fflush( stderr ); 03830 ip.s_addr = m_ClientIPAddress[ i ]; 03831 TCPLOG << ". A conexao foi associada ao IP " << inet_ntoa( ip ) 03832 << " e a porta " << ntohs( m_ClientPorts[ i ] ) << "." 03833 << endl; 03834 } 03835 else 03836 { 03837 TCPLOG << "CNetTcp::Start o cliente nao consegui estabelecer " 03838 << "uma conexao TCP com o servidor da posicao " << i 03839 << " do vetor cujo IP e com o igual a " 03840 << inet_ntoa( m_ServerAddress[ i ].sin_addr ) 03841 << " e cuja porta e igual a " 03842 << ntohs( m_ServerAddress[ i ].sin_port ) << "." << endl; 03843 } 03844 #endif 03845 } 03846 03847 // Verifica se foram criadas a conexao TCP com o dispatcher, e pelo 03848 // menos uma conexao TCP com um storage. 03849 if( ( !isDispatcherConnectionCreated ) || 03850 ( !isStorageConnectionCreated ) ) 03851 { 03852 // Fecha todas as conexoes que foram criadas com sucesso. 03853 RioStatus = CloseAllConnections(); 03854 #ifdef RIO_DEBUG2 03855 if( FAILED( RioStatus ) ) 03856 { 03857 TCPLOG << "CNetTcp::Start erro 0x" << hex << RioStatus 03858 << dec << " (" << GetErrorDescription( RioStatus ) 03859 << ") ao finalizar as conexoes TCP que foram " 03860 << "criadas com sucesso." << endl; 03861 } 03862 #endif 03863 03864 // Remove o vetor com os enderecos IPs do cliente nos servidores. 03865 delete[] m_ClientIPAddress; 03866 03867 // Remove o vetor com as portas do cliente nos servidores. 03868 delete[] m_ClientPorts; 03869 03870 #ifdef RIO_DEBUG1 03871 TCPLOG << "[CNetTcp - Start] Finish6" << endl; 03872 #endif 03873 03874 return ERROR_NETTCP + ERROR_SOCKET_CONNECT; 03875 } 03876 } 03877 03878 // Como inicializamos a classe corretamente, alteramos m_Started para true e 03879 // retornamos S_OK. 03880 m_Started = true; 03881 03882 #ifdef RIO_DEBUG2 03883 TCPLOG << "CNetTcp::Start objeto inicializado com sucesso!" << endl; 03884 #endif 03885 03886 #ifdef RIO_DEBUG1 03887 TCPLOG << "[CNetTcp - Start] Finish7" << endl; 03888 #endif 03889 03890 return S_OK; 03891 }
RioResult CNetTcp::Stop | ( | void | ) |
Funcao para parar o funcionamento do object (isto e, fechar todas as conexoes TCP e terminar todas as threads).
Definition at line 3895 of file NetTcp.cpp.
03896 { 03897 // Variavel usada para armazenar o retorno da funcao. 03898 RioResult RioStatus; 03899 03900 #ifdef RIO_DEBUG1 03901 TCPLOG << "[CNetTcp - Stop] Start" << endl; 03902 #endif 03903 03904 // Verifica se o objeto foi inicializado. 03905 if( !m_Started ) 03906 { 03907 #ifdef RIO_DEBUG2 03908 TCPLOG << "CNetTcp::Stop o objeto nao foi inicializado." << endl; 03909 #endif 03910 03911 #ifdef RIO_DEBUG1 03912 TCPLOG << "[CNetTcp - Stop] Finish1" << endl; 03913 #endif 03914 03915 return ERROR_NETTCP + ERROR_NOT_STARTED; 03916 } 03917 03918 // A finalizacao dependera do objeto estar associado a um cliente ou a um 03919 // dos servidores. 03920 if( m_ServerInstance ) 03921 { 03922 // Da um shutdown no socket principal do servidor. 03923 shutdown( m_TcpServerSocket, SHUT_RDWR ); 03924 // Fecha o socket do servidor 03925 close( m_TcpServerSocket ); 03926 03927 #ifdef RIO_DEBUG2 03928 TCPLOG << "CNetTcp::Stop Antes de executar pthread_cancel para a thread " 03929 << "com a ID " << m_TcpServerThreadId << "." << endl; 03930 #endif 03931 03932 // Esperamos o accept retornar EBADF, o que deveria ocorrer porque 03933 // fechamos o socket principal do servidor TCP. 03934 pthread_join( m_TcpServerThreadId, NULL ); 03935 03936 #ifdef RIO_DEBUG2 03937 TCPLOG << "CNetTcp::Stop Depois de executar pthread_cancel para a thread " 03938 << "com a ID " << m_TcpServerThreadId << "." << endl; 03939 #endif 03940 } 03941 03942 // Tenta fechar todas as conexoes TCP ativas. 03943 RioStatus = CloseAllConnections(); 03944 if( FAILED( RioStatus ) ) 03945 { 03946 #ifdef RIO_DEBUG2 03947 TCPLOG << "CNetTcp::Stop erro 0x" << hex << RioStatus << dec << " (" 03948 << GetErrorDescription( RioStatus ) << "ao fechar as conexoes " 03949 << "TCP ativas!" << endl; 03950 #endif 03951 03952 #ifdef RIO_DEBUG1 03953 TCPLOG << "[CNetTcp - Stop] Finish2" << endl; 03954 #endif 03955 03956 return RioStatus; 03957 } 03958 03959 // Se for o cliente, devemos remover os vetores com os IPs e as portas das 03960 // conexoes do cliente com os servidores. 03961 if( !m_ServerInstance ) 03962 { 03963 // Remove o vetor com os enderecos IPs do cliente nos servidores. 03964 if( m_ClientIPAddress != NULL ) 03965 delete[] m_ClientIPAddress; 03966 m_ClientIPAddress = NULL; 03967 03968 // Remove o vetor com as portas do cliente nos servidores. 03969 if( m_ClientPorts != NULL ) 03970 delete[] m_ClientPorts; 03971 m_ClientPorts = NULL; 03972 } 03973 03974 // Define que o objeto nao esta inicializado (para futuramente ser novamente 03975 // inicializado) 03976 m_Started = false; 03977 03978 #ifdef RIO_DEBUG2 03979 TCPLOG << "CNetTcp::Stop objeto parado com sucesso!" << endl; 03980 #endif 03981 03982 #ifdef RIO_DEBUG1 03983 TCPLOG << "[CNetTcp - Stop] Finish3" << endl; 03984 #endif 03985 03986 return S_OK; 03987 }
CTcpConnection * CNetTcp::TcpAccept | ( | int | ClientSocket, | |
int | ClientIP, | |||
int | ClientPort | |||
) | [private] |
Funcao executada, pelo servidor, para inicializar e, se nao ocorrer um erro, aceitar definitivamente uma conexao TCP criada com o cliente.
ClientSocket | socket criado para o cliente pela chamada ao sistema accept. | |
ClientIP | IP da conexao TCP com o cliente. | |
ClientPort | porta da conexao TCP com o cliente. |
Definition at line 2306 of file NetTcp.cpp.
02308 { 02309 // Armazena o ponteiro para um novo objeto que representa uma conexao. 02310 CTcpConnection *TcpConnection; 02311 // Armazena o tempo de timeout para os comandos send e recv. 02312 struct timeval timeout; 02313 // Armazena os dados recebidos do cliente. 02314 SNetTcpClientData ClientData; 02315 // Armazena os dados a serem enviados ao cliente. 02316 SNetTcpServerData ServerData; 02317 // Armazena o erro retornado pelas funcoes do RIO. 02318 RioResult RioStatus; 02319 // Armazena a string recebida no inicio da conexao, usada para detectar se 02320 // o cliente usa a implementacao nova ou a antiga. 02321 char ConnectionID[ TCP_START_MESSAGE_SIZE + 1 ]; 02322 // Variavel para armazenar o valor passado a funcao setsockopt, usado para 02323 // habilitar/desabilitar a bufferizacao no socket. 02324 int opt; 02325 02326 #ifdef RIO_DEBUG1 02327 TCPLOG << "[CNetTcp - TcpAccept] Start" << endl; 02328 #endif 02329 02330 #ifdef RIO_DEBUG2 02331 struct in_addr ip, ipc; 02332 ip.s_addr = ClientIP; 02333 02334 TCPLOG << "CNetTcp::TcpAccept ACCEPT vindo do cliente com " 02335 << "IP " << inet_ntoa( ip ) << " e porta " << ntohs( ClientPort ) 02336 << "." << endl; 02337 #endif 02338 02339 // Faz com que o socket seja exclusivo do processo, e nao seja passado 02340 // para um outro processo criado pelo processo que abriu o socket. 02341 if( fcntl( ClientSocket, F_SETFD, FD_CLOEXEC ) < 0 ) 02342 { 02343 #ifdef RIO_DEBUG2 02344 TCPLOG << "CNetTcp::TcpAccept erro " << errno << " (" 02345 << strerror( errno ) << ") ao fazer o socket de um cliente ser " 02346 << "exclusivo ao processo que criou o objeto da classe CNetTcp." 02347 << endl; 02348 #endif 02349 02350 #ifdef RIO_DEBUG1 02351 TCPLOG << "[CNetTcp - TcpAccept] Finish1" << endl; 02352 #endif 02353 02354 return( NULL ); 02355 } 02356 02357 // Altera o socket TCP para evitar que os dados sejam buferizados durante o 02358 // processo inicial de conexao (depois da conexao ser estabelecida com 02359 // sucesso, fazemos novamente o socket ser buferizado, pois isso parece ser 02360 // necessario para usar a opcao MSG_MORE no send, que nao tera efeito em 02361 // caso contrario, possivelmente sendo a responsavel pelo travamento do 02362 // servidor na segunda chamada da funcao recv). 02363 opt = 1; 02364 02365 if( setsockopt( ClientSocket, IPPROTO_TCP, TCP_NODELAY, (char *) &opt, 02366 sizeof( int ) ) < 0 ) 02367 { 02368 #ifdef RIO_DEBUG2 02369 TCPLOG << "CNetTcp::TcpAccept erro " << errno << " (" 02370 << strerror( errno ) << ") ao executar o setsockopt com o nivel " 02371 << "IPPROTO_TCP, opcao TCP_NODELAY." << endl; 02372 #endif 02373 02374 #ifdef RIO_DEBUG1 02375 TCPLOG << "[CNetTcp - TcpAccept] Finish2" << endl; 02376 #endif 02377 02378 return( NULL ); 02379 } 02380 02381 // Define um timeout para o recv de no maximo m_ReceiveTimeOut, para 02382 // evitar que o servidor ou o cliente fiquem bloqueados na funcao recv. 02383 timeout.tv_sec = m_ReceiveTimeOut / 1000; 02384 timeout.tv_usec = ( m_ReceiveTimeOut % 1000 ) * 1000; 02385 02386 if( setsockopt( ClientSocket, SOL_SOCKET, SO_RCVTIMEO, &timeout, 02387 sizeof( timeout ) ) < 0 ) 02388 { 02389 TCPLOG << "CNetTCP::TcpAccept erro " << errno << " (" 02390 << strerror( errno ) << ") ao executar o setsockopt com o nivel " 02391 << "SOL_SOCKET e a opcao SO_RCVTIMEO." << endl; 02392 close( ClientSocket ); 02393 02394 #ifdef RIO_DEBUG1 02395 TCPLOG << "[CNetTcp - TcpAccept] Finish3" << endl; 02396 #endif 02397 02398 return( NULL ); 02399 } 02400 02401 // Define um timeout para o send de no maximo m_SendTimeOut, para 02402 // evitar que o servidor ou o cliente fiquem bloqueados na funcao send. 02403 timeout.tv_sec = m_SendTimeOut / 1000; 02404 timeout.tv_usec = ( m_SendTimeOut % 1000 ) * 1000; 02405 02406 if( setsockopt( ClientSocket, SOL_SOCKET, SO_SNDTIMEO, &timeout, 02407 sizeof( timeout ) ) < 0 ) 02408 { 02409 TCPLOG << "CNetTCP::TcpAccept erro " << errno << " (" 02410 << strerror( errno ) << ") ao executar o setsockopt com o nivel " 02411 << "SOL_SOCKET e a opcao SO_SNDTIMEO." << endl; 02412 02413 #ifdef RIO_DEBUG1 02414 TCPLOG << "[CNetTcp - TcpAccept] Finish4" << endl; 02415 #endif 02416 02417 return( NULL ); 02418 } 02419 02420 // Recebe primeiramente o identificador usado para sabermos que o cliente 02421 // esta usando a nova implementacao do TCP (no caso de ser o cliente com 02422 // a implementacao antiga, fecharemos a conexao, esperando que o cliente 02423 // aborte a tentativa de conexao ao tentar enviar a proxima informacao 02424 // depois da string enviada, com 5 bytes, que sera igual a 00001 caso o 02425 // cliente consigua alocar um stream ou 00000 em caso contrario, e sera 02426 // diferente da string TCP_START_MESSAGE que usamos. 02427 memset( ConnectionID, 0, TCP_START_MESSAGE_SIZE + 1 ); 02428 if( recv( ClientSocket, ConnectionID, TCP_START_MESSAGE_SIZE, 02429 TCP_FLAGS_RECEIVE ) < 0 ) 02430 { 02431 #ifdef RIO_DEBUG2 02432 TCPLOG << "CNetTcp::TcpAccept erro " << errno << " (" 02433 << strerror( errno ) << ") ao receber o identificador da " 02434 << "conexao." << endl; 02435 #endif 02436 02437 #ifdef RIO_DEBUG1 02438 TCPLOG << "[CNetTcp - TcpAccept] Finish5" << endl; 02439 #endif 02440 02441 return( NULL ); 02442 } 02443 02444 // Verificamos agora se o identificador e valido. 02445 if( strcmp( ConnectionID, TCP_START_MESSAGE ) != 0 ) 02446 { 02447 #ifdef RIO_DEBUG2 02448 TCPLOG << "CNetTcp::TcpAccept recebido um identificador de conexao " 02449 << "invalido " << ConnectionID << ". O identificador deveria " 02450 << "ser " << TCP_START_MESSAGE << ". Fechando a conexao TCP " 02451 << "com o cliente." << endl; 02452 #endif 02453 02454 #ifdef RIO_DEBUG1 02455 TCPLOG << "[CNetTcp - TcpAccept] Finish6" << endl; 02456 #endif 02457 02458 return( NULL ); 02459 } 02460 02461 // Recepcao dos dados enviados pelo servidor sobre a conexao. 02462 memset( &ClientData, 0, sizeof( ClientData ) ); 02463 if( recv( ClientSocket, &ClientData, sizeof( ClientData ), 02464 TCP_FLAGS_RECEIVE ) < 0 ) 02465 { 02466 #ifdef RIO_DEBUG2 02467 TCPLOG << "CNetTcp::TcpAccept erro " << errno << " (" 02468 << strerror( errno ) << ") ao receber as informacao do cliente." 02469 << endl; 02470 #endif 02471 02472 #ifdef RIO_DEBUG1 02473 TCPLOG << "[CNetTcp - TcpAccept] Finish7" << endl; 02474 #endif 02475 02476 return( NULL ); 02477 } 02478 02479 #ifdef RIO_DEBUG2 02480 TCPLOG << "CNetTcp::TcpAccept O cliente " 02481 << ( ( ClientData.ConnectionCreated ) ? "tem" : "nao tem" ) 02482 << " espaco no buffer para uma conexao." << endl; 02483 #endif 02484 02485 if( ClientData.ConnectionCreated ) // Se existe espaco no cliente. 02486 { 02487 // Estabeleco a conexao e posso enviar pacotes. 02488 RioStatus = NewConnection( ClientData.IP, ClientData.Port, 02489 ClientSocket, &TcpConnection ); 02490 if( FAILED( RioStatus ) ) 02491 { 02492 #ifdef RIO_DEBUG2 02493 TCPLOG << "CNetTcp::TcpAccept erro 0x" << hex << RioStatus << dec 02494 << " (" << GetErrorDescription( RioStatus ) 02495 << ") ao criar um objeto para a conexao do socket." << endl; 02496 #endif 02497 } 02498 02499 #ifdef RIO_DEBUG2 02500 // Se existir espaco no buffer do servidor, imprime que conseguiu criar 02501 // um stream com sucesso. 02502 if( TcpConnection != NULL ) 02503 { 02504 ipc.s_addr = ClientData.IP; 02505 TCPLOG << "CNetTcp::TcpAccept criando uma nova conexao TCP: " 02506 << "socket = " << ClientSocket << ", IP TCP (Servidor) = " 02507 << inet_ntoa( ip ) << ", porta TCP (Servidor) = " 02508 << ntohs( ClientPort ) << ", IP TCP (Cliente) = " 02509 << inet_ntoa( ipc ) << ", porta TCP (Cliente) = " 02510 << ntohs( ClientData.Port ) << "." << endl; 02511 } 02512 #endif 02513 } 02514 else 02515 { 02516 // nao tem espaco no buffer do cliente. 02517 TcpConnection = NULL; 02518 02519 #ifdef RIO_DEBUG2 02520 TCPLOG << "CNetTcp::TcpAccept nao existe espaco para criar um objeto " 02521 << "de conexao no cliente com o IP = " << inet_ntoa( ip ) 02522 << " e a porta " << ntohs( ClientPort ) << endl; 02523 #endif 02524 } 02525 02526 // Preparacao dos dados do servidor. 02527 memset( &ServerData, 0, sizeof( ServerData ) ); 02528 ServerData.ConnectionCreated = ( TcpConnection != NULL ); 02529 02530 // Envio dos dados do servidor 02531 if( send( ClientSocket, &ServerData, sizeof( ServerData ), 02532 TCP_FLAGS_SENDDATA ) < 0 ) 02533 { 02534 #ifdef RIO_DEBUG2 02535 TCPLOG << "CNetTcp::TcpAccept erro " << errno << " (" 02536 << strerror( errno ) << ") ao enviar a informacao de espaco " 02537 << "disponivel no servidor para criar conexoes" << endl; 02538 #endif 02539 02540 // Remove o objeto associado a conexao TCP do cliente. 02541 if( TcpConnection != NULL ) 02542 { 02543 // Cancela a thread de conexao. 02544 RioStatus = TcpConnection->CancelConnection(); 02545 #ifdef RIO_DEBUG2 02546 TCPLOG << "CNetTcp::TcpAccept erro 0x" << hex << RioStatus << dec 02547 << " (" << GetErrorDescription( RioStatus ) << ") ao " 02548 << "executar a funcao CancelConnection sobre o objeto da " 02549 << "conexao TcpConnection." << endl; 02550 02551 #endif 02552 // Delete o objeto. 02553 delete TcpConnection; 02554 } 02555 02556 #ifdef RIO_DEBUG1 02557 TCPLOG << "[RioNeti - TcpAccept] Finish8" << endl; 02558 #endif 02559 02560 return( NULL ); 02561 } 02562 02563 if( TcpConnection == NULL ) 02564 { 02565 // Se ocorreu um erro ao alocar o espaco, devemos fechar a conexao 02566 #ifdef RIO_DEBUG2 02567 TCPLOG << "CNetTcp::TcpAccept Erro ao se conectar ao cliente. Nao " 02568 << "existe espaco para criar um objeto de conexao para o " 02569 << "cliente" << endl; 02570 #endif 02571 02572 #ifdef RIO_DEBUG1 02573 TCPLOG << "[CNetTcp - TcpAccept] Finish9" << endl; 02574 #endif 02575 02576 return( NULL ); 02577 } 02578 02579 // Altera o socket TCP para que os dados voltem a ser bufferizados (isso e, 02580 // cmo dissemos antes, ao desabilitar a bufferizacao, aparentemente 02581 // necessario para usarmos a opcao MSG_MORE no send). 02582 opt = 0; 02583 02584 if( setsockopt( ClientSocket, IPPROTO_TCP, TCP_NODELAY, (char *) &opt, 02585 sizeof( int ) ) < 0 ) 02586 { 02587 #ifdef RIO_DEBUG2 02588 TCPLOG << "CNetTcp::TcpAccept erro " << errno << " (" 02589 << strerror( errno ) << ") ao executar o setsockopt com o nivel " 02590 << "IPPROTO_TCP, opcao TCP_NODELAY." << endl; 02591 #endif 02592 02593 // Cancela a thread de conexao. 02594 RioStatus = TcpConnection->CancelConnection(); 02595 #ifdef RIO_DEBUG2 02596 TCPLOG << "CNetTcp::TcpAccept erro 0x" << hex << RioStatus << dec 02597 << " (" << GetErrorDescription( RioStatus ) << ") ao executar " 02598 << "a funcao CancelConnection sobre o objeto da conexao " 02599 << "TcpConnection." << endl; 02600 02601 #endif 02602 // Delete o objeto. 02603 delete TcpConnection; 02604 02605 #ifdef RIO_DEBUG1 02606 TCPLOG << "[CNetTcp - TcpAccept] Finish10" << endl; 02607 #endif 02608 02609 return( NULL ); 02610 } 02611 02612 // Como acabamos de finalizar o processo inicial de conexao, e como ele 02613 // foi feito com sucesso, habilitamos a conexao (desbloqueando a thread da 02614 // conexao) e colocamos o objeto associado a conexao na hash com todas as 02615 // conexoes. 02616 RioStatus = EnableConnection( TcpConnection ); 02617 if( FAILED( RioStatus ) ) 02618 { 02619 #ifdef RIO_DEBUG2 02620 TCPLOG << "CNetTcp::TcpAccept erro 0x" << hex << RioStatus << dec 02621 << " (" << GetErrorDescription( RioStatus ) 02622 << ") ao ativar o objeto de conexao criado para o socket." 02623 << endl; 02624 #endif 02625 02626 // Cancela a thread de conexao. 02627 RioStatus = TcpConnection->CancelConnection(); 02628 #ifdef RIO_DEBUG2 02629 TCPLOG << "CNetTcp::TcpAccept erro 0x" << hex << RioStatus << dec 02630 << " (" << GetErrorDescription( RioStatus ) << ") ao executar " 02631 << "a funcao CancelConnection sobre o objeto da conexao " 02632 << "TcpConnection." << endl; 02633 02634 #endif 02635 // Delete o objeto. 02636 delete TcpConnection; 02637 02638 #ifdef RIO_DEBUG1 02639 TCPLOG << "[CNetTcp - TcpAccept] Finish11" << endl; 02640 #endif 02641 02642 return( NULL ); 02643 } 02644 02645 #ifdef RIO_DEBUG2 02646 TCPLOG << "CNetTcp::TcpAccept Conectei ao cliente." << endl; 02647 #endif 02648 02649 #ifdef RIO_DEBUG1 02650 TCPLOG << "[CNetTcp - TcpAccept] Finish12" << endl; 02651 #endif 02652 02653 return( TcpConnection ); 02654 }
CTcpConnection * CNetTcp::TcpConnect | ( | int | ServerIP, | |
int | ServerPort, | |||
int * | ClientIP, | |||
int * | ClientPort | |||
) | [private] |
Funcao para estabelecer uma conexao TCP com um dos servidores.
ServerIP | endereco IP da conexao TCP no servidor. | |
ServerPort | porta da conexao TCP no servidor. | |
ClientIP | ponteiro para armazenar o IP associado ao cliente (criada pela conexao). | |
ClientPort | ponteiro para armazenar a porta associada ao cliente (tambem criada pela conexao). |
Definition at line 2658 of file NetTcp.cpp.
02660 { 02661 // Armazena o identificador do socket criado pela conexao com o servidor. 02662 int ServerSocket; 02663 // Armazena o ponteiro para um novo objeto que representa uma conexao. 02664 CTcpConnection *TcpConnection; 02665 // Armazena o tempo de timeout para os comandos send e recv. 02666 struct timeval timeout; 02667 // Armazena os dados recebidos do cliente. 02668 SNetTcpClientData ClientData; 02669 // Armazena os dados a serem enviados ao cliente. 02670 SNetTcpServerData ServerData; 02671 // Armazena o erro retornado pelas funcoes do RIO. 02672 RioResult RioStatus; 02673 // Armazena o endereco do servidor destino (usado pela funcao connect). 02674 struct sockaddr_in ServerAddr; 02675 // Armazena o endereco atribuido, no cliente, a conexao TCP com o servidor. 02676 struct sockaddr_in ClientAddr; 02677 // Armazena o tamanho da estrutura ClientAddr (necessario para obter o 02678 // endereco do cliente). 02679 socklen_t ClientAddrLen; 02680 // Variavel para armazenar o valor passado a funcao setsockopt, usado para 02681 // habilitar/desabilitar a bufferizacao no socket. 02682 int opt; 02683 02684 #ifdef RIO_DEBUG1 02685 TCPLOG << "[CNetTcp - TcpConnect] Start" << endl; 02686 #endif 02687 02688 #ifdef RIO_DEBUG2 02689 struct in_addr ip; 02690 02691 ip.s_addr = ServerIP; 02692 #endif 02693 02694 // Cria um socket para se conectar a um dos servidores. 02695 if( ( ServerSocket = socket( AF_INET, SOCK_STREAM, 0 ) ) < 0 ) 02696 { 02697 #ifdef RIO_DEBUG2 02698 TCPLOG << "CNetTcp::TcpConnect erro " << errno << " (" 02699 << strerror( errno ) << ") ao criar o socket de conexao." 02700 << endl; 02701 #endif 02702 02703 RioErr << "[TcpConnect] erro " << errno << " (" << strerror( errno ) 02704 << ") ao executar a funcao socket." << endl; 02705 02706 #ifdef RIO_DEBUG1 02707 TCPLOG << "[CNetTcp - TcpConnect] Finish1" << endl; 02708 #endif 02709 02710 return( NULL ); 02711 } 02712 02713 // Faz com que o socket seja exclusivo do processo, e nao seja passado 02714 // para um outro processo criado pelo processo que abriu o socket. 02715 if( fcntl( ServerSocket, F_SETFD, FD_CLOEXEC ) < 0 ) 02716 { 02717 #ifdef RIO_DEBUG2 02718 TCPLOG << "CNetTcp::TcpConnect erro " << errno << " (" 02719 << strerror( errno ) << ") ao fazer o socket de um servidor ser " 02720 << "exclusivo ao processo que criou o objeto da classe CNetTcp." 02721 << endl; 02722 #endif 02723 02724 RioErr << "[TcpConnect] erro " << errno << " (" << strerror( errno ) 02725 << ") ao executar o fcntl com as opcoes F_SETFD e a FD_CLOEXEC." 02726 << endl; 02727 02728 // Informa que nada deve ser recebido pela conexao 02729 shutdown( ServerSocket, SHUT_RDWR ); 02730 02731 // Fecha o socket com o servidor. 02732 close( ServerSocket ); 02733 02734 #ifdef RIO_DEBUG1 02735 TCPLOG << "[CNetTcp - TcpAccept] Finish2" << endl; 02736 #endif 02737 02738 return( NULL ); 02739 } 02740 02741 // Altera o socket TCP para evitar que os dados sejam buferizados durante o 02742 // processo inicial de conexao (depois da conexao ser estabelecida com 02743 // sucesso, fazemos novamente o socket ser buferizado, pois isso parece ser 02744 // necessario para usar a opcao MSG_MORE no send, que nao tera efeito em 02745 // caso contrario, possivelmente sendo a responsavel pelo travamento do 02746 // servidor na segunda chamada da funcao recv). 02747 opt = 1; 02748 02749 if( setsockopt( ServerSocket, IPPROTO_TCP, TCP_NODELAY, (char *) &opt, 02750 sizeof( int ) ) < 0 ) 02751 { 02752 RioErr << "[TcpConnect] erro " << errno << " (" << strerror( errno ) 02753 << ") ao executar o setsockopt com o nivel IPPROTO_TCP e a " 02754 << "opcao TCP_NODELAY." << endl; 02755 02756 // Informa que nada deve ser recebido pela conexao 02757 shutdown( ServerSocket, SHUT_RDWR ); 02758 02759 // Fecha o socket com o servidor. 02760 close( ServerSocket ); 02761 02762 #ifdef RIO_DEBUG1 02763 TCPLOG << "[CNetTcp - TcpConnect] Finish3" << endl; 02764 #endif 02765 02766 return( NULL ); 02767 } 02768 02769 // Define o endereco do servidor com o qual desejamos no conectar por TCP. 02770 memset( &ServerAddr, 0, sizeof( ServerAddr ) ); 02771 02772 ServerAddr.sin_family = AF_INET; 02773 ServerAddr.sin_addr.s_addr = ServerIP; 02774 ServerAddr.sin_port = ServerPort; 02775 02776 #ifdef RIO_DEBUG2 02777 TCPLOG << "CNetTcp::TcpConnect vou tentar conectar (connect) ao servidor " 02778 << "com o IP " << inet_ntoa( ip ) << " e a porta " 02779 << ntohs( ServerPort ) << endl; 02780 #endif 02781 02782 // Conecta ao servidor destino 02783 if( connect( ServerSocket, ( struct sockaddr * ) &ServerAddr, 02784 sizeof( ServerAddr ) ) < 0 ) 02785 { 02786 RioErr << "[TcpConnect] erro " << errno << " (" << strerror( errno ) 02787 << ") ao conectar ao socket TCP." << endl; 02788 02789 // Informa que nada deve ser recebido pela conexao 02790 shutdown( ServerSocket, SHUT_RDWR ); 02791 02792 // Fecha o socket com o servidor. 02793 close( ServerSocket ); 02794 02795 #ifdef RIO_DEBUG1 02796 TCPLOG << "[CNetTcp - TcpConnect] Finish4" << endl; 02797 #endif 02798 02799 return( NULL ); 02800 } 02801 02802 // Define um timeout para o recv de no maximo m_ReceiveTimeOut, para 02803 // evitar que o servidor ou o cliente fiquem bloqueados na funcao recv. 02804 timeout.tv_sec = m_ReceiveTimeOut / 1000; 02805 timeout.tv_usec = ( m_ReceiveTimeOut % 1000 ) * 1000; 02806 02807 if( setsockopt( ServerSocket, SOL_SOCKET, SO_RCVTIMEO, &timeout, 02808 sizeof( timeout ) ) < 0 ) 02809 { 02810 RioErr << "[TcpConnect] erro " << errno << " (" << strerror( errno ) 02811 << ") ao executar o setsockopt com o nivel SOL_SOCKET e a opcao " 02812 << "SO_RCVTIMEO." << endl; 02813 02814 // Informa que nada deve ser recebido pela conexao 02815 shutdown( ServerSocket, SHUT_RDWR ); 02816 02817 // Fecha o socket com o servidor. 02818 close( ServerSocket ); 02819 02820 #ifdef RIO_DEBUG1 02821 TCPLOG << "[CNetTcp - TcpConnect] Finish5" << endl; 02822 #endif 02823 02824 return( NULL ); 02825 } 02826 02827 // Define um timeout para o send de no maximo m_SendTimeOut, para 02828 // evitar que o servidor ou o cliente fiquem bloqueados na funcao send. 02829 timeout.tv_sec = m_SendTimeOut / 1000; 02830 timeout.tv_usec = ( m_SendTimeOut % 1000 ) * 1000; 02831 02832 if( setsockopt( ServerSocket, SOL_SOCKET, SO_SNDTIMEO, &timeout, 02833 sizeof( timeout ) ) < 0 ) 02834 { 02835 RioErr << "[TcpConnect] erro " << errno << " (" << strerror( errno ) 02836 << ") ao executar o setsockopt com o nivel SOL_SOCKET e a opcao " 02837 << "SO_SNDTIMEO." << endl; 02838 02839 // Informa que nada deve ser recebido pela conexao 02840 shutdown( ServerSocket, SHUT_RDWR ); 02841 02842 // Fecha o socket com o servidor. 02843 close( ServerSocket ); 02844 02845 #ifdef RIO_DEBUG1 02846 TCPLOG << "[CNetTcp - TcpConnect] Finish6" << endl; 02847 #endif 02848 02849 return( NULL ); 02850 } 02851 02852 // Envia primeiramente o identificador usado para o servidor saber que o 02853 // cliente esta usando a nova implementacao do TCP. 02854 if( send( ServerSocket, TCP_START_MESSAGE, TCP_START_MESSAGE_SIZE, 02855 TCP_FLAGS_SENDDATA ) < 0 ) 02856 { 02857 RioErr << "[TcpConnect] erro " << errno << " (" << strerror( errno ) 02858 << ") ao enviar o identificador da conexao " << TCP_START_MESSAGE 02859 << " ao servidor. " << endl; 02860 02861 // Informa que nada deve ser recebido pela conexao 02862 shutdown( ServerSocket, SHUT_RDWR ); 02863 02864 // Fecha o socket com o servidor. 02865 close( ServerSocket ); 02866 02867 #ifdef RIO_DEBUG1 02868 TCPLOG << "[CNetTcp - TcpAccept] Finish7" << endl; 02869 #endif 02870 02871 return( NULL ); 02872 } 02873 02874 // Obtem o IP e a porta associada a conexao TCP criada. 02875 ClientAddrLen = sizeof( ClientAddr ); 02876 if( getsockname( ServerSocket, (struct sockaddr *) &ClientAddr, 02877 &ClientAddrLen ) < 0 ) 02878 { 02879 RioErr << "[TcpConnect] erro " << errno << " (" << strerror( errno ) 02880 << ") ao obter as informacoes do socket." << endl; 02881 02882 // Informa que nada deve ser recebido pela conexao 02883 shutdown( ServerSocket, SHUT_RDWR ); 02884 02885 // Fecha o socket com o servidor. 02886 close( ServerSocket ); 02887 02888 #ifdef RIO_DEBUG1 02889 TCPLOG << "[CNetTcp - TcpConnect] Finish8" << endl; 02890 #endif 02891 02892 return( NULL ); 02893 } 02894 02895 RioStatus = NewConnection( ServerIP, ServerPort, ServerSocket, 02896 &TcpConnection ); 02897 if( FAILED( RioStatus ) ) 02898 { 02899 #ifdef RIO_DEBUG2 02900 TCPLOG << "CNetTcp::TcpConnect erro 0x" << hex << RioStatus << dec 02901 << " (" << GetErrorDescription( RioStatus ) 02902 << ") ao criar um objeto para a conexao do socket." << endl; 02903 #endif 02904 02905 RioErr << "[TcpConnect] erro do RIO 0x" << hex << RioStatus << dec 02906 << " (" << GetErrorDescription( RioStatus ) << ") ao criar um " 02907 << "objeto para a conexao do socket." << endl; 02908 02909 // Informa que nada deve ser recebido pela conexao 02910 shutdown( ServerSocket, SHUT_RDWR ); 02911 02912 // Fecha o socket com o servidor. 02913 close( ServerSocket ); 02914 02915 #ifdef RIO_DEBUG1 02916 TCPLOG << "[CNetTcp - TcpConnect] Finish9" << endl; 02917 #endif 02918 02919 return( NULL ); 02920 02921 } 02922 02923 #ifdef RIO_DEBUG2 02924 if( TcpConnection != NULL ) 02925 { 02926 TCPLOG << "CNetTcp::TcpConnect criando uma nova conexao TCP: socket = " 02927 << ServerSocket << ", IP TCP (Server) = " << inet_ntoa( ip ) 02928 << ", porta TCP (Server) = " << ntohs( ServerPort ) 02929 << ", IP TCP (Cliente) = " << inet_ntoa( ClientAddr.sin_addr ) 02930 << ", porta TCP (Cliente) = " << ntohs( ClientAddr.sin_port ) 02931 << "." << endl; 02932 } 02933 #endif 02934 02935 // Prepara os dados do cliente para serem enviados ao servidor. 02936 memset( &ClientData, 0, sizeof( ClientData ) ); 02937 ClientData.ConnectionCreated = ( TcpConnection != NULL ); 02938 ClientData.IP = ClientAddr.sin_addr.s_addr; 02939 ClientData.Port = ClientAddr.sin_port; 02940 02941 // Salva o IP e a porta do cliente nos ponteiros passados a funcao. 02942 *ClientIP = ClientData.IP; 02943 *ClientPort = ClientData.Port; 02944 02945 // Enviar dos dados de espaco no buffer 02946 if( send( ServerSocket, &ClientData, sizeof( ClientData ), 02947 TCP_FLAGS_SENDDATA ) < 0 ) 02948 { 02949 RioErr << "[TcpConnect] erro " << errno << " (" << strerror( errno ) 02950 << ") ao enviar o dado com a informacao de se foi possivel " 02951 << "alocar um espaco para a conexao." << endl; 02952 02953 // Remove o objeto associado a conexao TCP do cliente. 02954 if( TcpConnection != NULL ) 02955 { 02956 // Cancela a thread de conexao. 02957 RioStatus = TcpConnection->CancelConnection(); 02958 #ifdef RIO_DEBUG2 02959 TCPLOG << "CNetTcp::TcpConnect erro 0x" << hex << RioStatus << dec 02960 << " (" << GetErrorDescription( RioStatus ) << ") ao " 02961 << "executar a funcao CancelConnection sobre o objeto da " 02962 << "conexao TcpConnection." << endl; 02963 02964 #endif 02965 // Delete o objeto. 02966 delete TcpConnection; 02967 } 02968 02969 // Informa que nada deve ser recebido pela conexao 02970 shutdown( ServerSocket, SHUT_RDWR ); 02971 02972 // Fecha o socket com o servidor. 02973 close( ServerSocket ); 02974 02975 #ifdef RIO_DEBUG1 02976 TCPLOG << "[CNetTcp - TcpConnect] Finish10" << endl; 02977 #endif 02978 02979 return( NULL ); 02980 } 02981 02982 // Recebe os dados do servidor. 02983 memset( &ServerData, 0, sizeof( ServerData ) ); 02984 02985 if( recv( ServerSocket, &ServerData, sizeof( ServerData ), 02986 TCP_FLAGS_RECEIVE ) < 0 ) 02987 { 02988 TCPLOG << "[TcpConnect] erro " << errno << " (" << strerror( errno ) 02989 << ") ao receber o dado com a informacao de se foi possivel " 02990 << "alocar um espaco para a conexao." << endl; 02991 02992 // Remove o objeto associado a conexao TCP do cliente. 02993 if( TcpConnection != NULL ) 02994 { 02995 // Cancela a thread de conexao. 02996 RioStatus = TcpConnection->CancelConnection(); 02997 #ifdef RIO_DEBUG2 02998 TCPLOG << "CNetTcp::TcpConnect erro 0x" << hex << RioStatus << dec 02999 << " (" << GetErrorDescription( RioStatus ) << ") ao " 03000 << "executar a funcao CancelConnection sobre o objeto da " 03001 << "conexao TcpConnection." << endl; 03002 03003 #endif 03004 // Delete o objeto. 03005 delete TcpConnection; 03006 } 03007 03008 // Informa que nada deve ser recebido pela conexao 03009 shutdown( ServerSocket, SHUT_RDWR ); 03010 03011 // Fecha o socket com o servidor. 03012 close( ServerSocket ); 03013 03014 #ifdef RIO_DEBUG1 03015 TCPLOG << "[CNetTcp - TcpConnect] Finish11" << endl; 03016 #endif 03017 03018 return( NULL ); 03019 } 03020 03021 #ifdef RIO_DEBUG2 03022 TCPLOG << "CNetTcp::TcpConnect O servidor " 03023 << ( ( ServerData.ConnectionCreated ) ? "tem" : "nao tem" ) 03024 << " espaco no buffer para a conexao." << endl; 03025 #endif 03026 03027 // Se os streams foram corretamente aloacados no servidor e no cliente. 03028 if( ( ServerData.ConnectionCreated ) && ( TcpConnection != NULL ) ) 03029 { 03030 // Altera o socket TCP para que os dados voltem a ser bufferizados (isso 03031 // e, como dissemos antes, ao desabilitar a bufferizacao, aparentemente 03032 // necessario para usarmos a opcao MSG_MORE no send). 03033 opt = 0; 03034 03035 if( setsockopt( ServerSocket, IPPROTO_TCP, TCP_NODELAY, (char *) &opt, 03036 sizeof( int ) ) < 0 ) 03037 { 03038 #ifdef RIO_DEBUG2 03039 TCPLOG << "CNetTcp::TcpConnect erro " << errno << " (" 03040 << strerror( errno ) << ") ao executar o setsockopt com o " 03041 << "nivel IPPROTO_TCP, opcao TCP_NODELAY." << endl; 03042 #endif 03043 03044 // Cancela a thread de conexao. 03045 RioStatus = TcpConnection->CancelConnection(); 03046 #ifdef RIO_DEBUG2 03047 TCPLOG << "CNetTcp::TcpConnect erro 0x" << hex << RioStatus << dec 03048 << " (" << GetErrorDescription( RioStatus ) << ") ao " 03049 << "executar a funcao CancelConnection sobre o objeto da " 03050 << "conexao TcpConnection." << endl; 03051 03052 #endif 03053 // Delete o objeto. 03054 delete TcpConnection; 03055 03056 // Informa que nada deve ser recebido pela conexao 03057 shutdown( ServerSocket, SHUT_RDWR ); 03058 03059 // Fecha o socket com o servidor. 03060 close( ServerSocket ); 03061 03062 #ifdef RIO_DEBUG1 03063 TCPLOG << "[CNetTcp - TcpConnect] Finish12" << endl; 03064 #endif 03065 03066 return( NULL ); 03067 } 03068 03069 // Como acabamos de finalizar o processo inicial de conexao, e como ele 03070 // foi feito com sucesso, habilitamos a conexao (desbloqueando a thread 03071 // da conexao) e colocamos o objeto associado a conexao na hash com 03072 // todas as conexoes. 03073 RioStatus = EnableConnection( TcpConnection ); 03074 if( FAILED( RioStatus ) ) 03075 { 03076 #ifdef RIO_DEBUG2 03077 TCPLOG << "CNetTcp::TcpConnect erro 0x" << hex << RioStatus << dec 03078 << " (" << GetErrorDescription( RioStatus ) 03079 << ") ao ativar o objeto de conexao criado para o socket." 03080 << endl; 03081 #endif 03082 03083 // Cancela a thread de conexao. 03084 RioStatus = TcpConnection->CancelConnection(); 03085 #ifdef RIO_DEBUG2 03086 TCPLOG << "CNetTcp::TcpConnect erro 0x" << hex << RioStatus << dec 03087 << " (" << GetErrorDescription( RioStatus ) << ") ao " 03088 << "executar a funcao CancelConnection sobre o objeto da " 03089 << "conexao TcpConnection." << endl; 03090 03091 #endif 03092 // Delete o objeto. 03093 delete TcpConnection; 03094 03095 #ifdef RIO_DEBUG1 03096 TCPLOG << "[CNetTcp - TcpConnect] Finish13" << endl; 03097 #endif 03098 03099 return( NULL ); 03100 } 03101 03102 #ifdef RIO_DEBUG2 03103 TCPLOG << "CNetTcp::TcpConnect Conectei ao servidor." << endl; 03104 #endif 03105 03106 #ifdef RIO_DEBUG1 03107 TCPLOG << "[CNetTcp - TcpConnect] Finish14" << endl; 03108 #endif 03109 03110 return( TcpConnection ); 03111 } 03112 else // Em caso contrario, fecha o socket e retorne um erro. 03113 { 03114 // Remove o objeto associado a conexao TCP do cliente. 03115 if( TcpConnection != NULL ) 03116 { 03117 // Cancela a thread de conexao. 03118 RioStatus = TcpConnection->CancelConnection(); 03119 #ifdef RIO_DEBUG2 03120 TCPLOG << "CNetTcp::TcpConnect erro 0x" << hex << RioStatus << dec 03121 << " (" << GetErrorDescription( RioStatus ) << ") ao " 03122 << "executar a funcao CancelConnection sobre o objeto da " 03123 << "conexao TcpConnection." << endl; 03124 03125 #endif 03126 // Delete o objeto. 03127 delete TcpConnection; 03128 } 03129 03130 #ifdef RIO_DEBUG2 03131 TCPLOG << "CNetTcp::TcpConnect a conexao falhou pois nao existe espaco " 03132 << "no cliente e/ou no servidor para a conexao ser efetivada." 03133 << endl; 03134 #endif 03135 03136 RioErr << "[TcpConnect] a conexao falhou pois nao existe espaco para " 03137 << "um novo stream no outro lado da conexao." << endl; 03138 03139 // Informa que nada deve ser recebido pela conexao 03140 shutdown( ServerSocket, SHUT_RDWR ); 03141 03142 // Fecha o socket com o servidor. 03143 close( ServerSocket ); 03144 03145 #ifdef RIO_DEBUG1 03146 TCPLOG << "[CNetTcp - TcpConnect] Finish15" << endl; 03147 #endif 03148 03149 return( NULL ); 03150 } 03151 }
void CNetTcp::TcpServerThread | ( | void | ) | [private] |
Funcao que efetivamente executa o codigo da thread servidora do TCP, chamada pela funcao TcpServerThreadEp (esta funcao e usada para facilitar o acesso aos campos do objeto).
Definition at line 3155 of file NetTcp.cpp.
03156 { 03157 // Armazena o socket criado para um novo cliente. 03158 int ClientSocket; 03159 // Armazena o endereco usado pelo servidor TCP (usado pela funcao bind). 03160 struct sockaddr_in ServerAddr; 03161 // Armazena o par IP, Porta associado ao cliente (usado pela funcao accept). 03162 struct sockaddr_in ClientAddr; 03163 // Armazena o tamanho da estrutura ClientAddr. 03164 socklen_t ClientAddrLen; 03165 // Armazena o ponteiro para o objeto de conexao criado para um novo cliente 03166 // (retornado pela funcao TcpAccept). 03167 CTcpConnection *TcpConnection; 03168 03169 #ifdef RIO_DEBUG1 03170 TCPLOG << "[CNetTcp - TcpServerThread] Start" << endl; 03171 #endif 03172 03173 RioErr << "TCPSERVERTHREADID " << syscall( SYS_gettid ) << endl; 03174 03175 // Inicialmente supomos que o servidor nao iniciou com sucesso. 03176 m_TcpServerStarted = false; 03177 03178 // Criacao do socket de escuta TCP 03179 if( ( m_TcpServerSocket = socket( AF_INET, SOCK_STREAM, 0 ) ) < 0 ) 03180 { 03181 #ifdef RIO_DEBUG2 03182 TCPLOG << "CNetTcp::TcpServerThread erro " << errno << " (" 03183 << strerror( errno ) << ") ao criar o socket de escuta do TCP." 03184 << endl; 03185 #endif 03186 RioErr << "[CNetTcp] error when creating TCP socket: " 03187 << strerror( errno ) << endl; 03188 03189 // Desbloqueia a funcao Start, pois nao conseguimos criar um socket. 03190 pthread_mutex_lock( &m_Mutex ); 03191 pthread_cond_signal( &m_Cond ); 03192 pthread_mutex_unlock( &m_Mutex ); 03193 03194 #ifdef RIO_DEBUG1 03195 TCPLOG << "[CNetTcp - TcpServerThread] Finish1" << endl; 03196 #endif 03197 03198 return; 03199 } 03200 03201 memset( &ServerAddr, 0, sizeof( ServerAddr ) ); 03202 ServerAddr.sin_family = AF_INET; 03203 ServerAddr.sin_port = m_TcpServerPort; 03204 ServerAddr.sin_addr.s_addr = m_IP; 03205 03206 if( bind( m_TcpServerSocket, ( struct sockaddr * ) &ServerAddr, 03207 sizeof( ServerAddr ) ) < 0 ) 03208 { 03209 #ifdef RIO_DEBUG2 03210 TCPLOG << "CNetTcp::TcpServerThread erro " << errno << " (" 03211 << strerror( errno ) << ") no bind do socket de escuta do TCP." 03212 << endl; 03213 #endif 03214 03215 RioErr << "[CNetTcp] bind error in TCP socket: " << strerror( errno ) 03216 << endl; 03217 03218 // Desbloqueia a funcao Start, pois nao conseguimos criar um socket. 03219 pthread_mutex_lock( &m_Mutex ); 03220 pthread_cond_signal( &m_Cond ); 03221 pthread_mutex_unlock( &m_Mutex ); 03222 03223 #ifdef RIO_DEBUG1 03224 TCPLOG << "[CNetTcp - TcpServerThread] Finish2" << endl; 03225 #endif 03226 03227 return; 03228 } 03229 03230 if( listen( m_TcpServerSocket, SOMAXCONN ) < 0 ) 03231 { 03232 #ifdef RIO_DEBUG2 03233 TCPLOG << "CNetTcp::TcpServerThread erro " << errno << " (" 03234 << strerror( errno ) << ") no listen do socket de escuta do TCP." 03235 << endl; 03236 #endif 03237 RioErr << "[CNetTcp] listen error in TCP socket: " << strerror( errno ) 03238 << endl; 03239 03240 // Desbloqueia a funcao Start, pois nao conseguimos criar um socket. 03241 pthread_mutex_lock( &m_Mutex ); 03242 pthread_cond_signal( &m_Cond ); 03243 pthread_mutex_unlock( &m_Mutex ); 03244 03245 #ifdef RIO_DEBUG1 03246 TCPLOG << "[CNetTcp - TcpServerThread] Finish3" << endl; 03247 #endif 03248 03249 return; 03250 } 03251 03252 TCPLOG << "[CNetTcp] esperando por clientes no IP " 03253 << inet_ntoa( ServerAddr.sin_addr ) << " e na porta " 03254 << ntohs( ServerAddr.sin_port ) << endl; 03255 03256 // Como o servidor iniciou com sucesso, deveremos colocar o valor true em 03257 // m_TcpServerStarted 03258 m_TcpServerStarted = true; 03259 03260 // Desbloqueia a funcao Start, pois a thread do servidor ja foi iniciada 03261 // com sucesso. 03262 pthread_mutex_lock( &m_Mutex ); 03263 pthread_cond_signal( &m_Cond ); 03264 pthread_mutex_unlock( &m_Mutex ); 03265 03266 // Estado de aceite de conexoes 03267 while( true ) 03268 { 03269 ClientAddrLen = sizeof( ClientAddr ); 03270 03271 #ifdef RIO_DEBUG2 03272 TCPLOG << "CNetTcp::TcpServerThread aceitando conexoes TCP de um " 03273 << "cliente " << endl; 03274 #endif 03275 03276 // Aguarda por conexoes 03277 if( ( ClientSocket = accept( m_TcpServerSocket, 03278 ( struct sockaddr * ) &ClientAddr, 03279 &ClientAddrLen ) ) < 0 ) 03280 { 03281 if( ( errno == EBADF ) || ( errno != EINVAL ) ) 03282 { 03283 #ifdef RIO_DEBUG2 03284 TCPLOG << "CNetTcp::TcpServerThread recebi o erro que a " 03285 << "o socket se tornou invalido (porque provavelmente " 03286 << "foi fechado. Terminando a thread!"<< endl; 03287 #endif 03288 03289 TCPLOG << "[TcpServerThread] Recebido erro EBADF ou EINVAL no " 03290 << "accept. Como isso ocorre somente ao finalizar o " 03291 << "servidor, a thread servidora sera finalizada!" 03292 << endl; 03293 03294 return; 03295 } 03296 #ifdef RIO_DEBUG2 03297 else if( errno != EINTR ) 03298 TCPLOG << "CNetTcp::TcpServerThread recebi o erro que a " 03299 << "chamada ao sistena foi interrompida." << endl; 03300 else 03301 TCPLOG << "CNetTcp::TcpServerThread erro " << errno << " (" 03302 << strerror( errno ) << "ao executar o accept no " 03303 << "socket de escuta do TCP" << endl; 03304 #endif 03305 } 03306 else 03307 { 03308 #ifdef RIO_DEBUG2 03309 TCPLOG << "CNetTcp::TcpServerThread processando um pedido de " 03310 << "conexao recebido de um cliente!" << endl; 03311 #endif 03312 03313 // Chama a funcao para aceitar uma conexao com cliente. 03314 TcpConnection = TcpAccept( ClientSocket, 03315 ClientAddr.sin_addr.s_addr, 03316 ntohs( ClientAddr.sin_port ) ); 03317 03318 if( TcpConnection == NULL ) 03319 { 03320 // Nao foi possivel estabelecer a conexao. Devemos entao fechar 03321 // o socket criado. 03322 03323 #ifdef RIO_DEBUG2 03324 TCPLOG << "CNetTcp::TcpServerThread erro ao criar o socket TCP" 03325 << endl; 03326 #endif 03327 03328 // Informa que nada deve ser recebido pela conexao 03329 shutdown( ClientSocket, SHUT_RDWR ); 03330 03331 // Fecha o socket do cliente. 03332 close( ClientSocket ); 03333 } 03334 else 03335 { 03336 #ifdef RIO_DEBUG2 03337 TCPLOG << "CNetTcp::TcpServerThread conexao TCP para um " 03338 << "cliente com o IP " 03339 << inet_ntoa( ClientAddr.sin_addr ) << " e a porta " 03340 << ntohs( ClientAddr.sin_port ) << " foi aceita e " 03341 << "criada (com um sokect cujo ID e " << ClientSocket 03342 << ")." << endl; 03343 #endif 03344 } 03345 } 03346 03347 } 03348 03349 #ifdef RIO_DEBUG1 03350 TCPLOG << "[CNetTcp - TcpServerThread] Finish5" << endl; 03351 #endif 03352 03353 return; 03354 }
void * CNetTcp::TcpServerThreadEp | ( | void * | ThreadParam | ) | [static, private] |
Funcao que trata da execucao do codigo da thread servidora do TCP (somente para os servidores).
ThreadParam | ponteiro com o parametro da thread. Para esta thread, e um ponteiro para um objeto da classe CNetTcp. |
Definition at line 3359 of file NetTcp.cpp.
03360 { 03361 CNetTcp *NetTcp = ( CNetTcp * ) ThreadParam; 03362 03363 #ifdef RIO_DEBUG1 03364 TCPLOGEST << "[CNetTcp - TcpServerThreadEp] Start" << endl; 03365 #endif 03366 03367 NetTcp->TcpServerThread(); 03368 03369 #ifdef RIO_DEBUG1 03370 TCPLOGEST << "[CNetTcp - TcpServerThreadEp] Finish" << endl; 03371 #endif 03372 03373 return 0; 03374 }
unsigned int CNetTcp::m_AddressSize [private] |
bool CNetTcp::m_CancelThreads [private] |
int* CNetTcp::m_ClientIPAddress [private] |
int* CNetTcp::m_ClientPorts [private] |
pthread_cond_t CNetTcp::m_Cond [private] |
time_t CNetTcp::m_ConnectionTimeOut [private] |
int CNetTcp::m_IP [private] |
CLogRotation* CNetTcp::m_LogRotation [private] |
pthread_mutex_t CNetTcp::m_Mutex [private] |
CNetInterface* CNetTcp::m_NetInterface [private] |
unsigned int CNetTcp::m_ReceiveTimeOut [private] |
unsigned int CNetTcp::m_SendTimeOut [private] |
struct sockaddr_in* CNetTcp::m_ServerAddress [private] |
bool CNetTcp::m_ServerInstance [private] |
bool CNetTcp::m_Started [private] |
int CNetTcp::m_TcpServerPort [private] |
int CNetTcp::m_TcpServerSocket [private] |
bool CNetTcp::m_TcpServerStarted [private] |
pthread_t CNetTcp::m_TcpServerThreadId [private] |