libdrizzle Developer Documentation

proxy.c
Go to the documentation of this file.
1 /*
2  * Drizzle Client & Protocol Library
3  *
4  * Copyright (C) 2008 Eric Day (eday@oddments.org)
5  * All rights reserved.
6  *
7  * Use and distribution licensed under the BSD license. See
8  * the COPYING file in this directory for full text.
9  */
10 
11 #include <errno.h>
12 #include <stdio.h>
13 #include <stdlib.h>
14 #include <unistd.h>
15 
18 
19 #define DRIZZLE_RETURN_CHECK(__ret, __function, __drizzle) \
20 { \
21  if ((__ret) != DRIZZLE_RETURN_OK) \
22  DRIZZLE_RETURN_ERROR(__function, __drizzle) \
23 }
24 
25 #define DRIZZLE_RETURN_ERROR(__function, __drizzle) \
26 { \
27  printf(__function ":%s\n", drizzle_error(__drizzle)); \
28  return; \
29 }
30 
31 static void proxy(drizzle_st *drizzle, drizzle_con_st *server,
32  drizzle_con_st *client, drizzle_result_st *server_result,
33  drizzle_result_st *client_result, drizzle_column_st *column);
34 
35 int main(int argc, char *argv[])
36 {
37  int c;
38  uint32_t count= 0;
39  const char *server_host= NULL;
40  const char *client_host= NULL;
41  bool server_mysql= false;
42  bool client_mysql= false;
43  in_port_t server_port= 0;
44  in_port_t client_port= 0;
46  drizzle_return_t ret;
47  drizzle_st drizzle;
48  drizzle_con_st con_listen;
50  drizzle_con_st client;
51  drizzle_result_st server_result;
52  drizzle_result_st client_result;
53  drizzle_column_st column;
54 
55  while((c = getopt(argc, argv, "c:h:H:mMp:P:v")) != -1)
56  {
57  switch(c)
58  {
59  case 'c':
60  count= (uint32_t)atoi(optarg);
61  break;
62 
63  case 'h':
64  server_host= optarg;
65  break;
66 
67  case 'H':
68  client_host= optarg;
69  break;
70 
71  case 'm':
72  server_mysql= true;
73  break;
74 
75  case 'M':
76  client_mysql= true;
77  break;
78 
79  case 'p':
80  server_port= (in_port_t)atoi(optarg);
81  break;
82 
83  case 'P':
84  client_port= (in_port_t)atoi(optarg);
85  break;
86 
87  case 'v':
88  verbose++;
89  break;
90 
91  default:
92  printf("\nusage: %s [-c <count>] [-h <host>] [-H <host>] [-m] [-M] "
93  "[-p <port>] [-p <port>] [-v]\n", argv[0]);
94  printf("\t-c <count> - Number of connections to accept before exiting\n");
95  printf("\t-h <host> - Host to listen on\n");
96  printf("\t-H <host> - Host to connect to\n");
97  printf("\t-m - Use MySQL protocol for incoming connections\n");
98  printf("\t-M - Use MySQL protocol for outgoing connectionsn\n");
99  printf("\t-p <port> - Port to listen on\n");
100  printf("\t-P <port> - Port to connect to\n");
101  printf("\t-v - Increase verbosity level\n");
102  return 1;
103  }
104  }
105 
106  if (drizzle_create(&drizzle) == NULL)
107  {
108  printf("drizzle_create:NULL\n");
109  return 1;
110  }
111 
113  drizzle_set_verbose(&drizzle, verbose);
114 
115  if (drizzle_con_create(&drizzle, &con_listen) == NULL)
116  {
117  printf("drizzle_con_create:NULL\n");
118  return 1;
119  }
120 
122  drizzle_con_set_tcp(&con_listen, server_host, server_port);
123 
124  if (server_mysql)
126 
127  if (drizzle_con_listen(&con_listen) != DRIZZLE_RETURN_OK)
128  {
129  printf("drizzle_con_listen:%s\n", drizzle_error(&drizzle));
130  return 1;
131  }
132 
133  while (1)
134  {
135  (void)drizzle_con_accept(&drizzle, &server, &ret);
136  if (ret != DRIZZLE_RETURN_OK)
137  {
138  printf("drizzle_con_accept:%s\n", drizzle_error(&drizzle));
139  return 1;
140  }
141 
142  if (drizzle_con_create(&drizzle, &client) == NULL)
143  {
144  printf("drizzle_con_create:NULL\n");
145  return 1;
146  }
147 
148  drizzle_con_add_options(&client,
150  if (client_mysql)
152  drizzle_con_set_tcp(&client, client_host, client_port);
153 
154  ret= drizzle_con_connect(&client);
155  if (ret != DRIZZLE_RETURN_OK)
156  {
157  printf("drizzle_con_connect:%s\n", drizzle_error(&drizzle));
158  return 1;
159  }
160 
161  proxy(&drizzle, &server, &client, &server_result, &client_result, &column);
162 
163  drizzle_con_free(&client);
164  drizzle_con_free(&server);
165 
166  if (count > 0)
167  {
168  count--;
169 
170  if (count == 0)
171  break;
172  }
173  }
174 
175  drizzle_con_free(&con_listen);
176  drizzle_free(&drizzle);
177 
178  return 0;
179 }
180 
181 static void proxy(drizzle_st *drizzle, drizzle_con_st *server,
182  drizzle_con_st *client, drizzle_result_st *server_result,
183  drizzle_result_st *client_result, drizzle_column_st *column)
184 {
185  drizzle_return_t ret;
186  drizzle_command_t command;
187  const uint8_t *data;
188  size_t offset;
189  size_t size;
190  size_t total;
191  uint64_t row;
192  bool row_break;
193  drizzle_field_t field;
194 
195  /* Handshake packets. */
196  ret= drizzle_handshake_server_read(client);
197  DRIZZLE_RETURN_CHECK(ret, "drizzle_handshake_server_read", drizzle)
198 
199  drizzle_con_copy_handshake(server, client);
200 
201  ret= drizzle_handshake_server_write(server);
202  DRIZZLE_RETURN_CHECK(ret, "drizzle_handshake_server_write", drizzle)
203 
204  ret= drizzle_handshake_client_read(server);
205  DRIZZLE_RETURN_CHECK(ret, "drizzle_handshake_client_read", drizzle)
206 
207  drizzle_con_copy_handshake(client, server);
208 
209  ret= drizzle_handshake_client_write(client);
210  DRIZZLE_RETURN_CHECK(ret, "drizzle_handshake_client_write", drizzle)
211 
212  (void)drizzle_result_read(client, client_result, &ret);
213  DRIZZLE_RETURN_CHECK(ret, "drizzle_result_read", drizzle)
214 
216 
217  if (drizzle_result_clone(server, server_result, client_result) == NULL)
218  DRIZZLE_RETURN_ERROR("drizzle_result_clone", drizzle)
219 
220  ret= drizzle_result_write(server, server_result, true);
221  DRIZZLE_RETURN_CHECK(ret, "drizzle_result_write", drizzle)
222 
223  if (drizzle_result_error_code(client_result) != 0 ||
224  drizzle_result_eof(client_result))
225  {
226  /* There was a handshake or authentication error. */
227  return;
228  }
229 
231 
232  /* Command loop. */
233  while (1)
234  {
235  drizzle_result_free(server_result);
236  drizzle_result_free(client_result);
237 
238  while (1)
239  {
240  data= drizzle_con_command_read(server, &command, &offset, &size, &total,
241  &ret);
243  return;
244 
245  DRIZZLE_RETURN_CHECK(ret, "drizzle_con_command_read", drizzle)
246 
247  (void)drizzle_con_command_write(client, NULL, command, data, size, total,
248  &ret);
249  DRIZZLE_RETURN_CHECK(ret, "drizzle_con_command_write", drizzle)
250 
251  if ((offset + size) == total)
252  break;
253  }
254 
255  if (command == DRIZZLE_COMMAND_QUIT)
256  return;
257  else if (command == DRIZZLE_COMMAND_FIELD_LIST)
258  {
259  if (drizzle_result_create(client, client_result) == NULL)
260  DRIZZLE_RETURN_ERROR("drizzle_result_create", drizzle)
261 
262  if (drizzle_result_create(server, server_result) == NULL)
263  DRIZZLE_RETURN_ERROR("drizzle_result_create", drizzle)
264  }
265  else
266  {
267  (void)drizzle_result_read(client, client_result, &ret);
268  DRIZZLE_RETURN_CHECK(ret, "drizzle_result_read", drizzle)
269 
271  if (drizzle_result_clone(server, server_result, client_result) == NULL)
272  DRIZZLE_RETURN_ERROR("drizzle_result_clone", drizzle)
273 
274  if (drizzle_result_column_count(client_result) == 0)
275  {
276  /* Simple result with no column, row, or field data. */
277  ret= drizzle_result_write(server, server_result, true);
278  DRIZZLE_RETURN_CHECK(ret, "drizzle_result_write", drizzle)
279 
280  continue;
281  }
282 
283  ret= drizzle_result_write(server, server_result, false);
284  DRIZZLE_RETURN_CHECK(ret, "drizzle_result_write", drizzle)
285  }
286 
287  /* Columns. */
288  while (1)
289  {
290  if (drizzle_column_read(client_result, column, &ret) == NULL)
291  {
292  DRIZZLE_RETURN_CHECK(ret, "drizzle_column_read", drizzle)
293  break;
294  }
295 
296  DRIZZLE_RETURN_CHECK(ret, "drizzle_column_read", drizzle)
297 
298  ret= drizzle_column_write(server_result, column);
299  DRIZZLE_RETURN_CHECK(ret, "drizzle_column_write", drizzle)
300 
301  drizzle_column_free(column);
302  }
303 
305  drizzle_result_set_eof(server_result, true);
306 
307  if (command == DRIZZLE_COMMAND_FIELD_LIST)
308  {
309  ret= drizzle_result_write(server, server_result, true);
310  DRIZZLE_RETURN_CHECK(ret, "drizzle_result_write", drizzle)
311  continue;
312  }
313  else
314  {
315  ret= drizzle_result_write(server, server_result, false);
316  DRIZZLE_RETURN_CHECK(ret, "drizzle_result_write", drizzle)
317  }
318 
319  /* Rows. */
320  while (1)
321  {
322  row= drizzle_row_read(client_result, &ret);
323  DRIZZLE_RETURN_CHECK(ret, "drizzle_row_read", drizzle)
324 
325  if (row == 0)
326  break;
327 
328  drizzle_result_set_row_size(server_result,
329  drizzle_result_row_size(client_result));
330 
331  ret= drizzle_row_write(server_result);
332  DRIZZLE_RETURN_CHECK(ret, "drizzle_row_write", drizzle)
333 
334  /* Fields. */
335  row_break= false;
336  while (row_break == false)
337  {
338  field= drizzle_field_read(client_result, &offset, &size, &total, &ret);
339  if (ret == DRIZZLE_RETURN_ROW_END)
340  break;
341  else if (ret == DRIZZLE_RETURN_ROW_BREAK)
342  {
343  if (size == 0)
344  break;
345 
346  row_break= true;
347  }
348  else
349  DRIZZLE_RETURN_CHECK(ret, "drizzle_field_read", drizzle)
350 
351  ret= drizzle_field_write(server_result, field, size, total);
352  DRIZZLE_RETURN_CHECK(ret, "drizzle_field_write", drizzle)
353  }
354  }
355 
356  ret= drizzle_result_write(server, server_result, true);
357  DRIZZLE_RETURN_CHECK(ret, "drizzle_result_write", drizzle)
358  }
359 }