/* * This file is part of rasdaman community. * * Rasdaman community is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * Rasdaman community is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with rasdaman community. If not, see . * * Copyright 2003, 2004, 2005, 2006, 2007, 2008, 2009 Peter Baumann / rasdaman GmbH. * * For more information please see * or contact Peter Baumann via . */ /************************************************************* * * * PURPOSE: * * * COMMENTS: * - CLIENTID: | 0|.counter.|....timestamp ......| * |31,30.....24|23...16|15...8|7...0| * - requests count from 1..n between connect and disconnect * - fragments count from 1..n between ??? * ************************************************************/ #ifndef RMANVERSION #error "Please specify RMANVERSION variable!" #endif #ifndef COMPDATE #error "Please specify the COMPDATE variable!" /* COMPDATE=`date +"%d.%m.%Y %H:%M:%S"` and -DCOMPDATE="\"$(COMPDATE)\"" when compiling */ #endif #include "mymalloc/mymalloc.h" #include #include "rnprasserver.hh" #include "rnpservercomm.hh" #include "srvrasmgrcomm.hh" #include "server/rasserver_entry.hh" #include "debug-srv.hh" // aux function to avoid a compiler warning (see 'man strftime') size_t my_strftime(char *s, size_t max, const char *fmt, const struct tm *tm) { return strftime(s, max, fmt, tm); } // now(): aux function returning, as a static string, the current time // keep in sync with same function in rasmgr/rasmgr_localsrv.cc! const char* now() { size_t strfResult = 0; // return value of strftime() static char timestring[50]; // must hold 20+1 chars time_t t = time(NULL); // get time struct tm* tm = localtime(&t); // break down time strfResult = my_strftime( timestring, sizeof(timestring), "[%F %T]", tm ); // format time if (strfResult == 0) // bad luck? then take fallback message (void) strncpy( timestring, "[-no time available-]", sizeof(timestring) ); return( timestring ); } const int RnpRasDaManComm::NoClient = -1; RnpRasDaManComm::RnpRasDaManComm() throw() { ENTER( "RnpRasDaManComm::RnpRasDaManComm" ); requestCounter = 0; fragmentCounter = 0; clientID = NoClient; LEAVE( "RnpRasDaManComm::RnpRasDaManComm" ); } RnpRasDaManComm::~RnpRasDaManComm() throw() { TALK( "RnpRasDaManComm::~RnpRasDaManComm" ); } // we need our implementation because of r_Error, but we will go for the default when r_Error is AkgException void RnpRasDaManComm::processRequest(CommBuffer *receiverBuffer, CommBuffer *transmiterBuffer, RnpTransport::CarrierProtocol protocol, RnpServerJob *callingJob) throw() { RMTimer requestTime("RnpRasDaManComm","request"); ENTER( "RnpRasDaManComm::processRequest, at " << now() << ", client=" << callingJob->getClientHostAddress().getStringAddress() ); RMInit::logOut << endl << now() << " request from " << callingJob->getClientHostAddress().getStringAddress() << endl; decoder.decode(receiverBuffer); RnpQuark destServerType = decoder.getDestinationServerType(); Rnp::Endianness desEndianness = decoder.getDesiredEndianness(); // test if servertype matches! transmiterBuffer->allocate(getTransmitterBufferSize()); transmiterBuffer->clearToWrite(); encoder.setBuffer(transmiterBuffer); encoder.setFinalEndianness(desEndianness); encoder.startAnswer(destServerType, protocol); requestCounter++; decoder.getFirstFragment(); bool wasError = false; for(int fragment=0; fragment < decoder.countFragments(); fragment++) { if(wasError == false) { try { decodeFragment(); } // DBMS connection lost? then need to disconnect client to allow to resync catch(r_Ebase_dbms &edb) { RMInit::logOut << "Error: base DBMS reports: " << edb.what() << endl; wasError = true; answerr_Error(edb); #if 0 // seems too hard -- PB 2005-jul-25 try { RMInit::logOut << "detaching client..." ; executeDisconnect(); RMInit::logOut << "ok" << endl; } catch (...) // ignore any further error, just log it { RMInit::logOut << "failed" << endl; } #endif // 0 } catch(r_Error &ex) { RMInit::logOut << "Error: request terminated: " << ex.what() << endl; TALK( "rasdaman exception kind=" << ex.get_kind() << ", errorno=" << ex.get_errorno() ); wasError = true; answerr_Error(ex); #if 0 // seems too hard -- PB 2005-jul-25 // a base DBMS error we treat just like above // -- PB 2003-nov-24 if (ex.get_kind() == r_Error::r_Error_BaseDBMSFailed || ex.get_errorno() == 206) // serializable error, see errtxts { try { RMInit::logOut << "detaching client..."; executeDisconnect(); RMInit::logOut << "ok" << endl; } catch (...) // ignore any further error, just log it { RMInit::logOut << "failed" << endl; } } #endif // 0 } catch(exception &ex) { RMInit::logOut << "Error: request terminated with general exception: " << ex.what() << endl; wasError = true; answerSTLException(ex); } catch(...) { RMInit::logOut << "Error: request terminated with generic exception." << endl; wasError = true; answerUnknownError(); } } else { discardFragment(); } decoder.getNextFragment(); } encoder.endMessage(); RMInit::logOut << now() << " request completed in " << requestTime.getTime() << " usecs." << endl; LEAVE( "RnpRasDaManComm::processRequest" ); } RnpServerJob* RnpRasDaManComm::createJobs(int howMany) { TALK( "RNP: creating "<getCommandName( command ) ); // first parameter has to be the clientID verifyClientID( command ); switch(command) { case RnpRasserver::cmd_connect: executeConnect(); break; case RnpRasserver::cmd_disconnect: executeDisconnect(); break; case RnpRasserver::cmd_opendb: executeOpenDB(); break; case RnpRasserver::cmd_closedb: executeCloseDB(); break; case RnpRasserver::cmd_beginta: executeBeginTA(); break; case RnpRasserver::cmd_committa: executeCommitTA(); break; case RnpRasserver::cmd_abortta: executeAbortTA(); break; case RnpRasserver::cmd_istaopen: executeIsTAOpen(); break; case RnpRasserver::cmd_queryhttp: executeQueryHttp(); break; case RnpRasserver::cmd_getnewoid: executeGetNewOId(); break; case RnpRasserver::cmd_queryrpc: executeQueryRpc(); break; case RnpRasserver::cmd_getnextelem: executeGetNextElement(); break; case RnpRasserver::cmd_endtransfer: executeEndTransfer(); break; case RnpRasserver::cmd_getnextmdd: executeGetNextMDD(); break; case RnpRasserver::cmd_getnexttile: executeGetNextTile(); break; case RnpRasserver::cmd_updaterpc : executeUpdateQuery(); break; case RnpRasserver::cmd_startinsTmdd: executeStartInsertTransMDD(); break; case RnpRasserver::cmd_inserttile : executeInsertTile(); break; case RnpRasserver::cmd_endinsmdd : executeEndInsertMDD(); break; case RnpRasserver::cmd_initupdate : executeInitUpdate(); break; case RnpRasserver::cmd_gettypestruct: executeGetTypeStructure(); break; case RnpRasserver::cmd_startinsPmdd: executeStartInsertPersMDD(); break; case RnpRasserver::cmd_insertmdd: executeInsertMDD(); break; case RnpRasserver::cmd_insertcoll: executeInsertCollection(); break; case RnpRasserver::cmd_remobjfromcoll: executeRemoveObjFromColl(); break; case RnpRasserver::cmd_delobjbyoid: executeDeleteObjByOId(); break; case RnpRasserver::cmd_delcollbyname: executeDeleteCollByName(); break; case RnpRasserver::cmd_getcoll: executeGetCollection(); break; case RnpRasserver::cmd_getcolloids: executeGetCollectionOIds(); break; case RnpRasserver::cmd_getobjecttype: executeGetObjectType(); break; case RnpRasserver::cmd_setformat: executeSetFormat(); break; // --- until here the compatible ones --- // -- the secret, unofficial ones -- case RnpRasserver::cmd_createcollection: executeCreateCollection(); break; case RnpRasserver::cmd_createmdd: executeCreateMDD(); break; case RnpRasserver::cmd_extendmdd: executeExtendMDD(); break; case RnpRasserver::cmd_gettiledomains: executeGetTileDomains(); break; default: RMInit::logOut << "Protocol error: Unknown command: " << command << endl; LEAVE( "RnpRasDaManComm::decodeFragment: Unknown command: "< 1 || requestCounter > 1) // any previous un-disconnected activity? { RMInit::logOut << "Preparing request for new connect by resetting old connection; "; RnpRasDaManComm::disconnectInternally(); // FIXME: the entry in CltTable still remains (see compat_*()) // - although this doesn't harm in any way it should be removed } rasserver.compat_connectNewClient(capability); connectClient(); encoder.startFragment(Rnp::fgt_OkAnswer, decoder.getCommand()); encoder.addInt32Parameter(RnpRasserver::pmt_clientid, clientID); encoder.endFragment(); TALK( "adding clientID 0x" << hex << clientID << dec ); LEAVE( "RnpRasDaManComm::executeConnect, assigned clientID=0x"<domain); encoder.addInt32Parameter( RnpRasserver::pmt_typelength, tempRpcMarray->cellTypeLength); encoder.addInt32Parameter( RnpRasserver::pmt_currentformat, tempRpcMarray->currentFormat); encoder.addInt32Parameter( RnpRasserver::pmt_storageformat, tempRpcMarray->storageFormat); encoder.adjustBufferSize(tempRpcMarray->data.confarray_len); encoder.addOpaqueParameter(RnpRasserver::pmt_tiledata, tempRpcMarray->data.confarray_val, tempRpcMarray->data.confarray_len); // Do not free this! "tempRpcMarray->data.confarray_val"; free(tempRpcMarray->domain); free(tempRpcMarray); } encoder.endFragment(); /* Notez aici ca n-am unde: e adevarat ca tilele trebuie transferate si pe bucati, fiindca un tiff mare creat cu select e o tila! */ LEAVE("executeGetNextTile - out"); } //---------- void RnpRasDaManComm::executeUpdateQuery() { ENTER("executeUpdateQuery - in"); RasServerEntry& rasserver = RasServerEntry::getInstance(); decoder.getNextParameter(); const char* query = decoder.getDataAsString(); ExecuteUpdateRes returnStructure; returnStructure.token = NULL; int status = rasserver.compat_ExecuteUpdateQuery(query, returnStructure); const char *token = returnStructure.token != NULL ? returnStructure.token : ""; encoder.startFragment(Rnp::fgt_OkAnswer, decoder.getCommand()); encoder.addInt32Parameter( RnpRasserver::pmt_returnstatus, status); TALK( "adding return status " << status ); encoder.addInt32Parameter( RnpRasserver::pmt_errorno, returnStructure.errorNo); encoder.addInt32Parameter( RnpRasserver::pmt_lineno, returnStructure.lineNo); encoder.addInt32Parameter( RnpRasserver::pmt_columnno, returnStructure.columnNo); encoder.addStringParameter(RnpRasserver::pmt_errortoken, token ); encoder.endFragment(); if(returnStructure.token) free(returnStructure.token); LEAVE("executeUpdateQuery - out"); } void RnpRasDaManComm::executeInitUpdate() { ENTER("executeInitUpdate - in"); RasServerEntry& rasserver = RasServerEntry::getInstance(); int status = rasserver.compat_InitUpdate(); encoder.startFragment(Rnp::fgt_OkAnswer, decoder.getCommand()); encoder.addInt32Parameter(RnpRasserver::pmt_returnstatus, status); TALK( "adding return status " << status ); encoder.endFragment(); LEAVE("executeInitUpdate - out"); } void RnpRasDaManComm::executeStartInsertTransMDD() { ENTER("executeStartInsertTransMDD - in"); RasServerEntry& rasserver = RasServerEntry::getInstance(); decoder.getNextParameter(); const char* domain = decoder.getDataAsString(); decoder.getNextParameter(); int typeLength = decoder.getDataAsInteger(); decoder.getNextParameter(); const char* typeName = decoder.getDataAsString(); int status = rasserver.compat_StartInsertTransMDD(domain, typeLength, typeName); encoder.startFragment(Rnp::fgt_OkAnswer, decoder.getCommand()); encoder.addInt32Parameter(RnpRasserver::pmt_returnstatus, status); TALK( "adding return status " << status ); encoder.endFragment(); LEAVE("executeStartInsertTransMDD - out"); } void RnpRasDaManComm::executeInsertTile() { ENTER("executeInsertTile - in"); RasServerEntry& rasserver = RasServerEntry::getInstance(); RPCMarray *rpcMarray = new RPCMarray; decoder.getNextParameter(); int persistent = decoder.getDataAsInteger(); decoder.getNextParameter(); rpcMarray->domain = (char*)decoder.getDataAsString(); decoder.getNextParameter(); rpcMarray->cellTypeLength = decoder.getDataAsInteger(); decoder.getNextParameter(); rpcMarray->currentFormat = decoder.getDataAsInteger(); decoder.getNextParameter(); rpcMarray->storageFormat = decoder.getDataAsInteger(); decoder.getNextParameter(); const void* buffer = decoder.getData(); int length = decoder.getDataLength(); rpcMarray->data.confarray_val = (char*)mymalloc(length); memcpy(rpcMarray->data.confarray_val, buffer, length); rpcMarray->data.confarray_len = length; int status = rasserver.compat_InsertTile(persistent, rpcMarray); encoder.startFragment(Rnp::fgt_OkAnswer, decoder.getCommand()); encoder.addInt32Parameter(RnpRasserver::pmt_returnstatus, status); TALK( "adding return status " << status ); encoder.endFragment(); // rpcMarray->data.confarray_val is freed by Tile::Tile(...), which is stupid, but... delete rpcMarray; LEAVE("executeInsertTile - out"); } void RnpRasDaManComm::executeEndInsertMDD() { ENTER("executeEndInsertMDD - in"); RasServerEntry& rasserver = RasServerEntry::getInstance(); decoder.getNextParameter(); int persistent = decoder.getDataAsInteger(); int status = rasserver.compat_EndInsertMDD(persistent); encoder.startFragment(Rnp::fgt_OkAnswer, decoder.getCommand()); encoder.addInt32Parameter(RnpRasserver::pmt_returnstatus, status); TALK( "adding return status " << status ); encoder.endFragment(); LEAVE("executeEndInsertMDD - out"); } void RnpRasDaManComm::executeGetTypeStructure() { ENTER("executeGetTypeStructure - in"); RasServerEntry& rasserver = RasServerEntry::getInstance(); decoder.getNextParameter(); const char *typeName = decoder.getDataAsString(); decoder.getNextParameter(); int typeType = decoder.getDataAsInteger(); char *typeStructure=NULL; int status = rasserver.compat_GetTypeStructure(typeName, typeType, typeStructure); encoder.startFragment(Rnp::fgt_OkAnswer, decoder.getCommand()); encoder.addInt32Parameter(RnpRasserver::pmt_returnstatus, status); TALK( "adding return status " << status ); encoder.addStringParameter(RnpRasserver::pmt_typestructure, typeStructure ? typeStructure : ""); encoder.endFragment(); if(typeStructure) { free(typeStructure); } LEAVE("executeGetTypeStructure - out"); } void RnpRasDaManComm::executeStartInsertPersMDD() { ENTER("executeStartInsertPersMDD - in"); RasServerEntry& rasserver = RasServerEntry::getInstance(); decoder.getNextParameter(); const char* collName = decoder.getDataAsString(); decoder.getNextParameter(); r_Minterval mddDomain( decoder.getDataAsString() ); decoder.getNextParameter(); int typeLength = decoder.getDataAsInteger(); decoder.getNextParameter(); const char* typeName = decoder.getDataAsString(); decoder.getNextParameter(); r_OId oid( decoder.getDataAsString() ); int status = rasserver.compat_StartInsertPersMDD(collName, mddDomain, typeLength, typeName, oid); encoder.startFragment(Rnp::fgt_OkAnswer, decoder.getCommand()); encoder.addInt32Parameter(RnpRasserver::pmt_returnstatus, status); TALK( "adding return status " << status ); encoder.endFragment(); LEAVE("executeStartInsertPersMDD - out"); } void RnpRasDaManComm::executeInsertMDD() { ENTER("executeInsertMDD - in"); RasServerEntry& rasserver = RasServerEntry::getInstance(); decoder.getNextParameter(); const char* collName = decoder.getDataAsString(); decoder.getNextParameter(); const char* typeName = decoder.getDataAsString(); decoder.getNextParameter(); r_OId oid( decoder.getDataAsString() ); RPCMarray *rpcMarray = new RPCMarray; decoder.getNextParameter(); rpcMarray->domain = (char*)decoder.getDataAsString(); decoder.getNextParameter(); rpcMarray->cellTypeLength = decoder.getDataAsInteger(); decoder.getNextParameter(); rpcMarray->currentFormat = decoder.getDataAsInteger(); decoder.getNextParameter(); rpcMarray->storageFormat = decoder.getDataAsInteger(); decoder.getNextParameter(); const void* buffer = decoder.getData(); int length = decoder.getDataLength(); rpcMarray->data.confarray_val = (char*)mymalloc(length); memcpy(rpcMarray->data.confarray_val, buffer, length); rpcMarray->data.confarray_len = length; int status = rasserver.compat_InsertMDD(collName, rpcMarray, typeName, oid); encoder.startFragment(Rnp::fgt_OkAnswer, decoder.getCommand()); encoder.addInt32Parameter(RnpRasserver::pmt_returnstatus, status); TALK( "adding return status " << status ); encoder.endFragment(); LEAVE("executeInsertMDD - out"); } void RnpRasDaManComm::executeInsertCollection() { ENTER("executeInsertCollection - in"); RasServerEntry& rasserver = RasServerEntry::getInstance(); decoder.getNextParameter(); const char* collName = decoder.getDataAsString(); decoder.getNextParameter(); const char* typeName = decoder.getDataAsString(); decoder.getNextParameter(); r_OId oid( decoder.getDataAsString() ); int status = rasserver.compat_InsertCollection(collName, typeName, oid); encoder.startFragment(Rnp::fgt_OkAnswer, decoder.getCommand()); encoder.addInt32Parameter(RnpRasserver::pmt_returnstatus, status); TALK( "adding return status " << status ); encoder.endFragment(); LEAVE("executeInsertCollection - out"); } void RnpRasDaManComm::executeDeleteCollByName() { ENTER("executeDeleteCollByName - in"); RasServerEntry& rasserver = RasServerEntry::getInstance(); decoder.getNextParameter(); const char* collName = decoder.getDataAsString(); int status = rasserver.compat_DeleteCollByName(collName); encoder.startFragment(Rnp::fgt_OkAnswer, decoder.getCommand()); encoder.addInt32Parameter(RnpRasserver::pmt_returnstatus, status); TALK( "adding return status " << status ); encoder.endFragment(); LEAVE("executeDeleteCollByName - out"); } void RnpRasDaManComm::executeDeleteObjByOId() { ENTER("executeDeleteObjByOId - in"); RasServerEntry& rasserver = RasServerEntry::getInstance(); decoder.getNextParameter(); r_OId oid( decoder.getDataAsString() ); int status = rasserver.compat_DeleteObjByOId(oid); encoder.startFragment(Rnp::fgt_OkAnswer, decoder.getCommand()); encoder.addInt32Parameter(RnpRasserver::pmt_returnstatus, status); TALK( "adding return status " << status ); encoder.endFragment(); LEAVE("executeDeleteObjByOId - out"); } void RnpRasDaManComm::executeRemoveObjFromColl() { ENTER("executeRemoveObjFromColl - in"); RasServerEntry& rasserver = RasServerEntry::getInstance(); decoder.getNextParameter(); const char* collName = decoder.getDataAsString(); decoder.getNextParameter(); r_OId oid( decoder.getDataAsString() ); int status = rasserver.compat_RemoveObjFromColl(collName, oid); encoder.startFragment(Rnp::fgt_OkAnswer, decoder.getCommand()); encoder.addInt32Parameter(RnpRasserver::pmt_returnstatus, status); TALK( "adding return status " << status ); encoder.endFragment(); LEAVE("executeRemoveObjFromColl - out"); } void RnpRasDaManComm::executeGetCollection() { ENTER("executeGetCollection - in"); RasServerEntry& rasserver = RasServerEntry::getInstance(); char* typeName = NULL; char* typeStructure = NULL; char* collName = NULL; r_OId oid; int status = 0; decoder.getNextParameter(); if(decoder.getParameterType() == RnpRasserver::pmt_collname) { collName = strdup(decoder.getDataAsString()); status = rasserver.compat_GetCollectionByName(collName, typeName, typeStructure, oid); } else { const char* oidstring = decoder.getDataAsString(); oid = r_OId(oidstring); status = rasserver.compat_GetCollectionByName(oid, typeName, typeStructure, collName); } encoder.startFragment(Rnp::fgt_OkAnswer, decoder.getCommand()); encoder.addInt32Parameter(RnpRasserver::pmt_returnstatus, status); TALK( "adding return status " << status ); encoder.addStringParameter(RnpRasserver::pmt_typename, typeName); encoder.addStringParameter(RnpRasserver::pmt_typestructure, typeStructure); encoder.addStringParameter(RnpRasserver::pmt_oidstring, oid.get_string_representation()); encoder.addStringParameter(RnpRasserver::pmt_collname, collName); encoder.endFragment(); free((void*)typeName); free((void*)typeStructure); free((void*)collName); LEAVE("executeGetCollection - out"); } void RnpRasDaManComm::executeGetCollectionOIds() { ENTER("executeGetCollectionOIds - in"); RasServerEntry& rasserver = RasServerEntry::getInstance(); char* typeName = NULL; char* typeStructure = NULL; char* collName = NULL; r_OId oid; RPCOIdEntry* oidTable = NULL; unsigned int oidTableSize = 0; int status = 0; decoder.getNextParameter(); if(decoder.getParameterType() == RnpRasserver::pmt_collname) { collName = strdup(decoder.getDataAsString()); status = rasserver.compat_GetCollectionOidsByName(collName, typeName, typeStructure, oid, oidTable, oidTableSize); } else { oid = r_OId(decoder.getDataAsString()); status = rasserver.compat_GetCollectionOidsByOId(oid, typeName, typeStructure, oidTable, oidTableSize, collName); } encoder.startFragment(Rnp::fgt_OkAnswer, decoder.getCommand()); encoder.addInt32Parameter(RnpRasserver::pmt_returnstatus, status); TALK( "adding return status " << status ); encoder.addStringParameter(RnpRasserver::pmt_typename, typeName); encoder.addStringParameter(RnpRasserver::pmt_typestructure, typeStructure); encoder.addStringParameter(RnpRasserver::pmt_oidstring, oid.get_string_representation()); encoder.addStringParameter(RnpRasserver::pmt_collname, collName); if(oidTable) for(int i=0;i result = rasserver.getTileDomains(mddOId, stripeDomain); encoder.startFragment(Rnp::fgt_OkAnswer, decoder.getCommand()); for(int i=0;i < result.size(); i++) { const char *domain = result[i].get_string_representation(); encoder.addStringParameter(RnpRasserver::pmt_domain, domain); free((void*)domain); } encoder.endFragment(); LEAVE( "RnpRasDaManComm::executeGetTileDomains" ); } //######### helper functions ########################### void RnpRasDaManComm::connectClient() { clientID = makeNewClientID(); TALK( "RnpRasDaManComm::connectClient(): assigned new client id 0x" << hex << clientID << dec ); } void RnpRasDaManComm::disconnectInternally() { clientID = NoClient; requestCounter = 1; // because pre-increment before request processing will not be reached when this is called fragmentCounter = 1; // same phenomenon, different reason: verify needs this counter for OK'ing connect } void RnpRasDaManComm::disconnectClient() { clientID = NoClient; requestCounter = 0; fragmentCounter = 0; rasmgrComm.informRasmgrServerAvailable(); } void RnpRasDaManComm::verifyClientID( RnpQuark command ) throw (r_Error) { ENTER( "RnpRasDaManComm::verifyClientID( command=" << command << " ), fragmentCounter=" << fragmentCounter << ", requestCounter=" << requestCounter ); decoder.getFirstParameter(); if(decoder.getParameterType() != RnpRasserver::pmt_clientid) { RMInit::logOut << "Error: unidentified client." << endl; LEAVE( "RnpRasDaManComm::verifyClientID() - exception, unknown client id." ); throw r_Error(820); // sorry, I know, symbolic constants } int verClientID = decoder.getDataAsInteger(); TALK( "RnpRasDaManComm::verifyClientID: clientID 0x" << hex << clientID << dec << ", verClientID 0x" << hex << verClientID << dec ); // it's our client, it's OK if(clientID == verClientID) { LEAVE( "RnpRasDaManComm::verifyClientID() - it's our client, it's OK" ); return; } // connect cmd is OK too if(command == RnpRasserver::cmd_connect) { LEAVE( "RnpRasDaManComm::verifyClientID() - connect requested, OK" ); return; } // new client, first request, it's probably connect, so OK if(clientID == NoClient && fragmentCounter == 1) { LEAVE( "RnpRasDaManComm::verifyClientID() - new client, first request, it's probably connect, so OK" ); return; } // new client, same message, a new request, it's also OK (he is allowed to put more fragments in a request!) if(clientID != NoClient && fragmentCounter > 1 && requestCounter == 1 && verClientID == 0) { LEAVE( "RnpRasDaManComm::verifyClientID() - new client, same message, a new request (multi-fragment), so OK" ); return; } RMInit::logOut << "Error: unregistered client." << endl; LEAVE("RnpRasDaManComm::verifyClientID(): stored clientID is 0x" << hex << clientID << dec << ", but client identified as 0x" << hex << verClientID << dec << ", fragmentCounter=" << fragmentCounter << ", requestCounter=" << requestCounter); throw r_Error(821); // invalid sequence number } int RnpRasDaManComm::makeNewClientID() { // CLIENTID: | 0|.counter.|....timestamp ......| // |31,30.....24|23...16|15...8|7...0| static int counter = 0; int timeNow = time(NULL); int result = (timeNow & 0xFFFFFF) + (counter << 24); counter = (counter+1) & 0x7F; TALK( "RnpRasDaManComm::makeNewClientID() -> 0x" << hex << result << " (counter now: " << counter << ")" ); return result; } void RnpRasDaManComm::answerr_Error(r_Error &err) { const char *errText = err.serialiseError(); RMInit::logOut << "Error in response: (" << errText << ") " << err.what() << endl; encoder.startFragment(Rnp::fgt_Error, decoder.getCommand()); encoder.addInt32Parameter(Rnp::ert_Other, 0); encoder.addStringParameter(RnpRasserver::pmt_rErrorString, errText); // add descriptive text -- PB 2003-nov-24 encoder.addStringParameter(RnpRasserver::pmt_rErrorString, err.what() ); encoder.endFragment(); delete[] errText; } //###################################################### RnpRasserverJob::RnpRasserverJob() throw() { TALK( "RNP: RnpRasserverJob created" ); } bool RnpRasserverJob::validateMessage() throw() { TALK( "RNP: validateMessage()" ); return RnpServerJob::validateMessage(); } void RnpRasserverJob::executeOnAccept() throw() { TALK( "RNP: executeOnAccept()" ); RnpServerJob::executeOnAccept(); } void RnpRasserverJob::executeOnWriteReady() throw() { TALK( "RNP: executeOnWriteReady()" ); RnpServerJob::executeOnWriteReady(); } void RnpRasserverJob::specificCleanUpOnTimeout() throw() { TALK( "RNP: specificCleanUpOnTimeout()" ); RnpServerJob::specificCleanUpOnTimeout(); } void RnpRasserverJob::executeOnReadError() throw() { RMInit::logOut << "Error while executing read operation." << endl; RnpServerJob::executeOnReadError(); } void RnpRasserverJob::executeOnWriteError() throw() { RMInit::logOut << "Error while executing write operation." << endl; RnpServerJob::executeOnWriteError(); } //######################################################### RasserverCommunicator::RasserverCommunicator(RnpRasDaManComm* cmm) throw() { commPtr = cmm; } bool RasserverCommunicator::executeOnTimeout() throw() { TALK( "RasserverCommunicator::executeOnTimeout()" ); commPtr->checkForTimeout(); return true; } //######################################################### ClientTimer::ClientTimer() { interval = 0; lastAction = 0; enabled = false; } void ClientTimer::setTimeoutInterval(int seconds) { interval = seconds; enabled = true; markAction(); } void ClientTimer::markAction() { lastAction = time(NULL); } bool ClientTimer::checkForTimeout() { if(enabled == false) return false; time_t now = time(NULL); return now >= lastAction + interval; }