// BufferedSocket.cpp: implementation of the CBufferedSocket class. // ////////////////////////////////////////////////////////////////////// #include "stdafx.h" #include "BufferedSocket.h" #ifdef _DEBUG #undef THIS_FILE static char THIS_FILE[]=__FILE__; #define new DEBUG_NEW #endif //IMPLEMENT_DYNAMIC(CBufferedSocket, CThreadedSocket) ////////////////////////////////////////////////////////////////////// // Construction/Destruction ////////////////////////////////////////////////////////////////////// CBufferedSocket::CBufferedSocket() { separator = '\n'; ptr = buf; connected = false; InitializeCriticalSection( &m_CritSection ); } CBufferedSocket::~CBufferedSocket() { } void CBufferedSocket::Accept(CBufferedSocket& rConnectedSocket, SOCKADDR* lpSockAddr , int* lpSockAddrLen ) { CThreadedSocket::Accept(rConnectedSocket, lpSockAddr , lpSockAddrLen ); rConnectedSocket.connected = true; } void CBufferedSocket::OnReceive(int nErrorCode) { char *ptr_nl; long nb_to_read = 0; long nb; SOCKADDR addr; int len = sizeof( addr ); /* limitation taille buffer */ nb_to_read = MAX_BUFFER - ( ptr - buf ); if( nb_to_read == 0 ) { TRACE("Erreur message trop long sans LF\n"); ptr = buf; return; } nb = ReceiveFrom( ptr, nb_to_read, &addr, &len, MSG_PARTIAL ); if ( nb == SOCKET_ERROR ) { int err = GetLastError(); if ( err != WSAESHUTDOWN ) // shutdown by remote side ? TRACE("error Receive %d socket %d\n",GetLastError(),m_hSocket); Close(); return; } if ( nb == 0 ) // shutdown by remote side ? { Close(); return; } ptr += nb; assert ( ptr < (buf +sizeof( buf ))); *ptr = '\0'; ptr = buf; while( (ptr_nl = strchr( ptr, '\n' ))) { *ptr_nl = '\0'; //TRACE("message %s\n", ptr ); OnReceive( ptr ); ptr = ++ptr_nl; } if ( *ptr != '\0' ) { /* recopie ligne incomplete au debut du buffer */ strcpy( buf, ptr ); ptr = buf + strlen(buf); } else { ptr = buf; } } void CBufferedSocket::OnReceive( char *line ) { } void CBufferedSocket::SetSeparator( char sep ) { separator = sep; } void CBufferedSocket::OnWakeup() { string msg; BOOL empty; try { // on essaye de garder la section critique a l'interieur de la boucle // pour permettre l'entrelacement avec la partie emetrice do { EnterCriticalSection( &m_CritSection ); empty = buf_out.empty(); if ( !empty ) msg = buf_out.front(); LeaveCriticalSection( &m_CritSection ); //TRACE("CBufferedSocket::OnWakeup Sending buffer %s\n",msg.c_str()); if ( !empty ) { int lg = msg.length(); CThreadedSocket::Send( msg.c_str(), lg ); EnterCriticalSection( &m_CritSection ); buf_out.pop_front(); LeaveCriticalSection( &m_CritSection ); } } while ( !empty ); } catch ( CThreadedSocketException* e ) { int err = e->GetError(); if ( err == WSAEWOULDBLOCK ) { // put back the buffer, preserving the order //EnterCriticalSection( &m_CritSection ); //buf_out.push_front( msg); //LeaveCriticalSection( &m_CritSection ); } else TRACE("CBufferedSocket::OnWakeup error %d Sending buffer %s \n",err,msg.c_str()); } } void CBufferedSocket::OnSend( int nErrorCode ) { OnWakeup(); } void CBufferedSocket::OnConnect( int nErrorCode ) { connected = true; OnWakeup(); //TRACE("CBufferedSocket::OnConnect buffer empty %d\n",buf_out.IsEmpty()); } void CBufferedSocket::Send ( const char * data ) { //BOOL toBeSignaled; EnterCriticalSection( &m_CritSection ); //toBeSignaled = buf_out.IsEmpty() && connected; buf_out.push_back( string(data) ); LeaveCriticalSection( &m_CritSection ); //TRACE("CBufferedSocket::Send Adding buffer to send count %d\n",buf_out.size()); if ( connected ) { BOOL ok = WSASetEvent( m_hEvent[1] ); if ( !ok ) TRACE( "CBufferedSocket::Send Error SetEvent %d\n", WSAGetLastError()); } }