mirror of
https://github.com/signalwire/freeswitch.git
synced 2025-04-14 08:05:37 +00:00
add MongoDB CDR module
This commit is contained in:
parent
aff4bcbe12
commit
a91691999d
9
src/mod/event_handlers/mod_cdr_mongodb/Makefile
Normal file
9
src/mod/event_handlers/mod_cdr_mongodb/Makefile
Normal file
@ -0,0 +1,9 @@
|
||||
include ../../../../build/modmake.rules
|
||||
|
||||
MONGODB_DRIVER=./driver/src
|
||||
LOCAL_CFLAGS=-I$(MONGODB_DRIVER)
|
||||
LOCAL_OBJS=$(MONGODB_DRIVER)/md5.o \
|
||||
$(MONGODB_DRIVER)/mongo.o $(MONGODB_DRIVER)/net.o \
|
||||
$(MONGODB_DRIVER)/bson.o $(MONGODB_DRIVER)/numbers.o $(MONGODB_DRIVER)/encoding.o \
|
||||
|
||||
local_depend: $(LOCAL_OBJS)
|
202
src/mod/event_handlers/mod_cdr_mongodb/driver/APACHE-2.0.txt
Normal file
202
src/mod/event_handlers/mod_cdr_mongodb/driver/APACHE-2.0.txt
Normal file
@ -0,0 +1,202 @@
|
||||
|
||||
Apache License
|
||||
Version 2.0, January 2004
|
||||
http://www.apache.org/licenses/
|
||||
|
||||
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
||||
|
||||
1. Definitions.
|
||||
|
||||
"License" shall mean the terms and conditions for use, reproduction,
|
||||
and distribution as defined by Sections 1 through 9 of this document.
|
||||
|
||||
"Licensor" shall mean the copyright owner or entity authorized by
|
||||
the copyright owner that is granting the License.
|
||||
|
||||
"Legal Entity" shall mean the union of the acting entity and all
|
||||
other entities that control, are controlled by, or are under common
|
||||
control with that entity. For the purposes of this definition,
|
||||
"control" means (i) the power, direct or indirect, to cause the
|
||||
direction or management of such entity, whether by contract or
|
||||
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
||||
outstanding shares, or (iii) beneficial ownership of such entity.
|
||||
|
||||
"You" (or "Your") shall mean an individual or Legal Entity
|
||||
exercising permissions granted by this License.
|
||||
|
||||
"Source" form shall mean the preferred form for making modifications,
|
||||
including but not limited to software source code, documentation
|
||||
source, and configuration files.
|
||||
|
||||
"Object" form shall mean any form resulting from mechanical
|
||||
transformation or translation of a Source form, including but
|
||||
not limited to compiled object code, generated documentation,
|
||||
and conversions to other media types.
|
||||
|
||||
"Work" shall mean the work of authorship, whether in Source or
|
||||
Object form, made available under the License, as indicated by a
|
||||
copyright notice that is included in or attached to the work
|
||||
(an example is provided in the Appendix below).
|
||||
|
||||
"Derivative Works" shall mean any work, whether in Source or Object
|
||||
form, that is based on (or derived from) the Work and for which the
|
||||
editorial revisions, annotations, elaborations, or other modifications
|
||||
represent, as a whole, an original work of authorship. For the purposes
|
||||
of this License, Derivative Works shall not include works that remain
|
||||
separable from, or merely link (or bind by name) to the interfaces of,
|
||||
the Work and Derivative Works thereof.
|
||||
|
||||
"Contribution" shall mean any work of authorship, including
|
||||
the original version of the Work and any modifications or additions
|
||||
to that Work or Derivative Works thereof, that is intentionally
|
||||
submitted to Licensor for inclusion in the Work by the copyright owner
|
||||
or by an individual or Legal Entity authorized to submit on behalf of
|
||||
the copyright owner. For the purposes of this definition, "submitted"
|
||||
means any form of electronic, verbal, or written communication sent
|
||||
to the Licensor or its representatives, including but not limited to
|
||||
communication on electronic mailing lists, source code control systems,
|
||||
and issue tracking systems that are managed by, or on behalf of, the
|
||||
Licensor for the purpose of discussing and improving the Work, but
|
||||
excluding communication that is conspicuously marked or otherwise
|
||||
designated in writing by the copyright owner as "Not a Contribution."
|
||||
|
||||
"Contributor" shall mean Licensor and any individual or Legal Entity
|
||||
on behalf of whom a Contribution has been received by Licensor and
|
||||
subsequently incorporated within the Work.
|
||||
|
||||
2. Grant of Copyright License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
copyright license to reproduce, prepare Derivative Works of,
|
||||
publicly display, publicly perform, sublicense, and distribute the
|
||||
Work and such Derivative Works in Source or Object form.
|
||||
|
||||
3. Grant of Patent License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
(except as stated in this section) patent license to make, have made,
|
||||
use, offer to sell, sell, import, and otherwise transfer the Work,
|
||||
where such license applies only to those patent claims licensable
|
||||
by such Contributor that are necessarily infringed by their
|
||||
Contribution(s) alone or by combination of their Contribution(s)
|
||||
with the Work to which such Contribution(s) was submitted. If You
|
||||
institute patent litigation against any entity (including a
|
||||
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
||||
or a Contribution incorporated within the Work constitutes direct
|
||||
or contributory patent infringement, then any patent licenses
|
||||
granted to You under this License for that Work shall terminate
|
||||
as of the date such litigation is filed.
|
||||
|
||||
4. Redistribution. You may reproduce and distribute copies of the
|
||||
Work or Derivative Works thereof in any medium, with or without
|
||||
modifications, and in Source or Object form, provided that You
|
||||
meet the following conditions:
|
||||
|
||||
(a) You must give any other recipients of the Work or
|
||||
Derivative Works a copy of this License; and
|
||||
|
||||
(b) You must cause any modified files to carry prominent notices
|
||||
stating that You changed the files; and
|
||||
|
||||
(c) You must retain, in the Source form of any Derivative Works
|
||||
that You distribute, all copyright, patent, trademark, and
|
||||
attribution notices from the Source form of the Work,
|
||||
excluding those notices that do not pertain to any part of
|
||||
the Derivative Works; and
|
||||
|
||||
(d) If the Work includes a "NOTICE" text file as part of its
|
||||
distribution, then any Derivative Works that You distribute must
|
||||
include a readable copy of the attribution notices contained
|
||||
within such NOTICE file, excluding those notices that do not
|
||||
pertain to any part of the Derivative Works, in at least one
|
||||
of the following places: within a NOTICE text file distributed
|
||||
as part of the Derivative Works; within the Source form or
|
||||
documentation, if provided along with the Derivative Works; or,
|
||||
within a display generated by the Derivative Works, if and
|
||||
wherever such third-party notices normally appear. The contents
|
||||
of the NOTICE file are for informational purposes only and
|
||||
do not modify the License. You may add Your own attribution
|
||||
notices within Derivative Works that You distribute, alongside
|
||||
or as an addendum to the NOTICE text from the Work, provided
|
||||
that such additional attribution notices cannot be construed
|
||||
as modifying the License.
|
||||
|
||||
You may add Your own copyright statement to Your modifications and
|
||||
may provide additional or different license terms and conditions
|
||||
for use, reproduction, or distribution of Your modifications, or
|
||||
for any such Derivative Works as a whole, provided Your use,
|
||||
reproduction, and distribution of the Work otherwise complies with
|
||||
the conditions stated in this License.
|
||||
|
||||
5. Submission of Contributions. Unless You explicitly state otherwise,
|
||||
any Contribution intentionally submitted for inclusion in the Work
|
||||
by You to the Licensor shall be under the terms and conditions of
|
||||
this License, without any additional terms or conditions.
|
||||
Notwithstanding the above, nothing herein shall supersede or modify
|
||||
the terms of any separate license agreement you may have executed
|
||||
with Licensor regarding such Contributions.
|
||||
|
||||
6. Trademarks. This License does not grant permission to use the trade
|
||||
names, trademarks, service marks, or product names of the Licensor,
|
||||
except as required for reasonable and customary use in describing the
|
||||
origin of the Work and reproducing the content of the NOTICE file.
|
||||
|
||||
7. Disclaimer of Warranty. Unless required by applicable law or
|
||||
agreed to in writing, Licensor provides the Work (and each
|
||||
Contributor provides its Contributions) on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
implied, including, without limitation, any warranties or conditions
|
||||
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
||||
PARTICULAR PURPOSE. You are solely responsible for determining the
|
||||
appropriateness of using or redistributing the Work and assume any
|
||||
risks associated with Your exercise of permissions under this License.
|
||||
|
||||
8. Limitation of Liability. In no event and under no legal theory,
|
||||
whether in tort (including negligence), contract, or otherwise,
|
||||
unless required by applicable law (such as deliberate and grossly
|
||||
negligent acts) or agreed to in writing, shall any Contributor be
|
||||
liable to You for damages, including any direct, indirect, special,
|
||||
incidental, or consequential damages of any character arising as a
|
||||
result of this License or out of the use or inability to use the
|
||||
Work (including but not limited to damages for loss of goodwill,
|
||||
work stoppage, computer failure or malfunction, or any and all
|
||||
other commercial damages or losses), even if such Contributor
|
||||
has been advised of the possibility of such damages.
|
||||
|
||||
9. Accepting Warranty or Additional Liability. While redistributing
|
||||
the Work or Derivative Works thereof, You may choose to offer,
|
||||
and charge a fee for, acceptance of support, warranty, indemnity,
|
||||
or other liability obligations and/or rights consistent with this
|
||||
License. However, in accepting such obligations, You may act only
|
||||
on Your own behalf and on Your sole responsibility, not on behalf
|
||||
of any other Contributor, and only if You agree to indemnify,
|
||||
defend, and hold each Contributor harmless for any liability
|
||||
incurred by, or claims asserted against, such Contributor by reason
|
||||
of your accepting any such warranty or additional liability.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
APPENDIX: How to apply the Apache License to your work.
|
||||
|
||||
To apply the Apache License to your work, attach the following
|
||||
boilerplate notice, with the fields enclosed by brackets "[]"
|
||||
replaced with your own identifying information. (Don't include
|
||||
the brackets!) The text should be enclosed in the appropriate
|
||||
comment syntax for the file format. We also recommend that a
|
||||
file or class name and description of purpose be included on the
|
||||
same "printed page" as the copyright notice for easier
|
||||
identification within third-party archives.
|
||||
|
||||
Copyright [yyyy] [name of copyright owner]
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
139
src/mod/event_handlers/mod_cdr_mongodb/driver/HISTORY.md
Normal file
139
src/mod/event_handlers/mod_cdr_mongodb/driver/HISTORY.md
Normal file
@ -0,0 +1,139 @@
|
||||
# MongoDB C Driver History
|
||||
|
||||
## 0.4
|
||||
|
||||
THIS RELEASE INCLUDES NUMEROUS BACKWARD-BREAKING CHANGES.
|
||||
These changes have been made for extensibility, consistency,
|
||||
and ease of use. Please read the following release notes
|
||||
carefully, and study the updated tutorial.
|
||||
|
||||
API Principles:
|
||||
|
||||
1. Present a consistent interface for all objects: connections,
|
||||
cursors, bson objects, and bson iterators.
|
||||
2. Require no knowledge of an object's implementation to use the API.
|
||||
3. Allow users to allocate objects on the stack or on the heap.
|
||||
4. Integrate API with new error reporting strategy.
|
||||
5. Be concise, except where it impairs clarity.
|
||||
|
||||
Changes:
|
||||
|
||||
* mongo_replset_init_conn has been renamed to mongo_replset_init.
|
||||
* bson_buffer has been removed. All functions for building bson
|
||||
objects now take objects of type bson. The new pattern looks like this:
|
||||
|
||||
Example:
|
||||
|
||||
bson b[1];
|
||||
bson_init( b );
|
||||
bson_append_int( b, "foo", 1 );
|
||||
bson_finish( b );
|
||||
/* The object is ready to use.
|
||||
When finished, destroy it. */
|
||||
bson_destroy( b );
|
||||
|
||||
* mongo_connection has been renamed to mongo.
|
||||
|
||||
Example:
|
||||
|
||||
mongo conn[1];
|
||||
mongo_connect( conn, '127.0.0.1', 27017 );
|
||||
/* Connection is ready. Destroy when down. */
|
||||
mongo_destroy( conn );
|
||||
|
||||
* New cursor builder API for clearer code:
|
||||
|
||||
Example:
|
||||
|
||||
mongo_cursor cursor[1];
|
||||
mongo_cursor_init( cursor, conn, "test.foo" );
|
||||
|
||||
bson query[1];
|
||||
|
||||
bson_init( query );
|
||||
bson_append_int( query, "bar", 1 );
|
||||
bson_finish( query );
|
||||
|
||||
bson fields[1];
|
||||
|
||||
bson_init( fields );
|
||||
bson_append_int( fields, "baz", 1 );
|
||||
bson_finish( fields );
|
||||
|
||||
mongo_cursor_set_query( cursor, query );
|
||||
mongo_cursor_set_fields( cursor, fields );
|
||||
mongo_cursor_set_limit( cursor, 10 );
|
||||
mongo_cursor_set_skip( cursor, 10 );
|
||||
|
||||
while( mongo_cursor_next( cursor ) == MONGO_OK )
|
||||
bson_print( mongo_cursor_bson( cursor ) );
|
||||
|
||||
* bson_iterator_init now takes a (bson*) instead of a (const char*). This is consistent
|
||||
with bson_find, which also takes a (bson*). If you want to initiate a bson iterator
|
||||
with a buffer, use the new function bson_iterator_from_buffer.
|
||||
* With the addition of the mongo_cursor_bson function, it's now no
|
||||
longer necessary to know how bson and mongo_cursor objects are implemented.
|
||||
|
||||
Example:
|
||||
|
||||
bson b[1];
|
||||
bson_iterator i[1];
|
||||
|
||||
bson_iterator_init( i, b );
|
||||
|
||||
/* With a cursor */
|
||||
bson_iterator_init( i, mongo_cursor_bson( cursor ) );
|
||||
|
||||
* Added mongo_cursor_data and bson_data functions, which return the
|
||||
raw bson buffer as a (const char *).
|
||||
* All constants that were once lower case are now
|
||||
upper case. These include: MONGO_OP_MSG, MONGO_OP_UPDATE, MONGO_OP_INSERT,
|
||||
MONGO_OP_QUERY, MONGO_OP_GET_MORE, MONGO_OP_DELETE, MONGO_OP_KILL_CURSORS
|
||||
BSON_EOO, BSON_DOUBLE, BSON_STRING, BSON_OBJECT, BSON_ARRAY, BSON_BINDATA,
|
||||
BSON_UNDEFINED, BSON_OID, BSON_BOOL, BSON_DATE, BSON_NULL, BSON_REGEX, BSON_DBREF,
|
||||
BSON_CODE, BSON_SYMBOL, BSON_CODEWSCOPE, BSON_INT, BSON_TIMESTAMP, BSON_LONG,
|
||||
MONGO_CONN_SUCCESS, MONGO_CONN_BAD_ARG, MONGO_CONN_NO_SOCKET, MONGO_CONN_FAIL,
|
||||
MONGO_CONN_NOT_MASTER, MONGO_CONN_BAD_SET_NAME, MONGO_CONN_CANNOT_FIND_PRIMARY
|
||||
If your programs use any of these constants, you must convert them to their
|
||||
upper case forms, or you will see compile errors.
|
||||
* The error handling strategy has been changed. Exceptions are not longer being used.
|
||||
* Functions taking a mongo_connection object now return either MONGO_OK or MONGO_ERROR.
|
||||
In case of an error, an error code of type mongo_error_t will be indicated on the
|
||||
mongo_connection->err field.
|
||||
* Functions taking a bson object now return either BSON_OK or BSON_ERROR.
|
||||
In case of an error, an error code of type bson_validity_t will be indicated on the
|
||||
bson->err or bson_buffer->err field.
|
||||
* Calls to mongo_cmd_get_last_error store the error status on the
|
||||
mongo->lasterrcode and mongo->lasterrstr fields.
|
||||
* bson_print now prints all types.
|
||||
* Users may now set custom malloc, realloc, free, printf, sprintf, and fprintf fields.
|
||||
* Groundwork for modules for supporting platform-specific features (e.g., socket timeouts).
|
||||
* Added mongo_set_op_timeout for setting socket timeout. To take advantage of this, you must
|
||||
compile with --use-platform=LINUX. The compiles with platform/linux/net.h instead of the
|
||||
top-level net.h.
|
||||
* Fixed tailable cursors.
|
||||
* GridFS API is now in-line with the new driver API. In particular, all of the
|
||||
following functions now return MONGO_OK or MONGO_ERROR: gridfs_init,
|
||||
gridfile_init, gridfile_writer_done, gridfs_store_buffer, gridfs_store_file,
|
||||
and gridfs_find_query.
|
||||
* Fixed a few memory leaks.
|
||||
|
||||
## 0.3
|
||||
2011-4-14
|
||||
|
||||
* Support replica sets.
|
||||
* Better standard connection API.
|
||||
* GridFS write buffers iteratively.
|
||||
* Fixes for working with large GridFS files (> 3GB)
|
||||
* bson_append_string_n and family (Gergely Nagy)
|
||||
|
||||
## 0.2
|
||||
2011-2-11
|
||||
|
||||
* GridFS support (Chris Triolo).
|
||||
* BSON Timestamp type support.
|
||||
|
||||
## 0.1
|
||||
2009-11-30
|
||||
|
||||
* Initial release.
|
60
src/mod/event_handlers/mod_cdr_mongodb/driver/README.md
Normal file
60
src/mod/event_handlers/mod_cdr_mongodb/driver/README.md
Normal file
@ -0,0 +1,60 @@
|
||||
# MongoDB C Driver
|
||||
|
||||
This is then 10gen-supported MongoDB C driver. There are two goals for this driver.
|
||||
The first is to provide a strict, default compilation option for ultimate portability,
|
||||
no dependencies, and generic embeddability.
|
||||
|
||||
The second is to support more advanced, platform-specific features, like socket timeout,
|
||||
by providing an interface for platform-specific modules.
|
||||
|
||||
Until the 1.0 release, this driver should be considered alpha. Keep in mind that the API will be in flux until then.
|
||||
|
||||
# Building
|
||||
|
||||
First check out the version you want to build. *Always build from a particular tag, since HEAD may be
|
||||
a work in progress.* For example, to build version 0.4, run:
|
||||
|
||||
git checkout v0.4
|
||||
|
||||
You can then build the driver with scons:
|
||||
|
||||
scons
|
||||
|
||||
## Running the tests
|
||||
Make sure that you're running mongod on 127.0.0.1 on the default port (27017). The replica set
|
||||
test assumes a replica set with at least three nodes running at 127.0.0.1 and starting at port
|
||||
30000. Note that the driver does not recognize 'localhost' as a valid host name.
|
||||
|
||||
To compile and run the tests:
|
||||
|
||||
scons test
|
||||
|
||||
# Error Handling
|
||||
Most functions return MONGO_OK or BSON_OK on success and MONGO_ERROR or BSON_ERROR on failure.
|
||||
Specific error codes and error strings are then stored in the `err` and `errstr` fields of the
|
||||
`mongo` and `bson` objects. It is the client's responsibility to check for errors and handle
|
||||
them appropriately.
|
||||
|
||||
# Docs
|
||||
The docs are built using Sphinx and Doxygen. If you have these tools installed, then
|
||||
you can build the docs with scons:
|
||||
|
||||
scons docs
|
||||
|
||||
The html docs will appear in docs/html.
|
||||
|
||||
# ISSUES
|
||||
|
||||
You can report bugs, request new features, and view this driver's roadmap
|
||||
using [JIRA](http://jira.mongodb.org/browse/CDRIVER).
|
||||
|
||||
# CREDITS
|
||||
|
||||
* Gergely Nagy - Non-null-terminated string support.
|
||||
* Josh Rotenberg - Initial Doxygen setup and a significant chunk of documentation.
|
||||
|
||||
# LICENSE
|
||||
|
||||
Unless otherwise specified in a source file, sources in this
|
||||
repository are published under the terms of the Apache License version
|
||||
2.0, a copy of which is in this repository as APACHE-2.0.txt.
|
178
src/mod/event_handlers/mod_cdr_mongodb/driver/SConstruct
Normal file
178
src/mod/event_handlers/mod_cdr_mongodb/driver/SConstruct
Normal file
@ -0,0 +1,178 @@
|
||||
# -*- mode: python; -*-
|
||||
|
||||
VERSION = "0.4"
|
||||
|
||||
# --- options ----
|
||||
AddOption('--test-server',
|
||||
dest='test_server',
|
||||
default='127.0.0.1',
|
||||
type='string',
|
||||
nargs=1,
|
||||
action='store',
|
||||
help='IP address of server to use for testing')
|
||||
|
||||
AddOption('--seed-start-port',
|
||||
dest='seed_start_port',
|
||||
default=30000,
|
||||
type='int',
|
||||
nargs=1,
|
||||
action='store',
|
||||
help='IP address of server to use for testing')
|
||||
|
||||
AddOption('--c99',
|
||||
dest='use_c99',
|
||||
default=False,
|
||||
action='store_true',
|
||||
help='Compile with c99 (recommended for gcc)')
|
||||
|
||||
AddOption('--d',
|
||||
dest='optimize',
|
||||
default=True,
|
||||
action='store_false',
|
||||
help='disable optimizations')
|
||||
|
||||
AddOption('--use-platform',
|
||||
dest='compile_platform',
|
||||
default='GENERIC',
|
||||
type='string',
|
||||
nargs=1,
|
||||
action='store',
|
||||
help='Compile for a specific platform to take advantage '
|
||||
' of particular system features. For the moment, this include timeouts only.'
|
||||
' Current options include LINUX, '
|
||||
' GENERIC, and CUSTOM. If you specific CUSTOM, you must place a'
|
||||
' system-specific implementation of net.h and net.c in src/platform/custom/')
|
||||
|
||||
import os, sys
|
||||
|
||||
env = Environment( ENV=os.environ )
|
||||
|
||||
# ---- Docs ----
|
||||
def build_docs(env, target, source):
|
||||
buildscript_path = os.path.join(os.path.abspath("docs"))
|
||||
sys.path.insert(0, buildscript_path)
|
||||
import buildscripts
|
||||
from buildscripts import docs
|
||||
docs.main()
|
||||
|
||||
env.Alias("docs", [], [build_docs])
|
||||
env.AlwaysBuild("docs")
|
||||
|
||||
# ---- Platforms ----
|
||||
PLATFORM_TEST_DIR = None
|
||||
if "LINUX" == GetOption('compile_platform'):
|
||||
env.Append( CPPFLAGS=" -D_MONGO_USE_LINUX_SYSTEM" )
|
||||
NET_LIB = "src/platform/linux/net.c"
|
||||
PLATFORM_TEST_DIR = "test/platform/linux/"
|
||||
PLATFORM_TESTS = [ "timeouts" ]
|
||||
elif "CUSTOM" == GetOption('compile_platform'):
|
||||
env.Append( CPPFLAGS=" -D_MONGO_USE_CUSTOM_SYSTEM" )
|
||||
NET_LIB = "src/platform/custom/net.c"
|
||||
else:
|
||||
NET_LIB = "src/net.c"
|
||||
|
||||
# ---- Libraries ----
|
||||
if os.sys.platform in ["darwin", "linux2"]:
|
||||
env.Append( CPPFLAGS=" -pedantic -Wall -ggdb -DMONGO_HAVE_STDINT" )
|
||||
env.Append( CPPPATH=["/opt/local/include/"] )
|
||||
env.Append( LIBPATH=["/opt/local/lib/"] )
|
||||
|
||||
if GetOption('use_c99'):
|
||||
env.Append( CFLAGS=" -std=c99 " )
|
||||
env.Append( CXXDEFINES="MONGO_HAVE_STDINT" )
|
||||
else:
|
||||
env.Append( CFLAGS=" -ansi " )
|
||||
|
||||
if GetOption('optimize'):
|
||||
env.Append( CPPFLAGS=" -O3 " )
|
||||
# -O3 benchmarks *significantly* faster than -O2 when disabling networking
|
||||
elif 'win32' == os.sys.platform:
|
||||
env.Append( LIBS='ws2_32' )
|
||||
|
||||
#we shouldn't need these options in c99 mode
|
||||
if not GetOption('use_c99'):
|
||||
conf = Configure(env)
|
||||
|
||||
if not conf.CheckType('int64_t'):
|
||||
if conf.CheckType('int64_t', '#include <stdint.h>\n'):
|
||||
conf.env.Append( CPPDEFINES="MONGO_HAVE_STDINT" )
|
||||
elif conf.CheckType('int64_t', '#include <unistd.h>\n'):
|
||||
conf.env.Append( CPPDEFINES="MONGO_HAVE_UNISTD" )
|
||||
elif conf.CheckType('__int64'):
|
||||
conf.env.Append( CPPDEFINES="MONGO_USE__INT64" )
|
||||
elif conf.CheckType('long long int'):
|
||||
conf.env.Append( CPPDEFINES="MONGO_USE_LONG_LONG_INT" )
|
||||
else:
|
||||
print "*** what is your 64 bit int type? ****"
|
||||
Exit(1)
|
||||
|
||||
env = conf.Finish()
|
||||
|
||||
have_libjson = False
|
||||
conf = Configure(env)
|
||||
if conf.CheckLib('json'):
|
||||
have_libjson = True
|
||||
env = conf.Finish()
|
||||
|
||||
if sys.byteorder == 'big':
|
||||
env.Append( CPPDEFINES="MONGO_BIG_ENDIAN" )
|
||||
|
||||
env.Append( CPPPATH=["src/"] )
|
||||
|
||||
coreFiles = ["src/md5.c" ]
|
||||
mFiles = [ "src/mongo.c", NET_LIB, "src/gridfs.c"]
|
||||
bFiles = [ "src/bson.c", "src/numbers.c", "src/encoding.c"]
|
||||
mLibFiles = coreFiles + mFiles + bFiles
|
||||
bLibFiles = coreFiles + bFiles
|
||||
m = env.Library( "mongoc" , mLibFiles )
|
||||
b = env.Library( "bson" , bLibFiles )
|
||||
env.Default( env.Alias( "lib" , [ m[0] , b[0] ] ) )
|
||||
|
||||
if os.sys.platform == "linux2":
|
||||
env.Append( SHLINKFLAGS="-shared -Wl,-soname,libmongoc.so." + VERSION )
|
||||
env.Append( SHLINKFLAGS = "-shared -Wl,-soname,libbson.so." + VERSION )
|
||||
|
||||
dynm = env.SharedLibrary( "mongoc" , mLibFiles )
|
||||
dynb = env.SharedLibrary( "bson" , bLibFiles )
|
||||
env.Default( env.Alias( "sharedlib" , [ dynm[0] , dynb[0] ] ) )
|
||||
|
||||
|
||||
|
||||
# ---- Benchmarking ----
|
||||
benchmarkEnv = env.Clone()
|
||||
benchmarkEnv.Append( CPPDEFINES=[('TEST_SERVER', r'\"%s\"'%GetOption('test_server')),
|
||||
('SEED_START_PORT', r'%d'%GetOption('seed_start_port'))] )
|
||||
benchmarkEnv.Append( LIBS=[m, b] )
|
||||
benchmarkEnv.Prepend( LIBPATH=["."] )
|
||||
benchmarkEnv.Program( "benchmark" , [ "test/benchmark.c"] )
|
||||
|
||||
# ---- Tests ----
|
||||
testEnv = benchmarkEnv.Clone()
|
||||
testCoreFiles = [ ]
|
||||
|
||||
def run_tests( root, tests ):
|
||||
for name in tests:
|
||||
filename = "%s/%s.c" % (root, name)
|
||||
exe = "test_" + name
|
||||
test = testEnv.Program( exe , testCoreFiles + [filename] )
|
||||
test_alias = testEnv.Alias('test', [test], test[0].abspath + ' 2> ' + os.path.devnull)
|
||||
AlwaysBuild(test_alias)
|
||||
|
||||
tests = Split("sizes resize endian_swap bson bson_subobject simple update errors "
|
||||
"count_delete auth gridfs validate examples helpers oid functions cursors replica_set")
|
||||
|
||||
# Run standard tests
|
||||
run_tests("test", tests)
|
||||
|
||||
# Run platform tests
|
||||
if not PLATFORM_TEST_DIR is None:
|
||||
run_tests( PLATFORM_TEST_DIR, PLATFORM_TESTS )
|
||||
|
||||
if have_libjson:
|
||||
tests.append('json')
|
||||
testEnv.Append( LIBS=["json"] )
|
||||
|
||||
# special case for cpptest
|
||||
test = testEnv.Program( 'test_cpp' , testCoreFiles + ['test/cpptest.cpp'] )
|
||||
test_alias = testEnv.Alias('test', [test], test[0].abspath + ' 2> '+ os.path.devnull)
|
||||
AlwaysBuild(test_alias)
|
978
src/mod/event_handlers/mod_cdr_mongodb/driver/src/bson.c
Normal file
978
src/mod/event_handlers/mod_cdr_mongodb/driver/src/bson.c
Normal file
@ -0,0 +1,978 @@
|
||||
/* bson.c */
|
||||
|
||||
/* Copyright 2009, 2010 10gen Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include <time.h>
|
||||
#include <limits.h>
|
||||
|
||||
#include "bson.h"
|
||||
#include "encoding.h"
|
||||
|
||||
const int initialBufferSize = 128;
|
||||
|
||||
/* only need one of these */
|
||||
static const int zero = 0;
|
||||
|
||||
/* Custom standard function pointers. */
|
||||
void *( *bson_malloc_func )( size_t ) = malloc;
|
||||
void *( *bson_realloc_func )( void *, size_t ) = realloc;
|
||||
void ( *bson_free )( void * ) = free;
|
||||
bson_printf_func bson_printf = printf;
|
||||
bson_fprintf_func bson_fprintf = fprintf;
|
||||
bson_sprintf_func bson_sprintf = sprintf;
|
||||
|
||||
static int _bson_errprintf( const char *, ... );
|
||||
bson_printf_func bson_errprintf = _bson_errprintf;
|
||||
|
||||
/* ObjectId fuzz functions. */
|
||||
static int ( *oid_fuzz_func )( void ) = NULL;
|
||||
static int ( *oid_inc_func )( void ) = NULL;
|
||||
|
||||
/* ----------------------------
|
||||
READING
|
||||
------------------------------ */
|
||||
|
||||
bson *bson_empty( bson *obj ) {
|
||||
static char *data = "\005\0\0\0\0";
|
||||
bson_init_data( obj, data );
|
||||
obj->finished = 1;
|
||||
obj->err = 0;
|
||||
obj->stackPos = 0;
|
||||
return obj;
|
||||
}
|
||||
|
||||
void bson_copy_basic( bson *out, const bson *in ) {
|
||||
if ( !out ) return;
|
||||
bson_init_size( out, bson_size( in ) );
|
||||
memcpy( out->data, in->data, bson_size( in ) );
|
||||
}
|
||||
|
||||
void bson_copy( bson *out, const bson *in ) {
|
||||
int i;
|
||||
|
||||
if ( !out ) return;
|
||||
bson_copy_basic( out, in );
|
||||
out->cur = out->data + ( in->cur - in->data );
|
||||
out->dataSize = in->dataSize;
|
||||
out->finished = in->finished;
|
||||
out->stackPos = in->stackPos;
|
||||
out->err = in->err;
|
||||
for( i=0; i<out->stackPos; i++ )
|
||||
out->stack[i] = in->stack[i];
|
||||
}
|
||||
|
||||
int bson_init_data( bson *b, char *data ) {
|
||||
b->data = data;
|
||||
return BSON_OK;
|
||||
}
|
||||
|
||||
static void _bson_reset( bson *b ) {
|
||||
b->finished = 0;
|
||||
b->stackPos = 0;
|
||||
b->err = 0;
|
||||
b->errstr = NULL;
|
||||
}
|
||||
|
||||
int bson_size( const bson *b ) {
|
||||
int i;
|
||||
if ( ! b || ! b->data )
|
||||
return 0;
|
||||
bson_little_endian32( &i, b->data );
|
||||
return i;
|
||||
}
|
||||
|
||||
const char *bson_data( bson *b ) {
|
||||
return (const char *)b->data;
|
||||
}
|
||||
|
||||
static char hexbyte( char hex ) {
|
||||
switch ( hex ) {
|
||||
case '0':
|
||||
return 0x0;
|
||||
case '1':
|
||||
return 0x1;
|
||||
case '2':
|
||||
return 0x2;
|
||||
case '3':
|
||||
return 0x3;
|
||||
case '4':
|
||||
return 0x4;
|
||||
case '5':
|
||||
return 0x5;
|
||||
case '6':
|
||||
return 0x6;
|
||||
case '7':
|
||||
return 0x7;
|
||||
case '8':
|
||||
return 0x8;
|
||||
case '9':
|
||||
return 0x9;
|
||||
case 'a':
|
||||
case 'A':
|
||||
return 0xa;
|
||||
case 'b':
|
||||
case 'B':
|
||||
return 0xb;
|
||||
case 'c':
|
||||
case 'C':
|
||||
return 0xc;
|
||||
case 'd':
|
||||
case 'D':
|
||||
return 0xd;
|
||||
case 'e':
|
||||
case 'E':
|
||||
return 0xe;
|
||||
case 'f':
|
||||
case 'F':
|
||||
return 0xf;
|
||||
default:
|
||||
return 0x0; /* something smarter? */
|
||||
}
|
||||
}
|
||||
|
||||
void bson_oid_from_string( bson_oid_t *oid, const char *str ) {
|
||||
int i;
|
||||
for ( i=0; i<12; i++ ) {
|
||||
oid->bytes[i] = ( hexbyte( str[2*i] ) << 4 ) | hexbyte( str[2*i + 1] );
|
||||
}
|
||||
}
|
||||
|
||||
void bson_oid_to_string( const bson_oid_t *oid, char *str ) {
|
||||
static const char hex[16] = {'0','1','2','3','4','5','6','7','8','9','a','b','c','d','e','f'};
|
||||
int i;
|
||||
for ( i=0; i<12; i++ ) {
|
||||
str[2*i] = hex[( oid->bytes[i] & 0xf0 ) >> 4];
|
||||
str[2*i + 1] = hex[ oid->bytes[i] & 0x0f ];
|
||||
}
|
||||
str[24] = '\0';
|
||||
}
|
||||
|
||||
void bson_set_oid_fuzz( int ( *func )( void ) ) {
|
||||
oid_fuzz_func = func;
|
||||
}
|
||||
|
||||
void bson_set_oid_inc( int ( *func )( void ) ) {
|
||||
oid_inc_func = func;
|
||||
}
|
||||
|
||||
void bson_oid_gen( bson_oid_t *oid ) {
|
||||
static int incr = 0;
|
||||
static int fuzz = 0;
|
||||
int i;
|
||||
int t = time( NULL );
|
||||
|
||||
if( oid_inc_func )
|
||||
i = oid_inc_func();
|
||||
else
|
||||
i = incr++;
|
||||
|
||||
if ( !fuzz ) {
|
||||
if ( oid_fuzz_func )
|
||||
fuzz = oid_fuzz_func();
|
||||
else {
|
||||
srand( t );
|
||||
fuzz = rand();
|
||||
}
|
||||
}
|
||||
|
||||
bson_big_endian32( &oid->ints[0], &t );
|
||||
oid->ints[1] = fuzz;
|
||||
bson_big_endian32( &oid->ints[2], &i );
|
||||
}
|
||||
|
||||
time_t bson_oid_generated_time( bson_oid_t *oid ) {
|
||||
time_t out;
|
||||
bson_big_endian32( &out, &oid->ints[0] );
|
||||
|
||||
return out;
|
||||
}
|
||||
|
||||
void bson_print( bson *b ) {
|
||||
bson_print_raw( b->data , 0 );
|
||||
}
|
||||
|
||||
void bson_print_raw( const char *data , int depth ) {
|
||||
bson_iterator i;
|
||||
const char *key;
|
||||
int temp;
|
||||
bson_timestamp_t ts;
|
||||
char oidhex[25];
|
||||
bson scope;
|
||||
bson_iterator_from_buffer( &i, data );
|
||||
|
||||
while ( bson_iterator_next( &i ) ) {
|
||||
bson_type t = bson_iterator_type( &i );
|
||||
if ( t == 0 )
|
||||
break;
|
||||
key = bson_iterator_key( &i );
|
||||
|
||||
for ( temp=0; temp<=depth; temp++ )
|
||||
printf( "\t" );
|
||||
bson_printf( "%s : %d \t " , key , t );
|
||||
switch ( t ) {
|
||||
case BSON_DOUBLE:
|
||||
printf( "%f" , bson_iterator_double( &i ) );
|
||||
break;
|
||||
case BSON_STRING:
|
||||
printf( "%s" , bson_iterator_string( &i ) );
|
||||
break;
|
||||
case BSON_SYMBOL:
|
||||
printf( "SYMBOL: %s" , bson_iterator_string( &i ) );
|
||||
break;
|
||||
case BSON_OID:
|
||||
bson_oid_to_string( bson_iterator_oid( &i ), oidhex );
|
||||
printf( "%s" , oidhex );
|
||||
break;
|
||||
case BSON_BOOL:
|
||||
printf( "%s" , bson_iterator_bool( &i ) ? "true" : "false" );
|
||||
break;
|
||||
case BSON_DATE:
|
||||
printf( "%ld" , ( long int )bson_iterator_date( &i ) );
|
||||
break;
|
||||
case BSON_BINDATA:
|
||||
printf( "BSON_BINDATA" );
|
||||
break;
|
||||
case BSON_UNDEFINED:
|
||||
printf( "BSON_UNDEFINED" );
|
||||
break;
|
||||
case BSON_NULL:
|
||||
printf( "BSON_NULL" );
|
||||
break;
|
||||
case BSON_REGEX:
|
||||
printf( "BSON_REGEX: %s", bson_iterator_regex( &i ) );
|
||||
break;
|
||||
case BSON_CODE:
|
||||
printf( "BSON_CODE: %s", bson_iterator_code( &i ) );
|
||||
break;
|
||||
case BSON_CODEWSCOPE:
|
||||
printf( "BSON_CODE_W_SCOPE: %s", bson_iterator_code( &i ) );
|
||||
bson_init( &scope );
|
||||
bson_iterator_code_scope( &i, &scope );
|
||||
printf( "\n\t SCOPE: " );
|
||||
bson_print( &scope );
|
||||
break;
|
||||
case BSON_INT:
|
||||
printf( "%d" , bson_iterator_int( &i ) );
|
||||
break;
|
||||
case BSON_LONG:
|
||||
printf( "%lld" , ( long long int )bson_iterator_long( &i ) );
|
||||
break;
|
||||
case BSON_TIMESTAMP:
|
||||
ts = bson_iterator_timestamp( &i );
|
||||
printf( "i: %d, t: %d", ts.i, ts.t );
|
||||
break;
|
||||
case BSON_OBJECT:
|
||||
case BSON_ARRAY:
|
||||
printf( "\n" );
|
||||
bson_print_raw( bson_iterator_value( &i ) , depth + 1 );
|
||||
break;
|
||||
default:
|
||||
bson_errprintf( "can't print type : %d\n" , t );
|
||||
}
|
||||
printf( "\n" );
|
||||
}
|
||||
}
|
||||
|
||||
/* ----------------------------
|
||||
ITERATOR
|
||||
------------------------------ */
|
||||
|
||||
void bson_iterator_init( bson_iterator *i, const bson *b ) {
|
||||
i->cur = b->data + 4;
|
||||
i->first = 1;
|
||||
}
|
||||
|
||||
void bson_iterator_from_buffer( bson_iterator *i, const char *buffer ) {
|
||||
i->cur = buffer + 4;
|
||||
i->first = 1;
|
||||
}
|
||||
|
||||
bson_type bson_find( bson_iterator *it, const bson *obj, const char *name ) {
|
||||
bson_iterator_init( it, (bson *)obj );
|
||||
while( bson_iterator_next( it ) ) {
|
||||
if ( strcmp( name, bson_iterator_key( it ) ) == 0 )
|
||||
break;
|
||||
}
|
||||
return bson_iterator_type( it );
|
||||
}
|
||||
|
||||
bson_bool_t bson_iterator_more( const bson_iterator *i ) {
|
||||
return *( i->cur );
|
||||
}
|
||||
|
||||
bson_type bson_iterator_next( bson_iterator *i ) {
|
||||
int ds;
|
||||
|
||||
if ( i->first ) {
|
||||
i->first = 0;
|
||||
return ( bson_type )( *i->cur );
|
||||
}
|
||||
|
||||
switch ( bson_iterator_type( i ) ) {
|
||||
case BSON_EOO:
|
||||
return BSON_EOO; /* don't advance */
|
||||
case BSON_UNDEFINED:
|
||||
case BSON_NULL:
|
||||
ds = 0;
|
||||
break;
|
||||
case BSON_BOOL:
|
||||
ds = 1;
|
||||
break;
|
||||
case BSON_INT:
|
||||
ds = 4;
|
||||
break;
|
||||
case BSON_LONG:
|
||||
case BSON_DOUBLE:
|
||||
case BSON_TIMESTAMP:
|
||||
case BSON_DATE:
|
||||
ds = 8;
|
||||
break;
|
||||
case BSON_OID:
|
||||
ds = 12;
|
||||
break;
|
||||
case BSON_STRING:
|
||||
case BSON_SYMBOL:
|
||||
case BSON_CODE:
|
||||
ds = 4 + bson_iterator_int_raw( i );
|
||||
break;
|
||||
case BSON_BINDATA:
|
||||
ds = 5 + bson_iterator_int_raw( i );
|
||||
break;
|
||||
case BSON_OBJECT:
|
||||
case BSON_ARRAY:
|
||||
case BSON_CODEWSCOPE:
|
||||
ds = bson_iterator_int_raw( i );
|
||||
break;
|
||||
case BSON_DBREF:
|
||||
ds = 4+12 + bson_iterator_int_raw( i );
|
||||
break;
|
||||
case BSON_REGEX: {
|
||||
const char *s = bson_iterator_value( i );
|
||||
const char *p = s;
|
||||
p += strlen( p )+1;
|
||||
p += strlen( p )+1;
|
||||
ds = p-s;
|
||||
break;
|
||||
}
|
||||
|
||||
default: {
|
||||
char msg[] = "unknown type: 000000000000";
|
||||
bson_numstr( msg+14, ( unsigned )( i->cur[0] ) );
|
||||
bson_fatal_msg( 0, msg );
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
i->cur += 1 + strlen( i->cur + 1 ) + 1 + ds;
|
||||
|
||||
return ( bson_type )( *i->cur );
|
||||
}
|
||||
|
||||
bson_type bson_iterator_type( const bson_iterator *i ) {
|
||||
return ( bson_type )i->cur[0];
|
||||
}
|
||||
|
||||
const char *bson_iterator_key( const bson_iterator *i ) {
|
||||
return i->cur + 1;
|
||||
}
|
||||
|
||||
const char *bson_iterator_value( const bson_iterator *i ) {
|
||||
const char *t = i->cur + 1;
|
||||
t += strlen( t ) + 1;
|
||||
return t;
|
||||
}
|
||||
|
||||
/* types */
|
||||
|
||||
int bson_iterator_int_raw( const bson_iterator *i ) {
|
||||
int out;
|
||||
bson_little_endian32( &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;
|
||||
}
|
||||
|
||||
int64_t bson_iterator_long_raw( const bson_iterator *i ) {
|
||||
int64_t out;
|
||||
bson_little_endian64( &out, bson_iterator_value( i ) );
|
||||
return out;
|
||||
}
|
||||
|
||||
bson_bool_t bson_iterator_bool_raw( const bson_iterator *i ) {
|
||||
return bson_iterator_value( i )[0];
|
||||
}
|
||||
|
||||
bson_oid_t *bson_iterator_oid( const bson_iterator *i ) {
|
||||
return ( bson_oid_t * )bson_iterator_value( i );
|
||||
}
|
||||
|
||||
int bson_iterator_int( const bson_iterator *i ) {
|
||||
switch ( bson_iterator_type( i ) ) {
|
||||
case BSON_INT:
|
||||
return bson_iterator_int_raw( i );
|
||||
case BSON_LONG:
|
||||
return bson_iterator_long_raw( i );
|
||||
case BSON_DOUBLE:
|
||||
return bson_iterator_double_raw( i );
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
double bson_iterator_double( const bson_iterator *i ) {
|
||||
switch ( bson_iterator_type( i ) ) {
|
||||
case BSON_INT:
|
||||
return bson_iterator_int_raw( i );
|
||||
case BSON_LONG:
|
||||
return bson_iterator_long_raw( i );
|
||||
case BSON_DOUBLE:
|
||||
return bson_iterator_double_raw( i );
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
int64_t bson_iterator_long( const bson_iterator *i ) {
|
||||
switch ( bson_iterator_type( i ) ) {
|
||||
case BSON_INT:
|
||||
return bson_iterator_int_raw( i );
|
||||
case BSON_LONG:
|
||||
return bson_iterator_long_raw( i );
|
||||
case BSON_DOUBLE:
|
||||
return bson_iterator_double_raw( i );
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
bson_timestamp_t bson_iterator_timestamp( const bson_iterator *i ) {
|
||||
bson_timestamp_t ts;
|
||||
bson_little_endian32( &( ts.i ), bson_iterator_value( i ) );
|
||||
bson_little_endian32( &( ts.t ), bson_iterator_value( i ) + 4 );
|
||||
return ts;
|
||||
}
|
||||
|
||||
bson_bool_t bson_iterator_bool( const bson_iterator *i ) {
|
||||
switch ( bson_iterator_type( i ) ) {
|
||||
case BSON_BOOL:
|
||||
return bson_iterator_bool_raw( i );
|
||||
case BSON_INT:
|
||||
return bson_iterator_int_raw( i ) != 0;
|
||||
case BSON_LONG:
|
||||
return bson_iterator_long_raw( i ) != 0;
|
||||
case BSON_DOUBLE:
|
||||
return bson_iterator_double_raw( i ) != 0;
|
||||
case BSON_EOO:
|
||||
case BSON_NULL:
|
||||
return 0;
|
||||
default:
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
const char *bson_iterator_string( const bson_iterator *i ) {
|
||||
return bson_iterator_value( i ) + 4;
|
||||
}
|
||||
|
||||
int bson_iterator_string_len( const bson_iterator *i ) {
|
||||
return bson_iterator_int_raw( i );
|
||||
}
|
||||
|
||||
const char *bson_iterator_code( const bson_iterator *i ) {
|
||||
switch ( bson_iterator_type( i ) ) {
|
||||
case BSON_STRING:
|
||||
case BSON_CODE:
|
||||
return bson_iterator_value( i ) + 4;
|
||||
case BSON_CODEWSCOPE:
|
||||
return bson_iterator_value( i ) + 8;
|
||||
default:
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
void bson_iterator_code_scope( const bson_iterator *i, bson *scope ) {
|
||||
if ( bson_iterator_type( i ) == BSON_CODEWSCOPE ) {
|
||||
int code_len;
|
||||
bson_little_endian32( &code_len, bson_iterator_value( i )+4 );
|
||||
bson_init_data( scope, ( void * )( bson_iterator_value( i )+8+code_len ) );
|
||||
} else {
|
||||
bson_empty( scope );
|
||||
}
|
||||
}
|
||||
|
||||
bson_date_t bson_iterator_date( const bson_iterator *i ) {
|
||||
return bson_iterator_long_raw( i );
|
||||
}
|
||||
|
||||
time_t bson_iterator_time_t( const bson_iterator *i ) {
|
||||
return bson_iterator_date( i ) / 1000;
|
||||
}
|
||||
|
||||
int bson_iterator_bin_len( const bson_iterator *i ) {
|
||||
return ( bson_iterator_bin_type( i ) == BSON_BIN_BINARY_OLD )
|
||||
? bson_iterator_int_raw( i ) - 4
|
||||
: bson_iterator_int_raw( i );
|
||||
}
|
||||
|
||||
char bson_iterator_bin_type( const bson_iterator *i ) {
|
||||
return bson_iterator_value( i )[4];
|
||||
}
|
||||
|
||||
const char *bson_iterator_bin_data( const bson_iterator *i ) {
|
||||
return ( bson_iterator_bin_type( i ) == BSON_BIN_BINARY_OLD )
|
||||
? bson_iterator_value( i ) + 9
|
||||
: bson_iterator_value( i ) + 5;
|
||||
}
|
||||
|
||||
const char *bson_iterator_regex( const bson_iterator *i ) {
|
||||
return bson_iterator_value( i );
|
||||
}
|
||||
|
||||
const char *bson_iterator_regex_opts( const bson_iterator *i ) {
|
||||
const char *p = bson_iterator_value( i );
|
||||
return p + strlen( p ) + 1;
|
||||
|
||||
}
|
||||
|
||||
void bson_iterator_subobject( const bson_iterator *i, bson *sub ) {
|
||||
bson_init_data( sub, ( char * )bson_iterator_value( i ) );
|
||||
_bson_reset( sub );
|
||||
sub->finished = 1;
|
||||
}
|
||||
|
||||
void bson_iterator_subiterator( const bson_iterator *i, bson_iterator *sub ) {
|
||||
bson_iterator_from_buffer( sub, bson_iterator_value( i ) );
|
||||
}
|
||||
|
||||
/* ----------------------------
|
||||
BUILDING
|
||||
------------------------------ */
|
||||
|
||||
static void _bson_init_size( bson *b, int size ) {
|
||||
if( size == 0 )
|
||||
b->data = NULL;
|
||||
else
|
||||
b->data = ( char * )bson_malloc( size );
|
||||
b->dataSize = size;
|
||||
b->cur = b->data + 4;
|
||||
_bson_reset( b );
|
||||
}
|
||||
|
||||
void bson_init( bson *b ) {
|
||||
_bson_init_size( b, initialBufferSize );
|
||||
}
|
||||
|
||||
void bson_init_size( bson *b, int size ) {
|
||||
_bson_init_size( b, size );
|
||||
}
|
||||
|
||||
void bson_append_byte( bson *b, char c ) {
|
||||
b->cur[0] = c;
|
||||
b->cur++;
|
||||
}
|
||||
|
||||
void bson_append( bson *b, const void *data, int len ) {
|
||||
memcpy( b->cur , data , len );
|
||||
b->cur += len;
|
||||
}
|
||||
|
||||
void bson_append32( bson *b, const void *data ) {
|
||||
bson_little_endian32( b->cur, data );
|
||||
b->cur += 4;
|
||||
}
|
||||
|
||||
void bson_append64( bson *b, const void *data ) {
|
||||
bson_little_endian64( b->cur, data );
|
||||
b->cur += 8;
|
||||
}
|
||||
|
||||
int bson_ensure_space( bson *b, const int bytesNeeded ) {
|
||||
int pos = b->cur - b->data;
|
||||
char *orig = b->data;
|
||||
int new_size;
|
||||
|
||||
if ( pos + bytesNeeded <= b->dataSize )
|
||||
return BSON_OK;
|
||||
|
||||
new_size = 1.5 * ( b->dataSize + bytesNeeded );
|
||||
|
||||
if( new_size < b->dataSize ) {
|
||||
if( ( b->dataSize + bytesNeeded ) < INT_MAX )
|
||||
new_size = INT_MAX;
|
||||
else {
|
||||
b->err = BSON_SIZE_OVERFLOW;
|
||||
return BSON_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
b->data = bson_realloc( b->data, new_size );
|
||||
if ( !b->data )
|
||||
bson_fatal_msg( !!b->data, "realloc() failed" );
|
||||
|
||||
b->dataSize = new_size;
|
||||
b->cur += b->data - orig;
|
||||
|
||||
return BSON_OK;
|
||||
}
|
||||
|
||||
int bson_finish( bson *b ) {
|
||||
int i;
|
||||
|
||||
if( b->err & BSON_NOT_UTF8 )
|
||||
return BSON_ERROR;
|
||||
|
||||
if ( ! b->finished ) {
|
||||
if ( bson_ensure_space( b, 1 ) == BSON_ERROR ) return BSON_ERROR;
|
||||
bson_append_byte( b, 0 );
|
||||
i = b->cur - b->data;
|
||||
bson_little_endian32( b->data, &i );
|
||||
b->finished = 1;
|
||||
}
|
||||
|
||||
return BSON_OK;
|
||||
}
|
||||
|
||||
void bson_destroy( bson *b ) {
|
||||
bson_free( b->data );
|
||||
b->err = 0;
|
||||
b->data = 0;
|
||||
b->cur = 0;
|
||||
b->finished = 1;
|
||||
}
|
||||
|
||||
static int bson_append_estart( bson *b, int type, const char *name, const int dataSize ) {
|
||||
const int len = strlen( name ) + 1;
|
||||
|
||||
if ( b->finished ) {
|
||||
b->err |= BSON_ALREADY_FINISHED;
|
||||
return BSON_ERROR;
|
||||
}
|
||||
|
||||
if ( bson_ensure_space( b, 1 + len + dataSize ) == BSON_ERROR ) {
|
||||
return BSON_ERROR;
|
||||
}
|
||||
|
||||
if( bson_check_field_name( b, ( const char * )name, len - 1 ) == BSON_ERROR ) {
|
||||
bson_builder_error( b );
|
||||
return BSON_ERROR;
|
||||
}
|
||||
|
||||
bson_append_byte( b, ( char )type );
|
||||
bson_append( b, name, len );
|
||||
return BSON_OK;
|
||||
}
|
||||
|
||||
/* ----------------------------
|
||||
BUILDING TYPES
|
||||
------------------------------ */
|
||||
|
||||
int bson_append_int( bson *b, const char *name, const int i ) {
|
||||
if ( bson_append_estart( b, BSON_INT, name, 4 ) == BSON_ERROR )
|
||||
return BSON_ERROR;
|
||||
bson_append32( b , &i );
|
||||
return BSON_OK;
|
||||
}
|
||||
|
||||
int bson_append_long( bson *b, const char *name, const int64_t i ) {
|
||||
if ( bson_append_estart( b , BSON_LONG, name, 8 ) == BSON_ERROR )
|
||||
return BSON_ERROR;
|
||||
bson_append64( b , &i );
|
||||
return BSON_OK;
|
||||
}
|
||||
|
||||
int bson_append_double( bson *b, const char *name, const double d ) {
|
||||
if ( bson_append_estart( b, BSON_DOUBLE, name, 8 ) == BSON_ERROR )
|
||||
return BSON_ERROR;
|
||||
bson_append64( b , &d );
|
||||
return BSON_OK;
|
||||
}
|
||||
|
||||
int bson_append_bool( bson *b, const char *name, const bson_bool_t i ) {
|
||||
if ( bson_append_estart( b, BSON_BOOL, name, 1 ) == BSON_ERROR )
|
||||
return BSON_ERROR;
|
||||
bson_append_byte( b , i != 0 );
|
||||
return BSON_OK;
|
||||
}
|
||||
|
||||
int bson_append_null( bson *b, const char *name ) {
|
||||
if ( bson_append_estart( b , BSON_NULL, name, 0 ) == BSON_ERROR )
|
||||
return BSON_ERROR;
|
||||
return BSON_OK;
|
||||
}
|
||||
|
||||
int bson_append_undefined( bson *b, const char *name ) {
|
||||
if ( bson_append_estart( b, BSON_UNDEFINED, name, 0 ) == BSON_ERROR )
|
||||
return BSON_ERROR;
|
||||
return BSON_OK;
|
||||
}
|
||||
|
||||
int bson_append_string_base( bson *b, const char *name,
|
||||
const char *value, int len, bson_type type ) {
|
||||
|
||||
int sl = len + 1;
|
||||
if ( bson_check_string( b, ( const char * )value, sl - 1 ) == BSON_ERROR )
|
||||
return BSON_ERROR;
|
||||
if ( bson_append_estart( b, type, name, 4 + sl ) == BSON_ERROR ) {
|
||||
return BSON_ERROR;
|
||||
}
|
||||
bson_append32( b , &sl );
|
||||
bson_append( b , value , sl - 1 );
|
||||
bson_append( b , "\0" , 1 );
|
||||
return BSON_OK;
|
||||
}
|
||||
|
||||
int bson_append_string( bson *b, const char *name, const char *value ) {
|
||||
return bson_append_string_base( b, name, value, strlen ( value ), BSON_STRING );
|
||||
}
|
||||
|
||||
int bson_append_symbol( bson *b, const char *name, const char *value ) {
|
||||
return bson_append_string_base( b, name, value, strlen ( value ), BSON_SYMBOL );
|
||||
}
|
||||
|
||||
int bson_append_code( bson *b, const char *name, const char *value ) {
|
||||
return bson_append_string_base( b, name, value, strlen ( value ), BSON_CODE );
|
||||
}
|
||||
|
||||
int bson_append_string_n( bson *b, const char *name, const char *value, int len ) {
|
||||
return bson_append_string_base( b, name, value, len, BSON_STRING );
|
||||
}
|
||||
|
||||
int bson_append_symbol_n( bson *b, const char *name, const char *value, int len ) {
|
||||
return bson_append_string_base( b, name, value, len, BSON_SYMBOL );
|
||||
}
|
||||
|
||||
int bson_append_code_n( bson *b, const char *name, const char *value, int len ) {
|
||||
return bson_append_string_base( b, name, value, len, BSON_CODE );
|
||||
}
|
||||
|
||||
int bson_append_code_w_scope_n( bson *b, const char *name,
|
||||
const char *code, int len, const bson *scope ) {
|
||||
|
||||
int sl = len + 1;
|
||||
int size = 4 + 4 + sl + bson_size( scope );
|
||||
if ( bson_append_estart( b, BSON_CODEWSCOPE, name, size ) == BSON_ERROR )
|
||||
return BSON_ERROR;
|
||||
bson_append32( b, &size );
|
||||
bson_append32( b, &sl );
|
||||
bson_append( b, code, sl );
|
||||
bson_append( b, scope->data, bson_size( scope ) );
|
||||
return BSON_OK;
|
||||
}
|
||||
|
||||
int bson_append_code_w_scope( bson *b, const char *name, const char *code, const bson *scope ) {
|
||||
return bson_append_code_w_scope_n( b, name, code, strlen ( code ), scope );
|
||||
}
|
||||
|
||||
int bson_append_binary( bson *b, const char *name, char type, const char *str, int len ) {
|
||||
if ( type == BSON_BIN_BINARY_OLD ) {
|
||||
int subtwolen = len + 4;
|
||||
if ( bson_append_estart( b, BSON_BINDATA, name, 4+1+4+len ) == BSON_ERROR )
|
||||
return BSON_ERROR;
|
||||
bson_append32( b, &subtwolen );
|
||||
bson_append_byte( b, type );
|
||||
bson_append32( b, &len );
|
||||
bson_append( b, str, len );
|
||||
} else {
|
||||
if ( bson_append_estart( b, BSON_BINDATA, name, 4+1+len ) == BSON_ERROR )
|
||||
return BSON_ERROR;
|
||||
bson_append32( b, &len );
|
||||
bson_append_byte( b, type );
|
||||
bson_append( b, str, len );
|
||||
}
|
||||
return BSON_OK;
|
||||
}
|
||||
|
||||
int bson_append_oid( bson *b, const char *name, const bson_oid_t *oid ) {
|
||||
if ( bson_append_estart( b, BSON_OID, name, 12 ) == BSON_ERROR )
|
||||
return BSON_ERROR;
|
||||
bson_append( b , oid , 12 );
|
||||
return BSON_OK;
|
||||
}
|
||||
|
||||
int bson_append_new_oid( bson *b, const char *name ) {
|
||||
bson_oid_t oid;
|
||||
bson_oid_gen( &oid );
|
||||
return bson_append_oid( b, name, &oid );
|
||||
}
|
||||
|
||||
int bson_append_regex( bson *b, const char *name, const char *pattern, const char *opts ) {
|
||||
const int plen = strlen( pattern )+1;
|
||||
const int olen = strlen( opts )+1;
|
||||
if ( bson_append_estart( b, BSON_REGEX, name, plen + olen ) == BSON_ERROR )
|
||||
return BSON_ERROR;
|
||||
if ( bson_check_string( b, pattern, plen - 1 ) == BSON_ERROR )
|
||||
return BSON_ERROR;
|
||||
bson_append( b , pattern , plen );
|
||||
bson_append( b , opts , olen );
|
||||
return BSON_OK;
|
||||
}
|
||||
|
||||
int bson_append_bson( bson *b, const char *name, const bson *bson ) {
|
||||
if ( bson_append_estart( b, BSON_OBJECT, name, bson_size( bson ) ) == BSON_ERROR )
|
||||
return BSON_ERROR;
|
||||
bson_append( b , bson->data , bson_size( bson ) );
|
||||
return BSON_OK;
|
||||
}
|
||||
|
||||
int bson_append_element( bson *b, const char *name_or_null, const bson_iterator *elem ) {
|
||||
bson_iterator next = *elem;
|
||||
int size;
|
||||
|
||||
bson_iterator_next( &next );
|
||||
size = next.cur - elem->cur;
|
||||
|
||||
if ( name_or_null == NULL ) {
|
||||
if( bson_ensure_space( b, size ) == BSON_ERROR )
|
||||
return BSON_ERROR;
|
||||
bson_append( b, elem->cur, size );
|
||||
} else {
|
||||
int data_size = size - 2 - strlen( bson_iterator_key( elem ) );
|
||||
bson_append_estart( b, elem->cur[0], name_or_null, data_size );
|
||||
bson_append( b, bson_iterator_value( elem ), data_size );
|
||||
}
|
||||
|
||||
return BSON_OK;
|
||||
}
|
||||
|
||||
int bson_append_timestamp( bson *b, const char *name, bson_timestamp_t *ts ) {
|
||||
if ( bson_append_estart( b, BSON_TIMESTAMP, name, 8 ) == BSON_ERROR ) return BSON_ERROR;
|
||||
|
||||
bson_append32( b , &( ts->i ) );
|
||||
bson_append32( b , &( ts->t ) );
|
||||
|
||||
return BSON_OK;
|
||||
}
|
||||
|
||||
int bson_append_date( bson *b, const char *name, bson_date_t millis ) {
|
||||
if ( bson_append_estart( b, BSON_DATE, name, 8 ) == BSON_ERROR ) return BSON_ERROR;
|
||||
bson_append64( b , &millis );
|
||||
return BSON_OK;
|
||||
}
|
||||
|
||||
int bson_append_time_t( bson *b, const char *name, time_t secs ) {
|
||||
return bson_append_date( b, name, ( bson_date_t )secs * 1000 );
|
||||
}
|
||||
|
||||
int bson_append_start_object( bson *b, const char *name ) {
|
||||
if ( bson_append_estart( b, BSON_OBJECT, name, 5 ) == BSON_ERROR ) return BSON_ERROR;
|
||||
b->stack[ b->stackPos++ ] = b->cur - b->data;
|
||||
bson_append32( b , &zero );
|
||||
return BSON_OK;
|
||||
}
|
||||
|
||||
int bson_append_start_array( bson *b, const char *name ) {
|
||||
if ( bson_append_estart( b, BSON_ARRAY, name, 5 ) == BSON_ERROR ) return BSON_ERROR;
|
||||
b->stack[ b->stackPos++ ] = b->cur - b->data;
|
||||
bson_append32( b , &zero );
|
||||
return BSON_OK;
|
||||
}
|
||||
|
||||
int bson_append_finish_object( bson *b ) {
|
||||
char *start;
|
||||
int i;
|
||||
if ( bson_ensure_space( b, 1 ) == BSON_ERROR ) return BSON_ERROR;
|
||||
bson_append_byte( b , 0 );
|
||||
|
||||
start = b->data + b->stack[ --b->stackPos ];
|
||||
i = b->cur - start;
|
||||
bson_little_endian32( start, &i );
|
||||
|
||||
return BSON_OK;
|
||||
}
|
||||
|
||||
int bson_append_finish_array( bson *b ) {
|
||||
return bson_append_finish_object( b );
|
||||
}
|
||||
|
||||
|
||||
/* Error handling and allocators. */
|
||||
|
||||
static bson_err_handler err_handler = NULL;
|
||||
|
||||
bson_err_handler set_bson_err_handler( bson_err_handler func ) {
|
||||
bson_err_handler old = err_handler;
|
||||
err_handler = func;
|
||||
return old;
|
||||
}
|
||||
|
||||
void *bson_malloc( int size ) {
|
||||
void *p;
|
||||
p = bson_malloc_func( size );
|
||||
bson_fatal_msg( !!p, "malloc() failed" );
|
||||
return p;
|
||||
}
|
||||
|
||||
void *bson_realloc( void *ptr, int size ) {
|
||||
void *p;
|
||||
p = bson_realloc_func( ptr, size );
|
||||
bson_fatal_msg( !!p, "realloc() failed" );
|
||||
return p;
|
||||
}
|
||||
|
||||
int _bson_errprintf( const char *format, ... ) {
|
||||
va_list ap;
|
||||
int ret;
|
||||
va_start( ap, format );
|
||||
ret = vfprintf( stderr, format, ap );
|
||||
va_end( ap );
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* This method is invoked when a non-fatal bson error is encountered.
|
||||
* Calls the error handler if available.
|
||||
*
|
||||
* @param
|
||||
*/
|
||||
void bson_builder_error( bson *b ) {
|
||||
if( err_handler )
|
||||
err_handler( "BSON error." );
|
||||
}
|
||||
|
||||
void bson_fatal( int ok ) {
|
||||
bson_fatal_msg( ok, "" );
|
||||
}
|
||||
|
||||
void bson_fatal_msg( int ok , const char *msg ) {
|
||||
if ( ok )
|
||||
return;
|
||||
|
||||
if ( err_handler ) {
|
||||
err_handler( msg );
|
||||
}
|
||||
|
||||
bson_errprintf( "error: %s\n" , msg );
|
||||
exit( -5 );
|
||||
}
|
||||
|
||||
|
||||
/* Efficiently copy an integer to a string. */
|
||||
extern const char bson_numstrs[1000][4];
|
||||
|
||||
void bson_numstr( char *str, int i ) {
|
||||
if( i < 1000 )
|
||||
memcpy( str, bson_numstrs[i], 4 );
|
||||
else
|
||||
bson_sprintf( str,"%d", i );
|
||||
}
|
975
src/mod/event_handlers/mod_cdr_mongodb/driver/src/bson.h
Normal file
975
src/mod/event_handlers/mod_cdr_mongodb/driver/src/bson.h
Normal file
@ -0,0 +1,975 @@
|
||||
/**
|
||||
* @file bson.h
|
||||
* @brief BSON Declarations
|
||||
*/
|
||||
|
||||
/* Copyright 2009-2011 10gen Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef _BSON_H_
|
||||
#define _BSON_H_
|
||||
|
||||
#include "platform.h"
|
||||
#include <time.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include <stdarg.h>
|
||||
|
||||
MONGO_EXTERN_C_START
|
||||
|
||||
#define BSON_OK 0
|
||||
#define BSON_ERROR -1
|
||||
|
||||
enum bson_error_t {
|
||||
BSON_SIZE_OVERFLOW = 1 /**< Trying to create a BSON object larger than INT_MAX. */
|
||||
};
|
||||
|
||||
enum bson_validity_t {
|
||||
BSON_VALID = 0, /**< BSON is valid and UTF-8 compliant. */
|
||||
BSON_NOT_UTF8 = ( 1<<1 ), /**< A key or a string is not valid UTF-8. */
|
||||
BSON_FIELD_HAS_DOT = ( 1<<2 ), /**< Warning: key contains '.' character. */
|
||||
BSON_FIELD_INIT_DOLLAR = ( 1<<3 ), /**< Warning: key starts with '$' character. */
|
||||
BSON_ALREADY_FINISHED = ( 1<<4 ) /**< Trying to modify a finished BSON object. */
|
||||
};
|
||||
|
||||
enum bson_binary_subtype_t {
|
||||
BSON_BIN_BINARY = 0,
|
||||
BSON_BIN_FUNC = 1,
|
||||
BSON_BIN_BINARY_OLD = 2,
|
||||
BSON_BIN_UUID = 3,
|
||||
BSON_BIN_MD5 = 5,
|
||||
BSON_BIN_USER = 128
|
||||
};
|
||||
|
||||
typedef enum {
|
||||
BSON_EOO = 0,
|
||||
BSON_DOUBLE = 1,
|
||||
BSON_STRING = 2,
|
||||
BSON_OBJECT = 3,
|
||||
BSON_ARRAY = 4,
|
||||
BSON_BINDATA = 5,
|
||||
BSON_UNDEFINED = 6,
|
||||
BSON_OID = 7,
|
||||
BSON_BOOL = 8,
|
||||
BSON_DATE = 9,
|
||||
BSON_NULL = 10,
|
||||
BSON_REGEX = 11,
|
||||
BSON_DBREF = 12, /**< Deprecated. */
|
||||
BSON_CODE = 13,
|
||||
BSON_SYMBOL = 14,
|
||||
BSON_CODEWSCOPE = 15,
|
||||
BSON_INT = 16,
|
||||
BSON_TIMESTAMP = 17,
|
||||
BSON_LONG = 18
|
||||
} bson_type;
|
||||
|
||||
typedef int bson_bool_t;
|
||||
|
||||
typedef struct {
|
||||
const char *cur;
|
||||
bson_bool_t first;
|
||||
} bson_iterator;
|
||||
|
||||
typedef struct {
|
||||
char *data;
|
||||
char *cur;
|
||||
int dataSize;
|
||||
bson_bool_t finished;
|
||||
int stack[32];
|
||||
int stackPos;
|
||||
int err; /**< Bitfield representing errors or warnings on this buffer */
|
||||
char *errstr; /**< A string representation of the most recent error or warning. */
|
||||
} bson;
|
||||
|
||||
#pragma pack(1)
|
||||
typedef union {
|
||||
char bytes[12];
|
||||
int ints[3];
|
||||
} bson_oid_t;
|
||||
#pragma pack()
|
||||
|
||||
typedef int64_t bson_date_t; /* milliseconds since epoch UTC */
|
||||
|
||||
typedef struct {
|
||||
int i; /* increment */
|
||||
int t; /* time in seconds */
|
||||
} bson_timestamp_t;
|
||||
|
||||
/* ----------------------------
|
||||
READING
|
||||
------------------------------ */
|
||||
|
||||
/**
|
||||
* Size of a BSON object.
|
||||
*
|
||||
* @param b the BSON object.
|
||||
*
|
||||
* @return the size.
|
||||
*/
|
||||
int bson_size( const bson *b );
|
||||
|
||||
/**
|
||||
* Print a string representation of a BSON object.
|
||||
*
|
||||
* @param b the BSON object to print.
|
||||
*/
|
||||
void bson_print( bson *b );
|
||||
|
||||
/**
|
||||
* Return a pointer to the raw buffer stored by this bson object.
|
||||
*
|
||||
* @param b a BSON object
|
||||
*/
|
||||
const char *bson_data( bson *b );
|
||||
|
||||
/**
|
||||
* Print a string representation of a BSON object.
|
||||
*
|
||||
* @param bson the raw data to print.
|
||||
* @param depth the depth to recurse the object.x
|
||||
*/
|
||||
void bson_print_raw( const char *bson , int depth );
|
||||
|
||||
/**
|
||||
* Advance a bson_iterator to the named field.
|
||||
*
|
||||
* @param it the bson_iterator to use.
|
||||
* @param obj the BSON object to use.
|
||||
* @param name the name of the field to find.
|
||||
*
|
||||
* @return the type of the found object or BSON_EOO if it is not found.
|
||||
*/
|
||||
bson_type bson_find( bson_iterator *it, const bson *obj, const char *name );
|
||||
|
||||
/**
|
||||
* Initialize a bson_iterator.
|
||||
*
|
||||
* @param i the bson_iterator to initialize.
|
||||
* @param bson the BSON object to associate with the iterator.
|
||||
*/
|
||||
void bson_iterator_init( bson_iterator *i , const bson *b );
|
||||
|
||||
/**
|
||||
* Initialize a bson iterator from a const char* buffer. Note
|
||||
* that this is mostly used internally.
|
||||
*
|
||||
* @param i the bson_iterator to initialize.
|
||||
* @param buffer the buffer to point to.
|
||||
*/
|
||||
void bson_iterator_from_buffer( bson_iterator *i, const char *buffer );
|
||||
|
||||
/* more returns true for eoo. best to loop with bson_iterator_next(&it) */
|
||||
/**
|
||||
* Check to see if the bson_iterator has more data.
|
||||
*
|
||||
* @param i the iterator.
|
||||
*
|
||||
* @return returns true if there is more data.
|
||||
*/
|
||||
bson_bool_t bson_iterator_more( const bson_iterator *i );
|
||||
|
||||
/**
|
||||
* Point the iterator at the next BSON object.
|
||||
*
|
||||
* @param i the bson_iterator.
|
||||
*
|
||||
* @return the type of the next BSON object.
|
||||
*/
|
||||
bson_type bson_iterator_next( bson_iterator *i );
|
||||
|
||||
/**
|
||||
* Get the type of the BSON object currently pointed to by the iterator.
|
||||
*
|
||||
* @param i the bson_iterator
|
||||
*
|
||||
* @return the type of the current BSON object.
|
||||
*/
|
||||
bson_type bson_iterator_type( const bson_iterator *i );
|
||||
|
||||
/**
|
||||
* Get the key of the BSON object currently pointed to by the iterator.
|
||||
*
|
||||
* @param i the bson_iterator
|
||||
*
|
||||
* @return the key of the current BSON object.
|
||||
*/
|
||||
const char *bson_iterator_key( const bson_iterator *i );
|
||||
|
||||
/**
|
||||
* Get the value of the BSON object currently pointed to by the iterator.
|
||||
*
|
||||
* @param i the bson_iterator
|
||||
*
|
||||
* @return the value of the current BSON object.
|
||||
*/
|
||||
const char *bson_iterator_value( const bson_iterator *i );
|
||||
|
||||
/* these convert to the right type (return 0 if non-numeric) */
|
||||
/**
|
||||
* Get the double value of the BSON object currently pointed to by the
|
||||
* iterator.
|
||||
*
|
||||
* @param i the bson_iterator
|
||||
*
|
||||
* @return the value of the current BSON object.
|
||||
*/
|
||||
double bson_iterator_double( const bson_iterator *i );
|
||||
|
||||
/**
|
||||
* Get the int value of the BSON object currently pointed to by the iterator.
|
||||
*
|
||||
* @param i the bson_iterator
|
||||
*
|
||||
* @return the value of the current BSON object.
|
||||
*/
|
||||
int bson_iterator_int( const bson_iterator *i );
|
||||
|
||||
/**
|
||||
* Get the long value of the BSON object currently pointed to by the iterator.
|
||||
*
|
||||
* @param i the bson_iterator
|
||||
*
|
||||
* @return the value of the current BSON object.
|
||||
*/
|
||||
int64_t bson_iterator_long( const bson_iterator *i );
|
||||
|
||||
/* return the bson timestamp as a whole or in parts */
|
||||
/**
|
||||
* Get the timestamp value of the BSON object currently pointed to by
|
||||
* the iterator.
|
||||
*
|
||||
* @param i the bson_iterator
|
||||
*
|
||||
* @return the value of the current BSON object.
|
||||
*/
|
||||
bson_timestamp_t bson_iterator_timestamp( const bson_iterator *i );
|
||||
|
||||
/**
|
||||
* Get the boolean value of the BSON object currently pointed to by
|
||||
* the iterator.
|
||||
*
|
||||
* @param i the bson_iterator
|
||||
*
|
||||
* @return the value of the current BSON object.
|
||||
*/
|
||||
/* false: boolean false, 0 in any type, or null */
|
||||
/* true: anything else (even empty strings and objects) */
|
||||
bson_bool_t bson_iterator_bool( const bson_iterator *i );
|
||||
|
||||
/**
|
||||
* Get the double value of the BSON object currently pointed to by the
|
||||
* iterator. Assumes the correct type is used.
|
||||
*
|
||||
* @param i the bson_iterator
|
||||
*
|
||||
* @return the value of the current BSON object.
|
||||
*/
|
||||
/* these assume you are using the right type */
|
||||
double bson_iterator_double_raw( const bson_iterator *i );
|
||||
|
||||
/**
|
||||
* Get the int value of the BSON object currently pointed to by the
|
||||
* iterator. Assumes the correct type is used.
|
||||
*
|
||||
* @param i the bson_iterator
|
||||
*
|
||||
* @return the value of the current BSON object.
|
||||
*/
|
||||
int bson_iterator_int_raw( const bson_iterator *i );
|
||||
|
||||
/**
|
||||
* Get the long value of the BSON object currently pointed to by the
|
||||
* iterator. Assumes the correct type is used.
|
||||
*
|
||||
* @param i the bson_iterator
|
||||
*
|
||||
* @return the value of the current BSON object.
|
||||
*/
|
||||
int64_t bson_iterator_long_raw( const bson_iterator *i );
|
||||
|
||||
/**
|
||||
* Get the bson_bool_t value of the BSON object currently pointed to by the
|
||||
* iterator. Assumes the correct type is used.
|
||||
*
|
||||
* @param i the bson_iterator
|
||||
*
|
||||
* @return the value of the current BSON object.
|
||||
*/
|
||||
bson_bool_t bson_iterator_bool_raw( const bson_iterator *i );
|
||||
|
||||
/**
|
||||
* Get the bson_oid_t value of the BSON object currently pointed to by the
|
||||
* iterator.
|
||||
*
|
||||
* @param i the bson_iterator
|
||||
*
|
||||
* @return the value of the current BSON object.
|
||||
*/
|
||||
bson_oid_t *bson_iterator_oid( const bson_iterator *i );
|
||||
|
||||
/**
|
||||
* Get the string value of the BSON object currently pointed to by the
|
||||
* iterator.
|
||||
*
|
||||
* @param i the bson_iterator
|
||||
*
|
||||
* @return the value of the current BSON object.
|
||||
*/
|
||||
/* these can also be used with bson_code and bson_symbol*/
|
||||
const char *bson_iterator_string( const bson_iterator *i );
|
||||
|
||||
/**
|
||||
* Get the string length of the BSON object currently pointed to by the
|
||||
* iterator.
|
||||
*
|
||||
* @param i the bson_iterator
|
||||
*
|
||||
* @return the length of the current BSON object.
|
||||
*/
|
||||
int bson_iterator_string_len( const bson_iterator *i );
|
||||
|
||||
/**
|
||||
* Get the code value of the BSON object currently pointed to by the
|
||||
* iterator. Works with bson_code, bson_codewscope, and BSON_STRING
|
||||
* returns NULL for everything else.
|
||||
*
|
||||
* @param i the bson_iterator
|
||||
*
|
||||
* @return the code value of the current BSON object.
|
||||
*/
|
||||
/* works with bson_code, bson_codewscope, and BSON_STRING */
|
||||
/* returns NULL for everything else */
|
||||
const char *bson_iterator_code( const bson_iterator *i );
|
||||
|
||||
/**
|
||||
* Calls bson_empty on scope if not a bson_codewscope
|
||||
*
|
||||
* @param i the bson_iterator.
|
||||
* @param scope the bson scope.
|
||||
*/
|
||||
/* calls bson_empty on scope if not a bson_codewscope */
|
||||
void bson_iterator_code_scope( const bson_iterator *i, bson *scope );
|
||||
|
||||
/**
|
||||
* Get the date value of the BSON object currently pointed to by the
|
||||
* iterator.
|
||||
*
|
||||
* @param i the bson_iterator
|
||||
*
|
||||
* @return the date value of the current BSON object.
|
||||
*/
|
||||
/* both of these only work with bson_date */
|
||||
bson_date_t bson_iterator_date( const bson_iterator *i );
|
||||
|
||||
/**
|
||||
* Get the time value of the BSON object currently pointed to by the
|
||||
* iterator.
|
||||
*
|
||||
* @param i the bson_iterator
|
||||
*
|
||||
* @return the time value of the current BSON object.
|
||||
*/
|
||||
time_t bson_iterator_time_t( const bson_iterator *i );
|
||||
|
||||
/**
|
||||
* Get the length of the BSON binary object currently pointed to by the
|
||||
* iterator.
|
||||
*
|
||||
* @param i the bson_iterator
|
||||
*
|
||||
* @return the length of the current BSON binary object.
|
||||
*/
|
||||
int bson_iterator_bin_len( const bson_iterator *i );
|
||||
|
||||
/**
|
||||
* Get the type of the BSON binary object currently pointed to by the
|
||||
* iterator.
|
||||
*
|
||||
* @param i the bson_iterator
|
||||
*
|
||||
* @return the type of the current BSON binary object.
|
||||
*/
|
||||
char bson_iterator_bin_type( const bson_iterator *i );
|
||||
|
||||
/**
|
||||
* Get the value of the BSON binary object currently pointed to by the
|
||||
* iterator.
|
||||
*
|
||||
* @param i the bson_iterator
|
||||
*
|
||||
* @return the value of the current BSON binary object.
|
||||
*/
|
||||
const char *bson_iterator_bin_data( const bson_iterator *i );
|
||||
|
||||
/**
|
||||
* Get the value of the BSON regex object currently pointed to by the
|
||||
* iterator.
|
||||
*
|
||||
* @param i the bson_iterator
|
||||
*
|
||||
* @return the value of the current BSON regex object.
|
||||
*/
|
||||
const char *bson_iterator_regex( const bson_iterator *i );
|
||||
|
||||
/**
|
||||
* Get the options of the BSON regex object currently pointed to by the
|
||||
* iterator.
|
||||
*
|
||||
* @param i the bson_iterator.
|
||||
*
|
||||
* @return the options of the current BSON regex object.
|
||||
*/
|
||||
const char *bson_iterator_regex_opts( const bson_iterator *i );
|
||||
|
||||
/* these work with BSON_OBJECT and BSON_ARRAY */
|
||||
/**
|
||||
* Get the BSON subobject currently pointed to by the
|
||||
* iterator.
|
||||
*
|
||||
* @param i the bson_iterator.
|
||||
* @param sub the BSON subobject destination.
|
||||
*/
|
||||
void bson_iterator_subobject( const bson_iterator *i, bson *sub );
|
||||
|
||||
/**
|
||||
* Get a bson_iterator that on the BSON subobject.
|
||||
*
|
||||
* @param i the bson_iterator.
|
||||
* @param sub the iterator to point at the BSON subobject.
|
||||
*/
|
||||
void bson_iterator_subiterator( const bson_iterator *i, bson_iterator *sub );
|
||||
|
||||
/* str must be at least 24 hex chars + null byte */
|
||||
/**
|
||||
* Create a bson_oid_t from a string.
|
||||
*
|
||||
* @param oid the bson_oid_t destination.
|
||||
* @param str a null terminated string comprised of at least 24 hex chars.
|
||||
*/
|
||||
void bson_oid_from_string( bson_oid_t *oid, const char *str );
|
||||
|
||||
/**
|
||||
* Create a string representation of the bson_oid_t.
|
||||
*
|
||||
* @param oid the bson_oid_t source.
|
||||
* @param str the string representation destination.
|
||||
*/
|
||||
void bson_oid_to_string( const bson_oid_t *oid, char *str );
|
||||
|
||||
/**
|
||||
* Create a bson_oid object.
|
||||
*
|
||||
* @param oid the destination for the newly created bson_oid_t.
|
||||
*/
|
||||
void bson_oid_gen( bson_oid_t *oid );
|
||||
|
||||
/**
|
||||
* Set a function to be used to generate the second four bytes
|
||||
* of an object id.
|
||||
*
|
||||
* @param func a pointer to a function that returns an int.
|
||||
*/
|
||||
void bson_set_oid_fuzz( int ( *func )( void ) );
|
||||
|
||||
/**
|
||||
* Set a function to be used to generate the incrementing part
|
||||
* of an object id (last four bytes). If you need thread-safety
|
||||
* in generating object ids, you should set this function.
|
||||
*
|
||||
* @param func a pointer to a function that returns an int.
|
||||
*/
|
||||
void bson_set_oid_inc( int ( *func )( void ) );
|
||||
|
||||
/**
|
||||
* Get the time a bson_oid_t was created.
|
||||
*
|
||||
* @param oid the bson_oid_t.
|
||||
*/
|
||||
time_t bson_oid_generated_time( bson_oid_t *oid ); /* Gives the time the OID was created */
|
||||
|
||||
/* ----------------------------
|
||||
BUILDING
|
||||
------------------------------ */
|
||||
|
||||
/**
|
||||
* Initialize a new bson object. If not created
|
||||
* with bson_new, you must initialize each new bson
|
||||
* object using this function.
|
||||
*
|
||||
* @note When finished, you must pass the bson object to
|
||||
* bson_destroy( ).
|
||||
*/
|
||||
void bson_init( bson *b );
|
||||
|
||||
/**
|
||||
* Initialize a BSON object, and point its data
|
||||
* pointer to the provided char*.
|
||||
*
|
||||
* @param b the BSON object to initialize.
|
||||
* @param data the raw BSON data.
|
||||
*
|
||||
* @return BSON_OK or BSON_ERROR.
|
||||
*/
|
||||
int bson_init_data( bson *b , char *data );
|
||||
|
||||
/**
|
||||
* Initialize a BSON object, and set its
|
||||
* buffer to the given size.
|
||||
*
|
||||
* @param b the BSON object to initialize.
|
||||
* @param size the initial size of the buffer.
|
||||
*
|
||||
* @return BSON_OK or BSON_ERROR.
|
||||
*/
|
||||
void bson_init_size( bson *b, int size );
|
||||
|
||||
/**
|
||||
* Grow a bson object.
|
||||
*
|
||||
* @param b the bson to grow.
|
||||
* @param bytesNeeded the additional number of bytes needed.
|
||||
*
|
||||
* @return BSON_OK or BSON_ERROR with the bson error object set.
|
||||
* Exits if allocation fails.
|
||||
*/
|
||||
int bson_ensure_space( bson *b, const int bytesNeeded );
|
||||
|
||||
/**
|
||||
* Finalize a bson object.
|
||||
*
|
||||
* @param b the bson object to finalize.
|
||||
*
|
||||
* @return the standard error code. To deallocate memory,
|
||||
* call bson_destroy on the bson object.
|
||||
*/
|
||||
int bson_finish( bson *b );
|
||||
|
||||
/**
|
||||
* Destroy a bson object.
|
||||
*
|
||||
* @param b the bson object to destroy.
|
||||
*
|
||||
*/
|
||||
void bson_destroy( bson *b );
|
||||
|
||||
/**
|
||||
* Returns a pointer to a static empty BSON object.
|
||||
*
|
||||
* @param obj the BSON object to initialize.
|
||||
*
|
||||
* @return the empty initialized BSON object.
|
||||
*/
|
||||
/* returns pointer to static empty bson object */
|
||||
bson *bson_empty( bson *obj );
|
||||
|
||||
/**
|
||||
* Copy BSON data only from one object to another.
|
||||
*
|
||||
* @param out the copy destination BSON object.
|
||||
* @param in the copy source BSON object.
|
||||
*/
|
||||
void bson_copy_basic( bson *out, const bson *in );
|
||||
|
||||
/**
|
||||
* Make a complete copy of the a BSON object.
|
||||
*
|
||||
* @param out the copy destination BSON object.
|
||||
* @param in the copy source BSON object.
|
||||
*/
|
||||
void bson_copy( bson *out, const bson *in ); /* puts data in new buffer. NOOP if out==NULL */
|
||||
|
||||
/**
|
||||
* Append a previously created bson_oid_t to a bson object.
|
||||
*
|
||||
* @param b the bson to append to.
|
||||
* @param name the key for the bson_oid_t.
|
||||
* @param oid the bson_oid_t to append.
|
||||
*
|
||||
* @return BSON_OK or BSON_ERROR.
|
||||
*/
|
||||
int bson_append_oid( bson *b, const char *name, const bson_oid_t *oid );
|
||||
|
||||
/**
|
||||
* Append a bson_oid_t to a bson.
|
||||
*
|
||||
* @param b the bson to append to.
|
||||
* @param name the key for the bson_oid_t.
|
||||
*
|
||||
* @return BSON_OK or BSON_ERROR.
|
||||
*/
|
||||
int bson_append_new_oid( bson *b, const char *name );
|
||||
|
||||
/**
|
||||
* Append an int to a bson.
|
||||
*
|
||||
* @param b the bson to append to.
|
||||
* @param name the key for the int.
|
||||
* @param i the int to append.
|
||||
*
|
||||
* @return BSON_OK or BSON_ERROR.
|
||||
*/
|
||||
int bson_append_int( bson *b, const char *name, const int i );
|
||||
|
||||
/**
|
||||
* Append an long to a bson.
|
||||
*
|
||||
* @param b the bson to append to.
|
||||
* @param name the key for the long.
|
||||
* @param i the long to append.
|
||||
*
|
||||
* @return BSON_OK or BSON_ERROR.
|
||||
*/
|
||||
int bson_append_long( bson *b, const char *name, const int64_t i );
|
||||
|
||||
/**
|
||||
* Append an double to a bson.
|
||||
*
|
||||
* @param b the bson to append to.
|
||||
* @param name the key for the double.
|
||||
* @param d the double to append.
|
||||
*
|
||||
* @return BSON_OK or BSON_ERROR.
|
||||
*/
|
||||
int bson_append_double( bson *b, const char *name, const double d );
|
||||
|
||||
/**
|
||||
* Append a string to a bson.
|
||||
*
|
||||
* @param b the bson to append to.
|
||||
* @param name the key for the string.
|
||||
* @param str the string to append.
|
||||
*
|
||||
* @return BSON_OK or BSON_ERROR.
|
||||
*/
|
||||
int bson_append_string( bson *b, const char *name, const char *str );
|
||||
|
||||
/**
|
||||
* Append len bytes of a string to a bson.
|
||||
*
|
||||
* @param b the bson to append to.
|
||||
* @param name the key for the string.
|
||||
* @param str the string to append.
|
||||
* @param len the number of bytes from str to append.
|
||||
*
|
||||
* @return BSON_OK or BSON_ERROR.
|
||||
*/
|
||||
int bson_append_string_n( bson *b, const char *name, const char *str, int len );
|
||||
|
||||
/**
|
||||
* Append a symbol to a bson.
|
||||
*
|
||||
* @param b the bson to append to.
|
||||
* @param name the key for the symbol.
|
||||
* @param str the symbol to append.
|
||||
*
|
||||
* @return BSON_OK or BSON_ERROR.
|
||||
*/
|
||||
int bson_append_symbol( bson *b, const char *name, const char *str );
|
||||
|
||||
/**
|
||||
* Append len bytes of a symbol to a bson.
|
||||
*
|
||||
* @param b the bson to append to.
|
||||
* @param name the key for the symbol.
|
||||
* @param str the symbol to append.
|
||||
* @param len the number of bytes from str to append.
|
||||
*
|
||||
* @return BSON_OK or BSON_ERROR.
|
||||
*/
|
||||
int bson_append_symbol_n( bson *b, const char *name, const char *str, int len );
|
||||
|
||||
/**
|
||||
* Append code to a bson.
|
||||
*
|
||||
* @param b the bson to append to.
|
||||
* @param name the key for the code.
|
||||
* @param str the code to append.
|
||||
* @param len the number of bytes from str to append.
|
||||
*
|
||||
* @return BSON_OK or BSON_ERROR.
|
||||
*/
|
||||
int bson_append_code( bson *b, const char *name, const char *str );
|
||||
|
||||
/**
|
||||
* Append len bytes of code to a bson.
|
||||
*
|
||||
* @param b the bson to append to.
|
||||
* @param name the key for the code.
|
||||
* @param str the code to append.
|
||||
* @param len the number of bytes from str to append.
|
||||
*
|
||||
* @return BSON_OK or BSON_ERROR.
|
||||
*/
|
||||
int bson_append_code_n( bson *b, const char *name, const char *str, int len );
|
||||
|
||||
/**
|
||||
* Append code to a bson with scope.
|
||||
*
|
||||
* @param b the bson to append to.
|
||||
* @param name the key for the code.
|
||||
* @param str the string to append.
|
||||
* @param scope a BSON object containing the scope.
|
||||
*
|
||||
* @return BSON_OK or BSON_ERROR.
|
||||
*/
|
||||
int bson_append_code_w_scope( bson *b, const char *name, const char *code, const bson *scope );
|
||||
|
||||
/**
|
||||
* Append len bytes of code to a bson with scope.
|
||||
*
|
||||
* @param b the bson to append to.
|
||||
* @param name the key for the code.
|
||||
* @param str the string to append.
|
||||
* @param len the number of bytes from str to append.
|
||||
* @param scope a BSON object containing the scope.
|
||||
*
|
||||
* @return BSON_OK or BSON_ERROR.
|
||||
*/
|
||||
int bson_append_code_w_scope_n( bson *b, const char *name, const char *code, int size, const bson *scope );
|
||||
|
||||
/**
|
||||
* Append binary data to a bson.
|
||||
*
|
||||
* @param b the bson to append to.
|
||||
* @param name the key for the data.
|
||||
* @param type the binary data type.
|
||||
* @param str the binary data.
|
||||
* @param len the length of the data.
|
||||
*
|
||||
* @return BSON_OK or BSON_ERROR.
|
||||
*/
|
||||
int bson_append_binary( bson *b, const char *name, char type, const char *str, int len );
|
||||
|
||||
/**
|
||||
* Append a bson_bool_t to a bson.
|
||||
*
|
||||
* @param b the bson to append to.
|
||||
* @param name the key for the boolean value.
|
||||
* @param v the bson_bool_t to append.
|
||||
*
|
||||
* @return BSON_OK or BSON_ERROR.
|
||||
*/
|
||||
int bson_append_bool( bson *b, const char *name, const bson_bool_t v );
|
||||
|
||||
/**
|
||||
* Append a null value to a bson.
|
||||
*
|
||||
* @param b the bson to append to.
|
||||
* @param name the key for the null value.
|
||||
*
|
||||
* @return BSON_OK or BSON_ERROR.
|
||||
*/
|
||||
int bson_append_null( bson *b, const char *name );
|
||||
|
||||
/**
|
||||
* Append an undefined value to a bson.
|
||||
*
|
||||
* @param b the bson to append to.
|
||||
* @param name the key for the undefined value.
|
||||
*
|
||||
* @return BSON_OK or BSON_ERROR.
|
||||
*/
|
||||
int bson_append_undefined( bson *b, const char *name );
|
||||
|
||||
/**
|
||||
* Append a regex value to a bson.
|
||||
*
|
||||
* @param b the bson to append to.
|
||||
* @param name the key for the regex value.
|
||||
* @param pattern the regex pattern to append.
|
||||
* @param the regex options.
|
||||
*
|
||||
* @return BSON_OK or BSON_ERROR.
|
||||
*/
|
||||
int bson_append_regex( bson *b, const char *name, const char *pattern, const char *opts );
|
||||
|
||||
/**
|
||||
* Append bson data to a bson.
|
||||
*
|
||||
* @param b the bson to append to.
|
||||
* @param name the key for the bson data.
|
||||
* @param bson the bson object to append.
|
||||
*
|
||||
* @return BSON_OK or BSON_ERROR.
|
||||
*/
|
||||
int bson_append_bson( bson *b, const char *name, const bson *bson );
|
||||
|
||||
/**
|
||||
* Append a BSON element to a bson from the current point of an iterator.
|
||||
*
|
||||
* @param b the bson to append to.
|
||||
* @param name_or_null the key for the BSON element, or NULL.
|
||||
* @param elem the bson_iterator.
|
||||
*
|
||||
* @return BSON_OK or BSON_ERROR.
|
||||
*/
|
||||
int bson_append_element( bson *b, const char *name_or_null, const bson_iterator *elem );
|
||||
|
||||
/**
|
||||
* Append a bson_timestamp_t value to a bson.
|
||||
*
|
||||
* @param b the bson to append to.
|
||||
* @param name the key for the timestampe value.
|
||||
* @param ts the bson_timestamp_t value to append.
|
||||
*
|
||||
* @return BSON_OK or BSON_ERROR.
|
||||
*/
|
||||
int bson_append_timestamp( bson *b, const char *name, bson_timestamp_t *ts );
|
||||
|
||||
/* these both append a bson_date */
|
||||
/**
|
||||
* Append a bson_date_t value to a bson.
|
||||
*
|
||||
* @param b the bson to append to.
|
||||
* @param name the key for the date value.
|
||||
* @param millis the bson_date_t to append.
|
||||
*
|
||||
* @return BSON_OK or BSON_ERROR.
|
||||
*/
|
||||
int bson_append_date( bson *b, const char *name, bson_date_t millis );
|
||||
|
||||
/**
|
||||
* Append a time_t value to a bson.
|
||||
*
|
||||
* @param b the bson to append to.
|
||||
* @param name the key for the date value.
|
||||
* @param secs the time_t to append.
|
||||
*
|
||||
* @return BSON_OK or BSON_ERROR.
|
||||
*/
|
||||
int bson_append_time_t( bson *b, const char *name, time_t secs );
|
||||
|
||||
/**
|
||||
* Start appending a new object to a bson.
|
||||
*
|
||||
* @param b the bson to append to.
|
||||
* @param name the name of the new object.
|
||||
*
|
||||
* @return BSON_OK or BSON_ERROR.
|
||||
*/
|
||||
int bson_append_start_object( bson *b, const char *name );
|
||||
|
||||
/**
|
||||
* Start appending a new array to a bson.
|
||||
*
|
||||
* @param b the bson to append to.
|
||||
* @param name the name of the new array.
|
||||
*
|
||||
* @return BSON_OK or BSON_ERROR.
|
||||
*/
|
||||
int bson_append_start_array( bson *b, const char *name );
|
||||
|
||||
/**
|
||||
* Finish appending a new object or array to a bson.
|
||||
*
|
||||
* @param b the bson to append to.
|
||||
*
|
||||
* @return BSON_OK or BSON_ERROR.
|
||||
*/
|
||||
int bson_append_finish_object( bson *b );
|
||||
|
||||
/**
|
||||
* Finish appending a new object or array to a bson. This
|
||||
* is simply an alias for bson_append_finish_object.
|
||||
*
|
||||
* @param b the bson to append to.
|
||||
*
|
||||
* @return BSON_OK or BSON_ERROR.
|
||||
*/
|
||||
int bson_append_finish_array( bson *b );
|
||||
|
||||
void bson_numstr( char *str, int i );
|
||||
|
||||
void bson_incnumstr( char *str );
|
||||
|
||||
/* Error handling and stadard library function over-riding. */
|
||||
/* -------------------------------------------------------- */
|
||||
|
||||
/* bson_err_handlers shouldn't return!!! */
|
||||
typedef void( *bson_err_handler )( const char *errmsg );
|
||||
|
||||
typedef int (*bson_printf_func)( const char *, ... );
|
||||
typedef int (*bson_fprintf_func)( FILE *, const char *, ... );
|
||||
typedef int (*bson_sprintf_func)( char *, const char *, ... );
|
||||
|
||||
extern void *( *bson_malloc_func )( size_t );
|
||||
extern void *( *bson_realloc_func )( void *, size_t );
|
||||
extern void ( *bson_free )( void * );
|
||||
|
||||
extern bson_printf_func bson_printf;
|
||||
extern bson_fprintf_func bson_fprintf;
|
||||
extern bson_sprintf_func bson_sprintf;
|
||||
|
||||
extern bson_printf_func bson_errprintf;
|
||||
|
||||
/**
|
||||
* Allocates memory and checks return value, exiting fatally if malloc() fails.
|
||||
*
|
||||
* @param size bytes to allocate.
|
||||
*
|
||||
* @return a pointer to the allocated memory.
|
||||
*
|
||||
* @sa malloc(3)
|
||||
*/
|
||||
void *bson_malloc( int size );
|
||||
|
||||
/**
|
||||
* Changes the size of allocated memory and checks return value,
|
||||
* exiting fatally if realloc() fails.
|
||||
*
|
||||
* @param ptr pointer to the space to reallocate.
|
||||
* @param size bytes to allocate.
|
||||
*
|
||||
* @return a pointer to the allocated memory.
|
||||
*
|
||||
* @sa realloc()
|
||||
*/
|
||||
void *bson_realloc( void *ptr, int size );
|
||||
|
||||
/**
|
||||
* Set a function for error handling.
|
||||
*
|
||||
* @param func a bson_err_handler function.
|
||||
*
|
||||
* @return the old error handling function, or NULL.
|
||||
*/
|
||||
bson_err_handler set_bson_err_handler( bson_err_handler func );
|
||||
|
||||
/* does nothing if ok != 0 */
|
||||
/**
|
||||
* Exit fatally.
|
||||
*
|
||||
* @param ok exits if ok is equal to 0.
|
||||
*/
|
||||
void bson_fatal( int ok );
|
||||
|
||||
/**
|
||||
* Exit fatally with an error message.
|
||||
*
|
||||
* @param ok exits if ok is equal to 0.
|
||||
* @param msg prints to stderr before exiting.
|
||||
*/
|
||||
void bson_fatal_msg( int ok, const char *msg );
|
||||
|
||||
/**
|
||||
* Invoke the error handler, but do not exit.
|
||||
*
|
||||
* @param b the buffer object.
|
||||
*/
|
||||
void bson_builder_error( bson *b );
|
||||
|
||||
MONGO_EXTERN_C_END
|
||||
#endif
|
148
src/mod/event_handlers/mod_cdr_mongodb/driver/src/encoding.c
Normal file
148
src/mod/event_handlers/mod_cdr_mongodb/driver/src/encoding.c
Normal file
@ -0,0 +1,148 @@
|
||||
/*
|
||||
* Copyright 2009-2011 10gen, Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Portions Copyright 2001 Unicode, Inc.
|
||||
*
|
||||
* Disclaimer
|
||||
*
|
||||
* This source code is provided as is by Unicode, Inc. No claims are
|
||||
* made as to fitness for any particular purpose. No warranties of any
|
||||
* kind are expressed or implied. The recipient agrees to determine
|
||||
* applicability of information provided. If this file has been
|
||||
* purchased on magnetic or optical media from Unicode, Inc., the
|
||||
* sole remedy for any claim will be exchange of defective media
|
||||
* within 90 days of receipt.
|
||||
*
|
||||
* Limitations on Rights to Redistribute This Code
|
||||
*
|
||||
* Unicode, Inc. hereby grants the right to freely use the information
|
||||
* supplied in this file in the creation of products supporting the
|
||||
* Unicode Standard, and to make copies of this file in any form
|
||||
* for internal or external distribution as long as this notice
|
||||
* remains attached.
|
||||
*/
|
||||
|
||||
|
||||
#include "bson.h"
|
||||
#include "encoding.h"
|
||||
|
||||
/*
|
||||
* Index into the table below with the first byte of a UTF-8 sequence to
|
||||
* get the number of trailing bytes that are supposed to follow it.
|
||||
*/
|
||||
static const char trailingBytesForUTF8[256] = {
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
|
||||
2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, 3,3,3,3,3,3,3,3,4,4,4,4,5,5,5,5
|
||||
};
|
||||
|
||||
/* --------------------------------------------------------------------- */
|
||||
|
||||
/*
|
||||
* Utility routine to tell whether a sequence of bytes is legal UTF-8.
|
||||
* This must be called with the length pre-determined by the first byte.
|
||||
* The length can be set by:
|
||||
* length = trailingBytesForUTF8[*source]+1;
|
||||
* and the sequence is illegal right away if there aren't that many bytes
|
||||
* available.
|
||||
* If presented with a length > 4, this returns 0. The Unicode
|
||||
* definition of UTF-8 goes up to 4-byte sequences.
|
||||
*/
|
||||
static int isLegalUTF8( const unsigned char *source, int length ) {
|
||||
unsigned char a;
|
||||
const unsigned char *srcptr = source + length;
|
||||
switch ( length ) {
|
||||
default:
|
||||
return 0;
|
||||
/* Everything else falls through when "true"... */
|
||||
case 4:
|
||||
if ( ( a = ( *--srcptr ) ) < 0x80 || a > 0xBF ) return 0;
|
||||
case 3:
|
||||
if ( ( a = ( *--srcptr ) ) < 0x80 || a > 0xBF ) return 0;
|
||||
case 2:
|
||||
if ( ( a = ( *--srcptr ) ) > 0xBF ) return 0;
|
||||
switch ( *source ) {
|
||||
/* no fall-through in this inner switch */
|
||||
case 0xE0:
|
||||
if ( a < 0xA0 ) return 0;
|
||||
break;
|
||||
case 0xF0:
|
||||
if ( a < 0x90 ) return 0;
|
||||
break;
|
||||
case 0xF4:
|
||||
if ( a > 0x8F ) return 0;
|
||||
break;
|
||||
default:
|
||||
if ( a < 0x80 ) return 0;
|
||||
}
|
||||
case 1:
|
||||
if ( *source >= 0x80 && *source < 0xC2 ) return 0;
|
||||
if ( *source > 0xF4 ) return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int bson_validate_string( bson *b, const unsigned char *string,
|
||||
const int length, const char check_utf8, const char check_dot,
|
||||
const char check_dollar ) {
|
||||
|
||||
int position = 0;
|
||||
int sequence_length = 1;
|
||||
|
||||
if( check_dollar && string[0] == '$' ) {
|
||||
b->err |= BSON_FIELD_INIT_DOLLAR;
|
||||
}
|
||||
|
||||
while ( position < length ) {
|
||||
if ( check_dot && *( string + position ) == '.' ) {
|
||||
b->err |= BSON_FIELD_HAS_DOT;
|
||||
}
|
||||
|
||||
if ( check_utf8 ) {
|
||||
sequence_length = trailingBytesForUTF8[*( string + position )] + 1;
|
||||
if ( ( position + sequence_length ) > length ) {
|
||||
b->err |= BSON_NOT_UTF8;
|
||||
return BSON_ERROR;
|
||||
}
|
||||
if ( !isLegalUTF8( string + position, sequence_length ) ) {
|
||||
b->err |= BSON_NOT_UTF8;
|
||||
return BSON_ERROR;
|
||||
}
|
||||
}
|
||||
position += sequence_length;
|
||||
}
|
||||
|
||||
return BSON_OK;
|
||||
}
|
||||
|
||||
|
||||
int bson_check_string( bson *b, const char *string,
|
||||
const int length ) {
|
||||
|
||||
return bson_validate_string( b, ( const unsigned char * )string, length, 1, 0, 0 );
|
||||
}
|
||||
|
||||
int bson_check_field_name( bson *b, const char *string,
|
||||
const int length ) {
|
||||
|
||||
return bson_validate_string( b, ( const unsigned char * )string, length, 1, 1, 1 );
|
||||
}
|
54
src/mod/event_handlers/mod_cdr_mongodb/driver/src/encoding.h
Normal file
54
src/mod/event_handlers/mod_cdr_mongodb/driver/src/encoding.h
Normal file
@ -0,0 +1,54 @@
|
||||
/*
|
||||
* Copyright 2009-2011 10gen, Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef _BSON_ENCODING_H_
|
||||
#define _BSON_ENCODING_H_
|
||||
|
||||
MONGO_EXTERN_C_START
|
||||
|
||||
/**
|
||||
* Check that a field name is valid UTF8, does not start with a '$',
|
||||
* and contains no '.' characters. Set bson bit field appropriately.
|
||||
* Note that we don't need to check for '\0' because we're using
|
||||
* strlen(3), which stops at '\0'.
|
||||
*
|
||||
* @param b The bson object to which field name will be appended.
|
||||
* @param string The field name as char*.
|
||||
* @param length The length of the field name.
|
||||
*
|
||||
* @return BSON_OK if valid UTF8 and BSON_ERROR if not. All BSON strings must be
|
||||
* valid UTF8. This function will also check whether the string
|
||||
* contains '.' or starts with '$', since the validity of this depends on context.
|
||||
* Set the value of b->err appropriately.
|
||||
*/
|
||||
int bson_check_field_name( bson *b, const char *string,
|
||||
const int length );
|
||||
|
||||
/**
|
||||
* Check that a string is valid UTF8. Sets the buffer bit field appropriately.
|
||||
*
|
||||
* @param b The bson object to which string will be appended.
|
||||
* @param string The string to check.
|
||||
* @param length The length of the string.
|
||||
*
|
||||
* @return BSON_OK if valid UTF-8; otherwise, BSON_ERROR.
|
||||
* Sets b->err on error.
|
||||
*/
|
||||
bson_bool_t bson_check_string( bson *b, const char *string,
|
||||
const int length );
|
||||
|
||||
MONGO_EXTERN_C_END
|
||||
#endif
|
685
src/mod/event_handlers/mod_cdr_mongodb/driver/src/gridfs.c
Normal file
685
src/mod/event_handlers/mod_cdr_mongodb/driver/src/gridfs.c
Normal file
@ -0,0 +1,685 @@
|
||||
/* gridfs.c */
|
||||
|
||||
/* Copyright 2009-2011 10gen Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include "gridfs.h"
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <assert.h>
|
||||
|
||||
static bson *chunk_new( bson_oid_t id, int chunkNumber,
|
||||
const char *data, int len ) {
|
||||
bson *b = bson_malloc( sizeof( bson ) );
|
||||
|
||||
bson_init( b );
|
||||
bson_append_oid( b, "files_id", &id );
|
||||
bson_append_int( b, "n", chunkNumber );
|
||||
bson_append_binary( b, "data", BSON_BIN_BINARY, data, len );
|
||||
bson_finish( b );
|
||||
return b;
|
||||
}
|
||||
|
||||
static void chunk_free( bson *oChunk ) {
|
||||
bson_destroy( oChunk );
|
||||
bson_free( oChunk );
|
||||
}
|
||||
|
||||
int gridfs_init( mongo *client, const char *dbname, const char *prefix,
|
||||
gridfs *gfs ) {
|
||||
|
||||
int options;
|
||||
bson b;
|
||||
bson_bool_t success;
|
||||
|
||||
gfs->client = client;
|
||||
|
||||
/* Allocate space to own the dbname */
|
||||
gfs->dbname = ( const char * )bson_malloc( strlen( dbname )+1 );
|
||||
strcpy( ( char * )gfs->dbname, dbname );
|
||||
|
||||
/* Allocate space to own the prefix */
|
||||
if ( prefix == NULL ) prefix = "fs";
|
||||
gfs->prefix = ( const char * )bson_malloc( strlen( prefix )+1 );
|
||||
strcpy( ( char * )gfs->prefix, prefix );
|
||||
|
||||
/* Allocate space to own files_ns */
|
||||
gfs->files_ns =
|
||||
( const char * ) bson_malloc ( strlen( prefix )+strlen( dbname )+strlen( ".files" )+2 );
|
||||
strcpy( ( char * )gfs->files_ns, dbname );
|
||||
strcat( ( char * )gfs->files_ns, "." );
|
||||
strcat( ( char * )gfs->files_ns, prefix );
|
||||
strcat( ( char * )gfs->files_ns, ".files" );
|
||||
|
||||
/* Allocate space to own chunks_ns */
|
||||
gfs->chunks_ns = ( const char * ) bson_malloc( strlen( prefix ) + strlen( dbname )
|
||||
+ strlen( ".chunks" ) + 2 );
|
||||
strcpy( ( char * )gfs->chunks_ns, dbname );
|
||||
strcat( ( char * )gfs->chunks_ns, "." );
|
||||
strcat( ( char * )gfs->chunks_ns, prefix );
|
||||
strcat( ( char * )gfs->chunks_ns, ".chunks" );
|
||||
|
||||
bson_init( &b );
|
||||
bson_append_int( &b, "filename", 1 );
|
||||
bson_finish( &b );
|
||||
options = 0;
|
||||
success = ( mongo_create_index( gfs->client, gfs->files_ns, &b, options, NULL ) == MONGO_OK );
|
||||
bson_destroy( &b );
|
||||
if ( !success ) {
|
||||
bson_free( ( char * )gfs->dbname );
|
||||
bson_free( ( char * )gfs->prefix );
|
||||
bson_free( ( char * )gfs->files_ns );
|
||||
bson_free( ( char * )gfs->chunks_ns );
|
||||
return MONGO_ERROR;
|
||||
}
|
||||
|
||||
bson_init( &b );
|
||||
bson_append_int( &b, "files_id", 1 );
|
||||
bson_append_int( &b, "n", 1 );
|
||||
bson_finish( &b );
|
||||
options = MONGO_INDEX_UNIQUE;
|
||||
success = ( mongo_create_index( gfs->client, gfs->chunks_ns, &b, options, NULL ) == MONGO_OK );
|
||||
bson_destroy( &b );
|
||||
if ( !success ) {
|
||||
bson_free( ( char * )gfs->dbname );
|
||||
bson_free( ( char * )gfs->prefix );
|
||||
bson_free( ( char * )gfs->files_ns );
|
||||
bson_free( ( char * )gfs->chunks_ns );
|
||||
return MONGO_ERROR;
|
||||
}
|
||||
|
||||
return MONGO_OK;
|
||||
}
|
||||
|
||||
void gridfs_destroy( gridfs *gfs ) {
|
||||
if ( gfs == NULL ) return;
|
||||
if ( gfs->dbname ) bson_free( ( char * )gfs->dbname );
|
||||
if ( gfs->prefix ) bson_free( ( char * )gfs->prefix );
|
||||
if ( gfs->files_ns ) bson_free( ( char * )gfs->files_ns );
|
||||
if ( gfs->chunks_ns ) bson_free( ( char * )gfs->chunks_ns );
|
||||
}
|
||||
|
||||
static int gridfs_insert_file( gridfs *gfs, const char *name,
|
||||
const bson_oid_t id, gridfs_offset length,
|
||||
const char *contenttype ) {
|
||||
bson command;
|
||||
bson ret;
|
||||
bson res;
|
||||
bson_iterator it;
|
||||
int result;
|
||||
|
||||
/* Check run md5 */
|
||||
bson_init( &command );
|
||||
bson_append_oid( &command, "filemd5", &id );
|
||||
bson_append_string( &command, "root", gfs->prefix );
|
||||
bson_finish( &command );
|
||||
assert( mongo_run_command( gfs->client, gfs->dbname, &command, &res ) == MONGO_OK );
|
||||
bson_destroy( &command );
|
||||
|
||||
/* Create and insert BSON for file metadata */
|
||||
bson_init( &ret );
|
||||
bson_append_oid( &ret, "_id", &id );
|
||||
if ( name != NULL && *name != '\0' ) {
|
||||
bson_append_string( &ret, "filename", name );
|
||||
}
|
||||
bson_append_long( &ret, "length", length );
|
||||
bson_append_int( &ret, "chunkSize", DEFAULT_CHUNK_SIZE );
|
||||
bson_append_date( &ret, "uploadDate", ( bson_date_t )1000*time( NULL ) );
|
||||
bson_find( &it, &res, "md5" );
|
||||
bson_append_string( &ret, "md5", bson_iterator_string( &it ) );
|
||||
bson_destroy( &res );
|
||||
if ( contenttype != NULL && *contenttype != '\0' ) {
|
||||
bson_append_string( &ret, "contentType", contenttype );
|
||||
}
|
||||
bson_finish( &ret );
|
||||
result = mongo_insert( gfs->client, gfs->files_ns, &ret );
|
||||
bson_destroy( &ret );
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
int gridfs_store_buffer( gridfs *gfs, const char *data,
|
||||
gridfs_offset length, const char *remotename,
|
||||
const char *contenttype ) {
|
||||
|
||||
char const *end = data + length;
|
||||
const char *data_ptr = data;
|
||||
bson_oid_t id;
|
||||
int chunkNumber = 0;
|
||||
int chunkLen;
|
||||
bson *oChunk;
|
||||
|
||||
/* Large files Assertion */
|
||||
assert( length <= 0xffffffff );
|
||||
|
||||
/* Generate and append an oid*/
|
||||
bson_oid_gen( &id );
|
||||
|
||||
/* Insert the file's data chunk by chunk */
|
||||
while ( data_ptr < end ) {
|
||||
chunkLen = DEFAULT_CHUNK_SIZE < ( unsigned int )( end - data_ptr ) ?
|
||||
DEFAULT_CHUNK_SIZE : ( unsigned int )( end - data_ptr );
|
||||
oChunk = chunk_new( id, chunkNumber, data_ptr, chunkLen );
|
||||
mongo_insert( gfs->client, gfs->chunks_ns, oChunk );
|
||||
chunk_free( oChunk );
|
||||
chunkNumber++;
|
||||
data_ptr += chunkLen;
|
||||
}
|
||||
|
||||
/* Inserts file's metadata */
|
||||
return gridfs_insert_file( gfs, remotename, id, length, contenttype );
|
||||
}
|
||||
|
||||
void gridfile_writer_init( gridfile *gfile, gridfs *gfs,
|
||||
const char *remote_name, const char *content_type ) {
|
||||
gfile->gfs = gfs;
|
||||
|
||||
bson_oid_gen( &( gfile->id ) );
|
||||
gfile->chunk_num = 0;
|
||||
gfile->length = 0;
|
||||
gfile->pending_len = 0;
|
||||
gfile->pending_data = NULL;
|
||||
|
||||
gfile->remote_name = ( char * )bson_malloc( strlen( remote_name ) + 1 );
|
||||
strcpy( ( char * )gfile->remote_name, remote_name );
|
||||
|
||||
gfile->content_type = ( char * )bson_malloc( strlen( content_type ) + 1 );
|
||||
strcpy( ( char * )gfile->content_type, content_type );
|
||||
}
|
||||
|
||||
void gridfile_write_buffer( gridfile *gfile, const char *data,
|
||||
gridfs_offset length ) {
|
||||
|
||||
int bytes_left = 0;
|
||||
int data_partial_len = 0;
|
||||
int chunks_to_write = 0;
|
||||
char *buffer;
|
||||
bson *oChunk;
|
||||
gridfs_offset to_write = length + gfile->pending_len;
|
||||
|
||||
if ( to_write < DEFAULT_CHUNK_SIZE ) { /* Less than one chunk to write */
|
||||
if( gfile->pending_data ) {
|
||||
gfile->pending_data = ( char * )bson_realloc( ( void * )gfile->pending_data, gfile->pending_len + to_write );
|
||||
memcpy( gfile->pending_data + gfile->pending_len, data, length );
|
||||
} else if ( to_write > 0 ) {
|
||||
gfile->pending_data = ( char * )bson_malloc( to_write );
|
||||
memcpy( gfile->pending_data, data, length );
|
||||
}
|
||||
gfile->pending_len += length;
|
||||
|
||||
} else { /* At least one chunk of data to write */
|
||||
|
||||
/* If there's a pending chunk to be written, we need to combine
|
||||
* the buffer provided up to DEFAULT_CHUNK_SIZE.
|
||||
*/
|
||||
if ( gfile->pending_len > 0 ) {
|
||||
chunks_to_write = to_write / DEFAULT_CHUNK_SIZE;
|
||||
bytes_left = to_write % DEFAULT_CHUNK_SIZE;
|
||||
|
||||
data_partial_len = DEFAULT_CHUNK_SIZE - gfile->pending_len;
|
||||
buffer = ( char * )bson_malloc( DEFAULT_CHUNK_SIZE );
|
||||
memcpy( buffer, gfile->pending_data, gfile->pending_len );
|
||||
memcpy( buffer + gfile->pending_len, data, data_partial_len );
|
||||
|
||||
oChunk = chunk_new( gfile->id, gfile->chunk_num, buffer, DEFAULT_CHUNK_SIZE );
|
||||
mongo_insert( gfile->gfs->client, gfile->gfs->chunks_ns, oChunk );
|
||||
chunk_free( oChunk );
|
||||
gfile->chunk_num++;
|
||||
gfile->length += DEFAULT_CHUNK_SIZE;
|
||||
data += data_partial_len;
|
||||
|
||||
chunks_to_write--;
|
||||
|
||||
bson_free( buffer );
|
||||
}
|
||||
|
||||
while( chunks_to_write > 0 ) {
|
||||
oChunk = chunk_new( gfile->id, gfile->chunk_num, data, DEFAULT_CHUNK_SIZE );
|
||||
mongo_insert( gfile->gfs->client, gfile->gfs->chunks_ns, oChunk );
|
||||
chunk_free( oChunk );
|
||||
gfile->chunk_num++;
|
||||
chunks_to_write--;
|
||||
gfile->length += DEFAULT_CHUNK_SIZE;
|
||||
data += DEFAULT_CHUNK_SIZE;
|
||||
}
|
||||
|
||||
bson_free( gfile->pending_data );
|
||||
|
||||
/* If there are any leftover bytes, store them as pending data. */
|
||||
if( bytes_left == 0 )
|
||||
gfile->pending_data = NULL;
|
||||
else {
|
||||
gfile->pending_data = ( char * )bson_malloc( bytes_left );
|
||||
memcpy( gfile->pending_data, data, bytes_left );
|
||||
}
|
||||
|
||||
gfile->pending_len = bytes_left;
|
||||
}
|
||||
}
|
||||
|
||||
int gridfile_writer_done( gridfile *gfile ) {
|
||||
|
||||
/* write any remaining pending chunk data.
|
||||
* pending data will always take up less than one chunk */
|
||||
bson *oChunk;
|
||||
int response;
|
||||
if( gfile->pending_data ) {
|
||||
oChunk = chunk_new( gfile->id, gfile->chunk_num, gfile->pending_data, gfile->pending_len );
|
||||
mongo_insert( gfile->gfs->client, gfile->gfs->chunks_ns, oChunk );
|
||||
chunk_free( oChunk );
|
||||
bson_free( gfile->pending_data );
|
||||
gfile->length += gfile->pending_len;
|
||||
}
|
||||
|
||||
/* insert into files collection */
|
||||
response = gridfs_insert_file( gfile->gfs, gfile->remote_name, gfile->id,
|
||||
gfile->length, gfile->content_type );
|
||||
|
||||
bson_free( gfile->remote_name );
|
||||
bson_free( gfile->content_type );
|
||||
|
||||
return response;
|
||||
}
|
||||
|
||||
int gridfs_store_file( gridfs *gfs, const char *filename,
|
||||
const char *remotename, const char *contenttype ) {
|
||||
|
||||
char buffer[DEFAULT_CHUNK_SIZE];
|
||||
FILE *fd;
|
||||
bson_oid_t id;
|
||||
int chunkNumber = 0;
|
||||
gridfs_offset length = 0;
|
||||
gridfs_offset chunkLen = 0;
|
||||
bson *oChunk;
|
||||
|
||||
/* Open the file and the correct stream */
|
||||
if ( strcmp( filename, "-" ) == 0 ) fd = stdin;
|
||||
else fd = fopen( filename, "rb" );
|
||||
assert( fd != NULL ); /* No such file */
|
||||
|
||||
/* Generate and append an oid*/
|
||||
bson_oid_gen( &id );
|
||||
|
||||
/* Insert the file chunk by chunk */
|
||||
chunkLen = fread( buffer, 1, DEFAULT_CHUNK_SIZE, fd );
|
||||
do {
|
||||
oChunk = chunk_new( id, chunkNumber, buffer, chunkLen );
|
||||
mongo_insert( gfs->client, gfs->chunks_ns, oChunk );
|
||||
chunk_free( oChunk );
|
||||
length += chunkLen;
|
||||
chunkNumber++;
|
||||
chunkLen = fread( buffer, 1, DEFAULT_CHUNK_SIZE, fd );
|
||||
} while ( chunkLen != 0 );
|
||||
|
||||
/* Close the file stream */
|
||||
if ( fd != stdin ) fclose( fd );
|
||||
|
||||
/* Large files Assertion */
|
||||
/* assert(length <= 0xffffffff); */
|
||||
|
||||
/* Optional Remote Name */
|
||||
if ( remotename == NULL || *remotename == '\0' ) {
|
||||
remotename = filename;
|
||||
}
|
||||
|
||||
/* Inserts file's metadata */
|
||||
return gridfs_insert_file( gfs, remotename, id, length, contenttype );
|
||||
}
|
||||
|
||||
void gridfs_remove_filename( gridfs *gfs, const char *filename ) {
|
||||
bson query;
|
||||
mongo_cursor *files;
|
||||
bson file;
|
||||
bson_iterator it;
|
||||
bson_oid_t id;
|
||||
bson b;
|
||||
|
||||
bson_init( &query );
|
||||
bson_append_string( &query, "filename", filename );
|
||||
bson_finish( &query );
|
||||
files = mongo_find( gfs->client, gfs->files_ns, &query, NULL, 0, 0, 0 );
|
||||
bson_destroy( &query );
|
||||
|
||||
/* Remove each file and it's chunks from files named filename */
|
||||
while ( mongo_cursor_next( files ) == MONGO_OK ) {
|
||||
file = files->current;
|
||||
bson_find( &it, &file, "_id" );
|
||||
id = *bson_iterator_oid( &it );
|
||||
|
||||
/* Remove the file with the specified id */
|
||||
bson_init( &b );
|
||||
bson_append_oid( &b, "_id", &id );
|
||||
bson_finish( &b );
|
||||
mongo_remove( gfs->client, gfs->files_ns, &b );
|
||||
bson_destroy( &b );
|
||||
|
||||
/* Remove all chunks from the file with the specified id */
|
||||
bson_init( &b );
|
||||
bson_append_oid( &b, "files_id", &id );
|
||||
bson_finish( &b );
|
||||
mongo_remove( gfs->client, gfs->chunks_ns, &b );
|
||||
bson_destroy( &b );
|
||||
}
|
||||
|
||||
mongo_cursor_destroy( files );
|
||||
}
|
||||
|
||||
int gridfs_find_query( gridfs *gfs, bson *query,
|
||||
gridfile *gfile ) {
|
||||
|
||||
bson uploadDate;
|
||||
bson finalQuery;
|
||||
bson out;
|
||||
int i;
|
||||
|
||||
bson_init( &uploadDate );
|
||||
bson_append_int( &uploadDate, "uploadDate", -1 );
|
||||
bson_finish( &uploadDate );
|
||||
|
||||
bson_init( &finalQuery );
|
||||
bson_append_bson( &finalQuery, "query", query );
|
||||
bson_append_bson( &finalQuery, "orderby", &uploadDate );
|
||||
bson_finish( &finalQuery );
|
||||
|
||||
i = ( mongo_find_one( gfs->client, gfs->files_ns,
|
||||
&finalQuery, NULL, &out ) == MONGO_OK );
|
||||
bson_destroy( &uploadDate );
|
||||
bson_destroy( &finalQuery );
|
||||
if ( !i )
|
||||
return MONGO_ERROR;
|
||||
else {
|
||||
gridfile_init( gfs, &out, gfile );
|
||||
bson_destroy( &out );
|
||||
return MONGO_OK;
|
||||
}
|
||||
}
|
||||
|
||||
int gridfs_find_filename( gridfs *gfs, const char *filename,
|
||||
gridfile *gfile )
|
||||
|
||||
{
|
||||
bson query;
|
||||
int i;
|
||||
|
||||
bson_init( &query );
|
||||
bson_append_string( &query, "filename", filename );
|
||||
bson_finish( &query );
|
||||
i = gridfs_find_query( gfs, &query, gfile );
|
||||
bson_destroy( &query );
|
||||
return i;
|
||||
}
|
||||
|
||||
int gridfile_init( gridfs *gfs, bson *meta, gridfile *gfile )
|
||||
|
||||
{
|
||||
gfile->gfs = gfs;
|
||||
gfile->pos = 0;
|
||||
gfile->meta = ( bson * )bson_malloc( sizeof( bson ) );
|
||||
if ( gfile->meta == NULL ) return MONGO_ERROR;
|
||||
bson_copy( gfile->meta, meta );
|
||||
return MONGO_OK;
|
||||
}
|
||||
|
||||
void gridfile_destroy( gridfile *gfile )
|
||||
|
||||
{
|
||||
bson_destroy( gfile->meta );
|
||||
bson_free( gfile->meta );
|
||||
}
|
||||
|
||||
bson_bool_t gridfile_exists( gridfile *gfile ) {
|
||||
return ( bson_bool_t )( gfile != NULL || gfile->meta == NULL );
|
||||
}
|
||||
|
||||
const char *gridfile_get_filename( gridfile *gfile ) {
|
||||
bson_iterator it;
|
||||
|
||||
bson_find( &it, gfile->meta, "filename" );
|
||||
return bson_iterator_string( &it );
|
||||
}
|
||||
|
||||
int gridfile_get_chunksize( gridfile *gfile ) {
|
||||
bson_iterator it;
|
||||
|
||||
bson_find( &it, gfile->meta, "chunkSize" );
|
||||
return bson_iterator_int( &it );
|
||||
}
|
||||
|
||||
gridfs_offset gridfile_get_contentlength( gridfile *gfile ) {
|
||||
bson_iterator it;
|
||||
|
||||
bson_find( &it, gfile->meta, "length" );
|
||||
|
||||
if( bson_iterator_type( &it ) == BSON_INT )
|
||||
return ( gridfs_offset )bson_iterator_int( &it );
|
||||
else
|
||||
return ( gridfs_offset )bson_iterator_long( &it );
|
||||
}
|
||||
|
||||
const char *gridfile_get_contenttype( gridfile *gfile ) {
|
||||
bson_iterator it;
|
||||
|
||||
if ( bson_find( &it, gfile->meta, "contentType" ) )
|
||||
return bson_iterator_string( &it );
|
||||
else return NULL;
|
||||
}
|
||||
|
||||
bson_date_t gridfile_get_uploaddate( gridfile *gfile ) {
|
||||
bson_iterator it;
|
||||
|
||||
bson_find( &it, gfile->meta, "uploadDate" );
|
||||
return bson_iterator_date( &it );
|
||||
}
|
||||
|
||||
const char *gridfile_get_md5( gridfile *gfile ) {
|
||||
bson_iterator it;
|
||||
|
||||
bson_find( &it, gfile->meta, "md5" );
|
||||
return bson_iterator_string( &it );
|
||||
}
|
||||
|
||||
const char *gridfile_get_field( gridfile *gfile, const char *name ) {
|
||||
bson_iterator it;
|
||||
|
||||
bson_find( &it, gfile->meta, name );
|
||||
return bson_iterator_value( &it );
|
||||
}
|
||||
|
||||
bson_bool_t gridfile_get_boolean( gridfile *gfile, const char *name ) {
|
||||
bson_iterator it;
|
||||
|
||||
bson_find( &it, gfile->meta, name );
|
||||
return bson_iterator_bool( &it );
|
||||
}
|
||||
|
||||
bson gridfile_get_metadata( gridfile *gfile ) {
|
||||
bson sub;
|
||||
bson_iterator it;
|
||||
|
||||
if ( bson_find( &it, gfile->meta, "metadata" ) ) {
|
||||
bson_iterator_subobject( &it, &sub );
|
||||
return sub;
|
||||
} else {
|
||||
bson_empty( &sub );
|
||||
return sub;
|
||||
}
|
||||
}
|
||||
|
||||
int gridfile_get_numchunks( gridfile *gfile ) {
|
||||
bson_iterator it;
|
||||
gridfs_offset length;
|
||||
gridfs_offset chunkSize;
|
||||
double numchunks;
|
||||
|
||||
bson_find( &it, gfile->meta, "length" );
|
||||
|
||||
if( bson_iterator_type( &it ) == BSON_INT )
|
||||
length = ( gridfs_offset )bson_iterator_int( &it );
|
||||
else
|
||||
length = ( gridfs_offset )bson_iterator_long( &it );
|
||||
|
||||
bson_find( &it, gfile->meta, "chunkSize" );
|
||||
chunkSize = bson_iterator_int( &it );
|
||||
numchunks = ( ( double )length/( double )chunkSize );
|
||||
return ( numchunks - ( int )numchunks > 0 )
|
||||
? ( int )( numchunks+1 )
|
||||
: ( int )( numchunks );
|
||||
}
|
||||
|
||||
bson gridfile_get_chunk( gridfile *gfile, int n ) {
|
||||
bson query;
|
||||
bson out;
|
||||
bson_iterator it;
|
||||
bson_oid_t id;
|
||||
|
||||
bson_init( &query );
|
||||
bson_find( &it, gfile->meta, "_id" );
|
||||
id = *bson_iterator_oid( &it );
|
||||
bson_append_oid( &query, "files_id", &id );
|
||||
bson_append_int( &query, "n", n );
|
||||
bson_finish( &query );
|
||||
|
||||
assert( mongo_find_one( gfile->gfs->client,
|
||||
gfile->gfs->chunks_ns,
|
||||
&query, NULL, &out ) == MONGO_OK );
|
||||
|
||||
bson_destroy( &query );
|
||||
return out;
|
||||
}
|
||||
|
||||
mongo_cursor *gridfile_get_chunks( gridfile *gfile, int start, int size ) {
|
||||
bson_iterator it;
|
||||
bson_oid_t id;
|
||||
bson gte;
|
||||
bson query;
|
||||
bson orderby;
|
||||
bson command;
|
||||
mongo_cursor *cursor;
|
||||
|
||||
bson_find( &it, gfile->meta, "_id" );
|
||||
id = *bson_iterator_oid( &it );
|
||||
|
||||
bson_init( &query );
|
||||
bson_append_oid( &query, "files_id", &id );
|
||||
if ( size == 1 ) {
|
||||
bson_append_int( &query, "n", start );
|
||||
} else {
|
||||
bson_init( >e );
|
||||
bson_append_int( >e, "$gte", start );
|
||||
bson_finish( >e );
|
||||
bson_append_bson( &query, "n", >e );
|
||||
bson_destroy( >e );
|
||||
}
|
||||
bson_finish( &query );
|
||||
|
||||
bson_init( &orderby );
|
||||
bson_append_int( &orderby, "n", 1 );
|
||||
bson_finish( &orderby );
|
||||
|
||||
bson_init( &command );
|
||||
bson_append_bson( &command, "query", &query );
|
||||
bson_append_bson( &command, "orderby", &orderby );
|
||||
bson_finish( &command );
|
||||
|
||||
cursor = mongo_find( gfile->gfs->client, gfile->gfs->chunks_ns,
|
||||
&command, NULL, size, 0, 0 );
|
||||
|
||||
bson_destroy( &command );
|
||||
bson_destroy( &query );
|
||||
bson_destroy( &orderby );
|
||||
|
||||
return cursor;
|
||||
}
|
||||
|
||||
gridfs_offset gridfile_write_file( gridfile *gfile, FILE *stream ) {
|
||||
int i;
|
||||
size_t len;
|
||||
bson chunk;
|
||||
bson_iterator it;
|
||||
const char *data;
|
||||
const int num = gridfile_get_numchunks( gfile );
|
||||
|
||||
for ( i=0; i<num; i++ ) {
|
||||
chunk = gridfile_get_chunk( gfile, i );
|
||||
bson_find( &it, &chunk, "data" );
|
||||
len = bson_iterator_bin_len( &it );
|
||||
data = bson_iterator_bin_data( &it );
|
||||
fwrite( data , sizeof( char ), len, stream );
|
||||
bson_destroy( &chunk );
|
||||
}
|
||||
|
||||
return gridfile_get_contentlength( gfile );
|
||||
}
|
||||
|
||||
gridfs_offset gridfile_read( gridfile *gfile, gridfs_offset size, char *buf ) {
|
||||
mongo_cursor *chunks;
|
||||
bson chunk;
|
||||
|
||||
int first_chunk;
|
||||
int last_chunk;
|
||||
int total_chunks;
|
||||
gridfs_offset chunksize;
|
||||
gridfs_offset contentlength;
|
||||
gridfs_offset bytes_left;
|
||||
int i;
|
||||
bson_iterator it;
|
||||
gridfs_offset chunk_len;
|
||||
const char *chunk_data;
|
||||
|
||||
contentlength = gridfile_get_contentlength( gfile );
|
||||
chunksize = gridfile_get_chunksize( gfile );
|
||||
size = ( contentlength - gfile->pos < size )
|
||||
? contentlength - gfile->pos
|
||||
: size;
|
||||
bytes_left = size;
|
||||
|
||||
first_chunk = ( gfile->pos )/chunksize;
|
||||
last_chunk = ( gfile->pos+size-1 )/chunksize;
|
||||
total_chunks = last_chunk - first_chunk + 1;
|
||||
chunks = gridfile_get_chunks( gfile, first_chunk, total_chunks );
|
||||
|
||||
for ( i = 0; i < total_chunks; i++ ) {
|
||||
mongo_cursor_next( chunks );
|
||||
chunk = chunks->current;
|
||||
bson_find( &it, &chunk, "data" );
|
||||
chunk_len = bson_iterator_bin_len( &it );
|
||||
chunk_data = bson_iterator_bin_data( &it );
|
||||
if ( i == 0 ) {
|
||||
chunk_data += ( gfile->pos )%chunksize;
|
||||
chunk_len -= ( gfile->pos )%chunksize;
|
||||
}
|
||||
if ( bytes_left > chunk_len ) {
|
||||
memcpy( buf, chunk_data, chunk_len );
|
||||
bytes_left -= chunk_len;
|
||||
buf += chunk_len;
|
||||
} else {
|
||||
memcpy( buf, chunk_data, bytes_left );
|
||||
}
|
||||
}
|
||||
|
||||
mongo_cursor_destroy( chunks );
|
||||
gfile->pos = gfile->pos + size;
|
||||
|
||||
return size;
|
||||
}
|
||||
|
||||
gridfs_offset gridfile_seek( gridfile *gfile, gridfs_offset offset ) {
|
||||
gridfs_offset length;
|
||||
|
||||
length = gridfile_get_contentlength( gfile );
|
||||
gfile->pos = length < offset ? length : offset;
|
||||
return gfile->pos;
|
||||
}
|
326
src/mod/event_handlers/mod_cdr_mongodb/driver/src/gridfs.h
Normal file
326
src/mod/event_handlers/mod_cdr_mongodb/driver/src/gridfs.h
Normal file
@ -0,0 +1,326 @@
|
||||
/** @file gridfs.h
|
||||
*
|
||||
* @brief GridFS declarations
|
||||
*
|
||||
* */
|
||||
|
||||
/* Copyright 2009-2011 10gen Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include "mongo.h"
|
||||
|
||||
#ifndef GRIDFS_INCLUDED
|
||||
#define GRIDFS_INCLUDED
|
||||
|
||||
enum {DEFAULT_CHUNK_SIZE = 256 * 1024};
|
||||
|
||||
typedef uint64_t gridfs_offset;
|
||||
|
||||
/* A GridFS represents a single collection of GridFS files in the database. */
|
||||
typedef struct {
|
||||
mongo *client; /**> The client to db-connection. */
|
||||
const char *dbname; /**> The root database name */
|
||||
const char *prefix; /**> The prefix of the GridFS's collections, default is NULL */
|
||||
const char *files_ns; /**> The namespace where the file's metadata is stored */
|
||||
const char *chunks_ns; /**. The namespace where the files's data is stored in chunks */
|
||||
} gridfs;
|
||||
|
||||
/* A GridFile is a single GridFS file. */
|
||||
typedef struct {
|
||||
gridfs *gfs; /**> The GridFS where the GridFile is located */
|
||||
bson *meta; /**> The GridFile's bson object where all its metadata is located */
|
||||
gridfs_offset pos; /**> The position is the offset in the file */
|
||||
bson_oid_t id; /**> The files_id of the gridfile */
|
||||
char *remote_name; /**> The name of the gridfile as a string */
|
||||
char *content_type; /**> The gridfile's content type */
|
||||
gridfs_offset length; /**> The length of this gridfile */
|
||||
int chunk_num; /**> The number of the current chunk being written to */
|
||||
char *pending_data; /**> A buffer storing data still to be written to chunks */
|
||||
int pending_len; /**> Length of pending_data buffer */
|
||||
} gridfile;
|
||||
|
||||
/**
|
||||
* Initializes a GridFS object
|
||||
* @param client - db connection
|
||||
* @param dbname - database name
|
||||
* @param prefix - collection prefix, default is fs if NULL or empty
|
||||
* @param gfs - the GridFS object to initialize
|
||||
*
|
||||
* @return - MONGO_OK or MONGO_ERROR.
|
||||
*/
|
||||
int gridfs_init( mongo *client, const char *dbname,
|
||||
const char *prefix, gridfs *gfs );
|
||||
|
||||
/**
|
||||
* Destroys a GridFS object. Call this when finished with
|
||||
* the object..
|
||||
*
|
||||
* @param gfs a grid
|
||||
*/
|
||||
void gridfs_destroy( gridfs *gfs );
|
||||
|
||||
/**
|
||||
* Initializes a gridfile for writing incrementally with gridfs_write_buffer.
|
||||
* Once initialized, you can write any number of buffers with gridfs_write_buffer.
|
||||
* When done, you must call gridfs_writer_done to save the file metadata.
|
||||
*
|
||||
*/
|
||||
void gridfile_writer_init( gridfile *gfile, gridfs *gfs, const char *remote_name,
|
||||
const char *content_type );
|
||||
|
||||
/**
|
||||
* Write to a GridFS file incrementally. You can call this function any number
|
||||
* of times with a new buffer each time. This allows you to effectively
|
||||
* stream to a GridFS file. When finished, be sure to call gridfs_writer_done.
|
||||
*
|
||||
*/
|
||||
void gridfile_write_buffer( gridfile *gfile, const char *data,
|
||||
gridfs_offset length );
|
||||
|
||||
/**
|
||||
* Signal that writing of this gridfile is complete by
|
||||
* writing any buffered chunks along with the entry in the
|
||||
* files collection.
|
||||
*
|
||||
* @return - MONGO_OK or MONGO_ERROR.
|
||||
*/
|
||||
int gridfile_writer_done( gridfile *gfile );
|
||||
|
||||
/**
|
||||
* Store a buffer as a GridFS file.
|
||||
* @param gfs - the working GridFS
|
||||
* @param data - pointer to buffer to store in GridFS
|
||||
* @param length - length of the buffer
|
||||
* @param remotename - filename for use in the database
|
||||
* @param contenttype - optional MIME type for this object
|
||||
*
|
||||
* @return - MONGO_OK or MONGO_ERROR.
|
||||
*/
|
||||
int gridfs_store_buffer( gridfs *gfs, const char *data, gridfs_offset length,
|
||||
const char *remotename,
|
||||
const char *contenttype );
|
||||
|
||||
/**
|
||||
* Open the file referenced by filename and store it as a GridFS file.
|
||||
* @param gfs - the working GridFS
|
||||
* @param filename - local filename relative to the process
|
||||
* @param remotename - optional filename for use in the database
|
||||
* @param contenttype - optional MIME type for this object
|
||||
*
|
||||
* @return - MONGO_OK or MONGO_ERROR.
|
||||
*/
|
||||
int gridfs_store_file( gridfs *gfs, const char *filename,
|
||||
const char *remotename, const char *contenttype );
|
||||
|
||||
/**
|
||||
* Removes the files referenced by filename from the db
|
||||
* @param gfs - the working GridFS
|
||||
* @param filename - the filename of the file/s to be removed
|
||||
*/
|
||||
void gridfs_remove_filename( gridfs *gfs, const char *filename );
|
||||
|
||||
/**
|
||||
* Find the first file matching the provided query within the
|
||||
* GridFS files collection, and return the file as a GridFile.
|
||||
*
|
||||
* @param gfs - the working GridFS
|
||||
* @param query - a pointer to the bson with the query data
|
||||
* @param gfile - the output GridFile to be initialized
|
||||
*
|
||||
* @return MONGO_OK if successful, MONGO_ERROR otherwise
|
||||
*/
|
||||
int gridfs_find_query( gridfs *gfs, bson *query, gridfile *gfile );
|
||||
|
||||
/**
|
||||
* Find the first file referenced by filename within the GridFS
|
||||
* and return it as a GridFile
|
||||
* @param gfs - the working GridFS
|
||||
* @param filename - filename of the file to find
|
||||
* @param gfile - the output GridFile to be intialized
|
||||
*
|
||||
* @return MONGO_OK or MONGO_ERROR.
|
||||
*/
|
||||
int gridfs_find_filename( gridfs *gfs, const char *filename, gridfile *gfile );
|
||||
|
||||
/**
|
||||
* Initializes a GridFile containing the GridFS and file bson
|
||||
* @param gfs - the GridFS where the GridFile is located
|
||||
* @param meta - the file object
|
||||
* @param gfile - the output GridFile that is being initialized
|
||||
*
|
||||
* @return - MONGO_OK or MONGO_ERROR.
|
||||
*/
|
||||
int gridfile_init( gridfs *gfs, bson *meta, gridfile *gfile );
|
||||
|
||||
/**
|
||||
* Destroys the GridFile
|
||||
*
|
||||
* @param oGridFIle - the GridFile being destroyed
|
||||
*/
|
||||
void gridfile_destroy( gridfile *gfile );
|
||||
|
||||
/**
|
||||
* Returns whether or not the GridFile exists
|
||||
* @param gfile - the GridFile being examined
|
||||
*/
|
||||
bson_bool_t gridfile_exists( gridfile *gfile );
|
||||
|
||||
/**
|
||||
* Returns the filename of GridFile
|
||||
* @param gfile - the working GridFile
|
||||
*
|
||||
* @return - the filename of the Gridfile
|
||||
*/
|
||||
const char *gridfile_get_filename( gridfile *gfile );
|
||||
|
||||
/**
|
||||
* Returns the size of the chunks of the GridFile
|
||||
* @param gfile - the working GridFile
|
||||
*
|
||||
* @return - the size of the chunks of the Gridfile
|
||||
*/
|
||||
int gridfile_get_chunksize( gridfile *gfile );
|
||||
|
||||
/**
|
||||
* Returns the length of GridFile's data
|
||||
*
|
||||
* @param gfile - the working GridFile
|
||||
*
|
||||
* @return - the length of the Gridfile's data
|
||||
*/
|
||||
gridfs_offset gridfile_get_contentlength( gridfile *gfile );
|
||||
|
||||
/**
|
||||
* Returns the MIME type of the GridFile
|
||||
*
|
||||
* @param gfile - the working GridFile
|
||||
*
|
||||
* @return - the MIME type of the Gridfile
|
||||
* (NULL if no type specified)
|
||||
*/
|
||||
const char *gridfile_get_contenttype( gridfile *gfile );
|
||||
|
||||
/**
|
||||
* Returns the upload date of GridFile
|
||||
*
|
||||
* @param gfile - the working GridFile
|
||||
*
|
||||
* @return - the upload date of the Gridfile
|
||||
*/
|
||||
bson_date_t gridfile_get_uploaddate( gridfile *gfile );
|
||||
|
||||
/**
|
||||
* Returns the MD5 of GridFile
|
||||
*
|
||||
* @param gfile - the working GridFile
|
||||
*
|
||||
* @return - the MD5 of the Gridfile
|
||||
*/
|
||||
const char *gridfile_get_md5( gridfile *gfile );
|
||||
|
||||
/**
|
||||
* Returns the field in GridFile specified by name
|
||||
*
|
||||
* @param gfile - the working GridFile
|
||||
* @param name - the name of the field to be returned
|
||||
*
|
||||
* @return - the data of the field specified
|
||||
* (NULL if none exists)
|
||||
*/
|
||||
const char *gridfile_get_field( gridfile *gfile,
|
||||
const char *name );
|
||||
|
||||
/**
|
||||
* Returns a boolean field in GridFile specified by name
|
||||
* @param gfile - the working GridFile
|
||||
* @param name - the name of the field to be returned
|
||||
*
|
||||
* @return - the boolean of the field specified
|
||||
* (NULL if none exists)
|
||||
*/
|
||||
bson_bool_t gridfile_get_boolean( gridfile *gfile,
|
||||
const char *name );
|
||||
|
||||
/**
|
||||
* Returns the metadata of GridFile
|
||||
* @param gfile - the working GridFile
|
||||
*
|
||||
* @return - the metadata of the Gridfile in a bson object
|
||||
* (an empty bson is returned if none exists)
|
||||
*/
|
||||
bson gridfile_get_metadata( gridfile *gfile );
|
||||
|
||||
/**
|
||||
* Returns the number of chunks in the GridFile
|
||||
* @param gfile - the working GridFile
|
||||
*
|
||||
* @return - the number of chunks in the Gridfile
|
||||
*/
|
||||
int gridfile_get_numchunks( gridfile *gfile );
|
||||
|
||||
/**
|
||||
* Returns chunk n of GridFile
|
||||
* @param gfile - the working GridFile
|
||||
*
|
||||
* @return - the nth chunk of the Gridfile
|
||||
*/
|
||||
bson gridfile_get_chunk( gridfile *gfile, int n );
|
||||
|
||||
/**
|
||||
* Returns a mongo_cursor of *size* chunks starting with chunk *start*
|
||||
*
|
||||
* @param gfile - the working GridFile
|
||||
* @param start - the first chunk in the cursor
|
||||
* @param size - the number of chunks to be returned
|
||||
*
|
||||
* @return - mongo_cursor of the chunks (must be destroyed after use)
|
||||
*/
|
||||
mongo_cursor *gridfile_get_chunks( gridfile *gfile, int start, int size );
|
||||
|
||||
/**
|
||||
* Writes the GridFile to a stream
|
||||
*
|
||||
* @param gfile - the working GridFile
|
||||
* @param stream - the file stream to write to
|
||||
*/
|
||||
gridfs_offset gridfile_write_file( gridfile *gfile, FILE *stream );
|
||||
|
||||
/**
|
||||
* Reads length bytes from the GridFile to a buffer
|
||||
* and updates the position in the file.
|
||||
* (assumes the buffer is large enough)
|
||||
* (if size is greater than EOF gridfile_read reads until EOF)
|
||||
*
|
||||
* @param gfile - the working GridFile
|
||||
* @param size - the amount of bytes to be read
|
||||
* @param buf - the buffer to read to
|
||||
*
|
||||
* @return - the number of bytes read
|
||||
*/
|
||||
gridfs_offset gridfile_read( gridfile *gfile, gridfs_offset size, char *buf );
|
||||
|
||||
/**
|
||||
* Updates the position in the file
|
||||
* (If the offset goes beyond the contentlength,
|
||||
* the position is updated to the end of the file.)
|
||||
*
|
||||
* @param gfile - the working GridFile
|
||||
* @param offset - the position to update to
|
||||
*
|
||||
* @return - resulting offset location
|
||||
*/
|
||||
gridfs_offset gridfile_seek( gridfile *gfile, gridfs_offset offset );
|
||||
|
||||
#endif
|
381
src/mod/event_handlers/mod_cdr_mongodb/driver/src/md5.c
Normal file
381
src/mod/event_handlers/mod_cdr_mongodb/driver/src/md5.c
Normal file
@ -0,0 +1,381 @@
|
||||
/*
|
||||
Copyright (C) 1999, 2000, 2002 Aladdin Enterprises. All rights reserved.
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
|
||||
L. Peter Deutsch
|
||||
ghost@aladdin.com
|
||||
|
||||
*/
|
||||
/* $Id: md5.c,v 1.6 2002/04/13 19:20:28 lpd Exp $ */
|
||||
/*
|
||||
Independent implementation of MD5 (RFC 1321).
|
||||
|
||||
This code implements the MD5 Algorithm defined in RFC 1321, whose
|
||||
text is available at
|
||||
http://www.ietf.org/rfc/rfc1321.txt
|
||||
The code is derived from the text of the RFC, including the test suite
|
||||
(section A.5) but excluding the rest of Appendix A. It does not include
|
||||
any code or documentation that is identified in the RFC as being
|
||||
copyrighted.
|
||||
|
||||
The original and principal author of md5.c is L. Peter Deutsch
|
||||
<ghost@aladdin.com>. Other authors are noted in the change history
|
||||
that follows (in reverse chronological order):
|
||||
|
||||
2002-04-13 lpd Clarified derivation from RFC 1321; now handles byte order
|
||||
either statically or dynamically; added missing #include <string.h>
|
||||
in library.
|
||||
2002-03-11 lpd Corrected argument list for main(), and added int return
|
||||
type, in test program and T value program.
|
||||
2002-02-21 lpd Added missing #include <stdio.h> in test program.
|
||||
2000-07-03 lpd Patched to eliminate warnings about "constant is
|
||||
unsigned in ANSI C, signed in traditional"; made test program
|
||||
self-checking.
|
||||
1999-11-04 lpd Edited comments slightly for automatic TOC extraction.
|
||||
1999-10-18 lpd Fixed typo in header comment (ansi2knr rather than md5).
|
||||
1999-05-03 lpd Original version.
|
||||
*/
|
||||
|
||||
#include "md5.h"
|
||||
#include <string.h>
|
||||
|
||||
#undef BYTE_ORDER /* 1 = big-endian, -1 = little-endian, 0 = unknown */
|
||||
#ifdef MONGO_BIG_ENDIAN
|
||||
# define BYTE_ORDER 1
|
||||
#else
|
||||
# define BYTE_ORDER -1
|
||||
#endif
|
||||
|
||||
#define T_MASK ((mongo_md5_word_t)~0)
|
||||
#define T1 /* 0xd76aa478 */ (T_MASK ^ 0x28955b87)
|
||||
#define T2 /* 0xe8c7b756 */ (T_MASK ^ 0x173848a9)
|
||||
#define T3 0x242070db
|
||||
#define T4 /* 0xc1bdceee */ (T_MASK ^ 0x3e423111)
|
||||
#define T5 /* 0xf57c0faf */ (T_MASK ^ 0x0a83f050)
|
||||
#define T6 0x4787c62a
|
||||
#define T7 /* 0xa8304613 */ (T_MASK ^ 0x57cfb9ec)
|
||||
#define T8 /* 0xfd469501 */ (T_MASK ^ 0x02b96afe)
|
||||
#define T9 0x698098d8
|
||||
#define T10 /* 0x8b44f7af */ (T_MASK ^ 0x74bb0850)
|
||||
#define T11 /* 0xffff5bb1 */ (T_MASK ^ 0x0000a44e)
|
||||
#define T12 /* 0x895cd7be */ (T_MASK ^ 0x76a32841)
|
||||
#define T13 0x6b901122
|
||||
#define T14 /* 0xfd987193 */ (T_MASK ^ 0x02678e6c)
|
||||
#define T15 /* 0xa679438e */ (T_MASK ^ 0x5986bc71)
|
||||
#define T16 0x49b40821
|
||||
#define T17 /* 0xf61e2562 */ (T_MASK ^ 0x09e1da9d)
|
||||
#define T18 /* 0xc040b340 */ (T_MASK ^ 0x3fbf4cbf)
|
||||
#define T19 0x265e5a51
|
||||
#define T20 /* 0xe9b6c7aa */ (T_MASK ^ 0x16493855)
|
||||
#define T21 /* 0xd62f105d */ (T_MASK ^ 0x29d0efa2)
|
||||
#define T22 0x02441453
|
||||
#define T23 /* 0xd8a1e681 */ (T_MASK ^ 0x275e197e)
|
||||
#define T24 /* 0xe7d3fbc8 */ (T_MASK ^ 0x182c0437)
|
||||
#define T25 0x21e1cde6
|
||||
#define T26 /* 0xc33707d6 */ (T_MASK ^ 0x3cc8f829)
|
||||
#define T27 /* 0xf4d50d87 */ (T_MASK ^ 0x0b2af278)
|
||||
#define T28 0x455a14ed
|
||||
#define T29 /* 0xa9e3e905 */ (T_MASK ^ 0x561c16fa)
|
||||
#define T30 /* 0xfcefa3f8 */ (T_MASK ^ 0x03105c07)
|
||||
#define T31 0x676f02d9
|
||||
#define T32 /* 0x8d2a4c8a */ (T_MASK ^ 0x72d5b375)
|
||||
#define T33 /* 0xfffa3942 */ (T_MASK ^ 0x0005c6bd)
|
||||
#define T34 /* 0x8771f681 */ (T_MASK ^ 0x788e097e)
|
||||
#define T35 0x6d9d6122
|
||||
#define T36 /* 0xfde5380c */ (T_MASK ^ 0x021ac7f3)
|
||||
#define T37 /* 0xa4beea44 */ (T_MASK ^ 0x5b4115bb)
|
||||
#define T38 0x4bdecfa9
|
||||
#define T39 /* 0xf6bb4b60 */ (T_MASK ^ 0x0944b49f)
|
||||
#define T40 /* 0xbebfbc70 */ (T_MASK ^ 0x4140438f)
|
||||
#define T41 0x289b7ec6
|
||||
#define T42 /* 0xeaa127fa */ (T_MASK ^ 0x155ed805)
|
||||
#define T43 /* 0xd4ef3085 */ (T_MASK ^ 0x2b10cf7a)
|
||||
#define T44 0x04881d05
|
||||
#define T45 /* 0xd9d4d039 */ (T_MASK ^ 0x262b2fc6)
|
||||
#define T46 /* 0xe6db99e5 */ (T_MASK ^ 0x1924661a)
|
||||
#define T47 0x1fa27cf8
|
||||
#define T48 /* 0xc4ac5665 */ (T_MASK ^ 0x3b53a99a)
|
||||
#define T49 /* 0xf4292244 */ (T_MASK ^ 0x0bd6ddbb)
|
||||
#define T50 0x432aff97
|
||||
#define T51 /* 0xab9423a7 */ (T_MASK ^ 0x546bdc58)
|
||||
#define T52 /* 0xfc93a039 */ (T_MASK ^ 0x036c5fc6)
|
||||
#define T53 0x655b59c3
|
||||
#define T54 /* 0x8f0ccc92 */ (T_MASK ^ 0x70f3336d)
|
||||
#define T55 /* 0xffeff47d */ (T_MASK ^ 0x00100b82)
|
||||
#define T56 /* 0x85845dd1 */ (T_MASK ^ 0x7a7ba22e)
|
||||
#define T57 0x6fa87e4f
|
||||
#define T58 /* 0xfe2ce6e0 */ (T_MASK ^ 0x01d3191f)
|
||||
#define T59 /* 0xa3014314 */ (T_MASK ^ 0x5cfebceb)
|
||||
#define T60 0x4e0811a1
|
||||
#define T61 /* 0xf7537e82 */ (T_MASK ^ 0x08ac817d)
|
||||
#define T62 /* 0xbd3af235 */ (T_MASK ^ 0x42c50dca)
|
||||
#define T63 0x2ad7d2bb
|
||||
#define T64 /* 0xeb86d391 */ (T_MASK ^ 0x14792c6e)
|
||||
|
||||
|
||||
static void
|
||||
mongo_md5_process(mongo_md5_state_t *pms, const mongo_md5_byte_t *data /*[64]*/)
|
||||
{
|
||||
mongo_md5_word_t
|
||||
a = pms->abcd[0], b = pms->abcd[1],
|
||||
c = pms->abcd[2], d = pms->abcd[3];
|
||||
mongo_md5_word_t t;
|
||||
#if BYTE_ORDER > 0
|
||||
/* Define storage only for big-endian CPUs. */
|
||||
mongo_md5_word_t X[16];
|
||||
#else
|
||||
/* Define storage for little-endian or both types of CPUs. */
|
||||
mongo_md5_word_t xbuf[16];
|
||||
const mongo_md5_word_t *X;
|
||||
#endif
|
||||
|
||||
{
|
||||
#if BYTE_ORDER == 0
|
||||
/*
|
||||
* Determine dynamically whether this is a big-endian or
|
||||
* little-endian machine, since we can use a more efficient
|
||||
* algorithm on the latter.
|
||||
*/
|
||||
static const int w = 1;
|
||||
|
||||
if (*((const mongo_md5_byte_t *)&w)) /* dynamic little-endian */
|
||||
#endif
|
||||
#if BYTE_ORDER <= 0 /* little-endian */
|
||||
{
|
||||
/*
|
||||
* On little-endian machines, we can process properly aligned
|
||||
* data without copying it.
|
||||
*/
|
||||
if (!((data - (const mongo_md5_byte_t *)0) & 3)) {
|
||||
/* data are properly aligned */
|
||||
X = (const mongo_md5_word_t *)data;
|
||||
} else {
|
||||
/* not aligned */
|
||||
memcpy(xbuf, data, 64);
|
||||
X = xbuf;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
#if BYTE_ORDER == 0
|
||||
else /* dynamic big-endian */
|
||||
#endif
|
||||
#if BYTE_ORDER >= 0 /* big-endian */
|
||||
{
|
||||
/*
|
||||
* On big-endian machines, we must arrange the bytes in the
|
||||
* right order.
|
||||
*/
|
||||
const mongo_md5_byte_t *xp = data;
|
||||
int i;
|
||||
|
||||
# if BYTE_ORDER == 0
|
||||
X = xbuf; /* (dynamic only) */
|
||||
# else
|
||||
# define xbuf X /* (static only) */
|
||||
# endif
|
||||
for (i = 0; i < 16; ++i, xp += 4)
|
||||
xbuf[i] = xp[0] + (xp[1] << 8) + (xp[2] << 16) + (xp[3] << 24);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
#define ROTATE_LEFT(x, n) (((x) << (n)) | ((x) >> (32 - (n))))
|
||||
|
||||
/* Round 1. */
|
||||
/* Let [abcd k s i] denote the operation
|
||||
a = b + ((a + F(b,c,d) + X[k] + T[i]) <<< s). */
|
||||
#define F(x, y, z) (((x) & (y)) | (~(x) & (z)))
|
||||
#define SET(a, b, c, d, k, s, Ti)\
|
||||
t = a + F(b,c,d) + X[k] + Ti;\
|
||||
a = ROTATE_LEFT(t, s) + b
|
||||
/* Do the following 16 operations. */
|
||||
SET(a, b, c, d, 0, 7, T1);
|
||||
SET(d, a, b, c, 1, 12, T2);
|
||||
SET(c, d, a, b, 2, 17, T3);
|
||||
SET(b, c, d, a, 3, 22, T4);
|
||||
SET(a, b, c, d, 4, 7, T5);
|
||||
SET(d, a, b, c, 5, 12, T6);
|
||||
SET(c, d, a, b, 6, 17, T7);
|
||||
SET(b, c, d, a, 7, 22, T8);
|
||||
SET(a, b, c, d, 8, 7, T9);
|
||||
SET(d, a, b, c, 9, 12, T10);
|
||||
SET(c, d, a, b, 10, 17, T11);
|
||||
SET(b, c, d, a, 11, 22, T12);
|
||||
SET(a, b, c, d, 12, 7, T13);
|
||||
SET(d, a, b, c, 13, 12, T14);
|
||||
SET(c, d, a, b, 14, 17, T15);
|
||||
SET(b, c, d, a, 15, 22, T16);
|
||||
#undef SET
|
||||
|
||||
/* Round 2. */
|
||||
/* Let [abcd k s i] denote the operation
|
||||
a = b + ((a + G(b,c,d) + X[k] + T[i]) <<< s). */
|
||||
#define G(x, y, z) (((x) & (z)) | ((y) & ~(z)))
|
||||
#define SET(a, b, c, d, k, s, Ti)\
|
||||
t = a + G(b,c,d) + X[k] + Ti;\
|
||||
a = ROTATE_LEFT(t, s) + b
|
||||
/* Do the following 16 operations. */
|
||||
SET(a, b, c, d, 1, 5, T17);
|
||||
SET(d, a, b, c, 6, 9, T18);
|
||||
SET(c, d, a, b, 11, 14, T19);
|
||||
SET(b, c, d, a, 0, 20, T20);
|
||||
SET(a, b, c, d, 5, 5, T21);
|
||||
SET(d, a, b, c, 10, 9, T22);
|
||||
SET(c, d, a, b, 15, 14, T23);
|
||||
SET(b, c, d, a, 4, 20, T24);
|
||||
SET(a, b, c, d, 9, 5, T25);
|
||||
SET(d, a, b, c, 14, 9, T26);
|
||||
SET(c, d, a, b, 3, 14, T27);
|
||||
SET(b, c, d, a, 8, 20, T28);
|
||||
SET(a, b, c, d, 13, 5, T29);
|
||||
SET(d, a, b, c, 2, 9, T30);
|
||||
SET(c, d, a, b, 7, 14, T31);
|
||||
SET(b, c, d, a, 12, 20, T32);
|
||||
#undef SET
|
||||
|
||||
/* Round 3. */
|
||||
/* Let [abcd k s t] denote the operation
|
||||
a = b + ((a + H(b,c,d) + X[k] + T[i]) <<< s). */
|
||||
#define H(x, y, z) ((x) ^ (y) ^ (z))
|
||||
#define SET(a, b, c, d, k, s, Ti)\
|
||||
t = a + H(b,c,d) + X[k] + Ti;\
|
||||
a = ROTATE_LEFT(t, s) + b
|
||||
/* Do the following 16 operations. */
|
||||
SET(a, b, c, d, 5, 4, T33);
|
||||
SET(d, a, b, c, 8, 11, T34);
|
||||
SET(c, d, a, b, 11, 16, T35);
|
||||
SET(b, c, d, a, 14, 23, T36);
|
||||
SET(a, b, c, d, 1, 4, T37);
|
||||
SET(d, a, b, c, 4, 11, T38);
|
||||
SET(c, d, a, b, 7, 16, T39);
|
||||
SET(b, c, d, a, 10, 23, T40);
|
||||
SET(a, b, c, d, 13, 4, T41);
|
||||
SET(d, a, b, c, 0, 11, T42);
|
||||
SET(c, d, a, b, 3, 16, T43);
|
||||
SET(b, c, d, a, 6, 23, T44);
|
||||
SET(a, b, c, d, 9, 4, T45);
|
||||
SET(d, a, b, c, 12, 11, T46);
|
||||
SET(c, d, a, b, 15, 16, T47);
|
||||
SET(b, c, d, a, 2, 23, T48);
|
||||
#undef SET
|
||||
|
||||
/* Round 4. */
|
||||
/* Let [abcd k s t] denote the operation
|
||||
a = b + ((a + I(b,c,d) + X[k] + T[i]) <<< s). */
|
||||
#define I(x, y, z) ((y) ^ ((x) | ~(z)))
|
||||
#define SET(a, b, c, d, k, s, Ti)\
|
||||
t = a + I(b,c,d) + X[k] + Ti;\
|
||||
a = ROTATE_LEFT(t, s) + b
|
||||
/* Do the following 16 operations. */
|
||||
SET(a, b, c, d, 0, 6, T49);
|
||||
SET(d, a, b, c, 7, 10, T50);
|
||||
SET(c, d, a, b, 14, 15, T51);
|
||||
SET(b, c, d, a, 5, 21, T52);
|
||||
SET(a, b, c, d, 12, 6, T53);
|
||||
SET(d, a, b, c, 3, 10, T54);
|
||||
SET(c, d, a, b, 10, 15, T55);
|
||||
SET(b, c, d, a, 1, 21, T56);
|
||||
SET(a, b, c, d, 8, 6, T57);
|
||||
SET(d, a, b, c, 15, 10, T58);
|
||||
SET(c, d, a, b, 6, 15, T59);
|
||||
SET(b, c, d, a, 13, 21, T60);
|
||||
SET(a, b, c, d, 4, 6, T61);
|
||||
SET(d, a, b, c, 11, 10, T62);
|
||||
SET(c, d, a, b, 2, 15, T63);
|
||||
SET(b, c, d, a, 9, 21, T64);
|
||||
#undef SET
|
||||
|
||||
/* Then perform the following additions. (That is increment each
|
||||
of the four registers by the value it had before this block
|
||||
was started.) */
|
||||
pms->abcd[0] += a;
|
||||
pms->abcd[1] += b;
|
||||
pms->abcd[2] += c;
|
||||
pms->abcd[3] += d;
|
||||
}
|
||||
|
||||
void
|
||||
mongo_md5_init(mongo_md5_state_t *pms)
|
||||
{
|
||||
pms->count[0] = pms->count[1] = 0;
|
||||
pms->abcd[0] = 0x67452301;
|
||||
pms->abcd[1] = /*0xefcdab89*/ T_MASK ^ 0x10325476;
|
||||
pms->abcd[2] = /*0x98badcfe*/ T_MASK ^ 0x67452301;
|
||||
pms->abcd[3] = 0x10325476;
|
||||
}
|
||||
|
||||
void
|
||||
mongo_md5_append(mongo_md5_state_t *pms, const mongo_md5_byte_t *data, int nbytes)
|
||||
{
|
||||
const mongo_md5_byte_t *p = data;
|
||||
int left = nbytes;
|
||||
int offset = (pms->count[0] >> 3) & 63;
|
||||
mongo_md5_word_t nbits = (mongo_md5_word_t)(nbytes << 3);
|
||||
|
||||
if (nbytes <= 0)
|
||||
return;
|
||||
|
||||
/* Update the message length. */
|
||||
pms->count[1] += nbytes >> 29;
|
||||
pms->count[0] += nbits;
|
||||
if (pms->count[0] < nbits)
|
||||
pms->count[1]++;
|
||||
|
||||
/* Process an initial partial block. */
|
||||
if (offset) {
|
||||
int copy = (offset + nbytes > 64 ? 64 - offset : nbytes);
|
||||
|
||||
memcpy(pms->buf + offset, p, copy);
|
||||
if (offset + copy < 64)
|
||||
return;
|
||||
p += copy;
|
||||
left -= copy;
|
||||
mongo_md5_process(pms, pms->buf);
|
||||
}
|
||||
|
||||
/* Process full blocks. */
|
||||
for (; left >= 64; p += 64, left -= 64)
|
||||
mongo_md5_process(pms, p);
|
||||
|
||||
/* Process a final partial block. */
|
||||
if (left)
|
||||
memcpy(pms->buf, p, left);
|
||||
}
|
||||
|
||||
void
|
||||
mongo_md5_finish(mongo_md5_state_t *pms, mongo_md5_byte_t digest[16])
|
||||
{
|
||||
static const mongo_md5_byte_t pad[64] = {
|
||||
0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
|
||||
};
|
||||
mongo_md5_byte_t data[8];
|
||||
int i;
|
||||
|
||||
/* Save the length before padding. */
|
||||
for (i = 0; i < 8; ++i)
|
||||
data[i] = (mongo_md5_byte_t)(pms->count[i >> 2] >> ((i & 3) << 3));
|
||||
/* Pad to 56 bytes mod 64. */
|
||||
mongo_md5_append(pms, pad, ((55 - (pms->count[0] >> 3)) & 63) + 1);
|
||||
/* Append the length. */
|
||||
mongo_md5_append(pms, data, 8);
|
||||
for (i = 0; i < 16; ++i)
|
||||
digest[i] = (mongo_md5_byte_t)(pms->abcd[i >> 2] >> ((i & 3) << 3));
|
||||
}
|
91
src/mod/event_handlers/mod_cdr_mongodb/driver/src/md5.h
Normal file
91
src/mod/event_handlers/mod_cdr_mongodb/driver/src/md5.h
Normal file
@ -0,0 +1,91 @@
|
||||
/*
|
||||
Copyright (C) 1999, 2002 Aladdin Enterprises. All rights reserved.
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
|
||||
L. Peter Deutsch
|
||||
ghost@aladdin.com
|
||||
|
||||
*/
|
||||
/* $Id: md5.h,v 1.4 2002/04/13 19:20:28 lpd Exp $ */
|
||||
/*
|
||||
Independent implementation of MD5 (RFC 1321).
|
||||
|
||||
This code implements the MD5 Algorithm defined in RFC 1321, whose
|
||||
text is available at
|
||||
http://www.ietf.org/rfc/rfc1321.txt
|
||||
The code is derived from the text of the RFC, including the test suite
|
||||
(section A.5) but excluding the rest of Appendix A. It does not include
|
||||
any code or documentation that is identified in the RFC as being
|
||||
copyrighted.
|
||||
|
||||
The original and principal author of md5.h is L. Peter Deutsch
|
||||
<ghost@aladdin.com>. Other authors are noted in the change history
|
||||
that follows (in reverse chronological order):
|
||||
|
||||
2002-04-13 lpd Removed support for non-ANSI compilers; removed
|
||||
references to Ghostscript; clarified derivation from RFC 1321;
|
||||
now handles byte order either statically or dynamically.
|
||||
1999-11-04 lpd Edited comments slightly for automatic TOC extraction.
|
||||
1999-10-18 lpd Fixed typo in header comment (ansi2knr rather than md5);
|
||||
added conditionalization for C++ compilation from Martin
|
||||
Purschke <purschke@bnl.gov>.
|
||||
1999-05-03 lpd Original version.
|
||||
*/
|
||||
|
||||
#ifndef md5_INCLUDED
|
||||
# define md5_INCLUDED
|
||||
|
||||
/*
|
||||
* This package supports both compile-time and run-time determination of CPU
|
||||
* byte order. If ARCH_IS_BIG_ENDIAN is defined as 0, the code will be
|
||||
* compiled to run only on little-endian CPUs; if ARCH_IS_BIG_ENDIAN is
|
||||
* defined as non-zero, the code will be compiled to run only on big-endian
|
||||
* CPUs; if ARCH_IS_BIG_ENDIAN is not defined, the code will be compiled to
|
||||
* run on either big- or little-endian CPUs, but will run slightly less
|
||||
* efficiently on either one than if ARCH_IS_BIG_ENDIAN is defined.
|
||||
*/
|
||||
|
||||
typedef unsigned char mongo_md5_byte_t; /* 8-bit byte */
|
||||
typedef unsigned int mongo_md5_word_t; /* 32-bit word */
|
||||
|
||||
/* Define the state of the MD5 Algorithm. */
|
||||
typedef struct mongo_md5_state_s {
|
||||
mongo_md5_word_t count[2]; /* message length in bits, lsw first */
|
||||
mongo_md5_word_t abcd[4]; /* digest buffer */
|
||||
mongo_md5_byte_t buf[64]; /* accumulate block */
|
||||
} mongo_md5_state_t;
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
{
|
||||
#endif
|
||||
|
||||
/* Initialize the algorithm. */
|
||||
void mongo_md5_init(mongo_md5_state_t *pms);
|
||||
|
||||
/* Append a string to the message. */
|
||||
void mongo_md5_append(mongo_md5_state_t *pms, const mongo_md5_byte_t *data, int nbytes);
|
||||
|
||||
/* Finish the message and return the digest. */
|
||||
void mongo_md5_finish(mongo_md5_state_t *pms, mongo_md5_byte_t digest[16]);
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* end extern "C" */
|
||||
#endif
|
||||
|
||||
#endif /* md5_INCLUDED */
|
1217
src/mod/event_handlers/mod_cdr_mongodb/driver/src/mongo.c
Normal file
1217
src/mod/event_handlers/mod_cdr_mongodb/driver/src/mongo.c
Normal file
File diff suppressed because it is too large
Load Diff
648
src/mod/event_handlers/mod_cdr_mongodb/driver/src/mongo.h
Normal file
648
src/mod/event_handlers/mod_cdr_mongodb/driver/src/mongo.h
Normal file
@ -0,0 +1,648 @@
|
||||
/**
|
||||
* @file mongo.h
|
||||
* @brief Main MongoDB Declarations
|
||||
*/
|
||||
|
||||
/* Copyright 2009-2011 10gen Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef _MONGO_H_
|
||||
#define _MONGO_H_
|
||||
|
||||
#include "bson.h"
|
||||
|
||||
MONGO_EXTERN_C_START
|
||||
|
||||
#define MONGO_MAJOR 0
|
||||
#define MONGO_MINOR 4
|
||||
#define MONGO_PATCH 0
|
||||
|
||||
#define MONGO_OK 0
|
||||
#define MONGO_ERROR -1
|
||||
|
||||
#define MONGO_DEFAULT_PORT 27017
|
||||
|
||||
typedef enum mongo_error_t {
|
||||
MONGO_CONN_SUCCESS = 0, /**< Connection success! */
|
||||
MONGO_CONN_NO_SOCKET, /**< Could not create a socket. */
|
||||
MONGO_CONN_FAIL, /**< An error occured while calling connect(). */
|
||||
MONGO_CONN_ADDR_FAIL, /**< An error occured while calling getaddrinfo(). */
|
||||
MONGO_CONN_NOT_MASTER, /**< Warning: connected to a non-master node (read-only). */
|
||||
MONGO_CONN_BAD_SET_NAME, /**< Given rs name doesn't match this replica set. */
|
||||
MONGO_CONN_NO_PRIMARY, /**< Can't find primary in replica set. Connection closed. */
|
||||
|
||||
MONGO_IO_ERROR, /**< An error occurred while reading or writing on socket. */
|
||||
MONGO_READ_SIZE_ERROR, /**< The response is not the expected length. */
|
||||
MONGO_COMMAND_FAILED, /**< The command returned with 'ok' value of 0. */
|
||||
MONGO_CURSOR_EXHAUSTED, /**< The cursor has no more results. */
|
||||
MONGO_CURSOR_INVALID, /**< The cursor has timed out or is not recognized. */
|
||||
MONGO_CURSOR_PENDING, /**< Tailable cursor still alive but no data. */
|
||||
MONGO_BSON_INVALID, /**< BSON not valid for the specified op. */
|
||||
MONGO_BSON_NOT_FINISHED /**< BSON object has not been finished. */
|
||||
} mongo_error_t;
|
||||
|
||||
enum mongo_cursor_flags {
|
||||
MONGO_CURSOR_MUST_FREE = 1, /**< mongo_cursor_destroy should free cursor. */
|
||||
MONGO_CURSOR_QUERY_SENT = ( 1<<1 ) /**< Initial query has been sent. */
|
||||
};
|
||||
|
||||
enum mongo_index_opts {
|
||||
MONGO_INDEX_UNIQUE = ( 1<<0 ),
|
||||
MONGO_INDEX_DROP_DUPS = ( 1<<2 ),
|
||||
MONGO_INDEX_BACKGROUND = ( 1<<3 ),
|
||||
MONGO_INDEX_SPARSE = ( 1<<4 )
|
||||
};
|
||||
|
||||
enum mongo_update_opts {
|
||||
MONGO_UPDATE_UPSERT = 0x1,
|
||||
MONGO_UPDATE_MULTI = 0x2,
|
||||
MONGO_UPDATE_BASIC = 0x4
|
||||
};
|
||||
|
||||
enum mongo_cursor_opts {
|
||||
MONGO_TAILABLE = ( 1<<1 ), /**< Create a tailable cursor. */
|
||||
MONGO_SLAVE_OK = ( 1<<2 ), /**< Allow queries on a non-primary node. */
|
||||
MONGO_NO_CURSOR_TIMEOUT = ( 1<<4 ), /**< Disable cursor timeouts. */
|
||||
MONGO_AWAIT_DATA = ( 1<<5 ), /**< Momentarily block for more data. */
|
||||
MONGO_EXHAUST = ( 1<<6 ), /**< Stream in multiple 'more' packages. */
|
||||
MONGO_PARTIAL = ( 1<<7 ) /**< Allow reads even if a shard is down. */
|
||||
};
|
||||
|
||||
enum mongo_operations {
|
||||
MONGO_OP_MSG = 1000,
|
||||
MONGO_OP_UPDATE = 2001,
|
||||
MONGO_OP_INSERT = 2002,
|
||||
MONGO_OP_QUERY = 2004,
|
||||
MONGO_OP_GET_MORE = 2005,
|
||||
MONGO_OP_DELETE = 2006,
|
||||
MONGO_OP_KILL_CURSORS = 2007
|
||||
};
|
||||
|
||||
#pragma pack(1)
|
||||
typedef struct {
|
||||
int len;
|
||||
int id;
|
||||
int responseTo;
|
||||
int op;
|
||||
} mongo_header;
|
||||
|
||||
typedef struct {
|
||||
mongo_header head;
|
||||
char data;
|
||||
} mongo_message;
|
||||
|
||||
typedef struct {
|
||||
int flag; /* FIX THIS COMMENT non-zero on failure */
|
||||
int64_t cursorID;
|
||||
int start;
|
||||
int num;
|
||||
} mongo_reply_fields;
|
||||
|
||||
typedef struct {
|
||||
mongo_header head;
|
||||
mongo_reply_fields fields;
|
||||
char objs;
|
||||
} mongo_reply;
|
||||
#pragma pack()
|
||||
|
||||
typedef struct mongo_host_port {
|
||||
char host[255];
|
||||
int port;
|
||||
struct mongo_host_port *next;
|
||||
} mongo_host_port;
|
||||
|
||||
typedef struct {
|
||||
mongo_host_port *seeds; /**< List of seeds provided by the user. */
|
||||
mongo_host_port *hosts; /**< List of host/ports given by the replica set */
|
||||
char *name; /**< Name of the replica set. */
|
||||
bson_bool_t primary_connected; /**< Primary node connection status. */
|
||||
} mongo_replset;
|
||||
|
||||
typedef struct mongo {
|
||||
mongo_host_port *primary; /**< Primary connection info. */
|
||||
mongo_replset *replset; /**< replset object if connected to a replica set. */
|
||||
int sock; /**< Socket file descriptor. */
|
||||
int flags; /**< Flags on this connection object. */
|
||||
int conn_timeout_ms; /**< Connection timeout in milliseconds. */
|
||||
int op_timeout_ms; /**< Read and write timeout in milliseconds. */
|
||||
bson_bool_t connected; /**< Connection status. */
|
||||
|
||||
mongo_error_t err; /**< Most recent driver error code. */
|
||||
char *errstr; /**< String version of most recent driver error code. */
|
||||
int lasterrcode; /**< getlasterror given by the server on calls. */
|
||||
char *lasterrstr; /**< getlasterror string generated by server. */
|
||||
} mongo;
|
||||
|
||||
typedef struct {
|
||||
mongo_reply *reply; /**< reply is owned by cursor */
|
||||
mongo *conn; /**< connection is *not* owned by cursor */
|
||||
const char *ns; /**< owned by cursor */
|
||||
int flags; /**< Flags used internally by this drivers. */
|
||||
int seen; /**< Number returned so far. */
|
||||
bson current; /**< This cursor's current bson object. */
|
||||
mongo_error_t err; /**< Errors on this cursor. */
|
||||
bson *query; /**< Bitfield containing cursor options. */
|
||||
bson *fields; /**< Bitfield containing cursor options. */
|
||||
int options; /**< Bitfield containing cursor options. */
|
||||
int limit; /**< Bitfield containing cursor options. */
|
||||
int skip; /**< Bitfield containing cursor options. */
|
||||
} mongo_cursor;
|
||||
|
||||
/* Connection API */
|
||||
|
||||
/** Initialize a new mongo connection object. If not created
|
||||
* with mongo_new, you must initialize each mongo
|
||||
* object using this function.
|
||||
*
|
||||
* @note When finished, you must pass this object to
|
||||
* mongo_destroy( ).
|
||||
*
|
||||
* @param conn a mongo connection object allocated on the stack
|
||||
* or heap.
|
||||
*/
|
||||
void mongo_init( mongo *conn );
|
||||
|
||||
/**
|
||||
* Connect to a single MongoDB server.
|
||||
*
|
||||
* @param conn a mongo object.
|
||||
* @param host a numerical network address or a network hostname.
|
||||
* @param port the port to connect to.
|
||||
*
|
||||
* @return MONGO_OK or MONGO_ERROR on failure. On failure, a constant of type
|
||||
* mongo_conn_return_t will be set on the conn->err field.
|
||||
*/
|
||||
int mongo_connect( mongo *conn , const char *host, int port );
|
||||
|
||||
/**
|
||||
* Set up this connection object for connecting to a replica set.
|
||||
* To connect, pass the object to mongo_replset_connect().
|
||||
*
|
||||
* @param conn a mongo object.
|
||||
* @param name the name of the replica set to connect to.
|
||||
* */
|
||||
void mongo_replset_init( mongo *conn, const char *name );
|
||||
|
||||
/**
|
||||
* Add a seed node to the replica set connection object.
|
||||
*
|
||||
* You must specify at least one seed node before connecting to a replica set.
|
||||
*
|
||||
* @param conn a mongo object.
|
||||
* @param host a numerical network address or a network hostname.
|
||||
* @param port the port to connect to.
|
||||
*/
|
||||
void mongo_replset_add_seed( mongo *conn, const char *host, int port );
|
||||
|
||||
/**
|
||||
* Utility function for converting a host-port string to a mongo_host_port.
|
||||
*
|
||||
* @param host_string a string containing either a host or a host and port separated
|
||||
* by a colon.
|
||||
* @param host_port the mongo_host_port object to write the result to.
|
||||
*/
|
||||
void mongo_parse_host( const char *host_string, mongo_host_port *host_port );
|
||||
|
||||
/**
|
||||
* Connect to a replica set.
|
||||
*
|
||||
* Before passing a connection object to this function, you must already have called
|
||||
* mongo_set_replset and mongo_replset_add_seed.
|
||||
*
|
||||
* @param conn a mongo object.
|
||||
*
|
||||
* @return MONGO_OK or MONGO_ERROR on failure. On failure, a constant of type
|
||||
* mongo_conn_return_t will be set on the conn->err field.
|
||||
*/
|
||||
int mongo_replset_connect( mongo *conn );
|
||||
|
||||
/** Set a timeout for operations on this connection. This
|
||||
* is a platform-specific feature, and only work on *nix
|
||||
* system. You must also compile for linux to support this.
|
||||
*
|
||||
* @param conn a mongo object.
|
||||
* @param millis timeout time in milliseconds.
|
||||
*
|
||||
* @return MONGO_OK. On error, return MONGO_ERROR and
|
||||
* set the conn->err field.
|
||||
*/
|
||||
int mongo_set_op_timeout( mongo *conn, int millis );
|
||||
|
||||
/**
|
||||
* Ensure that this connection is healthy by performing
|
||||
* a round-trip to the server.
|
||||
*
|
||||
* @param conn a mongo connection
|
||||
*
|
||||
* @return MONGO_OK if connected; otherwise, MONGO_ERROR.
|
||||
*/
|
||||
int mongo_check_connection( mongo *conn );
|
||||
|
||||
/**
|
||||
* Try reconnecting to the server using the existing connection settings.
|
||||
*
|
||||
* This function will disconnect the current socket. If you've authenticated,
|
||||
* you'll need to re-authenticate after calling this function.
|
||||
*
|
||||
* @param conn a mongo object.
|
||||
*
|
||||
* @return MONGO_OK or MONGO_ERROR and
|
||||
* set the conn->err field.
|
||||
*/
|
||||
int mongo_reconnect( mongo *conn );
|
||||
|
||||
/**
|
||||
* Close the current connection to the server. After calling
|
||||
* this function, you may call mongo_reconnect with the same
|
||||
* connection object.
|
||||
*
|
||||
* @param conn a mongo object.
|
||||
*/
|
||||
void mongo_disconnect( mongo *conn );
|
||||
|
||||
/**
|
||||
* Close any existing connection to the server and free all allocated
|
||||
* memory associated with the conn object.
|
||||
*
|
||||
* You must always call this function when finished with the connection object.
|
||||
*
|
||||
* @param conn a mongo object.
|
||||
*/
|
||||
void mongo_destroy( mongo *conn );
|
||||
|
||||
/**
|
||||
* Insert a BSON document into a MongoDB server. This function
|
||||
* will fail if the supplied BSON struct is not UTF-8 or if
|
||||
* the keys are invalid for insert (contain '.' or start with '$').
|
||||
*
|
||||
* @param conn a mongo object.
|
||||
* @param ns the namespace.
|
||||
* @param data the bson data.
|
||||
*
|
||||
* @return MONGO_OK or MONGO_ERROR. If the conn->err
|
||||
* field is MONGO_BSON_INVALID, check the err field
|
||||
* on the bson struct for the reason.
|
||||
*/
|
||||
int mongo_insert( mongo *conn, const char *ns, bson *data );
|
||||
|
||||
/**
|
||||
* Insert a batch of BSON documents into a MongoDB server. This function
|
||||
* will fail if any of the documents to be inserted is invalid.
|
||||
*
|
||||
* @param conn a mongo object.
|
||||
* @param ns the namespace.
|
||||
* @param data the bson data.
|
||||
* @param num the number of documents in data.
|
||||
*
|
||||
* @return MONGO_OK or MONGO_ERROR.
|
||||
*
|
||||
*/
|
||||
int mongo_insert_batch( mongo *conn , const char *ns ,
|
||||
bson **data , int num );
|
||||
|
||||
/**
|
||||
* Update a document in a MongoDB server.
|
||||
*
|
||||
* @param conn a mongo object.
|
||||
* @param ns the namespace.
|
||||
* @param cond the bson update query.
|
||||
* @param op the bson update data.
|
||||
* @param flags flags for the update.
|
||||
*
|
||||
* @return MONGO_OK or MONGO_ERROR with error stored in conn object.
|
||||
*
|
||||
*/
|
||||
int mongo_update( mongo *conn, const char *ns, const bson *cond,
|
||||
const bson *op, int flags );
|
||||
|
||||
/**
|
||||
* Remove a document from a MongoDB server.
|
||||
*
|
||||
* @param conn a mongo object.
|
||||
* @param ns the namespace.
|
||||
* @param cond the bson query.
|
||||
*
|
||||
* @return MONGO_OK or MONGO_ERROR with error stored in conn object.
|
||||
*/
|
||||
int mongo_remove( mongo *conn, const char *ns, const bson *cond );
|
||||
|
||||
/**
|
||||
* Find documents in a MongoDB server.
|
||||
*
|
||||
* @param conn a mongo object.
|
||||
* @param ns the namespace.
|
||||
* @param query the bson query.
|
||||
* @param fields a bson document of fields to be returned.
|
||||
* @param limit the maximum number of documents to retrun.
|
||||
* @param skip the number of documents to skip.
|
||||
* @param options A bitfield containing cursor options.
|
||||
*
|
||||
* @return A cursor object allocated on the heap or NULL if
|
||||
* an error has occurred. For finer-grained error checking,
|
||||
* use the cursor builder API instead.
|
||||
*/
|
||||
mongo_cursor *mongo_find( mongo *conn, const char *ns, bson *query,
|
||||
bson *fields, int limit, int skip, int options );
|
||||
|
||||
/**
|
||||
* Initalize a new cursor object.
|
||||
*
|
||||
* @param cursor
|
||||
* @param ns the namespace, represented as the the database
|
||||
* name and collection name separated by a dot. e.g., "test.users"
|
||||
*/
|
||||
void mongo_cursor_init( mongo_cursor *cursor, mongo *conn, const char *ns );
|
||||
|
||||
/**
|
||||
* Set the bson object specifying this cursor's query spec. If
|
||||
* your query is the empty bson object "{}", then you need not
|
||||
* set this value.
|
||||
*
|
||||
* @param cursor
|
||||
* @param query a bson object representing the query spec. This may
|
||||
* be either a simple query spec or a complex spec storing values for
|
||||
* $query, $orderby, $hint, and/or $explain. See
|
||||
* http://www.mongodb.org/display/DOCS/Mongo+Wire+Protocol for details.
|
||||
*/
|
||||
void mongo_cursor_set_query( mongo_cursor *cursor, bson *query );
|
||||
|
||||
/**
|
||||
* Set the fields to return for this cursor. If you want to return
|
||||
* all fields, you need not set this value.
|
||||
*
|
||||
* @param cursor
|
||||
* @param fields a bson object representing the fields to return.
|
||||
* See http://www.mongodb.org/display/DOCS/Retrieving+a+Subset+of+Fields.
|
||||
*/
|
||||
void mongo_cursor_set_fields( mongo_cursor *cursor, bson *fields );
|
||||
|
||||
/**
|
||||
* Set the number of documents to skip.
|
||||
*
|
||||
* @param cursor
|
||||
* @param skip
|
||||
*/
|
||||
void mongo_cursor_set_skip( mongo_cursor *cursor, int skip );
|
||||
|
||||
/**
|
||||
* Set the number of documents to return.
|
||||
*
|
||||
* @param cursor
|
||||
* @param limit
|
||||
*/
|
||||
void mongo_cursor_set_limit( mongo_cursor *cursor, int limit );
|
||||
|
||||
/**
|
||||
* Set any of the available query options (e.g., MONGO_TAILABLE).
|
||||
*
|
||||
* @param cursor
|
||||
* @param options a bitfield storing query options. See
|
||||
* mongo_cursor_bitfield_t for available constants.
|
||||
*/
|
||||
void mongo_cursor_set_options( mongo_cursor *cursor, int options );
|
||||
|
||||
/**
|
||||
* Return the current BSON object data as a const char*. This is useful
|
||||
* for creating bson iterators with bson_iterator_init.
|
||||
*
|
||||
* @param cursor
|
||||
*/
|
||||
const char *mongo_cursor_data( mongo_cursor *cursor );
|
||||
|
||||
/**
|
||||
* Return the current BSON object data as a const char*. This is useful
|
||||
* for creating bson iterators with bson_iterator_init.
|
||||
*
|
||||
* @param cursor
|
||||
*/
|
||||
const bson *mongo_cursor_bson( mongo_cursor *cursor );
|
||||
|
||||
/**
|
||||
* Iterate the cursor, returning the next item. When successful,
|
||||
* the returned object will be stored in cursor->current;
|
||||
*
|
||||
* @param cursor
|
||||
*
|
||||
* @return MONGO_OK. On error, returns MONGO_ERROR and sets
|
||||
* cursor->err with a value of mongo_error_t.
|
||||
*/
|
||||
int mongo_cursor_next( mongo_cursor *cursor );
|
||||
|
||||
/**
|
||||
* Destroy a cursor object. When finished with a cursor, you
|
||||
* must pass it to this function.
|
||||
*
|
||||
* @param cursor the cursor to destroy.
|
||||
*
|
||||
* @return MONGO_OK or an error code. On error, check cursor->conn->err
|
||||
* for errors.
|
||||
*/
|
||||
int mongo_cursor_destroy( mongo_cursor *cursor );
|
||||
|
||||
/**
|
||||
* Find a single document in a MongoDB server.
|
||||
*
|
||||
* @param conn a mongo object.
|
||||
* @param ns the namespace.
|
||||
* @param query the bson query.
|
||||
* @param fields a bson document of the fields to be returned.
|
||||
* @param out a bson document in which to put the query result.
|
||||
*
|
||||
*/
|
||||
/* out can be NULL if you don't care about results. useful for commands */
|
||||
bson_bool_t mongo_find_one( mongo *conn, const char *ns, bson *query,
|
||||
bson *fields, bson *out );
|
||||
|
||||
/* MongoDB Helper Functions */
|
||||
|
||||
/**
|
||||
* Count the number of documents in a collection matching a query.
|
||||
*
|
||||
* @param conn a mongo object.
|
||||
* @param db the db name.
|
||||
* @param coll the collection name.
|
||||
* @param query the BSON query.
|
||||
*
|
||||
* @return the number of matching documents. If the command fails,
|
||||
* MONGO_ERROR is returned.
|
||||
*/
|
||||
int64_t mongo_count( mongo *conn, const char *db, const char *coll,
|
||||
bson *query );
|
||||
|
||||
/**
|
||||
* Create a compouned index.
|
||||
*
|
||||
* @param conn a mongo object.
|
||||
* @param ns the namespace.
|
||||
* @param data the bson index data.
|
||||
* @param options a bitfield for setting index options. Possibilities include
|
||||
* MONGO_INDEX_UNIQUE, MONGO_INDEX_DROP_DUPS, MONGO_INDEX_BACKGROUND,
|
||||
* and MONGO_INDEX_SPARSE.
|
||||
* @param out a bson document containing errors, if any.
|
||||
*
|
||||
* @return MONGO_OK if index is created successfully; otherwise, MONGO_ERROR.
|
||||
*/
|
||||
int mongo_create_index( mongo *conn, const char *ns, bson *key, int options, bson *out );
|
||||
|
||||
/**
|
||||
* Create an index with a single key.
|
||||
*
|
||||
* @param conn a mongo object.
|
||||
* @param ns the namespace.
|
||||
* @param field the index key.
|
||||
* @param options index options.
|
||||
* @param out a BSON document containing errors, if any.
|
||||
*
|
||||
* @return true if the index was created.
|
||||
*/
|
||||
bson_bool_t mongo_create_simple_index( mongo *conn, const char *ns, const char *field, int options, bson *out );
|
||||
|
||||
/* ----------------------------
|
||||
COMMANDS
|
||||
------------------------------ */
|
||||
|
||||
/**
|
||||
* Run a command on a MongoDB server.
|
||||
*
|
||||
* @param conn a mongo object.
|
||||
* @param db the name of the database.
|
||||
* @param command the BSON command to run.
|
||||
* @param out the BSON result of the command.
|
||||
*
|
||||
* @return true if the command ran without error.
|
||||
*/
|
||||
bson_bool_t mongo_run_command( mongo *conn, const char *db, bson *command, bson *out );
|
||||
|
||||
/**
|
||||
* Run a command that accepts a simple string key and integer value.
|
||||
*
|
||||
* @param conn a mongo object.
|
||||
* @param db the name of the database.
|
||||
* @param cmd the command to run.
|
||||
* @param arg the integer argument to the command.
|
||||
* @param out the BSON result of the command.
|
||||
*
|
||||
* @return MONGO_OK or an error code.
|
||||
*
|
||||
*/
|
||||
int mongo_simple_int_command( mongo *conn, const char *db,
|
||||
const char *cmd, int arg, bson *out );
|
||||
|
||||
/**
|
||||
* Run a command that accepts a simple string key and value.
|
||||
*
|
||||
* @param conn a mongo object.
|
||||
* @param db the name of the database.
|
||||
* @param cmd the command to run.
|
||||
* @param arg the string argument to the command.
|
||||
* @param out the BSON result of the command.
|
||||
*
|
||||
* @return true if the command ran without error.
|
||||
*
|
||||
*/
|
||||
bson_bool_t mongo_simple_str_command( mongo *conn, const char *db, const char *cmd, const char *arg, bson *out );
|
||||
|
||||
/**
|
||||
* Drop a database.
|
||||
*
|
||||
* @param conn a mongo object.
|
||||
* @param db the name of the database to drop.
|
||||
*
|
||||
* @return MONGO_OK or an error code.
|
||||
*/
|
||||
int mongo_cmd_drop_db( mongo *conn, const char *db );
|
||||
|
||||
/**
|
||||
* Drop a collection.
|
||||
*
|
||||
* @param conn a mongo object.
|
||||
* @param db the name of the database.
|
||||
* @param collection the name of the collection to drop.
|
||||
* @param out a BSON document containing the result of the command.
|
||||
*
|
||||
* @return true if the collection drop was successful.
|
||||
*/
|
||||
bson_bool_t mongo_cmd_drop_collection( mongo *conn, const char *db, const char *collection, bson *out );
|
||||
|
||||
/**
|
||||
* Add a database user.
|
||||
*
|
||||
* @param conn a mongo object.
|
||||
* @param db the database in which to add the user.
|
||||
* @param user the user name
|
||||
* @param pass the user password
|
||||
*
|
||||
* @return MONGO_OK or MONGO_ERROR.
|
||||
*/
|
||||
int mongo_cmd_add_user( mongo *conn, const char *db, const char *user, const char *pass );
|
||||
|
||||
/**
|
||||
* Authenticate a user.
|
||||
*
|
||||
* @param conn a mongo object.
|
||||
* @param db the database to authenticate against.
|
||||
* @param user the user name to authenticate.
|
||||
* @param pass the user's password.
|
||||
*
|
||||
* @return MONGO_OK on sucess and MONGO_ERROR on failure.
|
||||
*/
|
||||
int mongo_cmd_authenticate( mongo *conn, const char *db, const char *user, const char *pass );
|
||||
|
||||
/**
|
||||
* Check if the current server is a master.
|
||||
*
|
||||
* @param conn a mongo object.
|
||||
* @param out a BSON result of the command.
|
||||
*
|
||||
* @return true if the server is a master.
|
||||
*/
|
||||
/* return value is master status */
|
||||
bson_bool_t mongo_cmd_ismaster( mongo *conn, bson *out );
|
||||
|
||||
/**
|
||||
* Get the error for the last command with the current connection.
|
||||
*
|
||||
* @param conn a mongo object.
|
||||
* @param db the name of the database.
|
||||
* @param out a BSON object containing the error details.
|
||||
*
|
||||
* @return MONGO_OK if no error and MONGO_ERROR on error. On error, check the values
|
||||
* of conn->lasterrcode and conn->lasterrstr for the error status.
|
||||
*/
|
||||
int mongo_cmd_get_last_error( mongo *conn, const char *db, bson *out );
|
||||
|
||||
/**
|
||||
* Get the most recent error with the current connection.
|
||||
*
|
||||
* @param conn a mongo object.
|
||||
* @param db the name of the database.
|
||||
* @param out a BSON object containing the error details.
|
||||
*
|
||||
* @return MONGO_OK if no error and MONGO_ERROR on error. On error, check the values
|
||||
* of conn->lasterrcode and conn->lasterrstr for the error status.
|
||||
*/
|
||||
int mongo_cmd_get_prev_error( mongo *conn, const char *db, bson *out );
|
||||
|
||||
/**
|
||||
* Reset the error state for the connection.
|
||||
*
|
||||
* @param conn a mongo object.
|
||||
* @param db the name of the database.
|
||||
*/
|
||||
void mongo_cmd_reset_error( mongo *conn, const char *db );
|
||||
|
||||
MONGO_EXTERN_C_END
|
||||
|
||||
#endif
|
98
src/mod/event_handlers/mod_cdr_mongodb/driver/src/net.c
Normal file
98
src/mod/event_handlers/mod_cdr_mongodb/driver/src/net.c
Normal file
@ -0,0 +1,98 @@
|
||||
/* net.c */
|
||||
|
||||
/* Copyright 2009-2011 10gen Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
/* Implementation for generic version of net.h */
|
||||
#include "net.h"
|
||||
#include <string.h>
|
||||
|
||||
int mongo_write_socket( mongo *conn, const void *buf, int len ) {
|
||||
const char *cbuf = buf;
|
||||
while ( len ) {
|
||||
int sent = send( conn->sock, cbuf, len, 0 );
|
||||
if ( sent == -1 ) {
|
||||
conn->err = MONGO_IO_ERROR;
|
||||
return MONGO_ERROR;
|
||||
}
|
||||
cbuf += sent;
|
||||
len -= sent;
|
||||
}
|
||||
|
||||
return MONGO_OK;
|
||||
}
|
||||
|
||||
int mongo_read_socket( mongo *conn, void *buf, int len ) {
|
||||
char *cbuf = buf;
|
||||
while ( len ) {
|
||||
int sent = recv( conn->sock, cbuf, len, 0 );
|
||||
if ( sent == 0 || sent == -1 ) {
|
||||
conn->err = MONGO_IO_ERROR;
|
||||
return MONGO_ERROR;
|
||||
}
|
||||
cbuf += sent;
|
||||
len -= sent;
|
||||
}
|
||||
|
||||
return MONGO_OK;
|
||||
}
|
||||
|
||||
/* This is a no-op in the generic implementation. */
|
||||
int mongo_set_socket_op_timeout( mongo *conn, int millis ) {
|
||||
return MONGO_OK;
|
||||
}
|
||||
|
||||
static int mongo_create_socket( mongo *conn ) {
|
||||
int fd;
|
||||
|
||||
if( ( fd = socket( AF_INET, SOCK_STREAM, 0 ) ) == -1 ) {
|
||||
conn->err = MONGO_CONN_NO_SOCKET;
|
||||
return MONGO_ERROR;
|
||||
}
|
||||
conn->sock = fd;
|
||||
|
||||
return MONGO_OK;
|
||||
}
|
||||
|
||||
int mongo_socket_connect( mongo *conn, const char *host, int port ) {
|
||||
struct sockaddr_in sa;
|
||||
socklen_t addressSize;
|
||||
int flag = 1;
|
||||
|
||||
if( mongo_create_socket( conn ) != MONGO_OK )
|
||||
return MONGO_ERROR;
|
||||
|
||||
memset( sa.sin_zero , 0 , sizeof( sa.sin_zero ) );
|
||||
sa.sin_family = AF_INET;
|
||||
sa.sin_port = htons( port );
|
||||
sa.sin_addr.s_addr = inet_addr( host );
|
||||
addressSize = sizeof( sa );
|
||||
|
||||
if ( connect( conn->sock, ( struct sockaddr * )&sa, addressSize ) == -1 ) {
|
||||
mongo_close_socket( conn->sock );
|
||||
conn->connected = 0;
|
||||
conn->sock = 0;
|
||||
conn->err = MONGO_CONN_FAIL;
|
||||
return MONGO_ERROR;
|
||||
}
|
||||
|
||||
setsockopt( conn->sock, IPPROTO_TCP, TCP_NODELAY, ( char * ) &flag, sizeof( flag ) );
|
||||
if( conn->op_timeout_ms > 0 )
|
||||
mongo_set_socket_op_timeout( conn, conn->op_timeout_ms );
|
||||
|
||||
conn->connected = 1;
|
||||
|
||||
return MONGO_OK;
|
||||
}
|
57
src/mod/event_handlers/mod_cdr_mongodb/driver/src/net.h
Normal file
57
src/mod/event_handlers/mod_cdr_mongodb/driver/src/net.h
Normal file
@ -0,0 +1,57 @@
|
||||
/** @file net.h */
|
||||
|
||||
/* Copyright 2009-2011 10gen Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
/* Header for generic net.h */
|
||||
#ifndef _MONGO_NET_H_
|
||||
#define _MONGO_NET_H_
|
||||
|
||||
#include "mongo.h"
|
||||
|
||||
#ifdef _WIN32
|
||||
#include <windows.h>
|
||||
#include <winsock.h>
|
||||
#define mongo_close_socket(sock) ( closesocket(sock) )
|
||||
typedef int socklen_t;
|
||||
#else
|
||||
#include <arpa/inet.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
#include <netdb.h>
|
||||
#include <netinet/in.h>
|
||||
#include <netinet/tcp.h>
|
||||
#include <fcntl.h>
|
||||
#define mongo_close_socket(sock) ( close(sock) )
|
||||
#endif
|
||||
|
||||
#ifndef _WIN32
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
|
||||
#if defined(_XOPEN_SOURCE) || defined(_POSIX_SOURCE) || _POSIX_C_SOURCE >= 1
|
||||
#define _MONGO_USE_GETADDRINFO
|
||||
#endif
|
||||
|
||||
MONGO_EXTERN_C_START
|
||||
|
||||
/* This is a no-op in the generic implementation. */
|
||||
int mongo_set_socket_op_timeout( mongo *conn, int millis );
|
||||
int mongo_read_socket( mongo *conn, void *buf, int len );
|
||||
int mongo_write_socket( mongo *conn, const void *buf, int len );
|
||||
int mongo_socket_connect( mongo *conn, const char *host, int port );
|
||||
|
||||
MONGO_EXTERN_C_END
|
||||
#endif
|
127
src/mod/event_handlers/mod_cdr_mongodb/driver/src/numbers.c
Normal file
127
src/mod/event_handlers/mod_cdr_mongodb/driver/src/numbers.c
Normal file
@ -0,0 +1,127 @@
|
||||
/* Copyright 2009-2011 10gen Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
/* all the numbers that fit in a 4 byte string */
|
||||
const char bson_numstrs[1000][4] = {
|
||||
"0", "1", "2", "3", "4", "5", "6", "7", "8", "9",
|
||||
"10", "11", "12", "13", "14", "15", "16", "17", "18", "19",
|
||||
"20", "21", "22", "23", "24", "25", "26", "27", "28", "29",
|
||||
"30", "31", "32", "33", "34", "35", "36", "37", "38", "39",
|
||||
"40", "41", "42", "43", "44", "45", "46", "47", "48", "49",
|
||||
"50", "51", "52", "53", "54", "55", "56", "57", "58", "59",
|
||||
"60", "61", "62", "63", "64", "65", "66", "67", "68", "69",
|
||||
"70", "71", "72", "73", "74", "75", "76", "77", "78", "79",
|
||||
"80", "81", "82", "83", "84", "85", "86", "87", "88", "89",
|
||||
"90", "91", "92", "93", "94", "95", "96", "97", "98", "99",
|
||||
|
||||
"100", "101", "102", "103", "104", "105", "106", "107", "108", "109",
|
||||
"110", "111", "112", "113", "114", "115", "116", "117", "118", "119",
|
||||
"120", "121", "122", "123", "124", "125", "126", "127", "128", "129",
|
||||
"130", "131", "132", "133", "134", "135", "136", "137", "138", "139",
|
||||
"140", "141", "142", "143", "144", "145", "146", "147", "148", "149",
|
||||
"150", "151", "152", "153", "154", "155", "156", "157", "158", "159",
|
||||
"160", "161", "162", "163", "164", "165", "166", "167", "168", "169",
|
||||
"170", "171", "172", "173", "174", "175", "176", "177", "178", "179",
|
||||
"180", "181", "182", "183", "184", "185", "186", "187", "188", "189",
|
||||
"190", "191", "192", "193", "194", "195", "196", "197", "198", "199",
|
||||
|
||||
"200", "201", "202", "203", "204", "205", "206", "207", "208", "209",
|
||||
"210", "211", "212", "213", "214", "215", "216", "217", "218", "219",
|
||||
"220", "221", "222", "223", "224", "225", "226", "227", "228", "229",
|
||||
"230", "231", "232", "233", "234", "235", "236", "237", "238", "239",
|
||||
"240", "241", "242", "243", "244", "245", "246", "247", "248", "249",
|
||||
"250", "251", "252", "253", "254", "255", "256", "257", "258", "259",
|
||||
"260", "261", "262", "263", "264", "265", "266", "267", "268", "269",
|
||||
"270", "271", "272", "273", "274", "275", "276", "277", "278", "279",
|
||||
"280", "281", "282", "283", "284", "285", "286", "287", "288", "289",
|
||||
"290", "291", "292", "293", "294", "295", "296", "297", "298", "299",
|
||||
|
||||
"300", "301", "302", "303", "304", "305", "306", "307", "308", "309",
|
||||
"310", "311", "312", "313", "314", "315", "316", "317", "318", "319",
|
||||
"320", "321", "322", "323", "324", "325", "326", "327", "328", "329",
|
||||
"330", "331", "332", "333", "334", "335", "336", "337", "338", "339",
|
||||
"340", "341", "342", "343", "344", "345", "346", "347", "348", "349",
|
||||
"350", "351", "352", "353", "354", "355", "356", "357", "358", "359",
|
||||
"360", "361", "362", "363", "364", "365", "366", "367", "368", "369",
|
||||
"370", "371", "372", "373", "374", "375", "376", "377", "378", "379",
|
||||
"380", "381", "382", "383", "384", "385", "386", "387", "388", "389",
|
||||
"390", "391", "392", "393", "394", "395", "396", "397", "398", "399",
|
||||
|
||||
"400", "401", "402", "403", "404", "405", "406", "407", "408", "409",
|
||||
"410", "411", "412", "413", "414", "415", "416", "417", "418", "419",
|
||||
"420", "421", "422", "423", "424", "425", "426", "427", "428", "429",
|
||||
"430", "431", "432", "433", "434", "435", "436", "437", "438", "439",
|
||||
"440", "441", "442", "443", "444", "445", "446", "447", "448", "449",
|
||||
"450", "451", "452", "453", "454", "455", "456", "457", "458", "459",
|
||||
"460", "461", "462", "463", "464", "465", "466", "467", "468", "469",
|
||||
"470", "471", "472", "473", "474", "475", "476", "477", "478", "479",
|
||||
"480", "481", "482", "483", "484", "485", "486", "487", "488", "489",
|
||||
"490", "491", "492", "493", "494", "495", "496", "497", "498", "499",
|
||||
|
||||
"500", "501", "502", "503", "504", "505", "506", "507", "508", "509",
|
||||
"510", "511", "512", "513", "514", "515", "516", "517", "518", "519",
|
||||
"520", "521", "522", "523", "524", "525", "526", "527", "528", "529",
|
||||
"530", "531", "532", "533", "534", "535", "536", "537", "538", "539",
|
||||
"540", "541", "542", "543", "544", "545", "546", "547", "548", "549",
|
||||
"550", "551", "552", "553", "554", "555", "556", "557", "558", "559",
|
||||
"560", "561", "562", "563", "564", "565", "566", "567", "568", "569",
|
||||
"570", "571", "572", "573", "574", "575", "576", "577", "578", "579",
|
||||
"580", "581", "582", "583", "584", "585", "586", "587", "588", "589",
|
||||
"590", "591", "592", "593", "594", "595", "596", "597", "598", "599",
|
||||
|
||||
"600", "601", "602", "603", "604", "605", "606", "607", "608", "609",
|
||||
"610", "611", "612", "613", "614", "615", "616", "617", "618", "619",
|
||||
"620", "621", "622", "623", "624", "625", "626", "627", "628", "629",
|
||||
"630", "631", "632", "633", "634", "635", "636", "637", "638", "639",
|
||||
"640", "641", "642", "643", "644", "645", "646", "647", "648", "649",
|
||||
"650", "651", "652", "653", "654", "655", "656", "657", "658", "659",
|
||||
"660", "661", "662", "663", "664", "665", "666", "667", "668", "669",
|
||||
"670", "671", "672", "673", "674", "675", "676", "677", "678", "679",
|
||||
"680", "681", "682", "683", "684", "685", "686", "687", "688", "689",
|
||||
"690", "691", "692", "693", "694", "695", "696", "697", "698", "699",
|
||||
|
||||
"700", "701", "702", "703", "704", "705", "706", "707", "708", "709",
|
||||
"710", "711", "712", "713", "714", "715", "716", "717", "718", "719",
|
||||
"720", "721", "722", "723", "724", "725", "726", "727", "728", "729",
|
||||
"730", "731", "732", "733", "734", "735", "736", "737", "738", "739",
|
||||
"740", "741", "742", "743", "744", "745", "746", "747", "748", "749",
|
||||
"750", "751", "752", "753", "754", "755", "756", "757", "758", "759",
|
||||
"760", "761", "762", "763", "764", "765", "766", "767", "768", "769",
|
||||
"770", "771", "772", "773", "774", "775", "776", "777", "778", "779",
|
||||
"780", "781", "782", "783", "784", "785", "786", "787", "788", "789",
|
||||
"790", "791", "792", "793", "794", "795", "796", "797", "798", "799",
|
||||
|
||||
"800", "801", "802", "803", "804", "805", "806", "807", "808", "809",
|
||||
"810", "811", "812", "813", "814", "815", "816", "817", "818", "819",
|
||||
"820", "821", "822", "823", "824", "825", "826", "827", "828", "829",
|
||||
"830", "831", "832", "833", "834", "835", "836", "837", "838", "839",
|
||||
"840", "841", "842", "843", "844", "845", "846", "847", "848", "849",
|
||||
"850", "851", "852", "853", "854", "855", "856", "857", "858", "859",
|
||||
"860", "861", "862", "863", "864", "865", "866", "867", "868", "869",
|
||||
"870", "871", "872", "873", "874", "875", "876", "877", "878", "879",
|
||||
"880", "881", "882", "883", "884", "885", "886", "887", "888", "889",
|
||||
"890", "891", "892", "893", "894", "895", "896", "897", "898", "899",
|
||||
|
||||
"900", "901", "902", "903", "904", "905", "906", "907", "908", "909",
|
||||
"910", "911", "912", "913", "914", "915", "916", "917", "918", "919",
|
||||
"920", "921", "922", "923", "924", "925", "926", "927", "928", "929",
|
||||
"930", "931", "932", "933", "934", "935", "936", "937", "938", "939",
|
||||
"940", "941", "942", "943", "944", "945", "946", "947", "948", "949",
|
||||
"950", "951", "952", "953", "954", "955", "956", "957", "958", "959",
|
||||
"960", "961", "962", "963", "964", "965", "966", "967", "968", "969",
|
||||
"970", "971", "972", "973", "974", "975", "976", "977", "978", "979",
|
||||
"980", "981", "982", "983", "984", "985", "986", "987", "988", "989",
|
||||
"990", "991", "992", "993", "994", "995", "996", "997", "998", "999",
|
||||
};
|
94
src/mod/event_handlers/mod_cdr_mongodb/driver/src/platform.h
Normal file
94
src/mod/event_handlers/mod_cdr_mongodb/driver/src/platform.h
Normal file
@ -0,0 +1,94 @@
|
||||
/** @file platform.h */
|
||||
|
||||
/** Copyright 2009-2011 10gen Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
|
||||
/* all platform-specific ifdefs should go here */
|
||||
|
||||
#ifndef _PLATFORM_HACKS_H_
|
||||
#define _PLATFORM_HACKS_H_
|
||||
|
||||
#ifdef __GNUC__
|
||||
#define MONGO_INLINE static __inline__
|
||||
#else
|
||||
#define MONGO_INLINE static
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
#define MONGO_EXTERN_C_START extern "C" {
|
||||
#define MONGO_EXTERN_C_END }
|
||||
#else
|
||||
#define MONGO_EXTERN_C_START
|
||||
#define MONGO_EXTERN_C_END
|
||||
#endif
|
||||
|
||||
|
||||
#if defined(MONGO_HAVE_STDINT) || __STDC_VERSION__ >= 199901L
|
||||
#include <stdint.h>
|
||||
#elif defined(MONGO_HAVE_UNISTD)
|
||||
#include <unistd.h>
|
||||
#elif defined(MONGO_USE__INT64)
|
||||
typedef __int64 int64_t;
|
||||
typedef unsigned __int64 uint64_t;
|
||||
#elif defined(MONGO_USE_LONG_LONG_INT)
|
||||
typedef long long int int64_t;
|
||||
typedef unsigned long long int uint64_t;
|
||||
#else
|
||||
#error must have a 64bit int type
|
||||
#endif
|
||||
|
||||
/* big endian is only used for OID generation. little is used everywhere else */
|
||||
#ifdef MONGO_BIG_ENDIAN
|
||||
#define bson_little_endian64(out, in) ( bson_swap_endian64(out, in) )
|
||||
#define bson_little_endian32(out, in) ( bson_swap_endian32(out, in) )
|
||||
#define bson_big_endian64(out, in) ( memcpy(out, in, 8) )
|
||||
#define bson_big_endian32(out, in) ( memcpy(out, in, 4) )
|
||||
#else
|
||||
#define bson_little_endian64(out, in) ( memcpy(out, in, 8) )
|
||||
#define bson_little_endian32(out, in) ( memcpy(out, in, 4) )
|
||||
#define bson_big_endian64(out, in) ( bson_swap_endian64(out, in) )
|
||||
#define bson_big_endian32(out, in) ( bson_swap_endian32(out, in) )
|
||||
#endif
|
||||
|
||||
MONGO_EXTERN_C_START
|
||||
|
||||
MONGO_INLINE void bson_swap_endian64( void *outp, const void *inp ) {
|
||||
const char *in = ( const char * )inp;
|
||||
char *out = ( char * )outp;
|
||||
|
||||
out[0] = in[7];
|
||||
out[1] = in[6];
|
||||
out[2] = in[5];
|
||||
out[3] = in[4];
|
||||
out[4] = in[3];
|
||||
out[5] = in[2];
|
||||
out[6] = in[1];
|
||||
out[7] = in[0];
|
||||
|
||||
}
|
||||
MONGO_INLINE void bson_swap_endian32( void *outp, const void *inp ) {
|
||||
const char *in = ( const char * )inp;
|
||||
char *out = ( char * )outp;
|
||||
|
||||
out[0] = in[3];
|
||||
out[1] = in[2];
|
||||
out[2] = in[1];
|
||||
out[3] = in[0];
|
||||
}
|
||||
|
||||
MONGO_EXTERN_C_END
|
||||
|
||||
#endif
|
@ -0,0 +1,183 @@
|
||||
/* net.c */
|
||||
|
||||
/* Copyright 2009-2011 10gen Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
/* Implementation for Linux version of net.h */
|
||||
#include "net.h"
|
||||
#include <string.h>
|
||||
|
||||
int mongo_write_socket( mongo *conn, const void *buf, int len ) {
|
||||
const char *cbuf = buf;
|
||||
while ( len ) {
|
||||
int sent = send( conn->sock, cbuf, len, 0 );
|
||||
if ( sent == -1 ) {
|
||||
conn->err = MONGO_IO_ERROR;
|
||||
return MONGO_ERROR;
|
||||
}
|
||||
cbuf += sent;
|
||||
len -= sent;
|
||||
}
|
||||
|
||||
return MONGO_OK;
|
||||
}
|
||||
|
||||
int mongo_read_socket( mongo *conn, void *buf, int len ) {
|
||||
char *cbuf = buf;
|
||||
while ( len ) {
|
||||
int sent = recv( conn->sock, cbuf, len, 0 );
|
||||
if ( sent == 0 || sent == -1 ) {
|
||||
conn->err = MONGO_IO_ERROR;
|
||||
return MONGO_ERROR;
|
||||
}
|
||||
cbuf += sent;
|
||||
len -= sent;
|
||||
}
|
||||
|
||||
return MONGO_OK;
|
||||
}
|
||||
|
||||
static int mongo_create_socket( mongo *conn ) {
|
||||
int fd;
|
||||
|
||||
if( ( fd = socket( AF_INET, SOCK_STREAM, 0 ) ) == -1 ) {
|
||||
conn->err = MONGO_CONN_NO_SOCKET;
|
||||
return MONGO_ERROR;
|
||||
}
|
||||
conn->sock = fd;
|
||||
|
||||
return MONGO_OK;
|
||||
}
|
||||
|
||||
static int mongo_set_blocking_status( mongo *conn ) {
|
||||
int flags;
|
||||
int blocking;
|
||||
|
||||
blocking = ( conn->conn_timeout_ms == 0 );
|
||||
if( blocking )
|
||||
return MONGO_OK;
|
||||
else {
|
||||
if( ( flags = fcntl( conn->sock, F_GETFL ) ) == -1 ) {
|
||||
conn->err = MONGO_IO_ERROR;
|
||||
mongo_close_socket( conn->sock );
|
||||
return MONGO_ERROR;
|
||||
}
|
||||
|
||||
flags |= O_NONBLOCK;
|
||||
|
||||
if( ( flags = fcntl( conn->sock, F_SETFL, flags ) ) == -1 ) {
|
||||
conn->err = MONGO_IO_ERROR;
|
||||
mongo_close_socket( conn->sock );
|
||||
return MONGO_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
return MONGO_OK;
|
||||
}
|
||||
|
||||
int mongo_set_socket_op_timeout( mongo *conn, int millis ) {
|
||||
struct timeval tv;
|
||||
tv.tv_sec = millis / 1000;
|
||||
tv.tv_usec = ( millis % 1000 ) * 1000;
|
||||
|
||||
if ( setsockopt( conn->sock, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof( tv ) ) == -1 ) {
|
||||
conn->err = MONGO_IO_ERROR;
|
||||
return MONGO_ERROR;
|
||||
}
|
||||
|
||||
if ( setsockopt( conn->sock, SOL_SOCKET, SO_SNDTIMEO, &tv, sizeof( tv ) ) == -1 ) {
|
||||
conn->err = MONGO_IO_ERROR;
|
||||
return MONGO_ERROR;
|
||||
}
|
||||
|
||||
return MONGO_OK;
|
||||
}
|
||||
|
||||
#ifdef _MONGO_USE_GETADDRINFO
|
||||
int mongo_socket_connect( mongo *conn, const char *host, int port ) {
|
||||
|
||||
struct addrinfo *addrs = NULL;
|
||||
struct addrinfo hints;
|
||||
int flag = 1;
|
||||
char port_str[12];
|
||||
int ret;
|
||||
|
||||
conn->sock = 0;
|
||||
conn->connected = 0;
|
||||
|
||||
memset( &hints, 0, sizeof( hints ) );
|
||||
hints.ai_family = AF_INET;
|
||||
hints.ai_socktype = SOCK_STREAM;
|
||||
|
||||
sprintf( port_str, "%d", port );
|
||||
|
||||
if( mongo_create_socket( conn ) != MONGO_OK )
|
||||
return MONGO_ERROR;
|
||||
|
||||
if( getaddrinfo( host, port_str, &hints, &addrs ) != 0 ) {
|
||||
bson_errprintf( "getaddrinfo failed: %s", gai_strerror( ret ) );
|
||||
conn->err = MONGO_CONN_ADDR_FAIL;
|
||||
return MONGO_ERROR;
|
||||
}
|
||||
|
||||
if ( connect( conn->sock, addrs->ai_addr, addrs->ai_addrlen ) == -1 ) {
|
||||
mongo_close_socket( conn->sock );
|
||||
freeaddrinfo( addrs );
|
||||
conn->err = MONGO_CONN_FAIL;
|
||||
return MONGO_ERROR;
|
||||
}
|
||||
|
||||
setsockopt( conn->sock, IPPROTO_TCP, TCP_NODELAY, ( char * )&flag, sizeof( flag ) );
|
||||
if( conn->op_timeout_ms > 0 )
|
||||
mongo_set_socket_op_timeout( conn, conn->op_timeout_ms );
|
||||
|
||||
conn->connected = 1;
|
||||
freeaddrinfo( addrs );
|
||||
|
||||
return MONGO_OK;
|
||||
}
|
||||
#else
|
||||
int mongo_socket_connect( mongo *conn, const char *host, int port ) {
|
||||
struct sockaddr_in sa;
|
||||
socklen_t addressSize;
|
||||
int flag = 1;
|
||||
|
||||
if( mongo_create_socket( conn ) != MONGO_OK )
|
||||
return MONGO_ERROR;
|
||||
|
||||
memset( sa.sin_zero , 0 , sizeof( sa.sin_zero ) );
|
||||
sa.sin_family = AF_INET;
|
||||
sa.sin_port = htons( port );
|
||||
sa.sin_addr.s_addr = inet_addr( host );
|
||||
addressSize = sizeof( sa );
|
||||
|
||||
if ( connect( conn->sock, ( struct sockaddr * )&sa, addressSize ) == -1 ) {
|
||||
mongo_close_socket( conn->sock );
|
||||
conn->connected = 0;
|
||||
conn->sock = 0;
|
||||
conn->err = MONGO_CONN_FAIL;
|
||||
return MONGO_ERROR;
|
||||
}
|
||||
|
||||
setsockopt( conn->sock, IPPROTO_TCP, TCP_NODELAY, ( char * ) &flag, sizeof( flag ) );
|
||||
|
||||
if( conn->op_timeout_ms > 0 )
|
||||
mongo_set_socket_op_timeout( conn, conn->op_timeout_ms );
|
||||
|
||||
conn->connected = 1;
|
||||
|
||||
return MONGO_OK;
|
||||
}
|
||||
#endif
|
@ -0,0 +1,51 @@
|
||||
/**
|
||||
* @file net.h
|
||||
* @brief Networking.
|
||||
*/
|
||||
|
||||
/* Copyright 2009-2011 10gen Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
/* Header for Linux net.h */
|
||||
#ifndef _MONGO_NET_H_
|
||||
#define _MONGO_NET_H_
|
||||
|
||||
#include "mongo.h"
|
||||
|
||||
#include <arpa/inet.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/time.h>
|
||||
#include <netdb.h>
|
||||
#include <netinet/in.h>
|
||||
#include <netinet/tcp.h>
|
||||
#include <fcntl.h>
|
||||
#include <errno.h>
|
||||
#include <unistd.h>
|
||||
#define mongo_close_socket(sock) ( close(sock) )
|
||||
|
||||
#if defined(_XOPEN_SOURCE) || defined(_POSIX_SOURCE) || _POSIX_C_SOURCE >= 1
|
||||
#define _MONGO_USE_GETADDRINFO
|
||||
#endif
|
||||
|
||||
MONGO_EXTERN_C_START
|
||||
|
||||
int mongo_set_socket_op_timeout( mongo *conn, int millis );
|
||||
int mongo_read_socket( mongo *conn, void *buf, int len );
|
||||
int mongo_write_socket( mongo *conn, const void *buf, int len );
|
||||
int mongo_socket_connect( mongo *conn, const char *host, int port );
|
||||
|
||||
MONGO_EXTERN_C_END
|
||||
#endif
|
413
src/mod/event_handlers/mod_cdr_mongodb/mod_cdr_mongodb.c
Normal file
413
src/mod/event_handlers/mod_cdr_mongodb/mod_cdr_mongodb.c
Normal file
@ -0,0 +1,413 @@
|
||||
/*
|
||||
* FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application
|
||||
* Copyright (C) 2005-2011, Anthony Minessale II <anthm@freeswitch.org>
|
||||
*
|
||||
* Version: MPL 1.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Anthony Minessale II <anthm@freeswitch.org>
|
||||
* Portions created by the Initial Developer are Copyright (C)
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Daniel Swarbrick <daniel.swarbrick@seventhsignal.de>
|
||||
*
|
||||
* mod_cdr_mongodb.c -- MongoDB CDR Module
|
||||
*
|
||||
* Derived from:
|
||||
* mod_xml_cdr.c -- XML CDR Module to files or curl
|
||||
*
|
||||
*/
|
||||
#include <switch.h>
|
||||
#include <mongo.h>
|
||||
|
||||
static struct {
|
||||
switch_memory_pool_t *pool;
|
||||
int shutdown;
|
||||
char *mongo_host;
|
||||
uint32_t mongo_port;
|
||||
char *mongo_namespace;
|
||||
mongo mongo_conn[1];
|
||||
switch_mutex_t *mongo_mutex;
|
||||
switch_bool_t log_b;
|
||||
} globals;
|
||||
|
||||
static switch_xml_config_item_t config_settings[] = {
|
||||
/* key, flags, ptr, default_value, syntax, helptext */
|
||||
SWITCH_CONFIG_ITEM_STRING_STRDUP("host", CONFIG_REQUIRED, &globals.mongo_host, "127.0.0.1", NULL, "MongoDB server host address"),
|
||||
SWITCH_CONFIG_ITEM_STRING_STRDUP("namespace", CONFIG_REQUIRED, &globals.mongo_namespace, NULL, "database.collection", "MongoDB namespace"),
|
||||
|
||||
/* key, type, flags, ptr, default_value, data, syntax, helptext */
|
||||
SWITCH_CONFIG_ITEM("port", SWITCH_CONFIG_INT, CONFIG_REQUIRED, &globals.mongo_port, 27017, NULL, NULL, "MongoDB server TCP port"),
|
||||
SWITCH_CONFIG_ITEM("log-b-leg", SWITCH_CONFIG_BOOL, CONFIG_RELOADABLE, &globals.log_b, SWITCH_TRUE, NULL, NULL, "Log B-leg in addition to A-leg"),
|
||||
|
||||
SWITCH_CONFIG_ITEM_END()
|
||||
};
|
||||
|
||||
|
||||
SWITCH_MODULE_LOAD_FUNCTION(mod_cdr_mongodb_load);
|
||||
SWITCH_MODULE_SHUTDOWN_FUNCTION(mod_cdr_mongodb_shutdown);
|
||||
SWITCH_MODULE_DEFINITION(mod_cdr_mongodb, mod_cdr_mongodb_load, mod_cdr_mongodb_shutdown, NULL);
|
||||
|
||||
static void set_bson_profile_data(bson *b, switch_caller_profile_t *caller_profile)
|
||||
{
|
||||
bson_append_string(b, "username", caller_profile->username);
|
||||
bson_append_string(b, "dialplan", caller_profile->dialplan);
|
||||
bson_append_string(b, "caller_id_name", caller_profile->caller_id_name);
|
||||
bson_append_string(b, "ani", caller_profile->ani);
|
||||
bson_append_string(b, "aniii", caller_profile->aniii);
|
||||
bson_append_string(b, "caller_id_number", caller_profile->caller_id_number);
|
||||
bson_append_string(b, "network_addr", caller_profile->network_addr);
|
||||
bson_append_string(b, "rdnis", caller_profile->rdnis);
|
||||
bson_append_string(b, "destination_number", caller_profile->destination_number);
|
||||
bson_append_string(b, "uuid", caller_profile->uuid);
|
||||
bson_append_string(b, "source", caller_profile->source);
|
||||
bson_append_string(b, "context", caller_profile->context);
|
||||
bson_append_string(b, "chan_name", caller_profile->chan_name);
|
||||
}
|
||||
|
||||
|
||||
static switch_status_t my_on_reporting(switch_core_session_t *session)
|
||||
{
|
||||
switch_status_t status = SWITCH_STATUS_SUCCESS;
|
||||
switch_channel_t *channel = switch_core_session_get_channel(session);
|
||||
switch_event_header_t *hi;
|
||||
switch_caller_profile_t *caller_profile;
|
||||
switch_app_log_t *app_log;
|
||||
bson cdr;
|
||||
int is_b;
|
||||
char *tmp;
|
||||
|
||||
if (globals.shutdown) {
|
||||
return SWITCH_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
is_b = channel && switch_channel_get_originator_caller_profile(channel);
|
||||
if (!globals.log_b && is_b) {
|
||||
const char *force_cdr = switch_channel_get_variable(channel, SWITCH_FORCE_PROCESS_CDR_VARIABLE);
|
||||
if (!switch_true(force_cdr)) {
|
||||
return SWITCH_STATUS_SUCCESS;
|
||||
}
|
||||
}
|
||||
|
||||
bson_init(&cdr);
|
||||
|
||||
/* Channel data */
|
||||
bson_append_start_object(&cdr, "channel_data");
|
||||
bson_append_string(&cdr, "state", switch_channel_state_name(switch_channel_get_state(channel)));
|
||||
bson_append_string(&cdr, "direction", switch_channel_direction(channel) == SWITCH_CALL_DIRECTION_OUTBOUND ? "outbound" : "inbound");
|
||||
bson_append_int(&cdr, "state_number", switch_channel_get_state(channel));
|
||||
|
||||
if ((tmp = switch_channel_get_flag_string(channel))) {
|
||||
bson_append_string(&cdr, "flags", tmp);
|
||||
free(tmp);
|
||||
}
|
||||
|
||||
if ((tmp = switch_channel_get_cap_string(channel))) {
|
||||
bson_append_string(&cdr, "caps", tmp);
|
||||
free(tmp);
|
||||
}
|
||||
bson_append_finish_object(&cdr); /* channel_data */
|
||||
|
||||
|
||||
/* Channel variables */
|
||||
bson_append_start_object(&cdr, "variables");
|
||||
for (hi = switch_channel_variable_first(channel); hi; hi = hi->next) {
|
||||
if (!zstr(hi->name) && !zstr(hi->value)) {
|
||||
bson_append_string(&cdr, hi->name, hi->value);
|
||||
}
|
||||
}
|
||||
bson_append_finish_object(&cdr); /* variables */
|
||||
|
||||
|
||||
/* App log */
|
||||
if ((app_log = switch_core_session_get_app_log(session))) {
|
||||
switch_app_log_t *ap;
|
||||
|
||||
bson_append_start_object(&cdr, "app_log");
|
||||
for (ap = app_log; ap; ap = ap->next) {
|
||||
bson_append_start_object(&cdr, "application");
|
||||
bson_append_string(&cdr, "app_name", ap->app);
|
||||
bson_append_string(&cdr, "app_data", ap->arg);
|
||||
bson_append_long(&cdr, "app_stamp", ap->stamp);
|
||||
bson_append_finish_object(&cdr); /* application */
|
||||
}
|
||||
|
||||
bson_append_finish_object(&cdr); /* app_log */
|
||||
}
|
||||
|
||||
|
||||
/* Callflow */
|
||||
caller_profile = switch_channel_get_caller_profile(channel);
|
||||
|
||||
while (caller_profile) {
|
||||
bson_append_start_object(&cdr, "callflow");
|
||||
|
||||
if (!zstr(caller_profile->dialplan)) {
|
||||
bson_append_string(&cdr, "dialplan", caller_profile->dialplan);
|
||||
}
|
||||
|
||||
if (!zstr(caller_profile->profile_index)) {
|
||||
bson_append_string(&cdr, "profile_index", caller_profile->profile_index);
|
||||
}
|
||||
|
||||
if (caller_profile->caller_extension) {
|
||||
switch_caller_application_t *ap;
|
||||
|
||||
bson_append_start_object(&cdr, "extension");
|
||||
|
||||
bson_append_string(&cdr, "name", caller_profile->caller_extension->extension_name);
|
||||
bson_append_string(&cdr, "number", caller_profile->caller_extension->extension_number);
|
||||
|
||||
if (caller_profile->caller_extension->current_application) {
|
||||
bson_append_string(&cdr, "current_app", caller_profile->caller_extension->current_application->application_name);
|
||||
}
|
||||
|
||||
for (ap = caller_profile->caller_extension->applications; ap; ap = ap->next) {
|
||||
bson_append_start_object(&cdr, "application");
|
||||
if (ap == caller_profile->caller_extension->current_application) {
|
||||
bson_append_bool(&cdr, "last_executed", 1);
|
||||
}
|
||||
bson_append_string(&cdr, "app_name", ap->application_name);
|
||||
bson_append_string(&cdr, "app_data", ap->application_data);
|
||||
bson_append_finish_object(&cdr);
|
||||
}
|
||||
|
||||
if (caller_profile->caller_extension->children) {
|
||||
switch_caller_profile_t *cp = NULL;
|
||||
|
||||
for (cp = caller_profile->caller_extension->children; cp; cp = cp->next) {
|
||||
|
||||
if (!cp->caller_extension) {
|
||||
continue;
|
||||
}
|
||||
|
||||
bson_append_start_object(&cdr, "sub_extensions");
|
||||
bson_append_start_object(&cdr, "extension");
|
||||
|
||||
bson_append_string(&cdr, "name", cp->caller_extension->extension_name);
|
||||
bson_append_string(&cdr, "number", cp->caller_extension->extension_number);
|
||||
bson_append_string(&cdr, "dialplan", cp->dialplan);
|
||||
if (cp->caller_extension->current_application) {
|
||||
bson_append_string(&cdr, "current_app", cp->caller_extension->current_application->application_name);
|
||||
}
|
||||
|
||||
for (ap = cp->caller_extension->applications; ap; ap = ap->next) {
|
||||
bson_append_start_object(&cdr, "application");
|
||||
if (ap == cp->caller_extension->current_application) {
|
||||
bson_append_bool(&cdr, "last_executed", 1);
|
||||
}
|
||||
bson_append_string(&cdr, "app_name", ap->application_name);
|
||||
bson_append_string(&cdr, "app_data", ap->application_data);
|
||||
bson_append_finish_object(&cdr);
|
||||
}
|
||||
|
||||
bson_append_finish_object(&cdr); /* extension */
|
||||
bson_append_finish_object(&cdr); /* sub_extensions */
|
||||
}
|
||||
}
|
||||
|
||||
bson_append_finish_object(&cdr); /* extension */
|
||||
}
|
||||
|
||||
bson_append_start_object(&cdr, "caller_profile");
|
||||
set_bson_profile_data(&cdr, caller_profile);
|
||||
|
||||
if (caller_profile->origination_caller_profile) {
|
||||
switch_caller_profile_t *cp = NULL;
|
||||
|
||||
bson_append_start_object(&cdr, "origination");
|
||||
for (cp = caller_profile->origination_caller_profile; cp; cp = cp->next) {
|
||||
bson_append_start_object(&cdr, "origination_caller_profile");
|
||||
set_bson_profile_data(&cdr, cp);
|
||||
bson_append_finish_object(&cdr);
|
||||
}
|
||||
bson_append_finish_object(&cdr); /* origination */
|
||||
}
|
||||
|
||||
if (caller_profile->originator_caller_profile) {
|
||||
switch_caller_profile_t *cp = NULL;
|
||||
|
||||
bson_append_start_object(&cdr, "originator");
|
||||
for (cp = caller_profile->originator_caller_profile; cp; cp = cp->next) {
|
||||
bson_append_start_object(&cdr, "originator_caller_profile");
|
||||
set_bson_profile_data(&cdr, cp);
|
||||
bson_append_finish_object(&cdr);
|
||||
}
|
||||
bson_append_finish_object(&cdr); /* originator */
|
||||
}
|
||||
|
||||
if (caller_profile->originatee_caller_profile) {
|
||||
switch_caller_profile_t *cp = NULL;
|
||||
|
||||
bson_append_start_object(&cdr, "originatee");
|
||||
for (cp = caller_profile->originatee_caller_profile; cp; cp = cp->next) {
|
||||
bson_append_start_object(&cdr, "originatee_caller_profile");
|
||||
set_bson_profile_data(&cdr, cp);
|
||||
bson_append_finish_object(&cdr);
|
||||
}
|
||||
bson_append_finish_object(&cdr); /* originatee */
|
||||
}
|
||||
|
||||
bson_append_finish_object(&cdr); /* caller_profile */
|
||||
|
||||
/* Timestamps */
|
||||
if (caller_profile->times) {
|
||||
bson_append_start_object(&cdr, "times");
|
||||
|
||||
/* Insert timestamps as long ints (microseconds) to preserve accuracy */
|
||||
bson_append_long(&cdr, "created_time", caller_profile->times->created);
|
||||
bson_append_long(&cdr, "profile_created_time", caller_profile->times->profile_created);
|
||||
bson_append_long(&cdr, "progress_time", caller_profile->times->progress);
|
||||
bson_append_long(&cdr, "progress_media_time", caller_profile->times->progress_media);
|
||||
bson_append_long(&cdr, "answered_time", caller_profile->times->answered);
|
||||
bson_append_long(&cdr, "bridged_time", caller_profile->times->bridged);
|
||||
bson_append_long(&cdr, "last_hold_time", caller_profile->times->last_hold);
|
||||
bson_append_long(&cdr, "hold_accum_time", caller_profile->times->hold_accum);
|
||||
bson_append_long(&cdr, "hangup_time", caller_profile->times->hungup);
|
||||
bson_append_long(&cdr, "resurrect_time", caller_profile->times->resurrected);
|
||||
bson_append_long(&cdr, "transfer_time", caller_profile->times->transferred);
|
||||
bson_append_finish_object(&cdr); /* times */
|
||||
}
|
||||
|
||||
bson_append_finish_object(&cdr); /* callflow */
|
||||
caller_profile = caller_profile->next;
|
||||
}
|
||||
|
||||
bson_finish(&cdr);
|
||||
|
||||
switch_mutex_lock(globals.mongo_mutex);
|
||||
|
||||
if (mongo_insert(globals.mongo_conn, globals.mongo_namespace, &cdr) != MONGO_OK) {
|
||||
if (globals.mongo_conn->err == MONGO_IO_ERROR) {
|
||||
mongo_error_t db_status;
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "MongoDB connection failed; attempting reconnect...\n");
|
||||
db_status = mongo_reconnect(globals.mongo_conn);
|
||||
|
||||
if (db_status != MONGO_OK) {
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "MongoDB reconnect failed with error code %d\n", db_status);
|
||||
status = SWITCH_STATUS_FALSE;
|
||||
} else {
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "MongoDB connection re-established.\n");
|
||||
if (mongo_insert(globals.mongo_conn, globals.mongo_namespace, &cdr) != MONGO_OK) {
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "mongo_insert: error code %d\n", globals.mongo_conn->err);
|
||||
status = SWITCH_STATUS_FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
} else {
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "mongo_insert: error code %d\n", globals.mongo_conn->err);
|
||||
status = SWITCH_STATUS_FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
switch_mutex_unlock(globals.mongo_mutex);
|
||||
bson_destroy(&cdr);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
|
||||
static switch_state_handler_table_t state_handlers = {
|
||||
/*.on_init */ NULL,
|
||||
/*.on_routing */ NULL,
|
||||
/*.on_execute */ NULL,
|
||||
/*.on_hangup */ NULL,
|
||||
/*.on_exchange_media */ NULL,
|
||||
/*.on_soft_execute */ NULL,
|
||||
/*.on_consume_media */ NULL,
|
||||
/*.on_hibernate */ NULL,
|
||||
/*.on_reset */ NULL,
|
||||
/*.on_park */ NULL,
|
||||
/*.on_reporting */ my_on_reporting
|
||||
};
|
||||
|
||||
|
||||
static switch_status_t load_config(switch_memory_pool_t *pool)
|
||||
{
|
||||
switch_status_t status = SWITCH_STATUS_SUCCESS;
|
||||
|
||||
if (switch_xml_config_parse_module_settings("cdr_mongodb.conf", SWITCH_FALSE, config_settings) != SWITCH_STATUS_SUCCESS) {
|
||||
return SWITCH_STATUS_FALSE;
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
|
||||
SWITCH_MODULE_LOAD_FUNCTION(mod_cdr_mongodb_load)
|
||||
{
|
||||
switch_status_t status = SWITCH_STATUS_SUCCESS;
|
||||
mongo_error_t db_status;
|
||||
|
||||
memset(&globals, 0, sizeof(globals));
|
||||
globals.pool = pool;
|
||||
if (load_config(pool) != SWITCH_STATUS_SUCCESS) {
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "Unable to load or parse config!\n");
|
||||
}
|
||||
|
||||
db_status = mongo_connect(globals.mongo_conn, globals.mongo_host, globals.mongo_port);
|
||||
|
||||
if (db_status != MONGO_OK) {
|
||||
switch (globals.mongo_conn->err) {
|
||||
case MONGO_CONN_NO_SOCKET:
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "mongo_connect: no socket\n");
|
||||
break;
|
||||
case MONGO_CONN_FAIL:
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "mongo_connect: connection failed\n");
|
||||
break;
|
||||
case MONGO_CONN_NOT_MASTER:
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "mongo_connect: not master\n");
|
||||
break;
|
||||
default:
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "mongo_connect: unknown error %d\n", db_status);
|
||||
}
|
||||
return SWITCH_STATUS_FALSE;
|
||||
} else {
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "Connected to MongoDB server %s:%d\n", globals.mongo_host, globals.mongo_port);
|
||||
}
|
||||
|
||||
switch_mutex_init(&globals.mongo_mutex, SWITCH_MUTEX_NESTED, pool);
|
||||
|
||||
switch_core_add_state_handler(&state_handlers);
|
||||
*module_interface = switch_loadable_module_create_module_interface(pool, modname);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
|
||||
SWITCH_MODULE_SHUTDOWN_FUNCTION(mod_cdr_mongodb_shutdown)
|
||||
{
|
||||
globals.shutdown = 1;
|
||||
switch_core_remove_state_handler(&state_handlers);
|
||||
switch_mutex_destroy(globals.mongo_mutex);
|
||||
|
||||
mongo_destroy(globals.mongo_conn);
|
||||
|
||||
return SWITCH_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* For Emacs:
|
||||
* Local Variables:
|
||||
* mode:c
|
||||
* indent-tabs-mode:t
|
||||
* tab-width:4
|
||||
* c-basic-offset:4
|
||||
* End:
|
||||
* For VIM:
|
||||
* vim:set softtabstop=4 shiftwidth=4 tabstop=4:
|
||||
*/
|
Loading…
x
Reference in New Issue
Block a user