void mcon_serialize_int(struct mcon_str *str, int num)
{
	int i = MONGO_32(num);

	mcon_str_addl(str, (char*) &i, 4, 0);
}
Example #2
0
char *bson_next(char *data)
{
	unsigned char type = data[0];
	int32_t       length;

	if (type == 0) {
		return NULL;
	}

	data = bson_skip_field_name(data + 1); /* Skip 1, because of the type in data[0] */
/*
element 	::= 	"\x01" e_name double 	Floating point
	| 	"\x02" e_name string 	UTF-8 string
	| 	"\x03" e_name document 	Embedded document
	| 	"\x04" e_name document 	Array
	| 	"\x05" e_name binary 	Binary data
	| 	"\x06" e_name 	Undefined — Deprecated
	| 	"\x07" e_name (byte*12) 	ObjectId
	| 	"\x08" e_name "\x00" 	Boolean "false"
	| 	"\x08" e_name "\x01" 	Boolean "true"
	| 	"\x09" e_name int64 	UTC datetime
	| 	"\x0A" e_name 	Null value
	| 	"\x0B" e_name cstring cstring 	Regular expression
	| 	"\x0C" e_name string (byte*12) 	DBPointer — Deprecated
	| 	"\x0D" e_name string 	JavaScript code
	| 	"\x0E" e_name string 	Symbol
	| 	"\x0F" e_name code_w_s 	JavaScript code w/ scope
	| 	"\x10" e_name int32 	32-bit Integer
	| 	"\x11" e_name int64 	Timestamp
	| 	"\x12" e_name int64 	64-bit integer
	| 	"\xFF" e_name 	Min key
	| 	"\x7F" e_name 	Max key
*/
	switch (type) {
		case BSON_DOUBLE:
			return data + sizeof(double);
		case BSON_STRING:
		case BSON_JAVASCRIPT:
		case BSON_SYMBOL:
			length = MONGO_32(*(int*)data);
			return data + sizeof(int32_t) + length;
		case BSON_DOCUMENT:
		case BSON_ARRAY:
			length = MONGO_32(*(int*)data);
			return data + length;
		case BSON_BINARY:
			length = MONGO_32(*(int*)data);
			return data + sizeof(int32_t) + 1 + length;
		case BSON_UNDEFINED:
		case BSON_NULL:
		case BSON_MIN_KEY:
		case BSON_MAX_KEY:
			return data;
		case BSON_OBJECT_ID:
			return data + 12;
		case BSON_BOOLEAN:
			return data + 1;
		case BSON_DATETIME:
		case BSON_TIMESTAMP:
		case BSON_INT64:
			return data + sizeof(int64_t);
		case BSON_REGEXP:
			return strchr(data, '\0') + 1;
		case BSON_DBPOINTER:
			length = MONGO_32(*(int*)data);
			return data + sizeof(int32_t) + length + 12;
		case BSON_JAVASCRIPT_WITH_SCOPE:
			exit(-3); /* TODO */
		case BSON_INT32:
			return data + sizeof(int32_t);
	}
	return NULL;
}
Example #3
0
/* Returns 1 if it worked, and 0 if it didn't. If 0 is returned, *error_message
 * is set and must be free()d. On success *data_buffer is set and must be free()d */
