libcouchbase 0.3.3 → 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (167) hide show
  1. checksums.yaml +4 -4
  2. data/ext/libcouchbase/CMakeLists.txt +6 -8
  3. data/ext/libcouchbase/README.markdown +2 -2
  4. data/ext/libcouchbase/RELEASE_NOTES.markdown +229 -2
  5. data/ext/libcouchbase/cmake/Modules/ConfigureDtrace.cmake +11 -0
  6. data/ext/libcouchbase/cmake/Modules/GenerateConfigDotH.cmake +18 -0
  7. data/ext/libcouchbase/cmake/Modules/GetLibcouchbaseFlags.cmake +3 -2
  8. data/ext/libcouchbase/cmake/Modules/GetVersionInfo.cmake +3 -3
  9. data/ext/libcouchbase/cmake/config-cmake.h.in +4 -0
  10. data/ext/libcouchbase/cmake/defs.mk.in +0 -2
  11. data/ext/libcouchbase/cmake/source_files.cmake +21 -5
  12. data/ext/libcouchbase/contrib/cJSON/cJSON.c +1 -1
  13. data/ext/libcouchbase/contrib/cbsasl/src/client.c +2 -0
  14. data/ext/libcouchbase/example/users/README +48 -0
  15. data/ext/libcouchbase/example/users/users.c +147 -0
  16. data/ext/libcouchbase/include/libcouchbase/auth.h +175 -31
  17. data/ext/libcouchbase/include/libcouchbase/cntl.h +82 -1
  18. data/ext/libcouchbase/include/libcouchbase/couchbase.h +45 -3
  19. data/ext/libcouchbase/include/libcouchbase/error.h +19 -1
  20. data/ext/libcouchbase/include/libcouchbase/iops.h +3 -0
  21. data/ext/libcouchbase/include/libcouchbase/n1ql.h +31 -1
  22. data/ext/libcouchbase/include/libcouchbase/plugins/io/bsdio-inl.c +4 -1
  23. data/ext/libcouchbase/include/libcouchbase/subdoc.h +36 -2
  24. data/ext/libcouchbase/include/libcouchbase/views.h +7 -1
  25. data/ext/libcouchbase/include/libcouchbase/visibility.h +1 -0
  26. data/ext/libcouchbase/include/memcached/protocol_binary.h +24 -1146
  27. data/ext/libcouchbase/packaging/parse-git-describe.pl +1 -1
  28. data/ext/libcouchbase/plugins/io/libev/libev_io_opts.h +3 -2
  29. data/ext/libcouchbase/src/README.md +0 -2
  30. data/ext/libcouchbase/src/auth-priv.h +23 -4
  31. data/ext/libcouchbase/src/auth.cc +51 -43
  32. data/ext/libcouchbase/src/bootstrap.cc +244 -0
  33. data/ext/libcouchbase/src/bootstrap.h +58 -38
  34. data/ext/libcouchbase/src/bucketconfig/bc_cccp.cc +120 -158
  35. data/ext/libcouchbase/src/bucketconfig/bc_file.cc +281 -0
  36. data/ext/libcouchbase/src/bucketconfig/bc_http.cc +526 -0
  37. data/ext/libcouchbase/src/bucketconfig/bc_http.h +50 -25
  38. data/ext/libcouchbase/src/bucketconfig/bc_static.cc +150 -0
  39. data/ext/libcouchbase/src/bucketconfig/clconfig.h +410 -386
  40. data/ext/libcouchbase/src/bucketconfig/confmon.cc +393 -0
  41. data/ext/libcouchbase/src/cbft.cc +22 -27
  42. data/ext/libcouchbase/src/cntl.cc +56 -22
  43. data/ext/libcouchbase/src/connspec.cc +47 -6
  44. data/ext/libcouchbase/src/connspec.h +27 -0
  45. data/ext/libcouchbase/src/dns-srv.cc +147 -0
  46. data/ext/libcouchbase/src/dump.cc +3 -3
  47. data/ext/libcouchbase/src/errmap.cc +173 -0
  48. data/ext/libcouchbase/src/errmap.h +198 -0
  49. data/ext/libcouchbase/src/getconfig.cc +7 -33
  50. data/ext/libcouchbase/src/handler.cc +118 -7
  51. data/ext/libcouchbase/src/hostlist.cc +0 -36
  52. data/ext/libcouchbase/src/hostlist.h +44 -62
  53. data/ext/libcouchbase/src/http/http-priv.h +125 -112
  54. data/ext/libcouchbase/src/http/http.cc +27 -35
  55. data/ext/libcouchbase/src/http/http.h +1 -34
  56. data/ext/libcouchbase/src/http/http_io.cc +28 -36
  57. data/ext/libcouchbase/src/instance.cc +131 -34
  58. data/ext/libcouchbase/src/internal.h +58 -26
  59. data/ext/libcouchbase/src/jsparse/parser.cc +136 -210
  60. data/ext/libcouchbase/src/jsparse/parser.h +84 -98
  61. data/ext/libcouchbase/src/lcbht/lcbht.cc +177 -0
  62. data/ext/libcouchbase/src/lcbht/lcbht.h +174 -163
  63. data/ext/libcouchbase/src/lcbio/connect.cc +569 -0
  64. data/ext/libcouchbase/src/lcbio/connect.h +16 -7
  65. data/ext/libcouchbase/src/lcbio/ctx.c +1 -1
  66. data/ext/libcouchbase/src/lcbio/iotable.h +101 -16
  67. data/ext/libcouchbase/src/lcbio/{ioutils.c → ioutils.cc} +30 -51
  68. data/ext/libcouchbase/src/lcbio/ioutils.h +29 -90
  69. data/ext/libcouchbase/src/lcbio/manager.cc +543 -0
  70. data/ext/libcouchbase/src/lcbio/manager.h +133 -96
  71. data/ext/libcouchbase/src/lcbio/protoctx.c +2 -2
  72. data/ext/libcouchbase/src/lcbio/timer-cxx.h +87 -0
  73. data/ext/libcouchbase/src/mc/mcreq.c +11 -2
  74. data/ext/libcouchbase/src/mc/mcreq.h +9 -2
  75. data/ext/libcouchbase/src/mcserver/mcserver.cc +175 -43
  76. data/ext/libcouchbase/src/mcserver/mcserver.h +9 -13
  77. data/ext/libcouchbase/src/mcserver/negotiate.cc +181 -62
  78. data/ext/libcouchbase/src/mcserver/negotiate.h +1 -3
  79. data/ext/libcouchbase/src/mctx-helper.h +51 -0
  80. data/ext/libcouchbase/src/n1ql/ixmgmt.cc +1 -2
  81. data/ext/libcouchbase/src/n1ql/n1ql.cc +74 -42
  82. data/ext/libcouchbase/src/netbuf/netbuf.c +4 -4
  83. data/ext/libcouchbase/src/newconfig.cc +6 -6
  84. data/ext/libcouchbase/src/nodeinfo.cc +2 -2
  85. data/ext/libcouchbase/src/operations/{cbflush.c → cbflush.cc} +7 -15
  86. data/ext/libcouchbase/src/operations/{counter.c → counter.cc} +0 -0
  87. data/ext/libcouchbase/src/operations/durability.cc +6 -26
  88. data/ext/libcouchbase/src/operations/durability_internal.h +6 -3
  89. data/ext/libcouchbase/src/operations/{get.c → get.cc} +24 -26
  90. data/ext/libcouchbase/src/operations/{observe.c → observe.cc} +68 -93
  91. data/ext/libcouchbase/src/operations/{pktfwd.c → pktfwd.cc} +0 -0
  92. data/ext/libcouchbase/src/operations/{remove.c → remove.cc} +0 -0
  93. data/ext/libcouchbase/src/operations/stats.cc +3 -8
  94. data/ext/libcouchbase/src/operations/{store.c → store.cc} +27 -32
  95. data/ext/libcouchbase/src/operations/subdoc.cc +129 -42
  96. data/ext/libcouchbase/src/operations/{touch.c → touch.cc} +0 -0
  97. data/ext/libcouchbase/src/packetutils.h +30 -2
  98. data/ext/libcouchbase/src/probes.d +1 -1
  99. data/ext/libcouchbase/src/rdb/rope.c +1 -1
  100. data/ext/libcouchbase/src/{retrychk.c → retrychk.cc} +2 -3
  101. data/ext/libcouchbase/src/retryq.cc +52 -14
  102. data/ext/libcouchbase/src/retryq.h +3 -3
  103. data/ext/libcouchbase/src/settings.c +5 -0
  104. data/ext/libcouchbase/src/settings.h +11 -0
  105. data/ext/libcouchbase/src/ssl/ssl_c.c +1 -0
  106. data/ext/libcouchbase/src/ssl/ssl_common.c +2 -0
  107. data/ext/libcouchbase/src/ssl/ssl_e.c +0 -1
  108. data/ext/libcouchbase/src/strcodecs/strcodecs.h +1 -1
  109. data/ext/libcouchbase/src/trace.h +4 -4
  110. data/ext/libcouchbase/src/vbucket/vbucket.c +6 -10
  111. data/ext/libcouchbase/src/views/{docreq.c → docreq.cc} +48 -54
  112. data/ext/libcouchbase/src/views/docreq.h +24 -30
  113. data/ext/libcouchbase/src/views/viewreq.cc +318 -0
  114. data/ext/libcouchbase/src/views/viewreq.h +43 -13
  115. data/ext/libcouchbase/tests/basic/t_connstr.cc +88 -50
  116. data/ext/libcouchbase/tests/basic/t_creds.cc +47 -5
  117. data/ext/libcouchbase/tests/basic/t_host.cc +67 -75
  118. data/ext/libcouchbase/tests/basic/t_jsparse.cc +27 -82
  119. data/ext/libcouchbase/tests/basic/t_misc.cc +1 -1
  120. data/ext/libcouchbase/tests/basic/t_n1qlstrings.cc +0 -1
  121. data/ext/libcouchbase/tests/htparse/t_basic.cc +58 -78
  122. data/ext/libcouchbase/tests/ioserver/connection.cc +1 -1
  123. data/ext/libcouchbase/tests/ioserver/ioserver.cc +19 -6
  124. data/ext/libcouchbase/tests/iotests/mock-environment.cc +28 -2
  125. data/ext/libcouchbase/tests/iotests/mock-environment.h +51 -1
  126. data/ext/libcouchbase/tests/iotests/t_behavior.cc +1 -7
  127. data/ext/libcouchbase/tests/iotests/t_confmon.cc +97 -115
  128. data/ext/libcouchbase/tests/iotests/t_durability.cc +0 -1
  129. data/ext/libcouchbase/tests/iotests/t_eerrs.cc +119 -0
  130. data/ext/libcouchbase/tests/iotests/t_errmap.cc +178 -0
  131. data/ext/libcouchbase/tests/iotests/t_misc.cc +3 -3
  132. data/ext/libcouchbase/tests/iotests/t_netfail.cc +1 -1
  133. data/ext/libcouchbase/tests/iotests/t_obseqno.cc +0 -1
  134. data/ext/libcouchbase/tests/iotests/t_subdoc.cc +18 -11
  135. data/ext/libcouchbase/tests/mc/t_alloc.cc +9 -9
  136. data/ext/libcouchbase/tests/socktests/socktest.cc +7 -10
  137. data/ext/libcouchbase/tests/socktests/socktest.h +2 -3
  138. data/ext/libcouchbase/tests/socktests/t_basic.cc +6 -6
  139. data/ext/libcouchbase/tests/socktests/t_manager.cc +5 -6
  140. data/ext/libcouchbase/tests/socktests/t_ssl.cc +1 -1
  141. data/ext/libcouchbase/tests/vbucket/confdata/ketama_expected.json +2562 -0
  142. data/ext/libcouchbase/tests/vbucket/confdata/memd_ketama_config.json +31 -0
  143. data/ext/libcouchbase/tests/vbucket/t_config.cc +35 -5
  144. data/ext/libcouchbase/tools/CMakeLists.txt +2 -2
  145. data/ext/libcouchbase/tools/cbc-handlers.h +128 -0
  146. data/ext/libcouchbase/tools/cbc-n1qlback.cc +64 -10
  147. data/ext/libcouchbase/tools/cbc-pillowfight.cc +2 -2
  148. data/ext/libcouchbase/tools/cbc.cc +143 -10
  149. data/ext/libcouchbase/tools/docgen/loc.h +1 -1
  150. data/lib/libcouchbase/connection.rb +4 -3
  151. data/lib/libcouchbase/version.rb +1 -1
  152. metadata +37 -28
  153. data/ext/libcouchbase/include/memcached/vbucket.h +0 -42
  154. data/ext/libcouchbase/src/bootstrap.c +0 -269
  155. data/ext/libcouchbase/src/bucketconfig/bc_file.c +0 -347
  156. data/ext/libcouchbase/src/bucketconfig/bc_http.c +0 -630
  157. data/ext/libcouchbase/src/bucketconfig/bc_mcraw.c +0 -150
  158. data/ext/libcouchbase/src/bucketconfig/confmon.c +0 -474
  159. data/ext/libcouchbase/src/lcbht/lcbht.c +0 -282
  160. data/ext/libcouchbase/src/lcbio/connect.c +0 -557
  161. data/ext/libcouchbase/src/lcbio/manager.c +0 -584
  162. data/ext/libcouchbase/src/packetutils.c +0 -37
  163. data/ext/libcouchbase/src/simplestring.c +0 -211
  164. data/ext/libcouchbase/src/simplestring.h +0 -228
  165. data/ext/libcouchbase/src/ssobuf.h +0 -82
  166. data/ext/libcouchbase/src/views/viewreq.c +0 -358
  167. data/ext/libcouchbase/tests/basic/t_string.cc +0 -112
