2
* Drizzle Client & Protocol Library
4
* Copyright (C) 2008 Eric Day (eday@oddments.org)
7
* Redistribution and use in source and binary forms, with or without
8
* modification, are permitted provided that the following conditions are
11
* * Redistributions of source code must retain the above copyright
12
* notice, this list of conditions and the following disclaimer.
14
* * Redistributions in binary form must reproduce the above
15
* copyright notice, this list of conditions and the following disclaimer
16
* in the documentation and/or other materials provided with the
19
* * The names of its contributors may not be used to endorse or
20
* promote products derived from this software without specific prior
23
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
24
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
25
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
26
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
27
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
28
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
29
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
30
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
31
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
33
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
43
#include <libdrizzle/drizzle_client.h>
44
#include <libdrizzle/drizzle_server.h>
46
#define DRIZZLE_RETURN_CHECK(__ret, __function, __drizzle) \
48
if ((__ret) != DRIZZLE_RETURN_OK) \
49
DRIZZLE_RETURN_ERROR(__function, __drizzle) \
52
#define DRIZZLE_RETURN_ERROR(__function, __drizzle) \
54
printf(__function ":%s\n", drizzle_error(__drizzle)); \
58
static void proxy(drizzle_st *drizzle, drizzle_con_st *server,
59
drizzle_con_st *client, drizzle_result_st *server_result,
60
drizzle_result_st *client_result, drizzle_column_st *column);
62
int main(int argc, char *argv[])
66
const char *server_host= NULL;
67
const char *client_host= NULL;
68
bool server_mysql= false;
69
bool client_mysql= false;
70
in_port_t server_port= 0;
71
in_port_t client_port= 0;
72
drizzle_verbose_t verbose= DRIZZLE_VERBOSE_NEVER;
75
drizzle_con_st *con_listen= (drizzle_con_st*)malloc(sizeof(drizzle_con_st));
76
drizzle_con_st *server= (drizzle_con_st*)malloc(sizeof(drizzle_con_st));
77
drizzle_con_st *client= (drizzle_con_st*)malloc(sizeof(drizzle_con_st));
78
drizzle_result_st server_result;
79
drizzle_result_st client_result;
80
drizzle_column_st column;
82
while((c = getopt(argc, argv, "c:h:H:mMp:P:v")) != -1)
87
count= (uint32_t)atoi(optarg);
107
server_port= (in_port_t)atoi(optarg);
111
client_port= (in_port_t)atoi(optarg);
117
case DRIZZLE_VERBOSE_NEVER:
118
verbose= DRIZZLE_VERBOSE_FATAL;
120
case DRIZZLE_VERBOSE_FATAL:
121
verbose= DRIZZLE_VERBOSE_ERROR;
123
case DRIZZLE_VERBOSE_ERROR:
124
verbose= DRIZZLE_VERBOSE_INFO;
126
case DRIZZLE_VERBOSE_INFO:
127
verbose= DRIZZLE_VERBOSE_DEBUG;
129
case DRIZZLE_VERBOSE_DEBUG:
130
verbose= DRIZZLE_VERBOSE_CRAZY;
132
case DRIZZLE_VERBOSE_CRAZY:
133
case DRIZZLE_VERBOSE_MAX:
139
printf("\nusage: %s [-c <count>] [-h <host>] [-H <host>] [-m] [-M] "
140
"[-p <port>] [-p <port>] [-v]\n", argv[0]);
141
printf("\t-c <count> - Number of connections to accept before exiting\n");
142
printf("\t-h <host> - Host to listen on\n");
143
printf("\t-H <host> - Host to connect to\n");
144
printf("\t-m - Use MySQL protocol for incoming connections\n");
145
printf("\t-M - Use MySQL protocol for outgoing connectionsn\n");
146
printf("\t-p <port> - Port to listen on\n");
147
printf("\t-P <port> - Port to connect to\n");
148
printf("\t-v - Increase verbosity level\n");
153
if (drizzle_create(&drizzle) == NULL)
155
printf("drizzle_create:NULL\n");
159
drizzle_add_options(&drizzle, DRIZZLE_FREE_OBJECTS);
160
drizzle_set_verbose(&drizzle, verbose);
162
if (drizzle_con_create(&drizzle, con_listen) == NULL)
164
printf("drizzle_con_create:NULL\n");
168
drizzle_con_add_options(con_listen, DRIZZLE_CON_LISTEN);
169
drizzle_con_set_tcp(con_listen, server_host, server_port);
172
drizzle_con_add_options(con_listen, DRIZZLE_CON_MYSQL);
174
if (drizzle_con_listen(con_listen) != DRIZZLE_RETURN_OK)
176
printf("drizzle_con_listen:%s\n", drizzle_error(&drizzle));
182
(void)drizzle_con_accept(&drizzle, server, &ret);
183
if (ret != DRIZZLE_RETURN_OK)
185
printf("drizzle_con_accept:%s\n", drizzle_error(&drizzle));
189
if (drizzle_con_create(&drizzle, client) == NULL)
191
printf("drizzle_con_create:NULL\n");
195
drizzle_con_add_options(client,
196
DRIZZLE_CON_RAW_PACKET | DRIZZLE_CON_RAW_SCRAMBLE);
198
drizzle_con_add_options(client, DRIZZLE_CON_MYSQL);
199
drizzle_con_set_tcp(client, client_host, client_port);
201
ret= drizzle_con_connect(client);
202
if (ret != DRIZZLE_RETURN_OK)
204
printf("drizzle_con_connect:%s\n", drizzle_error(&drizzle));
208
proxy(&drizzle, server, client, &server_result, &client_result, &column);
210
drizzle_con_free(client);
211
drizzle_con_free(server);
222
drizzle_con_free(con_listen);
223
drizzle_free(&drizzle);
232
static void proxy(drizzle_st *drizzle, drizzle_con_st *server,
233
drizzle_con_st *client, drizzle_result_st *server_result,
234
drizzle_result_st *client_result, drizzle_column_st *column)
236
drizzle_return_t ret;
237
drizzle_command_t command;
244
drizzle_field_t field;
246
/* Handshake packets. */
247
ret= drizzle_handshake_server_read(client);
248
DRIZZLE_RETURN_CHECK(ret, "drizzle_handshake_server_read", drizzle)
250
drizzle_con_copy_handshake(server, client);
252
ret= drizzle_handshake_server_write(server);
253
DRIZZLE_RETURN_CHECK(ret, "drizzle_handshake_server_write", drizzle)
255
ret= drizzle_handshake_client_read(server);
256
DRIZZLE_RETURN_CHECK(ret, "drizzle_handshake_client_read", drizzle)
258
drizzle_con_copy_handshake(client, server);
260
ret= drizzle_handshake_client_write(client);
261
DRIZZLE_RETURN_CHECK(ret, "drizzle_handshake_client_write", drizzle)
263
(void)drizzle_result_read(client, client_result, &ret);
264
DRIZZLE_RETURN_CHECK(ret, "drizzle_result_read", drizzle)
266
drizzle_con_set_status(server, drizzle_con_status(client));
268
if (drizzle_result_clone(server, server_result, client_result) == NULL)
269
DRIZZLE_RETURN_ERROR("drizzle_result_clone", drizzle)
271
ret= drizzle_result_write(server, server_result, true);
272
DRIZZLE_RETURN_CHECK(ret, "drizzle_result_write", drizzle)
274
if (drizzle_result_error_code(client_result) != 0 ||
275
drizzle_result_eof(client_result))
277
/* There was a handshake or authentication error. */
281
drizzle_con_add_options(client, DRIZZLE_CON_READY);
286
drizzle_result_free(server_result);
287
drizzle_result_free(client_result);
291
data= (uint8_t *)drizzle_con_command_read(server, &command, &offset, &size, &total,
293
if (ret == DRIZZLE_RETURN_LOST_CONNECTION)
296
DRIZZLE_RETURN_CHECK(ret, "drizzle_con_command_read", drizzle)
298
(void)drizzle_con_command_write(client, NULL, command, data, size, total,
300
DRIZZLE_RETURN_CHECK(ret, "drizzle_con_command_write", drizzle)
302
if ((offset + size) == total)
306
if (command == DRIZZLE_COMMAND_QUIT)
308
else if (command == DRIZZLE_COMMAND_FIELD_LIST)
310
if (drizzle_result_create(client, client_result) == NULL)
311
DRIZZLE_RETURN_ERROR("drizzle_result_create", drizzle)
313
if (drizzle_result_create(server, server_result) == NULL)
314
DRIZZLE_RETURN_ERROR("drizzle_result_create", drizzle)
318
(void)drizzle_result_read(client, client_result, &ret);
319
DRIZZLE_RETURN_CHECK(ret, "drizzle_result_read", drizzle)
321
drizzle_con_set_status(server, drizzle_con_status(client));
322
if (drizzle_result_clone(server, server_result, client_result) == NULL)
323
DRIZZLE_RETURN_ERROR("drizzle_result_clone", drizzle)
325
if (drizzle_result_column_count(client_result) == 0)
327
/* Simple result with no column, row, or field data. */
328
ret= drizzle_result_write(server, server_result, true);
329
DRIZZLE_RETURN_CHECK(ret, "drizzle_result_write", drizzle)
334
ret= drizzle_result_write(server, server_result, false);
335
DRIZZLE_RETURN_CHECK(ret, "drizzle_result_write", drizzle)
341
if (drizzle_column_read(client_result, column, &ret) == NULL)
343
DRIZZLE_RETURN_CHECK(ret, "drizzle_column_read", drizzle)
347
DRIZZLE_RETURN_CHECK(ret, "drizzle_column_read", drizzle)
349
ret= drizzle_column_write(server_result, column);
350
DRIZZLE_RETURN_CHECK(ret, "drizzle_column_write", drizzle)
352
drizzle_column_free(column);
355
drizzle_con_set_status(server, drizzle_con_status(client));
356
drizzle_result_set_eof(server_result, true);
358
if (command == DRIZZLE_COMMAND_FIELD_LIST)
360
ret= drizzle_result_write(server, server_result, true);
361
DRIZZLE_RETURN_CHECK(ret, "drizzle_result_write", drizzle)
366
ret= drizzle_result_write(server, server_result, false);
367
DRIZZLE_RETURN_CHECK(ret, "drizzle_result_write", drizzle)
373
row= drizzle_row_read(client_result, &ret);
374
DRIZZLE_RETURN_CHECK(ret, "drizzle_row_read", drizzle)
379
drizzle_result_set_row_size(server_result,
380
drizzle_result_row_size(client_result));
382
ret= drizzle_row_write(server_result);
383
DRIZZLE_RETURN_CHECK(ret, "drizzle_row_write", drizzle)
387
while (row_break == false)
389
field= drizzle_field_read(client_result, &offset, &size, &total, &ret);
390
if (ret == DRIZZLE_RETURN_ROW_END)
392
else if (ret == DRIZZLE_RETURN_ROW_BREAK)
400
DRIZZLE_RETURN_CHECK(ret, "drizzle_field_read", drizzle)
402
ret= drizzle_field_write(server_result, field, size, total);
403
DRIZZLE_RETURN_CHECK(ret, "drizzle_field_write", drizzle)
407
ret= drizzle_result_write(server, server_result, true);
408
DRIZZLE_RETURN_CHECK(ret, "drizzle_result_write", drizzle)