int readAndProcClientMsg( rsComm_t * rsComm, int flags ) { int status = 0; msgHeader_t myHeader; bytesBuf_t inputStructBBuf, bsBBuf, errorBBuf; bzero( &inputStructBBuf, sizeof( inputStructBBuf ) ); bzero( &bsBBuf, sizeof( bsBBuf ) ); bzero( &errorBBuf, sizeof( errorBBuf ) ); svrChkReconnAtReadStart( rsComm ); /* everything else are set in readMsgBody */ /* read the header */ // =-=-=-=-=-=-=- // 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(); } if ( ( flags & READ_HEADER_TIMEOUT ) != 0 ) { int retryCnt = 0; struct timeval tv; tv.tv_sec = READ_HEADER_TIMEOUT_IN_SEC; tv.tv_usec = 0; while ( 1 ) { ret = readMsgHeader( net_obj, &myHeader, &tv ); if ( !ret.ok() ) { if ( isL1descInuse() && retryCnt < MAX_READ_HEADER_RETRY ) { rodsLogError( LOG_ERROR, status, "readAndProcClientMsg:readMsgHeader error. status = %d", ret.code() ); retryCnt++; continue; } if ( ret.code() == USER_SOCK_CONNECT_TIMEDOUT ) { rodsLog( LOG_ERROR, "readAndProcClientMsg: readMsgHeader by pid %d timedout", getpid() ); return ret.code(); } } break; } // while 1 } else { ret = readMsgHeader( net_obj, &myHeader, NULL ); } if ( !ret.ok() ) { irods::log( PASS( ret ) ); /* attempt to accept reconnect. ENOENT result from * user cntl-C */ if ( rsComm->reconnSock > 0 ) { int savedStatus = ret.code(); /* try again. the socket might have changed */ boost::unique_lock< boost::mutex > boost_lock( *rsComm->thread_ctx->lock ); rodsLog( LOG_DEBUG, "readAndProcClientMsg: svrSwitchConnect. cliState = %d,agState=%d", rsComm->clientState, rsComm->agentState ); svrSwitchConnect( rsComm ); boost_lock.unlock(); ret = readMsgHeader( net_obj, &myHeader, NULL ); if ( !ret.ok() ) { svrChkReconnAtReadEnd( rsComm ); return savedStatus; } } else { svrChkReconnAtReadEnd( rsComm ); return ret.code(); } } // if !ret.ok() #ifdef SYS_TIMING if ( strcmp( myHeader.type, RODS_API_REQ_T ) == 0 ) { /* Get the total time of AUTH_REQUEST_AN and AUTH_RESPONSE_AN */ if ( myHeader.intInfo != AUTH_RESPONSE_AN ) { initSysTiming( "irodsAgent", "recv request", 0 ); } } #endif ret = readMsgBody( net_obj, &myHeader, &inputStructBBuf, &bsBBuf, &errorBBuf, rsComm->irodsProt, NULL ); if ( !ret.ok() ) { irods::log( PASS( ret ) ); svrChkReconnAtReadEnd( rsComm ); return ret.code(); } svrChkReconnAtReadEnd( rsComm ); /* handler switch by msg type */ if ( strcmp( myHeader.type, RODS_API_REQ_T ) == 0 ) { status = rsApiHandler( rsComm, myHeader.intInfo, &inputStructBBuf, &bsBBuf ); #ifdef SYS_TIMING char tmpStr[NAME_LEN]; snprintf( tmpStr, NAME_LEN, "handle API %d", myHeader.intInfo ); printSysTiming( "irodsAgent", tmpStr, 0 ); #endif clearBBuf( &inputStructBBuf ); clearBBuf( &bsBBuf ); clearBBuf( &errorBBuf ); if ( ( flags & RET_API_STATUS ) != 0 ) { return status; } else { return 0; } } else if ( strcmp( myHeader.type, RODS_DISCONNECT_T ) == 0 ) { rodsLog( LOG_NOTICE, "readAndProcClientMsg: received disconnect msg from client" ); return DISCONN_STATUS; } else if ( strcmp( myHeader.type, RODS_RECONNECT_T ) == 0 ) { rodsLog( LOG_NOTICE, "readAndProcClientMsg: received reconnect msg from client" ); /* call itself again. be careful */ status = readAndProcClientMsg( rsComm, flags ); return status; } else { rodsLog( LOG_NOTICE, "agentMain: msg type %s not support by server", myHeader.type ); return USER_MSG_TYPE_NO_SUPPORT; } }
// =-=-=-=-=-=-=- // irods::error readVersion( irods::network_object_ptr _ptr, version_t** _version ) { // =-=-=-=-=-=-=- // init timval struct for header call struct timeval tv; tv.tv_sec = READ_VERSION_TOUT_SEC; tv.tv_usec = 0; // =-=-=-=-=-=-=- // call interface to read message header msgHeader_t myHeader; irods::error ret = readMsgHeader( _ptr, &myHeader, &tv ); if ( !ret.ok() ) { return PASS( ret ); } // =-=-=-=-=-=-=- // call interface to read message body bytesBuf_t inputStructBBuf, bsBBuf, errorBBuf; memset( &bsBBuf, 0, sizeof( bytesBuf_t ) ); ret = readMsgBody( _ptr, &myHeader, &inputStructBBuf, &bsBBuf, &errorBBuf, XML_PROT, NULL ); if ( !ret.ok() ) { return PASS( ret ); } // =-=-=-=-=-=-=- // basic error checking of message type if ( strcmp( myHeader.type, RODS_VERSION_T ) != 0 ) { if ( inputStructBBuf.buf != NULL ) { free( inputStructBBuf.buf ); } if ( bsBBuf.buf != NULL ) { free( bsBBuf.buf ); } if ( errorBBuf.buf != NULL ) { free( errorBBuf.buf ); } std::stringstream msg; msg << "wrong msg type [" << myHeader.type << " expected [" << RODS_VERSION_T << "]"; return ERROR( SYS_HEADER_TYPE_LEN_ERR, msg.str() ); } // =-=-=-=-=-=-=- // check length of byte stream buffer, should be 0 if ( myHeader.bsLen != 0 ) { if ( bsBBuf.buf != NULL ) { free( bsBBuf.buf ); } rodsLog( LOG_NOTICE, "readVersion: myHeader.bsLen = %d is not 0", myHeader.bsLen ); } // =-=-=-=-=-=-=- // check length of error buffer, should be 0 if ( myHeader.errorLen != 0 ) { if ( errorBBuf.buf != NULL ) { free( errorBBuf.buf ); } rodsLog( LOG_NOTICE, "readVersion: myHeader.errorLen = %d is not 0", myHeader.errorLen ); } // =-=-=-=-=-=-=- // bounds check message size if ( myHeader.msgLen > ( int ) sizeof( version_t ) * 2 || myHeader.msgLen <= 0 ) { if ( inputStructBBuf.buf != NULL ) { free( inputStructBBuf.buf ); } std::stringstream msg; msg << "header length is not within bounds: " << myHeader.msgLen; return ERROR( SYS_HEADER_READ_LEN_ERR, msg.str() ); } // =-=-=-=-=-=-=- // unpack the message, always use XML for this message type int status = unpackStruct( inputStructBBuf.buf, ( void** )( _version ), "Version_PI", RodsPackTable, XML_PROT ); free( inputStructBBuf.buf ); if ( status < 0 ) { rodsLogError( LOG_NOTICE, status, "readVersion:unpackStruct error. status = %d", status ); } return CODE( status ); } // readVersion
int readAndProcApiReply( rcComm_t *conn, int apiInx, void **outStruct, bytesBuf_t *outBsBBuf ) { int status = 0; msgHeader_t myHeader; /* bytesBuf_t outStructBBuf, errorBBuf, myOutBsBBuf; */ bytesBuf_t outStructBBuf, errorBBuf; cliChkReconnAtReadStart( conn ); memset( &outStructBBuf, 0, sizeof( bytesBuf_t ) ); memset( &outStructBBuf, 0, sizeof( bytesBuf_t ) ); /* memset (&myOutBsBBuf, 0, sizeof (bytesBuf_t)); */ /* some sanity check */ irods::api_entry_table& RcApiTable = irods::get_client_api_table(); if ( RcApiTable[apiInx]->outPackInstruct != NULL && outStruct == NULL ) { rodsLog( LOG_ERROR, "readAndProcApiReply: outStruct error for A apiNumber %d", RcApiTable[apiInx]->apiNumber ); cliChkReconnAtReadEnd( conn ); return ( USER_API_INPUT_ERR ); } if ( RcApiTable[apiInx]->outBsFlag > 0 && outBsBBuf == NULL ) { rodsLog( LOG_ERROR, "readAndProcApiReply: outBsBBuf error for B apiNumber %d", RcApiTable[apiInx]->apiNumber ); cliChkReconnAtReadEnd( conn ); return ( USER_API_INPUT_ERR ); } 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 = readMsgHeader( net_obj, &myHeader, NULL ); if ( !ret.ok() ) { irods::log( PASS( ret ) ); if ( conn->svrVersion != NULL && conn->svrVersion->reconnPort > 0 ) { int savedStatus = ret.code(); /* try again. the socket might have changed */ conn->thread_ctx->lock->lock(); rodsLog( LOG_DEBUG, "readAndProcClientMsg:svrSwitchConnect.cliState = %d,agState=%d", conn->clientState, conn->agentState ); cliSwitchConnect( conn ); conn->thread_ctx->lock->unlock(); irods::error ret = readMsgHeader( net_obj, &myHeader, NULL ); if ( !ret.ok() ) { cliChkReconnAtReadEnd( conn ); return ( savedStatus ); } } else { cliChkReconnAtReadEnd( conn ); return ( ret.code() ); } } // if !ret.ok ret = readMsgBody( net_obj, &myHeader, &outStructBBuf, outBsBBuf, &errorBBuf, conn->irodsProt, NULL ); if ( !ret.ok() ) { irods::log( PASS( ret ) ); cliChkReconnAtReadEnd( conn ); return ( status ); } // if !ret.ok cliChkReconnAtReadEnd( conn ); if ( strcmp( myHeader.type, RODS_API_REPLY_T ) == 0 ) { status = procApiReply( conn, apiInx, outStruct, outBsBBuf, &myHeader, &outStructBBuf, NULL, &errorBBuf ); } clearBBuf( &outStructBBuf ); /* clearBBuf (&myOutBsBBuf); */ clearBBuf( &errorBBuf ); return ( status ); }
// =-=-=-=-=-=-=- // irods::error readReconMsg( irods::network_object_ptr _ptr, reconnMsg_t** _msg ) { int status; msgHeader_t myHeader; bytesBuf_t inputStructBBuf, bsBBuf, errorBBuf; // =-=-=-=-=-=-=- // irods::error ret = readMsgHeader( _ptr, &myHeader, NULL ); if ( !ret.ok() ) { return PASSMSG( "read msg header error", ret ); } memset( &bsBBuf, 0, sizeof( bytesBuf_t ) ); ret = readMsgBody( _ptr, &myHeader, &inputStructBBuf, &bsBBuf, &errorBBuf, XML_PROT, NULL ); if ( !ret.ok() ) { return PASS( ret ); } /* some sanity check */ if ( strcmp( myHeader.type, RODS_RECONNECT_T ) != 0 ) { if ( inputStructBBuf.buf != NULL ) { free( inputStructBBuf.buf ); } if ( bsBBuf.buf != NULL ) { free( bsBBuf.buf ); } if ( errorBBuf.buf != NULL ) { free( errorBBuf.buf ); } std::stringstream msg; msg << "wrong msg type [" << myHeader.type << "] expected [" << RODS_CONNECT_T << "]"; return ERROR( SYS_HEADER_TYPE_LEN_ERR, msg.str() ); } if ( myHeader.bsLen != 0 ) { if ( bsBBuf.buf != NULL ) { free( bsBBuf.buf ); } rodsLog( LOG_NOTICE, "readReconMsg: myHeader.bsLen = %d is not 0", myHeader.bsLen ); } if ( myHeader.errorLen != 0 ) { if ( errorBBuf.buf != NULL ) { free( errorBBuf.buf ); } rodsLog( LOG_NOTICE, "readReconMsg: myHeader.errorLen = %d is not 0", myHeader.errorLen ); } if ( myHeader.msgLen <= 0 ) { if ( inputStructBBuf.buf != NULL ) { free( inputStructBBuf.buf ); } rodsLog( LOG_NOTICE, "readReconMsg: problem with myHeader.msgLen = %d", myHeader.msgLen ); std::stringstream msg; msg << "message length is invalid: " << myHeader.msgLen; return ERROR( SYS_HEADER_READ_LEN_ERR, msg.str() ); } /* always use XML_PROT for the startup pack */ status = unpackStruct( inputStructBBuf.buf, ( void** )( _msg ), "ReconnMsg_PI", RodsPackTable, XML_PROT ); clearBBuf( &inputStructBBuf ); if ( status < 0 ) { rodsLogError( LOG_NOTICE, status, "readReconMsg:unpackStruct error. status = %d", status ); } return CODE( status ); }
/// =-=-=-=-=-=-=- /// @brief function which sends the negotiation message error read_client_server_negotiation_message( irods::network_object_ptr _ptr, boost::shared_ptr< cs_neg_t >& _cs_neg_msg ) { // =-=-=-=-=-=-=- // read the message header struct timeval tv; tv.tv_sec = READ_VERSION_TOUT_SEC; tv.tv_usec = 0; msgHeader_t msg_header; irods::error ret = readMsgHeader( _ptr, &msg_header, &tv ); if ( !ret.ok() ) { return PASSMSG( "read message header failed", ret ); } // =-=-=-=-=-=-=- // read the message body bytesBuf_t struct_buf, data_buf, error_buf; memset( &data_buf, 0, sizeof( bytesBuf_t ) ); ret = readMsgBody( _ptr, &msg_header, &struct_buf, &data_buf, &error_buf, XML_PROT, 0 ); if ( !ret.ok() ) { return PASS( ret ); } // =-=-=-=-=-=-=- // check that we did in fact get the right type of message if ( strcmp( msg_header.type, RODS_CS_NEG_T ) != 0 ) { // =-=-=-=-=-=-=- // trap potential case where server does not support // advanced negotiation. a version msg would be sent // back instead. if ( strcmp( msg_header.type, RODS_VERSION_T ) == 0 ) { // =-=-=-=-=-=-=- // unpack the version struct to check the status version_t* version = 0; int status = unpackStruct( struct_buf.buf, ( void ** )( static_cast<void *>( &version ) ), "Version_PI", RodsPackTable, XML_PROT ); if ( struct_buf.buf ) { free( struct_buf.buf ); } if ( data_buf.buf ) { free( data_buf.buf ); } if ( error_buf.buf ) { free( error_buf.buf ); } if ( status < 0 ) { rodsLog( LOG_ERROR, "read_client_server_negotiation_message :: unpackStruct FAILED" ); return ERROR( status, "unpackStruct failed" ); } if ( version->status < 0 ) { rodsLog( LOG_ERROR, "read_client_server_negotiation_message :: received error message %d", version->status ); return ERROR( version->status, "negotiation failed" ); } else { // =-=-=-=-=-=-=- // if no negoation is allowed then provide a readable // error for the client std::stringstream msg; msg << "received [" << msg_header.type << "] "; msg << "but expected [" << RODS_CS_NEG_T << "]\n\n"; msg << "\t*** Advanced negotiation is enabled in this iRODS environment ***\n"; msg << "\t*** which is most likely not supported by the server. ***\n"; msg << "\t*** Comment out irodsClientServerNegotiation in the irodsEnv ***\n"; msg << "\t*** file to disable. ***\n"; return ERROR( ADVANCED_NEGOTIATION_NOT_SUPPORTED, msg.str() ); } } else { // =-=-=-=-=-=-=- // something entirely unexpected happened std::stringstream msg; msg << "wrong message type [" << msg_header.type << "] "; msg << "expected [" << RODS_CS_NEG_T << "]"; return ERROR( SYS_HEADER_TYPE_LEN_ERR, msg.str() ); } } // =-=-=-=-=-=-=- // check that we did not get any data with the message if ( msg_header.bsLen != 0 ) { if ( data_buf.buf != NULL ) { free( data_buf.buf ); } rodsLog( LOG_NOTICE, "read_client_server_negotiation_message: msg_header.bsLen = %d is not 0", msg_header.bsLen ); } // =-=-=-=-=-=-=- // check that we did not get anything in the error buffer if ( msg_header.errorLen != 0 ) { if ( error_buf.buf ) { free( error_buf.buf ); } rodsLog( LOG_NOTICE, "read_client_server_negotiation_message: msg_header.errorLen = %d is not 0", msg_header.errorLen ); } // =-=-=-=-=-=-=- // check that we did get an appropriately sized message if ( msg_header.msgLen > ( int ) sizeof( irods::cs_neg_t ) * 2 || msg_header.msgLen <= 0 ) { if ( struct_buf.buf != NULL ) { free( struct_buf.buf ); } std::stringstream msg; msg << "message length is invalid: " << msg_header.msgLen << " vs " << sizeof( irods::cs_neg_t ); return ERROR( SYS_HEADER_READ_LEN_ERR, msg.str() ); } // =-=-=-=-=-=-=- // do an unpack into our out variable using the xml protocol cs_neg_t* tmp_cs_neg = 0; int status = unpackStruct( struct_buf.buf, ( void ** )( static_cast<void *>( &tmp_cs_neg ) ), "CS_NEG_PI", RodsPackTable, XML_PROT ); free( struct_buf.buf ); if ( status < 0 ) { rodsLog( LOG_ERROR, "read_client_server_negotiation_message :: unpackStruct FAILED" ); return ERROR( status, "unpackStruct failed" ); } _cs_neg_msg.reset( tmp_cs_neg, free ); // =-=-=-=-=-=-=- // win!!!111one return SUCCESS(); } // read_client_server_negotiation_message