@@ -1,282 +0,0 @@
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 "sllist-inl.h"
20
- #include "contrib/http_parser/http_parser.h"
21
- #include "settings.h"
22
- enum last_call_type {
23
- CB_NONE,
24
- CB_HDR_KEY,
25
- CB_HDR_VALUE,
26
- CB_HDR_DONE,
27
- CB_BODY,
28
- CB_MSG_DONE
29
- };
30
-
31
- struct lcbht_PARSER {
32
- http_parser parser;
33
- lcbht_RESPONSE resp; /**< Current response being processed */
34
- lcb_settings *settings;
35
- enum last_call_type lastcall;
36
-
37
- /* this stuff for parse_ex() */
38
- const char *last_body;
39
- unsigned last_bodylen;
40
- char paused;
41
- char is_ex;
42
- };
43
-
44
- static int
45
- on_hdr_key(http_parser *pb, const char *s, size_t n)
46
- {
47
- lcbht_pPARSER p = (void *)pb;
48
- lcbht_MIMEHDR *hdr;
49
- lcbht_RESPONSE *resp = &p->resp;
50
-
51
- if (p->lastcall != CB_HDR_KEY) {
52
- /* new key */
53
- hdr = calloc(1, sizeof *hdr);
54
- sllist_append(&resp->headers, &hdr->slnode);
55
- lcb_string_init(&hdr->buf_);
56
- } else {
57
- hdr = SLLIST_ITEM(resp->headers.last, lcbht_MIMEHDR, slnode);
58
- }
59
-
60
- /* append key data */
61
- lcb_string_append(&hdr->buf_, s, n);
62
- p->lastcall = CB_HDR_KEY;
63
- return 0;
64
- }
65
-
66
- static int
67
- on_hdr_value(http_parser *pb, const char *s, size_t n)
68
- {
69
- lcbht_pPARSER p = (void *)pb;
70
- lcbht_MIMEHDR *hdr;
71
- lcbht_RESPONSE *resp = &p->resp;
72
-
73
- hdr = SLLIST_ITEM(resp->headers.last, lcbht_MIMEHDR, slnode);
74
- if (p->lastcall == CB_HDR_KEY) {
75
- lcb_string_appendz(&hdr->buf_, ":");
76
- }
77
- lcb_string_append(&hdr->buf_, s, n);
78
- p->lastcall = CB_HDR_VALUE;
79
- return 0;
80
- }
81
-
82
- static int
83
- on_hdr_done(http_parser *pb)
84
- {
85
- lcbht_pPARSER p = (void *)pb;
86
- lcbht_RESPONSE *resp = &p->resp;
87
- sllist_iterator iter;
88
- resp->state |= LCBHT_S_HTSTATUS|LCBHT_S_HEADER;
89
-
90
- /* extract the status */
91
- resp->status = pb->status_code;
92
- p->lastcall = CB_HDR_DONE;
93
-
94
- /** Iterate through all the headers and do proper formatting */
95
- SLLIST_ITERFOR(&resp->headers, &iter) {
96
- char *delim;
97
- lcbht_MIMEHDR *hdr = SLLIST_ITEM(iter.cur, lcbht_MIMEHDR, slnode);
98
-
99
- delim = strstr(hdr->buf_.base, ":");
100
- hdr->key = hdr->buf_.base;
101
-
102
- if (delim) {
103
- *delim = '\0';
104
- hdr->value = delim + 1;
105
- } else {
106
- hdr->value = "";
107
- }
108
- }
109
- return 0;
110
- }
111
-
112
- static int
113
- on_body(http_parser *pb, const char *s, size_t n)
114
- {
115
- lcbht_pPARSER p = (void *)pb;
116
- lcbht_RESPONSE *resp = &p->resp;
117
- if (p->is_ex) {
118
- p->last_body = s;
119
- p->last_bodylen = n;
120
- p->paused = 1;
121
- _lcb_http_parser_pause(pb, 1);
122
- } else {
123
- lcb_string_append(&resp->body, s, n);
124
- }
125
-
126
- p->lastcall = CB_BODY;
127
- resp->state |= LCBHT_S_BODY;
128
- return 0;
129
- }
130
-
131
- static int
132
- on_msg_done(http_parser *pb)
133
- {
134
- lcbht_pPARSER p = (void *)pb;
135
- lcbht_RESPONSE *resp = &p->resp;
136
- resp->state |= LCBHT_S_DONE;
137
- return 0;
138
- }
139
-
140
-
141
- static struct http_parser_settings Parser_Settings = {
142
- NULL, /* msg_begin */
143
- NULL, /* on_url */
144
- on_hdr_key,
145
- on_hdr_value,
146
- on_hdr_done,
147
- on_body,
148
- on_msg_done
149
- };
150
-
151
- lcbht_pPARSER
152
- lcbht_new(lcb_settings *settings)
153
- {
154
- lcbht_pPARSER ret = calloc(1, sizeof *ret);
155
- lcbht_reset(ret);
156
- ret->settings = settings;
157
- lcb_settings_ref(settings);
158
- return ret;
159
- }
160
-
161
- void
162
- lcbht_free(lcbht_pPARSER parser)
163
- {
164
- lcbht_clear_response(&parser->resp);
165
- lcb_settings_unref(parser->settings);
166
- free(parser);
167
- }
168
-
169
- lcbht_RESPSTATE
170
- lcbht_parse(lcbht_pPARSER parser, const void *data, unsigned ndata)
171
- {
172
- size_t nb;
173
- parser->is_ex = 0;
174
- nb = _lcb_http_parser_execute(&parser->parser, &Parser_Settings, data, ndata);
175
- if (nb != ndata) {
176
- parser->resp.state |= LCBHT_S_ERROR;
177
- }
178
- return parser->resp.state;
179
- }
180
-
181
- lcbht_RESPSTATE
182
- lcbht_parse_ex(lcbht_pPARSER parser, const void *data, unsigned ndata,
183
- unsigned *nused, unsigned *nbody, const char **pbody)
184
- {
185
- size_t nb;
186
- parser->is_ex = 1;
187
- nb = _lcb_http_parser_execute(&parser->parser, &Parser_Settings, data, ndata);
188
- if (nb != ndata) {
189
- if (parser->paused) {
190
- _lcb_http_parser_pause(&parser->parser, 0);
191
- parser->paused = 0;
192
- } else {
193
- parser->resp.state |= LCBHT_S_ERROR;
194
- return parser->resp.state;
195
- }
196
- }
197
-
198
- *nused = nb;
199
- *nbody = parser->last_bodylen;
200
- *pbody = parser->last_body;
201
-
202
- parser->last_body = NULL;
203
- parser->last_bodylen = 0;
204
- return parser->resp.state;
205
- }
206
-
207
- lcbht_RESPONSE *
208
- lcbht_get_response(lcbht_pPARSER parser)
209
- {
210
- return &parser->resp;
211
- }
212
-
213
- int
214
- lcbht_can_keepalive(lcbht_pPARSER parser)
215
- {
216
- if (!(parser->resp.state & LCBHT_S_DONE)) {
217
- return 0;
218
- }
219
-
220
- if (parser->resp.state & LCBHT_S_ERROR) {
221
- return 0;
222
- }
223
-
224
- return _lcb_http_should_keep_alive(&parser->parser);
225
- }
226
-
227
- void
228
- lcbht_clear_response(lcbht_RESPONSE *resp)
229
- {
230
- sllist_iterator iter;
231
- SLLIST_ITERFOR(&resp->headers, &iter) {
232
- lcbht_MIMEHDR *hdr = SLLIST_ITEM(iter.cur, lcbht_MIMEHDR, slnode);
233
- lcb_string_release(&hdr->buf_);
234
- sllist_iter_remove(&resp->headers, &iter);
235
- free(hdr);
236
- }
237
- lcb_string_release(&resp->body);
238
- resp->state = 0;
239
- resp->status = 0;
240
- }
241
-
242
- void
243
- lcbht_reset(lcbht_pPARSER parser)
244
- {
245
- lcbht_clear_response(&parser->resp);
246
- _lcb_http_parser_init(&parser->parser, HTTP_RESPONSE);
247
- }
248
-
249
- const char *
250
- lcbht_get_resphdr(const lcbht_RESPONSE *resp, const char *key)
251
- {
252
- sllist_node *curnode;
253
- SLLIST_ITERBASIC(&resp->headers, curnode) {
254
- lcbht_MIMEHDR *hdr = SLLIST_ITEM(curnode, lcbht_MIMEHDR, slnode);
255
- if (!strcmp(hdr->key, key)) {
256
- return hdr->value;
257
- }
258
- }
259
- return NULL;
260
- }
261
-
262
- char **
263
- lcbht_make_resphdrlist(lcbht_RESPONSE *response)
264
- {
265
- char **ret;
266
- unsigned nhdrs = 0;
267
- unsigned curix = 0;
268
- sllist_node *curnode;
269
- SLLIST_ITERBASIC(&response->headers, curnode) {
270
- nhdrs++;
271
- }
272
- ret = malloc(sizeof(*ret) * (nhdrs + 1) * 2);
273
-
274
- SLLIST_ITERBASIC(&response->headers, curnode) {
275
- lcbht_MIMEHDR *hdr = SLLIST_ITEM(curnode, lcbht_MIMEHDR, slnode);
276
- ret[curix++] = strdup(hdr->key);
277
- ret[curix++] = strdup(hdr->value);
278
- }
279
-
280
- ret[curix] = NULL;
281
- return ret;
282
- }
@@ -1,557 +0,0 @@
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 "config.h"
19
- #include "connect.h"
20
- #include "ioutils.h"
21
- #include "iotable.h"
22
- #include "settings.h"
23
- #include "timer-ng.h"
24
- #include <errno.h>
25
-
26
- /* win32 lacks EAI_SYSTEM */
27
- #ifndef EAI_SYSTEM
28
- #define EAI_SYSTEM 0
29
- #endif
30
- #define LOGARGS(conn, lvl) conn->settings, "connection", LCB_LOG_##lvl, __FILE__, __LINE__
31
- static const lcb_host_t *get_loghost(lcbio_SOCKET *s) {
32
- static lcb_host_t host = { "NOHOST", "NOPORT" };
33
- if (!s) { return &host; }
34
- if (!s->info) { return &host; }
35
- return &s->info->ep;
36
- }
37
-
38
- /** Format string arguments for %p%s:%s */
39
- #define CSLOGID(sock) get_loghost(sock)->host, get_loghost(sock)->port, (void*)s
40
- #define CSLOGFMT "<%s:%s> (SOCK=%p) "
41
-
42
- typedef enum {
43
- CS_PENDING = 0,
44
- CS_CANCELLED,
45
- CS_TIMEDOUT,
46
- CS_CONNECTED,
47
- CS_ERROR
48
- } connect_state;
49
-
50
- typedef struct lcbio_CONNSTART {
51
- lcbio_CONNDONE_cb handler;
52
- lcbio_SOCKET *sock;
53
- lcbio_OSERR syserr;
54
- void *arg;
55
- void *event;
56
- short ev_active; /* whether the event pointer is active (Event only) */
57
- short in_uhandler; /* Whether we're inside the user-defined handler */
58
- struct addrinfo *ai_root;
59
- struct addrinfo *ai;
60
- connect_state state;
61
- lcb_error_t pending;
62
- lcbio_ASYNC *async;
63
- char *hoststr;
64
- } lcbio_CONNSTART;
65
-
66
- static void
67
- cs_unwatch(lcbio_CONNSTART *cs)
68
- {
69
- lcbio_SOCKET *s = cs->sock;
70
- if (s && cs->ev_active) {
71
- lcb_assert(s->u.fd != INVALID_SOCKET);
72
- IOT_V0EV(s->io).cancel(IOT_ARG(s->io), s->u.fd, cs->event);
73
- cs->ev_active = 0;
74
- }
75
- }
76
-
77
- /**
78
- * Handler invoked to deliver final status for a connection. This will invoke
79
- * the user supplied callback with the relevant status (if it has not been
80
- * cancelled) and then free the CONNSTART object.
81
- */
82
- static void
83
- cs_handler(void *cookie)
84
- {
85
- lcbio_CONNSTART *cs = cookie;
86
- lcb_error_t err;
87
- lcbio_SOCKET *s = cs->sock;
88
-
89
- if (s && cs->event) {
90
- cs_unwatch(cs);
91
- IOT_V0EV(s->io).destroy(IOT_ARG(s->io), cs->event);
92
- }
93
-
94
- if (cs->state == CS_PENDING) {
95
- /* state was not changed since initial scheduling */
96
- err = LCB_ETIMEDOUT;
97
- } else if (cs->state == CS_CONNECTED) {
98
- /* clear pending error */
99
- err = LCB_SUCCESS;
100
- } else {
101
- if (s != NULL && cs->pending == LCB_CONNECT_ERROR) {
102
- err = lcbio_mklcberr(cs->syserr, s->settings);
103
- } else {
104
- err = cs->pending;
105
- }
106
- }
107
-
108
- if (cs->state == CS_CANCELLED) {
109
- /* ignore everything. Clean up resources */
110
- goto GT_DTOR;
111
- }
112
-
113
- if (s) {
114
- lcbio__load_socknames(s);
115
- if (err == LCB_SUCCESS) {
116
- lcb_log(LOGARGS(s, INFO), CSLOGFMT "Connected ", CSLOGID(s));
117
-
118
- if (s->settings->tcp_nodelay) {
119
- lcb_error_t ndrc = lcbio_disable_nagle(s);
120
- if (ndrc != LCB_SUCCESS) {
121
- lcb_log(LOGARGS(s, INFO), CSLOGFMT "Couldn't set TCP_NODELAY", CSLOGID(s));
122
- } else {
123
- lcb_log(LOGARGS(s, DEBUG), CSLOGFMT "Successfuly set TCP_NODELAY", CSLOGID(s));
124
- }
125
- }
126
- } else {
127
- lcb_log(LOGARGS(s, ERR), CSLOGFMT "Failed: lcb_err=0x%x, os_errno=%u", CSLOGID(s), err, cs->syserr);
128
- }
129
- }
130
-
131
- /** Handler section */
132
- cs->in_uhandler = 1;
133
- cs->handler(err == LCB_SUCCESS ? s : NULL, cs->arg, err, cs->syserr);
134
-
135
- GT_DTOR:
136
- if (cs->async) {
137
- lcbio_timer_destroy(cs->async);
138
- }
139
- if (cs->sock) {
140
- lcbio_unref(cs->sock);
141
- }
142
- if (cs->ai_root) {
143
- freeaddrinfo(cs->ai_root);
144
- }
145
- free(cs);
146
- }
147
-
148
- static void
149
- cs_state_signal(lcbio_CONNSTART *cs, connect_state state, lcb_error_t err)
150
- {
151
- if (cs->state != CS_PENDING) {
152
- /** State already set */
153
- return;
154
- }
155
-
156
-
157
- if (state == CS_CONNECTED) {
158
- /* clear last errors if we're successful */
159
- cs->pending = LCB_SUCCESS;
160
- } else if (cs->pending == LCB_SUCCESS) {
161
- /* set error code only if previous code was not a failure */
162
- cs->pending = err;
163
- }
164
-
165
- cs->state = state;
166
- lcbio_async_signal(cs->async);
167
- }
168
-
169
- /** Cancels and mutes any pending event */
170
- void
171
- lcbio_connect_cancel(lcbio_pCONNSTART cs)
172
- {
173
- if (cs->in_uhandler) {
174
- /* already inside user-defined handler */
175
- return;
176
- }
177
- cs->state = CS_CANCELLED;
178
- cs_handler(cs);
179
- }
180
-
181
-
182
- static int
183
- ensure_sock(lcbio_CONNSTART *cs)
184
- {
185
- lcbio_SOCKET *s = cs->sock;
186
- lcbio_TABLE *io = s->io;
187
- int errtmp = 0;
188
-
189
- if (cs->ai == NULL) {
190
- return -1;
191
- }
192
-
193
- if (IOT_IS_EVENT(io)) {
194
- if (s->u.fd != INVALID_SOCKET) {
195
- /* already have one? */
196
- return 0;
197
- }
198
-
199
- while (s->u.fd == INVALID_SOCKET && cs->ai != NULL) {
200
- s->u.fd = lcbio_E_ai2sock(io, &cs->ai, &errtmp);
201
- if (s->u.fd != INVALID_SOCKET) {
202
- return 0;
203
- }
204
- }
205
- } else {
206
- if (s->u.sd) {
207
- return 0;
208
- }
209
-
210
- while (s->u.sd == NULL && cs->ai != NULL) {
211
- s->u.sd = lcbio_C_ai2sock(io, &cs->ai, &errtmp);
212
- if (s->u.sd) {
213
- s->u.sd->lcbconn = (void *) cs->sock;
214
- s->u.sd->parent = IOT_ARG(io);
215
- return 0;
216
- }
217
- }
218
- }
219
-
220
- if (cs->ai == NULL) {
221
- lcbio_mksyserr(IOT_ERRNO(io), &cs->syserr);
222
- return -1;
223
- }
224
- return 0;
225
- }
226
-
227
- static void
228
- destroy_cursock(lcbio_CONNSTART *cs)
229
- {
230
- lcbio_SOCKET *s = cs->sock;
231
- lcbio_TABLE *iot = s->io;
232
- if (cs->ai) {
233
- cs->ai = cs->ai->ai_next;
234
- }
235
-
236
- if (!cs->ai) {
237
- return;
238
- }
239
-
240
- if (IOT_IS_EVENT(iot)) {
241
- if (cs->ev_active) {
242
- lcb_assert(s->u.fd != INVALID_SOCKET);
243
- IOT_V0EV(iot).cancel(IOT_ARG(iot), s->u.fd, cs->event);
244
- cs->ev_active = 0;
245
- }
246
- IOT_V0IO(iot).close(IOT_ARG(iot), s->u.fd);
247
- s->u.fd = INVALID_SOCKET;
248
- } else {
249
- if (s->u.sd) {
250
- IOT_V1(iot).close(IOT_ARG(iot), s->u.sd);
251
- s->u.sd = NULL;
252
- }
253
- }
254
- }
255
-
256
- static void
257
- E_connect(lcb_socket_t sock, short events, void *arg)
258
- {
259
- lcbio_CONNSTART *cs = arg;
260
- lcbio_SOCKET *s = cs->sock;
261
- lcbio_TABLE *io = s->io;
262
- int retry_once = 0;
263
- lcbio_CSERR connstatus;
264
-
265
- (void)sock;
266
-
267
- lcb_log(LOGARGS(s, TRACE), CSLOGFMT "Got event handler for new connection", CSLOGID(s));
268
-
269
- GT_NEXTSOCK:
270
- if (ensure_sock(cs) == -1) {
271
- cs_state_signal(cs, CS_ERROR, LCB_CONNECT_ERROR);
272
- return;
273
- }
274
-
275
- if (events & LCB_ERROR_EVENT) {
276
- socklen_t errlen = sizeof(int);
277
- int sockerr = 0;
278
- lcb_log(LOGARGS(s, TRACE), CSLOGFMT "Received ERROR_EVENT", CSLOGID(s));
279
- getsockopt(s->u.fd, SOL_SOCKET, SO_ERROR, (char *)&sockerr, &errlen);
280
- lcbio_mksyserr(sockerr, &cs->syserr);
281
- destroy_cursock(cs);
282
- goto GT_NEXTSOCK;
283
-
284
- } else {
285
- int rv = 0;
286
- struct addrinfo *ai = cs->ai;
287
-
288
- GT_CONNECT:
289
- rv = IOT_V0IO(io).connect0(
290
- IOT_ARG(io), s->u.fd, ai->ai_addr, (unsigned)ai->ai_addrlen);
291
-
292
- if (rv == 0) {
293
- cs_unwatch(cs);
294
- cs_state_signal(cs, CS_CONNECTED, LCB_SUCCESS);
295
- return;
296
- }
297
- }
298
-
299
- connstatus = lcbio_mkcserr(IOT_ERRNO(io));
300
- lcbio_mksyserr(IOT_ERRNO(io), &cs->syserr);
301
-
302
-
303
- switch (connstatus) {
304
-
305
- case LCBIO_CSERR_INTR:
306
- goto GT_CONNECT;
307
-
308
- case LCBIO_CSERR_CONNECTED:
309
- cs_unwatch(cs);
310
- cs_state_signal(cs, CS_CONNECTED, LCB_SUCCESS);
311
- return;
312
-
313
- case LCBIO_CSERR_BUSY:
314
- lcb_log(LOGARGS(s, TRACE), CSLOGFMT "Scheduling asynchronous watch for socket.", CSLOGID(s));
315
- IOT_V0EV(io).watch(
316
- IOT_ARG(io), s->u.fd, cs->event, LCB_WRITE_EVENT, cs, E_connect);
317
- cs->ev_active = 1;
318
- return;
319
-
320
- case LCBIO_CSERR_EINVAL:
321
- if (!retry_once) {
322
- retry_once = 1;
323
- goto GT_CONNECT;
324
- }
325
- /* fallthrough */
326
-
327
- case LCBIO_CSERR_EFAIL:
328
- default:
329
- /* close the current socket and try again */
330
- lcb_log(LOGARGS(s, TRACE), CSLOGFMT "connect() failed. os_error=%d [%s]", CSLOGID(s), IOT_ERRNO(io), strerror(IOT_ERRNO(io)));
331
- destroy_cursock(cs);
332
- goto GT_NEXTSOCK;
333
- }
334
- }
335
-
336
- static void C_connect(lcbio_CONNSTART *cs);
337
-
338
- static void
339
- C_conncb(lcb_sockdata_t *sock, int status)
340
- {
341
- lcbio_SOCKET *s = (void *)sock->lcbconn;
342
- lcbio_CONNSTART *cs = (void *)s->ctx;
343
-
344
- lcb_log(LOGARGS(s, TRACE), CSLOGFMT "Received completion handler. Status=%d. errno=%d", CSLOGID(s), status, IOT_ERRNO(s->io));
345
-
346
- if (!--s->refcount) {
347
- lcbio__destroy(s);
348
- return;
349
- }
350
-
351
- if (!status) {
352
- if (cs->state == CS_PENDING) {
353
- cs->state = CS_CONNECTED;
354
- }
355
- cs_handler(cs);
356
- } else {
357
- lcbio_mksyserr(IOT_ERRNO(s->io), &cs->syserr);
358
- destroy_cursock(cs);
359
- C_connect(cs);
360
- }
361
- }
362
-
363
- static void
364
- C_connect(lcbio_CONNSTART *cs)
365
- {
366
- int rv;
367
- lcbio_SOCKET *s = cs->sock;
368
- int retry_once = 0;
369
- lcbio_CSERR status;
370
- lcbio_TABLE *io = s->io;
371
-
372
- GT_NEXTSOCK:
373
- if (ensure_sock(cs) != 0) {
374
- lcbio_mksyserr(IOT_ERRNO(io), &cs->syserr);
375
- cs_state_signal(cs, CS_ERROR, LCB_CONNECT_ERROR);
376
- return;
377
- }
378
-
379
- GT_CONNECT:
380
- rv = IOT_V1(io).connect(IOT_ARG(io), s->u.sd, cs->ai->ai_addr,
381
- (unsigned)cs->ai->ai_addrlen, C_conncb);
382
- if (rv == 0) {
383
- lcbio_ref(s);
384
- return;
385
- }
386
-
387
- lcbio_mksyserr(IOT_ERRNO(io), &cs->syserr);
388
- status = lcbio_mkcserr(IOT_ERRNO(io));
389
- switch (status) {
390
-
391
- case LCBIO_CSERR_INTR:
392
- goto GT_CONNECT;
393
-
394
- case LCBIO_CSERR_CONNECTED:
395
- cs_state_signal(cs, CS_CONNECTED, LCB_SUCCESS);
396
- return;
397
-
398
- case LCBIO_CSERR_BUSY:
399
- return;
400
-
401
- case LCBIO_CSERR_EINVAL:
402
- if (!retry_once) {
403
- retry_once = 1;
404
- goto GT_CONNECT;
405
- }
406
- /* fallthrough */
407
-
408
- case LCBIO_CSERR_EFAIL:
409
- default:
410
- destroy_cursock(cs);
411
- goto GT_NEXTSOCK;
412
- }
413
- }
414
-
415
- struct lcbio_CONNSTART *
416
- lcbio_connect(lcbio_TABLE *iot, lcb_settings *settings, const lcb_host_t *dest,
417
- uint32_t timeout, lcbio_CONNDONE_cb handler, void *arg)
418
- {
419
- lcbio_SOCKET *s;
420
- lcbio_CONNSTART *ret;
421
- struct addrinfo hints;
422
- int rv;
423
-
424
- s = calloc(1, sizeof(*s));
425
- ret = calloc(1, sizeof(*ret));
426
-
427
- /** Initialize the socket first */
428
- s->io = iot;
429
- s->settings = settings;
430
- s->ctx = ret;
431
- s->refcount = 1;
432
- s->info = calloc(1, sizeof(*s->info));
433
- s->info->ep = *dest;
434
- lcbio_table_ref(s->io);
435
- lcb_settings_ref(s->settings);
436
- lcb_list_init(&s->protos);
437
-
438
- if (IOT_IS_EVENT(iot)) {
439
- s->u.fd = INVALID_SOCKET;
440
- ret->event = IOT_V0EV(iot).create(IOT_ARG(iot));
441
- }
442
-
443
- /** Initialize the connstart structure */
444
- ret->handler = handler;
445
- ret->arg = arg;
446
- ret->sock = s;
447
- ret->async = lcbio_timer_new(iot, ret, cs_handler);
448
-
449
- lcbio_timer_rearm(ret->async, timeout);
450
- lcb_log(LOGARGS(s, INFO), CSLOGFMT "Starting. Timeout=%uus", CSLOGID(s), timeout);
451
-
452
- /** Hostname lookup: */
453
- memset(&hints, 0, sizeof(hints));
454
- hints.ai_flags = AI_PASSIVE;
455
- hints.ai_socktype = SOCK_STREAM;
456
- if (settings->ipv6 == LCB_IPV6_DISABLED) {
457
- hints.ai_family = AF_INET;
458
- } else if (settings->ipv6 == LCB_IPV6_ONLY) {
459
- hints.ai_family = AF_INET6;
460
- } else {
461
- hints.ai_family = AF_UNSPEC;
462
- }
463
-
464
- if ((rv = getaddrinfo(dest->host, dest->port, &hints, &ret->ai_root))) {
465
- const char *errstr = rv != EAI_SYSTEM ? gai_strerror(rv) : "";
466
- lcb_log(LOGARGS(s, ERR), CSLOGFMT "Couldn't look up %s (%s) [EAI=%d]", CSLOGID(s), dest->host, errstr, rv);
467
- cs_state_signal(ret, CS_ERROR, LCB_UNKNOWN_HOST);
468
- } else {
469
- ret->ai = ret->ai_root;
470
-
471
- /** Figure out how to connect */
472
- if (IOT_IS_EVENT(iot)) {
473
- E_connect(-1, LCB_WRITE_EVENT, ret);
474
- } else {
475
- C_connect(ret);
476
- }
477
- }
478
- return ret;
479
- }
480
-
481
- lcbio_CONNSTART *
482
- lcbio_connect_hl(lcbio_TABLE *iot, lcb_settings *settings,
483
- hostlist_t hl, int rollover, uint32_t timeout,
484
- lcbio_CONNDONE_cb handler, void *arg)
485
- {
486
- const lcb_host_t *cur;
487
- unsigned ii, hlmax;
488
- ii = 0;
489
- hlmax = hostlist_size(hl);
490
-
491
- while ( (cur = hostlist_shift_next(hl, rollover)) && ii++ < hlmax) {
492
- lcbio_CONNSTART *ret = lcbio_connect(
493
- iot, settings, cur, timeout, handler, arg);
494
- if (ret) {
495
- return ret;
496
- }
497
- }
498
-
499
- return NULL;
500
- }
501
-
502
- lcbio_SOCKET *
503
- lcbio_wrap_fd(lcbio_pTABLE iot, lcb_settings *settings, lcb_socket_t fd)
504
- {
505
- lcbio_SOCKET *ret = calloc(1, sizeof(*ret));
506
- lcbio_CONNDONE_cb *ci = calloc(1, sizeof(*ci));
507
-
508
- if (ret == NULL || ci == NULL) {
509
- free(ret);
510
- free(ci);
511
- return NULL;
512
- }
513
-
514
- assert(iot->model = LCB_IOMODEL_EVENT);
515
-
516
- lcb_list_init(&ret->protos);
517
- ret->settings = settings;
518
- ret->io = iot;
519
- ret->refcount = 1;
520
- ret->u.fd = fd;
521
-
522
- lcbio_table_ref(ret->io);
523
- lcb_settings_ref(ret->settings);
524
- lcbio__load_socknames(ret);
525
- return ret;
526
- }
527
-
528
- void
529
- lcbio_shutdown(lcbio_SOCKET *s)
530
- {
531
- lcbio_TABLE *io = s->io;
532
-
533
- lcbio__protoctx_delall(s);
534
- if (IOT_IS_EVENT(io)) {
535
- if (s->u.fd != INVALID_SOCKET) {
536
- IOT_V0IO(io).close(IOT_ARG(io), s->u.fd);
537
- s->u.fd = INVALID_SOCKET;
538
- }
539
- } else {
540
- if (s->u.sd) {
541
- IOT_V1(io).close(IOT_ARG(io), s->u.sd);
542
- s->u.sd = NULL;
543
- }
544
- }
545
- }
546
-
547
- void
548
- lcbio__destroy(lcbio_SOCKET *s)
549
- {
550
- lcbio_shutdown(s);
551
- if (s->info) {
552
- free(s->info);
553
- }
554
- lcbio_table_unref(s->io);
555
- lcb_settings_unref(s->settings);
556
- free(s);
557
- }