CTcpConnection Class Reference

#include <NetTcp.h>

Public Member Functions

 CTcpConnection (CNetTcp *NetTcp, bool ServerInstance)
 Construtor da classe, usado para criar um novo objeto.
 ~CTcpConnection ()
 Destrutor da classe, usado para remover um objeto criado.
RioResult Initialize (int IP, int Port, int Socket, int HostIP, time_t ConnectionTimeOut, CLogRotation *LogRotation)
 Funcao para inicializar a nova conexao TCP criada.
RioResult EnableConnection (void)
 Funcao para habilitar o uso da conexao TCP (a thread criada na funcao Initialize acima ficara bloqueada em uma variavel de condicao ate esta funcao ser chamada.
RioResult CancelConnection (void)
 Funcao para abortar a execucao da thread (a thread nao deletara o objeto neste caso).
RioResult PutSendData (char *Data, unsigned int DataSize, void *Param, unsigned int *SendDataSize)
 Funcao para inserir um conjunto de dados a serem enviados posteriormente pelo socket da conexao TCP.
RioResult GetIpAndPort (int *IP, int *Port)
 Funcao para obter o IP, a porta associado a conexao TCP do objeto (usado para colocar o objeto na hash de conexoes).

Private Member Functions

RioResult GetSendData (char **Data, unsigned int *DataSize, void **Param)
 Funcao para obter um conjunto de dados a serem enviados do objeto da classe.
RioResult ReceiveStreamData (char **Data, unsigned int *DataSize)
 Funcao para receber dados de uma conexao TCP associada ao stream.
RioResult SendStreamData (unsigned int *DataSize, void **Param)
 Funcao para enviar o primeiro bloco de dados pendente em um stream TCP.
bool WaitEnableConnection (void)
 Funcao para esperar ate que a funcao EnableConnection.
bool TcpNetMgrThread (void)
 Funcao que efetivamente executa o codigo da thread de gerenciamento da reda, chamada pela funcao ReceiveThreadEp (esta funcao e usada para facilitar o acesso aos campos do objeto).

Static Private Member Functions

static void * TcpNetMgrThreadEp (void *ThreadParam)
 Funcao que trata da execucao do codigo da thread de gerenciamento das conexoes TCP ativas.

Private Attributes

CNetTcpm_NetTcp
bool m_Initialized
bool m_ServerInstance
CLogRotationm_LogRotation
int m_IP
int m_Port
int m_Socket
time_t m_LastUseTime
time_t m_ConnectionTimeOut
TSendQueue m_SendQueue
bool m_isClosingSocket
pthread_t m_TcpNetMgrThreadId
pthread_mutex_t m_Mutex
pthread_cond_t m_Cond
bool m_isAborted
bool m_SentSignal
int m_PollSocket
struct sockaddr_in m_PollSocketAddr

Detailed Description

Definition at line 199 of file NetTcp.h.


Constructor & Destructor Documentation

CTcpConnection::CTcpConnection ( CNetTcp NetTcp,
bool  ServerInstance 
)

Construtor da classe, usado para criar um novo objeto.

Parameters:
NetTcp ponteiro para o objeto da classe CNetTcp que criou a conexao TCP.
ServerInstance se a conexao esta associada a um cliente ou a um servidor

Definition at line 66 of file NetTcp.cpp.

00067 {
00068     // Atribui o ponteiro para a classe de gerenciamento do TCP.
00069     m_NetTcp = NetTcp;
00070 
00071     #ifdef RIO_DEBUG1
00072     TCPCONNECTIONLOG << "[CTcpConnection - Construtor] Start" << endl;
00073     #endif
00074 
00075     // Inicializa as variaveis da classe.
00076     m_NetTcp = NetTcp;
00077     m_ServerInstance = ServerInstance;
00078     m_IP = 0;
00079     m_Port = 0;
00080     m_Socket = 0;
00081     m_LastUseTime = 0;
00082     m_isClosingSocket = false;
00083     m_LogRotation = NULL;
00084     m_isAborted = false;
00085     m_ConnectionTimeOut = 0;
00086     m_SentSignal = false;
00087     m_PollSocket = 0;
00088     memset( &m_PollSocketAddr, 0, sizeof( m_PollSocketAddr ) );
00089     #ifdef RIO_DEBUG2
00090     m_ReceiveCount = 0;
00091     m_SendCount = 0;
00092     #endif
00093     // m_SendQueue nao precisa ser inicializada
00094 
00095     // Define que o objeto ainda nao foi inicializado.
00096     m_Initialized = false;
00097     
00098     // Inicializa o mutex da classe, usado para garantir o acesso exclusivo
00099     // as variaveis da classe, a variavel de condicao usada para bloquear a
00100     // thread de gerenciamento da rede ate que 
00101     pthread_mutex_init( &m_Mutex, NULL );
00102     pthread_cond_init( &m_Cond, NULL );
00103 
00104     #ifdef RIO_DEBUG1
00105     TCPCONNECTIONLOG << "[CTcpConnection - Construtor] Finish" << endl;
00106     #endif
00107 } 

CTcpConnection::~CTcpConnection (  ) 

Destrutor da classe, usado para remover um objeto criado.

Definition at line 110 of file NetTcp.cpp.

00111 {
00112     #ifdef RIO_DEBUG1
00113     TCPCONNECTIONLOG << "[CTcpConnection - Destrutor] Start" << endl;
00114     #endif
00115 
00116     // Destroi o mutex da classe.
00117     pthread_mutex_destroy( &m_Mutex );
00118 
00119     // Destroi a variavel de condicao da classe usada para bloquear uma thread 
00120     // ate o processo inicial de conexao ter sido finalizado.
00121     pthread_cond_destroy( &m_Cond );
00122 
00123     #ifdef RIO_DEBUG1
00124     TCPCONNECTIONLOG << "[CTcpConnection - Destrutor] Finish" << endl;
00125     #endif
00126 }


Member Function Documentation

RioResult CTcpConnection::CancelConnection ( void   ) 

Funcao para abortar a execucao da thread (a thread nao deletara o objeto neste caso).

A funcao esperara ate que a thread termine a sua execucao.

Returns:
S_OK se nenhum erro ocorreu ou o erro em caso contrario.

Definition at line 1748 of file NetTcp.cpp.

01749 {
01750     #ifdef RIO_DEBUG1
01751     TCPCONNECTIONLOG << "[CTcpConnection - CancelConnection] Start" << endl;
01752     #endif
01753 
01754     // Verifica se o objeto da classe ja foi inicializado.
01755     if( !m_Initialized )
01756     {
01757         #ifdef RIO_DEBUG2
01758         TCPCONNECTIONLOG << "CTcpConnection::CancelConnection o objeto da "
01759                          << "classe nao esta inicializado!" << endl;
01760         #endif
01761 
01762         #ifdef RIO_DEBUG1
01763         TCPCONNECTIONLOG << "[CTcpConnection - CancelConnection] Finish1"
01764                          << endl;
01765         #endif
01766 
01767         return ERROR_TCPCONNECTION + ERROR_NOT_INITIALIZED;
01768     }
01769 
01770     // Obtem o lock do objeto.
01771     pthread_mutex_lock( &m_Mutex );
01772 
01773     // Informa que a conexao foi cancelada e que a thread deve finalizar a
01774     // execucao (sem remover o objeto).
01775     m_isAborted = true;
01776 
01777     // Sinaliza a variavel de condicao, para desbloquear a thread da conexao
01778     // TCP.
01779     pthread_cond_signal( &m_Cond );
01780 
01781     // Informa que um sinal foi gerado.
01782     m_SentSignal = true;
01783 
01784     // Libera o acesso exlusivo ao lock.
01785     pthread_mutex_unlock( &m_Mutex );
01786 
01787     // Espera ate que a thread termine a sua execucao.
01788     pthread_join( m_TcpNetMgrThreadId, NULL );
01789 
01790     #ifdef RIO_DEBUG1
01791     TCPCONNECTIONLOG << "[CTcpConnection - EnableConnection] Finish2" << endl;
01792     #endif
01793 
01794     return S_OK;
01795 }

RioResult CTcpConnection::EnableConnection ( void   ) 

Funcao para habilitar o uso da conexao TCP (a thread criada na funcao Initialize acima ficara bloqueada em uma variavel de condicao ate esta funcao ser chamada.

Obs: Esta funcao e usada para evitar que a thread da conexao execute o select antes do processo de inicializacao da conexao ter sido finalizado, o que poderia confundir este processo porque o select poderia incorretamente reportar os dados de inicializacao como dados validos recebidos (ou enviados) do (para o) outro lado.

Returns:
S_OK se nenhum erro ocorreu ou o erro em caso contrario.

Definition at line 1704 of file NetTcp.cpp.

01705 {
01706     #ifdef RIO_DEBUG1
01707     TCPCONNECTIONLOG << "[CTcpConnection - EnableConnection] Start" << endl;
01708     #endif
01709 
01710     // Verifica se o objeto da classe ja foi inicializado.
01711     if( !m_Initialized )
01712     {
01713         #ifdef RIO_DEBUG2
01714         TCPCONNECTIONLOG << "CTcpConnection::EnableConnection o objeto da "
01715                          << "classe nao esta inicializado!" << endl;
01716         #endif
01717 
01718         #ifdef RIO_DEBUG1
01719         TCPCONNECTIONLOG << "[CTcpConnection - EnableConnection] Finish1"
01720                          << endl;
01721         #endif
01722 
01723         return ERROR_TCPCONNECTION + ERROR_NOT_INITIALIZED;
01724     }
01725 
01726     // Obtem o lock do objeto.
01727     pthread_mutex_lock( &m_Mutex );
01728 
01729     // Sinaliza a variavel de condicao, para desbloquear a thread da conexao
01730     // TCP.
01731     pthread_cond_signal( &m_Cond );
01732 
01733     // Informa que um sinal foi gerado.
01734     m_SentSignal = true;
01735 
01736     // Libera o acesso exlusivo ao lock.
01737     pthread_mutex_unlock( &m_Mutex );
01738 
01739     #ifdef RIO_DEBUG1
01740     TCPCONNECTIONLOG << "[CTcpConnection - EnableConnection] Finish2" << endl;
01741     #endif
01742 
01743     return S_OK;
01744 }

RioResult CTcpConnection::GetIpAndPort ( int *  IP,
int *  Port 
)

Funcao para obter o IP, a porta associado a conexao TCP do objeto (usado para colocar o objeto na hash de conexoes).

Parameters:
IP ponteiro para o endreco onde colocaremos o IP.
Port ponteiro para o endereco onde colocaremos a porta.
Returns:
S_OK se nenhum erro ocorreu ao obtermos o par IP, porta ou diferente de S_OK se algum erro ocorreu.

Definition at line 1955 of file NetTcp.cpp.

01956 {
01957     // Verifica se o objeto da classe ja foi inicializado.
01958     if( !m_Initialized )
01959     {
01960         //  Inicializa o IP e a porta com valores invalidos.
01961         *IP = 0;
01962         *Port = 0;
01963 
01964         #ifdef RIO_DEBUG2
01965         TCPCONNECTIONLOG << "CTcpConnection::GetIpAndPort o objeto da classe "
01966                          << "nao esta inicializado!" << endl;
01967         #endif
01968 
01969         #ifdef RIO_DEBUG1
01970         TCPCONNECTIONLOG << "[CTcpConnection - GetIpAndPort] Finish1" << endl;
01971         #endif
01972 
01973         return ERROR_TCPCONNECTION + ERROR_NOT_INITIALIZED;
01974     }
01975 
01976     *IP = m_IP;
01977     *Port = m_Port;
01978 
01979     #ifdef RIO_DEBUG1
01980     TCPCONNECTIONLOG << "[CTcpConnection - GetIpAndPort] Finish2" << endl;
01981     #endif
01982 
01983     return S_OK;
01984 }

RioResult CTcpConnection::GetSendData ( char **  Data,
unsigned int *  DataSize,
void **  Param 
) [private]

Funcao para obter um conjunto de dados a serem enviados do objeto da classe.

Parameters:
Data ponteiro para armazenar o endereco do inicio dos dados
DataSize ponteiro para armazenar o tamanho dos dados a serem transferidos.
Param ponteiro para armazenar o parametro void* (passado ao chamarmos a funcao SendData da classe CNetTCP).
Returns:
S_OK se nenhum erro ocorreu ou o erro em caso contrario.

Definition at line 129 of file NetTcp.cpp.

00131 {
00132     #ifdef RIO_DEBUG1
00133     TCPCONNECTIONLOG << "[CTcpConnection - GetSendData] Start" << endl;
00134     #endif
00135 
00136     // Obtem o lock do objeto.
00137     pthread_mutex_lock( &m_Mutex );
00138 
00139     // Agora verificamos se existem dados para serem enviados, mas antes 
00140     // deveremos verificar se a fila de envio esta vazia.
00141     if( m_SendQueue.empty() )
00142     {
00143         // Obtem o lock do objeto.
00144         pthread_mutex_unlock( &m_Mutex );
00145 
00146         // Neste caso nao temos dados para enviar (o tratamento do erro sera da
00147         // classe CNetTcp, pois o erro de implementacao esta nesta classe).
00148         #ifdef RIO_DEBUG2
00149         TCPCONNECTIONLOG << "CTcpConnection::GetSendData a fila de envio do "
00150                          << "socket com a ID " << m_Socket << " esta vazia!" 
00151                          << endl;
00152         #endif
00153 
00154         *Data = NULL;
00155         *DataSize = 0;
00156         *Param = NULL;
00157 
00158         #ifdef RIO_DEBUG1
00159         TCPCONNECTIONLOG << "[CTcpConnection - GetSendData] Finish1" << endl;
00160         #endif
00161 
00162         return ERROR_TCPCONNECTION + ERROR_UNEXPECTED;
00163     }
00164     else
00165     {
00166         #ifdef RIO_DEBUG2
00167         TCPCONNECTIONLOG << "CTcpConnection::GetSendData tentando retirar os "
00168                          << "dados a serem enviados pelo socket com a ID " 
00169                          << m_Socket << ". Tamanho da fila e de " 
00170                          << m_SendQueue.size() << "." << endl;
00171         #endif
00172 
00173         // Obtem os dados a serem enviados primeiramente (que estarao no inicio 
00174         // da fila) e remove esta entrada da fila.
00175         *Data = m_SendQueue.front().Data;
00176         *DataSize = m_SendQueue.front().DataSize;
00177         *Param = m_SendQueue.front().Param;
00178         // Sera que isso pode gerar um erro? Eu nao tenho certeza.
00179         m_SendQueue.pop();
00180 
00181         #ifdef RIO_DEBUG2
00182         TCPCONNECTIONLOG << "CTcpConnection::GetSendData dados a serem "
00183                          << "enviados pelo socket com a ID " << m_Socket 
00184                          << " retirados com sucesso. Tamanho da fila e agora "
00185                          << "de " << m_SendQueue.size() << "." << endl;
00186         #endif
00187     }
00188 
00189     // Libera o acesso exlusivo ao lock.
00190     pthread_mutex_unlock( &m_Mutex ); 
00191 
00192     #ifdef RIO_DEBUG1
00193     TCPCONNECTIONLOG << "[CTcpConnection - GetSendData] Finish2" << endl;
00194     #endif
00195     
00196     return S_OK;
00197 }

RioResult CTcpConnection::Initialize ( int  IP,
int  Port,
int  Socket,
int  HostIP,
time_t  ConnectionTimeOut,
CLogRotation LogRotation 
)

Funcao para inicializar a nova conexao TCP criada.

Parameters:
IP endereco IP associado ao stream.
Port porta associadao ao stream.
Socket socket associado ao stream.
HostIP associado a maquina na qual o objeto foi alocado (usado para criar o socket UDP).
ConnectionTimeOut tempo de timeout da conexao TCP.
LogRotation ponteiro para a classe que gerencia os logs.
Returns:
S_OK se nenhum erro ocorreu ou o erro em caso contrario.

Definition at line 1529 of file NetTcp.cpp.

01532 {
01533     // Atributos da thread de gerenciamento das conexoes TCP.
01534     pthread_attr_t attribTcpNetMgrThread;
01535     // Armazena o endereco do socket usado para desbloquear o select antes de
01536     // obtermos a porta (escolhida aleatoriamente pelo sistema operacional).
01537     struct sockaddr_in TempAddr;
01538     // Armazena o tamanho do endereco do socket usado para desbloquear o select.
01539     socklen_t AddrSize;
01540 
01541     #ifdef RIO_DEBUG1
01542     TCPCONNECTIONLOG << "[CTcpConnection - Initialize] Start" << endl;
01543     #endif
01544 
01545     // Verifica se o objeto da classe ja foi inicializado.
01546     if( m_Initialized )
01547     {
01548         #ifdef RIO_DEBUG2
01549         TCPCONNECTIONLOG << "CTcpConnection::Initialize o objeto da classe ja "
01550                          << "esta inicializado!" << endl;
01551         #endif
01552 
01553         #ifdef RIO_DEBUG1
01554         TCPCONNECTIONLOG << "[CTcpConnection - Initialize] Finish1" << endl;
01555         #endif
01556 
01557         return ERROR_TCPCONNECTION + ERROR_INITIALIZED;
01558     }
01559 
01560     // Inicializa as variaveis da classe.
01561     m_IP = IP;
01562     m_Port = Port;
01563     m_Socket = Socket;
01564     m_ConnectionTimeOut = ConnectionTimeOut;
01565     m_LogRotation = LogRotation;
01566     m_SentSignal = false;
01567     #ifdef RIO_DEBUG2
01568     m_ReceiveCount = 0;
01569     m_SendCount = 0;
01570     #endif
01571 
01572     // Cria o socket usado para desbloquear o poll quando dados precisam ser
01573     // enviados ou quando novas conexoes sao estabelecidas (somente no caso do
01574     // servidor).
01575     m_PollSocket = socket( AF_INET, SOCK_DGRAM, 0 );
01576     if( m_PollSocket < 0 )
01577     {
01578         #ifdef RIO_DEBUG2
01579         TCPCONNECTIONLOG << "CTcpConnection::Initialize erro " << errno << " ("
01580                          << strerror( errno ) << ") ao criar o socket usado "
01581                          << "para desbloquear o poll quando necessario."
01582                          << endl;
01583         #endif
01584 
01585         #ifdef RIO_DEBUG1
01586         TCPCONNECTIONLOG << "[CTcpConnection - Initialize] Finish2" << endl;
01587         #endif
01588 
01589         return ERROR_NETTCP + ERROR_SOCKET_CREATE;
01590     }
01591 
01592     // Faz com que o socket seja exclusivo do processo, e nao seja passado
01593     // para um outro processo criado pelo processo que abriu o socket.
01594     if( fcntl( m_PollSocket, F_SETFD, FD_CLOEXEC ) < 0 )
01595     {
01596         #ifdef RIO_DEBUG2
01597         TCPCONNECTIONLOG << "CTcpConnection::Initialize erro " << errno << " ("
01598                          << strerror( errno ) << ") ao fazer o socket usado "
01599                          << "para desbloquear o poll ser exclusivo ao processo "
01600                          << "que criou o objeto da classe CTcpConnection."
01601                          << endl;
01602         #endif
01603 
01604         #ifdef RIO_DEBUG1
01605         TCPCONNECTIONLOG << "[CTcpConnection - Initialize] Finish3" << endl;
01606         #endif
01607 
01608         return ERROR_NETTCP + ERROR_SOCKET_OPTIONS;
01609     }
01610 
01611     // Limpa a estrutura TempAddr.
01612     memset( &TempAddr, 0, sizeof( TempAddr ) );
01613     // associa o socket UDP usado para desbloquear o poll ao IP do servidor e
01614     // a uma porta escolhida aleatoriamente (isso esta bom, ou devemos usar a
01615     // porta do UDP mais 1 - para nao colidir com a porta UDP da RioNeti?).
01616     TempAddr.sin_family = AF_INET;
01617     TempAddr.sin_addr.s_addr = HostIP;
01618     TempAddr.sin_port = 0; // O sistema escolhe a porta.
01619     if( bind( m_PollSocket, ( struct sockaddr * ) &TempAddr,
01620               sizeof( TempAddr ) ) < 0 )
01621     {
01622         #ifdef RIO_DEBUG2
01623         TCPCONNECTIONLOG << "CTcpConnection::Initialize erro " << errno << " ("
01624                          << strerror( errno ) << ") ao ligar o socket usado "
01625                          << "para desbloquear o poll ao IP "
01626                          << inet_ntoa( TempAddr.sin_addr ) << "." << endl;
01627         #endif
01628 
01629         #ifdef RIO_DEBUG1
01630         TCPCONNECTIONLOG << "[CTcpConnection - Initialize] Finish4" << endl;
01631         #endif
01632 
01633         return ERROR_NETTCP + ERROR_SOCKET_BIND;
01634     }
01635 
01636     AddrSize = sizeof( m_PollSocketAddr );
01637     if( getsockname( m_PollSocket, ( struct sockaddr * ) &m_PollSocketAddr,
01638                      &AddrSize ) != 0 )
01639     {
01640         #ifdef RIO_DEBUG2
01641         TCPCONNECTIONLOG << "CTcpConnection::Initialize erro " << errno << " ("
01642                          << strerror( errno ) << ") ao obter as informacoes do "
01643                          << "socket usado para desbloquear o poll ao IP "
01644                          << inet_ntoa( TempAddr.sin_addr ) << "." << endl;
01645         #endif
01646 
01647         #ifdef RIO_DEBUG1
01648         TCPCONNECTIONLOG << "[CTcpConnection - Initialize] Finish5" << endl;
01649         #endif
01650 
01651         return ERROR_NETTCP + ERROR_SOCKET_OPTIONS;
01652     }
01653 
01654     #ifdef RIO_DEBUG2
01655     TCPCONNECTIONLOG << "CTcpConnection::Initialize socket usado para "
01656                      << "desbloquear o poll criado sucesso. O identificador do "
01657                      << "socket e " << m_PollSocket << ", e foi associado ao "
01658                      << "endereco IP " << inet_ntoa( m_PollSocketAddr.sin_addr )
01659                      << " e a porta " << ntohs( m_PollSocketAddr.sin_port )
01660                      << "." << endl;
01661     #endif
01662 
01663     // Inicializa os atributos da thread usada para gerenciar as transferencias 
01664     // de dados.
01665     pthread_attr_init( &attribTcpNetMgrThread );
01666     // Inicializa a pilha da thread usada para gerenciar as transferencias de 
01667     // dados.
01668     pthread_attr_setstacksize( &attribTcpNetMgrThread, 2 * PTHREAD_STACK_MIN );
01669 
01670     // Cria a thread usada para gerenciar as transferencias de dados.
01671     if ( pthread_create( &m_TcpNetMgrThreadId, &attribTcpNetMgrThread,
01672                          TcpNetMgrThreadEp, ( void * ) this ) != 0 )
01673     {
01674         #ifdef RIO_DEBUG2
01675         TCPCONNECTIONLOG << "CTcpConnection::Initialize erro " << errno
01676                          << " (" << strerror( errno ) << ") ao criar a thread "
01677                          << "TcpNetMgrThread." << endl;
01678         #endif
01679 
01680         #ifdef RIO_DEBUG1
01681         TCPCONNECTIONLOG << "[CTcpConnection - Initialize] Finish6" << endl;
01682         #endif
01683 
01684         return ERROR_TCPCONNECTION + ERROR_CREATE_THREAD;
01685     }
01686 
01687     // Desassocia a thread criada par a nova conexao TCP da thread que criou a
01688     // conexao TCP.
01689     pthread_detach( m_TcpNetMgrThreadId );
01690 
01691     // Informa que o objeto foi inicializado com sucesso.
01692     m_Initialized = true;
01693 
01694     #ifdef RIO_DEBUG1
01695     TCPCONNECTIONLOG << "[CTcpConnection - Initialize] Finish7" << endl;
01696     #endif
01697 
01698     return S_OK;
01699 }

RioResult CTcpConnection::PutSendData ( char *  Data,
unsigned int  DataSize,
void *  Param,
unsigned int *  SendDataSize 
)

Funcao para inserir um conjunto de dados a serem enviados posteriormente pelo socket da conexao TCP.

Parameters:
Data ponteiro para o endereco do inicio dos dados a serem enviados.
DataSize tamanho dos dados a serem enviados (em bytes).
Param parametro a ser passado quando os dados forem enviados (passado ao chamarmos a funcao SendData da classe CNetTCP).
SendDataSize ponteiro para armazenar o tamanho atual da fila. Se o tamanho for 1, precisaremos desbloquear o select.
Returns:
S_OK se nenhum erro ocorreu ou o erro em caso contrario.

Definition at line 1799 of file NetTcp.cpp.

01802 {
01803     // Armazena os dados a serem colocados na fila
01804     SSendData SendData;
01805 
01806     #ifdef RIO_DEBUG2
01807     // Armazena o endereco ip para ser usado pela funcao inet_ntoa
01808     in_addr ip;
01809     #endif
01810 
01811     #ifdef RIO_DEBUG1
01812     TCPCONNECTIONLOG << "[CTcpConnection - PutSendData] Start" << endl;
01813     #endif
01814 
01815     #ifdef RIO_DEBUG2
01816     // Inicializa o ip com o IP do objeto.
01817     ip.s_addr = m_IP;
01818     #endif
01819 
01820     // Verifica se o objeto da classe ja foi inicializado.
01821     if( !m_Initialized )
01822     {
01823         #ifdef RIO_DEBUG2
01824         TCPCONNECTIONLOG << "CTcpConnection::PutSendData o objeto da classe "
01825                          << "nao esta inicializado!" << endl;
01826         #endif
01827 
01828         #ifdef RIO_DEBUG1
01829         TCPCONNECTIONLOG << "[CTcpConnection - PutSendData] Finish1"
01830                          << endl;
01831         #endif
01832 
01833         return ERROR_TCPCONNECTION + ERROR_NOT_INITIALIZED;
01834     }
01835 
01836     // Obtem o lock para o acesso exclusivo as estruturas do objeto.
01837     pthread_mutex_lock( &m_Mutex );
01838 
01839     // Verificamos se estamos fechando o socket pois, caso o socket esteja sendo
01840     // fechado, nao tem sentido colocar dados na fila.
01841     if( m_isClosingSocket )
01842     {
01843         // Libera o acesso exlusivo ao lock.
01844         pthread_mutex_unlock( &m_Mutex );
01845 
01846         #ifdef RIO_DEBUG2
01847         TCPCONNECTIONLOG << "CTcpConnection::PutSendData o socket com a ID "
01848                          << m_Socket << " esta sendo fechado. Nao e possivel "
01849                          << "portanto colocar mais dados na fila de saida."
01850                          << endl;
01851         #endif
01852 
01853         #ifdef RIO_DEBUG1
01854         TCPCONNECTIONLOG << "[CTcpConnection - PutSendData] Finish2" << endl;
01855         #endif
01856 
01857         return ERROR_TCPCONNECTION + ERROR_NOTCONNECTED;
01858     }
01859 
01860     // Inicializa os campos dos dados a serem enviados.
01861     SendData.Data = Data;
01862     SendData.DataSize = DataSize;
01863     SendData.Param = Param;
01864 
01865     // Tenta colocar os dados na fila.
01866     try
01867     {
01868         #ifdef RIO_DEBUG2
01869         TCPCONNECTIONLOG << "CTcpConnection::PutSendData tentando colocar os "
01870                          << "dados a serem enviados pelo socket com a ID "
01871                          << m_Socket << ". Tamanho da fila e de "
01872                          << m_SendQueue.size() << "." << endl;
01873         #endif
01874 
01875         m_SendQueue.push( SendData );
01876 
01877         #ifdef RIO_DEBUG2
01878         TCPCONNECTIONLOG << "CTcpConnection::PutSendData os dados a serem "
01879                          << "enviados pelo socket com a ID " << m_Socket
01880                          << ", o IP " << inet_ntoa( ip ) << " e a porta "
01881                          << ntohs( m_Port ) << " foram colocados na fila com "
01882                          << "sucesso. Tamanho da fila agora e de "
01883                          << m_SendQueue.size() << "." << endl;
01884         #endif
01885     }
01886     catch( bad_alloc& ba )
01887     {
01888         // Obtem o tamanho atual da fila.
01889         *SendDataSize = m_SendQueue.size();
01890 
01891         // Libera o acesso exlusivo ao lock.
01892         pthread_mutex_unlock( &m_Mutex );
01893 
01894         #ifdef RIO_DEBUG2
01895         TCPCONNECTIONLOG << "CTcpConnection::PutSendData erro de alocacao de "
01896                          << "memoria (bad_alloc, error = " << ba.what() << ") "
01897                          << "ao criar uma entrada na fila SendQueue do socket "
01898                          << "com a ID " << m_Socket << ", o IP "
01899                          << inet_ntoa( ip ) << " e a porta " << ntohs( m_Port )
01900                          << "." << endl;
01901         #endif
01902 
01903         #ifdef RIO_DEBUG1
01904         TCPCONNECTIONLOG << "[CTcpConnection - PutSendData] Finish3" << endl;
01905         #endif
01906 
01907         return ERROR_TCPCONNECTION + ERROR_MEMORY;
01908 
01909     }
01910 
01911     // Obtem o tamanho atual da fila.
01912     *SendDataSize = m_SendQueue.size();
01913 
01914     // Tenta desbloquear o poll para que o socket associado ao dado
01915     // enviado possa ser verificado. Como o socket somente nao estara no
01916     // conjunto de saida quando nao existir nenhum dado pendente para ser
01917     // enviado, entao precisamos enviar uma mensagem pelo socket
01918     // m_PollSocket usado para desbloquear o poll somente se SendDataSize for 1.
01919     if( ( *SendDataSize ) == 1 )
01920     {
01921         #ifdef RIO_DEBUG2
01922         TCPCONNECTIONLOG << "CTcpConnection::PutSendData tentanto desbloquear "
01923                          << "o poll, enviando a mensagem \"" << MSG_POLL_NEWDATA
01924                          << "\" ao socket com a ID " << m_PollSocket << "."
01925                          << endl;
01926         #endif
01927         if( sendto( m_PollSocket, ( void * ) MSG_POLL_NEWDATA,
01928                     MSG_POLL_SIZE, UDP_FLAGS_SEND,
01929                     ( struct sockaddr * ) &m_PollSocketAddr,
01930                     sizeof( m_PollSocketAddr ) ) < 0 )
01931         {
01932             #ifdef RIO_DEBUG2
01933             TCPCONNECTIONLOG << "CTcpConnection::PutSendData erro " << errno
01934                              << " (" << strerror( errno ) << ") ao enviar "
01935                              << "dados pelo socket usado para desbloquear o "
01936                              << "poll com a ID " << m_PollSocket
01937                              << ". Esperando entao pelo proximo dado a ser "
01938                              << "enviado!" << endl;
01939             #endif
01940         }
01941     }
01942 
01943     // Libera o acesso exlusivo ao lock.
01944     pthread_mutex_unlock( &m_Mutex );
01945 
01946     #ifdef RIO_DEBUG1
01947     TCPCONNECTIONLOG << "[CTcpConnection - PutSendData] Finish4" << endl;
01948     #endif
01949 
01950     return S_OK;
01951 }

RioResult CTcpConnection::ReceiveStreamData ( char **  Data,
unsigned int *  DataSize 
) [private]

Funcao para receber dados de uma conexao TCP associada ao stream.

Parameters:
Data ponteiro que ira armazenar o ponteiro em que os dados foram armazenados
DataSize ponteiro para armazenar o tamanho dos dados lidos.
Returns:
S_OK se nenhum erro ocorreu ao recebermos os dados, ou um valor diferente de S_OK caso algum erro tenha ocorrido.

Definition at line 200 of file NetTcp.cpp.

00202 {
00203     // Armazena os erros ao chamar as funcoes da biblioteca do C.
00204     ssize_t BytesReceived;
00205     // Variavel usada para armazenar o valor do tamanho convertido para a ordem
00206     // de bytes usada na rede.
00207     unsigned int NetDataSize;
00208 
00209     #ifdef RIO_DEBUG1
00210     TCPCONNECTIONLOG << "[CTcpConnection - ReceiveStreamData] Start" << endl;
00211     #endif
00212 
00213     // Armazena o endereco IP do stream (para a funcao inet_ntoa).
00214     struct in_addr ip;
00215 
00216     #ifdef RIO_DEBUG2
00217     // Estruturas usadas para medir o tempo de execucao de cada funcao da
00218     // thread.
00219     struct timeval Start, End;
00220     unsigned int DiffTime;
00221     #endif
00222     
00223     // Copia o endereco associado ao stream.
00224     ip.s_addr = m_IP;
00225 
00226     // Atualiza o tempo do timeout.
00227     m_LastUseTime = time( NULL );
00228 
00229     #ifdef RIO_DEBUG2
00230     // Obtem o tempo antes de executar recv (tamanho).
00231     gettimeofday( &Start, NULL );
00232     #endif
00233 
00234     // Tenta receber primeiramente o tamanho dos dados.
00235     BytesReceived = recv( m_Socket, &NetDataSize, sizeof( unsigned int ),
00236                           TCP_FLAGS_RECEIVE );
00237 
00238     #ifdef RIO_DEBUG2
00239     // Obtem o tempo depois de executar recv (tamanho).
00240     gettimeofday( &End, NULL );
00241     DiffTime = ( End.tv_sec - Start.tv_sec ) * 1000 +
00242                ( End.tv_usec - Start.tv_usec ) / 1000;
00243     TCPCONNECTIONLOG << "CTcpConnection::ReceiveStreamData tempo para executar "
00244                      << "a funcao recv (tamanho) para o socket com a ID "
00245                      << m_Socket << ": " << DiffTime << " ms." << endl;
00246     #endif
00247 
00248     // Verifica se o tamanho foi recebido corretamente.
00249     if( BytesReceived < 0 )
00250     {
00251         #ifdef RIO_DEBUG2
00252         TCPCONNECTIONLOG << "CTcpConnection::ReceiveStreamData " << errno
00253                          << " (" << strerror( errno ) << ") ao receber o "
00254                          << "tamanho do endereco IP " << inet_ntoa( ip )
00255                          << " e a porta " << ntohs( m_Port ) << " a partir "
00256                          << "do socket com a ID " << m_Socket << "." << endl;
00257         #endif
00258 
00259         *Data = NULL;
00260         *DataSize = 0;
00261 
00262         #ifdef RIO_DEBUG1
00263         TCPCONNECTIONLOG << "[CTcpConnection - ReceiveStreamData] Finish1"
00264                          << endl;
00265         #endif
00266 
00267         return ERROR_TCPCONNECTION + ERROR_SOCKET_RECEIVE;
00268     }
00269     else if( BytesReceived != sizeof( unsigned int ) )
00270     {
00271         *Data = NULL;
00272         *DataSize = 0;
00273         
00274         if( BytesReceived == 0 )
00275         {
00276             // Neste caso, possivelmente ocorreu uma queda na conexao que ainda
00277             // nao foi detectada. Por isso, vamos retornar S_OK, pois o efeito
00278             // sera similar ao de receber uma mensagem com tamanho igual a 0.
00279             // Reportamos isso no log para fins de depuracao.
00280             #ifdef RIO_DEBUG2
00281             TCPCONNECTIONLOG << "[CTcpConnection] Tentamos receber dados pela "
00282                              << "conexao TCP do IP " << inet_ntoa( ip )
00283                              << " e a porta " << ntohs( m_Port ) << ", mas "
00284                              << "nenhum dado chegou pelo socket com a ID "
00285                              << m_Socket << ". Logo, esta conexao TCP sera "
00286                              << "entao fechada!" << endl;
00287             #endif
00288 
00289             #ifdef RIO_DEBUG1
00290             TCPCONNECTIONLOG << "[CTcpConnection - ReceiveStreamData] Finish2"
00291                              << endl;
00292             #endif
00293 
00294             // Retorna S_OK para que a acao tomada na thread TcpNetMgrThread
00295             // seja similar a do termino de uma conexao devido a termos recebido
00296             // uma mensasem com tamanho igual a 0.
00297             return S_OK;
00298         }
00299         else
00300         {
00301             // Neste caso realmente ocorreu um erro, pois nao recebemos bytes
00302             // sufucientes para um tamanho de dados.
00303 
00304             #ifdef RIO_DEBUG2
00305             TCPCONNECTIONLOG << "CTcpConnection::ReceiveStreamData nao foram "
00306                              << "recebidos bytes suficientes ao receber o "
00307                              << "tamanho dos dados do endereco IP "
00308                              << inet_ntoa( ip ) << " e a porta "
00309                              << ntohs( m_Port ) << " pelo socket com a ID "
00310                              << m_Socket << ". Foram recebidos "
00311                              << BytesReceived << " bytes, mas deveriam ser "
00312                              << sizeof( unsigned int ) << " bytes." << endl;
00313             #endif
00314 
00315             #ifdef RIO_DEBUG1
00316             TCPCONNECTIONLOG << "[CTcpConnection - ReceiveStreamData] Finish3"
00317                              << endl;
00318             #endif
00319 
00320             return ERROR_TCPCONNECTION + ERROR_SOCKET_RECEIVE;
00321         }
00322     }
00323     
00324     // Converte o tamanho da ordem da rede para a ordem da maquina.
00325     *DataSize = ntohl( NetDataSize );
00326 
00327     // Recebe os dados se o tamanho for maior do que 0. Se o tamanho for igual a
00328     // 0, isso indicara que a conexao TCP foi fechada pelo outro lado.
00329     if( DataSize > 0 )
00330     {
00331         // Tenta alocar o buffer para receber os dados.
00332         try
00333         {
00334             #ifdef RIO_DEBUG2
00335             TCPCONNECTIONLOG << "CTcpConnection::ReceiveStreamData tentando "
00336                              << "alocar um vetor com " << *DataSize << " bytes "
00337                              << "para receber dados do socket com a ID "
00338                              << m_Socket << "." << endl;
00339             #endif
00340 
00341             *Data = new char[ *DataSize ];
00342 
00343             #ifdef RIO_DEBUG2
00344             TCPCONNECTIONLOG << "CTcpConnection::ReceiveStreamData vetor com "
00345                              << *DataSize << " bytes alocado com sucesso para "
00346                              << "receber dados do socket com a ID " << m_Socket
00347                              << "." << endl;
00348             #endif
00349         }
00350         catch( bad_alloc &ba )
00351         {
00352             #ifdef RIO_DEBUG2
00353             TCPCONNECTIONLOG << "CTcpConnection::ReceiveStreamData memoria "
00354                              << "insuficiente para criar o buffer com "
00355                              << *DataSize << " bytes para  receber os dados "
00356                              << "do endereco IP " << inet_ntoa( ip )
00357                              << " e a porta "  << ntohs( m_Port )
00358                              << " pelo socket com a ID " << m_Socket
00359                              << " (bad_alloc, error = " << ba.what() << ")."
00360                              << endl;
00361             #endif
00362 
00363             *DataSize = 0;
00364             *Data = NULL;
00365 
00366             #ifdef RIO_DEBUG1
00367             TCPCONNECTIONLOG << "[CTcpConnection - ReceiveStreamData] Finish4"
00368                              << endl;
00369             #endif
00370 
00371             return ERROR_TCPCONNECTION + ERROR_MEMORY;
00372 
00373         }
00374 
00375         #ifdef RIO_DEBUG2
00376         // Obtem o tempo antes de executar recv (dados)
00377         gettimeofday( &Start, NULL );
00378         #endif
00379 
00380         // Agora recebemos os dados pela conexao TCP
00381         BytesReceived = recv( m_Socket, *Data, *DataSize, TCP_FLAGS_RECEIVE );
00382 
00383         #ifdef RIO_DEBUG2
00384         // Obtem o tempo depois de executar recv (dados).
00385         gettimeofday( &End, NULL );
00386         DiffTime = ( End.tv_sec - Start.tv_sec ) * 1000 +
00387                    ( End.tv_usec - Start.tv_usec ) / 1000;
00388         TCPCONNECTIONLOG << "CTcpConnection::ReceiveStreamData tempo para "
00389                          << "executar a funcao recv (dados) para o socket com "
00390                          << "a ID " << m_Socket << ": " << DiffTime  << " ms."
00391                          << endl;
00392         #endif
00393 
00394         // Verifica se os dados foram recebidos corretamente.
00395         if( BytesReceived < 0 )
00396         {
00397             #ifdef RIO_DEBUG2
00398             TCPCONNECTIONLOG << "CTcpConnection::ReceiveStreamData erro "
00399                              << errno << " (" << strerror( errno ) << ") ao "
00400                              << "receber os dados do endereco IP "
00401                              << inet_ntoa( ip ) << " e a porta "
00402                              << ntohs( m_Port ) << "pelo socket com a ID "
00403                              << m_Socket << "." << endl;
00404             #endif
00405         
00406             // Remove o buffer alocado anteriormente.
00407             delete[] *Data;
00408 
00409             *Data = NULL;
00410             *DataSize = 0;
00411 
00412             #ifdef RIO_DEBUG1
00413             TCPCONNECTIONLOG << "[CTcpConnection - ReceiveStreamData] Finish5"
00414                              << endl;
00415             #endif
00416             
00417             return ERROR_TCPCONNECTION + ERROR_SOCKET_RECEIVE;
00418         }
00419         else if( ( ( unsigned int ) BytesReceived ) != *DataSize )
00420         {
00421             #ifdef RIO_DEBUG2
00422             TCPCONNECTIONLOG << "CTcpConnection::ReceiveStreamData os dados "
00423                              << "do endereco IP " << inet_ntoa( ip ) << " e a "
00424                              << "porta "  << ntohs( m_Port ) << "pelo "
00425                              << "socket com a ID " << m_Socket << " foram "
00426                              << "recebidos parcialmente, pois somente chegaram "
00427                              << BytesReceived << " bytes do total de "
00428                              << DataSize << "bytes." << endl;
00429             #endif
00430 
00431             // Remove o buffer alocado anteriormente.
00432             delete[] *Data;
00433 
00434             *Data = NULL;
00435             *DataSize = 0;
00436 
00437             #ifdef RIO_DEBUG1
00438             TCPCONNECTIONLOG << "[CTcpConnection - ReceiveStreamData] Finish6"
00439                              << endl;
00440             #endif
00441             
00442             return ERROR_TCPCONNECTION + ERROR_SOCKET_RECEIVE;
00443         }
00444     }
00445 
00446     #ifdef RIO_DEBUG2
00447     // Atualiza o contador de recebimento de dados.
00448     m_ReceiveCount++;
00449 
00450     TCPCONNECTIONLOG << "CTcpConnection::ReceiveStreamData foram recebidos "
00451                      << *DataSize << " bytes com sucesso pelo socket com a ID "
00452                      << m_Socket << "." << endl;
00453     #endif
00454 
00455     #ifdef RIO_DEBUG1
00456     TCPCONNECTIONLOG << "[CTcpConnection - ReceiveStreamData] Finish7"
00457                      << endl;
00458     #endif
00459 
00460     return S_OK;
00461 }

RioResult CTcpConnection::SendStreamData ( unsigned int *  DataSize,
void **  Param 
) [private]

Funcao para enviar o primeiro bloco de dados pendente em um stream TCP.

Parameters:
DataSize ponteiro para um parametro que armazenara o tamanho dos dados enviados.
Param ponteiro para o parametro passado quando os dados forem enviados pela funcao SendData.
Returns:
S_OK se nenhum erro ocorreu ao enviarmos os dados, ou um valor diferente de S_OK caso algum erro tenha ocorrido.

Definition at line 464 of file NetTcp.cpp.

00465 {
00466     // Armazena o erro retornado pelas chamadas ao sistema.
00467     ssize_t BytesSended;
00468     // Armazenam o erro retornado pelas funcoes do RIO.
00469     RioResult RioStatus;
00470     // Variavel usada para armazenar o valor do tamanho convertido para a ordem
00471     // de bytes usada na rede.
00472     unsigned int NetDataSize;
00473     // Variavel usada para armazenar um ponteiro para os dados.
00474     char *Data;
00475 
00476     #ifdef RIO_DEBUG1
00477     TCPCONNECTIONLOG << "[CTcpConnection - SendStreamData] Start" << endl;
00478     #endif
00479 
00480     #ifdef RIO_DEBUG2
00481     // Armazena o endereco IP do stream (para a funcao inet_ntoa).
00482     struct in_addr ip;
00483 
00484     // Estruturas usadas para medir o tempo de execucao de cada funcao da
00485     // thread.
00486     struct timeval Start, End;
00487     unsigned int DiffTime;
00488     #endif
00489 
00490     // Inicializa o erro retornado pela funcao.
00491     RioStatus = S_OK;
00492 
00493     // Inicializa o tamanho dos dados enviados e o identificador da
00494     // transferencia
00495     *DataSize = 0;
00496     *Param = NULL;
00497 
00498     #ifdef RIO_DEBUG2
00499     // Usado somente quando a depuracao do codigo estiver ativa.
00500     ip.s_addr = m_IP;
00501     #endif
00502 
00503     // Atualiza o tempo do timeout.
00504     m_LastUseTime = time( NULL );
00505 
00506     #ifdef RIO_DEBUG2
00507     // Obtem o tempo antes de executar GetSendData.
00508     gettimeofday( &Start, NULL );
00509     #endif
00510 
00511     // Obtem os dados a serem enviados.
00512     RioStatus = GetSendData( &Data, DataSize, Param );
00513     if( FAILED( RioStatus ) )
00514     {
00515         #ifdef RIO_DEBUG2
00516         TCPCONNECTIONLOG << "CTcpConnection::SendStreamData erro 0x" << hex
00517                          << RioStatus << dec << " ("
00518                          << GetErrorDescription( RioStatus ) << ") ao obter os "
00519                          << "dados a serem enviados pela conexao TCP com o "
00520                          << "socket com a ID " << m_Socket << "." << endl;
00521         #endif
00522 
00523         #ifdef RIO_DEBUG1
00524         TCPCONNECTIONLOG << "[CTcpConnection - SendStreamData] Finish1" << endl;
00525         #endif
00526 
00527         return RioStatus;
00528     }
00529 
00530     #ifdef RIO_DEBUG2
00531     // Obtem o tempo depois de executar GetSendData.
00532     gettimeofday( &End, NULL );
00533     DiffTime = ( End.tv_sec - Start.tv_sec ) * 1000 +
00534                ( End.tv_usec - Start.tv_usec ) / 1000;
00535     TCPCONNECTIONLOG << "CTcpConnection::SendStreamData tempo para executar a "
00536                      << "funcao GetSendData para o socket com a ID " << m_Socket
00537                      << ": " << DiffTime << " ms." << endl;
00538     #endif
00539 
00540     // Verifica se temos dados para enviar (se nao temos dados, entao estamos
00541     // enviando uma mensagem para finalizar a conexao.
00542     if( *DataSize != 0 )
00543     {
00544         // Neste caso estamos enviando dados ao outro lado (e nao terminando a
00545         // conexao).
00546 
00547         // Converte o tamanho da ordem de bytes da maquina para a ordem de bytes
00548         // da rede
00549         NetDataSize = htonl( *DataSize );
00550 
00551         // Tenta enviar os dados. Primeiramente enviaremos o tamanho dos dados,
00552         // para depois enviar os dados.
00553 
00554         // Primeramente tenta enviar o tamaho dos dados.
00555         #ifdef RIO_DEBUG2
00556         //Obtem o tempo antes de executar send (tamahho).
00557         gettimeofday( &Start, NULL );
00558         #endif
00559 
00560         BytesSended = send( m_Socket, &NetDataSize, sizeof( unsigned int ),
00561                             TCP_FLAGS_SENDSIZE );
00562 
00563         #ifdef RIO_DEBUG2
00564         // Obtem o tempo depois de executar send (tamanho).
00565         gettimeofday( &End, NULL );
00566         DiffTime = ( End.tv_sec - Start.tv_sec ) * 1000 +
00567                    ( End.tv_usec - Start.tv_usec ) / 1000;
00568         TCPCONNECTIONLOG << "CTcpConnection::SendStreamData tempo para "
00569                          << "executar a funcao send (tamanho) para o socket "
00570                          << "com a ID " << m_Socket << ": " << DiffTime 
00571                          << " ms." << endl;
00572         #endif
00573 
00574         // Verifica se ocorreu um erro ao enviar o tamanho.
00575         if( BytesSended < 0 )
00576         {
00577             #ifdef RIO_DEBUG2
00578             TCPCONNECTIONLOG << "CTcpConnection::SendStreamData " << errno
00579                              << " (" << strerror( errno ) << ") ao enviar "
00580                              << "o tamanho " << *DataSize << " ao endereco IP "
00581                              << inet_ntoa( ip ) << " e a porta " 
00582                              << ntohs( m_Port ) << " pelo socket com a ID "
00583                              << m_Socket << "." << endl;
00584             #endif
00585 
00586             RioStatus = ERROR_TCPCONNECTION + ERROR_SOCKET_SEND;
00587         }
00588         else if( BytesSended != sizeof( unsigned int ) )
00589         {
00590             #ifdef RIO_DEBUG2
00591             TCPCONNECTIONLOG << "CTcpConnection::SendStreamData nao foram "
00592                              << "enviados bytes suficientes ao enviar o "
00593                              << "tamanho dos dados para o endereco IP "
00594                              << inet_ntoa( ip ) << " e a porta "
00595                              << ntohs( m_Port ) << " pelo socket com a ID "
00596                              << m_Socket << "." << endl;
00597             #endif
00598 
00599             RioStatus = ERROR_TCPCONNECTION + ERROR_SOCKET_SEND;
00600         }
00601         else
00602         {
00603             #ifdef RIO_DEBUG2
00604             // Obtem o tempo antes de executar CreateStreamsSet
00605             gettimeofday( &Start, NULL );
00606             #endif
00607 
00608             // Primeramente tenta enviar o tamaho dos dados.
00609             // Agora que conseguimos enviar o tamanho com sucesso, passamos
00610             // entao ao envio dos dados.
00611             BytesSended = send( m_Socket, Data, *DataSize, TCP_FLAGS_SENDDATA );
00612 
00613             #ifdef RIO_DEBUG2
00614             // Obtem o tempo depois de executar CreateStreamsSet.
00615             gettimeofday( &End, NULL );
00616             DiffTime = ( End.tv_sec - Start.tv_sec ) * 1000 +
00617                        ( End.tv_usec - Start.tv_usec ) / 1000;
00618             TCPCONNECTIONLOG << "CTcpConnection::SendStreamData tempo para "
00619                              << "executar a funcao send (dados) para o socket "
00620                              << "com a ID : " << DiffTime << " ms." << endl;
00621             #endif
00622 
00623             // Verifica se ocorreu um erro ao enviar os dados.
00624             if( BytesSended < 0 )
00625             {
00626                 #ifdef RIO_DEBUG2
00627                 TCPCONNECTIONLOG << "CTcpConnection::SendStreamData " << errno
00628                                  << " (" << strerror( errno ) << ") ao enviar "
00629                                  << "os dados ao endereco IP "
00630                                  << inet_ntoa( ip ) << " e a porta "
00631                                  << ntohs( m_Port ) << " pelo socket com a ID "
00632                                  << m_Socket << "." << endl;
00633                 #endif
00634 
00635                 RioStatus = ERROR_TCPCONNECTION + ERROR_SOCKET_SEND;
00636             }
00637             else if( ( ( unsigned int ) BytesSended ) != *DataSize )
00638             {
00639                 #ifdef RIO_DEBUG2
00640                 TCPCONNECTIONLOG << "CTcpConnection::SendStreamData os dados "
00641                                  << "do endereco IP "<< inet_ntoa( ip )
00642                                  << " e a porta " << ntohs( m_Port ) << "pelo "
00643                                  << "socket com a ID " << m_Socket << " foram "
00644                                  << "enviados parcialmente, pois somente foram "
00645                                  << BytesSended << " bytes do total de "
00646                                  << *DataSize << "bytes." << endl;
00647                 #endif
00648 
00649                 RioStatus = ERROR_TCPCONNECTION + ERROR_SOCKET_SEND;
00650             }
00651             #ifdef RIO_DEBUG2
00652             else
00653             {
00654                 TCPCONNECTIONLOG << "CTcpConnection::SendStreamData foram "
00655                                  << "enviados " << *DataSize << " bytes com "
00656                                  << "sucesso pela conexao TCP com o socket com "
00657                                  << "a ID " << m_Socket << "." << endl;
00658 
00659                 // Atualiza o contador de envio de dados.
00660                 m_SendCount++;
00661             }
00662             #endif
00663         }
00664     }
00665     else
00666     {
00667         // Neste caso estamos finalizando a conexao. Precisamos enviar uma
00668         // mensagem com tamanho 0 ao outro lado da conexao.
00669         NetDataSize = htonl( 0 );
00670 
00671         #ifdef RIO_DEBUG2
00672         // Obtem o tempo antes de executar send (tamanho 0).
00673         gettimeofday( &Start, NULL );
00674         #endif
00675 
00676         // Tenta enviar o tamamnho 0.
00677         BytesSended = send( m_Socket, &NetDataSize, sizeof( unsigned int ),
00678                             TCP_FLAGS_SENDDATA );
00679 
00680         #ifdef RIO_DEBUG2
00681         // Obtem o tempo depois de executar (tamanho 0).
00682         gettimeofday( &End, NULL );
00683         DiffTime = ( End.tv_sec - Start.tv_sec ) * 1000 +
00684                    ( End.tv_usec - Start.tv_usec ) / 1000;
00685         TCPCONNECTIONLOG << "CTcpConnection::SendStreamData tempo para "
00686                          << "executar a funcao send (tamanho 0) para o "
00687                          << "socket com a ID " << m_Socket << ": " << DiffTime
00688                          << " ms." << endl;
00689         #endif
00690 
00691         // Verifica se ocorreu um erro ao enviar o tamanho 0.
00692         if( BytesSended < 0 )
00693         {
00694             #ifdef RIO_DEBUG2
00695             TCPCONNECTIONLOG << "CTcpConnection::SendStreamData " << errno
00696                              << " (" << strerror( errno ) << ") ao enviar o "
00697                              << "tamanho "<< *DataSize << " ao endereco IP "
00698                              << inet_ntoa( ip ) << " e a porta "
00699                              << ntohs( m_Port ) << " para o socket com a ID "
00700                              << m_Socket << "." << endl;
00701             #endif
00702 
00703             RioStatus = ERROR_TCPCONNECTION + ERROR_SOCKET_SEND;
00704         }
00705         else if( BytesSended != sizeof( unsigned int ) )
00706         {
00707             #ifdef RIO_DEBUG2
00708             TCPCONNECTIONLOG << "CTcpConnection::SendStreamData nao foram "
00709                              << "enviados bytes suficientes ao enviar o "
00710                              << "tamanho dos dados para o endereco IP "
00711                              << inet_ntoa( ip ) << " e a porta "
00712                              << ntohs( m_Port ) << " pelo socket com a ID "
00713                              << m_Socket << "." << endl;
00714             #endif
00715 
00716             RioStatus = ERROR_TCPCONNECTION + ERROR_SOCKET_SEND;
00717         }
00718     }
00719 
00720     #ifdef RIO_DEBUG1
00721     TCPCONNECTIONLOG << "[CTcpConnection - SendStreamData] Finish2" << endl;
00722     #endif
00723     
00724     return RioStatus;
00725 }

bool CTcpConnection::TcpNetMgrThread ( void   )  [private]

Funcao que efetivamente executa o codigo da thread de gerenciamento da reda, chamada pela funcao ReceiveThreadEp (esta funcao e usada para facilitar o acesso aos campos do objeto).

Returns:
true se podemos deletar o objeto e false em caso contrario (este valor e usado pela funcao TcpNetMgrThreadEp, que chama esta funcao, para saber se o objeto passado em ThreadParam pode ou nao ser removido.

Definition at line 767 of file NetTcp.cpp.

00768 {
00769     // Variavel booleana que diz se ainda devemos receber dados. Esta variavel
00770     // ficara true ate que a conexao seja fechada pelo outro lado (o primeiro
00771     // recv foi finalizado com nenhum byte lido), enviamos uma mensagem, com
00772     // tamanho 0, de termino de conexao, para o outro lado, ou recebemos uma
00773     // mensagem com tamanho 0.
00774     bool isConnectionActive;
00775     // Tempo atual em segundos desde a Epoch (usado para verificar o timeout
00776     // dos streams).
00777     time_t CurrentTime;
00778     // Define o movito para a conexao ter sido fechada quando isConnectionActive
00779     // se tornar false.
00780     EClosedType ClosedType;
00781     // Vetor de sockes usado pelo comando poll
00782     struct pollfd SoketsInfo[ TCPCONNECTIONSOCKETSNUMBER ];
00783     // Armazena o tempo de timeout do comando poll. Ele sera igual ao tempo de
00784     // timeout do socket TCP associado ao objeto.
00785     int PollTimeOut;
00786     // Armazena o resultado das execucoes das funcoes da classe e do objeto da
00787     // classe CTcpStreams e da classe CNetTcp.
00788     RioResult RioStatus;
00789     // Armazena o resultado da execucao das funcoes da biblioteca do C.
00790     int SystemStatus;
00791     // Usado para impressao do IP.
00792     in_addr ip;
00793 
00794     #ifdef RIO_DEBUG2
00795     // Estruturas usadas para medir o tempo de execucao de cada funcao da
00796     // thread.
00797     struct timeval Start, End;
00798     // Estruturas para medir o tempo de execucao da thread,
00799     struct timeval StartThread, EndThread;
00800 
00801     unsigned int DiffTime;
00802     #endif
00803 
00804     #ifdef RIO_DEBUG1
00805     TCPCONNECTIONLOG << "[CTcpConnection - TcpNetMgrThread] Start" << endl;
00806     #endif
00807 
00808     #ifdef RIO_DEBUG2
00809     // Inicializa a contagem de tempo da thread.
00810     if( m_ServerInstance )
00811         gettimeofday( &StartThread, NULL );
00812     #endif
00813 
00814     // Inicializa a variavel usada pelas impressoes.
00815     ip.s_addr = m_IP;
00816 
00817     #ifdef RIO_DEBUG2
00818     // Somente imprime a ID da thread se a thread estiver associada ao servidor
00819     // ou ao storage.
00820     if( m_ServerInstance )
00821         RioErr << "TCPNETMGRTHREADID START SYSID=" << syscall( SYS_gettid )
00822                << ", THREADID=" << pthread_self() << ", IP = "
00823                << inet_ntoa( ip ) << ", Port = " << ntohs( m_Port )
00824                << ", Socket = " << m_Socket << ", SYSTIME = " << time( NULL )
00825                << endl;
00826     #endif
00827 
00828     // Espera ate que a thread seja liberada para inicializar (isso somente
00829     // ocorrera apos a chamada da funcao EnableConnection, e e usado para evitar
00830     // que a threa atrapalhe o processo inicial do estabelecimento da conexao. 
00831     // Se o retorno da funcao for true, entao a conexao foi cancelada, e a 
00832     // thread foi desbloqueada somente para terminarmos a execucao.
00833     if( WaitEnableConnection() )
00834     {
00835         #ifdef RIO_DEBUG2
00836         TCPCONNECTIONLOG << "CTcpConnection::TcpNetMgrThread a conexao para o "
00837                          << "IP " << inet_ntoa( ip ) << ", a porta " 
00838                          << ntohs( m_Port ) << " e o socket com a ID " 
00839                          << m_Socket << " foi cancelada. Retornando da thread!"
00840                          << endl;
00841         #endif
00842 
00843         #ifdef RIO_DEBUG1
00844         TCPCONNECTIONLOG << "[CTcpConnection - TcpNetMgrThread] Finish1" 
00845                          << endl;
00846         #endif
00847         
00848         return false;
00849     }
00850 
00851     // Inicializa a estrutura usada pelo poll. A primeira entrada estara
00852     // associada ao socket TCP e a segunda ao socket UDP.
00853     SoketsInfo[ TCPCONNECTIONSOCKETTCP ].fd = m_Socket;
00854     SoketsInfo[ TCPCONNECTIONSOCKETTCP ].events = POLLIN;
00855     SoketsInfo[ TCPCONNECTIONSOCKETUDP ].fd = m_PollSocket;
00856     SoketsInfo[ TCPCONNECTIONSOCKETUDP ].events = POLLIN;
00857 
00858     // Inicialmente a conexao esta ativa.
00859     isConnectionActive = true;
00860 
00861     // Inicialmente a conexao nao foi fechada, entao o motivo deve estar como
00862     // nao inicializado.
00863     ClosedType = CONNECTIONUNDEFINED;
00864 
00865     // Inicializa o tempo de uso do socket.
00866     m_LastUseTime = time( NULL );
00867 
00868     // Fica em um laco ate a conexao deixar de ficar ativa.
00869     while( isConnectionActive )
00870     {
00871         // Primeiramente iremos verificar se ocorreu um timeout com o socket.
00872         // Caso isso tenha ocorrido, a conexao TCP devera ser fechada, e a
00873         // thread terminada (ou seja, isConnectionActive se tornara false).
00874         //
00875         // Obtem o tempo atual (usado para verificar se algum socket ja teve um
00876         // timeout. O tempo e desde a Epoch).
00877         CurrentTime = time( NULL );
00878 
00879         // Obtem o mutex do objeto da classe.
00880         pthread_mutex_lock( &m_Mutex );
00881 
00882         // Verifica se o socket deu timeout, caso o socket esteja associado a um
00883         // dos servidores (o cliente nao tem timeout).
00884         if( ( m_ServerInstance ) && ( m_ConnectionTimeOut != 0 ) &&
00885             ( ( m_LastUseTime + m_ConnectionTimeOut ) < CurrentTime ) &&
00886               ( m_SendQueue.empty() ) )
00887         {
00888             // Neste caso o socket deu timeout. Deveremos entao fechalo,
00889             // remove-lo do stream, e avisar o objeto da classe NetInterface que
00890             // o socket foi fechado.
00891             #ifdef RIO_DEBUG2
00892             TCPCONNECTIONLOG << "CTcpConnection::TcpNetMgrThread a conexao "
00893                              << "para o IP " << inet_ntoa( ip ) << " e a porta "
00894                              << ntohs( m_Port ) << " sera fechada por timeout "
00895                              << "porque " << m_LastUseTime + m_ConnectionTimeOut
00896                              << " e menor do que " << CurrentTime << " , e nao "
00897                              << "existem dados pendentes a serem enviados pelo "
00898                              << "socket com a ID " << m_Socket << " porque o "
00899                              << "tamanho da fila de envio e de "
00900                              << m_SendQueue.size()  << "." << endl;
00901             #endif
00902 
00903             // Informa que nao vamos mais executar o laco da conexao TCP.
00904             isConnectionActive = false;
00905 
00906             // Informa que o motivo da conexao ser fechada foi por timeout.
00907             ClosedType = CONNECTIONTIMEOUT;
00908         }
00909 
00910         // Configura o conjunto do poll para o socket TCP para usar ou nao a
00911         // escrita, de acordo com o a fila de saida estar ou nao vazia.
00912         if( m_SendQueue.empty() )
00913             SoketsInfo[ TCPCONNECTIONSOCKETTCP ].events &= POLLIN;
00914         else
00915             SoketsInfo[ TCPCONNECTIONSOCKETTCP ].events |= POLLOUT;
00916 
00917         // Libera o mutex do objeto da classe.
00918         pthread_mutex_unlock( &m_Mutex );
00919 
00920         // Somente executamos o select se a conexao nao foi fechada acima por
00921         // timeout.
00922         if( isConnectionActive )
00923         {
00924             // Nao ocorreu um timeout do socket. Entao temos que verificar, no
00925             // select, se o socket dever receber ou enviar dados.
00926 
00927             // Se e o servidor, calculamos o tempo de timeout. Porem, se e o
00928             // cliente, nao existira um timeout, e setamos
00929             if( m_ServerInstance )
00930             {
00931                 // Calcula o tempo maximo durante o qual o select sera
00932                 // bloqueado.
00933                 PollTimeOut = m_LastUseTime + m_ConnectionTimeOut -
00934                               time( NULL );
00935                 if( PollTimeOut < 0 )
00936                     PollTimeOut = 0;
00937                 else // Converte para milisegundos
00938                     PollTimeOut = PollTimeOut * 1000;
00939             }
00940             else // No caso de o objeto estar associado a um cliente,
00941                  // definiremos o timeout do poll para um valor negativo. Isso
00942                  // indicara que o poll deve ficar bloqueado ate receber algo
00943                  // de um dos sockets (o cliente nao possui timeout da conexao).
00944                 PollTimeOut = -1;
00945 
00946             #ifdef RIO_DEBUG2
00947             TCPCONNECTIONLOG << "CTcpConnection::TcpNetMgrThread antes de "
00948                              << "executar o poll, Flags do socket TCP com a ID "
00949                              << m_Socket << ": [";
00950             if( ( SoketsInfo[ TCPCONNECTIONSOCKETTCP ].events & POLLIN ) != 0 )
00951                 TCPCONNECTIONLOG << "POLLIN ";
00952             if( ( SoketsInfo[ TCPCONNECTIONSOCKETTCP ].events & POLLOUT ) != 0 )
00953                 TCPCONNECTIONLOG << "POLLOUT ";
00954             TCPCONNECTIONLOG << "], Flags do socket UDP com a ID "
00955                              << m_PollSocket << ": [";
00956             if( ( SoketsInfo[ TCPCONNECTIONSOCKETUDP ].events & POLLIN ) != 0 )
00957                 TCPCONNECTIONLOG << "POLLIN ";
00958             if( ( SoketsInfo[ TCPCONNECTIONSOCKETUDP ].events & POLLOUT ) != 0 )
00959                 TCPCONNECTIONLOG << "POLLOUT ";
00960             TCPCONNECTIONLOG << "], Timeout = " << PollTimeOut << "." << endl;
00961             #endif
00962 
00963             // Espera pelo socket TCP ou o UDP estar pronto para leitura, ou
00964             // o socket TCP esta pronto para escrita caso existam dados a serem
00965             // enviados.
00966             SystemStatus = poll( SoketsInfo, TCPCONNECTIONSOCKETSNUMBER,
00967                                  PollTimeOut );
00968 
00969             #ifdef RIO_DEBUG2
00970             TCPCONNECTIONLOG << "CTcpConnection::TcpNetMgrThread depois de "
00971                              << "executar o poll, erro = " << errno << " ("
00972                              << strerror( errno ) << ")." << endl;
00973             #endif
00974 
00975             if( SystemStatus < 0 )
00976             {
00977                 if( errno == EINTR ) // Interrupted system call
00978                 {
00979                      #ifdef RIO_DEBUG2
00980                      TCPCONNECTIONLOG << "CTcpConnection::TcpNetMgrThread "
00981                                       << "recebi o erro que a chamada ao "
00982                                       << "sistema foi interrompida." << endl;
00983                      #endif
00984                 }
00985                 else
00986                 {
00987                     #ifdef RIO_DEBUG2
00988                     TCPCONNECTIONLOG << "CTcpConnection::TcpNetMgrThread erro "
00989                                      << errno << " (" << strerror( errno )
00990                                      << ") ao executar o comando poll para o "
00991                                      << "socket com a ID " << m_Socket << "."
00992                                      << endl;
00993                     #endif
00994 
00995                     // Chama a funcao do objeto da classe CNetInterface que
00996                     // processa os erros.
00997                     m_NetTcp->ProcessError( m_IP, m_Port, ERROR_NETTCP +
00998                                                           ERROR_SOCKETS_SELECT,
00999                                             "TcpNetMgrThread-poll",
01000                                             OTHERERROR,
01001                                             ( void * ) NULLTRANSFERID );
01002                 }
01003             }
01004             else
01005             {
01006                 #ifdef RIO_DEBUG2
01007                 TCPCONNECTIONLOG << "CTcpConnection::TcpNetMgrThread a funcao "
01008                                  << "poll executada com sucesso!" << endl;
01009                 #endif
01010             }
01011 
01012             // Verifica se o socket para desbloquear o select foi usado.
01013             if( ( SoketsInfo[ TCPCONNECTIONSOCKETUDP ].revents & POLLIN ) != 0 )
01014             {
01015 
01016                 // Armazena a mensagem de estado recebida.
01017                 char Message[ MSG_POLL_SIZE + 1 ];
01018 
01019                 // Inicializa o buffer da mensagem
01020                 memset( Message, 0, MSG_POLL_SIZE + 1 );
01021 
01022                 // Recebe e imprime uma mensagem informando que o socket UDP foi
01023                 // usado para desbloquear o poll.
01024                 if( recv( m_PollSocket, Message, MSG_POLL_SIZE,
01025                           UDP_FLAGS_RECEIVE ) < 0 )
01026                 {
01027                     #ifdef RIO_DEBUG2
01028                     TCPCONNECTIONLOG << "CTcpConnection::TcpNetMgrThread erro "
01029                                      << errno << " (" << strerror( errno )
01030                                      << ") ao tentar receber a mensagem usada "
01031                                      << "para desbloquear o poll." << endl;
01032                     #endif
01033                 }
01034                 #ifdef RIO_DEBUG2
01035                 else
01036                 {
01037                     TCPCONNECTIONLOG << "CTcpConnection::TcpNetMgrThread dados "
01038                                      << "detectados no socket usado para "
01039                                      << "desbloquear o poll. A mensagem "
01040                                      << "passada foi \"" << Message << "\"."
01041                                      << endl;
01042                 }
01043                 #endif
01044             }
01045 
01046             // Verifica se o socket TCP (se o socket ainda estiver em
01047             // TcpReadSocketsSet, isso significara que dados foram recebidos por
01048             // este socket).
01049             if( ( SoketsInfo[ TCPCONNECTIONSOCKETTCP ].revents & POLLIN ) != 0 )
01050             {
01051                 // Armazena o ponteiro para o buffer com os dados lidos (alocado
01052                 // pela funcao que recebe os dados).
01053                 char *ReceivedData;
01054                 // Armazena o tamanho dos dados recebidos (definido tambem pela
01055                 // funcao que recebe os dados).
01056                 unsigned int ReceivedDataSize;
01057             
01058                 #ifdef RIO_DEBUG2
01059                 // Obtem o tempo antes de executar ReceiveStreamData.
01060                 gettimeofday( &Start, NULL );
01061                 #endif
01062 
01063                 // Recebe os dados pelo socket TCP.
01064                 RioStatus = ReceiveStreamData( &ReceivedData, 
01065                                                &ReceivedDataSize );
01066 
01067                 #ifdef RIO_DEBUG2
01068                 // Obtem o tempo depois de executar ReceiveStreamData.
01069                 gettimeofday( &End, NULL );
01070                 DiffTime = ( End.tv_sec - Start.tv_sec ) * 1000 +
01071                            ( End.tv_usec - Start.tv_usec ) / 1000;
01072                 TCPCONNECTIONLOG << "CTcpConnection::TcpNetMgrThread tempo "
01073                                  << "para executar a funcao ReceiveStreamData "
01074                                  << "para o socket com a ID " << m_Socket
01075                                  << ": " << DiffTime << " ms." << endl;
01076                 #endif
01077 
01078                 // Verifica se ocorreu erro na leitura.
01079                 if( FAILED( RioStatus ) )
01080                 {
01081                     // Se ocorreu algum erro, devemos avisar para a classe de
01082                     // gerenciamento da conexao.
01083 
01084                     #ifdef RIO_DEBUG2
01085                     TCPCONNECTIONLOG << "CTcpConnection::TcpNetMgrThread erro "
01086                                      << " 0x" << hex << RioStatus << dec << " ("
01087                                      << GetErrorDescription( RioStatus ) << ") "
01088                                      << "ao receber dados pela conexao TCP "
01089                                      << "associada ao IP " << inet_ntoa( ip )
01090                                      << ", a porta " << ntohs( m_Port )
01091                                      << "pelo socket com o ID " << m_Socket
01092                                      << endl;
01093                     #endif
01094 
01095                     // Chama a funcao do objeto da classe CNetInterface que
01096                     // processa os erros.
01097                     m_NetTcp->ProcessError( m_IP, m_Port, RioStatus,
01098                                             "TcpNetMgrThread-ReceiveStreamData",
01099                                             RECEIVEERROR,
01100                                             ( void * ) NULLTRANSFERID );
01101                 }
01102                 else
01103                 {
01104                     // Verifica se o tamanho dos dados e 0. Neste caso, o outro
01105                     // lado da conexao fechou a conexao.
01106                     if( ReceivedDataSize == 0 )
01107                     {
01108                         // Obtem o mutex do objeto da classe.
01109                         pthread_mutex_lock( &m_Mutex );
01110 
01111                         // Imprime as informacoes de depuracao (se RIO_DEBUG2
01112                         // for usado).
01113                         #ifdef RIO_DEBUG2
01114                         TCPCONNECTIONLOG << "CTcpConnection::TcpNetMgrThread "
01115                                          << "conexao TCP com o IP "
01116                                          << inet_ntoa( ip ) << ", a porta "
01117                                          << ntohs( m_Port ) << " e com o "
01118                                          << "socket com a ID " << m_Socket
01119                                          << " foi fechada pelo outro lado."
01120                                          << endl;
01121                         #endif
01122 
01123                         // Remove a flag de escrita pronta do socket.
01124                         SoketsInfo[ TCPCONNECTIONSOCKETTCP ].revents &= POLLIN;
01125 
01126                         // Informa que nao vamos mais executar o laco da conexao
01127                         // TCP.
01128                         isConnectionActive = false;
01129 
01130                         // Informa que o motivo da conexao ser fechada foi pelo
01131                         // outro lado.
01132                         ClosedType = CONNECTIONCLOSEDREMOTELLY;
01133 
01134                         // Libera o mutex do objeto da classe.
01135                         pthread_mutex_unlock( &m_Mutex );
01136                     }
01137                     else
01138                     {
01139                         // Neste caso recebemos corretamente um pacote da
01140                         // conexao TCP. Entao deveremos chamar a funcao
01141                         // responsavel por tratar dos dados recebidos.
01142                         #ifdef RIO_DEBUG2
01143                         TCPCONNECTIONLOG << "CTcpConnection::TcpNetMgrThread "
01144                                          << "Recebidos " << ReceivedDataSize
01145                                          << " bytes pelo IP " << inet_ntoa( ip )
01146                                          << " e da porta " << ntohs( m_Port )
01147                                          << "pelo socket com a ID "
01148                                          << m_Socket << "." << endl;
01149                         #endif
01150 
01151                         #ifdef RIO_DEBUG2
01152                         // Obtem o tempo antes de executar ProcessData.
01153                         gettimeofday( &Start, NULL );
01154                         #endif
01155 
01156                         // Chama a funcao do objeto da classe CNetInterface que
01157                         // processa os dados recebidos pela conexao TCP.
01158                         m_NetTcp->ProcessData( m_IP, m_Port, ReceivedData,
01159                                                ReceivedDataSize );
01160 
01161                         #ifdef RIO_DEBUG2
01162                         // Obtem o tempo depois de executar ProcessData.
01163                         gettimeofday( &End, NULL );
01164                         DiffTime = ( End.tv_sec - Start.tv_sec ) * 1000 +
01165                                    ( End.tv_usec - Start.tv_usec ) / 1000;
01166                         TCPCONNECTIONLOG << "CTcpConnection::TcpNetMgrThread "
01167                                          << "tempo para executar a funcao "
01168                                          << "ProcessData para o socket com a "
01169                                          << "ID " << m_Socket << ": "
01170                                          << DiffTime << " ms." << endl;
01171                         #endif
01172 
01173                         // Remove o buffer com os dados recebidos (a funcao
01174                         // ProcessData deve copiar os dados e nunca usar o
01175                         // ponteiro ReceivedData depois de retornar).
01176                         delete[] ReceivedData;
01177                     }
01178                 }
01179             }
01180 
01181             // Verifica se o socket TCP pode enviar dados (se ele estiver em
01182             // TcpWriteSocketsSet, isso significara que dados podem ser enviados
01183             // por este socket.
01184             if( ( SoketsInfo[ TCPCONNECTIONSOCKETTCP ].revents & POLLOUT )
01185                 != 0 )
01186             {
01187                 // Armazena o tamanho dos dados enviados pelo comando send.
01188                 unsigned int DataSize;
01189                 void *Param;
01190 
01191                 #ifdef RIO_DEBUG2
01192                 // Obtem o tempo antes de executar SendStreamData.
01193                 gettimeofday( &Start, NULL );
01194                 #endif
01195 
01196                 // Envia o proximo dado pendente pelo socket.
01197                 RioStatus = SendStreamData( &DataSize, &Param );
01198 
01199                 #ifdef RIO_DEBUG2
01200                 // Obtem o tempo depois de executar SendStreamData.
01201                 gettimeofday( &End, NULL );
01202                 DiffTime = ( End.tv_sec - Start.tv_sec ) * 1000 +
01203                            ( End.tv_usec - Start.tv_usec ) / 1000;
01204                 TCPCONNECTIONLOG << "CTcpConnection::TcpNetMgrThread tempo "
01205                                  << "para executar a funcao SendStreamData "
01206                                  << "para o socket com a ID " << m_Socket
01207                                  << ": " << DiffTime << " ms." << endl;
01208                 #endif
01209 
01210                 // Verifica se ocorreu algum erro ao executar SendStreamData.
01211                 if( FAILED( RioStatus ) )
01212                 {
01213                     // Se ocorreu algum erro, devemos avisar para a classe de
01214                     // gerenciamento da conexao.
01215                     #ifdef RIO_DEBUG2
01216                     TCPCONNECTIONLOG << "CTcpConnection::TcpNetMgrThread erro "
01217                                      << "0x" << hex << RioStatus << dec << " ("
01218                                      << GetErrorDescription( RioStatus )
01219                                      << ") ao enviar dados pela conexao TCP "
01220                                      << "associada ao IP " << inet_ntoa( ip )
01221                                      << ", a porta " << ntohs( m_Port ) << " e "
01222                                      << "o socket com a ID " << m_Socket << "."
01223                                      << endl;
01224                     #endif
01225 
01226                     // Chama a funcao do objeto da classe CNetInterface que
01227                     // processa os erros.
01228                     m_NetTcp->ProcessError( m_IP, m_Port, RioStatus,
01229                                             "TcpNetMgrThread-SendStreamData",
01230                                             SENDERROR, Param );
01231                 }
01232                 else
01233                 {
01234                     // Verifica se devemos chamar a callback (isso nao ocorrera
01235                     // se o tamanho dos dados for 0, pois o tamanho 0 e usado
01236                     // para finalizar as conexoes TCP.
01237                     if( DataSize == 0 )
01238                     {
01239                         // Obtem o mutex do objeto da classe.
01240                         pthread_mutex_lock( &m_Mutex );
01241 
01242                         #ifdef RIO_DEBUG2
01243                         TCPCONNECTIONLOG << "CTcpConnection::TcpNetMgrThread "
01244                                          << "conexao TCP com o IP "
01245                                          << inet_ntoa( ip ) << ", a porta "
01246                                          << ntohs( m_Port ) << " e com o "
01247                                          << "socket com a ID " << m_Socket
01248                                          << " foi fechada pelo por este lado. "
01249                                          << endl;
01250                         #endif
01251 
01252                         // Informa que nao vamos mais executar o laco da conexao
01253                         // TCP.
01254                         isConnectionActive = false;
01255 
01256                         // Informa que o motivo da conexao ser fechada foi
01257                         // porque locamente a conexao foi finalizada.
01258                         ClosedType = CONNECTIONCLOSEDLOCALLY;
01259 
01260                         // Libera o mutex do objeto da classe.
01261                         pthread_mutex_unlock( &m_Mutex );
01262                     }
01263                     else
01264                     {
01265                         #ifdef RIO_DEBUG2
01266                         TCPCONNECTIONLOG << "CTcpConnection::TcpNetMgrThread os "
01267                                          << DataSize << " bytes dos dados "
01268                                          << "foram enviados com sucesso pela "
01269                                          << "conexao TCP com o IP "
01270                                          << inet_ntoa( ip ) << ", a porta "
01271                                          << ntohs( m_Port )
01272                                          << " e com socket a ID " << m_Socket
01273                                          << "." << endl;
01274                         #endif
01275 
01276                         // Adiciona os dados que foram enviados no log de envio
01277                         // de dados. Porem, antes precisamos verificar se
01278                         // deveremos gerar uma linha com os logs
01279                         if( ( m_ServerInstance ) && ( m_LogRotation != NULL ) )
01280                         {
01281                             // Tamanho suficiente para um numero de ate 4GB
01282                             // mais o '\0'. Devemos mudar isso depois? Era assim
01283                             // que estava na RioNeti.
01284                             char StrPacketSize[ 11 ];
01285                             sprintf( StrPacketSize, "%d", DataSize );
01286                             RioStatus = m_LogRotation->NewLogLine( time( NULL ),
01287                                                                    StrPacketSize
01288                                                                   );
01289                             #ifdef RIO_DEBUG2
01290                             if( FAILED( RioStatus ) )
01291                                 TCPCONNECTIONLOG << "CTcpConnection::"
01292                                                  << "TcpNetMgrThread erro 0x"
01293                                                  << hex << RioStatus << dec
01294                                                  << " ("
01295                                                  << GetErrorDescription(
01296                                                                  RioStatus )
01297                                                  << ") ao escrever no log."
01298                                                  << endl;
01299                             #endif
01300                         }
01301 
01302                         #ifdef RIO_DEBUG2
01303                         // Obtem o tempo antes de executar SendDataCompleted.
01304                         gettimeofday( &Start, NULL );
01305                         #endif
01306 
01307                         // Chama a funcao do objeto da classe CNetInterface,
01308                         // para informar que os dados foram enviados.
01309                         m_NetTcp->SendDataCompleted( m_IP, m_Port, Param );
01310 
01311                         #ifdef RIO_DEBUG2
01312                         // Obtem o tempo depois de executar SendDataCompleted.
01313                         gettimeofday( &End, NULL );
01314                         DiffTime = ( End.tv_sec - Start.tv_sec ) * 1000 +
01315                                    ( End.tv_usec - Start.tv_usec ) / 1000;
01316                         TCPCONNECTIONLOG << "CTcpConnection::TcpNetMgrThread "
01317                                          << "tempo para executar a funcao "
01318                                          << "SendDataCompleted para o socket "
01319                                          << "com a ID " << m_Socket << ": "
01320                                          << DiffTime << " ms." << endl;
01321                         #endif
01322                     }
01323                 }
01324             }
01325 
01326             #ifdef RIO_DEBUG2
01327             // Verifica os outros erros que podem ter ocorrido com os sockets
01328             // TCP e UDP.
01329             if( ( SoketsInfo[ TCPCONNECTIONSOCKETTCP ].revents & POLLPRI )
01330                 != 0 )
01331             {
01332                 TCPCONNECTIONLOG << "CTcpConnection::TcpNetMgrThread evento "
01333                                  << "POLLPRI detectado no socket TCP com a "
01334                                  << "ID " << m_Socket << "." << endl;
01335             }
01336             if( ( SoketsInfo[ TCPCONNECTIONSOCKETUDP ].revents & POLLPRI )
01337                 != 0 )
01338             {
01339                 TCPCONNECTIONLOG << "CTcpConnection::TcpNetMgrThread evento "
01340                                  << "POLLPRI detectado no socket UDP com a "
01341                                  << "ID " << m_PollSocket << "." << endl;
01342             }
01343             if( ( SoketsInfo[ TCPCONNECTIONSOCKETTCP ].revents & POLLERR )
01344                 != 0 )
01345             {
01346                 TCPCONNECTIONLOG << "CTcpConnection::TcpNetMgrThread evento "
01347                                  << "POLLERR detectado no socket TCP com a "
01348                                  << "ID " << m_Socket << "." << endl;
01349             }
01350             if( ( SoketsInfo[ TCPCONNECTIONSOCKETUDP ].revents & POLLERR )
01351                 != 0 )
01352             {
01353                 TCPCONNECTIONLOG << "CTcpConnection::TcpNetMgrThread evento "
01354                                  << "POLLERR detectado no socket UDP com a "
01355                                  << "ID " << m_PollSocket << "." << endl;
01356             }
01357             if( ( SoketsInfo[ TCPCONNECTIONSOCKETTCP ].revents & POLLHUP )
01358                 != 0 )
01359             {
01360                 TCPCONNECTIONLOG << "CTcpConnection::TcpNetMgrThread evento "
01361                                  << "POLLHUP detectado no socket TCP com a "
01362                                  << "ID " << m_Socket << "." << endl;
01363             }
01364             if( ( SoketsInfo[ TCPCONNECTIONSOCKETUDP ].revents & POLLHUP )
01365                 != 0 )
01366             {
01367                 TCPCONNECTIONLOG << "CTcpConnection::TcpNetMgrThread evento "
01368                                  << "POLLHUP detectado no socket UDP com a "
01369                                  << "ID " << m_PollSocket << "." << endl;
01370             }
01371             if( ( SoketsInfo[ TCPCONNECTIONSOCKETTCP ].revents & POLLNVAL )
01372                 != 0 )
01373             {
01374                 TCPCONNECTIONLOG << "CTcpConnection::TcpNetMgrThread evento "
01375                                  << "POLLNVAL detectado no socket TCP com a "
01376                                  << "ID " << m_Socket << "." << endl;
01377             }
01378             if( ( SoketsInfo[ TCPCONNECTIONSOCKETUDP ].revents & POLLNVAL )
01379                 != 0 )
01380             {
01381                 TCPCONNECTIONLOG << "CTcpConnection::TcpNetMgrThread evento "
01382                                  << "POLLNVAL detectado no socket UDP com a "
01383                                  << "ID " << m_PollSocket << "." << endl;
01384             }
01385             #endif
01386 
01387         }
01388     }
01389 
01390     // Como saimos do laco, isso significa que a conexao TCP foi fechada.
01391 
01392     #ifdef RIO_DEBUG2
01393     // Obtem o tempo antes de executar ConnectionClosed.
01394     gettimeofday( &Start, NULL );
01395     #endif
01396 
01397     // Informa ao objeto da classe CNetInterface que a conexao associada a
01398     // conexao TCP foi fechada.
01399     m_NetTcp->ConnectionClosed( m_IP, m_Port, ClosedType );
01400 
01401     #ifdef RIO_DEBUG2
01402     // Obtem o tempo depois de executar ConnectionClosed.
01403     gettimeofday( &End, NULL );
01404     DiffTime = ( End.tv_sec - Start.tv_sec ) * 1000 +
01405                ( End.tv_usec - Start.tv_usec ) / 1000;
01406     TCPCONNECTIONLOG << "CTcpConnection::TcpNetMgrThread tempo para executar a "
01407                      << "funcao ConnectionClosed para o socket com a ID "
01408                      << m_Socket << ": " << DiffTime << " ms." << endl;
01409     #endif
01410 
01411     // Obtem o mutex do objeto da classe.
01412     pthread_mutex_lock( &m_Mutex );
01413 
01414     // Verifica se o socket a ser fechado tem dados
01415     // pendentes pois, neste caso, nao iremos mais enviar
01416     // dados por ele.
01417     if( m_SendQueue.size() > 0 )
01418     {
01419         #ifdef RIO_DEBUG2
01420         TCPCONNECTIONLOG << "CTcpConnection::TcpNetMgrThread Existia(m) um "
01421                          << "conjunto(s) de " << m_SendQueue.size() << " dados "
01422                          << "pendentes para serem enviados! Os dados serao ignorados!"
01423                          << endl;
01424         #endif
01425     }
01426 
01427     // Libera o mutex do objeto da classe.
01428     pthread_mutex_unlock( &m_Mutex );
01429 
01430     // Faz o shutdown no socket.
01431     shutdown( m_Socket, SHUT_RDWR );
01432 
01433     // Fecha o socket associado ao stream TCP.
01434     close( m_Socket );
01435 
01436     // Faz o shudown do socket usado para desbloquear o poll.
01437     shutdown( m_PollSocket, SHUT_RDWR );
01438 
01439     // Fecha o socket usado para desbloquear o poll.
01440     close( m_PollSocket );
01441 
01442     // Imprime as informacoes de depuracao (se RIO_DEBUG2 for
01443     // usado).
01444     #ifdef RIO_DEBUG2
01445     TCPCONNECTIONLOG << "CTcpConnection::TcpNetMgrThread conexao TCP com o IP "
01446                      << inet_ntoa( ip ) << ", a porta " << ntohs( m_Port )
01447                      << " e com o socket com a ID " << m_Socket << " foi "
01448                      << "fechada ";
01449     switch( ClosedType )
01450     {
01451         case CONNECTIONCLOSEDLOCALLY:
01452             TCPCONNECTIONLOG << "localmente.";
01453             break;
01454         case CONNECTIONCLOSEDREMOTELLY:
01455             TCPCONNECTIONLOG << "remotamente.";
01456             break;
01457         case CONNECTIONTIMEOUT:
01458             TCPCONNECTIONLOG << "devido a um timeout (depois de "
01459                              << m_ConnectionTimeOut << " segundos).";
01460             break;
01461         default:
01462             TCPCONNECTIONLOG << "(valor " << ClosedType << "e o "
01463                          << "CONNECTIONUNDEFINED ou invalido, e nao "
01464                          << "deveria ter sido usado!).";
01465             break;
01466     }
01467     TCPCONNECTIONLOG << "Dados enviados = " << m_SendCount << " e dados "
01468                      << "recebidos = " << m_ReceiveCount << "." << endl;
01469     #endif
01470 
01471     #ifdef RIO_DEBUG2
01472     if( m_ServerInstance )
01473     {
01474         // Final da a contagem de tempo da thread.
01475         gettimeofday( &EndThread, NULL );
01476 
01477         // Calcula o tempo de execucao em ms.
01478         DiffTime = ( EndThread.tv_sec - StartThread.tv_sec ) * 1000 +
01479                    ( EndThread.tv_usec - StartThread.tv_usec ) / 1000;
01480 
01481         RioErr << "TCPNETMGRTHREADID END, SYSID=" << syscall( SYS_gettid )
01482                << ", THREADID=" << pthread_self() << ", IP = "
01483                << inet_ntoa( ip ) << ", Port = " << ntohs( m_Port )
01484                << ", Socket = " << m_Socket << ", Time = " << DiffTime << "ms."
01485                << endl;
01486     }
01487     #endif
01488 
01489     #ifdef RIO_DEBUG1
01490     TCPCONNECTIONLOG << "[CTcpConnection - TcpNetMgrThread] Finish2" << endl;
01491     #endif
01492 
01493     return true;
01494 }

void * CTcpConnection::TcpNetMgrThreadEp ( void *  ThreadParam  )  [static, private]

Funcao que trata da execucao do codigo da thread de gerenciamento das conexoes TCP ativas.

Parameters:
ThreadParam ponteiro com o parametro da thread. Para esta thread, e um ponteiro para um objeto da classe CNetTcp.

Definition at line 1499 of file NetTcp.cpp.

01500 {
01501     // Armazena o ponteiro do objeto passado como parametro a thread.
01502     CTcpConnection *TcpConnection = ( CTcpConnection * ) ThreadParam;
01503     // Armazena o retorno da execucao da thread.
01504     bool ThreadResult;
01505 
01506     #ifdef RIO_DEBUG1
01507     TCPCONNECTIONLOGEST << "[CTcpConnection - TcpNetMgrThreadEp] Start" << endl;
01508     #endif
01509 
01510     // Executa o codigo da thread associada ao objeto TcpConnection.
01511     ThreadResult = TcpConnection->TcpNetMgrThread();
01512 
01513     // Remove o objeto TcpConnection, se ThreadResult for true (Se for false,
01514     // entao a execucao da thread foi abortada, o que significa que o objeto
01515     // sera deletado em outro lugar (isso ocorrera ou na funcao TcpAccept ou
01516     // na funcao TcpConnect da classe CNetTcp.
01517     if( ThreadResult )
01518         delete TcpConnection;
01519 
01520     #ifdef RIO_DEBUG1
01521     TCPCONNECTIONLOGEST << "[CTcpConnection - TcpNetMgrThreadEp] Finish"
01522                         << endl;
01523     #endif
01524 
01525     return NULL;
01526 }

bool CTcpConnection::WaitEnableConnection ( void   )  [private]

Funcao para esperar ate que a funcao EnableConnection.

Returns:
true se a conexao foi cancelada, ou false caso a conexao nao tenha sido cancelada.

Definition at line 728 of file NetTcp.cpp.

00729 {
00730     // Armazena uma copia de m_isAborted;
00731     bool isAborted;
00732 
00733     #ifdef RIO_DEBUG1
00734     TCPCONNECTIONLOG << "[CTcpConnection - WaitEnableConnection] Start" << endl;
00735     #endif
00736     
00737     // Obtem o lock do objeto.
00738     pthread_mutex_lock( &m_Mutex );
00739 
00740     // Espera, na variavel de condicao m_Cond, a conexao ser habilitada, somente
00741     // se m_SentSignal for false.
00742     if( !m_SentSignal )
00743         pthread_cond_wait( &m_Cond, &m_Mutex );
00744 
00745     // Como recebemos o sinal, fazemos m_SentSignal ser false.
00746     m_SentSignal = false;
00747 
00748     // Copia o valor de m_isAborted, que informa se devemos continuar a execucao
00749     // da thread (false) ou se a conexao foi abortada e a thread deve ser 
00750     // finalizada (true).
00751 
00752     isAborted = m_isAborted;
00753 
00754     // Libera o acesso exlusivo ao lock.
00755     pthread_mutex_unlock( &m_Mutex );
00756 
00757     #ifdef RIO_DEBUG1
00758     TCPCONNECTIONLOG << "[CTcpConnection - WaitEnableConnection] Finish"
00759                      << endl;
00760     #endif
00761 
00762     return isAborted;
00763 }


Field Documentation

pthread_cond_t CTcpConnection::m_Cond [private]

Definition at line 247 of file NetTcp.h.

Definition at line 224 of file NetTcp.h.

Definition at line 205 of file NetTcp.h.

int CTcpConnection::m_IP [private]

Definition at line 213 of file NetTcp.h.

Definition at line 249 of file NetTcp.h.

Definition at line 231 of file NetTcp.h.

Definition at line 220 of file NetTcp.h.

Definition at line 211 of file NetTcp.h.

pthread_mutex_t CTcpConnection::m_Mutex [private]

Definition at line 244 of file NetTcp.h.

Definition at line 203 of file NetTcp.h.

Definition at line 254 of file NetTcp.h.

struct sockaddr_in CTcpConnection::m_PollSocketAddr [private]

Definition at line 256 of file NetTcp.h.

int CTcpConnection::m_Port [private]

Definition at line 215 of file NetTcp.h.

Definition at line 227 of file NetTcp.h.

Definition at line 251 of file NetTcp.h.

Definition at line 208 of file NetTcp.h.

int CTcpConnection::m_Socket [private]

Definition at line 217 of file NetTcp.h.

Definition at line 240 of file NetTcp.h.


The documentation for this class was generated from the following files:
Generated on Wed Jul 4 16:03:34 2012 for RIO by  doxygen 1.6.3