libcouchbase 0.3.3 → 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/ext/libcouchbase/CMakeLists.txt +6 -8
- data/ext/libcouchbase/README.markdown +2 -2
- data/ext/libcouchbase/RELEASE_NOTES.markdown +229 -2
- data/ext/libcouchbase/cmake/Modules/ConfigureDtrace.cmake +11 -0
- data/ext/libcouchbase/cmake/Modules/GenerateConfigDotH.cmake +18 -0
- data/ext/libcouchbase/cmake/Modules/GetLibcouchbaseFlags.cmake +3 -2
- data/ext/libcouchbase/cmake/Modules/GetVersionInfo.cmake +3 -3
- data/ext/libcouchbase/cmake/config-cmake.h.in +4 -0
- data/ext/libcouchbase/cmake/defs.mk.in +0 -2
- data/ext/libcouchbase/cmake/source_files.cmake +21 -5
- data/ext/libcouchbase/contrib/cJSON/cJSON.c +1 -1
- data/ext/libcouchbase/contrib/cbsasl/src/client.c +2 -0
- data/ext/libcouchbase/example/users/README +48 -0
- data/ext/libcouchbase/example/users/users.c +147 -0
- data/ext/libcouchbase/include/libcouchbase/auth.h +175 -31
- data/ext/libcouchbase/include/libcouchbase/cntl.h +82 -1
- data/ext/libcouchbase/include/libcouchbase/couchbase.h +45 -3
- data/ext/libcouchbase/include/libcouchbase/error.h +19 -1
- data/ext/libcouchbase/include/libcouchbase/iops.h +3 -0
- data/ext/libcouchbase/include/libcouchbase/n1ql.h +31 -1
- data/ext/libcouchbase/include/libcouchbase/plugins/io/bsdio-inl.c +4 -1
- data/ext/libcouchbase/include/libcouchbase/subdoc.h +36 -2
- data/ext/libcouchbase/include/libcouchbase/views.h +7 -1
- data/ext/libcouchbase/include/libcouchbase/visibility.h +1 -0
- data/ext/libcouchbase/include/memcached/protocol_binary.h +24 -1146
- data/ext/libcouchbase/packaging/parse-git-describe.pl +1 -1
- data/ext/libcouchbase/plugins/io/libev/libev_io_opts.h +3 -2
- data/ext/libcouchbase/src/README.md +0 -2
- data/ext/libcouchbase/src/auth-priv.h +23 -4
- data/ext/libcouchbase/src/auth.cc +51 -43
- data/ext/libcouchbase/src/bootstrap.cc +244 -0
- data/ext/libcouchbase/src/bootstrap.h +58 -38
- data/ext/libcouchbase/src/bucketconfig/bc_cccp.cc +120 -158
- data/ext/libcouchbase/src/bucketconfig/bc_file.cc +281 -0
- data/ext/libcouchbase/src/bucketconfig/bc_http.cc +526 -0
- data/ext/libcouchbase/src/bucketconfig/bc_http.h +50 -25
- data/ext/libcouchbase/src/bucketconfig/bc_static.cc +150 -0
- data/ext/libcouchbase/src/bucketconfig/clconfig.h +410 -386
- data/ext/libcouchbase/src/bucketconfig/confmon.cc +393 -0
- data/ext/libcouchbase/src/cbft.cc +22 -27
- data/ext/libcouchbase/src/cntl.cc +56 -22
- data/ext/libcouchbase/src/connspec.cc +47 -6
- data/ext/libcouchbase/src/connspec.h +27 -0
- data/ext/libcouchbase/src/dns-srv.cc +147 -0
- data/ext/libcouchbase/src/dump.cc +3 -3
- data/ext/libcouchbase/src/errmap.cc +173 -0
- data/ext/libcouchbase/src/errmap.h +198 -0
- data/ext/libcouchbase/src/getconfig.cc +7 -33
- data/ext/libcouchbase/src/handler.cc +118 -7
- data/ext/libcouchbase/src/hostlist.cc +0 -36
- data/ext/libcouchbase/src/hostlist.h +44 -62
- data/ext/libcouchbase/src/http/http-priv.h +125 -112
- data/ext/libcouchbase/src/http/http.cc +27 -35
- data/ext/libcouchbase/src/http/http.h +1 -34
- data/ext/libcouchbase/src/http/http_io.cc +28 -36
- data/ext/libcouchbase/src/instance.cc +131 -34
- data/ext/libcouchbase/src/internal.h +58 -26
- data/ext/libcouchbase/src/jsparse/parser.cc +136 -210
- data/ext/libcouchbase/src/jsparse/parser.h +84 -98
- data/ext/libcouchbase/src/lcbht/lcbht.cc +177 -0
- data/ext/libcouchbase/src/lcbht/lcbht.h +174 -163
- data/ext/libcouchbase/src/lcbio/connect.cc +569 -0
- data/ext/libcouchbase/src/lcbio/connect.h +16 -7
- data/ext/libcouchbase/src/lcbio/ctx.c +1 -1
- data/ext/libcouchbase/src/lcbio/iotable.h +101 -16
- data/ext/libcouchbase/src/lcbio/{ioutils.c → ioutils.cc} +30 -51
- data/ext/libcouchbase/src/lcbio/ioutils.h +29 -90
- data/ext/libcouchbase/src/lcbio/manager.cc +543 -0
- data/ext/libcouchbase/src/lcbio/manager.h +133 -96
- data/ext/libcouchbase/src/lcbio/protoctx.c +2 -2
- data/ext/libcouchbase/src/lcbio/timer-cxx.h +87 -0
- data/ext/libcouchbase/src/mc/mcreq.c +11 -2
- data/ext/libcouchbase/src/mc/mcreq.h +9 -2
- data/ext/libcouchbase/src/mcserver/mcserver.cc +175 -43
- data/ext/libcouchbase/src/mcserver/mcserver.h +9 -13
- data/ext/libcouchbase/src/mcserver/negotiate.cc +181 -62
- data/ext/libcouchbase/src/mcserver/negotiate.h +1 -3
- data/ext/libcouchbase/src/mctx-helper.h +51 -0
- data/ext/libcouchbase/src/n1ql/ixmgmt.cc +1 -2
- data/ext/libcouchbase/src/n1ql/n1ql.cc +74 -42
- data/ext/libcouchbase/src/netbuf/netbuf.c +4 -4
- data/ext/libcouchbase/src/newconfig.cc +6 -6
- data/ext/libcouchbase/src/nodeinfo.cc +2 -2
- data/ext/libcouchbase/src/operations/{cbflush.c → cbflush.cc} +7 -15
- data/ext/libcouchbase/src/operations/{counter.c → counter.cc} +0 -0
- data/ext/libcouchbase/src/operations/durability.cc +6 -26
- data/ext/libcouchbase/src/operations/durability_internal.h +6 -3
- data/ext/libcouchbase/src/operations/{get.c → get.cc} +24 -26
- data/ext/libcouchbase/src/operations/{observe.c → observe.cc} +68 -93
- data/ext/libcouchbase/src/operations/{pktfwd.c → pktfwd.cc} +0 -0
- data/ext/libcouchbase/src/operations/{remove.c → remove.cc} +0 -0
- data/ext/libcouchbase/src/operations/stats.cc +3 -8
- data/ext/libcouchbase/src/operations/{store.c → store.cc} +27 -32
- data/ext/libcouchbase/src/operations/subdoc.cc +129 -42
- data/ext/libcouchbase/src/operations/{touch.c → touch.cc} +0 -0
- data/ext/libcouchbase/src/packetutils.h +30 -2
- data/ext/libcouchbase/src/probes.d +1 -1
- data/ext/libcouchbase/src/rdb/rope.c +1 -1
- data/ext/libcouchbase/src/{retrychk.c → retrychk.cc} +2 -3
- data/ext/libcouchbase/src/retryq.cc +52 -14
- data/ext/libcouchbase/src/retryq.h +3 -3
- data/ext/libcouchbase/src/settings.c +5 -0
- data/ext/libcouchbase/src/settings.h +11 -0
- data/ext/libcouchbase/src/ssl/ssl_c.c +1 -0
- data/ext/libcouchbase/src/ssl/ssl_common.c +2 -0
- data/ext/libcouchbase/src/ssl/ssl_e.c +0 -1
- data/ext/libcouchbase/src/strcodecs/strcodecs.h +1 -1
- data/ext/libcouchbase/src/trace.h +4 -4
- data/ext/libcouchbase/src/vbucket/vbucket.c +6 -10
- data/ext/libcouchbase/src/views/{docreq.c → docreq.cc} +48 -54
- data/ext/libcouchbase/src/views/docreq.h +24 -30
- data/ext/libcouchbase/src/views/viewreq.cc +318 -0
- data/ext/libcouchbase/src/views/viewreq.h +43 -13
- data/ext/libcouchbase/tests/basic/t_connstr.cc +88 -50
- data/ext/libcouchbase/tests/basic/t_creds.cc +47 -5
- data/ext/libcouchbase/tests/basic/t_host.cc +67 -75
- data/ext/libcouchbase/tests/basic/t_jsparse.cc +27 -82
- data/ext/libcouchbase/tests/basic/t_misc.cc +1 -1
- data/ext/libcouchbase/tests/basic/t_n1qlstrings.cc +0 -1
- data/ext/libcouchbase/tests/htparse/t_basic.cc +58 -78
- data/ext/libcouchbase/tests/ioserver/connection.cc +1 -1
- data/ext/libcouchbase/tests/ioserver/ioserver.cc +19 -6
- data/ext/libcouchbase/tests/iotests/mock-environment.cc +28 -2
- data/ext/libcouchbase/tests/iotests/mock-environment.h +51 -1
- data/ext/libcouchbase/tests/iotests/t_behavior.cc +1 -7
- data/ext/libcouchbase/tests/iotests/t_confmon.cc +97 -115
- data/ext/libcouchbase/tests/iotests/t_durability.cc +0 -1
- data/ext/libcouchbase/tests/iotests/t_eerrs.cc +119 -0
- data/ext/libcouchbase/tests/iotests/t_errmap.cc +178 -0
- data/ext/libcouchbase/tests/iotests/t_misc.cc +3 -3
- data/ext/libcouchbase/tests/iotests/t_netfail.cc +1 -1
- data/ext/libcouchbase/tests/iotests/t_obseqno.cc +0 -1
- data/ext/libcouchbase/tests/iotests/t_subdoc.cc +18 -11
- data/ext/libcouchbase/tests/mc/t_alloc.cc +9 -9
- data/ext/libcouchbase/tests/socktests/socktest.cc +7 -10
- data/ext/libcouchbase/tests/socktests/socktest.h +2 -3
- data/ext/libcouchbase/tests/socktests/t_basic.cc +6 -6
- data/ext/libcouchbase/tests/socktests/t_manager.cc +5 -6
- data/ext/libcouchbase/tests/socktests/t_ssl.cc +1 -1
- data/ext/libcouchbase/tests/vbucket/confdata/ketama_expected.json +2562 -0
- data/ext/libcouchbase/tests/vbucket/confdata/memd_ketama_config.json +31 -0
- data/ext/libcouchbase/tests/vbucket/t_config.cc +35 -5
- data/ext/libcouchbase/tools/CMakeLists.txt +2 -2
- data/ext/libcouchbase/tools/cbc-handlers.h +128 -0
- data/ext/libcouchbase/tools/cbc-n1qlback.cc +64 -10
- data/ext/libcouchbase/tools/cbc-pillowfight.cc +2 -2
- data/ext/libcouchbase/tools/cbc.cc +143 -10
- data/ext/libcouchbase/tools/docgen/loc.h +1 -1
- data/lib/libcouchbase/connection.rb +4 -3
- data/lib/libcouchbase/version.rb +1 -1
- metadata +37 -28
- data/ext/libcouchbase/include/memcached/vbucket.h +0 -42
- data/ext/libcouchbase/src/bootstrap.c +0 -269
- data/ext/libcouchbase/src/bucketconfig/bc_file.c +0 -347
- data/ext/libcouchbase/src/bucketconfig/bc_http.c +0 -630
- data/ext/libcouchbase/src/bucketconfig/bc_mcraw.c +0 -150
- data/ext/libcouchbase/src/bucketconfig/confmon.c +0 -474
- data/ext/libcouchbase/src/lcbht/lcbht.c +0 -282
- data/ext/libcouchbase/src/lcbio/connect.c +0 -557
- data/ext/libcouchbase/src/lcbio/manager.c +0 -584
- data/ext/libcouchbase/src/packetutils.c +0 -37
- data/ext/libcouchbase/src/simplestring.c +0 -211
- data/ext/libcouchbase/src/simplestring.h +0 -228
- data/ext/libcouchbase/src/ssobuf.h +0 -82
- data/ext/libcouchbase/src/views/viewreq.c +0 -358
- data/ext/libcouchbase/tests/basic/t_string.cc +0 -112
|
@@ -20,60 +20,104 @@
|
|
|
20
20
|
#include <libcouchbase/couchbase.h>
|
|
21
21
|
#include <libcouchbase/views.h>
|
|
22
22
|
#include "contrib/jsonsl/jsonsl.h"
|
|
23
|
-
#include "
|
|
23
|
+
#include "contrib/lcb-jsoncpp/lcb-jsoncpp.h"
|
|
24
|
+
#include <string>
|
|
24
25
|
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
#endif
|
|
26
|
+
namespace lcb {
|
|
27
|
+
namespace jsparse {
|
|
28
28
|
|
|
29
|
-
|
|
29
|
+
struct Parser;
|
|
30
30
|
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
31
|
+
struct Row {
|
|
32
|
+
lcb_IOV docid;
|
|
33
|
+
lcb_IOV key;
|
|
34
|
+
lcb_IOV value;
|
|
35
|
+
lcb_IOV row;
|
|
36
|
+
lcb_IOV geo;
|
|
37
|
+
};
|
|
36
38
|
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
39
|
+
struct Parser {
|
|
40
|
+
enum Mode {
|
|
41
|
+
MODE_VIEWS,
|
|
42
|
+
MODE_N1QL,
|
|
43
|
+
MODE_FTS
|
|
44
|
+
};
|
|
45
|
+
|
|
46
|
+
struct Actions {
|
|
47
|
+
/**
|
|
48
|
+
* Called when a row is received.
|
|
49
|
+
* This is a row of view data. You can parse this as JSON from your
|
|
50
|
+
* favorite decoder/converter
|
|
51
|
+
*/
|
|
52
|
+
virtual void JSPARSE_on_row(const Row&) = 0;
|
|
53
|
+
|
|
54
|
+
/**
|
|
55
|
+
* A JSON parse error occured. The payload will contain string data. This
|
|
56
|
+
* may be JSON (but this is not likely).
|
|
57
|
+
* The callback will be delivered twice. First when the error is noticed,
|
|
58
|
+
* and second at the end (instead of a COMPLETE callback)
|
|
59
|
+
*/
|
|
60
|
+
virtual void JSPARSE_on_error(const std::string& buf) = 0;
|
|
61
|
+
|
|
62
|
+
/**
|
|
63
|
+
* All the rows have been returned. In this case, the data is the 'meta'.
|
|
64
|
+
* This is a valid JSON payload which was returned from the server.
|
|
65
|
+
* The "rows" : [] array will be empty.
|
|
66
|
+
*/
|
|
67
|
+
virtual void JSPARSE_on_complete(const std::string& meta) = 0;
|
|
68
|
+
|
|
69
|
+
virtual ~Actions(){}
|
|
70
|
+
};
|
|
41
71
|
|
|
42
72
|
/**
|
|
43
|
-
*
|
|
44
|
-
*
|
|
45
|
-
*
|
|
73
|
+
* Creates a new vrow context object.
|
|
74
|
+
* You must set callbacks on this object if you wish it to be useful.
|
|
75
|
+
* You must feed it data (calling vrow_feed) as well. The data may be fed
|
|
76
|
+
* in chunks and callbacks will be invoked as each row is read.
|
|
46
77
|
*/
|
|
47
|
-
|
|
78
|
+
Parser(Mode mode, Actions* actions_);
|
|
79
|
+
~Parser();
|
|
48
80
|
|
|
49
81
|
/**
|
|
50
|
-
*
|
|
51
|
-
*
|
|
52
|
-
*
|
|
53
|
-
* and second at the end (instead of a COMPLETE callback)
|
|
82
|
+
* Feeds data into the vrow. The callback may be invoked multiple times
|
|
83
|
+
* in this function. In the context of normal lcb usage, this will typically
|
|
84
|
+
* be invoked from within an http_data_callback.
|
|
54
85
|
*/
|
|
55
|
-
|
|
56
|
-
|
|
86
|
+
void feed(const char *s, size_t n);
|
|
87
|
+
void feed(const std::string& s) {
|
|
88
|
+
feed(s.c_str(), s.size());
|
|
89
|
+
}
|
|
57
90
|
|
|
91
|
+
/**
|
|
92
|
+
* Parse the row buffer into its constituent parts. This should be called
|
|
93
|
+
* if you want to split the row into its basic 'docid', 'key' and 'value'
|
|
94
|
+
* fields
|
|
95
|
+
* @param vp The parser to use
|
|
96
|
+
* @param vr The row to parse. This assumes the row's "row" field is properly
|
|
97
|
+
* set.
|
|
98
|
+
*/
|
|
99
|
+
void parse_viewrow(Row& vr);
|
|
58
100
|
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
101
|
+
/**
|
|
102
|
+
* Get the raw contents of the current buffer. This can be used to debug errors.
|
|
103
|
+
*
|
|
104
|
+
* Note that the buffer may be partial or malformed or otherwise unsuitable
|
|
105
|
+
* for structured inspection, but may help human observers debug problems.
|
|
106
|
+
*
|
|
107
|
+
* @param out The iov structure to contain the buffer/offset
|
|
108
|
+
*/
|
|
109
|
+
void get_postmortem(lcb_IOV& out) const;
|
|
67
110
|
|
|
68
|
-
|
|
111
|
+
inline const char *get_buffer_region(size_t pos, size_t desired, size_t* actual);
|
|
112
|
+
inline void combine_meta();
|
|
113
|
+
inline static const char *jprstr_for_mode(Mode);
|
|
69
114
|
|
|
70
|
-
struct lcbvrow_PARSER_st {
|
|
71
115
|
jsonsl_t jsn; /**< Parser for the row itself */
|
|
72
116
|
jsonsl_t jsn_rdetails; /**< Parser for the row details */
|
|
73
117
|
jsonsl_jpr_t jpr; /**< jsonpointer match object */
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
118
|
+
std::string meta_buf; /**< String containing the skeleton (outer layer) */
|
|
119
|
+
std::string current_buf; /**< Scratch/read buffer */
|
|
120
|
+
std::string last_hk; /**< Last hashkey */
|
|
77
121
|
|
|
78
122
|
lcb_U8 mode;
|
|
79
123
|
|
|
@@ -101,73 +145,15 @@ struct lcbvrow_PARSER_st {
|
|
|
101
145
|
*/
|
|
102
146
|
size_t last_row_endpos;
|
|
103
147
|
|
|
104
|
-
void *data;
|
|
105
|
-
|
|
106
148
|
/**
|
|
107
149
|
* std::string to contain parsed document ID.
|
|
108
150
|
*/
|
|
109
|
-
|
|
151
|
+
Json::Value cxx_data;
|
|
110
152
|
|
|
111
153
|
/* callback to invoke */
|
|
112
|
-
|
|
154
|
+
Actions *actions;
|
|
113
155
|
};
|
|
114
156
|
|
|
115
|
-
/**
|
|
116
|
-
* Creates a new vrow context object.
|
|
117
|
-
* You must set callbacks on this object if you wish it to be useful.
|
|
118
|
-
* You must feed it data (calling vrow_feed) as well. The data may be fed
|
|
119
|
-
* in chunks and callbacks will be invoked as each row is read.
|
|
120
|
-
*/
|
|
121
|
-
lcbjsp_PARSER*
|
|
122
|
-
lcbjsp_create(int);
|
|
123
|
-
|
|
124
|
-
/**
|
|
125
|
-
* Resets the context to a pristine state. Callbacks and cookies are kept.
|
|
126
|
-
* This may be more efficient than allocating/freeing a context each time
|
|
127
|
-
* (as this can be expensive with the jsonsl structures)
|
|
128
|
-
*/
|
|
129
|
-
void
|
|
130
|
-
lcbjsp_reset(lcbjsp_PARSER *ctx);
|
|
131
|
-
|
|
132
|
-
/**
|
|
133
|
-
* Frees a vrow object created by vrow_create
|
|
134
|
-
*/
|
|
135
|
-
void
|
|
136
|
-
lcbjsp_free(lcbjsp_PARSER *ctx);
|
|
137
|
-
|
|
138
|
-
/**
|
|
139
|
-
* Feeds data into the vrow. The callback may be invoked multiple times
|
|
140
|
-
* in this function. In the context of normal lcb usage, this will typically
|
|
141
|
-
* be invoked from within an http_data_callback.
|
|
142
|
-
*/
|
|
143
|
-
void
|
|
144
|
-
lcbjsp_feed(lcbjsp_PARSER *ctx, const char *data, size_t ndata);
|
|
145
|
-
|
|
146
|
-
/**
|
|
147
|
-
* Parse the row buffer into its constituent parts. This should be called
|
|
148
|
-
* if you want to split the row into its basic 'docid', 'key' and 'value'
|
|
149
|
-
* fields
|
|
150
|
-
* @param vp The parser to use
|
|
151
|
-
* @param vr The row to parse. This assumes the row's "row" field is properly
|
|
152
|
-
* set.
|
|
153
|
-
*/
|
|
154
|
-
void
|
|
155
|
-
lcbjsp_parse_viewrow(lcbjsp_PARSER *vp, lcbjsp_ROW *vr);
|
|
156
|
-
|
|
157
|
-
/**
|
|
158
|
-
* Get the raw contents of the current buffer. This can be used to debug errors.
|
|
159
|
-
*
|
|
160
|
-
* Note that the buffer may be partial or malformed or otherwise unsuitable
|
|
161
|
-
* for structured inspection, but may help human observers debug problems.
|
|
162
|
-
*
|
|
163
|
-
* @param v The parser
|
|
164
|
-
* @param out The iov structure to contain the buffer/offset
|
|
165
|
-
*/
|
|
166
|
-
void
|
|
167
|
-
lcbjsp_get_postmortem(const lcbjsp_PARSER *v, lcb_IOV *out);
|
|
168
|
-
|
|
169
|
-
#ifdef __cplusplus
|
|
170
157
|
}
|
|
171
|
-
|
|
172
|
-
|
|
158
|
+
}
|
|
173
159
|
#endif /* LCB_VIEWROW_H_ */
|
|
@@ -0,0 +1,177 @@
|
|
|
1
|
+
/* -*- Mode: C; tab-width: 4; c-basic-offset: 4; indent-tabs-mode: nil -*- */
|
|
2
|
+
/*
|
|
3
|
+
* Copyright 2014 Couchbase, Inc.
|
|
4
|
+
*
|
|
5
|
+
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
6
|
+
* you may not use this file except in compliance with the License.
|
|
7
|
+
* You may obtain a copy of the License at
|
|
8
|
+
*
|
|
9
|
+
* http://www.apache.org/licenses/LICENSE-2.0
|
|
10
|
+
*
|
|
11
|
+
* Unless required by applicable law or agreed to in writing, software
|
|
12
|
+
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
13
|
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
14
|
+
* See the License for the specific language governing permissions and
|
|
15
|
+
* limitations under the License.
|
|
16
|
+
*/
|
|
17
|
+
|
|
18
|
+
#include "lcbht.h"
|
|
19
|
+
#include "contrib/http_parser/http_parser.h"
|
|
20
|
+
#include "settings.h"
|
|
21
|
+
|
|
22
|
+
using namespace lcb::htparse;
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
Parser::Parser(lcb_settings_st *settings_)
|
|
26
|
+
: http_parser(), settings(settings_), lastcall(CB_NONE),
|
|
27
|
+
last_body(0), last_bodylen(0), paused(false), is_ex(false) {
|
|
28
|
+
lcb_settings_ref(settings);
|
|
29
|
+
reset();
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
Parser::~Parser() {
|
|
33
|
+
lcb_settings_unref(settings);
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
static int on_hdr_key(http_parser *pb, const char *s, size_t n) {
|
|
37
|
+
return Parser::from_htp(pb)->on_hdr_key(s, n);
|
|
38
|
+
}
|
|
39
|
+
int Parser::on_hdr_key(const char *s, size_t n) {
|
|
40
|
+
if (lastcall != CB_HDR_KEY) {
|
|
41
|
+
/* new key */
|
|
42
|
+
resp.headers.push_back(MimeHeader());
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
resp.headers.back().key.append(s, n);
|
|
46
|
+
lastcall = CB_HDR_KEY;
|
|
47
|
+
return 0;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
static int on_hdr_value(http_parser *pb, const char *s, size_t n) {
|
|
51
|
+
return Parser::from_htp(pb)->on_hdr_value(s, n);
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
int Parser::on_hdr_value(const char *s, size_t n) {
|
|
55
|
+
MimeHeader *header = &resp.headers.back();
|
|
56
|
+
header->value.append(s, n);
|
|
57
|
+
lastcall = CB_HDR_VALUE;
|
|
58
|
+
return 0;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
static int on_hdr_done(http_parser *pb) {
|
|
62
|
+
return Parser::from_htp(pb)->on_hdr_done();
|
|
63
|
+
}
|
|
64
|
+
int Parser::on_hdr_done() {
|
|
65
|
+
resp.state |= S_HTSTATUS|S_HEADER;
|
|
66
|
+
|
|
67
|
+
/* extract the status */
|
|
68
|
+
resp.status = http_parser::status_code;
|
|
69
|
+
lastcall = CB_HDR_DONE;
|
|
70
|
+
return 0;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
static int on_body(http_parser *pb, const char *s, size_t n) {
|
|
74
|
+
return Parser::from_htp(pb)->on_body(s, n);
|
|
75
|
+
}
|
|
76
|
+
int Parser::on_body(const char *s, size_t n) {
|
|
77
|
+
if (is_ex) {
|
|
78
|
+
last_body = s;
|
|
79
|
+
last_bodylen = n;
|
|
80
|
+
paused = true;
|
|
81
|
+
_lcb_http_parser_pause(this, 1);
|
|
82
|
+
} else {
|
|
83
|
+
resp.body.append(s, n);
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
lastcall = CB_BODY;
|
|
87
|
+
resp.state |= S_BODY;
|
|
88
|
+
return 0;
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
static int on_msg_done(http_parser *pb) {
|
|
92
|
+
return Parser::from_htp(pb)->on_msg_done();
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
int Parser::on_msg_done() {
|
|
96
|
+
resp.state |= S_DONE;
|
|
97
|
+
return 0;
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
|
|
101
|
+
static struct http_parser_settings Parser_Settings = {
|
|
102
|
+
NULL, /* msg_begin */
|
|
103
|
+
NULL, /* on_url */
|
|
104
|
+
::on_hdr_key,
|
|
105
|
+
::on_hdr_value,
|
|
106
|
+
::on_hdr_done,
|
|
107
|
+
::on_body,
|
|
108
|
+
::on_msg_done
|
|
109
|
+
};
|
|
110
|
+
|
|
111
|
+
unsigned
|
|
112
|
+
Parser::parse(const void *data_, size_t ndata) {
|
|
113
|
+
is_ex = false;
|
|
114
|
+
size_t nb = _lcb_http_parser_execute(this,
|
|
115
|
+
&Parser_Settings,
|
|
116
|
+
reinterpret_cast<const char *>(data_), ndata);
|
|
117
|
+
|
|
118
|
+
if (nb != ndata) {
|
|
119
|
+
resp.state |= S_ERROR;
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
return resp.state;
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
unsigned
|
|
126
|
+
Parser::parse_ex(const void *data_, unsigned ndata,
|
|
127
|
+
unsigned *nused, unsigned *nbody, const char **pbody)
|
|
128
|
+
{
|
|
129
|
+
is_ex = true;
|
|
130
|
+
size_t nb = _lcb_http_parser_execute(this,
|
|
131
|
+
&Parser_Settings, reinterpret_cast<const char*>(data_), ndata);
|
|
132
|
+
if (nb != ndata) {
|
|
133
|
+
if (paused) {
|
|
134
|
+
_lcb_http_parser_pause(this, 0);
|
|
135
|
+
paused = false;
|
|
136
|
+
} else {
|
|
137
|
+
resp.state |= S_ERROR;
|
|
138
|
+
return resp.state;
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
*nused = nb;
|
|
143
|
+
*nbody = last_bodylen;
|
|
144
|
+
*pbody = last_body;
|
|
145
|
+
|
|
146
|
+
last_body = NULL;
|
|
147
|
+
last_bodylen = 0;
|
|
148
|
+
return resp.state;
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
bool Parser::can_keepalive() const {
|
|
152
|
+
if (!(resp.state & S_DONE)) {
|
|
153
|
+
return 0;
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
if (resp.state & S_ERROR) {
|
|
157
|
+
return 0;
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
return _lcb_http_should_keep_alive(
|
|
161
|
+
const_cast<http_parser*>(static_cast<const http_parser*>(this)));
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
void Parser::reset() {
|
|
165
|
+
resp.clear();
|
|
166
|
+
_lcb_http_parser_init(this, HTTP_RESPONSE);
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
const MimeHeader* Response::get_header(const std::string& key) const {
|
|
170
|
+
std::list<MimeHeader>::const_iterator it;
|
|
171
|
+
for (it = headers.begin(); it != headers.end(); ++it) {
|
|
172
|
+
if (it->key == key) {
|
|
173
|
+
return &*it;
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
return NULL;
|
|
177
|
+
}
|
|
@@ -19,14 +19,11 @@
|
|
|
19
19
|
#define LCB_HTTP_H
|
|
20
20
|
|
|
21
21
|
#include <libcouchbase/couchbase.h>
|
|
22
|
-
#include "
|
|
23
|
-
#include
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
#ifdef __cplusplus
|
|
27
|
-
extern "C" {
|
|
28
|
-
#endif
|
|
22
|
+
#include "contrib/http_parser/http_parser.h"
|
|
23
|
+
#include <list>
|
|
24
|
+
#include <string>
|
|
29
25
|
|
|
26
|
+
struct lcb_settings_st;
|
|
30
27
|
|
|
31
28
|
/**
|
|
32
29
|
* @file
|
|
@@ -39,161 +36,175 @@ extern "C" {
|
|
|
39
36
|
* body.
|
|
40
37
|
*/
|
|
41
38
|
|
|
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
|
-
* Parse incoming data into a message
|
|
86
|
-
* @param parser The parser
|
|
87
|
-
* @param data Pointer to new data
|
|
88
|
-
* @param ndata Size of the data
|
|
89
|
-
*
|
|
90
|
-
* @return The current state of the parser. If `state & LCBHT_S_DONE` then
|
|
91
|
-
* the current response should be handled before continuing.
|
|
92
|
-
* If `state & LCBHT_S_ERROR` then there was an error parsing the contents
|
|
93
|
-
* as it violated the HTTP protocol.
|
|
94
|
-
*/
|
|
95
|
-
lcbht_RESPSTATE
|
|
96
|
-
lcbht_parse(lcbht_pPARSER parser, const void *data, unsigned ndata);
|
|
97
|
-
|
|
98
|
-
/**
|
|
99
|
-
* Parse incoming data without buffering
|
|
100
|
-
* @param parser The parser to use
|
|
101
|
-
* @param data The data to parse
|
|
102
|
-
* @param ndata Length of the data
|
|
103
|
-
* @param[out] nused How much of the data was actually consumed
|
|
104
|
-
* @param[out] nbody Size of the body pointer
|
|
105
|
-
* @param[out] pbody a pointer for the body
|
|
106
|
-
*
|
|
107
|
-
* @return See lcbht_set_bufmode for the meaning of this value
|
|
108
|
-
*
|
|
109
|
-
* @note It is not an error if `pbody` is NULL. It may mean that the parse state
|
|
110
|
-
* is still within the headers and there is no body to parse yet.
|
|
111
|
-
*
|
|
112
|
-
* This function is intended to be used in a loop, until there is no input
|
|
113
|
-
* remaining. The use of the `nused` pointer is to determine by how much the
|
|
114
|
-
* `data` pointer should be incremented (and the `ndata` decremented) for the
|
|
115
|
-
* next call. When this function returns with a non-error status, `pbody`
|
|
116
|
-
* will contain a pointer to a buffer of data (but see note above) which can
|
|
117
|
-
* then be processed by the application.
|
|
118
|
-
*
|
|
119
|
-
* @code{.c}
|
|
120
|
-
* char **body, *input;
|
|
121
|
-
* unsigned inlen = get_input_len(), nused, bodylen;
|
|
122
|
-
* lcbht_RESPSTATE res;
|
|
123
|
-
* do {
|
|
124
|
-
* res = lcbht_parse_ex(parser, input, inlen, &nused, &nbody, &body);
|
|
125
|
-
* if (res & LCBHT_S_ERROR) {
|
|
126
|
-
* // handle error
|
|
127
|
-
* break;
|
|
128
|
-
* }
|
|
129
|
-
* if (nbody) {
|
|
130
|
-
* // handle body
|
|
131
|
-
* }
|
|
132
|
-
* input += nused;
|
|
133
|
-
* inlen -= nused;
|
|
134
|
-
* } while (!(res & LCBHT_S_DONE));
|
|
135
|
-
* @endcode
|
|
136
|
-
*/
|
|
137
|
-
lcbht_RESPSTATE
|
|
138
|
-
lcbht_parse_ex(lcbht_pPARSER parser, const void *data, unsigned ndata,
|
|
139
|
-
unsigned *nused, unsigned *nbody, const char **pbody);
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
/**
|
|
143
|
-
* Obtain the current response being processed.
|
|
144
|
-
* @param parser The parser
|
|
145
|
-
* @return a pointer to a response object. The response object is only valid
|
|
146
|
-
* until the next call into another parser API
|
|
147
|
-
*/
|
|
148
|
-
lcbht_RESPONSE *
|
|
149
|
-
lcbht_get_response(lcbht_pPARSER parser);
|
|
150
|
-
|
|
151
|
-
/**
|
|
152
|
-
* Determine whether HTTP/1.1 keepalive is enabled on the connection
|
|
153
|
-
* @param parser The parser
|
|
154
|
-
* @return true if keepalive is enabled, false otherwise.
|
|
155
|
-
*/
|
|
156
|
-
int
|
|
157
|
-
lcbht_can_keepalive(lcbht_pPARSER parser);
|
|
158
|
-
|
|
159
|
-
/**
|
|
160
|
-
* Clear the response object
|
|
161
|
-
* @param resp the response to clear
|
|
162
|
-
*/
|
|
163
|
-
void
|
|
164
|
-
lcbht_clear_response(lcbht_RESPONSE *resp);
|
|
165
|
-
|
|
166
|
-
/**
|
|
167
|
-
* Get a header value for a key
|
|
168
|
-
* @param response The response
|
|
169
|
-
* @param key The key to look up
|
|
170
|
-
* @return A string containing the value. If the header has no value then the
|
|
171
|
-
* empty string will be returned. If the header does not exist NULL will be
|
|
172
|
-
* returned.
|
|
173
|
-
*/
|
|
174
|
-
const char *
|
|
175
|
-
lcbht_get_resphdr(const lcbht_RESPONSE *response, const char *key);
|
|
39
|
+
namespace lcb {
|
|
40
|
+
namespace htparse {
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
struct MimeHeader {
|
|
44
|
+
std::string key;
|
|
45
|
+
std::string value;
|
|
46
|
+
};
|
|
47
|
+
|
|
48
|
+
struct Response {
|
|
49
|
+
void clear() {
|
|
50
|
+
status = 0;
|
|
51
|
+
state = 0;
|
|
52
|
+
headers.clear();
|
|
53
|
+
body.clear();
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
/**
|
|
57
|
+
* Get a header value for a key
|
|
58
|
+
* @param response The response
|
|
59
|
+
* @param key The key to look up
|
|
60
|
+
* @return A string containing the value. If the header has no value then the
|
|
61
|
+
* empty string will be returned. If the header does not exist NULL will be
|
|
62
|
+
* returned.
|
|
63
|
+
*/
|
|
64
|
+
const MimeHeader* get_header(const std::string& key) const;
|
|
65
|
+
|
|
66
|
+
/**
|
|
67
|
+
* Get a header value for a key
|
|
68
|
+
* @param key The key to look up
|
|
69
|
+
* @return A string containing the value. If the header has no value then the
|
|
70
|
+
* empty string will be returned. If the header does not exist NULL will be
|
|
71
|
+
* returned.
|
|
72
|
+
*/
|
|
73
|
+
const char *get_header_value(const std::string& key) const {
|
|
74
|
+
const MimeHeader *header = get_header(key);
|
|
75
|
+
if (header) {
|
|
76
|
+
return header->value.c_str();
|
|
77
|
+
}
|
|
78
|
+
return NULL;
|
|
79
|
+
}
|
|
176
80
|
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
81
|
+
unsigned short status; /**< HTTP Status code */
|
|
82
|
+
unsigned state;
|
|
83
|
+
typedef std::list<MimeHeader> HeaderList;
|
|
84
|
+
HeaderList headers;
|
|
85
|
+
std::string body; /**< Body */
|
|
86
|
+
};
|
|
87
|
+
|
|
88
|
+
class Parser : private http_parser {
|
|
89
|
+
public:
|
|
90
|
+
/**
|
|
91
|
+
* Initialize the parser object
|
|
92
|
+
* @param settings the settings structure used for logging
|
|
93
|
+
*/
|
|
94
|
+
Parser(lcb_settings_st*);
|
|
95
|
+
~Parser();
|
|
96
|
+
|
|
97
|
+
/** Response state */
|
|
98
|
+
enum State {
|
|
99
|
+
S_NONE = 0,
|
|
100
|
+
S_HTSTATUS = 1 << 0, /**< Have HTTP status */
|
|
101
|
+
S_HEADER = 1 << 1, /**< Have HTTP header */
|
|
102
|
+
S_BODY = 1 << 2, /**< Have HTTP body */
|
|
103
|
+
S_DONE = 1 << 3, /**< Have a full message */
|
|
104
|
+
|
|
105
|
+
/**Have a parse error. Note this is not the same as a HTTP error */
|
|
106
|
+
S_ERROR = 1 << 4
|
|
107
|
+
};
|
|
108
|
+
|
|
109
|
+
/**
|
|
110
|
+
* Parse incoming data into a message
|
|
111
|
+
* @param data Pointer to new data
|
|
112
|
+
* @param ndata Size of the data
|
|
113
|
+
*
|
|
114
|
+
* @return The current state of the parser. If `state & LCBHT_S_DONE` then
|
|
115
|
+
* the current response should be handled before continuing.
|
|
116
|
+
* If `state & LCBHT_S_ERROR` then there was an error parsing the contents
|
|
117
|
+
* as it violated the HTTP protocol.
|
|
118
|
+
*/
|
|
119
|
+
unsigned parse(const void *data, size_t ndata);
|
|
120
|
+
|
|
121
|
+
/**
|
|
122
|
+
* Parse incoming data without buffering
|
|
123
|
+
* @param data The data to parse
|
|
124
|
+
* @param ndata Length of the data
|
|
125
|
+
* @param[out] nused How much of the data was actually consumed
|
|
126
|
+
* @param[out] nbody Size of the body pointer
|
|
127
|
+
* @param[out] pbody a pointer for the body
|
|
128
|
+
*
|
|
129
|
+
* @return See lcbht_set_bufmode for the meaning of this value
|
|
130
|
+
*
|
|
131
|
+
* @note It is not an error if `pbody` is NULL. It may mean that the parse state
|
|
132
|
+
* is still within the headers and there is no body to parse yet.
|
|
133
|
+
*
|
|
134
|
+
* This function is intended to be used in a loop, until there is no input
|
|
135
|
+
* remaining. The use of the `nused` pointer is to determine by how much the
|
|
136
|
+
* `data` pointer should be incremented (and the `ndata` decremented) for the
|
|
137
|
+
* next call. When this function returns with a non-error status, `pbody`
|
|
138
|
+
* will contain a pointer to a buffer of data (but see note above) which can
|
|
139
|
+
* then be processed by the application.
|
|
140
|
+
*
|
|
141
|
+
* @code{.c++}
|
|
142
|
+
* char **body, *input;
|
|
143
|
+
* unsigned inlen = get_input_len(), nused, bodylen;
|
|
144
|
+
* unsigned res;
|
|
145
|
+
* do {
|
|
146
|
+
* res = parser->parse_ex(input, inlen, &nused, &nbody, &body);
|
|
147
|
+
* if (res & Parser::S_ERROR) {
|
|
148
|
+
* // handle error
|
|
149
|
+
* break;
|
|
150
|
+
* }
|
|
151
|
+
* if (nbody) {
|
|
152
|
+
* // handle body
|
|
153
|
+
* }
|
|
154
|
+
* input += nused;
|
|
155
|
+
* inlen -= nused;
|
|
156
|
+
* } while (!(res & Parser::S_DONE));
|
|
157
|
+
* @endcode
|
|
158
|
+
*/
|
|
159
|
+
unsigned parse_ex(const void *data, unsigned ndata,
|
|
160
|
+
unsigned* nused, unsigned *nbody, const char **pbody);
|
|
161
|
+
|
|
162
|
+
/**
|
|
163
|
+
* Obtain the current response being processed.
|
|
164
|
+
* @return a reference to a response object. The response object is only valid
|
|
165
|
+
* until the next call into another parser API
|
|
166
|
+
*/
|
|
167
|
+
Response& get_cur_response() {
|
|
168
|
+
return resp;
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
/**
|
|
172
|
+
* Determine whether HTTP/1.1 keepalive is enabled on the connection
|
|
173
|
+
* @return true if keepalive is enabled, false otherwise.
|
|
174
|
+
*/
|
|
175
|
+
bool can_keepalive() const;
|
|
176
|
+
|
|
177
|
+
void reset();
|
|
178
|
+
|
|
179
|
+
// Callbacks:
|
|
180
|
+
inline int on_hdr_key(const char *, size_t);
|
|
181
|
+
inline int on_hdr_value(const char *, size_t);
|
|
182
|
+
inline int on_hdr_done();
|
|
183
|
+
inline int on_body(const char *, size_t);
|
|
184
|
+
inline int on_msg_done();
|
|
185
|
+
|
|
186
|
+
static Parser* from_htp(http_parser *p) {
|
|
187
|
+
return static_cast<Parser*>(p);
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
private:
|
|
191
|
+
Response resp;
|
|
192
|
+
lcb_settings_st *settings;
|
|
193
|
+
|
|
194
|
+
enum last_call_type {
|
|
195
|
+
CB_NONE, CB_HDR_KEY, CB_HDR_VALUE,
|
|
196
|
+
CB_HDR_DONE, CB_BODY, CB_MSG_DONE
|
|
197
|
+
};
|
|
198
|
+
last_call_type lastcall;
|
|
199
|
+
|
|
200
|
+
/* For parse_ex */
|
|
201
|
+
const char *last_body;
|
|
202
|
+
unsigned last_bodylen;
|
|
203
|
+
|
|
204
|
+
bool paused;
|
|
205
|
+
bool is_ex;
|
|
206
|
+
};
|
|
207
|
+
|
|
208
|
+
} // namespace htparse
|
|
209
|
+
} // namespace lcb
|
|
199
210
|
#endif
|