libdrizzle Public API Documentation

examples/proxy.c
Go to the documentation of this file.
00001 /*
00002  * Drizzle Client & Protocol Library
00003  *
00004  * Copyright (C) 2008 Eric Day (eday@oddments.org)
00005  * All rights reserved.
00006  *
00007  * Use and distribution licensed under the BSD license.  See
00008  * the COPYING file in this directory for full text.
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   /* Handshake packets. */
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     /* There was a handshake or authentication error. */
00227     return;
00228   }
00229 
00230   drizzle_con_add_options(client, DRIZZLE_CON_READY);
00231 
00232   /* Command loop. */
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         /* Simple result with no column, row, or field data. */
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     /* Columns. */
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     /* Rows. */
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       /* Fields. */
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 }