static inline int ElemToLong(BSONElem* val2,int64_t* outVal){ int32_t int32; int64_t d2; int64_t lng; double doVal; switch(val2->type) { case BSON_INT: bson_little_endian32(&int32,val2->value); d2 = int32; break; case BSON_LONG: case BSON_DATE: bson_little_endian64(&lng,val2->value); d2 = lng; break; case BSON_DOUBLE: bson_little_endian64(&doVal,val2->value); d2 = doVal; break; default: return -1; } *outVal = d2; return 0; }
mongo_reply * mongo_read_response( mongo_connection * conn ){ mongo_header head; /* header from network */ mongo_reply_fields fields; /* header from network */ mongo_reply * out; /* native endian */ int len; looping_read(conn, &head, sizeof(head)); looping_read(conn, &fields, sizeof(fields)); bson_little_endian32(&len, &head.len); if (len < sizeof(head)+sizeof(fields) || len > 64*1024*1024) MONGO_THROW(MONGO_EXCEPT_NETWORK); /* most likely corruption */ out = (mongo_reply*)bson_malloc(len); out->head.len = len; bson_little_endian32(&out->head.id, &head.id); bson_little_endian32(&out->head.responseTo, &head.responseTo); bson_little_endian32(&out->head.op, &head.op); bson_little_endian32(&out->fields.flag, &fields.flag); bson_little_endian64(&out->fields.cursorID, &fields.cursorID); bson_little_endian32(&out->fields.start, &fields.start); bson_little_endian32(&out->fields.num, &fields.num); MONGO_TRY{ looping_read(conn, &out->objs, len-sizeof(head)-sizeof(fields)); }MONGO_CATCH{ free(out); MONGO_RETHROW(); } return out; }
mongo_reply * mongo_read_response( mongo_connection * conn ){ mongo_header head; /* header from network */ mongo_reply_fields fields; /* header from network */ mongo_reply * out; /* native endian */ int len; looping_read(conn, &head, sizeof(head)); looping_read(conn, &fields, sizeof(fields)); bson_little_endian32(&len, &head.len); out = (mongo_reply*)apr_palloc(conn->p, len); out->head.len = len; bson_little_endian32(&out->head.id, &head.id); bson_little_endian32(&out->head.responseTo, &head.responseTo); bson_little_endian32(&out->head.op, &head.op); bson_little_endian32(&out->fields.flag, &fields.flag); bson_little_endian64(&out->fields.cursorID, &fields.cursorID); bson_little_endian32(&out->fields.start, &fields.start); bson_little_endian32(&out->fields.num, &fields.num); MONGO_TRY{ looping_read(conn, &out->objs, len-sizeof(head)-sizeof(fields)); }MONGO_CATCH{ //free(out); MONGO_RETHROW(); } return out; }
int mongo_read_response( mongo *conn, mongo_reply **reply ) { mongo_header head; /* header from network */ mongo_reply_fields fields; /* header from network */ mongo_reply *out; /* native endian */ unsigned int len; int res; mongo_read_socket( conn, &head, sizeof( head ) ); mongo_read_socket( conn, &fields, sizeof( fields ) ); bson_little_endian32( &len, &head.len ); if ( len < sizeof( head )+sizeof( fields ) || len > 64*1024*1024 ) return MONGO_READ_SIZE_ERROR; /* most likely corruption */ out = ( mongo_reply * )bson_malloc( len ); out->head.len = len; bson_little_endian32( &out->head.id, &head.id ); bson_little_endian32( &out->head.responseTo, &head.responseTo ); bson_little_endian32( &out->head.op, &head.op ); bson_little_endian32( &out->fields.flag, &fields.flag ); bson_little_endian64( &out->fields.cursorID, &fields.cursorID ); bson_little_endian32( &out->fields.start, &fields.start ); bson_little_endian32( &out->fields.num, &fields.num ); res = mongo_read_socket( conn, &out->objs, len-sizeof( head )-sizeof( fields ) ); if( res != MONGO_OK ) { bson_free( out ); return res; } *reply = out; return MONGO_OK; }
void bson_append64( bson *b, const void *data ) { bson_little_endian64( b->cur, data ); b->cur += 8; }
int64_t bson_iterator_long_raw( const bson_iterator *i ) { int64_t out; bson_little_endian64( &out, bson_iterator_value( i ) ); return out; }
double bson_iterator_double_raw( const bson_iterator *i ) { double out; bson_little_endian64( &out, bson_iterator_value( i ) ); return out; }
char *mongo_data_append64( char *start , const void *data ) { bson_little_endian64( start , data ); return start + 8; }
static void bson_append64( bson *b, const void *data ) { check_mongo_object( (void*)b ); bson_little_endian64( b->cur, data ); b->cur += 8; }
int64_t bson_iterator_long_raw( const bson_iterator *i ) { int64_t out; check_mongo_object( (void*)i ); bson_little_endian64( &out, bson_iterator_value( i ) ); return out; }
double bson_iterator_double_raw( const bson_iterator *i ) { double out; check_mongo_object( (void*)i ); bson_little_endian64( &out, bson_iterator_value( i ) ); return out; }
char * uvmongo_message_append64(char * start , const void * data) { bson_little_endian64(start, data); return start + 8; }
int uvmongo_message_read(uvmongo_t * m, char * msg, size_t buflen) { uvmongo_header_t * header; uvmongo_message_t * message; uvmongo_reply_fields_t * fields; uvmongo_reply_t * reply; unsigned int len, next; header = (uvmongo_header_t *) msg; fields = (uvmongo_reply_fields_t *)(msg+16); bson_little_endian32(&len, &header->msglen); reply = (uvmongo_reply_t *) bson_malloc(sizeof(uvmongo_reply_t) - sizeof(char) + len - 16 - 20); reply->header.msglen = len; bson_little_endian32(&reply->header.req_id, &header->req_id); bson_little_endian32(&reply->header.res_to, &header->res_to); bson_little_endian32(&reply->header.opcode, &header->opcode); bson_little_endian32(&reply->fields.flag, &fields->flag); bson_little_endian64(&reply->fields.cursorID, &fields->cursorID); bson_little_endian32(&reply->fields.start, &fields->start); bson_little_endian32(&reply->fields.num, &fields->num); reply->objs = msg+16+20; next = 0; int msg_name_len = Length(reply->header.res_to); char msg_name[msg_name_len]; snprintf(msg_name, sizeof(msg_name), "%d", reply->header.res_to); message = (uvmongo_message_t *)(hash_get(m->msgs, msg_name)); if (message == NULL) { fprintf(stderr, "could not found request id: %s", msg_name); return UVMONGO_ERROR; } do { bson res[1]; bson_init_finished_data(res, reply->objs + next, 1); if (!res) { break; } if (message->on_data) { message->on_data(m, res, message->privdata); } next += bson_size(res); if (next >= reply->header.msglen - 36) { break; } } while (next); /* * Handle Get more */ if (reply->fields.cursorID == 0 || reply->fields.num < message->cursor->limit) { /* * Here, we could call `response_cb` to notify user-land this response * has been ended. */ if (message->on_drain) { message->on_drain(m, message->privdata); } uvmongo_cursor_free(message->cursor); } else { uvmongo_cursor_t * cursor = uvmongo_cursor_new(message->cursor->coll); uvmongo_cursor_set_id(cursor, reply->fields.cursorID); uvmongo_cursor_set_limit(cursor, message->cursor->limit); uvmongo_message_t * new_msg = uvmongo_message_serialize_more(cursor); new_msg->cursor = cursor; uvmongo_message_set_callback(new_msg, message->on_data, message->on_drain, message->privdata); uvmongo_message_send(m, new_msg); } /* * check the buffer size is bigger than reply length, * that means multiple replies has been received. */ if (buflen > reply->header.msglen) { uvmongo_message_read(m, msg + reply->header.msglen, buflen - reply->header.msglen); } return UVMONGO_OK; }