// IvyApplication.cpp : implementation file // #include "stdafx.h" #ifdef _DEBUG #define DEBUG_NEW new(__FILE__, __LINE__) #define new DEBUG_NEW #endif #include "IvyApplication.h" #include "Regexp.h" #define IVY_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 ( unsigned 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 IVY_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 IVY_DEBUG TRACE("Receive %s\n",line); #endif //IVY_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 IVY_DEBUG TRACE("Quitting %s\n", line); #endif //IVY_DEBUG // bus->RemoveApplication( this ); Close(); break; case Error: #ifdef IVY_DEBUG TRACE("Receive error %d %s\n", id, arg); #endif //IVY_DEBUG break; case AddRegexp: #ifdef IVY_DEBUG TRACE("Regexp id=%d exp='%s'\n", id, arg); #endif //IVY_DEBUG if ( !bus->CheckRegexp( arg ) ) { #ifdef IVY_DEBUG TRACE("Warning exp='%s' can't match removing from %s\n",arg,appname.c_str()); #endif //IVY_DEBUG return; } exp = new Regexp( arg ); if ( !exp->CompiledOK() ) { string err( "Error can't compile regexp '" ); err += arg; err += "' error "; err += exp->GetErrorString(); SendMsg( Error, Error, err.c_str() ); TRACE("IvyApplication %s\n",err.c_str()); return; } regexp_in.reserve( id +1 ); regexp_in[ id ] = exp; break; case DelRegexp: #ifdef IVY_DEBUG TRACE("Regexp Delete id=%d\n", id); #endif //IVY_DEBUG if ( regexp_in[id] ) { exp = regexp_in[ id ]; delete exp; regexp_in[ id ] = NULL; } break; case StartRegexp: #ifdef IVY_DEBUG TRACE("Regexp Start id=%d\n", id); #endif //IVY_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 IVY_DEBUG TRACE("Regexp End id=%d\n", id); #endif //IVY_DEBUG bus->CallApplicationConnectedCallback( this ); AppConnectedCallbackCalled = true; if ( !bus->ready_message.empty() ) SendMsg( bus->ready_message.c_str() ); break; case Msg: #ifdef IVY_DEBUG TRACE("Message id=%d msg='%s'\n", id, arg); #endif //IVY_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 IVY_DEBUG TRACE("Direct Message id=%d msg='%s'\n", id, arg); #endif //IVY_DEBUG bus->CallDirectMessageCallback( this, id, arg ); break; case Die: #ifdef IVY_DEBUG TRACE("Die Message id=%d msg='%s'\n", id, arg); #endif //IVY_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 IVY_DEBUG TRACE("SendMsg %s\n",buffer); #endif //IVY_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 ( unsigned 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; /* send to already connected */ for ( unsigned int i = 0; i < regexp_in.size(); i++ ) { exp = regexp_in[i]; if ( exp && exp->Match( message ) ) { string buffer; for ( int i = 1; i < exp->SubStrings()+1; i++ ) { buffer += (*exp)[i]; buffer += ARG_END; } SendMsg( Msg, i, 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; }