~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to examples/proxy.c

  • Committer: Monty Taylor
  • Date: 2010-12-24 02:13:05 UTC
  • mto: This revision was merged to the branch mainline in revision 2038.
  • Revision ID: mordred@inaugust.com-20101224021305-e3slv1cyjczqorij
Changed the bzrignore file.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * Drizzle Client & Protocol Library
 
3
 *
 
4
 * Copyright (C) 2008 Eric Day (eday@oddments.org)
 
5
 * All rights reserved.
 
6
 *
 
7
 * Redistribution and use in source and binary forms, with or without
 
8
 * modification, are permitted provided that the following conditions are
 
9
 * met:
 
10
 *
 
11
 *     * Redistributions of source code must retain the above copyright
 
12
 * notice, this list of conditions and the following disclaimer.
 
13
 *
 
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
 
17
 * distribution.
 
18
 *
 
19
 *     * The names of its contributors may not be used to endorse or
 
20
 * promote products derived from this software without specific prior
 
21
 * written permission.
 
22
 *
 
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.
 
34
 *
 
35
 */
 
36
 
 
37
 
 
38
#include <errno.h>
 
39
#include <stdio.h>
 
40
#include <stdlib.h>
 
41
#include <unistd.h>
 
42
 
 
43
#include <libdrizzle/drizzle_client.h>
 
44
#include <libdrizzle/drizzle_server.h>
 
45
 
 
46
#define DRIZZLE_RETURN_CHECK(__ret, __function, __drizzle) \
 
47
{ \
 
48
  if ((__ret) != DRIZZLE_RETURN_OK) \
 
49
    DRIZZLE_RETURN_ERROR(__function, __drizzle) \
 
50
}
 
51
 
 
52
#define DRIZZLE_RETURN_ERROR(__function, __drizzle) \
 
53
{ \
 
54
  printf(__function ":%s\n", drizzle_error(__drizzle)); \
 
55
  return; \
 
56
}
 
57
 
 
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);
 
61
 
 
62
int main(int argc, char *argv[])
 
63
{
 
64
  int c;
 
65
  uint32_t count= 0;
 
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;
 
73
  drizzle_return_t ret;
 
74
  drizzle_st drizzle;
 
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;
 
81
 
 
82
  while((c = getopt(argc, argv, "c:h:H:mMp:P:v")) != -1)
 
83
  {
 
84
    switch(c)
 
85
    {
 
86
    case 'c':
 
87
      count= (uint32_t)atoi(optarg);
 
88
      break;
 
89
 
 
90
    case 'h':
 
91
      server_host= optarg;
 
92
      break;
 
93
 
 
94
    case 'H':
 
95
      client_host= optarg;
 
96
      break;
 
97
 
 
98
    case 'm':
 
99
      server_mysql= true;
 
100
      break;
 
101
 
 
102
    case 'M':
 
103
      client_mysql= true;
 
104
      break;
 
105
 
 
106
    case 'p':
 
107
      server_port= (in_port_t)atoi(optarg);
 
108
      break;
 
109
 
 
110
    case 'P':
 
111
      client_port= (in_port_t)atoi(optarg);
 
112
      break;
 
113
 
 
114
    case 'v':
 
115
      switch(verbose)
 
116
      {
 
117
      case DRIZZLE_VERBOSE_NEVER:
 
118
        verbose= DRIZZLE_VERBOSE_FATAL;
 
119
        break;
 
120
      case DRIZZLE_VERBOSE_FATAL:
 
121
        verbose= DRIZZLE_VERBOSE_ERROR;
 
122
        break;
 
123
      case DRIZZLE_VERBOSE_ERROR:
 
124
        verbose= DRIZZLE_VERBOSE_INFO;
 
125
        break;
 
126
      case DRIZZLE_VERBOSE_INFO:
 
127
        verbose= DRIZZLE_VERBOSE_DEBUG;
 
128
        break;
 
129
      case DRIZZLE_VERBOSE_DEBUG:
 
130
        verbose= DRIZZLE_VERBOSE_CRAZY;
 
131
        break;
 
132
      case DRIZZLE_VERBOSE_CRAZY:
 
133
      case DRIZZLE_VERBOSE_MAX:
 
134
        break;
 
135
      }
 
136
      break;
 
137
 
 
138
    default:
 
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");
 
149
      return 1;
 
150
    }
 
151
  }
 
152
 
 
153
  if (drizzle_create(&drizzle) == NULL)
 
154
  {
 
155
    printf("drizzle_create:NULL\n");
 
156
    return 1;
 
157
  }
 
158
 
 
159
  drizzle_add_options(&drizzle, DRIZZLE_FREE_OBJECTS);
 
160
  drizzle_set_verbose(&drizzle, verbose);
 
161
 
 
162
  if (drizzle_con_create(&drizzle, con_listen) == NULL)
 
163
  {
 
164
    printf("drizzle_con_create:NULL\n");
 
165
    return 1;
 
166
  }
 
167
 
 
168
  drizzle_con_add_options(con_listen, DRIZZLE_CON_LISTEN);
 
169
  drizzle_con_set_tcp(con_listen, server_host, server_port);
 
170
 
 
171
  if (server_mysql)
 
172
    drizzle_con_add_options(con_listen, DRIZZLE_CON_MYSQL);
 
173
 
 
174
  if (drizzle_con_listen(con_listen) != DRIZZLE_RETURN_OK)
 
175
  {
 
176
    printf("drizzle_con_listen:%s\n", drizzle_error(&drizzle));
 
177
    return 1;
 
178
  }
 
179
 
 
180
  while (1)
 
181
  {
 
182
    (void)drizzle_con_accept(&drizzle, server, &ret);
 
183
    if (ret != DRIZZLE_RETURN_OK)
 
184
    {
 
185
      printf("drizzle_con_accept:%s\n", drizzle_error(&drizzle));
 
186
      return 1;
 
187
    }
 
188
 
 
189
    if (drizzle_con_create(&drizzle, client) == NULL)
 
190
    {
 
191
      printf("drizzle_con_create:NULL\n");
 
192
      return 1;
 
193
    }
 
194
 
 
195
    drizzle_con_add_options(client,
 
196
                            DRIZZLE_CON_RAW_PACKET | DRIZZLE_CON_RAW_SCRAMBLE);
 
197
    if (client_mysql)
 
198
      drizzle_con_add_options(client, DRIZZLE_CON_MYSQL);
 
199
    drizzle_con_set_tcp(client, client_host, client_port);
 
200
 
 
201
    ret= drizzle_con_connect(client);
 
202
    if (ret != DRIZZLE_RETURN_OK)
 
203
    {
 
204
      printf("drizzle_con_connect:%s\n", drizzle_error(&drizzle));
 
205
      return 1;
 
206
    }
 
207
 
 
208
    proxy(&drizzle, server, client, &server_result, &client_result, &column);
 
209
 
 
210
    drizzle_con_free(client);
 
211
    drizzle_con_free(server);
 
212
 
 
213
    if (count > 0)
 
214
    {
 
215
      count--;
 
216
 
 
217
      if (count == 0)
 
218
        break;
 
219
    }
 
220
  }
 
221
 
 
222
  drizzle_con_free(con_listen);
 
223
  drizzle_free(&drizzle);
 
224
 
 
225
  free(con_listen);
 
226
  free(server);
 
227
  free(client);
 
228
 
 
229
  return 0;
 
230
}
 