static int mongo_connect_send_packet(mongo_con_manager *manager, mongo_connection *con, mongo_server_options *options, mcon_str *packet, char **data_buffer, char **error_message)
{
	int            read;
	uint32_t       data_size;
	char           reply_buffer[MONGO_REPLY_HEADER_SIZE];
	uint32_t       flags; /* To check for query reply status */

	/* Send and wait for reply */
	if (manager->send(con, options, packet->d, packet->l, error_message) == -1) {
		mcon_str_ptr_dtor(packet);
		return 0;
	}
	mcon_str_ptr_dtor(packet);
	read = manager->recv_header(con, options, options->socketTimeoutMS, reply_buffer, MONGO_REPLY_HEADER_SIZE, error_message);
	if (read < 0) {
		/* Error already populated */
		return 0;
	}

	mongo_manager_log(manager, MLOG_CON, MLOG_FINE, "send_packet: read from header: %d", read);
	if (read < MONGO_REPLY_HEADER_SIZE) {
		*error_message = malloc(256);
		snprintf(*error_message, 256, "send_package: the amount of bytes read (%d) is less than the header size (%d)", read, MONGO_REPLY_HEADER_SIZE);
		return 0;
	}

	/* Read result flags */
	flags = MONGO_32(*(int*)(reply_buffer + sizeof(int32_t) * 4));

	/* Read the rest of the data */
	data_size = MONGO_32(*(int*)(reply_buffer)) - MONGO_REPLY_HEADER_SIZE;
	mongo_manager_log(manager, MLOG_CON, MLOG_FINE, "send_packet: data_size: %d", data_size);

	/* Check size limits */
	if (con->max_bson_size && data_size > (uint32_t)con->max_bson_size) {
		*error_message = malloc(256);
		snprintf(*error_message, 256, "send_package: data corruption: the returned size of the reply (%d) is larger than the maximum allowed size (%d)", data_size, con->max_bson_size);
		return 0;
	}

	/* Read data */
	*data_buffer = malloc(data_size + 1);
	if (manager->recv_data(con, options, options->socketTimeoutMS, *data_buffer, data_size, error_message) <= 0) {
		free(*data_buffer);
		return 0;
	}

	/* Check for a query error */
	if (flags & MONGO_REPLY_FLAG_QUERY_FAILURE) {
		char *ptr = *data_buffer + sizeof(int32_t); /* Skip the length */
		char *err;
		int32_t code;

		/* Find the error */
		if (bson_find_field_as_string(ptr, "$err", &err)) {
			*error_message = malloc(256 + strlen(err));

			if (bson_find_field_as_int32(ptr, "code", &code)) {
				snprintf(*error_message, 256 + strlen(err), "send_package: the query returned a failure: %s (code: %d)", err, code);
			} else {
				snprintf(*error_message, 256 + strlen(err), "send_package: the query returned a failure: %s", err);
			}
		} else {
			*error_message = strdup("send_package: the query returned an unknown error");
		}

		free(*data_buffer);
		return 0;
	}

	return 1;
}
Example #4
0
/*
 * Gets a reply from the MongoDB server and
 * creates a cursor for it
 */
int mongo_link_hear(SV *cursor_sv) {
  int sock;
  int num_returned = 0;
  mongo_cursor *cursor = (mongo_cursor*)perl_mongo_get_ptr_from_instance(cursor_sv);
  SV *link_sv = perl_mongo_call_reader(cursor_sv, "_connection");
  mongo_link *link = (mongo_link*)perl_mongo_get_ptr_from_instance(link_sv);

  if (!check_connection(link)) {
    SvREFCNT_dec(link_sv);
    croak("can't get db response, not connected");
    return 0;
  }
  
  sock = perl_mongo_link_master(link_sv);

  // if this fails, we might be disconnected... but we're probably
  // just out of results
  if (recv(sock, (char*)&cursor->header.length, INT_32, 0) == -1) {
    SvREFCNT_dec(link_sv);
    return 0;
  }

  cursor->header.length = MONGO_32(cursor->header.length);

  // make sure we're not getting crazy data
  if (cursor->header.length > MAX_RESPONSE_LEN ||
      cursor->header.length < REPLY_HEADER_SIZE) {

    set_disconnected(link);

    if (!check_connection(link)) {
      SvREFCNT_dec(link_sv);
      croak("bad response length: %d, max: %d, did the db assert?\n", cursor->header.length, MAX_RESPONSE_LEN);
      return 0;
    }
  }
  
  if (recv(sock, (char*)&cursor->header.request_id, INT_32, 0) == -1 ||
      recv(sock, (char*)&cursor->header.response_to, INT_32, 0) == -1 ||
      recv(sock, (char*)&cursor->header.op, INT_32, 0) == -1 ||
      recv(sock, (char*)&cursor->flag, INT_32, 0) == -1 ||
      recv(sock, (char*)&cursor->cursor_id, INT_64, 0) == -1 ||
      recv(sock, (char*)&cursor->start, INT_32, 0) == -1 ||
      recv(sock, (char*)&num_returned, INT_32, 0) == -1) {
    SvREFCNT_dec(link_sv);
    return 0;
  }

  cursor->header.request_id = MONGO_32(cursor->header.request_id);
  cursor->header.response_to = MONGO_32(cursor->header.response_to);
  cursor->header.op = MONGO_32(cursor->header.op);
  cursor->flag = MONGO_32(cursor->flag);
  cursor->cursor_id = MONGO_64(cursor->cursor_id);
  cursor->start = MONGO_32(cursor->start);
  num_returned = MONGO_32(num_returned);

  // create buf
  cursor->header.length -= INT_32*9;

  // point buf.start at buf's first char
  if (!cursor->buf.start) {
    New(0, cursor->buf.start, cursor->header.length, char);
    cursor->buf.end = cursor->buf.start + cursor->header.length;
  }