void operator()() const { DBClientConnection dest; string errmsg; while (!dest.connect(mongoBridgeGlobalParams.destUri, errmsg)) sleepmillis( 500 ); Message m; while( 1 ) { try { m.reset(); if ( !mp_.recv( m ) ) { cout << "end connection " << mp_.psock->remoteString() << endl; mp_.shutdown(); break; } sleepmillis(mongoBridgeGlobalParams.delay); int oldId = m.header()->id; if ( m.operation() == dbQuery || m.operation() == dbMsg || m.operation() == dbGetMore ) { bool exhaust = false; if ( m.operation() == dbQuery ) { DbMessage d( m ); QueryMessage q( d ); exhaust = q.queryOptions & QueryOption_Exhaust; } Message response; dest.port().call( m, response ); // nothing to reply with? if ( response.empty() ) cleanup(0); mp_.reply( m, response, oldId ); while ( exhaust ) { MsgData *header = response.header(); QueryResult *qr = (QueryResult *) header; if ( qr->cursorId ) { response.reset(); dest.port().recv( response ); mp_.reply( m, response ); // m argument is ignored anyway } else { exhaust = false; } } } else { dest.port().say( m, oldId ); } } catch ( ... ) { log() << "caught exception in Forwarder, continuing" << endl; } } }
void operator()() const { DBClientConnection dest; string errmsg; while( !dest.connect( destUri, errmsg ) ) sleepmillis( 500 ); Message m; while( 1 ) { m.reset(); if ( !mp_.recv( m ) ) { cout << "end connection " << mp_.farEnd.toString() << endl; mp_.shutdown(); break; } int oldId = m.data->id; if ( m.data->operation() == dbQuery || m.data->operation() == dbMsg || m.data->operation() == dbGetMore ) { Message response; dest.port().call( m, response ); mp_.reply( m, response, oldId ); } else { dest.port().say( m, oldId ); } } }
void got_packet(u_char *args, const struct pcap_pkthdr *header, const u_char *packet){ const struct sniff_ip* ip = (struct sniff_ip*)(packet + captureHeaderSize); int size_ip = IP_HL(ip)*4; if ( size_ip < 20 ){ cerr << "*** Invalid IP header length: " << size_ip << " bytes" << endl; return; } assert( ip->ip_p == IPPROTO_TCP ); const struct sniff_tcp* tcp = (struct sniff_tcp*)(packet + captureHeaderSize + size_ip); int size_tcp = TH_OFF(tcp)*4; if (size_tcp < 20){ cerr << "*** Invalid TCP header length: " << size_tcp << " bytes" << endl; return; } if ( ! ( serverPorts.count( ntohs( tcp->th_sport ) ) || serverPorts.count( ntohs( tcp->th_dport ) ) ) ){ return; } const u_char * payload = (const u_char*)(packet + captureHeaderSize + size_ip + size_tcp); unsigned totalSize = ntohs(ip->ip_len); assert( totalSize <= header->caplen ); int size_payload = totalSize - (size_ip + size_tcp); if (size_payload <= 0 ) return; Connection c; c.srcAddr = ip->ip_src; c.srcPort = tcp->th_sport; c.dstAddr = ip->ip_dst; c.dstPort = tcp->th_dport; if ( seen[ c ] ) { if ( expectedSeq[ c ] != ntohl( tcp->th_seq ) ) { cerr << "Warning: sequence # mismatch, there may be dropped packets" << endl; } } else { seen[ c ] = true; } expectedSeq[ c ] = ntohl( tcp->th_seq ) + size_payload; Message m; if ( bytesRemainingInMessage[ c ] == 0 ) { m.setData( (MsgData*)payload , false ); if ( !m.data->valid() ) { cerr << "Invalid message start, skipping packet." << endl; return; } if ( size_payload > m.data->len ) { cerr << "Multiple messages in packet, skipping packet." << endl; return; } if ( size_payload < m.data->len ) { bytesRemainingInMessage[ c ] = m.data->len - size_payload; messageBuilder[ c ].reset( new BufBuilder() ); messageBuilder[ c ]->append( (void*)payload, size_payload ); return; } } else { bytesRemainingInMessage[ c ] -= size_payload; messageBuilder[ c ]->append( (void*)payload, size_payload ); if ( bytesRemainingInMessage[ c ] < 0 ) { cerr << "Received too many bytes to complete message, resetting buffer" << endl; bytesRemainingInMessage[ c ] = 0; messageBuilder[ c ].reset(); return; } if ( bytesRemainingInMessage[ c ] > 0 ) return; m.setData( (MsgData*)messageBuilder[ c ]->buf(), true ); messageBuilder[ c ]->decouple(); messageBuilder[ c ].reset(); } DbMessage d( m ); cout << inet_ntoa(ip->ip_src) << ":" << ntohs( tcp->th_sport ) << ( serverPorts.count( ntohs( tcp->th_dport ) ) ? " -->> " : " <<-- " ) << inet_ntoa(ip->ip_dst) << ":" << ntohs( tcp->th_dport ) << " " << d.getns() << " " << m.data->len << " bytes " << m.data->id; if ( m.data->operation() == mongo::opReply ) cout << " - " << m.data->responseTo; cout << endl; switch( m.data->operation() ){ case mongo::opReply:{ mongo::QueryResult* r = (mongo::QueryResult*)m.data; cout << "\treply" << " n:" << r->nReturned << " cursorId: " << r->cursorId << endl; if ( r->nReturned ){ mongo::BSONObj o( r->data() , 0 ); cout << "\t" << o << endl; } break; } case mongo::dbQuery:{ mongo::QueryMessage q(d); cout << "\tquery: " << q.query << endl; break; } case mongo::dbUpdate:{ int flags = d.pullInt(); BSONObj q = d.nextJsObj(); BSONObj o = d.nextJsObj(); cout << "\tupdate flags:" << flags << " q:" << q << " o:" << o << endl; break; } case mongo::dbInsert:{ cout << "\tinsert: " << d.nextJsObj() << endl; while ( d.moreJSObjs() ) cout << "\t\t" << d.nextJsObj() << endl; break; } case mongo::dbGetMore:{ int nToReturn = d.pullInt(); long long cursorId = d.pullInt64(); cout << "\tgetMore nToReturn: " << nToReturn << " cursorId: " << cursorId << endl; break; } case mongo::dbDelete:{ int flags = d.pullInt(); BSONObj q = d.nextJsObj(); cout << "\tdelete flags: " << flags << " q: " << q << endl; break; } case mongo::dbKillCursors:{ int *x = (int *) m.data->_data; x++; // reserved int n = *x; cout << "\tkillCursors n: " << n << endl; break; } default: cerr << "*** CANNOT HANDLE TYPE: " << m.data->operation() << endl; } if ( !forwardAddress.empty() ) { if ( m.data->operation() != mongo::opReply ) { DBClientConnection *conn = forwarder[ c ]; if ( !conn ) { // These won't get freed on error, oh well hopefully we'll just // abort in that case anyway. conn = new DBClientConnection( true ); conn->connect( forwardAddress ); forwarder[ c ] = conn; } if ( m.data->operation() == mongo::dbQuery || m.data->operation() == mongo::dbGetMore ) { if ( m.data->operation() == mongo::dbGetMore ) { DbMessage d( m ); d.pullInt(); long long &cId = d.pullInt64(); cId = mapCursor[ c ][ cId ]; } Message response; conn->port().call( m, response ); QueryResult *qr = (QueryResult *) response.data; if ( !( qr->resultFlags() & QueryResult::ResultFlag_CursorNotFound ) ) { if ( qr->cursorId != 0 ) { lastCursor[ c ] = qr->cursorId; return; } } lastCursor[ c ] = 0; } else { conn->port().say( m ); } } else { Connection r = c.reverse(); long long myCursor = lastCursor[ r ]; QueryResult *qr = (QueryResult *) m.data; long long yourCursor = qr->cursorId; if ( ( qr->resultFlags() & QueryResult::ResultFlag_CursorNotFound ) ) yourCursor = 0; if ( myCursor && !yourCursor ) cerr << "Expected valid cursor in sniffed response, found none" << endl; if ( !myCursor && yourCursor ) cerr << "Sniffed valid cursor when none expected" << endl; if ( myCursor && yourCursor ) { mapCursor[ r ][ qr->cursorId ] = lastCursor[ r ]; lastCursor[ r ] = 0; } } } }
void operator()() const { DBClientConnection dest; string errmsg; Timer connectTimer; while (!dest.connect(HostAndPort(mongoBridgeGlobalParams.destUri), errmsg)) { // If we can't connect for the configured timeout, give up // if (connectTimer.seconds() >= mongoBridgeGlobalParams.connectTimeoutSec) { cout << "Unable to establish connection from " << mp_.psock->remoteString() << " to " << mongoBridgeGlobalParams.destUri << " after " << connectTimer.seconds() << " seconds. Giving up." << endl; mp_.shutdown(); return; } sleepmillis(500); } Message m; while( 1 ) { try { m.reset(); if ( !mp_.recv( m ) ) { cout << "end connection " << mp_.psock->remoteString() << endl; mp_.shutdown(); break; } sleepmillis(mongoBridgeGlobalParams.delay); int oldId = m.header()->id; if ( m.operation() == dbQuery || m.operation() == dbMsg || m.operation() == dbGetMore ) { bool exhaust = false; if ( m.operation() == dbQuery ) { DbMessage d( m ); QueryMessage q( d ); exhaust = q.queryOptions & QueryOption_Exhaust; } Message response; dest.port().call( m, response ); // nothing to reply with? if ( response.empty() ) cleanup(0); mp_.reply( m, response, oldId ); while ( exhaust ) { MsgData *header = response.header(); QueryResult *qr = (QueryResult *) header; if ( qr->cursorId ) { response.reset(); dest.port().recv( response ); mp_.reply( m, response ); // m argument is ignored anyway } else { exhaust = false; } } } else { dest.port().say( m, oldId ); } } catch ( ... ) { log() << "caught exception in Forwarder, continuing" << endl; } } }