bool CCBListener::HandleCCBRequest( ClassAd &msg ) { MyString address; MyString connect_id; MyString request_id; MyString name; if( !msg.LookupString( ATTR_MY_ADDRESS, address) || !msg.LookupString( ATTR_CLAIM_ID, connect_id) || !msg.LookupString( ATTR_REQUEST_ID, request_id) ) { MyString msg_str; msg.sPrint(msg_str); EXCEPT("CCBListener: invalid CCB request from %s: %s\n", m_ccb_address.Value(), msg_str.Value() ); } msg.LookupString( ATTR_NAME, name ); if( name.find(address.Value())<0 ) { name.formatstr_cat(" with reverse connect address %s",address.Value()); } dprintf(D_FULLDEBUG|D_NETWORK, "CCBListener: received request to connect to %s, request id %s.\n", name.Value(), request_id.Value()); return DoReversedCCBConnect( address.Value(), connect_id.Value(), request_id.Value(), name.Value() ); }
bool CCBListener::HandleCCBRegistrationReply( ClassAd &msg ) { if( !msg.LookupString(ATTR_CCBID,m_ccbid) ) { MyString msg_str; msg.sPrint(msg_str); EXCEPT("CCBListener: no ccbid in registration reply: %s\n", msg_str.Value() ); } msg.LookupString(ATTR_CLAIM_ID,m_reconnect_cookie); dprintf(D_ALWAYS, "CCBListener: registered with CCB server %s as ccbid %s\n", m_ccb_address.Value(), m_ccbid.Value() ); m_waiting_for_registration = false; m_registered = true; daemonCore->daemonContactInfoChanged(); return true; }
bool CCBListener::ReadMsgFromCCB() { if( !m_sock ) { return false; } m_sock->timeout(CCB_TIMEOUT); ClassAd msg; if( !msg.initFromStream( *m_sock ) || !m_sock->end_of_message() ) { dprintf(D_ALWAYS, "CCBListener: failed to receive message from CCB server %s\n", m_ccb_address.Value()); Disconnected(); return false; } m_last_contact_from_peer = time(NULL); RescheduleHeartbeat(); int cmd = -1; msg.LookupInteger( ATTR_COMMAND, cmd ); switch( cmd ) { case CCB_REGISTER: return HandleCCBRegistrationReply( msg ); case CCB_REQUEST: return HandleCCBRequest( msg ); case ALIVE: dprintf(D_FULLDEBUG,"CCBListener: received heartbeat from server.\n"); return true; } MyString msg_str; msg.sPrint(msg_str); dprintf( D_ALWAYS, "CCBListener: Unexpected message received from CCB " "server: %s\n", msg_str.Value() ); return false; }
void CCBServer::HandleRequestResultsMsg( CCBTarget *target ) { // Reply from target daemon about whether it succeeded in // connecting to the requested client. Sock *sock = target->getSock(); ClassAd msg; sock->decode(); if( !msg.initFromStream( *sock ) || !sock->end_of_message() ) { // disconnect dprintf(D_FULLDEBUG, "CCB: received disconnect from target daemon %s " "with ccbid %lu.\n", sock->peer_description(), target->getCCBID() ); RemoveTarget( target ); return; } int command = 0; if( msg.LookupInteger( ATTR_COMMAND, command ) && command == ALIVE ) { SendHeartbeatResponse( target ); return; } target->decPendingRequestResults(); bool success = false; MyString error_msg; MyString reqid_str; CCBID reqid; MyString connect_id; msg.LookupBool( ATTR_RESULT, success ); msg.LookupString( ATTR_ERROR_STRING, error_msg ); msg.LookupString( ATTR_REQUEST_ID, reqid_str ); msg.LookupString( ATTR_CLAIM_ID, connect_id ); if( !CCBIDFromString( reqid, reqid_str.Value() ) ) { MyString msg_str; msg.sPrint(msg_str); dprintf(D_ALWAYS, "CCB: received reply from target daemon %s with ccbid %lu " "without a valid request id: %s\n", sock->peer_description(), target->getCCBID(), msg_str.Value()); RemoveTarget( target ); return; } CCBServerRequest *request = GetRequest( reqid ); if( request && request->getSock()->readReady() ) { // Request socket must have just closed. To avoid noise in // logs when we fail to write to it, delete the request now. RemoveRequest( request ); request = NULL; } char const *request_desc = "(client which has gone away)"; if( request ) { request_desc = request->getSock()->peer_description(); } if( success ) { dprintf(D_FULLDEBUG,"CCB: received 'success' from target daemon %s " "with ccbid %lu for " "request %s from %s.\n", sock->peer_description(), target->getCCBID(), reqid_str.Value(), request_desc); } else { dprintf(D_FULLDEBUG,"CCB: received error from target daemon %s " "with ccbid %lu for " "request %s from %s: %s\n", sock->peer_description(), target->getCCBID(), reqid_str.Value(), request_desc, error_msg.Value()); } if( !request ) { if( success ) { // expected: the client has gone away; it got what it wanted return; } dprintf( D_FULLDEBUG, "CCB: client for request %s to target daemon %s with ccbid " "%lu disappeared before receiving error details.\n", reqid_str.Value(), sock->peer_description(), target->getCCBID()); return; } if( connect_id != request->getConnectID() ) { MyString msg_str; msg.sPrint(msg_str); dprintf( D_FULLDEBUG, "CCB: received wrong connect id (%s) from target daemon %s " "with ccbid %lu for " "request %s\n", connect_id.Value(), sock->peer_description(), target->getCCBID(), reqid_str.Value()); RemoveTarget( target ); return; } RequestFinished( request, success, error_msg.Value() ); }
int CCBServer::HandleRequest(int cmd,Stream *stream) { ReliSock *sock = (ReliSock *)stream; ASSERT( cmd == CCB_REQUEST ); // Avoid lengthy blocking on communication with our peer. // This command-handler should not get called until data // is ready to read. sock->timeout(1); ClassAd msg; sock->decode(); if( !msg.initFromStream( *sock ) || !sock->end_of_message() ) { dprintf(D_ALWAYS, "CCB: failed to receive request " "from %s.\n", sock->peer_description() ); return FALSE; } MyString name; if( msg.LookupString(ATTR_NAME,name) ) { // client name is purely for debugging purposes name.formatstr_cat(" on %s",sock->peer_description()); sock->set_peer_description(name.Value()); } MyString target_ccbid_str; MyString return_addr; MyString connect_id; // id target daemon should present to requester CCBID target_ccbid; // NOTE: using ATTR_CLAIM_ID for connect id so that it is // automatically treated as a secret over the network. // It must be presented by the target daemon when connecting // to the requesting client, so the client can confirm that // the connection is in response to its request. if( !msg.LookupString(ATTR_CCBID,target_ccbid_str) || !msg.LookupString(ATTR_MY_ADDRESS,return_addr) || !msg.LookupString(ATTR_CLAIM_ID,connect_id) ) { MyString ad_str; msg.sPrint(ad_str); dprintf(D_ALWAYS, "CCB: invalid request from %s: %s\n", sock->peer_description(), ad_str.Value() ); return FALSE; } if( !CCBIDFromString(target_ccbid,target_ccbid_str.Value()) ) { dprintf(D_ALWAYS, "CCB: request from %s contains invalid CCBID %s\n", sock->peer_description(), target_ccbid_str.Value() ); return FALSE; } CCBTarget *target = GetTarget( target_ccbid ); if( !target ) { dprintf(D_ALWAYS, "CCB: rejecting request from %s for ccbid %s because no daemon is " "currently registered with that id " "(perhaps it recently disconnected).\n", sock->peer_description(), target_ccbid_str.Value()); MyString error_msg; error_msg.formatstr( "CCB server rejecting request for ccbid %s because no daemon is " "currently registered with that id " "(perhaps it recently disconnected).", target_ccbid_str.Value()); RequestReply( sock, false, error_msg.Value(), 0, target_ccbid ); return FALSE; } SetSmallBuffers(sock); CCBServerRequest *request = new CCBServerRequest( sock, target_ccbid, return_addr.Value(), connect_id.Value() ); AddRequest( request, target ); dprintf(D_FULLDEBUG, "CCB: received request id %lu from %s for target ccbid %s " "(registered as %s)\n", request->getRequestID(), request->getSock()->peer_description(), target_ccbid_str.Value(), target->getSock()->peer_description()); ForwardRequestToTarget( request, target ); return KEEP_STREAM; }
bool DCSchedd::getJobConnectInfo( PROC_ID jobid, int subproc, char const *session_info, int timeout, CondorError *errstack, MyString &starter_addr, MyString &starter_claim_id, MyString &starter_version, MyString &slot_name, MyString &error_msg, bool &retry_is_sensible) { ClassAd input; ClassAd output; input.Assign(ATTR_CLUSTER_ID,jobid.cluster); input.Assign(ATTR_PROC_ID,jobid.proc); if( subproc != -1 ) { input.Assign(ATTR_SUB_PROC_ID,subproc); } input.Assign(ATTR_SESSION_INFO,session_info); ReliSock sock; if( !connectSock(&sock,timeout,errstack) ) { error_msg = "Failed to connect to schedd"; dprintf( D_ALWAYS, "%s\n",error_msg.Value()); return false; } if( !startCommand(GET_JOB_CONNECT_INFO, &sock, timeout, errstack) ) { error_msg = "Failed to send GET_JOB_CONNECT_INFO to schedd"; dprintf( D_ALWAYS, "%s\n",error_msg.Value()); return false; } if( !forceAuthentication(&sock, errstack) ) { error_msg = "Failed to authenticate"; dprintf( D_ALWAYS, "%s\n",error_msg.Value()); return false; } sock.encode(); if( !input.put(sock) || !sock.end_of_message() ) { error_msg = "Failed to send GET_JOB_CONNECT_INFO to schedd"; dprintf( D_ALWAYS, "%s\n",error_msg.Value()); return false; } sock.decode(); if( !output.initFromStream(sock) || !sock.end_of_message() ) { error_msg = "Failed to get response from schedd"; dprintf( D_ALWAYS, "%s\n",error_msg.Value()); return false; } if( IsFulldebug(D_FULLDEBUG) ) { std::string adstr; output.SetPrivateAttributesInvisible(true); output.sPrint(adstr); output.SetPrivateAttributesInvisible(false); dprintf(D_FULLDEBUG,"Response for GET_JOB_CONNECT_INFO:\n%s\n", adstr.c_str()); } bool result=false; output.LookupBool(ATTR_RESULT,result); if( !result ) { output.LookupString(ATTR_ERROR_STRING,error_msg); retry_is_sensible = false; output.LookupBool(ATTR_RETRY,retry_is_sensible); } else { output.LookupString(ATTR_STARTER_IP_ADDR,starter_addr); output.LookupString(ATTR_CLAIM_ID,starter_claim_id); output.LookupString(ATTR_VERSION,starter_version); output.LookupString(ATTR_REMOTE_HOST,slot_name); } return result; }
bool DCTransferQueue::PollForTransferQueueSlot(int timeout,bool &pending,MyString &error_desc) { if( GoAheadAlways( m_xfer_downloading ) ) { return true; } CheckTransferQueueSlot(); if( !m_xfer_queue_pending ) { // status of request is known pending = false; if( !m_xfer_queue_go_ahead ) { error_desc = m_xfer_rejected_reason; } return m_xfer_queue_go_ahead; } Selector selector; selector.add_fd( m_xfer_queue_sock->get_file_desc(), Selector::IO_READ ); time_t start = time(NULL); do { int t = timeout - (time(NULL) - start); selector.set_timeout( t >= 0 ? t : 0 ); selector.execute(); } while( selector.signalled() ); if( selector.timed_out() ) { // It is expected that we may time out while waiting for a // response. The caller should keep calling this function // periodically until we get a result. pending = true; return false; } m_xfer_queue_sock->decode(); ClassAd msg; if( !msg.initFromStream(*m_xfer_queue_sock) || !m_xfer_queue_sock->end_of_message() ) { formatstr(m_xfer_rejected_reason, "Failed to receive transfer queue response from %s for job %s " "(initial file %s).", m_xfer_queue_sock->peer_description(), m_xfer_jobid.c_str(), m_xfer_fname.c_str()); goto request_failed; } int result; // this should be one of the values in XFER_QUEUE_ENUM if( !msg.LookupInteger(ATTR_RESULT,result) ) { std::string msg_str; msg.sPrint(msg_str); formatstr(m_xfer_rejected_reason, "Invalid transfer queue response from %s for job %s (%s): %s", m_xfer_queue_sock->peer_description(), m_xfer_jobid.c_str(), m_xfer_fname.c_str(), msg_str.c_str()); goto request_failed; } if( result == XFER_QUEUE_GO_AHEAD ) { m_xfer_queue_go_ahead = true; } else { m_xfer_queue_go_ahead = false; std::string reason; msg.LookupString(ATTR_ERROR_STRING,reason); formatstr(m_xfer_rejected_reason, "Request to transfer files for %s (%s) was rejected by %s: %s", m_xfer_jobid.c_str(), m_xfer_fname.c_str(), m_xfer_queue_sock->peer_description(), reason.c_str()); goto request_failed; } m_xfer_queue_pending = false; pending = m_xfer_queue_pending; return true; request_failed: error_desc = m_xfer_rejected_reason; dprintf(D_ALWAYS, "%s\n", m_xfer_rejected_reason.c_str()); m_xfer_queue_pending = false; m_xfer_queue_go_ahead = false; pending = m_xfer_queue_pending; return false; }