231
 
 
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)
 
235
{
 
236
  drizzle_return_t ret;
 
237
  drizzle_command_t command;
 
238
  uint8_t *data;
 
239
  size_t offset;
 
240
  size_t size;
 
241
  size_t total;
 
242
  uint64_t row;
 
243
  bool row_break;
 
244
  drizzle_field_t field;
 
245
 
 
246
  /* Handshake packets. */
 
247
  ret= drizzle_handshake_server_read(client);
 
248
  DRIZZLE_RETURN_CHECK(ret, "drizzle_handshake_server_read", drizzle)
 
249
 
 
250
  drizzle_con_copy_handshake(server, client);
 
251
 
 
252
  ret= drizzle_handshake_server_write(server);
 
253
  DRIZZLE_RETURN_CHECK(ret, "drizzle_handshake_server_write", drizzle)
 
254
 
 
255
  ret= drizzle_handshake_client_read(server);
 
256
  DRIZZLE_RETURN_CHECK(ret, "drizzle_handshake_client_read", drizzle)
 
257
 
 
258
  drizzle_con_copy_handshake(client, server);
 
259
 
 
260
  ret= drizzle_handshake_client_write(client);
 
261
  DRIZZLE_RETURN_CHECK(ret, "drizzle_handshake_client_write", drizzle)
 
262
 
 
263
  (void)drizzle_result_read(client, client_result, &ret);
 
264
  DRIZZLE_RETURN_CHECK(ret, "drizzle_result_read", drizzle)
 
265
 
 
266
  drizzle_con_set_status(server, drizzle_con_status(client));
 
267
 
 
268
  if (drizzle_result_clone(server, server_result, client_result) == NULL)
 
269
    DRIZZLE_RETURN_ERROR("drizzle_result_clone", drizzle)
 
270
 
 
271
  ret= drizzle_result_write(server, server_result, true);
 
272
  DRIZZLE_RETURN_CHECK(ret, "drizzle_result_write", drizzle)
 
273
 
 
274
  if (drizzle_result_error_code(client_result) != 0 ||
 
275
      drizzle_result_eof(client_result))
 
276
  {
 
277
    /* There was a handshake or authentication error. */
 
278
    return;
 
279
  }
 
280
 
 
281
  drizzle_con_add_options(client, DRIZZLE_CON_READY);
 
282
 
 
283
  /* Command loop. */
 
284
  while (1)
 
285
  {
 
286
    drizzle_result_free(server_result);
 
287
    drizzle_result_free(client_result);
 
288
 
 
289
    while (1)
 
290
    {
 
291
      data= (uint8_t *)drizzle_con_command_read(server, &command, &offset, &size, &total,
 
292
                                     &ret);
 
293
      if (ret == DRIZZLE_RETURN_LOST_CONNECTION)
 
294
        return;
 
295
 
 
296
      DRIZZLE_RETURN_CHECK(ret, "drizzle_con_command_read", drizzle)
 
297
 
 
298
      (void)drizzle_con_command_write(client, NULL, command, data, size, total,
 
299
                                      &ret);
 
300
      DRIZZLE_RETURN_CHECK(ret, "drizzle_con_command_write", drizzle)
 
301
 
 
302
      if ((offset + size) == total)
 
303
        break;
 
304
    }
 
305
 
 
306
    if (command == DRIZZLE_COMMAND_QUIT)
 
307
      return;
 
308
    else if (command == DRIZZLE_COMMAND_FIELD_LIST)
 
309
    {
 
310
      if (drizzle_result_create(client, client_result) == NULL)
 
311
        DRIZZLE_RETURN_ERROR("drizzle_result_create", drizzle)
 
312
 
 
313
      if (drizzle_result_create(server, server_result) == NULL)
 
314
        DRIZZLE_RETURN_ERROR("drizzle_result_create", drizzle)
 
315
    }
 
316
    else
 
317
    {
 
318
      (void)drizzle_result_read(client, client_result, &ret);
 
319
      DRIZZLE_RETURN_CHECK(ret, "drizzle_result_read", drizzle)
 
320
 
 
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)
 
324
 
 
325
      if (drizzle_result_column_count(client_result) == 0)
 
326
      {
 
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)
 
330
 
 
331
        continue;
 
332
      }
 
333
 
 
334
      ret= drizzle_result_write(server, server_result, false);
 
335
      DRIZZLE_RETURN_CHECK(ret, "drizzle_result_write", drizzle)
 
336
    }
 
