00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011 #include <errno.h>
00012 #include <stdio.h>
00013 #include <stdlib.h>
00014 #include <unistd.h>
00015
00016 #include <libdrizzle/drizzle_client.h>
00017 #include <libdrizzle/drizzle_server.h>
00018
00019 #define DRIZZLE_RETURN_CHECK(__ret, __function, __drizzle) \
00020 { \
00021 if ((__ret) != DRIZZLE_RETURN_OK) \
00022 DRIZZLE_RETURN_ERROR(__function, __drizzle) \
00023 }
00024
00025 #define DRIZZLE_RETURN_ERROR(__function, __drizzle) \
00026 { \
00027 printf(__function ":%s\n", drizzle_error(__drizzle)); \
00028 return; \
00029 }
00030
00031 static void proxy(drizzle_st *drizzle, drizzle_con_st *server,
00032 drizzle_con_st *client, drizzle_result_st *server_result,
00033 drizzle_result_st *client_result, drizzle_column_st *column);
00034
00035 int main(int argc, char *argv[])
00036 {
00037 int c;
00038 uint32_t count= 0;
00039 const char *server_host= NULL;
00040 const char *client_host= NULL;
00041 bool server_mysql= false;
00042 bool client_mysql= false;
00043 in_port_t server_port= 0;
00044 in_port_t client_port= 0;
00045 drizzle_verbose_t verbose= DRIZZLE_VERBOSE_NEVER;
00046 drizzle_return_t ret;
00047 drizzle_st drizzle;
00048 drizzle_con_st con_listen;
00049 drizzle_con_st server;
00050 drizzle_con_st client;
00051 drizzle_result_st server_result;
00052 drizzle_result_st client_result;
00053 drizzle_column_st column;
00054
00055 while((c = getopt(argc, argv, "c:h:H:mMp:P:v")) != -1)
00056 {
00057 switch(c)
00058 {
00059 case 'c':
00060 count= (uint32_t)atoi(optarg);
00061 break;
00062
00063 case 'h':
00064 server_host= optarg;
00065 break;
00066
00067 case 'H':
00068 client_host= optarg;
00069 break;
00070
00071 case 'm':
00072 server_mysql= true;
00073 break;
00074
00075 case 'M':
00076 client_mysql= true;
00077 break;
00078
00079 case 'p':
00080 server_port= (in_port_t)atoi(optarg);
00081 break;
00082
00083 case 'P':
00084 client_port= (in_port_t)atoi(optarg);
00085 break;
00086
00087 case 'v':
00088 verbose++;
00089 break;
00090
00091 default:
00092 printf("\nusage: %s [-c <count>] [-h <host>] [-H <host>] [-m] [-M] "
00093 "[-p <port>] [-p <port>] [-v]\n", argv[0]);
00094 printf("\t-c <count> - Number of connections to accept before exiting\n");
00095 printf("\t-h <host> - Host to listen on\n");
00096 printf("\t-H <host> - Host to connect to\n");
00097 printf("\t-m - Use MySQL protocol for incoming connections\n");
00098 printf("\t-M - Use MySQL protocol for outgoing connectionsn\n");
00099 printf("\t-p <port> - Port to listen on\n");
00100 printf("\t-P <port> - Port to connect to\n");
00101 printf("\t-v - Increase verbosity level\n");
00102 return 1;
00103 }
00104 }
00105
00106 if (drizzle_create(&drizzle) == NULL)
00107 {
00108 printf("drizzle_create:NULL\n");
00109 return 1;
00110 }
00111
00112 drizzle_add_options(&drizzle, DRIZZLE_FREE_OBJECTS);
00113 drizzle_set_verbose(&drizzle, verbose);
00114
00115 if (drizzle_con_create(&drizzle, &con_listen) == NULL)
00116 {
00117 printf("drizzle_con_create:NULL\n");
00118 return 1;
00119 }
00120
00121 drizzle_con_add_options(&con_listen, DRIZZLE_CON_LISTEN);
00122 drizzle_con_set_tcp(&con_listen, server_host, server_port);
00123
00124 if (server_mysql)
00125 drizzle_con_add_options(&con_listen, DRIZZLE_CON_MYSQL);
00126
00127 if (drizzle_con_listen(&con_listen) != DRIZZLE_RETURN_OK)
00128 {
00129 printf("drizzle_con_listen:%s\n", drizzle_error(&drizzle));
00130 return 1;
00131 }
00132
00133 while (1)
00134 {
00135 (void)drizzle_con_accept(&drizzle, &server, &ret);
00136 if (ret != DRIZZLE_RETURN_OK)
00137 {
00138 printf("drizzle_con_accept:%s\n", drizzle_error(&drizzle));
00139 return 1;
00140 }
00141
00142 if (drizzle_con_create(&drizzle, &client) == NULL)
00143 {
00144 printf("drizzle_con_create:NULL\n");
00145 return 1;
00146 }
00147
00148 drizzle_con_add_options(&client,
00149 DRIZZLE_CON_RAW_PACKET | DRIZZLE_CON_RAW_SCRAMBLE);
00150 if (client_mysql)
00151 drizzle_con_add_options(&client, DRIZZLE_CON_MYSQL);
00152 drizzle_con_set_tcp(&client, client_host, client_port);
00153
00154 ret= drizzle_con_connect(&client);
00155 if (ret != DRIZZLE_RETURN_OK)
00156 {
00157 printf("drizzle_con_connect:%s\n", drizzle_error(&drizzle));
00158 return 1;
00159 }
00160
00161 proxy(&drizzle, &server, &client, &server_result, &client_result, &column);
00162
00163 drizzle_con_free(&client);
00164 drizzle_con_free(&server);
00165
00166 if (count > 0)
00167 {
00168 count--;
00169
00170 if (count == 0)
00171 break;
00172 }
00173 }
00174
00175 drizzle_con_free(&con_listen);
00176 drizzle_free(&drizzle);
00177
00178 return 0;
00179 }
00180
00181 static void proxy(drizzle_st *drizzle, drizzle_con_st *server,
00182 drizzle_con_st *client, drizzle_result_st *server_result,
00183 drizzle_result_st *client_result, drizzle_column_st *column)
00184 {
00185 drizzle_return_t ret;
00186 drizzle_command_t command;
00187 const uint8_t *data;
00188 size_t offset;
00189 size_t size;
00190 size_t total;
00191 uint64_t row;
00192 bool row_break;
00193 drizzle_field_t field;
00194
00195
00196 ret= drizzle_handshake_server_read(client);
00197 DRIZZLE_RETURN_CHECK(ret, "drizzle_handshake_server_read", drizzle)
00198
00199 drizzle_con_copy_handshake(server, client);
00200
00201 ret= drizzle_handshake_server_write(server);
00202 DRIZZLE_RETURN_CHECK(ret, "drizzle_handshake_server_write", drizzle)
00203
00204 ret= drizzle_handshake_client_read(server);
00205 DRIZZLE_RETURN_CHECK(ret, "drizzle_handshake_client_read", drizzle)
00206
00207 drizzle_con_copy_handshake(client, server);
00208
00209 ret= drizzle_handshake_client_write(client);
00210 DRIZZLE_RETURN_CHECK(ret, "drizzle_handshake_client_write", drizzle)
00211
00212 (void)drizzle_result_read(client, client_result, &ret);
00213 DRIZZLE_RETURN_CHECK(ret, "drizzle_result_read", drizzle)
00214
00215 drizzle_con_set_status(server, drizzle_con_status(client));
00216
00217 if (drizzle_result_clone(server, server_result, client_result) == NULL)
00218 DRIZZLE_RETURN_ERROR("drizzle_result_clone", drizzle)
00219
00220 ret= drizzle_result_write(server, server_result, true);
00221 DRIZZLE_RETURN_CHECK(ret, "drizzle_result_write", drizzle)
00222
00223 if (drizzle_result_error_code(client_result) != 0 ||
00224 drizzle_result_eof(client_result))
00225 {
00226
00227 return;
00228 }
00229
00230 drizzle_con_add_options(client, DRIZZLE_CON_READY);
00231
00232
00233 while (1)
00234 {
00235 drizzle_result_free(server_result);
00236 drizzle_result_free(client_result);
00237
00238 while (1)
00239 {
00240 data= drizzle_con_command_read(server, &command, &offset, &size, &total,
00241 &ret);
00242 if (ret == DRIZZLE_RETURN_LOST_CONNECTION)
00243 return;
00244
00245 DRIZZLE_RETURN_CHECK(ret, "drizzle_con_command_read", drizzle)
00246
00247 (void)drizzle_con_command_write(client, NULL, command, data, size, total,
00248 &ret);
00249 DRIZZLE_RETURN_CHECK(ret, "drizzle_con_command_write", drizzle)
00250
00251 if ((offset + size) == total)
00252 break;
00253 }
00254
00255 if (command == DRIZZLE_COMMAND_QUIT)
00256 return;
00257 else if (command == DRIZZLE_COMMAND_FIELD_LIST)
00258 {
00259 if (drizzle_result_create(client, client_result) == NULL)
00260 DRIZZLE_RETURN_ERROR("drizzle_result_create", drizzle)
00261
00262 if (drizzle_result_create(server, server_result) == NULL)
00263 DRIZZLE_RETURN_ERROR("drizzle_result_create", drizzle)
00264 }
00265 else
00266 {
00267 (void)drizzle_result_read(client, client_result, &ret);
00268 DRIZZLE_RETURN_CHECK(ret, "drizzle_result_read", drizzle)
00269
00270 drizzle_con_set_status(server, drizzle_con_status(client));
00271 if (drizzle_result_clone(server, server_result, client_result) == NULL)
00272 DRIZZLE_RETURN_ERROR("drizzle_result_clone", drizzle)
00273
00274 if (drizzle_result_column_count(client_result) == 0)
00275 {
00276
00277 ret= drizzle_result_write(server, server_result, true);
00278 DRIZZLE_RETURN_CHECK(ret, "drizzle_result_write", drizzle)
00279
00280 continue;
00281 }
00282
00283 ret= drizzle_result_write(server, server_result, false);
00284 DRIZZLE_RETURN_CHECK(ret, "drizzle_result_write", drizzle)
00285 }
00286
00287
00288 while (1)
00289 {
00290 if (drizzle_column_read(client_result, column, &ret) == NULL)
00291 {
00292 DRIZZLE_RETURN_CHECK(ret, "drizzle_column_read", drizzle)
00293 break;
00294 }
00295
00296 DRIZZLE_RETURN_CHECK(ret, "drizzle_column_read", drizzle)
00297
00298 ret= drizzle_column_write(server_result, column);
00299 DRIZZLE_RETURN_CHECK(ret, "drizzle_column_write", drizzle)
00300
00301 drizzle_column_free(column);
00302 }
00303
00304 drizzle_con_set_status(server, drizzle_con_status(client));
00305 drizzle_result_set_eof(server_result, true);
00306
00307 if (command == DRIZZLE_COMMAND_FIELD_LIST)
00308 {
00309 ret= drizzle_result_write(server, server_result, true);
00310 DRIZZLE_RETURN_CHECK(ret, "drizzle_result_write", drizzle)
00311 continue;
00312 }
00313 else
00314 {
00315 ret= drizzle_result_write(server, server_result, false);
00316 DRIZZLE_RETURN_CHECK(ret, "drizzle_result_write", drizzle)
00317 }
00318
00319
00320 while (1)
00321 {
00322 row= drizzle_row_read(client_result, &ret);
00323 DRIZZLE_RETURN_CHECK(ret, "drizzle_row_read", drizzle)
00324
00325 if (row == 0)
00326 break;
00327
00328 drizzle_result_set_row_size(server_result,
00329 drizzle_result_row_size(client_result));
00330
00331 ret= drizzle_row_write(server_result);
00332 DRIZZLE_RETURN_CHECK(ret, "drizzle_row_write", drizzle)
00333
00334
00335 row_break= false;
00336 while (row_break == false)
00337 {
00338 field= drizzle_field_read(client_result, &offset, &size, &total, &ret);
00339 if (ret == DRIZZLE_RETURN_ROW_END)
00340 break;
00341 else if (ret == DRIZZLE_RETURN_ROW_BREAK)
00342 {
00343 if (size == 0)
00344 break;
00345
00346 row_break= true;
00347 }
00348 else
00349 DRIZZLE_RETURN_CHECK(ret, "drizzle_field_read", drizzle)
00350
00351 ret= drizzle_field_write(server_result, field, size, total);
00352 DRIZZLE_RETURN_CHECK(ret, "drizzle_field_write", drizzle)
00353 }
00354 }
00355
00356 ret= drizzle_result_write(server, server_result, true);
00357 DRIZZLE_RETURN_CHECK(ret, "drizzle_result_write", drizzle)
00358 }
00359 }