// IvyApplication.cpp : implementation file // #include "stdafx.h" //#include "libIvy.h" #include "IvyApplication.h" #include "Regexp.h" //#define DEBUG #define ARG_START "\002" #define ARG_END "\003" ///////////////////////////////////////////////////////////////////////////// // IvyApplication IvyApplication::IvyApplication(Ivy * bus) { this->bus = bus; remoteService = 0; /* unknown or unconnected application */ appname = "Unknown"; AppConnectedCallbackCalled = false; } IvyApplication::~IvyApplication() { // bus->RemoveApplication( this ); for ( int i = 0; i < regexp_in.size(); i++) delete regexp_in[i]; regexp_in.clear(); if ( m_hSocket != INVALID_SOCKET ) Close(); } ///////////////////////////////////////////////////////////////////////////// // IvyApplication member functions void IvyApplication::Create(const char* host, UINT & port) { // Exception to catch CBufferedSocket::Create(); Connect(host, port); } UINT IvyApplication::Create() { string host; UINT port; CBufferedSocket::Create(); // Max Listen Connexion Listen( SOMAXCONN ); GetSockName( host, port ); TRACE(" TCP %s:%d\n", host.c_str(), port ); #ifdef DEBUG TRACE( "IvyApplication::Create server socket %d\n", m_hSocket ); #endif return port; } void IvyApplication::OnReceive(char * line) { int err,id; int kind_of_msg = Bye; Regexp *exp; int argc = 0; const char *argv[Regexp::NSUBEXP]; char *arg; #ifdef DEBUG TRACE("Receive %s\n",line); #endif //DEBUG err = sscanf( line ,"%d %d", &kind_of_msg, &id); arg = strstr( line , ARG_START ); if ( (err != 2) || (arg == NULL) ) { TRACE("Quitting bad format %s\n", line); SendMsg(Error, Error, "bad format request expected 'type id ...'"); // bus->RemoveApplication( this ); Close(); return; } arg++; switch( kind_of_msg ) { case Bye: #ifdef DEBUG TRACE("Quitting %s\n", line); #endif //DEBUG // bus->RemoveApplication( this ); Close(); break; case Error: #ifdef DEBUG TRACE("Receive error %d %s\n", id, arg); #endif //DEBUG break; case AddRegexp: #ifdef DEBUG TRACE("Regexp id=%d exp='%s'\n", id, arg); #endif //DEBUG if ( !bus->CheckRegexp( arg ) ) { #ifdef DEBUG TRACE("Warning exp='%s' can't match removing from %s\n",arg,appname.c_str()); #endif //DEBUG return; } exp = new Regexp( arg ); if ( !exp->CompiledOK() ) { string regerr = exp->GetErrorString(); string err; err = "Error can't compile regexp '"+string(arg)+"' error "+regerr; SendMsg( Error, Error, err.c_str() ); TRACE("IvyApplication %s\n",err.c_str()); return; } regexp_in[ id ] = exp ; break; case DelRegexp: #ifdef DEBUG TRACE("Regexp Delete id=%d\n", id); #endif //DEBUG if ( regexp_in.find(id) != regexp_in.end() ) { exp = regexp_in[ id ]; delete exp; regexp_in.erase( id ); } break; case StartRegexp: #ifdef DEBUG TRACE("Regexp Start id=%d\n", id); #endif //DEBUG appname = arg; /* remote socket port */ remoteService = id; if ( bus->CheckConnected( this ) ) { TRACE("Quitting already connected %s\n", appname.c_str()); SendMsg( Error, Error, "already connected" ); // bus->RemoveApplication( this ); Close(); } break; case EndRegexp: #ifdef DEBUG TRACE("Regexp End id=%d\n", id); #endif //DEBUG bus->CallApplicationConnectedCallback( this ); AppConnectedCallbackCalled = true; if ( !bus->ready_message.empty() ) SendMsg( bus->ready_message.c_str() ); break; case Msg: #ifdef DEBUG TRACE("Message id=%d msg='%s'\n", id, arg); #endif //DEBUG arg = strtok( arg, ARG_END); while ( arg ) { argv[argc++] = arg; arg = strtok( NULL, ARG_END ); } bus->CallMessageCallback( this, id, argc, argv ); break; case DirectMsg: #ifdef DEBUG TRACE("Direct Message id=%d msg='%s'\n", id, arg); #endif //DEBUG bus->CallDirectMessageCallback( this, id, arg ); break; case Die: #ifdef DEBUG TRACE("Die Message id=%d msg='%s'\n", id, arg); #endif //DEBUG if ( bus->CallDieCallback( this, id, arg ) ) { PostMessage( NULL, WM_CLOSE, 0, 0); exit(-1); } break; default: TRACE("Receive unhandled message %s\n", line); break; } } void IvyApplication::SendMsg(MsgType msg, int id, const char * arg) { char buffer[1024]; if ( arg ) sprintf( buffer, "%d %d" ARG_START "%s\n", msg, id, arg ); else sprintf( buffer, "%d %d" ARG_START "\n", msg, id ); #ifdef DEBUG TRACE("SendMsg %s\n",buffer); #endif //DEBUG Send( buffer ); } void IvyApplication::OnAccept(int nErrorCode) { string remotehost; UINT remoteport; // construct a new, empty socket IvyApplication *newapp = new IvyApplication(bus); // accept connection Accept( *newapp ); newapp->GetPeerName( remotehost, remoteport ); TRACE("Connexion de %s:%u\n", remotehost.c_str(), remoteport ); bus->AddApplication( newapp ); } void IvyApplication::OnClose(int nErrorCode) { string remotehost; UINT remoteport; GetPeerName( remotehost, remoteport ); TRACE("Deconnexion de %s:%u\n", remotehost.c_str(), remoteport ); if ( AppConnectedCallbackCalled ) bus->CallApplicationDisconnectedCallback( this ); // bus->RemoveApplication( this ); for ( int i = 0; i < regexp_in.size(); i++) delete regexp_in[i]; regexp_in.clear(); Close(); } int IvyApplication::SendMsg(const char *message) { int count = 0; Regexp *exp; std::map::iterator iter; /* send to already connected */ if ( !regexp_in.empty() ) for ( iter = regexp_in.begin(); iter != regexp_in.end(); iter++ ) { exp = (*iter).second; if ( exp && exp->Match( message ) ) { string buffer; for ( int i = 1; i < exp->SubStrings()+1; i++ ) { buffer += (*exp)[i]; buffer += ARG_END; } SendMsg( Msg, (*iter).first, buffer.c_str() ); count++; } } return count; } const char *IvyApplication::GetName(void) { return appname.c_str(); } BOOL IvyApplication::SameApplication(IvyApplication * app) { string host1; UINT port1; string host2; UINT port2; if ( (remoteService != 0) && (remoteService == app->remoteService) ) { GetPeerName( host1, port1 ); app->GetPeerName( host2, port2 ); TRACE( "IvyApplication::SameApplication %s:%d %s:%d\n", host1.c_str(),port1, host2.c_str(),port2); return ( host1 == host2 ); } return false; }