/** * @param in incoming metaserver packet * * NMT_SERVERKEEPALIVE indicates a keep alive for a server, also serves as a "registration" * Response Packet Type: NMT_HANDSHAKE * - pack packet type * - pack random number */ void MetaServer::processSERVERKEEPALIVE(const MetaServerPacket& in, MetaServerPacket& out) { uint32_t i = msdo.addHandshake(); if ( i > 0 ) { m_Logger.debug("processSERVERKEEPALIVE(%u)", i); out.setPacketType(NMT_HANDSHAKE); out.addPacketData(i); out.setAddress( in.getAddress() ); } }
/** * NMT_LISTREQ: * 4 bytes type * 4 bytes start index * * Response: * * NMT_LISTRESP * * 4 bytes type * 4 bytes total servers in list * 4 bytes servers in this packet ( triggering client to have another REQ with total-servers offset ) * 4 bytes per server in this packet * */ void MetaServer::processLISTREQ( const MetaServerPacket& in, MetaServerPacket& out) { uint32_t server_index = in.getIntData(4); uint32_t total = msdo.getServerSessionCount(); uint32_t packed_max = total; uint32_t packed = 0; std::list<uint32_t> resp_list; /* * If we are unable to pack the entire list into 1 packet */ if ( (total*sizeof(uint32_t) - (server_index*sizeof(uint32_t)) ) > (MAX_UDP_OUT_BYTES-4-4-4) ) { /* * We want it to round ... just like the price is right, the goal is not to go over */ packed_max = (MAX_UDP_OUT_BYTES-4-4-4) / sizeof(uint32_t); } /* * We hide the craziness of what goes on here inside the single method. * The goal, is to get the list of servers constrained by packed_max */ std::list<std::string> sess_list = msdo.getServerSessionList(server_index,packed_max); std::list<std::string>::iterator list_itr; for ( list_itr = sess_list.begin(); list_itr != sess_list.end() ; list_itr++ ) { /* * Defensive to make sure we're not going to exceed our max */ if ( packed >= packed_max ) break; /* * Defensive to make sure that the item in the list is * actually a valid data item we can send ( orthogonal processes * such as expiry could invalidate at any time ). * * Thus we can iterate over as much of the server list as we need to * and dead items won't count, only those added to the response packet. */ if ( msdo.serverSessionExists( *list_itr )) { /* * Note: see if there is a way to do this without atoi */ resp_list.push_back( atoi( msdo.getServerSession(*list_itr)["ip_int"].c_str() ) ); ++packed; } } if ( packed != resp_list.size() ) { m_Logger.warn("Packed (%u) vs Response(%u) MISMATCH!", packed, resp_list.size() ); } out.setAddress( in.getAddress() ); out.setPacketType(NMT_LISTRESP); /** * If the list is empty, just send a 0,0 to indicate completion. * NOTE: I think this logic is a bug in the protocol, as the * original MS code looks as if this was just not working correctly. */ if ( resp_list.size() > 0 ) { out.addPacketData( msdo.getServerSessionCount() ); out.addPacketData( (uint32_t)resp_list.size() ); while ( ! resp_list.empty() ) { m_Logger.debug("processLISTRESP(%d) - Adding", resp_list.front() ); out.addPacketData(resp_list.front()); resp_list.pop_front(); } } else { /* * For the record, I think this is a stupid protocol construct */ m_Logger.debug("processLISTRESP(0,0) - Empty"); out.addPacketData( 0 ); out.addPacketData( 0 ); } }