trilogy 2.0.0
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of trilogy might be problematic. Click here for more details.
- checksums.yaml +7 -0
- data/LICENSE +22 -0
- data/README.md +74 -0
- data/Rakefile +18 -0
- data/ext/trilogy-ruby/cast.c +272 -0
- data/ext/trilogy-ruby/cext.c +933 -0
- data/ext/trilogy-ruby/extconf.rb +16 -0
- data/ext/trilogy-ruby/inc/trilogy/blocking.h +163 -0
- data/ext/trilogy-ruby/inc/trilogy/buffer.h +64 -0
- data/ext/trilogy-ruby/inc/trilogy/builder.h +161 -0
- data/ext/trilogy-ruby/inc/trilogy/charset.h +277 -0
- data/ext/trilogy-ruby/inc/trilogy/client.h +546 -0
- data/ext/trilogy-ruby/inc/trilogy/error.h +43 -0
- data/ext/trilogy-ruby/inc/trilogy/packet_parser.h +34 -0
- data/ext/trilogy-ruby/inc/trilogy/protocol.h +756 -0
- data/ext/trilogy-ruby/inc/trilogy/reader.h +212 -0
- data/ext/trilogy-ruby/inc/trilogy/socket.h +111 -0
- data/ext/trilogy-ruby/inc/trilogy/vendor/curl_hostcheck.h +29 -0
- data/ext/trilogy-ruby/inc/trilogy/vendor/openssl_hostname_validation.h +51 -0
- data/ext/trilogy-ruby/inc/trilogy.h +8 -0
- data/ext/trilogy-ruby/src/blocking.c +241 -0
- data/ext/trilogy-ruby/src/buffer.c +60 -0
- data/ext/trilogy-ruby/src/builder.c +198 -0
- data/ext/trilogy-ruby/src/charset.c +212 -0
- data/ext/trilogy-ruby/src/client.c +728 -0
- data/ext/trilogy-ruby/src/error.c +17 -0
- data/ext/trilogy-ruby/src/packet_parser.c +140 -0
- data/ext/trilogy-ruby/src/protocol.c +676 -0
- data/ext/trilogy-ruby/src/reader.c +244 -0
- data/ext/trilogy-ruby/src/socket.c +623 -0
- data/ext/trilogy-ruby/src/vendor/curl_hostcheck.c +206 -0
- data/ext/trilogy-ruby/src/vendor/openssl_hostname_validation.c +175 -0
- data/ext/trilogy-ruby/trilogy-ruby.h +36 -0
- data/lib/trilogy/version.rb +3 -0
- data/lib/trilogy.rb +61 -0
- data/trilogy.gemspec +27 -0
- metadata +106 -0
@@ -0,0 +1,546 @@
|
|
1
|
+
#ifndef TRILOGY_CLIENT_H
|
2
|
+
#define TRILOGY_CLIENT_H
|
3
|
+
|
4
|
+
#include <sys/socket.h>
|
5
|
+
#include <sys/types.h>
|
6
|
+
#include <unistd.h>
|
7
|
+
|
8
|
+
#include "trilogy/buffer.h"
|
9
|
+
#include "trilogy/packet_parser.h"
|
10
|
+
#include "trilogy/protocol.h"
|
11
|
+
#include "trilogy/socket.h"
|
12
|
+
|
13
|
+
/* Trilogy Non-blocking Client API
|
14
|
+
*
|
15
|
+
* This API is designed for allowing the caller to deal with I/O themselves.
|
16
|
+
* The API is split into `_send` and `_recv` calls. Allowing the caller to wait
|
17
|
+
* on writeability before calling a `_send` function, and waiting for
|
18
|
+
* readability before `_recv` calls. This can especially be useful for
|
19
|
+
* applications that live inside of managed runtime or event-loop.
|
20
|
+
*
|
21
|
+
* Some pseudo-code typical lifecycle of a connection might look something like
|
22
|
+
* this:
|
23
|
+
*
|
24
|
+
* trilogy_conn_t conn;
|
25
|
+
* trilogy_init(&conn);
|
26
|
+
*
|
27
|
+
* trilogy_connect_send(&conn, addrinfo);
|
28
|
+
*
|
29
|
+
* trilogy_handshake_t handshake;
|
30
|
+
* trilogy_connect_recv(&conn, &handshake);
|
31
|
+
*
|
32
|
+
* trilogy_auth_send(&conn, &handshake, "root", NULL, 0, 0);
|
33
|
+
* int rc = trilogy_auth_recv(&conn, &handshake);
|
34
|
+
* if (rc == TRILOGY_AUTH_SWITCH) {
|
35
|
+
* trilogy_auth_switch_send(&conn, &handshake);
|
36
|
+
* trilogy_auth_recv(&conn, &handshake);
|
37
|
+
* }
|
38
|
+
*
|
39
|
+
* At this point the connection is open, authenticated, and ready for commands.
|
40
|
+
* From here a caller can start issuing commands:
|
41
|
+
*
|
42
|
+
* char* db_name = "test";
|
43
|
+
* trilogy_change_db_send(&conn, db_name, strlen(db_name));
|
44
|
+
* trilogy_change_db_recv(&conn);
|
45
|
+
*
|
46
|
+
* Assuming the connection isn't in an error state, and all responses have been
|
47
|
+
* read off the network - it's ready for another command.
|
48
|
+
*
|
49
|
+
* Specific to the trilogy_query_send/trilogy_query_recv lifecycle - if
|
50
|
+
* TRILOGY_HAVE_RESULTS is returned from trilogy_query_recv, the caller *must* read
|
51
|
+
* all columns and rows from the server before the connection will be command-
|
52
|
+
* ready again. This is a requirement of a MySQL-compatible protocol.
|
53
|
+
*
|
54
|
+
* trilogy_close_send/trilogy_close_recv may be used to sent a quit command to the
|
55
|
+
* server. While this is considered best practice, simply calling trilogy_free
|
56
|
+
* to close the socket and free any internal buffers is enough to clean things
|
57
|
+
* up.
|
58
|
+
*/
|
59
|
+
|
60
|
+
#define TRILOGY_DEFAULT_BUF_SIZE 32768
|
61
|
+
|
62
|
+
/* trilogy_column_t - The Trilogy client's column type.
|
63
|
+
*/
|
64
|
+
typedef trilogy_column_packet_t trilogy_column_t;
|
65
|
+
|
66
|
+
/* trilogy_conn_t - The Trilogy client's instance type.
|
67
|
+
*
|
68
|
+
* This type is shared for the non-blocking and blocking versions of the API.
|
69
|
+
*/
|
70
|
+
typedef struct {
|
71
|
+
uint64_t affected_rows;
|
72
|
+
uint64_t last_insert_id;
|
73
|
+
uint16_t warning_count;
|
74
|
+
char last_gtid[TRILOGY_MAX_LAST_GTID_LEN];
|
75
|
+
size_t last_gtid_len;
|
76
|
+
|
77
|
+
uint16_t error_code;
|
78
|
+
const char *error_message;
|
79
|
+
size_t error_message_len;
|
80
|
+
|
81
|
+
uint32_t capabilities;
|
82
|
+
uint16_t server_status;
|
83
|
+
|
84
|
+
trilogy_sock_t *socket;
|
85
|
+
|
86
|
+
// private:
|
87
|
+
uint8_t recv_buff[TRILOGY_DEFAULT_BUF_SIZE];
|
88
|
+
size_t recv_buff_pos;
|
89
|
+
size_t recv_buff_len;
|
90
|
+
|
91
|
+
trilogy_packet_parser_t packet_parser;
|
92
|
+
trilogy_buffer_t packet_buffer;
|
93
|
+
size_t packet_buffer_written;
|
94
|
+
|
95
|
+
uint64_t column_count;
|
96
|
+
bool started_reading_rows;
|
97
|
+
} trilogy_conn_t;
|
98
|
+
|
99
|
+
/* trilogy_init - Initialize a pre-allocated trilogy_conn_t pointer.
|
100
|
+
*
|
101
|
+
* conn - A pre-allocated trilogy_conn_t pointer.
|
102
|
+
*
|
103
|
+
* Return values:
|
104
|
+
* TRILOGY_OK - The trilogy_conn_t pointer was properly initialized
|
105
|
+
* TRILOGY_SYSERR - A system error occurred, check errno.
|
106
|
+
*/
|
107
|
+
int trilogy_init(trilogy_conn_t *conn);
|
108
|
+
|
109
|
+
/* trilogy_flush_writes - Attempt to flush the internal packet buffer to the
|
110
|
+
* network. This must be used if a `_send` function returns TRILOGY_AGAIN, and
|
111
|
+
* should continue to be called until it returns a value other than
|
112
|
+
* TRILOGY_AGAIN.
|
113
|
+
*
|
114
|
+
* conn - A connected trilogy_conn_t pointer. Using a disconnected trilogy_conn_t is
|
115
|
+
* undefined.
|
116
|
+
*
|
117
|
+
* Return values:
|
118
|
+
* TRILOGY_OK - The entire packet buffer has been written to the network.
|
119
|
+
* TRILOGY_AGAIN - Only part of the packet buffer was written to the network or
|
120
|
+
* the socket wasn't ready for writing. The caller should wait
|
121
|
+
* for writabilty using `conn->sock`. Then call this function
|
122
|
+
* until it returns a different value.
|
123
|
+
* TRILOGY_SYSERR - A system error occurred, check errno.
|
124
|
+
*/
|
125
|
+
int trilogy_flush_writes(trilogy_conn_t *conn);
|
126
|
+
|
127
|
+
/* trilogy_connect_send - Create a socket and attempt initial connection to the
|
128
|
+
* server.
|
129
|
+
*
|
130
|
+
* conn - A pre-initialized trilogy_conn_t pointer.
|
131
|
+
* addr - A pre-initialized trilogy_sockopt_t pointer with the connection
|
132
|
+
* parameters.
|
133
|
+
*
|
134
|
+
* Return values:
|
135
|
+
* TRILOGY_OK - The socket was created and the initial connection has been
|
136
|
+
* established.
|
137
|
+
* TRILOGY_SYSERR - A system error occurred, check errno.
|
138
|
+
*/
|
139
|
+
int trilogy_connect_send(trilogy_conn_t *conn, const trilogy_sockopt_t *opts);
|
140
|
+
|
141
|
+
/* trilogy_connect_send_socket - Attempt initial connection to the server using an
|
142
|
+
* existing trilogy_sock_t. The socket must _not_ have been connected yet.
|
143
|
+
*
|
144
|
+
* sock - An instance of trilogy_sock_t
|
145
|
+
*
|
146
|
+
* Return values:
|
147
|
+
* TRILOGY_OK - The socket was created and the initial connection has been
|
148
|
+
* established.
|
149
|
+
* TRILOGY_SYSERR - A system error occurred, check errno.
|
150
|
+
*/
|
151
|
+
int trilogy_connect_send_socket(trilogy_conn_t *conn, trilogy_sock_t *sock);
|
152
|
+
|
153
|
+
/* trilogy_connect_recv - Read the initial handshake from the server.
|
154
|
+
*
|
155
|
+
* This should be called after trilogy_connect_send returns TRILOGY_OK. Calling
|
156
|
+
* this at any other time during the connection lifecycle is undefined.
|
157
|
+
*
|
158
|
+
* conn - A connected trilogy_conn_t pointer. Using a disconnected
|
159
|
+
* trilogy_conn_t is undefined.
|
160
|
+
* handshake_out - A pre-allocated trilogy_handshake_t pointer. If TRILOGY_OK is
|
161
|
+
* returned, this struct will be filled out and ready to use.
|
162
|
+
*
|
163
|
+
* Return values:
|
164
|
+
* TRILOGY_OK - The initial handshake packet was read off the
|
165
|
+
* network.
|
166
|
+
* TRILOGY_AGAIN - The socket wasn't ready for reading. The caller
|
167
|
+
* should wait for readability using `conn->sock`.
|
168
|
+
* Then call this function again.
|
169
|
+
* TRILOGY_PROTOCOL_VIOLATION - An error occurred while processing a network
|
170
|
+
* packet.
|
171
|
+
* TRILOGY_CLOSED_CONNECTION - The connection is closed.
|
172
|
+
* TRILOGY_SYSERR - A system error occurred, check errno.
|
173
|
+
*/
|
174
|
+
int trilogy_connect_recv(trilogy_conn_t *conn, trilogy_handshake_t *handshake_out);
|
175
|
+
|
176
|
+
/* trilogy_ssl_request_send - Send an SSL handshake request to the server.
|
177
|
+
*
|
178
|
+
* This should be called after a successful connection to the server. Calling
|
179
|
+
* this at any other time during the connection lifecycle is undefined. It is an
|
180
|
+
* error to call this function if TRILOGY_CAPABILITIES_SSL was not set by the
|
181
|
+
* server.
|
182
|
+
*
|
183
|
+
* conn - A connected trilogy_conn_t pointer. Using a disconnected
|
184
|
+
* trilogy_conn_t is undefined.
|
185
|
+
*
|
186
|
+
* Return values:
|
187
|
+
* TRILOGY_OK - Authorization info was successfully sent to the server.
|
188
|
+
* TRILOGY_AGAIN - The socket wasn't ready for writing. The caller should wait
|
189
|
+
* for writeability using `conn->sock`. Then call
|
190
|
+
* trilogy_flush_writes.
|
191
|
+
* TRILOGY_SYSERR - A system error occurred, check errno.
|
192
|
+
*/
|
193
|
+
int trilogy_ssl_request_send(trilogy_conn_t *conn);
|
194
|
+
|
195
|
+
/* trilogy_auth_send - Send a authorization info to the server.
|
196
|
+
*
|
197
|
+
* This should be called after a successful connection to the server. Calling
|
198
|
+
* this at any other time during the connection lifecycle is undefined.
|
199
|
+
*
|
200
|
+
* conn - A connected trilogy_conn_t pointer. Using a disconnected
|
201
|
+
* trilogy_conn_t is undefined.
|
202
|
+
* handshake - A pre-initialized trilogy_handshake_t pointer.
|
203
|
+
*
|
204
|
+
* Return values:
|
205
|
+
* TRILOGY_OK - Authorization info was successfully sent to the server.
|
206
|
+
* TRILOGY_AGAIN - The socket wasn't ready for writing. The caller should wait
|
207
|
+
* for writeability using `conn->sock`. Then call
|
208
|
+
* trilogy_flush_writes.
|
209
|
+
* TRILOGY_SYSERR - A system error occurred, check errno.
|
210
|
+
*/
|
211
|
+
int trilogy_auth_send(trilogy_conn_t *conn, const trilogy_handshake_t *handshake);
|
212
|
+
|
213
|
+
/* trilogy_auth_recv - Read the authorization response from the server.
|
214
|
+
*
|
215
|
+
* This should be called after all data written by trilogy_auth_send is flushed to
|
216
|
+
* the network. Calling this at any other time during the connection lifecycle
|
217
|
+
* is undefined.
|
218
|
+
*
|
219
|
+
* conn - A connected trilogy_conn_t pointer. Using a disconnected trilogy_conn_t is
|
220
|
+
* undefined.
|
221
|
+
*
|
222
|
+
* Return values:
|
223
|
+
* TRILOGY_OK - Authorization completed successfully. The
|
224
|
+
* connection is ready for commands.
|
225
|
+
* TRILOGY_AUTH_SWITCH - The server requested an auth switch. Use
|
226
|
+
* `trilogy_auth_switch_send` to reply with the
|
227
|
+
* confirmation of the switch.
|
228
|
+
* TRILOGY_AGAIN - The socket wasn't ready for reading. The caller
|
229
|
+
* should wait for readability using `conn->sock`.
|
230
|
+
* Then call this function until it returns a
|
231
|
+
* different value.
|
232
|
+
* TRILOGY_UNEXPECTED_PACKET - The response packet wasn't what was expected.
|
233
|
+
* TRILOGY_PROTOCOL_VIOLATION - An error occurred while processing a network
|
234
|
+
* packet.
|
235
|
+
* TRILOGY_CLOSED_CONNECTION - The connection is closed.
|
236
|
+
* TRILOGY_SYSERR - A system error occurred, check errno.
|
237
|
+
*/
|
238
|
+
int trilogy_auth_recv(trilogy_conn_t *conn, trilogy_handshake_t *handshake);
|
239
|
+
|
240
|
+
/* trilogy_auth_switch_send - Send a reply after an authentication switch request.
|
241
|
+
*
|
242
|
+
* This should be called after the server requests and auth switch. Calling
|
243
|
+
* this at any other time during the connection lifecycle is undefined.
|
244
|
+
*
|
245
|
+
* conn - A connected trilogy_conn_t pointer. Using a disconnected trilogy_conn_t is undefined.
|
246
|
+
* handshake - A pre-initialized trilogy_handshake_t pointer.
|
247
|
+
*
|
248
|
+
* Return values:
|
249
|
+
* TRILOGY_OK - Authorization info was successfully sent to the server.
|
250
|
+
* TRILOGY_AGAIN - The socket wasn't ready for writing. The caller should wait
|
251
|
+
* for writeability using `conn->sock`. Then call
|
252
|
+
* trilogy_flush_writes.
|
253
|
+
* TRILOGY_SYSERR - A system error occurred, check errno.
|
254
|
+
*/
|
255
|
+
int trilogy_auth_switch_send(trilogy_conn_t *conn, const trilogy_handshake_t *handshake);
|
256
|
+
|
257
|
+
/* trilogy_change_db_send - Send a change database command to the server. This
|
258
|
+
* will change the default database for this connection.
|
259
|
+
*
|
260
|
+
* This should only be called while the connection is ready for commands.
|
261
|
+
*
|
262
|
+
* conn - A connected trilogy_conn_t pointer. Using a disconnected
|
263
|
+
* trilogy_conn_t is undefined.
|
264
|
+
* name - The name of the database.
|
265
|
+
* name_len - The length of the database name in bytes.
|
266
|
+
*
|
267
|
+
* Return values:
|
268
|
+
* TRILOGY_OK - The change database command was successfully sent to the
|
269
|
+
* server.
|
270
|
+
* TRILOGY_AGAIN - The socket wasn't ready for writing. The caller should wait
|
271
|
+
* for writeability using `conn->sock`. Then call
|
272
|
+
* trilogy_flush_writes.
|
273
|
+
* TRILOGY_SYSERR - A system error occurred, check errno.
|
274
|
+
*/
|
275
|
+
int trilogy_change_db_send(trilogy_conn_t *conn, const char *name, size_t name_len);
|
276
|
+
|
277
|
+
/* trilogy_change_db_recv - Read the change database command response from the
|
278
|
+
* server.
|
279
|
+
*
|
280
|
+
* This should be called after all data written by trilogy_change_db_send is
|
281
|
+
* flushed to the network. Calling this at any other time during the connection
|
282
|
+
* lifecycle is undefined.
|
283
|
+
*
|
284
|
+
* conn - A connected trilogy_conn_t pointer. Using a disconnected trilogy_conn_t is
|
285
|
+
* undefined.
|
286
|
+
*
|
287
|
+
* Return values:
|
288
|
+
* TRILOGY_OK - The change database command was successfully
|
289
|
+
* sent to the server.
|
290
|
+
* TRILOGY_AGAIN - The socket wasn't ready for reading. The
|
291
|
+
* caller should wait for readability using
|
292
|
+
* `conn->sock`. Then call this function until
|
293
|
+
* it returns a different value.
|
294
|
+
* TRILOGY_UNEXPECTED_PACKET - The response packet wasn't what was expected.
|
295
|
+
* TRILOGY_PROTOCOL_VIOLATION - An error occurred while processing a network
|
296
|
+
* packet.
|
297
|
+
* TRILOGY_CLOSED_CONNECTION - The connection is closed.
|
298
|
+
* TRILOGY_SYSERR - A system error occurred, check errno.
|
299
|
+
*/
|
300
|
+
int trilogy_change_db_recv(trilogy_conn_t *conn);
|
301
|
+
|
302
|
+
/* trilogy_query_send - Send a query command to the server.
|
303
|
+
*
|
304
|
+
* This should only be called while the connection is ready for commands.
|
305
|
+
*
|
306
|
+
* conn - A connected trilogy_conn_t pointer. Using a disconnected
|
307
|
+
* trilogy_conn_t is undefined.
|
308
|
+
* query - The query string.
|
309
|
+
* query_len - The length of query string in bytes.
|
310
|
+
*
|
311
|
+
* Return values:
|
312
|
+
* TRILOGY_OK - The query command was successfully sent to the server.
|
313
|
+
* TRILOGY_AGAIN - The socket wasn't ready for writing. The caller should
|
314
|
+
* wait for writeability using `conn->sock`. Then call
|
315
|
+
* trilogy_flush_writes.
|
316
|
+
* TRILOGY_SYSERR - A system error occurred, check errno.
|
317
|
+
*/
|
318
|
+
int trilogy_query_send(trilogy_conn_t *conn, const char *query, size_t query_len);
|
319
|
+
|
320
|
+
/* trilogy_query_recv - Read the query command response from the server.
|
321
|
+
*
|
322
|
+
* This should be called after all data written by trilogy_query_send is flushed
|
323
|
+
* to the network. Calling this at any other time during the connection
|
324
|
+
* lifecycle is undefined.
|
325
|
+
*
|
326
|
+
* conn - A connected trilogy_conn_t pointer. Using a disconnected
|
327
|
+
* trilogy_conn_t is undefined.
|
328
|
+
* column_count_out - Out parameter; If TRILOGY_HAVE_RESULTS is returned, this
|
329
|
+
* will be set to the number of columns in the result set.
|
330
|
+
*
|
331
|
+
* Return values:
|
332
|
+
* TRILOGY_OK - The query response was received and fully read.
|
333
|
+
* TRILOGY_HAVE_RESULTS - The query response was received and there are
|
334
|
+
* results to be read.
|
335
|
+
* TRILOGY_AGAIN - The socket wasn't ready for reading. The caller
|
336
|
+
* should wait for readability using `conn->sock`.
|
337
|
+
* Then call this function until it returns a
|
338
|
+
* different value.
|
339
|
+
* TRILOGY_UNEXPECTED_PACKET - The response packet wasn't what was expected.
|
340
|
+
* TRILOGY_PROTOCOL_VIOLATION - An error occurred while processing a network
|
341
|
+
* packet.
|
342
|
+
* TRILOGY_CLOSED_CONNECTION - The connection is closed.
|
343
|
+
* TRILOGY_SYSERR - A system error occurred, check errno.
|
344
|
+
*/
|
345
|
+
int trilogy_query_recv(trilogy_conn_t *conn, uint64_t *column_count_out);
|
346
|
+
|
347
|
+
/* trilogy_read_column - Read a column from the result set.
|
348
|
+
*
|
349
|
+
* This should be called as many times as there are columns in the result set.
|
350
|
+
* Calling this more times than that is undefined. This should also only be
|
351
|
+
* called after a query command has completed and returned TRILOGY_HAVE_RESULTS.
|
352
|
+
* Calling this at any other time during the connection lifecycle is undefined.
|
353
|
+
*
|
354
|
+
* conn - A connected trilogy_conn_t pointer. Using a disconnected
|
355
|
+
* trilogy_conn_t is undefined.
|
356
|
+
* column_out - Out parameter; A pointer to a pre-allocated trilogy_column_t. If
|
357
|
+
* TRILOGY_OK is returned this will be filled out. This value will be
|
358
|
+
* invalid after any other call to this API. The caller should make
|
359
|
+
* a copy if they want to keep the value around.
|
360
|
+
*
|
361
|
+
* Return values:
|
362
|
+
* TRILOGY_OK - The column was successfully read.
|
363
|
+
* TRILOGY_AGAIN - The socket wasn't ready for reading. The caller
|
364
|
+
* should wait for readability using `conn->sock`.
|
365
|
+
* Then call this function until it returns a
|
366
|
+
* different value.
|
367
|
+
* TRILOGY_UNEXPECTED_PACKET - The response packet wasn't what was expected.
|
368
|
+
* TRILOGY_PROTOCOL_VIOLATION - An error occurred while processing a network
|
369
|
+
* packet.
|
370
|
+
* TRILOGY_CLOSED_CONNECTION - The connection is closed.
|
371
|
+
* TRILOGY_SYSERR - A system error occurred, check errno.
|
372
|
+
*/
|
373
|
+
int trilogy_read_column(trilogy_conn_t *conn, trilogy_column_t *column_out);
|
374
|
+
|
375
|
+
/* trilogy_read_row - Read a column from the result set.
|
376
|
+
*
|
377
|
+
* This should be called after reading all columns from the network. Calling
|
378
|
+
* this at any other time during the connection lifecycle is undefined.
|
379
|
+
*
|
380
|
+
* conn - A connected trilogy_conn_t pointer. Using a disconnected
|
381
|
+
* trilogy_conn_t is undefined.
|
382
|
+
* values_out - Out parameter; A pre-allocated trilogy_value_t pointer, which will
|
383
|
+
* be filled out by this function. It should be allocated with
|
384
|
+
* enough space to hold a trilogy_value_t pointer for each column.
|
385
|
+
* Something like: `(sizeof(trilogy_value_t) * column_count)`. This
|
386
|
+
* pointer is invalid after any other call to this API. The caller
|
387
|
+
* should make a copy of the values inside if they want to keep
|
388
|
+
* them around.
|
389
|
+
*
|
390
|
+
* Return values:
|
391
|
+
* TRILOGY_OK - The query response was received and fully read.
|
392
|
+
* TRILOGY_EOF - There are no more rows to be read.
|
393
|
+
* TRILOGY_AGAIN - The socket wasn't ready for reading. The caller
|
394
|
+
* should wait for readability using `conn->sock`.
|
395
|
+
* Then call this function until it returns a
|
396
|
+
* different value.
|
397
|
+
* TRILOGY_UNEXPECTED_PACKET - The response packet wasn't what was expected.
|
398
|
+
* TRILOGY_PROTOCOL_VIOLATION - An error occurred while processing a network
|
399
|
+
* packet.
|
400
|
+
* TRILOGY_CLOSED_CONNECTION - The connection is closed.
|
401
|
+
* TRILOGY_SYSERR - A system error occurred, check errno.
|
402
|
+
*/
|
403
|
+
int trilogy_read_row(trilogy_conn_t *conn, trilogy_value_t *values_out);
|
404
|
+
|
405
|
+
/* trilogy_drain_results - A convenience function to read and throw away the
|
406
|
+
* remaining rows from a result set. Any MySQL-compatible protocol requires that all
|
407
|
+
* responses from a command are read off the network before any other commands
|
408
|
+
* can be issued. A caller could otherwise do the same thing this function does
|
409
|
+
* by calling trilogy_read_row until it returns TRILOGY_EOF. But this call does that
|
410
|
+
* in a much more efficient manner by only reading packet frames then throwing
|
411
|
+
* them away, skipping the parsing of value information from inside each packet.
|
412
|
+
*
|
413
|
+
* conn - A connected trilogy_conn_t pointer. Using a disconnected trilogy_conn_t is
|
414
|
+
* undefined.
|
415
|
+
*
|
416
|
+
* Return values:
|
417
|
+
* TRILOGY_OK - The rest of the result was drained and the
|
418
|
+
* connection is ready for another command.
|
419
|
+
* TRILOGY_AGAIN - The socket wasn't ready for reading. The caller
|
420
|
+
* should wait for readability using `conn->sock`.
|
421
|
+
* Then call this function until it returns a
|
422
|
+
* different value.
|
423
|
+
* TRILOGY_UNEXPECTED_PACKET - The response packet wasn't what was expected.
|
424
|
+
* TRILOGY_PROTOCOL_VIOLATION - An error occurred while processing a network
|
425
|
+
* packet.
|
426
|
+
* TRILOGY_CLOSED_CONNECTION - The connection is closed.
|
427
|
+
* TRILOGY_SYSERR - A system error occurred, check errno.
|
428
|
+
*/
|
429
|
+
int trilogy_drain_results(trilogy_conn_t *conn);
|
430
|
+
|
431
|
+
/* trilogy_ping_send - Send a ping command to the server.
|
432
|
+
*
|
433
|
+
* This should only be called while the connection is ready for commands.
|
434
|
+
*
|
435
|
+
* conn - A connected trilogy_conn_t pointer. Using a disconnected trilogy_conn_t
|
436
|
+
* is undefined.
|
437
|
+
*
|
438
|
+
* Return values:
|
439
|
+
* TRILOGY_OK - The ping command was successfully sent to the server.
|
440
|
+
* TRILOGY_AGAIN - The socket wasn't ready for writing. The caller should wait
|
441
|
+
* for writeability using `conn->sock`. Then call
|
442
|
+
* trilogy_flush_writes.
|
443
|
+
* TRILOGY_SYSERR - A system error occurred, check errno.
|
444
|
+
*/
|
445
|
+
int trilogy_ping_send(trilogy_conn_t *conn);
|
446
|
+
|
447
|
+
/* trilogy_ping_recv - Read the ping command response from the server.
|
448
|
+
*
|
449
|
+
* This should be called after all data written by trilogy_ping_send is flushed to
|
450
|
+
* the network. Calling this at any other time during the connection lifecycle
|
451
|
+
* is undefined.
|
452
|
+
*
|
453
|
+
* conn - A connected trilogy_conn_t pointer. Using a disconnected trilogy_conn_t is
|
454
|
+
* undefined.
|
455
|
+
*
|
456
|
+
* Return values:
|
457
|
+
* TRILOGY_OK - The ping command was successfully sent to the
|
458
|
+
* server.
|
459
|
+
* TRILOGY_AGAIN - The socket wasn't ready for reading. The caller
|
460
|
+
* should wait for readability using `conn->sock`.
|
461
|
+
* Then call this function until it returns a
|
462
|
+
* different value.
|
463
|
+
* TRILOGY_UNEXPECTED_PACKET - The response packet wasn't what was expected.
|
464
|
+
* TRILOGY_PROTOCOL_VIOLATION - An error occurred while processing a network
|
465
|
+
* packet.
|
466
|
+
* TRILOGY_CLOSED_CONNECTION - The connection is closed.
|
467
|
+
* TRILOGY_SYSERR - A system error occurred, check errno.
|
468
|
+
*/
|
469
|
+
int trilogy_ping_recv(trilogy_conn_t *conn);
|
470
|
+
|
471
|
+
/* trilogy_escape - Escape a string, making it safe to use in a query.
|
472
|
+
*
|
473
|
+
* This function assumes the input is in an ASCII-compatible encoding. Passing
|
474
|
+
* in a string in any other encoding is undefined and will likely corrupt the
|
475
|
+
* input. Potentially leaving the caller open to SQL-injection style attacks.
|
476
|
+
*
|
477
|
+
* If the TRILOGY_SERVER_STATUS_NO_BACKSLASH_ESCAPES flag is set, it will disable
|
478
|
+
* the use of the backslash character ("\") as an escape character. Making
|
479
|
+
* backslash an ordinary character like any other.
|
480
|
+
*
|
481
|
+
* That mode can be enabled at runtime by issuing setting the
|
482
|
+
* NO_BACKSLASH_ESCAPES sql mode. This can be done with a query like:
|
483
|
+
* "SET SQL_MODE=NO_BACKSLASH_ESCAPES"
|
484
|
+
*
|
485
|
+
* conn - A pre-initialized trilogy_conn_t pointer.
|
486
|
+
* str - The string to be escaped.
|
487
|
+
* len - The length of `str` in bytes.
|
488
|
+
* escaped_str_out - Out parameter; The dereferenced value of this pointer will
|
489
|
+
* point to the escaped version of `str` if TRILOGY_OK was
|
490
|
+
* returned.
|
491
|
+
* escaped_len_out - Out parameter; The length of the buffer `escaped_str_out`
|
492
|
+
* points to if TRILOGY_OK was returned.
|
493
|
+
*
|
494
|
+
* Return values:
|
495
|
+
* TRILOGY_OK - The input string has been processed.
|
496
|
+
* TRILOGY_SYSERR - A system error occurred, check errno.
|
497
|
+
*/
|
498
|
+
int trilogy_escape(trilogy_conn_t *conn, const char *str, size_t len, const char **escaped_str_out,
|
499
|
+
size_t *escaped_len_out);
|
500
|
+
|
501
|
+
/* trilogy_close_send - Send a quit command to the server.
|
502
|
+
*
|
503
|
+
* conn - A connected trilogy_conn_t pointer. Using a disconnected trilogy_conn_t is
|
504
|
+
* undefined.
|
505
|
+
*
|
506
|
+
* Return values:
|
507
|
+
* TRILOGY_OK - The quit command was successfully sent to the server.
|
508
|
+
* TRILOGY_AGAIN - The socket wasn't ready for writing. The caller should wait
|
509
|
+
* for writeability using `conn->sock`. Then call
|
510
|
+
* trilogy_flush_writes.
|
511
|
+
* TRILOGY_SYSERR - A system error occurred, check errno.
|
512
|
+
*/
|
513
|
+
int trilogy_close_send(trilogy_conn_t *conn);
|
514
|
+
|
515
|
+
/* trilogy_close_recv - Read the quit command response from the MySQL-compatible server.
|
516
|
+
*
|
517
|
+
* This should be called after all data written by trilogy_close_send is flushed
|
518
|
+
* to the network. Calling this at any other time during the connection
|
519
|
+
* lifecycle is undefined.
|
520
|
+
*
|
521
|
+
* conn - A pre-initialized trilogy_conn_t pointer. It can also be connected but
|
522
|
+
* a disconnected trilogy_conn_t will also return TRILOGY_OK.
|
523
|
+
*
|
524
|
+
* Return values:
|
525
|
+
* TRILOGY_OK - The quit command response successfully read from
|
526
|
+
* the server.
|
527
|
+
* TRILOGY_AGAIN - The socket wasn't ready for reading. The caller
|
528
|
+
* should wait for readability using `conn->sock`.
|
529
|
+
* Then call this function until it returns a
|
530
|
+
* different value.
|
531
|
+
* TRILOGY_UNEXPECTED_PACKET - The response packet wasn't what was expected.
|
532
|
+
* TRILOGY_PROTOCOL_VIOLATION - An error occurred while processing a network
|
533
|
+
* packet.
|
534
|
+
* TRILOGY_SYSERR - A system error occurred, check errno.
|
535
|
+
*/
|
536
|
+
int trilogy_close_recv(trilogy_conn_t *conn);
|
537
|
+
|
538
|
+
/* trilogy_free - Close the connection and free any internal buffers.
|
539
|
+
*
|
540
|
+
* conn - A pre-initialized trilogy_conn_t pointer.
|
541
|
+
*
|
542
|
+
* Returns nothing.
|
543
|
+
*/
|
544
|
+
void trilogy_free(trilogy_conn_t *conn);
|
545
|
+
|
546
|
+
#endif
|
@@ -0,0 +1,43 @@
|
|
1
|
+
#ifndef TRILOGY_ERROR_H
|
2
|
+
#define TRILOGY_ERROR_H
|
3
|
+
|
4
|
+
#define TRILOGY_ERROR_CODES(XX) \
|
5
|
+
XX(TRILOGY_OK, 0) \
|
6
|
+
XX(TRILOGY_ERR, -1) \
|
7
|
+
XX(TRILOGY_EOF, -2) \
|
8
|
+
XX(TRILOGY_SYSERR, -3) /* check errno */ \
|
9
|
+
XX(TRILOGY_UNEXPECTED_PACKET, -4) \
|
10
|
+
XX(TRILOGY_TRUNCATED_PACKET, -5) \
|
11
|
+
XX(TRILOGY_PROTOCOL_VIOLATION, -6) \
|
12
|
+
XX(TRILOGY_AUTH_PLUGIN_TOO_LONG, -7) \
|
13
|
+
XX(TRILOGY_EXTRA_DATA_IN_PACKET, -8) \
|
14
|
+
XX(TRILOGY_INVALID_CHARSET, -9) \
|
15
|
+
XX(TRILOGY_AGAIN, -10) \
|
16
|
+
XX(TRILOGY_CLOSED_CONNECTION, -11) \
|
17
|
+
XX(TRILOGY_HAVE_RESULTS, -12) \
|
18
|
+
XX(TRILOGY_NULL_VALUE, -13) \
|
19
|
+
XX(TRILOGY_INVALID_SEQUENCE_ID, -14) \
|
20
|
+
XX(TRILOGY_TYPE_OVERFLOW, -15) \
|
21
|
+
XX(TRILOGY_OPENSSL_ERR, -16) /* check ERR_get_error() */ \
|
22
|
+
XX(TRILOGY_UNSUPPORTED, -17) \
|
23
|
+
XX(TRILOGY_DNS_ERR, -18) \
|
24
|
+
XX(TRILOGY_AUTH_SWITCH, -19)
|
25
|
+
|
26
|
+
enum {
|
27
|
+
#define XX(name, code) name = code,
|
28
|
+
TRILOGY_ERROR_CODES(XX)
|
29
|
+
#undef XX
|
30
|
+
};
|
31
|
+
|
32
|
+
/* trilogy_error - Get the string version of an Trilogy error code.
|
33
|
+
*
|
34
|
+
* This can be useful for logging or debugging as printing the error value
|
35
|
+
* integer itself doesn't provide much context.
|
36
|
+
*
|
37
|
+
* error - An Trilogy error code integer.
|
38
|
+
*
|
39
|
+
* Returns an error name constant from TRILOGY_ERROR_CODES as a C-string.
|
40
|
+
*/
|
41
|
+
const char *trilogy_error(int error);
|
42
|
+
|
43
|
+
#endif
|
@@ -0,0 +1,34 @@
|
|
1
|
+
#ifndef TRILOGY_PACKET_PARSER_H
|
2
|
+
#define TRILOGY_PACKET_PARSER_H
|
3
|
+
|
4
|
+
#include <stddef.h>
|
5
|
+
#include <stdint.h>
|
6
|
+
|
7
|
+
// Data between client and server is exchanged in packets of max 16MByte size.
|
8
|
+
#define TRILOGY_MAX_PACKET_LEN 0xffffff
|
9
|
+
|
10
|
+
typedef struct {
|
11
|
+
int (*on_packet_begin)(void *);
|
12
|
+
int (*on_packet_data)(void *, const uint8_t *, size_t);
|
13
|
+
int (*on_packet_end)(void *);
|
14
|
+
} trilogy_packet_parser_callbacks_t;
|
15
|
+
|
16
|
+
typedef struct {
|
17
|
+
void *user_data;
|
18
|
+
const trilogy_packet_parser_callbacks_t *callbacks;
|
19
|
+
|
20
|
+
uint8_t sequence_number;
|
21
|
+
|
22
|
+
// private:
|
23
|
+
unsigned bytes_remaining : 24;
|
24
|
+
|
25
|
+
unsigned state : 3;
|
26
|
+
unsigned fragment : 1;
|
27
|
+
unsigned deferred_end_callback : 1;
|
28
|
+
} trilogy_packet_parser_t;
|
29
|
+
|
30
|
+
void trilogy_packet_parser_init(trilogy_packet_parser_t *parser, const trilogy_packet_parser_callbacks_t *callbacks);
|
31
|
+
|
32
|
+
size_t trilogy_packet_parser_execute(trilogy_packet_parser_t *parser, const uint8_t *buf, size_t len, int *error);
|
33
|
+
|
34
|
+
#endif
|