337
 
 
338
    /* Columns. */
 
339
    while (1)
 
340
    {
 
341
      if (drizzle_column_read(client_result, column, &ret) == NULL)
 
342
      {
 
343
        DRIZZLE_RETURN_CHECK(ret, "drizzle_column_read", drizzle)
 
344
        break;
 
345
      }
 
346
 
 
347
      DRIZZLE_RETURN_CHECK(ret, "drizzle_column_read", drizzle)
 
348
 
 
349
      ret= drizzle_column_write(server_result, column);
 
350
      DRIZZLE_RETURN_CHECK(ret, "drizzle_column_write", drizzle)
 
351
 
 
352
      drizzle_column_free(column);
 
353
    }
 
354
 
 
355
    drizzle_con_set_status(server, drizzle_con_status(client));
 
356
    drizzle_result_set_eof(server_result, true);
 
357
 
 
358
    if (command == DRIZZLE_COMMAND_FIELD_LIST)
 
359
    {
 
360
      ret= drizzle_result_write(server, server_result, true);
 
361
      DRIZZLE_RETURN_CHECK(ret, "drizzle_result_write", drizzle)
 
362
      continue;
 
363
    }
 
364
    else
 
365
    {
 
366
      ret= drizzle_result_write(server, server_result, false);
 
367
      DRIZZLE_RETURN_CHECK(ret, "drizzle_result_write", drizzle)
 
368
    }
 
369
 
 
370
    /* Rows. */
 
371
    while (1)
 
372
    {
 
373
      row= drizzle_row_read(client_result, &ret);
 
374
      DRIZZLE_RETURN_CHECK(ret, "drizzle_row_read", drizzle)
 
375
 
 
376
      if (row == 0)
 
377
        break;
 
378
 
 
379
      drizzle_result_set_row_size(server_result,
 
380
                                  drizzle_result_row_size(client_result));
 
381
 
 
382
      ret= drizzle_row_write(server_result);
 
383
      DRIZZLE_RETURN_CHECK(ret, "drizzle_row_write", drizzle)
 
384
 
 
385
      /* Fields. */
 
386
      row_break= false;
 
387
      while (row_break == false)
 
388
      {
 
389
        field= drizzle_field_read(client_result, &offset, &size, &total, &ret);
 
390
        if (ret == DRIZZLE_RETURN_ROW_END)
 
391
          break;
 
392
        else if (ret == DRIZZLE_RETURN_ROW_BREAK)
 
393
        {
 
394
          if (size == 0)
 
395
            break;
 
396
 
 
397
          row_break= true;
 
398
        }
 
399
        else
 
400
          DRIZZLE_RETURN_CHECK(ret, "drizzle_field_read", drizzle)
 
401
 
 
402
        ret= drizzle_field_write(server_result, field, size, total);
 
403
        DRIZZLE_RETURN_CHECK(ret, "drizzle_field_write", drizzle)
 
404
      }
 
405
    }
 
406
 
 
407
    ret= drizzle_result_write(server, server_result, true);
 
408
    DRIZZLE_RETURN_CHECK(ret, "drizzle_result_write", drizzle)
 
409
  }
 
410
}