bson_ext 1.5.1 → 1.5.2

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,91 +0,0 @@
1
- /*
2
- Copyright (C) 1999, 2002 Aladdin Enterprises. All rights reserved.
3
-
4
- This software is provided 'as-is', without any express or implied
5
- warranty. In no event will the authors be held liable for any damages
6
- arising from the use of this software.
7
-
8
- Permission is granted to anyone to use this software for any purpose,
9
- including commercial applications, and to alter it and redistribute it
10
- freely, subject to the following restrictions:
11
-
12
- 1. The origin of this software must not be misrepresented; you must not
13
- claim that you wrote the original software. If you use this software
14
- in a product, an acknowledgment in the product documentation would be
15
- appreciated but is not required.
16
- 2. Altered source versions must be plainly marked as such, and must not be
17
- misrepresented as being the original software.
18
- 3. This notice may not be removed or altered from any source distribution.
19
-
20
- L. Peter Deutsch
21
- ghost@aladdin.com
22
-
23
- */
24
- /* $Id: md5.h,v 1.4 2002/04/13 19:20:28 lpd Exp $ */
25
- /*
26
- Independent implementation of MD5 (RFC 1321).
27
-
28
- This code implements the MD5 Algorithm defined in RFC 1321, whose
29
- text is available at
30
- http://www.ietf.org/rfc/rfc1321.txt
31
- The code is derived from the text of the RFC, including the test suite
32
- (section A.5) but excluding the rest of Appendix A. It does not include
33
- any code or documentation that is identified in the RFC as being
34
- copyrighted.
35
-
36
- The original and principal author of md5.h is L. Peter Deutsch
37
- <ghost@aladdin.com>. Other authors are noted in the change history
38
- that follows (in reverse chronological order):
39
-
40
- 2002-04-13 lpd Removed support for non-ANSI compilers; removed
41
- references to Ghostscript; clarified derivation from RFC 1321;
42
- now handles byte order either statically or dynamically.
43
- 1999-11-04 lpd Edited comments slightly for automatic TOC extraction.
44
- 1999-10-18 lpd Fixed typo in header comment (ansi2knr rather than md5);
45
- added conditionalization for C++ compilation from Martin
46
- Purschke <purschke@bnl.gov>.
47
- 1999-05-03 lpd Original version.
48
- */
49
-
50
- #ifndef md5_INCLUDED
51
- # define md5_INCLUDED
52
-
53
- /*
54
- * This package supports both compile-time and run-time determination of CPU
55
- * byte order. If ARCH_IS_BIG_ENDIAN is defined as 0, the code will be
56
- * compiled to run only on little-endian CPUs; if ARCH_IS_BIG_ENDIAN is
57
- * defined as non-zero, the code will be compiled to run only on big-endian
58
- * CPUs; if ARCH_IS_BIG_ENDIAN is not defined, the code will be compiled to
59
- * run on either big- or little-endian CPUs, but will run slightly less
60
- * efficiently on either one than if ARCH_IS_BIG_ENDIAN is defined.
61
- */
62
-
63
- typedef unsigned char mongo_md5_byte_t; /* 8-bit byte */
64
- typedef unsigned int mongo_md5_word_t; /* 32-bit word */
65
-
66
- /* Define the state of the MD5 Algorithm. */
67
- typedef struct mongo_md5_state_s {
68
- mongo_md5_word_t count[2]; /* message length in bits, lsw first */
69
- mongo_md5_word_t abcd[4]; /* digest buffer */
70
- mongo_md5_byte_t buf[64]; /* accumulate block */
71
- } mongo_md5_state_t;
72
-
73
- #ifdef __cplusplus
74
- extern "C"
75
- {
76
- #endif
77
-
78
- /* Initialize the algorithm. */
79
- void mongo_md5_init(mongo_md5_state_t *pms);
80
-
81
- /* Append a string to the message. */
82
- void mongo_md5_append(mongo_md5_state_t *pms, const mongo_md5_byte_t *data, int nbytes);
83
-
84
- /* Finish the message and return the digest. */
85
- void mongo_md5_finish(mongo_md5_state_t *pms, mongo_md5_byte_t digest[16]);
86
-
87
- #ifdef __cplusplus
88
- } /* end extern "C" */
89
- #endif
90
-
91
- #endif /* md5_INCLUDED */
@@ -1,1020 +0,0 @@
1
- /* mongo.c */
2
-
3
- /* Copyright 2009, 2010 10gen Inc.
4
- *
5
- * Licensed under the Apache License, Version 2.0 (the "License");
6
- * you may not use this file except in compliance with the License.
7
- * You may obtain a copy of the License at
8
- *
9
- * http://www.apache.org/licenses/LICENSE-2.0
10
- *
11
- * Unless required by applicable law or agreed to in writing, software
12
- * distributed under the License is distributed on an "AS IS" BASIS,
13
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
- * See the License for the specific language governing permissions and
15
- * limitations under the License.
16
- */
17
-
18
- #include "mongo.h"
19
- #include "md5.h"
20
-
21
- #include <stdlib.h>
22
- #include <stdio.h>
23
- #include <errno.h>
24
- #include <string.h>
25
- #include <stdlib.h>
26
- #include <errno.h>
27
-
28
- #ifndef _WIN32
29
- #include <unistd.h>
30
- #endif
31
-
32
- /* only need one of these */
33
- static const int zero = 0;
34
- static const int one = 1;
35
-
36
- /* ----------------------------
37
- message stuff
38
- ------------------------------ */
39
-
40
- static void looping_write(mongo_connection * conn, const void* buf, int len){
41
- const char* cbuf = buf;
42
- while (len){
43
- int sent = send(conn->sock, cbuf, len, 0);
44
- if (sent == -1) MONGO_THROW(MONGO_EXCEPT_NETWORK);
45
- cbuf += sent;
46
- len -= sent;
47
- }
48
- }
49
-
50
- static void looping_read(mongo_connection * conn, void* buf, int len){
51
- char* cbuf = buf;
52
- while (len){
53
- int sent = recv(conn->sock, cbuf, len, 0);
54
- if (sent == 0 || sent == -1) MONGO_THROW(MONGO_EXCEPT_NETWORK);
55
- cbuf += sent;
56
- len -= sent;
57
- }
58
- }
59
-
60
- /* Always calls free(mm) */
61
- void mongo_message_send(mongo_connection * conn, mongo_message* mm){
62
- mongo_header head; /* little endian */
63
- bson_little_endian32(&head.len, &mm->head.len);
64
- bson_little_endian32(&head.id, &mm->head.id);
65
- bson_little_endian32(&head.responseTo, &mm->head.responseTo);
66
- bson_little_endian32(&head.op, &mm->head.op);
67
-
68
- MONGO_TRY{
69
- looping_write(conn, &head, sizeof(head));
70
- looping_write(conn, &mm->data, mm->head.len - sizeof(head));
71
- }MONGO_CATCH{
72
- free(mm);
73
- MONGO_RETHROW();
74
- }
75
- free(mm);
76
- }
77
-
78
- char * mongo_data_append( char * start , const void * data , int len ){
79
- memcpy( start , data , len );
80
- return start + len;
81
- }
82
-
83
- char * mongo_data_append32( char * start , const void * data){
84
- bson_little_endian32( start , data );
85
- return start + 4;
86
- }
87
-
88
- char * mongo_data_append64( char * start , const void * data){
89
- bson_little_endian64( start , data );
90
- return start + 8;
91
- }
92
-
93
- mongo_message * mongo_message_create( int len , int id , int responseTo , int op ){
94
- mongo_message * mm = (mongo_message*)bson_malloc( len );
95
-
96
- if (!id)
97
- id = rand();
98
-
99
- /* native endian (converted on send) */
100
- mm->head.len = len;
101
- mm->head.id = id;
102
- mm->head.responseTo = responseTo;
103
- mm->head.op = op;
104
-
105
- return mm;
106
- }
107
-
108
- /* ----------------------------
109
- connection stuff
110
- ------------------------------ */
111
- #ifdef _MONGO_USE_GETADDRINFO
112
- static int mongo_socket_connect( mongo_connection * conn, const char * host, int port ){
113
-
114
- struct addrinfo* addrs = NULL;
115
- struct addrinfo hints;
116
- char port_str[12];
117
- int ret;
118
-
119
- conn->sock = 0;
120
- conn->connected = 0;
121
-
122
- memset( &hints, 0, sizeof( hints ) );
123
- hints.ai_family = AF_INET;
124
-
125
- sprintf( port_str, "%d", port );
126
-
127
- conn->sock = socket( AF_INET, SOCK_STREAM, 0 );
128
- if ( conn->sock <= 0 ){
129
- mongo_close_socket( conn->sock );
130
- return mongo_conn_no_socket;
131
- }
132
-
133
- ret = getaddrinfo( host, port_str, &hints, &addrs );
134
- if(ret) {
135
- fprintf( stderr, "getaddrinfo failed: %s", gai_strerror( ret ) );
136
- return mongo_conn_fail;
137
- }
138
-
139
- if ( connect( conn->sock, addrs->ai_addr, addrs->ai_addrlen ) ){
140
- mongo_close_socket( conn->sock );
141
- freeaddrinfo( addrs );
142
- return mongo_conn_fail;
143
- }
144
-
145
- setsockopt( conn->sock, IPPROTO_TCP, TCP_NODELAY, (char *) &one, sizeof(one) );
146
-
147
- conn->connected = 1;
148
- freeaddrinfo( addrs );
149
- return 0;
150
- }
151
- #else
152
- static int mongo_socket_connect( mongo_connection * conn, const char * host, int port ){
153
- struct sockaddr_in sa;
154
- socklen_t addressSize;
155
-
156
- memset( sa.sin_zero , 0 , sizeof( sa.sin_zero ) );
157
- sa.sin_family = AF_INET;
158
- sa.sin_port = htons( port );
159
- sa.sin_addr.s_addr = inet_addr( host );
160
- addressSize = sizeof( sa );
161
-
162
- conn->sock = socket( AF_INET, SOCK_STREAM, 0 );
163
- if ( conn->sock <= 0 ){
164
- mongo_close_socket( conn->sock );
165
- return mongo_conn_no_socket;
166
- }
167
-
168
- if ( connect( conn->sock, (struct sockaddr *)&sa, addressSize ) ){
169
- return mongo_conn_fail;
170
- }
171
-
172
- setsockopt( conn->sock, IPPROTO_TCP, TCP_NODELAY, (char *) &one, sizeof(one) );
173
-
174
- conn->connected = 1;
175
- return 0;
176
- }
177
- #endif
178
-
179
- mongo_conn_return mongo_connect( mongo_connection * conn , const char * host, int port ){
180
- MONGO_INIT_EXCEPTION(&conn->exception);
181
- conn->replset = NULL;
182
-
183
- conn->primary = bson_malloc( sizeof( mongo_host_port ) );
184
-
185
- strncpy( conn->primary->host, host, strlen( host ) + 1 );
186
- conn->primary->port = port;
187
- conn->primary->next = NULL;
188
-
189
- return mongo_socket_connect(conn, host, port);
190
- }
191
-
192
- void mongo_replset_init_conn( mongo_connection* conn, const char* name ) {
193
- MONGO_INIT_EXCEPTION(&conn->exception);
194
- conn->replset = bson_malloc( sizeof( mongo_replset ) );
195
- conn->replset->primary_connected = 0;
196
- conn->replset->seeds = NULL;
197
- conn->replset->hosts = NULL;
198
- conn->replset->name = (char *)bson_malloc( sizeof( name ) + 1 );
199
- memcpy( conn->replset->name, name, sizeof( name ) + 1 );
200
-
201
- conn->primary = bson_malloc( sizeof( mongo_host_port ) );
202
- conn->primary = NULL;
203
- }
204
-
205
- static int mongo_replset_add_node( mongo_host_port** list, const char* host, int port ) {
206
- mongo_host_port* host_port = bson_malloc( sizeof( mongo_host_port ) );
207
- host_port->port = port;
208
- host_port->next = NULL;
209
- strncpy( host_port->host, host, strlen(host) + 1 );
210
-
211
- if( *list == NULL )
212
- *list = host_port;
213
- else {
214
- mongo_host_port* p = *list;
215
- while( p->next != NULL )
216
- p = p->next;
217
- p->next = host_port;
218
- }
219
-
220
- return 0;
221
- }
222
-
223
- static int mongo_replset_free_list( mongo_host_port** list ) {
224
- mongo_host_port* node = *list;
225
- mongo_host_port* prev;
226
-
227
- while( node != NULL ) {
228
- prev = node;
229
- node = node->next;
230
- free(prev);
231
- }
232
-
233
- *list = NULL;
234
- return 0;
235
- }
236
-
237
- int mongo_replset_add_seed(mongo_connection* conn, const char* host, int port) {
238
- return mongo_replset_add_node( &conn->replset->seeds, host, port );
239
- }
240
-
241
- static int mongo_replset_check_seed( mongo_connection* conn ) {
242
- bson out;
243
- bson hosts;
244
- const char* data;
245
- bson_iterator it;
246
- bson_iterator it_sub;
247
- const char* host_string;
248
- char* host;
249
- int len, idx, port, split;
250
-
251
- out.data = NULL;
252
- out.owned = 1;
253
-
254
- hosts.data = NULL;
255
- hosts.owned = 1;
256
-
257
- if (mongo_simple_int_command(conn, "admin", "ismaster", 1, &out)) {
258
-
259
- if( bson_find( &it, &out, "hosts" ) ) {
260
- data = bson_iterator_value( &it );
261
- bson_iterator_init( &it_sub, data );
262
-
263
- /* Iterate over host list, adding each host to the
264
- * connection's host list.
265
- */
266
- while( bson_iterator_next( &it_sub ) ) {
267
- host_string = bson_iterator_string( &it_sub );
268
- len = split = idx = 0;
269
-
270
- /* Split the host_port string at the ':' */
271
- while(1) {
272
- if( *(host_string + len) == 0)
273
- break;
274
- if( *(host_string + len) == ':' )
275
- split = len;
276
- len++;
277
- }
278
-
279
- /* If 'split' is set, we know the that port exists;
280
- * Otherwise, we set the default port.
281
- */
282
- if( len > 0 ) {
283
- idx = split ? split : len;
284
- host = (char *)bson_malloc( idx + 1 );
285
- memcpy( host, host_string, idx );
286
- memcpy( host + idx, "\0", 1 );
287
- if( split )
288
- port = atoi( host_string + idx + 1 );
289
- else
290
- port = 27017;
291
-
292
- mongo_replset_add_node( &conn->replset->hosts, host, port );
293
- }
294
- }
295
- }
296
- }
297
-
298
- bson_destroy( &out );
299
- bson_destroy( &hosts );
300
- mongo_close_socket( conn->sock );
301
- conn->sock = 0;
302
- conn->connected = 0;
303
-
304
- return 0;
305
- }
306
-
307
- /* Find out whether the current connected node is master, and
308
- * verify that the node's replica set name matched the provided name
309
- */
310
- static int mongo_replset_check_host( mongo_connection* conn ) {
311
-
312
- bson out;
313
- bson_iterator it;
314
- bson_bool_t ismaster = 0;
315
- const char* set_name;
316
-
317
- out.data = NULL;
318
- out.owned = 1;
319
-
320
- if (mongo_simple_int_command(conn, "admin", "ismaster", 1, &out)) {
321
- if( bson_find(&it, &out, "ismaster") )
322
- ismaster = bson_iterator_bool( &it );
323
-
324
- if( bson_find( &it, &out, "setName" ) ) {
325
- set_name = bson_iterator_string( &it );
326
- if( strcmp( set_name, conn->replset->name ) != 0 ) {
327
- return mongo_conn_bad_set_name;
328
- }
329
- }
330
- }
331
- bson_destroy( &out );
332
-
333
- if(ismaster) {
334
- conn->replset->primary_connected = 1;
335
- }
336
- else {
337
- mongo_close_socket( conn->sock );
338
- }
339
-
340
- return 0;
341
- }
342
-
343
- mongo_conn_return mongo_replset_connect(mongo_connection* conn) {
344
-
345
- int connect_error = 0;
346
- mongo_host_port* node;
347
-
348
- conn->sock = 0;
349
- conn->connected = 0;
350
-
351
- /* First iterate over the seed nodes to get the canonical list of hosts
352
- * from the replica set. Break out once we have a host list.
353
- */
354
- node = conn->replset->seeds;
355
- while( node != NULL ) {
356
- connect_error = mongo_socket_connect( conn, (const char*)&node->host, node->port );
357
-
358
- if( connect_error == 0 ) {
359
- if ( (connect_error = mongo_replset_check_seed( conn )) )
360
- return connect_error;
361
- }
362
-
363
- if( conn->replset->hosts )
364
- break;
365
-
366
- node = node->next;
367
- }
368
-
369
- /* Iterate over the host list, checking for the primary node. */
370
- if( !conn->replset->hosts )
371
- return mongo_conn_cannot_find_primary;
372
- else {
373
- node = conn->replset->hosts;
374
-
375
- while( node != NULL ) {
376
- connect_error = mongo_socket_connect( conn, (const char*)&node->host, node->port );
377
-
378
- if( connect_error == 0 ) {
379
- if ( (connect_error = mongo_replset_check_host( conn )) )
380
- return connect_error;
381
-
382
- /* Primary found, so return. */
383
- else if( conn->replset->primary_connected )
384
- return 0;
385
-
386
- /* No primary, so close the connection. */
387
- else {
388
- mongo_close_socket( conn->sock );
389
- conn->sock = 0;
390
- conn->connected = 0;
391
- }
392
- }
393
-
394
- node = node->next;
395
- }
396
- }
397
-
398
- return mongo_conn_cannot_find_primary;
399
- }
400
-
401
- mongo_conn_return mongo_reconnect( mongo_connection * conn ){
402
- int res;
403
- mongo_disconnect(conn);
404
-
405
- if( conn->replset ) {
406
- conn->replset->primary_connected = 0;
407
- mongo_replset_free_list( &conn->replset->hosts );
408
- conn->replset->hosts = NULL;
409
- res = mongo_replset_connect( conn );
410
- return res;
411
- }
412
- else
413
- return mongo_socket_connect( conn, conn->primary->host, conn->primary->port );
414
- }
415
-
416
- bson_bool_t mongo_disconnect( mongo_connection * conn ){
417
- if( ! conn->connected )
418
- return 1;
419
-
420
- if( conn->replset ) {
421
- conn->replset->primary_connected = 0;
422
- mongo_replset_free_list( &conn->replset->hosts );
423
- conn->replset->hosts = NULL;
424
- return mongo_replset_connect( conn );
425
- }
426
-
427
- mongo_close_socket( conn->sock );
428
-
429
- conn->sock = 0;
430
- conn->connected = 0;
431
-
432
- return 0;
433
- }
434
-
435
- bson_bool_t mongo_destroy( mongo_connection * conn ){
436
- if( conn->replset ) {
437
- mongo_replset_free_list( &conn->replset->seeds );
438
- mongo_replset_free_list( &conn->replset->hosts );
439
- free( conn->replset->name );
440
- free( conn->replset );
441
- conn->replset = NULL;
442
- }
443
-
444
- free( conn->primary );
445
- return mongo_disconnect( conn );
446
- }
447
-
448
- void mongo_insert_batch( mongo_connection * conn , const char * ns , bson ** bsons, int count){
449
- int size = 16 + 4 + strlen( ns ) + 1;
450
- int i;
451
- mongo_message * mm;
452
- char* data;
453
-
454
- for(i=0; i<count; i++){
455
- size += bson_size(bsons[i]);
456
- }
457
-
458
- mm = mongo_message_create( size , 0 , 0 , mongo_op_insert );
459
-
460
- data = &mm->data;
461
- data = mongo_data_append32(data, &zero);
462
- data = mongo_data_append(data, ns, strlen(ns) + 1);
463
-
464
- for(i=0; i<count; i++){
465
- data = mongo_data_append(data, bsons[i]->data, bson_size( bsons[i] ) );
466
- }
467
-
468
- mongo_message_send(conn, mm);
469
- }
470
-
471
- void mongo_insert( mongo_connection * conn , const char * ns , bson * bson ){
472
- char * data;
473
- mongo_message * mm = mongo_message_create( 16 /* header */
474
- + 4 /* ZERO */
475
- + strlen(ns)
476
- + 1 + bson_size(bson)
477
- , 0, 0, mongo_op_insert);
478
-
479
- data = &mm->data;
480
- data = mongo_data_append32(data, &zero);
481
- data = mongo_data_append(data, ns, strlen(ns) + 1);
482
- data = mongo_data_append(data, bson->data, bson_size(bson));
483
-
484
- mongo_message_send(conn, mm);
485
- }
486
-
487
- void mongo_update(mongo_connection* conn, const char* ns, const bson* cond, const bson* op, int flags){
488
- char * data;
489
- mongo_message * mm = mongo_message_create( 16 /* header */
490
- + 4 /* ZERO */
491
- + strlen(ns) + 1
492
- + 4 /* flags */
493
- + bson_size(cond)
494
- + bson_size(op)
495
- , 0 , 0 , mongo_op_update );
496
-
497
- data = &mm->data;
498
- data = mongo_data_append32(data, &zero);
499
- data = mongo_data_append(data, ns, strlen(ns) + 1);
500
- data = mongo_data_append32(data, &flags);
501
- data = mongo_data_append(data, cond->data, bson_size(cond));
502
- data = mongo_data_append(data, op->data, bson_size(op));
503
-
504
- mongo_message_send(conn, mm);
505
- }
506
-
507
- void mongo_remove(mongo_connection* conn, const char* ns, const bson* cond){
508
- char * data;
509
- mongo_message * mm = mongo_message_create( 16 /* header */
510
- + 4 /* ZERO */
511
- + strlen(ns) + 1
512
- + 4 /* ZERO */
513
- + bson_size(cond)
514
- , 0 , 0 , mongo_op_delete );
515
-
516
- data = &mm->data;
517
- data = mongo_data_append32(data, &zero);
518
- data = mongo_data_append(data, ns, strlen(ns) + 1);
519
- data = mongo_data_append32(data, &zero);
520
- data = mongo_data_append(data, cond->data, bson_size(cond));
521
-
522
- mongo_message_send(conn, mm);
523
- }
524
-
525
- mongo_reply * mongo_read_response( mongo_connection * conn ){
526
- mongo_header head; /* header from network */
527
- mongo_reply_fields fields; /* header from network */
528
- mongo_reply * out; /* native endian */
529
- unsigned int len;
530
-
531
- looping_read(conn, &head, sizeof(head));
532
- looping_read(conn, &fields, sizeof(fields));
533
-
534
- bson_little_endian32(&len, &head.len);
535
-
536
- if (len < sizeof(head)+sizeof(fields) || len > 64*1024*1024)
537
- MONGO_THROW(MONGO_EXCEPT_NETWORK); /* most likely corruption */
538
-
539
- out = (mongo_reply*)bson_malloc(len);
540
-
541
- out->head.len = len;
542
- bson_little_endian32(&out->head.id, &head.id);
543
- bson_little_endian32(&out->head.responseTo, &head.responseTo);
544
- bson_little_endian32(&out->head.op, &head.op);
545
-
546
- bson_little_endian32(&out->fields.flag, &fields.flag);
547
- bson_little_endian64(&out->fields.cursorID, &fields.cursorID);
548
- bson_little_endian32(&out->fields.start, &fields.start);
549
- bson_little_endian32(&out->fields.num, &fields.num);
550
-
551
- MONGO_TRY{
552
- looping_read(conn, &out->objs, len-sizeof(head)-sizeof(fields));
553
- }MONGO_CATCH{
554
- free(out);
555
- MONGO_RETHROW();
556
- }
557
-
558
- return out;
559
- }
560
-
561
- mongo_cursor* mongo_find(mongo_connection* conn, const char* ns, bson* query, bson* fields, int nToReturn, int nToSkip, int options){
562
- int sl;
563
- volatile mongo_cursor * cursor; /* volatile due to longjmp in mongo exception handler */
564
- char * data;
565
- mongo_message * mm = mongo_message_create( 16 + /* header */
566
- 4 + /* options */
567
- strlen( ns ) + 1 + /* ns */
568
- 4 + 4 + /* skip,return */
569
- bson_size( query ) +
570
- bson_size( fields ) ,
571
- 0 , 0 , mongo_op_query );
572
-
573
-
574
- data = &mm->data;
575
- data = mongo_data_append32( data , &options );
576
- data = mongo_data_append( data , ns , strlen( ns ) + 1 );
577
- data = mongo_data_append32( data , &nToSkip );
578
- data = mongo_data_append32( data , &nToReturn );
579
- data = mongo_data_append( data , query->data , bson_size( query ) );
580
- if ( fields )
581
- data = mongo_data_append( data , fields->data , bson_size( fields ) );
582
-
583
- bson_fatal_msg( (data == ((char*)mm) + mm->head.len), "query building fail!" );
584
-
585
- mongo_message_send( conn , mm );
586
-
587
- cursor = (mongo_cursor*)bson_malloc(sizeof(mongo_cursor));
588
-
589
- MONGO_TRY{
590
- cursor->mm = mongo_read_response(conn);
591
- }MONGO_CATCH{
592
- free((mongo_cursor*)cursor); /* cast away volatile, not changing type */
593
- MONGO_RETHROW();
594
- }
595
-
596
- sl = strlen(ns)+1;
597
- cursor->ns = bson_malloc(sl);
598
- if (!cursor->ns){
599
- free(cursor->mm);
600
- free((mongo_cursor*)cursor); /* cast away volatile, not changing type */
601
- return 0;
602
- }
603
- memcpy((void*)cursor->ns, ns, sl); /* cast needed to silence GCC warning */
604
- cursor->conn = conn;
605
- cursor->current.data = NULL;
606
- return (mongo_cursor*)cursor;
607
- }
608
-
609
- bson_bool_t mongo_find_one(mongo_connection* conn, const char* ns, bson* query, bson* fields, bson* out){
610
- mongo_cursor* cursor = mongo_find(conn, ns, query, fields, 1, 0, 0);
611
-
612
- if (cursor && mongo_cursor_next(cursor)){
613
- bson_copy(out, &cursor->current);
614
- mongo_cursor_destroy(cursor);
615
- return 1;
616
- }else{
617
- mongo_cursor_destroy(cursor);
618
- return 0;
619
- }
620
- }
621
-
622
- int64_t mongo_count(mongo_connection* conn, const char* db, const char* ns, bson* query){
623
- bson_buffer bb;
624
- bson cmd;
625
- bson out;
626
- int64_t count = -1;
627
-
628
- bson_buffer_init(&bb);
629
- bson_append_string(&bb, "count", ns);
630
- if (query && bson_size(query) > 5) /* not empty */
631
- bson_append_bson(&bb, "query", query);
632
- bson_from_buffer(&cmd, &bb);
633
-
634
- MONGO_TRY{
635
- if(mongo_run_command(conn, db, &cmd, &out)){
636
- bson_iterator it;
637
- if(bson_find(&it, &out, "n"))
638
- count = bson_iterator_long(&it);
639
- }
640
- }MONGO_CATCH{
641
- bson_destroy(&cmd);
642
- MONGO_RETHROW();
643
- }
644
-
645
- bson_destroy(&cmd);
646
- bson_destroy(&out);
647
- return count;
648
- }
649
-
650
-
651
-
652
- bson_bool_t mongo_cursor_get_more(mongo_cursor* cursor){
653
- if (cursor->mm && cursor->mm->fields.cursorID){
654
- mongo_connection* conn = cursor->conn;
655
- char* data;
656
- int sl = strlen(cursor->ns)+1;
657
- mongo_message * mm = mongo_message_create(16 /*header*/
658
- +4 /*ZERO*/
659
- +sl
660
- +4 /*numToReturn*/
661
- +8 /*cursorID*/
662
- , 0, 0, mongo_op_get_more);
663
- data = &mm->data;
664
- data = mongo_data_append32(data, &zero);
665
- data = mongo_data_append(data, cursor->ns, sl);
666
- data = mongo_data_append32(data, &zero);
667
- data = mongo_data_append64(data, &cursor->mm->fields.cursorID);
668
- mongo_message_send(conn, mm);
669
-
670
- free(cursor->mm);
671
-
672
- MONGO_TRY{
673
- cursor->mm = mongo_read_response(cursor->conn);
674
- }MONGO_CATCH{
675
- cursor->mm = NULL;
676
- mongo_cursor_destroy(cursor);
677
- MONGO_RETHROW();
678
- }
679
-
680
- return cursor->mm && cursor->mm->fields.num;
681
- } else{
682
- return 0;
683
- }
684
- }
685
-
686
- bson_bool_t mongo_cursor_next(mongo_cursor* cursor){
687
- char* bson_addr;
688
-
689
- /* no data */
690
- if (!cursor->mm || cursor->mm->fields.num == 0)
691
- return 0;
692
-
693
- /* first */
694
- if (cursor->current.data == NULL){
695
- bson_init(&cursor->current, &cursor->mm->objs, 0);
696
- return 1;
697
- }
698
-
699
- bson_addr = cursor->current.data + bson_size(&cursor->current);
700
- if (bson_addr >= ((char*)cursor->mm + cursor->mm->head.len)){
701
- if (!mongo_cursor_get_more(cursor))
702
- return 0;
703
- bson_init(&cursor->current, &cursor->mm->objs, 0);
704
- } else {
705
- bson_init(&cursor->current, bson_addr, 0);
706
- }
707
-
708
- return 1;
709
- }
710
-
711
- void mongo_cursor_destroy(mongo_cursor* cursor){
712
- if (!cursor) return;
713
-
714
- if (cursor->mm && cursor->mm->fields.cursorID){
715
- mongo_connection* conn = cursor->conn;
716
- mongo_message * mm = mongo_message_create(16 /*header*/
717
- +4 /*ZERO*/
718
- +4 /*numCursors*/
719
- +8 /*cursorID*/
720
- , 0, 0, mongo_op_kill_cursors);
721
- char* data = &mm->data;
722
- data = mongo_data_append32(data, &zero);
723
- data = mongo_data_append32(data, &one);
724
- data = mongo_data_append64(data, &cursor->mm->fields.cursorID);
725
-
726
- MONGO_TRY{
727
- mongo_message_send(conn, mm);
728
- }MONGO_CATCH{
729
- free(cursor->mm);
730
- free((void*)cursor->ns);
731
- free(cursor);
732
- MONGO_RETHROW();
733
- }
734
- }
735
-
736
- free(cursor->mm);
737
- free((void*)cursor->ns);
738
- free(cursor);
739
- }
740
-
741
- bson_bool_t mongo_create_index(mongo_connection * conn, const char * ns, bson * key, int options, bson * out){
742
- bson_buffer bb;
743
- bson b;
744
- bson_iterator it;
745
- char name[255] = {'_'};
746
- int i = 1;
747
- char idxns[1024];
748
-
749
- bson_iterator_init(&it, key->data);
750
- while(i < 255 && bson_iterator_next(&it)){
751
- strncpy(name + i, bson_iterator_key(&it), 255 - i);
752
- i += strlen(bson_iterator_key(&it));
753
- }
754
- name[254] = '\0';
755
-
756
- bson_buffer_init(&bb);
757
- bson_append_bson(&bb, "key", key);
758
- bson_append_string(&bb, "ns", ns);
759
- bson_append_string(&bb, "name", name);
760
- if (options & MONGO_INDEX_UNIQUE)
761
- bson_append_bool(&bb, "unique", 1);
762
- if (options & MONGO_INDEX_DROP_DUPS)
763
- bson_append_bool(&bb, "dropDups", 1);
764
-
765
- bson_from_buffer(&b, &bb);
766
-
767
- strncpy(idxns, ns, 1024-16);
768
- strcpy(strchr(idxns, '.'), ".system.indexes");
769
- mongo_insert(conn, idxns, &b);
770
- bson_destroy(&b);
771
-
772
- *strchr(idxns, '.') = '\0'; /* just db not ns */
773
- return !mongo_cmd_get_last_error(conn, idxns, out);
774
- }
775
- bson_bool_t mongo_create_simple_index(mongo_connection * conn, const char * ns, const char* field, int options, bson * out){
776
- bson_buffer bb;
777
- bson b;
778
- bson_bool_t success;
779
-
780
- bson_buffer_init(&bb);
781
- bson_append_int(&bb, field, 1);
782
- bson_from_buffer(&b, &bb);
783
-
784
- success = mongo_create_index(conn, ns, &b, options, out);
785
- bson_destroy(&b);
786
- return success;
787
- }
788
-
789
- bson_bool_t mongo_run_command(mongo_connection * conn, const char * db, bson * command, bson * out){
790
- bson fields;
791
- int sl = strlen(db);
792
- char* ns = bson_malloc(sl + 5 + 1); /* ".$cmd" + nul */
793
- bson_bool_t success;
794
-
795
- strcpy(ns, db);
796
- strcpy(ns+sl, ".$cmd");
797
-
798
- success = mongo_find_one(conn, ns, command, bson_empty(&fields), out);
799
- free(ns);
800
- return success;
801
- }
802
-
803
- bson_bool_t mongo_simple_int_command(mongo_connection * conn, const char * db, const char* cmdstr, int arg, bson * realout){
804
- bson out;
805
- bson cmd;
806
- bson_buffer bb;
807
- bson_bool_t success = 0;
808
-
809
- bson_buffer_init(&bb);
810
- bson_append_int(&bb, cmdstr, arg);
811
- bson_from_buffer(&cmd, &bb);
812
-
813
- if(mongo_run_command(conn, db, &cmd, &out)){
814
- bson_iterator it;
815
- if(bson_find(&it, &out, "ok"))
816
- success = bson_iterator_bool(&it);
817
- }
818
-
819
- bson_destroy(&cmd);
820
-
821
- if (realout)
822
- *realout = out;
823
- else
824
- bson_destroy(&out);
825
-
826
- return success;
827
- }
828
-
829
- bson_bool_t mongo_simple_str_command(mongo_connection * conn, const char * db, const char* cmdstr, const char* arg, bson * realout){
830
- bson out;
831
- bson cmd;
832
- bson_buffer bb;
833
- bson_bool_t success = 0;
834
-
835
- bson_buffer_init(&bb);
836
- bson_append_string(&bb, cmdstr, arg);
837
- bson_from_buffer(&cmd, &bb);
838
-
839
- if(mongo_run_command(conn, db, &cmd, &out)){
840
- bson_iterator it;
841
- if(bson_find(&it, &out, "ok"))
842
- success = bson_iterator_bool(&it);
843
- }
844
-
845
- bson_destroy(&cmd);
846
-
847
- if (realout)
848
- *realout = out;
849
- else
850
- bson_destroy(&out);
851
-
852
- return success;
853
- }
854
-
855
- bson_bool_t mongo_cmd_drop_db(mongo_connection * conn, const char * db){
856
- return mongo_simple_int_command(conn, db, "dropDatabase", 1, NULL);
857
- }
858
-
859
- bson_bool_t mongo_cmd_drop_collection(mongo_connection * conn, const char * db, const char * collection, bson * out){
860
- return mongo_simple_str_command(conn, db, "drop", collection, out);
861
- }
862
-
863
- void mongo_cmd_reset_error(mongo_connection * conn, const char * db){
864
- mongo_simple_int_command(conn, db, "reseterror", 1, NULL);
865
- }
866
-
867
- static bson_bool_t mongo_cmd_get_error_helper(mongo_connection * conn, const char * db, bson * realout, const char * cmdtype){
868
- bson out = {NULL,0};
869
- bson_bool_t haserror = 1;
870
-
871
-
872
- if(mongo_simple_int_command(conn, db, cmdtype, 1, &out)){
873
- bson_iterator it;
874
- haserror = (bson_find(&it, &out, "err") != bson_null);
875
- }
876
-
877
- if(realout)
878
- *realout = out; /* transfer of ownership */
879
- else
880
- bson_destroy(&out);
881
-
882
- return haserror;
883
- }
884
-
885
- bson_bool_t mongo_cmd_get_prev_error(mongo_connection * conn, const char * db, bson * out){
886
- return mongo_cmd_get_error_helper(conn, db, out, "getpreverror");
887
- }
888
- bson_bool_t mongo_cmd_get_last_error(mongo_connection * conn, const char * db, bson * out){
889
- return mongo_cmd_get_error_helper(conn, db, out, "getlasterror");
890
- }
891
-
892
- bson_bool_t mongo_cmd_ismaster(mongo_connection * conn, bson * realout){
893
- bson out = {NULL,0};
894
- bson_bool_t ismaster = 0;
895
-
896
- if (mongo_simple_int_command(conn, "admin", "ismaster", 1, &out)){
897
- bson_iterator it;
898
- bson_find(&it, &out, "ismaster");
899
- ismaster = bson_iterator_bool(&it);
900
- }
901
-
902
- if(realout)
903
- *realout = out; /* transfer of ownership */
904
- else
905
- bson_destroy(&out);
906
-
907
- return ismaster;
908
- }
909
-
910
- static void digest2hex(mongo_md5_byte_t digest[16], char hex_digest[33]){
911
- static const char hex[16] = {'0','1','2','3','4','5','6','7','8','9','a','b','c','d','e','f'};
912
- int i;
913
- for (i=0; i<16; i++){
914
- hex_digest[2*i] = hex[(digest[i] & 0xf0) >> 4];
915
- hex_digest[2*i + 1] = hex[ digest[i] & 0x0f ];
916
- }
917
- hex_digest[32] = '\0';
918
- }
919
-
920
- static void mongo_pass_digest(const char* user, const char* pass, char hex_digest[33]){
921
- mongo_md5_state_t st;
922
- mongo_md5_byte_t digest[16];
923
-
924
- mongo_md5_init(&st);
925
- mongo_md5_append(&st, (const mongo_md5_byte_t*)user, strlen(user));
926
- mongo_md5_append(&st, (const mongo_md5_byte_t*)":mongo:", 7);
927
- mongo_md5_append(&st, (const mongo_md5_byte_t*)pass, strlen(pass));
928
- mongo_md5_finish(&st, digest);
929
- digest2hex(digest, hex_digest);
930
- }
931
-
932
- void mongo_cmd_add_user(mongo_connection* conn, const char* db, const char* user, const char* pass){
933
- bson_buffer bb;
934
- bson user_obj;
935
- bson pass_obj;
936
- char hex_digest[33];
937
- char* ns = bson_malloc(strlen(db) + strlen(".system.users") + 1);
938
-
939
- strcpy(ns, db);
940
- strcpy(ns+strlen(db), ".system.users");
941
-
942
- mongo_pass_digest(user, pass, hex_digest);
943
-
944
- bson_buffer_init(&bb);
945
- bson_append_string(&bb, "user", user);
946
- bson_from_buffer(&user_obj, &bb);
947
-
948
- bson_buffer_init(&bb);
949
- bson_append_start_object(&bb, "$set");
950
- bson_append_string(&bb, "pwd", hex_digest);
951
- bson_append_finish_object(&bb);
952
- bson_from_buffer(&pass_obj, &bb);
953
-
954
-
955
- MONGO_TRY{
956
- mongo_update(conn, ns, &user_obj, &pass_obj, MONGO_UPDATE_UPSERT);
957
- }MONGO_CATCH{
958
- free(ns);
959
- bson_destroy(&user_obj);
960
- bson_destroy(&pass_obj);
961
- MONGO_RETHROW();
962
- }
963
-
964
- free(ns);
965
- bson_destroy(&user_obj);
966
- bson_destroy(&pass_obj);
967
- }
968
-
969
- bson_bool_t mongo_cmd_authenticate(mongo_connection* conn, const char* db, const char* user, const char* pass){
970
- bson_buffer bb;
971
- bson from_db, auth_cmd;
972
- const char* nonce;
973
- bson_bool_t success = 0;
974
-
975
- mongo_md5_state_t st;
976
- mongo_md5_byte_t digest[16];
977
- char hex_digest[33];
978
-
979
- if (mongo_simple_int_command(conn, db, "getnonce", 1, &from_db)){
980
- bson_iterator it;
981
- bson_find(&it, &from_db, "nonce");
982
- nonce = bson_iterator_string(&it);
983
- }else{
984
- return 0;
985
- }
986
-
987
- mongo_pass_digest(user, pass, hex_digest);
988
-
989
- mongo_md5_init(&st);
990
- mongo_md5_append(&st, (const mongo_md5_byte_t*)nonce, strlen(nonce));
991
- mongo_md5_append(&st, (const mongo_md5_byte_t*)user, strlen(user));
992
- mongo_md5_append(&st, (const mongo_md5_byte_t*)hex_digest, 32);
993
- mongo_md5_finish(&st, digest);
994
- digest2hex(digest, hex_digest);
995
-
996
- bson_buffer_init(&bb);
997
- bson_append_int(&bb, "authenticate", 1);
998
- bson_append_string(&bb, "user", user);
999
- bson_append_string(&bb, "nonce", nonce);
1000
- bson_append_string(&bb, "key", hex_digest);
1001
- bson_from_buffer(&auth_cmd, &bb);
1002
-
1003
- bson_destroy(&from_db);
1004
-
1005
- MONGO_TRY{
1006
- if(mongo_run_command(conn, db, &auth_cmd, &from_db)){
1007
- bson_iterator it;
1008
- if(bson_find(&it, &from_db, "ok"))
1009
- success = bson_iterator_bool(&it);
1010
- }
1011
- }MONGO_CATCH{
1012
- bson_destroy(&auth_cmd);
1013
- MONGO_RETHROW();
1014
- }
1015
-
1016
- bson_destroy(&from_db);
1017
- bson_destroy(&auth_cmd);
1018
-
1019
- return success;
1020
- }