/// =-=-=-=-=-=-=- /// @brief function which sends the negotiation message error send_client_server_negotiation_message( irods::network_object_ptr _ptr, cs_neg_t& _cs_neg_msg ) { // =-=-=-=-=-=-=- // pack the negotiation message bytesBuf_t* cs_neg_buf = 0; int status = packStruct( &_cs_neg_msg, &cs_neg_buf, "CS_NEG_PI", RodsPackTable, 0, XML_PROT ); if ( status < 0 ) { return ERROR( status, "failed to pack client-server message" ); } // =-=-=-=-=-=-=- // pack the negotiation message irods::error ret = sendRodsMsg( _ptr, RODS_CS_NEG_T, cs_neg_buf, 0, 0, 0, XML_PROT ); freeBBuf( cs_neg_buf ); if ( !ret.ok() ) { return PASSMSG( "failed to send client-server negotiation message", ret ); } return SUCCESS(); } // send_client_server_negotiation_message
irods::error sendVersion( irods::network_object_ptr _ptr, int versionStatus, int reconnPort, char* reconnAddr, int cookie ) { version_t myVersion; int status; bytesBuf_t *versionBBuf = NULL; /* setup the version struct */ memset( &myVersion, 0, sizeof( myVersion ) ); myVersion.status = versionStatus; rstrcpy( myVersion.relVersion, RODS_REL_VERSION, NAME_LEN ); rstrcpy( myVersion.apiVersion, RODS_API_VERSION, NAME_LEN ); if ( reconnAddr != NULL ) { myVersion.reconnPort = reconnPort; rstrcpy( myVersion.reconnAddr, reconnAddr, LONG_NAME_LEN ); myVersion.cookie = cookie; } else { // =-=-=-=-=-=-=- // super secret jargon irods detection // sshhhhhhh... myVersion.cookie = 400; } /* alway use XML for version */ status = packStruct( ( char * ) &myVersion, &versionBBuf, "Version_PI", RodsPackTable, 0, XML_PROT ); if ( status < 0 ) { return ERROR( status, "packStruct error" ); } irods::error ret = sendRodsMsg( _ptr, RODS_VERSION_T, versionBBuf, NULL, NULL, 0, XML_PROT ); freeBBuf( versionBBuf ); if ( !ret.ok() ) { return PASS( ret ); } return SUCCESS(); } // sendVersion
// =-=-=-=-=-=-=- // interface for requesting a reconnection irods::error sendReconnMsg( irods::network_object_ptr _ptr, reconnMsg_t* _msg ) { // =-=-=-=-=-=-=- // trap invalid param if ( _msg == NULL ) { return ERROR( USER__NULL_INPUT_ERR, "null msg buf" ); } // =-=-=-=-=-=-=- // pack outgoing message - alway use XML for version bytesBuf_t* recon_buf = NULL; int status = packStruct( static_cast<void*>( _msg ), &recon_buf, "ReconnMsg_PI", RodsPackTable, 0, XML_PROT ); if ( status < 0 ) { return ERROR( status, "failed to pack struct" ); } // =-=-=-=-=-=-=- // pack outgoing message - alway use XML for version irods::error ret = sendRodsMsg( _ptr, RODS_RECONNECT_T, recon_buf, NULL, NULL, 0, XML_PROT ); freeBBuf( recon_buf ); if ( !ret.ok() ) { rodsLogError( LOG_ERROR, status, "sendReconnMsg: sendRodsMsg of reconnect msg failed, status = %d", status ); } return CODE( status ); } // sendReconnMsg
int rsApiHandler( rsComm_t* rsComm, int apiNumber, bytesBuf_t* inputStructBBuf, bytesBuf_t* bsBBuf ) { int apiInx; int status = 0; char *myInStruct = NULL; funcPtr myHandler = NULL; void *myOutStruct = NULL; bytesBuf_t myOutBsBBuf; int retVal = 0; int numArg = 0; void *myArgv[4]; memset( &myOutBsBBuf, 0, sizeof( bytesBuf_t ) ); memset( &rsComm->rError, 0, sizeof( rError_t ) ); apiInx = apiTableLookup( apiNumber ); // =-=-=-=-=-=-=- // create a network object irods::network_object_ptr net_obj; irods::error ret = irods::network_factory( rsComm, net_obj ); if ( !ret.ok() ) { irods::log( PASS( ret ) ); return apiInx; } if ( apiInx < 0 ) { rodsLog( LOG_ERROR, "rsApiHandler: apiTableLookup of apiNumber %d failed", apiNumber ); /* cannot use sendApiReply because it does not know apiInx */ sendRodsMsg( net_obj, RODS_API_REPLY_T, NULL, NULL, NULL, apiInx, rsComm->irodsProt ); return apiInx; } rsComm->apiInx = apiInx; status = chkApiVersion( apiInx ); if ( status < 0 ) { sendApiReply( rsComm, apiInx, status, myOutStruct, &myOutBsBBuf ); return status; } status = chkApiPermission( rsComm, apiInx ); if ( status < 0 ) { rodsLog( LOG_NOTICE, "rsApiHandler: User has no permission for apiNumber %d", apiNumber ); sendApiReply( rsComm, apiInx, status, myOutStruct, &myOutBsBBuf ); return status; } irods::api_entry_table& RsApiTable = irods::get_server_api_table(); /* some sanity check */ if ( inputStructBBuf->len > 0 && RsApiTable[apiInx]->inPackInstruct == NULL ) { rodsLog( LOG_NOTICE, "rsApiHandler: input struct error 1 for apiNumber %d", apiNumber ); sendApiReply( rsComm, apiInx, SYS_API_INPUT_ERR, myOutStruct, &myOutBsBBuf ); return SYS_API_INPUT_ERR; } if ( inputStructBBuf->len <= 0 && RsApiTable[apiInx]->inPackInstruct != NULL ) { rodsLog( LOG_NOTICE, "rsApiHandler: input struct error 2 for apiNumber %d", apiNumber ); sendApiReply( rsComm, apiInx, SYS_API_INPUT_ERR, myOutStruct, &myOutBsBBuf ); return SYS_API_INPUT_ERR; } if ( bsBBuf->len > 0 && RsApiTable[apiInx]->inBsFlag <= 0 ) { rodsLog( LOG_NOTICE, "rsApiHandler: input byte stream error for apiNumber %d", apiNumber ); sendApiReply( rsComm, apiInx, SYS_API_INPUT_ERR, myOutStruct, &myOutBsBBuf ); return SYS_API_INPUT_ERR; } if ( inputStructBBuf->len > 0 ) { status = unpackStruct( inputStructBBuf->buf, ( void ** )( static_cast< void * >( &myInStruct ) ), ( char* )RsApiTable[apiInx]->inPackInstruct, RodsPackTable, rsComm->irodsProt ); if ( status < 0 ) { rodsLog( LOG_NOTICE, "rsApiHandler: unpackStruct error for apiNumber %d, status = %d", apiNumber, status ); sendApiReply( rsComm, apiInx, status, myOutStruct, &myOutBsBBuf ); return status; } } /* ready to call the handler functions */ myHandler = RsApiTable[apiInx]->svrHandler; if ( !myHandler ) { rodsLog( LOG_ERROR, "Null handler encountered for api number %d in rsApiHandler.", apiNumber ); return SYS_API_INPUT_ERR; } if ( RsApiTable[apiInx]->inPackInstruct != NULL ) { myArgv[numArg] = myInStruct; numArg++; }; if ( RsApiTable[apiInx]->inBsFlag != 0 ) { myArgv[numArg] = bsBBuf; numArg++; }; if ( RsApiTable[apiInx]->outPackInstruct != NULL ) { myArgv[numArg] = ( void * ) &myOutStruct; numArg++; }; if ( RsApiTable[apiInx]->outBsFlag != 0 ) { myArgv[numArg] = ( void * ) &myOutBsBBuf; numArg++; }; if ( numArg == 0 ) { retVal = ( *myHandler )( rsComm ); } else if ( numArg == 1 ) { retVal = ( *myHandler )( rsComm, myArgv[0] ); } else if ( numArg == 2 ) { retVal = ( *myHandler )( rsComm, myArgv[0], myArgv[1] ); } else if ( numArg == 3 ) { retVal = ( *myHandler )( rsComm, myArgv[0], myArgv[1], myArgv[2] ); } else if ( numArg == 4 ) { retVal = ( *myHandler )( rsComm, myArgv[0], myArgv[1], myArgv[2], myArgv[3] ); } if ( retVal != SYS_NO_HANDLER_REPLY_MSG ) { status = sendAndProcApiReply ( rsComm, apiInx, retVal, myOutStruct, &myOutBsBBuf ); } // =-=-=-=-=-=-=- // clear the incoming packing instruction if ( myInStruct != NULL ) { if ( RsApiTable[apiInx]->clearInStruct ) { RsApiTable[apiInx]->clearInStruct( myInStruct ); } free( myInStruct ); myInStruct = NULL; } if ( retVal >= 0 && status < 0 ) { return status; } else { return retVal; } }
int sendApiReply( rsComm_t * rsComm, int apiInx, int retVal, void * myOutStruct, bytesBuf_t * myOutBsBBuf ) { int status = 0; bytesBuf_t *outStructBBuf = NULL; bytesBuf_t *myOutStructBBuf; bytesBuf_t *rErrorBBuf = NULL; bytesBuf_t *myRErrorBBuf; //#ifndef windows_platform svrChkReconnAtSendStart( rsComm ); //#endif if ( retVal == SYS_HANDLER_DONE_NO_ERROR ) { /* not actually an error */ retVal = 0; } // =-=-=-=-=-=-=- // create a network object irods::network_object_ptr net_obj; irods::error ret = irods::network_factory( rsComm, net_obj ); if ( !ret.ok() ) { irods::log( PASS( ret ) ); return ret.code(); } irods::api_entry_table& RsApiTable = irods::get_server_api_table(); if ( RsApiTable[apiInx]->outPackInstruct != NULL && myOutStruct != NULL ) { status = packStruct( ( char * ) myOutStruct, &outStructBBuf, ( char* )RsApiTable[apiInx]->outPackInstruct, RodsPackTable, FREE_POINTER, rsComm->irodsProt ); if ( status < 0 ) { rodsLog( LOG_NOTICE, "sendApiReply: packStruct error, status = %d", status ); sendRodsMsg( net_obj, RODS_API_REPLY_T, NULL, NULL, NULL, status, rsComm->irodsProt ); svrChkReconnAtSendEnd( rsComm ); return status; } myOutStructBBuf = outStructBBuf; } else { myOutStructBBuf = NULL; } if ( RsApiTable[apiInx]->outBsFlag == 0 ) { myOutBsBBuf = NULL; } if ( rsComm->rError.len > 0 ) { status = packStruct( ( char * ) &rsComm->rError, &rErrorBBuf, "RError_PI", RodsPackTable, 0, rsComm->irodsProt ); if ( status < 0 ) { rodsLog( LOG_NOTICE, "sendApiReply: packStruct error, status = %d", status ); sendRodsMsg( net_obj, RODS_API_REPLY_T, NULL, NULL, NULL, status, rsComm->irodsProt ); svrChkReconnAtSendEnd( rsComm ); freeBBuf( outStructBBuf ); freeBBuf( rErrorBBuf ); return status; } myRErrorBBuf = rErrorBBuf; } else { myRErrorBBuf = NULL; } ret = sendRodsMsg( net_obj, RODS_API_REPLY_T, myOutStructBBuf, myOutBsBBuf, myRErrorBBuf, retVal, rsComm->irodsProt ); if ( !ret.ok() ) { int status1; irods::log( PASS( ret ) ); if ( rsComm->reconnSock > 0 ) { int savedStatus = ret.code(); boost::unique_lock< boost::mutex > boost_lock( *rsComm->thread_ctx->lock ); rodsLog( LOG_DEBUG, "sendApiReply: svrSwitchConnect. cliState = %d,agState=%d", rsComm->clientState, rsComm->agentState ); status1 = svrSwitchConnect( rsComm ); boost_lock.unlock(); if ( status1 > 0 ) { /* should not be here */ rodsLog( LOG_NOTICE, "sendApiReply: Switch connection and retry sendRodsMsg" ); ret = sendRodsMsg( net_obj, RODS_API_REPLY_T, myOutStructBBuf, myOutBsBBuf, myRErrorBBuf, retVal, rsComm->irodsProt ); if ( ret.code() >= 0 ) { rodsLog( LOG_NOTICE, "sendApiReply: retry sendRodsMsg succeeded" ); } else { status = savedStatus; } } } } svrChkReconnAtSendEnd( rsComm ); freeBBuf( outStructBBuf ); freeBBuf( rErrorBBuf ); return status; }
int sendStartupPack( rcComm_t *conn, int connectCnt, int reconnFlag ) { startupPack_t startupPack; int status; char *tmpStr; bytesBuf_t *startupPackBBuf = NULL; /* setup the startup pack */ startupPack.irodsProt = conn->irodsProt; startupPack.connectCnt = connectCnt; startupPack.reconnFlag = reconnFlag; rstrcpy( startupPack.proxyUser, conn->proxyUser.userName, NAME_LEN ); rstrcpy( startupPack.proxyRodsZone, conn->proxyUser.rodsZone, NAME_LEN ); rstrcpy( startupPack.clientUser, conn->clientUser.userName, NAME_LEN ); rstrcpy( startupPack.clientRodsZone, conn->clientUser.rodsZone, NAME_LEN ); rstrcpy( startupPack.relVersion, RODS_REL_VERSION, NAME_LEN ); rstrcpy( startupPack.apiVersion, RODS_API_VERSION, NAME_LEN ); if ( ( tmpStr = getenv( SP_OPTION ) ) != NULL ) { rstrcpy( startupPack.option, tmpStr, NAME_LEN ); } else { startupPack.option[0] = '\0'; } // =-=-=-=-=-=-=- // if the advanced negotiation is requested from the irodsEnv, // tack those results onto the startup pack option string rodsEnv rods_env; status = getRodsEnv( &rods_env ); if ( status >= 0 && strlen( rods_env.rodsClientServerNegotiation ) > 0 ) { strncat( startupPack.option, rods_env.rodsClientServerNegotiation, strlen( rods_env.rodsClientServerNegotiation ) ); } /* always use XML_PROT for the startupPack */ status = packStruct( ( void * ) &startupPack, &startupPackBBuf, "StartupPack_PI", RodsPackTable, 0, XML_PROT ); if ( status < 0 ) { rodsLogError( LOG_NOTICE, status, "sendStartupPack: packStruct error, status = %d", status ); return status; } irods::network_object_ptr net_obj; irods::error ret = irods::network_factory( conn, net_obj ); if ( !ret.ok() ) { irods::log( PASS( ret ) ); freeBBuf( startupPackBBuf ); return ret.code(); } ret = sendRodsMsg( net_obj, RODS_CONNECT_T, startupPackBBuf, NULL, NULL, 0, XML_PROT ); freeBBuf( startupPackBBuf ); if ( !ret.ok() ) { irods::log( PASS( ret ) ); return ret.code(); } return ret.code(); } // sendStartupPack
// =-=-=-=-=-=-=- // request shut down client-server connection int rcDisconnect( rcComm_t* _conn ) { // =-=-=-=-=-=-=- // check for invalid param if ( _conn == NULL ) { return 0; } // =-=-=-=-=-=-=- // create network object to pass to plugin interface irods::network_object_ptr net_obj; irods::error ret = irods::network_factory( _conn, net_obj ); if ( !ret.ok() ) { irods::log( PASS( ret ) ); return ret.code(); } // =-=-=-=-=-=-=- // send disconnect msg to agent ret = sendRodsMsg( net_obj, RODS_DISCONNECT_T, NULL, NULL, NULL, 0, _conn->irodsProt ); if ( !ret.ok() ) { irods::log( PASS( ret ) ); } // =-=-=-=-=-=-=- // get rods env to pass to client start for policy decisions rodsEnv rods_env; int status = getRodsEnv( &rods_env ); // =-=-=-=-=-=-=- // shut down any network plugin activity ret = sockClientStop( net_obj, &rods_env ); if ( !ret.ok() ) { irods::log( PASS( ret ) ); } net_obj->to_client( _conn ); close( _conn->sock ); _conn->exit_flg = true; // if ( _conn->thread_ctx->reconnThr ) { try { // force an interruption point _conn->exit_flg = true; bool val = _conn->thread_ctx->reconnThr->try_join_for( boost::chrono::seconds( 2 ) ); if( true != val ) { // do not error out to client } } catch ( const boost::thread_interrupted& ) { rodsLog( LOG_ERROR, "Thread encountered interrupt." ); status = SYS_THREAD_ENCOUNTERED_INTERRUPT; } catch ( const boost::thread_resource_error& ) { rodsLog( LOG_ERROR, "Threads exceed maximum supported concurrent threads" ); status = SYS_INTERNAL_ERR; } } status = freeRcComm( _conn ); return status; } // rcDisconnect
int sendApiRequest( rcComm_t *conn, int apiInx, void *inputStruct, bytesBuf_t *inputBsBBuf ) { int status = 0; bytesBuf_t *inputStructBBuf = NULL; bytesBuf_t *myInputStructBBuf = NULL; cliChkReconnAtSendStart( conn ); irods::api_entry_table& RcApiTable = irods::get_client_api_table(); irods::api_entry_table::iterator itr = RcApiTable.find( apiInx ); if ( itr == RcApiTable.end() ) { rodsLogError( LOG_ERROR, SYS_UNMATCHED_API_NUM, "API Entry not found at index %d", apiInx ); return SYS_UNMATCHED_API_NUM; } if ( RcApiTable[apiInx]->inPackInstruct != NULL ) { if ( inputStruct == NULL ) { cliChkReconnAtSendEnd( conn ); return ( USER_API_INPUT_ERR ); } status = packStruct( ( void * ) inputStruct, &inputStructBBuf, ( char* )RcApiTable[apiInx]->inPackInstruct, RodsPackTable, 0, conn->irodsProt ); if ( status < 0 ) { rodsLogError( LOG_ERROR, status, "sendApiRequest: packStruct error, status = %d", status ); cliChkReconnAtSendEnd( conn ); return status; } myInputStructBBuf = inputStructBBuf; } else { myInputStructBBuf = NULL; }; if ( RcApiTable[apiInx]->inBsFlag <= 0 ) { inputBsBBuf = NULL; } irods::network_object_ptr net_obj; irods::error ret = irods::network_factory( conn, net_obj ); if ( !ret.ok() ) { irods::log( PASS( ret ) ); return ret.code(); } ret = sendRodsMsg( net_obj, RODS_API_REQ_T, myInputStructBBuf, inputBsBBuf, NULL, RcApiTable[apiInx]->apiNumber, conn->irodsProt ); if ( !ret.ok() ) { irods::log( PASS( ret ) ); if ( conn->svrVersion != NULL && conn->svrVersion->reconnPort > 0 ) { int status1; int savedStatus = ret.code() ; conn->thread_ctx->lock->lock(); status1 = cliSwitchConnect( conn ); rodsLog( LOG_DEBUG, "sendApiRequest: svrSwitchConnect. cliState = %d,agState=%d", conn->clientState, conn->agentState ); conn->thread_ctx->lock->unlock(); if ( status1 > 0 ) { /* should not be here */ rodsLog( LOG_NOTICE, "sendApiRequest: Switch connection and retry sendRodsMsg" ); ret = sendRodsMsg( net_obj, RODS_API_REQ_T, myInputStructBBuf, inputBsBBuf, NULL, RcApiTable[apiInx]->apiNumber, conn->irodsProt ); if ( !ret.ok() ) { irods::log( PASS( ret ) ); } else { status = savedStatus; } } // if status1 > 0 } // if svrVersion != NULL ... } else { // =-=-=-=-=-=-=- // be sure to pass along the return code from the // plugin call status = ret.code(); } freeBBuf( inputStructBBuf ); return ( status ); }