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.
45
#include <libdrizzle/drizzle_client.h>
46
#include <libdrizzle/drizzle_server.h>
48
#define DRIZZLE_RETURN_CHECK(__ret, __function, __drizzle) \
50
if ((__ret) != DRIZZLE_RETURN_OK) \
51
DRIZZLE_RETURN_ERROR(__function, __drizzle) \
54
#define DRIZZLE_RETURN_ERROR(__function, __drizzle) \
56
printf(__function ":%s\n", drizzle_error(__drizzle)); \
60
static void proxy(drizzle_st *drizzle, drizzle_con_st *server,
61
drizzle_con_st *client, drizzle_result_st *server_result,
62
drizzle_result_st *client_result, drizzle_column_st *column);
64
int main(int argc, char *argv[])
68
const char *server_host= NULL;
69
const char *client_host= NULL;
70
bool server_mysql= false;
71
bool client_mysql= false;
72
in_port_t server_port= 0;
73
in_port_t client_port= 0;
74
drizzle_verbose_t verbose= DRIZZLE_VERBOSE_NEVER;
77
drizzle_con_st *con_listen= (drizzle_con_st*)malloc(sizeof(drizzle_con_st));
78
drizzle_con_st *server= (drizzle_con_st*)malloc(sizeof(drizzle_con_st));
79
drizzle_con_st *client= (drizzle_con_st*)malloc(sizeof(drizzle_con_st));
80
drizzle_result_st server_result;
81
drizzle_result_st client_result;
82
drizzle_column_st column;
84
while((c = getopt(argc, argv, "c:h:H:mMp:P:v")) != -1)
89
count= (uint32_t)atoi(optarg);
109
server_port= (in_port_t)atoi(optarg);
113
client_port= (in_port_t)atoi(optarg);
119
case DRIZZLE_VERBOSE_NEVER:
120
verbose= DRIZZLE_VERBOSE_FATAL;
122
case DRIZZLE_VERBOSE_FATAL:
123
verbose= DRIZZLE_VERBOSE_ERROR;
125
case DRIZZLE_VERBOSE_ERROR:
126
verbose= DRIZZLE_VERBOSE_INFO;
128
case DRIZZLE_VERBOSE_INFO:
129
verbose= DRIZZLE_VERBOSE_DEBUG;
131
case DRIZZLE_VERBOSE_DEBUG:
132
verbose= DRIZZLE_VERBOSE_CRAZY;
134
case DRIZZLE_VERBOSE_CRAZY:
135
case DRIZZLE_VERBOSE_MAX:
141
printf("\nusage: %s [-c <count>] [-h <host>] [-H <host>] [-m] [-M] "
142
"[-p <port>] [-p <port>] [-v]\n", argv[0]);
143
printf("\t-c <count> - Number of connections to accept before exiting\n");
144
printf("\t-h <host> - Host to listen on\n");
145
printf("\t-H <host> - Host to connect to\n");
146
printf("\t-m - Use MySQL protocol for incoming connections\n");
147
printf("\t-M - Use MySQL protocol for outgoing connectionsn\n");
148
printf("\t-p <port> - Port to listen on\n");
149
printf("\t-P <port> - Port to connect to\n");
150
printf("\t-v - Increase verbosity level\n");
155
if (drizzle_create(&drizzle) == NULL)
157
printf("drizzle_create:NULL\n");
161
drizzle_add_options(&drizzle, DRIZZLE_FREE_OBJECTS);
162
drizzle_set_verbose(&drizzle, verbose);
164
if (drizzle_con_create(&drizzle, con_listen) == NULL)
166
printf("drizzle_con_create:NULL\n");
170
drizzle_con_add_options(con_listen, DRIZZLE_CON_LISTEN);
171
drizzle_con_set_tcp(con_listen, server_host, server_port);
174
drizzle_con_add_options(con_listen, DRIZZLE_CON_MYSQL);
176
if (drizzle_con_listen(con_listen) != DRIZZLE_RETURN_OK)
178
printf("drizzle_con_listen:%s\n", drizzle_error(&drizzle));
184
(void)drizzle_con_accept(&drizzle, server, &ret);
185
if (ret != DRIZZLE_RETURN_OK)
187
printf("drizzle_con_accept:%s\n", drizzle_error(&drizzle));
191
if (drizzle_con_create(&drizzle, client) == NULL)
193
printf("drizzle_con_create:NULL\n");
197
drizzle_con_add_options(client,
198
DRIZZLE_CON_RAW_PACKET | DRIZZLE_CON_RAW_SCRAMBLE);
200
drizzle_con_add_options(client, DRIZZLE_CON_MYSQL);
201
drizzle_con_set_tcp(client, client_host, client_port);
203
ret= drizzle_con_connect(client);
204
if (ret != DRIZZLE_RETURN_OK)
206
printf("drizzle_con_connect:%s\n", drizzle_error(&drizzle));
210
proxy(&drizzle, server, client, &server_result, &client_result, &column);
212
drizzle_con_free(client);
213
drizzle_con_free(server);
224
drizzle_con_free(con_listen);
225
drizzle_free(&drizzle);
234
static void proxy(drizzle_st *drizzle, drizzle_con_st *server,
235
drizzle_con_st *client, drizzle_result_st *server_result,
236
drizzle_result_st *client_result, drizzle_column_st *column)
238
drizzle_return_t ret;
239
drizzle_command_t command;
246
drizzle_field_t field;
248
/* Handshake packets. */
249
ret= drizzle_handshake_server_read(client);
250
DRIZZLE_RETURN_CHECK(ret, "drizzle_handshake_server_read", drizzle)
252
drizzle_con_copy_handshake(server, client);
254
ret= drizzle_handshake_server_write(server);
255
DRIZZLE_RETURN_CHECK(ret, "drizzle_handshake_server_write", drizzle)
257
ret= drizzle_handshake_client_read(server);
258
DRIZZLE_RETURN_CHECK(ret, "drizzle_handshake_client_read", drizzle)
260
drizzle_con_copy_handshake(client, server);
262
ret= drizzle_handshake_client_write(client);
263
DRIZZLE_RETURN_CHECK(ret, "drizzle_handshake_client_write", drizzle)
265
(void)drizzle_result_read(client, client_result, &ret);
266
DRIZZLE_RETURN_CHECK(ret, "drizzle_result_read", drizzle)
268
drizzle_con_set_status(server, drizzle_con_status(client));
270
if (drizzle_result_clone(server, server_result, client_result) == NULL)
271
DRIZZLE_RETURN_ERROR("drizzle_result_clone", drizzle)
273
ret= drizzle_result_write(server, server_result, true);
274
DRIZZLE_RETURN_CHECK(ret, "drizzle_result_write", drizzle)
276
if (drizzle_result_error_code(client_result) != 0 ||
277
drizzle_result_eof(client_result))
279
/* There was a handshake or authentication error. */
283
drizzle_con_add_options(client, DRIZZLE_CON_READY);
288
drizzle_result_free(server_result);
289
drizzle_result_free(client_result);
293
data= (uint8_t *)drizzle_con_command_read(server, &command, &offset, &size, &total,
295
if (ret == DRIZZLE_RETURN_LOST_CONNECTION)
298
DRIZZLE_RETURN_CHECK(ret, "drizzle_con_command_read", drizzle)
300
(void)drizzle_con_command_write(client, NULL, command, data, size, total,
302
DRIZZLE_RETURN_CHECK(ret, "drizzle_con_command_write", drizzle)
304
if ((offset + size) == total)
308
if (command == DRIZZLE_COMMAND_QUIT)
310
else if (command == DRIZZLE_COMMAND_FIELD_LIST)
312
if (drizzle_result_create(client, client_result) == NULL)
313
DRIZZLE_RETURN_ERROR("drizzle_result_create", drizzle)
315
if (drizzle_result_create(server, server_result) == NULL)
316
DRIZZLE_RETURN_ERROR("drizzle_result_create", drizzle)
320
(void)drizzle_result_read(client, client_result, &ret);
321
DRIZZLE_RETURN_CHECK(ret, "drizzle_result_read", drizzle)
323
drizzle_con_set_status(server, drizzle_con_status(client));
324
if (drizzle_result_clone(server, server_result, client_result) == NULL)
325
DRIZZLE_RETURN_ERROR("drizzle_result_clone", drizzle)
327
if (drizzle_result_column_count(client_result) == 0)
329
/* Simple result with no column, row, or field data. */
330
ret= drizzle_result_write(server, server_result, true);
331
DRIZZLE_RETURN_CHECK(ret, "drizzle_result_write", drizzle)
336
ret= drizzle_result_write(server, server_result, false);
337
DRIZZLE_RETURN_CHECK(ret, "drizzle_result_write", drizzle)
343
if (drizzle_column_read(client_result, column, &ret) == NULL)
345
DRIZZLE_RETURN_CHECK(ret, "drizzle_column_read", drizzle)
349
DRIZZLE_RETURN_CHECK(ret, "drizzle_column_read", drizzle)
351
ret= drizzle_column_write(server_result, column);
352
DRIZZLE_RETURN_CHECK(ret, "drizzle_column_write", drizzle)
354
drizzle_column_free(column);
357
drizzle_con_set_status(server, drizzle_con_status(client));
358
drizzle_result_set_eof(server_result, true);
360
if (command == DRIZZLE_COMMAND_FIELD_LIST)
362
ret= drizzle_result_write(server, server_result, true);
363
DRIZZLE_RETURN_CHECK(ret, "drizzle_result_write", drizzle)
368
ret= drizzle_result_write(server, server_result, false);
369
DRIZZLE_RETURN_CHECK(ret, "drizzle_result_write", drizzle)
375
row= drizzle_row_read(client_result, &ret);
376
DRIZZLE_RETURN_CHECK(ret, "drizzle_row_read", drizzle)
381
drizzle_result_set_row_size(server_result,
382
drizzle_result_row_size(client_result));
384
ret= drizzle_row_write(server_result);
385
DRIZZLE_RETURN_CHECK(ret, "drizzle_row_write", drizzle)
389
while (row_break == false)
391
field= drizzle_field_read(client_result, &offset, &size, &total, &ret);
392
if (ret == DRIZZLE_RETURN_ROW_END)
394
else if (ret == DRIZZLE_RETURN_ROW_BREAK)
402
DRIZZLE_RETURN_CHECK(ret, "drizzle_field_read", drizzle)
404
ret= drizzle_field_write(server_result, field, size, total);
405
DRIZZLE_RETURN_CHECK(ret, "drizzle_field_write", drizzle)
409
ret= drizzle_result_write(server, server_result, true);
410
DRIZZLE_RETURN_CHECK(ret, "drizzle_result_write", drizzle)