~drizzle-trunk/drizzle/development

2244.1.1 by Monty Taylor
Split libdrizzle into 1.0 and 2.0. Applied the C++ changes to 2.0 branch.
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
/**
39
 * @file
40
 * @brief Connection Definitions
41
 */
42
2449.1.2 by Brian Aker
Additional fixes for libdrizzle.
43
#include <libdrizzle-2.0/common.h>
2244.1.1 by Monty Taylor
Split libdrizzle into 1.0 and 2.0. Applied the C++ changes to 2.0 branch.
44
45
/**
46
 * @addtogroup drizzle_con_static Static Connection Declarations
47
 * @ingroup drizzle_con
48
 * @{
49
 */
50
51
/**
52
 * Set socket options for a connection.
53
 *
54
 * @param[in] con Connection structure previously initialized with
55
 *  drizzle_con_create(), drizzle_con_clone(), or related functions.
56
 * @return Standard drizzle return value.
57
 */
58
static drizzle_return_t _con_setsockopt(drizzle_con_st *con);
59
60
/** @} */
61
62
/*
63
 * Common Definitions
64
 */
65
66
int drizzle_con_fd(const drizzle_con_st *con)
67
{
68
  return con->fd;
69
}
70
71
drizzle_return_t drizzle_con_set_fd(drizzle_con_st *con, int fd)
72
{
73
  con->fd= fd;
74
2318.5.27 by Olaf van der Spek
Refactor
75
  drizzle_return_t ret= _con_setsockopt(con);
2244.1.1 by Monty Taylor
Split libdrizzle into 1.0 and 2.0. Applied the C++ changes to 2.0 branch.
76
  if (ret != DRIZZLE_RETURN_OK)
77
    con->drizzle->last_errno= errno;
78
79
  return ret;
80
}
81
82
void drizzle_con_close(drizzle_con_st *con)
83
{
84
  if (con->fd == -1)
85
    return;
86
87
  (void)closesocket(con->fd);
88
  con->fd= -1;
89
90
  con->options&= ~DRIZZLE_CON_READY;
91
  con->packet_number= 0;
92
  con->buffer_ptr= con->buffer;
93
  con->buffer_size= 0;
94
  con->events= 0;
95
  con->revents= 0;
96
97
  drizzle_state_reset(con);
98
}
99
100
drizzle_return_t drizzle_con_set_events(drizzle_con_st *con, short events)
101
{
102
  if ((con->events | events) == con->events)
103
    return DRIZZLE_RETURN_OK;
104
105
  con->events|= events;
106
107
  if (con->drizzle->event_watch_fn != NULL)
108
  {
2318.5.27 by Olaf van der Spek
Refactor
109
    drizzle_return_t ret= con->drizzle->event_watch_fn(con, con->events,
2244.1.1 by Monty Taylor
Split libdrizzle into 1.0 and 2.0. Applied the C++ changes to 2.0 branch.
110
                                      con->drizzle->event_watch_context);
111
    if (ret != DRIZZLE_RETURN_OK)
112
    {
113
      drizzle_con_close(con);
114
      return ret;
115
    }
116
  }
117
118
  return DRIZZLE_RETURN_OK;
119
}
120
121
drizzle_return_t drizzle_con_set_revents(drizzle_con_st *con, short revents)
122
{
123
  if (revents != 0)
124
    con->options|= DRIZZLE_CON_IO_READY;
125
126
  con->revents= revents;
127
128
  /* Remove external POLLOUT watch if we didn't ask for it. Otherwise we spin
129
     forever until another POLLIN state change. This is much more efficient
130
     than removing POLLOUT on every state change since some external polling
131
     mechanisms need to use a system call to change flags (like Linux epoll). */
132
  if (revents & POLLOUT && !(con->events & POLLOUT) &&
133
      con->drizzle->event_watch_fn != NULL)
134
  {
2318.5.27 by Olaf van der Spek
Refactor
135
    drizzle_return_t ret= con->drizzle->event_watch_fn(con, con->events,
2244.1.1 by Monty Taylor
Split libdrizzle into 1.0 and 2.0. Applied the C++ changes to 2.0 branch.
136
                                      con->drizzle->event_watch_context);
137
    if (ret != DRIZZLE_RETURN_OK)
138
    {
139
      drizzle_con_close(con);
140
      return ret;
141
    }
142
  }
143
144
  con->events&= (short)~revents;
145
146
  return DRIZZLE_RETURN_OK;
147
}
148
149
drizzle_st *drizzle_con_drizzle(const drizzle_con_st *con)
150
{
151
  return con->drizzle;
152
}
153
154
const char *drizzle_con_error(const drizzle_con_st *con)
155
{
156
  return drizzle_error(con->drizzle);
157
}
158
159
int drizzle_con_errno(const drizzle_con_st *con)
160
{
161
  return drizzle_errno(con->drizzle);
162
}
163
164
uint16_t drizzle_con_error_code(const drizzle_con_st *con)
165
{
166
  return drizzle_error_code(con->drizzle);
167
}
168
169
const char *drizzle_con_sqlstate(const drizzle_con_st *con)
170
{
171
  return drizzle_sqlstate(con->drizzle);
172
}
173
174
int drizzle_con_options(const drizzle_con_st *con)
175
{
176
  return con->options;
177
}
178
2463.1.4 by Brian Aker
Remove con from being passed object.
179
void drizzle_con_set_options(drizzle_con_st *con, int options)
2244.1.1 by Monty Taylor
Split libdrizzle into 1.0 and 2.0. Applied the C++ changes to 2.0 branch.
180
{
181
  con->options= options;
182
}
183
2463.1.4 by Brian Aker
Remove con from being passed object.
184
void drizzle_con_add_options(drizzle_con_st *con, int options)
2244.1.1 by Monty Taylor
Split libdrizzle into 1.0 and 2.0. Applied the C++ changes to 2.0 branch.
185
{
186
  con->options|= options;
187
188
  /* If asking for the experimental Drizzle protocol, clean the MySQL flag. */
189
  if (con->options & DRIZZLE_CON_EXPERIMENTAL)
2463.1.4 by Brian Aker
Remove con from being passed object.
190
  {
2244.1.1 by Monty Taylor
Split libdrizzle into 1.0 and 2.0. Applied the C++ changes to 2.0 branch.
191
    con->options&= ~DRIZZLE_CON_MYSQL;
2463.1.4 by Brian Aker
Remove con from being passed object.
192
  }
2244.1.1 by Monty Taylor
Split libdrizzle into 1.0 and 2.0. Applied the C++ changes to 2.0 branch.
193
}
194
2463.1.4 by Brian Aker
Remove con from being passed object.
195
void drizzle_con_remove_options(drizzle_con_st *con, int options)
2244.1.1 by Monty Taylor
Split libdrizzle into 1.0 and 2.0. Applied the C++ changes to 2.0 branch.
196
{
197
  con->options&= ~options;
198
}
199
200
const char *drizzle_con_host(const drizzle_con_st *con)
201
{
2463.1.4 by Brian Aker
Remove con from being passed object.
202
  if (con == NULL)
203
  {
204
    return NULL;
205
  }
206
2244.1.1 by Monty Taylor
Split libdrizzle into 1.0 and 2.0. Applied the C++ changes to 2.0 branch.
207
  if (con->socket_type == DRIZZLE_CON_SOCKET_TCP)
208
  {
209
    if (con->socket.tcp.host == NULL && !(con->options & DRIZZLE_CON_LISTEN))
2463.1.4 by Brian Aker
Remove con from being passed object.
210
    {
2244.1.1 by Monty Taylor
Split libdrizzle into 1.0 and 2.0. Applied the C++ changes to 2.0 branch.
211
      return DRIZZLE_DEFAULT_TCP_HOST;
2463.1.4 by Brian Aker
Remove con from being passed object.
212
    }
2244.1.1 by Monty Taylor
Split libdrizzle into 1.0 and 2.0. Applied the C++ changes to 2.0 branch.
213
214
    return con->socket.tcp.host;
215
  }
216
217
  return NULL;
218
}
219
220
in_port_t drizzle_con_port(const drizzle_con_st *con)
221
{
222
  if (con->socket_type == DRIZZLE_CON_SOCKET_TCP)
223
  {
224
    if (con->socket.tcp.port != 0)
225
      return con->socket.tcp.port;
226
227
    if (con->options & DRIZZLE_CON_MYSQL)
228
      return DRIZZLE_DEFAULT_TCP_PORT_MYSQL;
229
230
    return DRIZZLE_DEFAULT_TCP_PORT;
231
  }
232
233
  return 0;
234
}
235
236
void drizzle_con_set_tcp(drizzle_con_st *con, const char *host, in_port_t port)
237
{
238
  drizzle_con_reset_addrinfo(con);
239
240
  con->socket_type= DRIZZLE_CON_SOCKET_TCP;
241
242
  if (host == NULL)
2463.1.4 by Brian Aker
Remove con from being passed object.
243
  {
2244.1.1 by Monty Taylor
Split libdrizzle into 1.0 and 2.0. Applied the C++ changes to 2.0 branch.
244
    con->socket.tcp.host= NULL;
2463.1.4 by Brian Aker
Remove con from being passed object.
245
  }
2244.1.1 by Monty Taylor
Split libdrizzle into 1.0 and 2.0. Applied the C++ changes to 2.0 branch.
246
  else
247
  {
248
    con->socket.tcp.host= con->socket.tcp.host_buffer;
249
    strncpy(con->socket.tcp.host, host, NI_MAXHOST);
250
    con->socket.tcp.host[NI_MAXHOST - 1]= 0;
251
  }
252
253
  con->socket.tcp.port= port;
254
}
255
256
const char *drizzle_con_user(const drizzle_con_st *con)
257
{
2463.1.4 by Brian Aker
Remove con from being passed object.
258
  if (con == NULL)
259
  {
260
    return NULL;
261
  }
262
2244.1.1 by Monty Taylor
Split libdrizzle into 1.0 and 2.0. Applied the C++ changes to 2.0 branch.
263
  return con->user;
264
}
265
266
const char *drizzle_con_password(const drizzle_con_st *con)
267
{
2463.1.4 by Brian Aker
Remove con from being passed object.
268
  if (con == NULL)
269
  {
270
    return NULL;
271
  }
272
2244.1.1 by Monty Taylor
Split libdrizzle into 1.0 and 2.0. Applied the C++ changes to 2.0 branch.
273
  return con->password;
274
}
275
2463.1.4 by Brian Aker
Remove con from being passed object.
276
void drizzle_con_set_auth(drizzle_con_st *con, const char *user, const char *password)
2244.1.1 by Monty Taylor
Split libdrizzle into 1.0 and 2.0. Applied the C++ changes to 2.0 branch.
277
{
2463.1.4 by Brian Aker
Remove con from being passed object.
278
  if (con == NULL)
279
  {
280
    return;
281
  }
282
2244.1.1 by Monty Taylor
Split libdrizzle into 1.0 and 2.0. Applied the C++ changes to 2.0 branch.
283
  if (user == NULL)
2463.1.4 by Brian Aker
Remove con from being passed object.
284
  {
2244.1.1 by Monty Taylor
Split libdrizzle into 1.0 and 2.0. Applied the C++ changes to 2.0 branch.
285
    con->user[0]= 0;
2463.1.4 by Brian Aker
Remove con from being passed object.
286
  }
2244.1.1 by Monty Taylor
Split libdrizzle into 1.0 and 2.0. Applied the C++ changes to 2.0 branch.
287
  else
288
  {
289
    strncpy(con->user, user, DRIZZLE_MAX_USER_SIZE);
290
    con->user[DRIZZLE_MAX_USER_SIZE - 1]= 0;
291
  }
292
293
  if (password == NULL)
2461.1.1 by Brian Aker
Fix safety issues around calling API with no check for NULL
294
  {
2244.1.1 by Monty Taylor
Split libdrizzle into 1.0 and 2.0. Applied the C++ changes to 2.0 branch.
295
    con->password[0]= 0;
2461.1.1 by Brian Aker
Fix safety issues around calling API with no check for NULL
296
  }
2244.1.1 by Monty Taylor
Split libdrizzle into 1.0 and 2.0. Applied the C++ changes to 2.0 branch.
297
  else
298
  {
299
    strncpy(con->password, password, DRIZZLE_MAX_PASSWORD_SIZE);
300
    con->password[DRIZZLE_MAX_PASSWORD_SIZE - 1]= 0;
301
  }
302
}
303
2461.1.1 by Brian Aker
Fix safety issues around calling API with no check for NULL
304
const char *drizzle_con_schema(const drizzle_con_st *con)
305
{
306
  if (con == NULL)
307
  {
308
    return NULL;
309
  }
310
311
  return con->schema;
312
}
313
2244.1.1 by Monty Taylor
Split libdrizzle into 1.0 and 2.0. Applied the C++ changes to 2.0 branch.
314
const char *drizzle_con_db(const drizzle_con_st *con)
315
{
2461.1.1 by Brian Aker
Fix safety issues around calling API with no check for NULL
316
  return drizzle_con_schema(con);
2244.1.1 by Monty Taylor
Split libdrizzle into 1.0 and 2.0. Applied the C++ changes to 2.0 branch.
317
}
318
2461.1.1 by Brian Aker
Fix safety issues around calling API with no check for NULL
319
void drizzle_con_set_schema(drizzle_con_st *con, const char *schema)
2244.1.1 by Monty Taylor
Split libdrizzle into 1.0 and 2.0. Applied the C++ changes to 2.0 branch.
320
{
2461.1.1 by Brian Aker
Fix safety issues around calling API with no check for NULL
321
  if (con == NULL)
322
  {
323
    return;
324
  }
325
326
  if (schema == NULL)
327
  {
328
    con->schema[0]= 0;
329
  }
2244.1.1 by Monty Taylor
Split libdrizzle into 1.0 and 2.0. Applied the C++ changes to 2.0 branch.
330
  else
331
  {
2461.1.1 by Brian Aker
Fix safety issues around calling API with no check for NULL
332
    strncpy(con->schema, schema, DRIZZLE_MAX_DB_SIZE);
333
    con->schema[DRIZZLE_MAX_DB_SIZE - 1]= 0;
2244.1.1 by Monty Taylor
Split libdrizzle into 1.0 and 2.0. Applied the C++ changes to 2.0 branch.
334
  }
335
}
336
2461.1.1 by Brian Aker
Fix safety issues around calling API with no check for NULL
337
void drizzle_con_set_db(drizzle_con_st *con, const char *schema)
338
{
339
  drizzle_con_set_schema(con, schema);
340
}
341
2244.1.1 by Monty Taylor
Split libdrizzle into 1.0 and 2.0. Applied the C++ changes to 2.0 branch.
342
void *drizzle_con_context(const drizzle_con_st *con)
343
{
2461.1.1 by Brian Aker
Fix safety issues around calling API with no check for NULL
344
  if (con == NULL)
345
  {
346
    return NULL;
347
  }
348
2244.1.1 by Monty Taylor
Split libdrizzle into 1.0 and 2.0. Applied the C++ changes to 2.0 branch.
349
  return con->context;
350
}
351
352
void drizzle_con_set_context(drizzle_con_st *con, void *context)
353
{
2461.1.1 by Brian Aker
Fix safety issues around calling API with no check for NULL
354
  if (con == NULL)
355
  {
356
    return;
357
  }
358
2244.1.1 by Monty Taylor
Split libdrizzle into 1.0 and 2.0. Applied the C++ changes to 2.0 branch.
359
  con->context= context;
360
}
361
362
void drizzle_con_set_context_free_fn(drizzle_con_st *con,
363
                                     drizzle_con_context_free_fn *function)
364
{
2461.1.1 by Brian Aker
Fix safety issues around calling API with no check for NULL
365
  if (con == NULL)
366
  {
367
    return;
368
  }
369
2244.1.1 by Monty Taylor
Split libdrizzle into 1.0 and 2.0. Applied the C++ changes to 2.0 branch.
370
  con->context_free_fn= function;
371
}
372
373
uint8_t drizzle_con_protocol_version(const drizzle_con_st *con)
374
{
2461.1.1 by Brian Aker
Fix safety issues around calling API with no check for NULL
375
  if (con == NULL)
376
  {
377
    return 0;
378
  }
379
2244.1.1 by Monty Taylor
Split libdrizzle into 1.0 and 2.0. Applied the C++ changes to 2.0 branch.
380
  return con->protocol_version;
381
}
382
383
const char *drizzle_con_server_version(const drizzle_con_st *con)
384
{
2461.1.1 by Brian Aker
Fix safety issues around calling API with no check for NULL
385
  if (con == NULL)
386
  {
387
    return NULL;
388
  }
389
2244.1.1 by Monty Taylor
Split libdrizzle into 1.0 and 2.0. Applied the C++ changes to 2.0 branch.
390
  return con->server_version;
391
}
392
393
uint32_t drizzle_con_server_version_number(const drizzle_con_st *con)
394
{
2463.1.4 by Brian Aker
Remove con from being passed object.
395
  if (con == NULL or con->server_version)
2461.1.1 by Brian Aker
Fix safety issues around calling API with no check for NULL
396
  {
397
    return 0;
398
  }
399
400
  const char *current= con->server_version;
401
2244.1.1 by Monty Taylor
Split libdrizzle into 1.0 and 2.0. Applied the C++ changes to 2.0 branch.
402
  char *end;
2461.1.1 by Brian Aker
Fix safety issues around calling API with no check for NULL
403
  uint32_t major= (uint32_t)strtoul(current, &end, 10);
404
  current= end + 1;
405
406
  uint32_t minor= (uint32_t)strtoul(current, &end, 10);
407
  current= end + 1;
408
409
  uint32_t version= (uint32_t)strtoul(current, &end, 10);
2244.1.1 by Monty Taylor
Split libdrizzle into 1.0 and 2.0. Applied the C++ changes to 2.0 branch.
410
411
  return (major * 10000) + (minor * 100) + version;
412
}
413
414
uint32_t drizzle_con_thread_id(const drizzle_con_st *con)
415
{
2461.1.1 by Brian Aker
Fix safety issues around calling API with no check for NULL
416
  if (con == NULL)
417
  {
418
    return 0;
419
  }
420
2244.1.1 by Monty Taylor
Split libdrizzle into 1.0 and 2.0. Applied the C++ changes to 2.0 branch.
421
  return con->thread_id;
422
}
423
424
const uint8_t *drizzle_con_scramble(const drizzle_con_st *con)
425
{
2461.1.1 by Brian Aker
Fix safety issues around calling API with no check for NULL
426
  if (con == NULL)
427
  {
428
    return 0;
429
  }
430
2244.1.1 by Monty Taylor
Split libdrizzle into 1.0 and 2.0. Applied the C++ changes to 2.0 branch.
431
  return con->scramble;
432
}
433
434
int drizzle_con_capabilities(const drizzle_con_st *con)
435
{
2461.1.1 by Brian Aker
Fix safety issues around calling API with no check for NULL
436
  if (con == NULL)
437
  {
438
    return 0;
439
  }
440
2244.1.1 by Monty Taylor
Split libdrizzle into 1.0 and 2.0. Applied the C++ changes to 2.0 branch.
441
  return con->capabilities;
442
}
443
444
drizzle_charset_t drizzle_con_charset(const drizzle_con_st *con)
445
{
2461.1.1 by Brian Aker
Fix safety issues around calling API with no check for NULL
446
  if (con == NULL)
447
  {
448
    return drizzle_charset_t();
449
  }
450
2244.1.1 by Monty Taylor
Split libdrizzle into 1.0 and 2.0. Applied the C++ changes to 2.0 branch.
451
  return con->charset;
452
}
453
454
drizzle_con_status_t drizzle_con_status(const drizzle_con_st *con)
455
{
2461.1.1 by Brian Aker
Fix safety issues around calling API with no check for NULL
456
  if (con == NULL)
457
  {
458
    return drizzle_con_status_t();
459
  }
460
2244.1.1 by Monty Taylor
Split libdrizzle into 1.0 and 2.0. Applied the C++ changes to 2.0 branch.
461
  return con->status;
462
}
463
464
uint32_t drizzle_con_max_packet_size(const drizzle_con_st *con)
465
{
2461.1.1 by Brian Aker
Fix safety issues around calling API with no check for NULL
466
  if (con == NULL)
467
  {
468
    return 0;
469
  }
470
2244.1.1 by Monty Taylor
Split libdrizzle into 1.0 and 2.0. Applied the C++ changes to 2.0 branch.
471
  return con->max_packet_size;
472
}
473
474
/*
475
 * Client Definitions
476
 */
477
478
drizzle_return_t drizzle_con_connect(drizzle_con_st *con)
479
{
2461.1.1 by Brian Aker
Fix safety issues around calling API with no check for NULL
480
  if (con == NULL)
481
  {
482
    return DRIZZLE_RETURN_INVALID_ARGUMENT;
483
  }
484
2244.1.1 by Monty Taylor
Split libdrizzle into 1.0 and 2.0. Applied the C++ changes to 2.0 branch.
485
  if (con->options & DRIZZLE_CON_READY)
2461.1.1 by Brian Aker
Fix safety issues around calling API with no check for NULL
486
  {
2244.1.1 by Monty Taylor
Split libdrizzle into 1.0 and 2.0. Applied the C++ changes to 2.0 branch.
487
    return DRIZZLE_RETURN_OK;
2461.1.1 by Brian Aker
Fix safety issues around calling API with no check for NULL
488
  }
2244.1.1 by Monty Taylor
Split libdrizzle into 1.0 and 2.0. Applied the C++ changes to 2.0 branch.
489
490
  if (drizzle_state_none(con))
491
  {
492
    if (!(con->options & DRIZZLE_CON_RAW_PACKET))
493
    {
494
      drizzle_state_push(con, drizzle_state_handshake_server_read);
495
      drizzle_state_push(con, drizzle_state_packet_read);
496
    }
497
498
    drizzle_state_push(con, drizzle_state_connect);
499
    drizzle_state_push(con, drizzle_state_addrinfo);
500
  }
501
502
  return drizzle_state_loop(con);
503
}
504
505
drizzle_result_st *drizzle_con_quit(drizzle_con_st *con,
506
                                    drizzle_result_st *result,
507
                                    drizzle_return_t *ret_ptr)
508
{
509
  return drizzle_con_command_write(con, result, DRIZZLE_COMMAND_QUIT, NULL, 0,
510
                                   0, ret_ptr);
511
}
512
513
drizzle_result_st *drizzle_quit(drizzle_con_st *con,
514
                                drizzle_result_st *result,
515
                                drizzle_return_t *ret_ptr)
516
{
517
  return drizzle_con_quit(con, result, ret_ptr);
518
}
519
520
drizzle_result_st *drizzle_con_select_db(drizzle_con_st *con,
521
                                         drizzle_result_st *result,
522
                                         const char *db,
523
                                         drizzle_return_t *ret_ptr)
524
{
525
  drizzle_con_set_db(con, db);
526
  return drizzle_con_command_write(con, result, DRIZZLE_COMMAND_INIT_DB,
527
                                   db, strlen(db), strlen(db), ret_ptr);
528
}
529
530
drizzle_result_st *drizzle_select_db(drizzle_con_st *con,
531
                                     drizzle_result_st *result,
532
                                     const char *db,
533
                                     drizzle_return_t *ret_ptr)
534
{
535
  return drizzle_con_select_db(con, result, db, ret_ptr);
536
}
537
538
drizzle_result_st *drizzle_con_shutdown(drizzle_con_st *con,
539
                                        drizzle_result_st *result,
540
                                        drizzle_return_t *ret_ptr)
541
{
2461.1.1 by Brian Aker
Fix safety issues around calling API with no check for NULL
542
  if (con == NULL)
543
  {
544
    return NULL;
545
  }
546
2244.1.1 by Monty Taylor
Split libdrizzle into 1.0 and 2.0. Applied the C++ changes to 2.0 branch.
547
  if (con->options & DRIZZLE_CON_MYSQL)
548
  {
549
    return drizzle_con_command_write(con, result, DRIZZLE_COMMAND_SHUTDOWN,
550
                                     "0", 1, 1, ret_ptr);
551
  }
552
553
  return drizzle_con_command_write(con, result, DRIZZLE_COMMAND_SHUTDOWN, NULL,
554
                                   0, 0, ret_ptr);
555
}
556
557
drizzle_result_st *drizzle_shutdown(drizzle_con_st *con,
2461.1.1 by Brian Aker
Fix safety issues around calling API with no check for NULL
558
                                    drizzle_result_st *result, uint32_t,
2244.1.1 by Monty Taylor
Split libdrizzle into 1.0 and 2.0. Applied the C++ changes to 2.0 branch.
559
                                    drizzle_return_t *ret_ptr)
560
{
561
  return drizzle_con_shutdown(con, result, ret_ptr);
562
}
563
564
drizzle_result_st *drizzle_kill(drizzle_con_st *con,
565
                                drizzle_result_st *result,
566
                                uint32_t query_id,
567
                                drizzle_return_t *ret_ptr)
568
{
569
  uint32_t sent= htonl(query_id);
570
  return drizzle_con_command_write(con, result, DRIZZLE_COMMAND_PROCESS_KILL,
571
                                   &sent, sizeof(uint32_t), sizeof(uint32_t), ret_ptr);
572
}
573
574
drizzle_result_st *drizzle_con_ping(drizzle_con_st *con,
575
                                    drizzle_result_st *result,
576
                                    drizzle_return_t *ret_ptr)
577
{
578
  return drizzle_con_command_write(con, result, DRIZZLE_COMMAND_PING, NULL, 0,
579
                                   0, ret_ptr);
580
}
581
582
drizzle_result_st *drizzle_ping(drizzle_con_st *con,
583
                                drizzle_result_st *result,
584
                                drizzle_return_t *ret_ptr)
585
{
586
  return drizzle_con_ping(con, result, ret_ptr);
587
}
588
589
drizzle_result_st *drizzle_con_command_write(drizzle_con_st *con,
590
                                             drizzle_result_st *result,
591
                                             drizzle_command_t command,
592
                                             const void *data, size_t size,
593
                                             size_t total,
594
                                             drizzle_return_t *ret_ptr)
595
{
2461.1.1 by Brian Aker
Fix safety issues around calling API with no check for NULL
596
  if (con == NULL)
597
  {
598
    return NULL;
599
  }
2244.1.1 by Monty Taylor
Split libdrizzle into 1.0 and 2.0. Applied the C++ changes to 2.0 branch.
600
2449.1.4 by Brian Aker
Complete update of libdrizzle
601
  drizzle_return_t unused;
602
  if (ret_ptr == NULL)
603
  {
604
    ret_ptr= &unused;
605
  }
606
2461.1.1 by Brian Aker
Fix safety issues around calling API with no check for NULL
607
  if ((con->options & DRIZZLE_CON_READY) == 0)
2244.1.1 by Monty Taylor
Split libdrizzle into 1.0 and 2.0. Applied the C++ changes to 2.0 branch.
608
  {
609
    if (con->options & DRIZZLE_CON_RAW_PACKET)
610
    {
2461.1.1 by Brian Aker
Fix safety issues around calling API with no check for NULL
611
      drizzle_set_error(con->drizzle, "drizzle_command_write", "connection not ready");
2244.1.1 by Monty Taylor
Split libdrizzle into 1.0 and 2.0. Applied the C++ changes to 2.0 branch.
612
      *ret_ptr= DRIZZLE_RETURN_NOT_READY;
2461.1.2 by Brian Aker
Pass through refactoring.
613
      return NULL;
2244.1.1 by Monty Taylor
Split libdrizzle into 1.0 and 2.0. Applied the C++ changes to 2.0 branch.
614
    }
615
616
    *ret_ptr= drizzle_con_connect(con);
617
    if (*ret_ptr != DRIZZLE_RETURN_OK)
2449.1.4 by Brian Aker
Complete update of libdrizzle
618
    {
2461.1.2 by Brian Aker
Pass through refactoring.
619
      return NULL;
2449.1.4 by Brian Aker
Complete update of libdrizzle
620
    }
2244.1.1 by Monty Taylor
Split libdrizzle into 1.0 and 2.0. Applied the C++ changes to 2.0 branch.
621
  }
622
623
  if (drizzle_state_none(con))
624
  {
625
    if (con->options & (DRIZZLE_CON_RAW_PACKET | DRIZZLE_CON_NO_RESULT_READ))
2449.1.4 by Brian Aker
Complete update of libdrizzle
626
    {
2244.1.1 by Monty Taylor
Split libdrizzle into 1.0 and 2.0. Applied the C++ changes to 2.0 branch.
627
      con->result= NULL;
2449.1.4 by Brian Aker
Complete update of libdrizzle
628
    }
2244.1.1 by Monty Taylor
Split libdrizzle into 1.0 and 2.0. Applied the C++ changes to 2.0 branch.
629
    else
630
    {
2461.1.1 by Brian Aker
Fix safety issues around calling API with no check for NULL
631
      for (drizzle_result_st *old_result= con->result_list; old_result != NULL; old_result= old_result->next)
2244.1.1 by Monty Taylor
Split libdrizzle into 1.0 and 2.0. Applied the C++ changes to 2.0 branch.
632
      {
633
        if (result == old_result)
634
        {
635
          drizzle_set_error(con->drizzle, "drizzle_command_write", "result struct already in use");
636
          *ret_ptr= DRIZZLE_RETURN_INTERNAL_ERROR;
2461.1.2 by Brian Aker
Pass through refactoring.
637
          return NULL;
2244.1.1 by Monty Taylor
Split libdrizzle into 1.0 and 2.0. Applied the C++ changes to 2.0 branch.
638
        }
639
      }
640
2463.1.5 by Brian Aker
Move result over to being behind API.
641
      con->result= drizzle_result_create_with(con, result);
2244.1.1 by Monty Taylor
Split libdrizzle into 1.0 and 2.0. Applied the C++ changes to 2.0 branch.
642
      if (con->result == NULL)
643
      {
644
        *ret_ptr= DRIZZLE_RETURN_MEMORY;
645
        return NULL;
646
      }
647
    }
648
649
    con->command= command;
650
    con->command_data= (uint8_t *)data;
651
    con->command_size= size;
652
    con->command_offset= 0;
653
    con->command_total= total;
654
655
    drizzle_state_push(con, drizzle_state_command_write);
656
  }
657
  else if (con->command_data == NULL)
658
  {
659
    con->command_data= (uint8_t *)data;
660
    con->command_size= size;
661
  }
662
663
  *ret_ptr= drizzle_state_loop(con);
664
  if (*ret_ptr == DRIZZLE_RETURN_PAUSE)
2461.1.1 by Brian Aker
Fix safety issues around calling API with no check for NULL
665
  {
2244.1.1 by Monty Taylor
Split libdrizzle into 1.0 and 2.0. Applied the C++ changes to 2.0 branch.
666
    *ret_ptr= DRIZZLE_RETURN_OK;
2461.1.1 by Brian Aker
Fix safety issues around calling API with no check for NULL
667
  }
2244.1.1 by Monty Taylor
Split libdrizzle into 1.0 and 2.0. Applied the C++ changes to 2.0 branch.
668
  else if (*ret_ptr != DRIZZLE_RETURN_OK &&
669
           *ret_ptr != DRIZZLE_RETURN_IO_WAIT &&
670
           *ret_ptr != DRIZZLE_RETURN_ERROR_CODE)
671
  {
672
    drizzle_result_free(con->result);
673
    con->result= result;
674
  }
675
676
  return con->result;
677
}
678
679
/*
680
 * Server Definitions
681
 */
682
683
drizzle_return_t drizzle_con_listen(drizzle_con_st *con)
684
{
2461.1.1 by Brian Aker
Fix safety issues around calling API with no check for NULL
685
  if (con == NULL)
686
  {
687
    return DRIZZLE_RETURN_INVALID_ARGUMENT;
688
  }
689
2244.1.1 by Monty Taylor
Split libdrizzle into 1.0 and 2.0. Applied the C++ changes to 2.0 branch.
690
  if (con->options & DRIZZLE_CON_READY)
2461.1.1 by Brian Aker
Fix safety issues around calling API with no check for NULL
691
  {
2244.1.1 by Monty Taylor
Split libdrizzle into 1.0 and 2.0. Applied the C++ changes to 2.0 branch.
692
    return DRIZZLE_RETURN_OK;
2461.1.1 by Brian Aker
Fix safety issues around calling API with no check for NULL
693
  }
2244.1.1 by Monty Taylor
Split libdrizzle into 1.0 and 2.0. Applied the C++ changes to 2.0 branch.
694
695
  if (drizzle_state_none(con))
696
  {
697
    drizzle_state_push(con, drizzle_state_listen);
698
    drizzle_state_push(con, drizzle_state_addrinfo);
699
  }
700
701
  return drizzle_state_loop(con);
702
}
703
704
int drizzle_con_backlog(const drizzle_con_st *con)
705
{
2461.1.1 by Brian Aker
Fix safety issues around calling API with no check for NULL
706
  if (con == NULL)
707
  {
708
    return 0;
709
  }
710
2244.1.1 by Monty Taylor
Split libdrizzle into 1.0 and 2.0. Applied the C++ changes to 2.0 branch.
711
  return con->backlog;
712
}
713
714
void drizzle_con_set_backlog(drizzle_con_st *con, int backlog)
715
{
2461.1.1 by Brian Aker
Fix safety issues around calling API with no check for NULL
716
  if (con == NULL)
717
  {
718
    return;
719
  }
720
2244.1.1 by Monty Taylor
Split libdrizzle into 1.0 and 2.0. Applied the C++ changes to 2.0 branch.
721
  con->backlog= backlog;
722
}
723
2461.1.2 by Brian Aker
Pass through refactoring.
724
void drizzle_con_set_protocol_version(drizzle_con_st *con, uint8_t protocol_version)
2244.1.1 by Monty Taylor
Split libdrizzle into 1.0 and 2.0. Applied the C++ changes to 2.0 branch.
725
{
2461.1.1 by Brian Aker
Fix safety issues around calling API with no check for NULL
726
  if (con == NULL)
727
  {
728
    return;
729
  }
730
2244.1.1 by Monty Taylor
Split libdrizzle into 1.0 and 2.0. Applied the C++ changes to 2.0 branch.
731
  con->protocol_version= protocol_version;
732
}
733
734
void drizzle_con_set_server_version(drizzle_con_st *con,
735
                                    const char *server_version)
736
{
2461.1.1 by Brian Aker
Fix safety issues around calling API with no check for NULL
737
  if (con == NULL)
738
  {
739
    return;
740
  }
741
2244.1.1 by Monty Taylor
Split libdrizzle into 1.0 and 2.0. Applied the C++ changes to 2.0 branch.
742
  if (server_version == NULL)
2461.1.1 by Brian Aker
Fix safety issues around calling API with no check for NULL
743
  {
2244.1.1 by Monty Taylor
Split libdrizzle into 1.0 and 2.0. Applied the C++ changes to 2.0 branch.
744
    con->server_version[0]= 0;
2461.1.1 by Brian Aker
Fix safety issues around calling API with no check for NULL
745
  }
2244.1.1 by Monty Taylor
Split libdrizzle into 1.0 and 2.0. Applied the C++ changes to 2.0 branch.
746
  else
747
  {
748
    strncpy(con->server_version, server_version,
749
            DRIZZLE_MAX_SERVER_VERSION_SIZE);
750
    con->server_version[DRIZZLE_MAX_SERVER_VERSION_SIZE - 1]= 0;
751
  }
752
}
753
754
void drizzle_con_set_thread_id(drizzle_con_st *con, uint32_t thread_id)
755
{
2461.1.1 by Brian Aker
Fix safety issues around calling API with no check for NULL
756
  if (con == NULL)
757
  {
758
    return;
759
  }
760
2244.1.1 by Monty Taylor
Split libdrizzle into 1.0 and 2.0. Applied the C++ changes to 2.0 branch.
761
  con->thread_id= thread_id;
762
}
763
764
void drizzle_con_set_scramble(drizzle_con_st *con, const uint8_t *scramble)
765
{
2461.1.1 by Brian Aker
Fix safety issues around calling API with no check for NULL
766
  if (con == NULL)
767
  {
768
    return;
769
  }
770
2244.1.1 by Monty Taylor
Split libdrizzle into 1.0 and 2.0. Applied the C++ changes to 2.0 branch.
771
  if (scramble == NULL)
2461.1.1 by Brian Aker
Fix safety issues around calling API with no check for NULL
772
  {
2244.1.1 by Monty Taylor
Split libdrizzle into 1.0 and 2.0. Applied the C++ changes to 2.0 branch.
773
    con->scramble= NULL;
2461.1.1 by Brian Aker
Fix safety issues around calling API with no check for NULL
774
  }
2244.1.1 by Monty Taylor
Split libdrizzle into 1.0 and 2.0. Applied the C++ changes to 2.0 branch.
775
  else
776
  {
777
    con->scramble= con->scramble_buffer;
778
    memcpy(con->scramble, scramble, DRIZZLE_MAX_SCRAMBLE_SIZE);
779
  }
780
}
781
782
void drizzle_con_set_capabilities(drizzle_con_st *con,
783
                                  int capabilities)
784
{
2461.1.1 by Brian Aker
Fix safety issues around calling API with no check for NULL
785
  if (con == NULL)
786
  {
787
    return;
788
  }
789
2244.1.1 by Monty Taylor
Split libdrizzle into 1.0 and 2.0. Applied the C++ changes to 2.0 branch.
790
  con->capabilities= capabilities;
791
}
792
793
void drizzle_con_set_charset(drizzle_con_st *con, drizzle_charset_t charset)
794
{
2461.1.1 by Brian Aker
Fix safety issues around calling API with no check for NULL
795
  if (con == NULL)
796
  {
797
    return;
798
  }
799
2244.1.1 by Monty Taylor
Split libdrizzle into 1.0 and 2.0. Applied the C++ changes to 2.0 branch.
800
  con->charset= charset;
801
}
802
803
void drizzle_con_set_status(drizzle_con_st *con, drizzle_con_status_t status)
804
{
2461.1.1 by Brian Aker
Fix safety issues around calling API with no check for NULL
805
  if (con == NULL)
806
  {
807
    return;
808
  }
809
2244.1.1 by Monty Taylor
Split libdrizzle into 1.0 and 2.0. Applied the C++ changes to 2.0 branch.
810
  con->status= status;
811
}
812
813
void drizzle_con_set_max_packet_size(drizzle_con_st *con,
814
                                     uint32_t max_packet_size)
815
{
2461.1.1 by Brian Aker
Fix safety issues around calling API with no check for NULL
816
  if (con == NULL)
817
  {
818
    return;
819
  }
820
2244.1.1 by Monty Taylor
Split libdrizzle into 1.0 and 2.0. Applied the C++ changes to 2.0 branch.
821
  con->max_packet_size= max_packet_size;
822
}
823
824
void drizzle_con_copy_handshake(drizzle_con_st *con, drizzle_con_st *from)
825
{
2461.1.1 by Brian Aker
Fix safety issues around calling API with no check for NULL
826
  if (con == NULL)
827
  {
828
    return;
829
  }
830
2244.1.1 by Monty Taylor
Split libdrizzle into 1.0 and 2.0. Applied the C++ changes to 2.0 branch.
831
  drizzle_con_set_auth(con, from->user, NULL);
832
  drizzle_con_set_scramble(con, from->scramble);
2461.1.1 by Brian Aker
Fix safety issues around calling API with no check for NULL
833
  drizzle_con_set_db(con, from->schema);
2244.1.1 by Monty Taylor
Split libdrizzle into 1.0 and 2.0. Applied the C++ changes to 2.0 branch.
834
  drizzle_con_set_protocol_version(con, from->protocol_version);
835
  drizzle_con_set_server_version(con, from->server_version);
836
  drizzle_con_set_thread_id(con, from->thread_id);
837
  drizzle_con_set_scramble(con, from->scramble);
838
  drizzle_con_set_capabilities(con, from->capabilities);
839
  drizzle_con_set_charset(con, from->charset);
840
  drizzle_con_set_status(con, from->status);
841
  drizzle_con_set_max_packet_size(con, from->max_packet_size);
842
}
843
844
void *drizzle_con_command_read(drizzle_con_st *con,
845
                               drizzle_command_t *command, size_t *offset,
846
                               size_t *size, size_t *total,
847
                               drizzle_return_t *ret_ptr)
848
{
2461.1.1 by Brian Aker
Fix safety issues around calling API with no check for NULL
849
  if (con == NULL)
850
  {
851
    return NULL;
852
  }
853
854
  drizzle_return_t unused;
855
  if (ret_ptr == NULL)
856
  {
857
    ret_ptr= &unused;
858
  }
859
2244.1.1 by Monty Taylor
Split libdrizzle into 1.0 and 2.0. Applied the C++ changes to 2.0 branch.
860
  if (drizzle_state_none(con))
861
  {
862
    con->packet_number= 0;
863
    con->command_offset= 0;
864
    con->command_total= 0;
865
866
    drizzle_state_push(con, drizzle_state_command_read);
867
    drizzle_state_push(con, drizzle_state_packet_read);
868
  }
869
870
  *offset= con->command_offset;
871
872
  *ret_ptr= drizzle_state_loop(con);
873
  if (*ret_ptr == DRIZZLE_RETURN_PAUSE)
874
    *ret_ptr= DRIZZLE_RETURN_OK;
875
876
  *command= con->command;
877
  *size= con->command_size;
878
  *total= con->command_total;
879
880
  return con->command_data;
881
}
882
883
void *drizzle_con_command_buffer(drizzle_con_st *con,
884
                                 drizzle_command_t *command, size_t *total,
885
                                 drizzle_return_t *ret_ptr)
886
{
887
  size_t offset= 0;
888
  size_t size= 0;
889
2461.1.1 by Brian Aker
Fix safety issues around calling API with no check for NULL
890
  if (con == NULL)
891
  {
892
    return NULL;
893
  }
894
895
  drizzle_return_t unused;
896
  if (ret_ptr == NULL)
897
  {
898
    ret_ptr= &unused;
899
  }
900
901
  size_t total_unused;
902
  if (total == NULL)
903
  {
904
    total= &total_unused;
905
  }
906
2244.1.1 by Monty Taylor
Split libdrizzle into 1.0 and 2.0. Applied the C++ changes to 2.0 branch.
907
  uint8_t *command_data=
908
    static_cast<uint8_t *>(drizzle_con_command_read(con, command, &offset,
909
                                                    &size, total, ret_ptr));
910
  if (*ret_ptr != DRIZZLE_RETURN_OK)
2461.1.1 by Brian Aker
Fix safety issues around calling API with no check for NULL
911
  {
2244.1.1 by Monty Taylor
Split libdrizzle into 1.0 and 2.0. Applied the C++ changes to 2.0 branch.
912
    return NULL;
2461.1.1 by Brian Aker
Fix safety issues around calling API with no check for NULL
913
  }
2244.1.1 by Monty Taylor
Split libdrizzle into 1.0 and 2.0. Applied the C++ changes to 2.0 branch.
914
915
  if (command_data == NULL)
916
  {
917
    *total= 0;
918
    return NULL;
919
  }
920
921
  if (con->command_buffer == NULL)
922
  {
2461.1.2 by Brian Aker
Pass through refactoring.
923
    con->command_buffer= new (std::nothrow) uint8_t[(*total) + 1];
924
925
    if (con->command_buffer == NULL)
926
    {
927
      *total= 0;
928
      *ret_ptr= DRIZZLE_RETURN_MEMORY;
929
      return NULL;
930
    }
2244.1.1 by Monty Taylor
Split libdrizzle into 1.0 and 2.0. Applied the C++ changes to 2.0 branch.
931
  }
932
933
  memcpy(con->command_buffer + offset, command_data, size);
934
935
  while ((offset + size) != (*total))
936
  {
937
    command_data= (uint8_t *)drizzle_con_command_read(con, command, &offset,
938
                                                      &size, total, ret_ptr);
939
    if (*ret_ptr != DRIZZLE_RETURN_OK)
2461.1.1 by Brian Aker
Fix safety issues around calling API with no check for NULL
940
    {
2244.1.1 by Monty Taylor
Split libdrizzle into 1.0 and 2.0. Applied the C++ changes to 2.0 branch.
941
      return NULL;
2461.1.1 by Brian Aker
Fix safety issues around calling API with no check for NULL
942
    }
2244.1.1 by Monty Taylor
Split libdrizzle into 1.0 and 2.0. Applied the C++ changes to 2.0 branch.
943
944
    memcpy(con->command_buffer + offset, command_data, size);
945
  }
946
947
  command_data= con->command_buffer;
948
  con->command_buffer= NULL;
949
  command_data[*total]= 0;
950
951
  return command_data;
952
}
953
954
void drizzle_con_command_buffer_free(uint8_t *command_buffer)
955
{
956
  delete[] command_buffer;
957
}
958
959
/*
960
 * Local Definitions
961
 */
962
963
void drizzle_con_reset_addrinfo(drizzle_con_st *con)
964
{
965
  switch (con->socket_type)
966
  {
967
  case DRIZZLE_CON_SOCKET_TCP:
968
    if (con->socket.tcp.addrinfo != NULL)
969
    {
970
      freeaddrinfo(con->socket.tcp.addrinfo);
971
      con->socket.tcp.addrinfo= NULL;
972
    }
973
    break;
974
975
  case DRIZZLE_CON_SOCKET_UDS:
976
    con->socket.uds.addrinfo.ai_addr= NULL;
977
    break;
978
979
  default:
980
    break;
981
  }
982
983
  con->addrinfo_next= NULL;
984
}
985
986
/*
987
 * State Definitions
988
 */
989
990
drizzle_return_t drizzle_state_addrinfo(drizzle_con_st *con)
991
{
992
  drizzle_con_tcp_st *tcp;
993
  const char *host;
994
  char port[NI_MAXSERV];
995
  struct addrinfo ai;
996
  int ret;
997
2461.1.1 by Brian Aker
Fix safety issues around calling API with no check for NULL
998
  if (con == NULL)
999
  {
1000
    return DRIZZLE_RETURN_INVALID_ARGUMENT;
1001
  }
1002
2244.1.1 by Monty Taylor
Split libdrizzle into 1.0 and 2.0. Applied the C++ changes to 2.0 branch.
1003
  drizzle_log_debug(con->drizzle, "drizzle_state_addrinfo");
1004
1005
  switch (con->socket_type)
1006
  {
1007
  case DRIZZLE_CON_SOCKET_TCP:
1008
    tcp= &(con->socket.tcp);
1009
1010
    if (tcp->addrinfo != NULL)
1011
    {
1012
      freeaddrinfo(tcp->addrinfo);
1013
      tcp->addrinfo= NULL;
1014
    }
1015
1016
    if (tcp->port != 0)
2461.1.1 by Brian Aker
Fix safety issues around calling API with no check for NULL
1017
    {
2244.1.1 by Monty Taylor
Split libdrizzle into 1.0 and 2.0. Applied the C++ changes to 2.0 branch.
1018
      snprintf(port, NI_MAXSERV, "%u", tcp->port);
2461.1.1 by Brian Aker
Fix safety issues around calling API with no check for NULL
1019
    }
2244.1.1 by Monty Taylor
Split libdrizzle into 1.0 and 2.0. Applied the C++ changes to 2.0 branch.
1020
    else if (con->options & DRIZZLE_CON_MYSQL)
2461.1.1 by Brian Aker
Fix safety issues around calling API with no check for NULL
1021
    {
2244.1.1 by Monty Taylor
Split libdrizzle into 1.0 and 2.0. Applied the C++ changes to 2.0 branch.
1022
      snprintf(port, NI_MAXSERV, "%u", DRIZZLE_DEFAULT_TCP_PORT_MYSQL);
2461.1.1 by Brian Aker
Fix safety issues around calling API with no check for NULL
1023
    }
2244.1.1 by Monty Taylor
Split libdrizzle into 1.0 and 2.0. Applied the C++ changes to 2.0 branch.
1024
    else
2461.1.1 by Brian Aker
Fix safety issues around calling API with no check for NULL
1025
    {
2244.1.1 by Monty Taylor
Split libdrizzle into 1.0 and 2.0. Applied the C++ changes to 2.0 branch.
1026
      snprintf(port, NI_MAXSERV, "%u", DRIZZLE_DEFAULT_TCP_PORT);
2461.1.1 by Brian Aker
Fix safety issues around calling API with no check for NULL
1027
    }
2269.2.1 by Marc Isambart
Various libdrizzle Windows fixes, including closesocket() instead of close(), snprintf handling and WSAECONNREFUSED mapping
1028
    port[NI_MAXSERV-1]= 0;
2244.1.1 by Monty Taylor
Split libdrizzle into 1.0 and 2.0. Applied the C++ changes to 2.0 branch.
1029
2318.5.6 by Olaf van der Spek
Refactor
1030
    memset(&ai, 0, sizeof(ai));
2244.1.1 by Monty Taylor
Split libdrizzle into 1.0 and 2.0. Applied the C++ changes to 2.0 branch.
1031
    ai.ai_socktype= SOCK_STREAM;
1032
    ai.ai_protocol= IPPROTO_TCP;
1033
    ai.ai_flags = AI_PASSIVE;
1034
    ai.ai_family = AF_UNSPEC;
1035
1036
    if (con->options & DRIZZLE_CON_LISTEN)
1037
    {
1038
      host= tcp->host;
1039
    }
1040
    else
1041
    {
1042
      if (tcp->host == NULL)
1043
        host= DRIZZLE_DEFAULT_TCP_HOST;
1044
      else
1045
        host= tcp->host;
1046
    }
1047
1048
    ret= getaddrinfo(host, port, &ai, &(tcp->addrinfo));
1049
    if (ret != 0)
1050
    {
1051
      drizzle_set_error(con->drizzle, "drizzle_state_addrinfo",
1052
                        "getaddrinfo:%s", gai_strerror(ret));
1053
      return DRIZZLE_RETURN_GETADDRINFO;
1054
    }
1055
1056
    con->addrinfo_next= tcp->addrinfo;
1057
1058
    break;
1059
1060
  case DRIZZLE_CON_SOCKET_UDS:
1061
    con->addrinfo_next= &(con->socket.uds.addrinfo);
1062
    break;
1063
  }
1064
1065
  drizzle_state_pop(con);
1066
  return DRIZZLE_RETURN_OK;
1067
}
1068
1069
drizzle_return_t drizzle_state_connect(drizzle_con_st *con)
1070
{
2463.1.4 by Brian Aker
Remove con from being passed object.
1071
  if (con == NULL)
1072
  {
1073
    return DRIZZLE_RETURN_INVALID_ARGUMENT;
1074
  }
2244.1.1 by Monty Taylor
Split libdrizzle into 1.0 and 2.0. Applied the C++ changes to 2.0 branch.
1075
  drizzle_log_debug(con->drizzle, "drizzle_state_connect");
1076
1077
  if (con->fd != -1)
1078
  {
2269.2.1 by Marc Isambart
Various libdrizzle Windows fixes, including closesocket() instead of close(), snprintf handling and WSAECONNREFUSED mapping
1079
    (void)closesocket(con->fd);
2244.1.1 by Monty Taylor
Split libdrizzle into 1.0 and 2.0. Applied the C++ changes to 2.0 branch.
1080
    con->fd= -1;
1081
  }
1082
1083
  if (con->addrinfo_next == NULL)
1084
  {
1085
    drizzle_set_error(con->drizzle, "drizzle_state_connect",
1086
                      "could not connect");
1087
    drizzle_state_reset(con);
1088
    return DRIZZLE_RETURN_COULD_NOT_CONNECT;
1089
  }
1090
1091
  con->fd= socket(con->addrinfo_next->ai_family,
1092
                  con->addrinfo_next->ai_socktype,
1093
                  con->addrinfo_next->ai_protocol);
1094
  if (con->fd == -1)
1095
  {
1096
    drizzle_set_error(con->drizzle, "drizzle_state_connect", "socket:%d",
1097
                      errno);
1098
    con->drizzle->last_errno= errno;
1099
    return DRIZZLE_RETURN_ERRNO;
1100
  }
1101
2318.5.27 by Olaf van der Spek
Refactor
1102
  drizzle_return_t dret= _con_setsockopt(con);
2244.1.1 by Monty Taylor
Split libdrizzle into 1.0 and 2.0. Applied the C++ changes to 2.0 branch.
1103
  if (dret != DRIZZLE_RETURN_OK)
1104
  {
1105
    con->drizzle->last_errno= errno;
1106
    return dret;
1107
  }
1108
1109
  while (1)
1110
  {
2318.5.27 by Olaf van der Spek
Refactor
1111
    int ret= connect(con->fd, con->addrinfo_next->ai_addr, con->addrinfo_next->ai_addrlen);
2244.1.1 by Monty Taylor
Split libdrizzle into 1.0 and 2.0. Applied the C++ changes to 2.0 branch.
1112
1113
#ifdef _WIN32
2263.4.1 by Monty Taylor
Updated the windows/posix error mapping as per notes from Marc Isambart.
1114
    errno = WSAGetLastError();
1115
    switch(errno) {
1116
    case WSAEINVAL:
1117
    case WSAEALREADY:
1118
    case WSAEWOULDBLOCK:
1119
      errno= EINPROGRESS;
1120
      break;
2269.2.1 by Marc Isambart
Various libdrizzle Windows fixes, including closesocket() instead of close(), snprintf handling and WSAECONNREFUSED mapping
1121
    case WSAECONNREFUSED:
1122
      errno= ECONNREFUSED;
1123
      break;
2263.4.1 by Monty Taylor
Updated the windows/posix error mapping as per notes from Marc Isambart.
1124
    case WSAENETUNREACH:
1125
      errno= ENETUNREACH;
1126
      break;
1127
    case WSAETIMEDOUT:
1128
      errno= ETIMEDOUT;
1129
      break;
1130
    case WSAECONNRESET:
1131
      errno= ECONNRESET;
1132
      break;
1133
    case WSAEADDRINUSE:
1134
      errno= EADDRINUSE;
1135
      break;
1136
    case WSAEOPNOTSUPP:
1137
      errno= EOPNOTSUPP;
1138
      break;
1139
    case WSAENOPROTOOPT:
1140
      errno= ENOPROTOOPT;
1141
      break;
1142
    default:
1143
      break;
1144
    }
2244.1.1 by Monty Taylor
Split libdrizzle into 1.0 and 2.0. Applied the C++ changes to 2.0 branch.
1145
#endif /* _WIN32 */
1146
	
1147
    drizzle_log_crazy(con->drizzle, "connect return=%d errno=%d", ret, errno);
1148
1149
    if (ret == 0)
1150
    {
1151
      con->addrinfo_next= NULL;
1152
      break;
1153
    }
1154
1155
    if (errno == EAGAIN || errno == EINTR)
1156
      continue;
1157
1158
    if (errno == EINPROGRESS)
1159
    {
1160
      drizzle_state_pop(con);
1161
      drizzle_state_push(con, drizzle_state_connecting);
1162
      return DRIZZLE_RETURN_OK;
1163
    }
1164
1165
    if (errno == ECONNREFUSED || errno == ENETUNREACH || errno == ETIMEDOUT)
1166
    {
1167
      con->addrinfo_next= con->addrinfo_next->ai_next;
1168
      return DRIZZLE_RETURN_OK;
1169
    }
1170
1171
    drizzle_set_error(con->drizzle, "drizzle_state_connect", "connect:%d",
1172
                      errno);
1173
    con->drizzle->last_errno= errno;
1174
    return DRIZZLE_RETURN_ERRNO;
1175
  }
1176
1177
  drizzle_state_pop(con);
1178
  return DRIZZLE_RETURN_OK;
1179
}
1180
1181
drizzle_return_t drizzle_state_connecting(drizzle_con_st *con)
1182
{
2463.1.4 by Brian Aker
Remove con from being passed object.
1183
  if (con == NULL)
1184
  {
1185
    return DRIZZLE_RETURN_INVALID_ARGUMENT;
1186
  }
2244.1.1 by Monty Taylor
Split libdrizzle into 1.0 and 2.0. Applied the C++ changes to 2.0 branch.
1187
  drizzle_log_debug(con->drizzle, "drizzle_state_connecting");
1188
1189
  while (1)
1190
  {
1191
    if (con->revents & POLLOUT)
1192
    {
1193
      drizzle_state_pop(con);
1194
      return DRIZZLE_RETURN_OK;
1195
    }
1196
    else if (con->revents & (POLLERR | POLLHUP | POLLNVAL))
1197
    {
1198
      con->revents= 0;
1199
      drizzle_state_pop(con);
1200
      drizzle_state_push(con, drizzle_state_connect);
1201
      con->addrinfo_next= con->addrinfo_next->ai_next;
1202
      return DRIZZLE_RETURN_OK;
1203
    }
1204
2318.5.27 by Olaf van der Spek
Refactor
1205
    drizzle_return_t ret= drizzle_con_set_events(con, POLLOUT);
2244.1.1 by Monty Taylor
Split libdrizzle into 1.0 and 2.0. Applied the C++ changes to 2.0 branch.
1206
    if (ret != DRIZZLE_RETURN_OK)
1207
      return ret;
1208
2461.1.2 by Brian Aker
Pass through refactoring.
1209
    if (con->drizzle->options.is_non_blocking)
1210
    {
2244.1.1 by Monty Taylor
Split libdrizzle into 1.0 and 2.0. Applied the C++ changes to 2.0 branch.
1211
      return DRIZZLE_RETURN_IO_WAIT;
2461.1.2 by Brian Aker
Pass through refactoring.
1212
    }
2244.1.1 by Monty Taylor
Split libdrizzle into 1.0 and 2.0. Applied the C++ changes to 2.0 branch.
1213
1214
    ret= drizzle_con_wait(con->drizzle);
1215
    if (ret != DRIZZLE_RETURN_OK)
2461.1.2 by Brian Aker
Pass through refactoring.
1216
    {
2244.1.1 by Monty Taylor
Split libdrizzle into 1.0 and 2.0. Applied the C++ changes to 2.0 branch.
1217
      return ret;
2461.1.2 by Brian Aker
Pass through refactoring.
1218
    }
2244.1.1 by Monty Taylor
Split libdrizzle into 1.0 and 2.0. Applied the C++ changes to 2.0 branch.
1219
  }
1220
}
1221
1222
drizzle_return_t drizzle_state_read(drizzle_con_st *con)
1223
{
2463.1.4 by Brian Aker
Remove con from being passed object.
1224
  if (con == NULL)
1225
  {
1226
    return DRIZZLE_RETURN_INVALID_ARGUMENT;
1227
  }
2244.1.1 by Monty Taylor
Split libdrizzle into 1.0 and 2.0. Applied the C++ changes to 2.0 branch.
1228
1229
  drizzle_log_debug(con->drizzle, "drizzle_state_read");
1230
1231
  if (con->buffer_size == 0)
1232
    con->buffer_ptr= con->buffer;
1233
  else if ((con->buffer_ptr - con->buffer) > (DRIZZLE_MAX_BUFFER_SIZE / 2))
1234
  {
1235
    memmove(con->buffer, con->buffer_ptr, con->buffer_size);
1236
    con->buffer_ptr= con->buffer;
1237
  }
1238
1239
  if ((con->revents & POLLIN) == 0 &&
2461.1.2 by Brian Aker
Pass through refactoring.
1240
      (con->drizzle->options.is_non_blocking))
2244.1.1 by Monty Taylor
Split libdrizzle into 1.0 and 2.0. Applied the C++ changes to 2.0 branch.
1241
  {
1242
    /* non-blocking mode: return IO_WAIT instead of attempting to read. This
1243
     * avoids reading immediately after writing a command, which typically
1244
     * returns EAGAIN. This improves performance. */
2463.1.4 by Brian Aker
Remove con from being passed object.
1245
    drizzle_return_t ret= drizzle_con_set_events(con, POLLIN);
2244.1.1 by Monty Taylor
Split libdrizzle into 1.0 and 2.0. Applied the C++ changes to 2.0 branch.
1246
    if (ret != DRIZZLE_RETURN_OK)
2463.1.4 by Brian Aker
Remove con from being passed object.
1247
    {
2244.1.1 by Monty Taylor
Split libdrizzle into 1.0 and 2.0. Applied the C++ changes to 2.0 branch.
1248
      return ret;
2463.1.4 by Brian Aker
Remove con from being passed object.
1249
    }
2244.1.1 by Monty Taylor
Split libdrizzle into 1.0 and 2.0. Applied the C++ changes to 2.0 branch.
1250
    return DRIZZLE_RETURN_IO_WAIT;
1251
  }
1252
1253
  while (1)
1254
  {
1255
    size_t available_buffer= (size_t)DRIZZLE_MAX_BUFFER_SIZE -
1256
        ((size_t)(con->buffer_ptr - con->buffer) + con->buffer_size);
2318.5.27 by Olaf van der Spek
Refactor
1257
    ssize_t read_size = recv(con->fd, (char *)con->buffer_ptr + con->buffer_size,
2244.1.1 by Monty Taylor
Split libdrizzle into 1.0 and 2.0. Applied the C++ changes to 2.0 branch.
1258
                     available_buffer, 0);
1259
#ifdef _WIN32
2263.4.1 by Monty Taylor
Updated the windows/posix error mapping as per notes from Marc Isambart.
1260
    errno = WSAGetLastError();
1261
    switch(errno) {
1262
    case WSAENOTCONN:
1263
    case WSAEWOULDBLOCK:
1264
      errno= EAGAIN;
1265
      break;
1266
    case WSAEINVAL:
1267
    case WSAEALREADY:
2269.2.1 by Marc Isambart
Various libdrizzle Windows fixes, including closesocket() instead of close(), snprintf handling and WSAECONNREFUSED mapping
1268
      errno= EINPROGRESS;
1269
      break;
2263.4.1 by Monty Taylor
Updated the windows/posix error mapping as per notes from Marc Isambart.
1270
    case WSAECONNREFUSED:
2269.2.1 by Marc Isambart
Various libdrizzle Windows fixes, including closesocket() instead of close(), snprintf handling and WSAECONNREFUSED mapping
1271
      errno= ECONNREFUSED;
2263.4.1 by Monty Taylor
Updated the windows/posix error mapping as per notes from Marc Isambart.
1272
      break;
1273
    case WSAENETUNREACH:
1274
      errno= ENETUNREACH;
1275
      break;
1276
    case WSAETIMEDOUT:
1277
      errno= ETIMEDOUT;
1278
      break;
1279
    case WSAECONNRESET:
1280
      errno= ECONNRESET;
1281
      break;
1282
    case WSAEADDRINUSE:
1283
      errno= EADDRINUSE;
1284
      break;
1285
    case WSAEOPNOTSUPP:
1286
      errno= EOPNOTSUPP;
1287
      break;
1288
    case WSAENOPROTOOPT:
1289
      errno= ENOPROTOOPT;
1290
      break;
1291
    default:
1292
      break;
1293
    }
2244.1.1 by Monty Taylor
Split libdrizzle into 1.0 and 2.0. Applied the C++ changes to 2.0 branch.
1294
#endif /* _WIN32 */	
2265.1.3 by Monty Taylor
Perform proper windows error handling. Also turns out errno.h is not needed on vs2010.
1295
2244.1.1 by Monty Taylor
Split libdrizzle into 1.0 and 2.0. Applied the C++ changes to 2.0 branch.
1296
    drizzle_log_crazy(con->drizzle, "read fd=%d return=%zd errno=%d", con->fd,
1297
                      read_size, errno);
1298
1299
    if (read_size == 0)
1300
    {
1301
      drizzle_set_error(con->drizzle, "drizzle_state_read",
1302
                        "lost connection to server (EOF)");
1303
      return DRIZZLE_RETURN_LOST_CONNECTION;
1304
    }
1305
    else if (read_size == -1)
1306
    {
1307
      if (errno == EAGAIN)
1308
      {
1309
        /* clear the read ready flag */
1310
        con->revents&= ~POLLIN;
2463.1.4 by Brian Aker
Remove con from being passed object.
1311
        drizzle_return_t ret= drizzle_con_set_events(con, POLLIN);
2244.1.1 by Monty Taylor
Split libdrizzle into 1.0 and 2.0. Applied the C++ changes to 2.0 branch.
1312
        if (ret != DRIZZLE_RETURN_OK)
2463.1.4 by Brian Aker
Remove con from being passed object.
1313
        {
2244.1.1 by Monty Taylor
Split libdrizzle into 1.0 and 2.0. Applied the C++ changes to 2.0 branch.
1314
          return ret;
2463.1.4 by Brian Aker
Remove con from being passed object.
1315
        }
2244.1.1 by Monty Taylor
Split libdrizzle into 1.0 and 2.0. Applied the C++ changes to 2.0 branch.
1316
2461.1.2 by Brian Aker
Pass through refactoring.
1317
        if (con->drizzle->options.is_non_blocking)
1318
        {
2244.1.1 by Monty Taylor
Split libdrizzle into 1.0 and 2.0. Applied the C++ changes to 2.0 branch.
1319
          return DRIZZLE_RETURN_IO_WAIT;
2461.1.2 by Brian Aker
Pass through refactoring.
1320
        }
2244.1.1 by Monty Taylor
Split libdrizzle into 1.0 and 2.0. Applied the C++ changes to 2.0 branch.
1321
1322
        ret= drizzle_con_wait(con->drizzle);
1323
        if (ret != DRIZZLE_RETURN_OK)
2461.1.2 by Brian Aker
Pass through refactoring.
1324
        {
2244.1.1 by Monty Taylor
Split libdrizzle into 1.0 and 2.0. Applied the C++ changes to 2.0 branch.
1325
          return ret;
2461.1.2 by Brian Aker
Pass through refactoring.
1326
        }
2244.1.1 by Monty Taylor
Split libdrizzle into 1.0 and 2.0. Applied the C++ changes to 2.0 branch.
1327
1328
        continue;
1329
      }
1330
      else if (errno == ECONNREFUSED)
1331
      {
1332
        con->revents= 0;
1333
        drizzle_state_pop(con);
1334
        drizzle_state_push(con, drizzle_state_connect);
1335
        con->addrinfo_next= con->addrinfo_next->ai_next;
1336
        return DRIZZLE_RETURN_OK;
1337
      }
1338
      else if (errno == EINTR)
1339
        continue;
1340
      else if (errno == EPIPE || errno == ECONNRESET)
1341
      {
1342
        drizzle_set_error(con->drizzle, "drizzle_state_read",
1343
                          "lost connection to server (%d)", errno);
1344
        return DRIZZLE_RETURN_LOST_CONNECTION;
1345
      }
1346
1347
      drizzle_set_error(con->drizzle, "drizzle_state_read", "read:%d", errno);
1348
      con->drizzle->last_errno= errno;
1349
      return DRIZZLE_RETURN_ERRNO;
1350
    }
1351
1352
    /* clear the "read ready" flag if we read all available data. */
1353
    if ((size_t) read_size < available_buffer) con->revents&= ~POLLIN;
1354
    con->buffer_size+= (size_t)read_size;
1355
    break;
1356
  }
1357
1358
  drizzle_state_pop(con);
1359
  return DRIZZLE_RETURN_OK;
1360
}
1361
1362
drizzle_return_t drizzle_state_write(drizzle_con_st *con)
1363
{
2463.1.4 by Brian Aker
Remove con from being passed object.
1364
  if (con == NULL)
1365
  {
1366
    return DRIZZLE_RETURN_INVALID_ARGUMENT;
1367
  }
2244.1.1 by Monty Taylor
Split libdrizzle into 1.0 and 2.0. Applied the C++ changes to 2.0 branch.
1368
1369
  drizzle_log_debug(con->drizzle, "drizzle_state_write");
1370
1371
  while (con->buffer_size != 0)
1372
  {
2318.5.27 by Olaf van der Spek
Refactor
1373
    ssize_t write_size = send(con->fd,(char *) con->buffer_ptr, con->buffer_size, 0);
2244.1.1 by Monty Taylor
Split libdrizzle into 1.0 and 2.0. Applied the C++ changes to 2.0 branch.
1374
2263.4.1 by Monty Taylor
Updated the windows/posix error mapping as per notes from Marc Isambart.
1375
#ifdef _WIN32
1376
    errno = WSAGetLastError();
1377
    switch(errno) {
1378
    case WSAENOTCONN:
1379
    case WSAEWOULDBLOCK:
1380
      errno= EAGAIN;
1381
      break;
1382
    case WSAEINVAL:
1383
    case WSAEALREADY:
2269.2.1 by Marc Isambart
Various libdrizzle Windows fixes, including closesocket() instead of close(), snprintf handling and WSAECONNREFUSED mapping
1384
      errno= EINPROGRESS;
1385
      break;
2263.4.1 by Monty Taylor
Updated the windows/posix error mapping as per notes from Marc Isambart.
1386
    case WSAECONNREFUSED:
2269.2.1 by Marc Isambart
Various libdrizzle Windows fixes, including closesocket() instead of close(), snprintf handling and WSAECONNREFUSED mapping
1387
      errno= ECONNREFUSED;
2263.4.1 by Monty Taylor
Updated the windows/posix error mapping as per notes from Marc Isambart.
1388
      break;
1389
    case WSAENETUNREACH:
1390
      errno= ENETUNREACH;
1391
      break;
1392
    case WSAETIMEDOUT:
1393
      errno= ETIMEDOUT;
1394
      break;
1395
    case WSAECONNRESET:
1396
      errno= ECONNRESET;
1397
      break;
1398
    case WSAEADDRINUSE:
1399
      errno= EADDRINUSE;
1400
      break;
1401
    case WSAEOPNOTSUPP:
1402
      errno= EOPNOTSUPP;
1403
      break;
1404
    case WSAENOPROTOOPT:
1405
      errno= ENOPROTOOPT;
1406
      break;
1407
    default:
1408
      break;
1409
    }
1410
#endif /* _WIN32 */	
1411
2244.1.1 by Monty Taylor
Split libdrizzle into 1.0 and 2.0. Applied the C++ changes to 2.0 branch.
1412
    drizzle_log_crazy(con->drizzle, "write fd=%d return=%zd errno=%d", con->fd,
1413
                      write_size, errno);
1414
1415
    if (write_size == 0)
1416
    {
1417
      drizzle_set_error(con->drizzle, "drizzle_state_write",
1418
                        "lost connection to server (EOF)");
1419
      return DRIZZLE_RETURN_LOST_CONNECTION;
1420
    }
1421
    else if (write_size == -1)
1422
    {
1423
      if (errno == EAGAIN)
1424
      {
2463.1.4 by Brian Aker
Remove con from being passed object.
1425
        drizzle_return_t ret= drizzle_con_set_events(con, POLLOUT);
2244.1.1 by Monty Taylor
Split libdrizzle into 1.0 and 2.0. Applied the C++ changes to 2.0 branch.
1426
        if (ret != DRIZZLE_RETURN_OK)
2461.1.2 by Brian Aker
Pass through refactoring.
1427
        {
2244.1.1 by Monty Taylor
Split libdrizzle into 1.0 and 2.0. Applied the C++ changes to 2.0 branch.
1428
          return ret;
2461.1.2 by Brian Aker
Pass through refactoring.
1429
        }
2244.1.1 by Monty Taylor
Split libdrizzle into 1.0 and 2.0. Applied the C++ changes to 2.0 branch.
1430
2461.1.2 by Brian Aker
Pass through refactoring.
1431
        if (con->drizzle->options.is_non_blocking)
1432
        {
2244.1.1 by Monty Taylor
Split libdrizzle into 1.0 and 2.0. Applied the C++ changes to 2.0 branch.
1433
          return DRIZZLE_RETURN_IO_WAIT;
2461.1.2 by Brian Aker
Pass through refactoring.
1434
        }
2244.1.1 by Monty Taylor
Split libdrizzle into 1.0 and 2.0. Applied the C++ changes to 2.0 branch.
1435
1436
        ret= drizzle_con_wait(con->drizzle);
1437
        if (ret != DRIZZLE_RETURN_OK)
2461.1.2 by Brian Aker
Pass through refactoring.
1438
        {
2244.1.1 by Monty Taylor
Split libdrizzle into 1.0 and 2.0. Applied the C++ changes to 2.0 branch.
1439
          return ret;
2461.1.2 by Brian Aker
Pass through refactoring.
1440
        }
2244.1.1 by Monty Taylor
Split libdrizzle into 1.0 and 2.0. Applied the C++ changes to 2.0 branch.
1441
1442
        continue;
1443
      }
1444
      else if (errno == EINTR)
2461.1.2 by Brian Aker
Pass through refactoring.
1445
      {
2244.1.1 by Monty Taylor
Split libdrizzle into 1.0 and 2.0. Applied the C++ changes to 2.0 branch.
1446
        continue;
2461.1.2 by Brian Aker
Pass through refactoring.
1447
      }
2244.1.1 by Monty Taylor
Split libdrizzle into 1.0 and 2.0. Applied the C++ changes to 2.0 branch.
1448
      else if (errno == EPIPE || errno == ECONNRESET)
1449
      {
1450
        drizzle_set_error(con->drizzle, "drizzle_state_write",
1451
                          "lost connection to server (%d)", errno);
1452
        return DRIZZLE_RETURN_LOST_CONNECTION;
1453
      }
1454
1455
      drizzle_set_error(con->drizzle, "drizzle_state_write", "write:%d", errno);
1456
      con->drizzle->last_errno= errno;
1457
      return DRIZZLE_RETURN_ERRNO;
1458
    }
1459
1460
    con->buffer_ptr+= write_size;
1461
    con->buffer_size-= (size_t)write_size;
1462
    if (con->buffer_size == 0)
1463
      break;
1464
  }
1465
1466
  con->buffer_ptr= con->buffer;
1467
1468
  drizzle_state_pop(con);
1469
  return DRIZZLE_RETURN_OK;
1470
}
1471
1472
drizzle_return_t drizzle_state_listen(drizzle_con_st *con)
1473
{
1474
  char host[NI_MAXHOST];
1475
  char port[NI_MAXSERV];
1476
  int ret;
1477
  int fd;
1478
  int opt;
1479
  drizzle_con_st *new_con;
1480
2463.1.4 by Brian Aker
Remove con from being passed object.
1481
  if (con == NULL)
1482
  {
1483
    return DRIZZLE_RETURN_INVALID_ARGUMENT;
1484
  }
1485
1486
2244.1.1 by Monty Taylor
Split libdrizzle into 1.0 and 2.0. Applied the C++ changes to 2.0 branch.
1487
  for (; con->addrinfo_next != NULL;
1488
       con->addrinfo_next= con->addrinfo_next->ai_next)
1489
  {
1490
    ret= getnameinfo(con->addrinfo_next->ai_addr,
1491
                     con->addrinfo_next->ai_addrlen, host, NI_MAXHOST, port,
1492
                     NI_MAXSERV, NI_NUMERICHOST | NI_NUMERICSERV);
1493
    if (ret != 0)
1494
    {
1495
      drizzle_set_error(con->drizzle, "drizzle_state_listen", "getnameinfo:%s",
1496
                        gai_strerror(ret));
1497
      return DRIZZLE_RETURN_GETADDRINFO;
1498
    }
1499
1500
    /* Call to socket() can fail for some getaddrinfo results, try another. */
1501
    fd= socket(con->addrinfo_next->ai_family, con->addrinfo_next->ai_socktype,
1502
               con->addrinfo_next->ai_protocol);
1503
    if (fd == -1)
1504
    {
1505
      drizzle_log_info(con->drizzle, "could not listen on %s:%s", host, port);
1506
      drizzle_set_error(con->drizzle, "drizzle_state_listen", "socket:%d",
1507
                        errno);
1508
      continue;
1509
    }
1510
	
1511
	opt= 1;
1512
#ifdef _WIN32
1513
        ret= setsockopt(fd, SOL_SOCKET, SO_REUSEADDR,(const char*) &opt, sizeof(opt));
1514
#else
1515
        ret= setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt));
1516
#endif /* _WIN32 */
1517
    if (ret == -1)
1518
    {
2269.2.1 by Marc Isambart
Various libdrizzle Windows fixes, including closesocket() instead of close(), snprintf handling and WSAECONNREFUSED mapping
1519
      closesocket(fd);
2244.1.1 by Monty Taylor
Split libdrizzle into 1.0 and 2.0. Applied the C++ changes to 2.0 branch.
1520
      drizzle_set_error(con->drizzle, "drizzle_state_listen", "setsockopt:%d",
1521
                        errno);
1522
      return DRIZZLE_RETURN_ERRNO;
1523
    }
1524
1525
    ret= bind(fd, con->addrinfo_next->ai_addr, con->addrinfo_next->ai_addrlen);
1526
    if (ret == -1)
1527
    {
2269.2.1 by Marc Isambart
Various libdrizzle Windows fixes, including closesocket() instead of close(), snprintf handling and WSAECONNREFUSED mapping
1528
      closesocket(fd);
2244.1.1 by Monty Taylor
Split libdrizzle into 1.0 and 2.0. Applied the C++ changes to 2.0 branch.
1529
      drizzle_set_error(con->drizzle, "drizzle_state_listen", "bind:%d", errno);
1530
      if (errno == EADDRINUSE)
1531
      {
1532
        if (con->fd == -1)
1533
        {
1534
          drizzle_log_info(con->drizzle, "could not listen on %s:%s", host,
1535
                           port);
1536
        }
1537
1538
        continue;
1539
      }
1540
1541
      return DRIZZLE_RETURN_ERRNO;
1542
    }
1543
1544
    if (listen(fd, con->backlog) == -1)
1545
    {
2269.2.1 by Marc Isambart
Various libdrizzle Windows fixes, including closesocket() instead of close(), snprintf handling and WSAECONNREFUSED mapping
1546
      closesocket(fd);
2244.1.1 by Monty Taylor
Split libdrizzle into 1.0 and 2.0. Applied the C++ changes to 2.0 branch.
1547
      drizzle_set_error(con->drizzle, "drizzle_state_listen", "listen:%d",
1548
                        errno);
1549
      return DRIZZLE_RETURN_ERRNO;
1550
    }
1551
1552
    if (con->fd == -1)
1553
    {
1554
      con->fd= fd;
1555
      new_con= con;
1556
    }
1557
    else
1558
    {
2463.1.4 by Brian Aker
Remove con from being passed object.
1559
      new_con= drizzle_con_clone(con->drizzle, con);
2244.1.1 by Monty Taylor
Split libdrizzle into 1.0 and 2.0. Applied the C++ changes to 2.0 branch.
1560
      if (new_con == NULL)
1561
      {
2269.2.1 by Marc Isambart
Various libdrizzle Windows fixes, including closesocket() instead of close(), snprintf handling and WSAECONNREFUSED mapping
1562
        closesocket(fd);
2244.1.1 by Monty Taylor
Split libdrizzle into 1.0 and 2.0. Applied the C++ changes to 2.0 branch.
1563
        return DRIZZLE_RETURN_MEMORY;
1564
      }
1565
1566
      new_con->fd= fd;
1567
    }
1568
1569
    /* Wait for read events on the listening socket. */
1570
    drizzle_return_t driz_ret= drizzle_con_set_events(new_con, POLLIN);
1571
    if (ret != DRIZZLE_RETURN_OK)
1572
    {
1573
      drizzle_con_free(new_con);
1574
      return driz_ret;
1575
    }
1576
1577
    drizzle_log_info(con->drizzle, "listening on %s:%s", host, port);
1578
  }
1579
1580
  /* Report last socket() error if we couldn't find an address to bind. */
1581
  if (con->fd == -1)
2463.1.4 by Brian Aker
Remove con from being passed object.
1582
  {
2244.1.1 by Monty Taylor
Split libdrizzle into 1.0 and 2.0. Applied the C++ changes to 2.0 branch.
1583
    return DRIZZLE_RETURN_ERRNO;
2463.1.4 by Brian Aker
Remove con from being passed object.
1584
  }
2244.1.1 by Monty Taylor
Split libdrizzle into 1.0 and 2.0. Applied the C++ changes to 2.0 branch.
1585
1586
  drizzle_state_pop(con);
1587
  return DRIZZLE_RETURN_OK;
1588
}
1589
1590
/*
1591
 * Static Definitions
1592
 */
1593
1594
static drizzle_return_t _con_setsockopt(drizzle_con_st *con)
1595
{
1596
  int ret;
1597
  struct linger linger;
1598
  struct timeval waittime;
1599
2463.1.4 by Brian Aker
Remove con from being passed object.
1600
  if (con == NULL)
1601
  {
1602
    return DRIZZLE_RETURN_INVALID_ARGUMENT;
1603
  }
1604
1605
2244.1.1 by Monty Taylor
Split libdrizzle into 1.0 and 2.0. Applied the C++ changes to 2.0 branch.
1606
  ret= 1;
1607
1608
#ifdef _WIN32
1609
  ret= setsockopt(con->fd, IPPROTO_TCP, TCP_NODELAY, (const char*)&ret,
1610
                  (socklen_t)sizeof(int));
1611
#else
1612
  ret= setsockopt(con->fd, IPPROTO_TCP, TCP_NODELAY, &ret,
1613
                  (socklen_t)sizeof(int));
1614
#endif /* _WIN32 */
1615
1616
  if (ret == -1 && errno != EOPNOTSUPP)
1617
  {
1618
    drizzle_set_error(con->drizzle, "_con_setsockopt",
1619
                      "setsockopt:TCP_NODELAY:%d", errno);
1620
    return DRIZZLE_RETURN_ERRNO;
1621
  }
1622
1623
  linger.l_onoff= 1;
1624
  linger.l_linger= DRIZZLE_DEFAULT_SOCKET_TIMEOUT;
1625
1626
#ifdef _WIN32
1627
  ret= setsockopt(con->fd, SOL_SOCKET, SO_LINGER, (const char*)&linger,
1628
                  (socklen_t)sizeof(struct linger));
1629
#else
1630
  ret= setsockopt(con->fd, SOL_SOCKET, SO_LINGER, &linger,
1631
                  (socklen_t)sizeof(struct linger));
1632
#endif /* _WIN32 */
1633
1634
  if (ret == -1)
1635
  {
1636
    drizzle_set_error(con->drizzle, "_con_setsockopt",
1637
                      "setsockopt:SO_LINGER:%d", errno);
1638
    return DRIZZLE_RETURN_ERRNO;
1639
  }
1640
1641
  waittime.tv_sec= DRIZZLE_DEFAULT_SOCKET_TIMEOUT;
1642
  waittime.tv_usec= 0;
1643
1644
#ifdef _WIN32
1645
  ret= setsockopt(con->fd, SOL_SOCKET, SO_SNDTIMEO, (const char*)&waittime,
1646
                  (socklen_t)sizeof(struct timeval));
1647
#else
1648
  ret= setsockopt(con->fd, SOL_SOCKET, SO_SNDTIMEO, &waittime,
1649
                  (socklen_t)sizeof(struct timeval));
1650
#endif /* _WIN32 */
1651
1652
  if (ret == -1 && errno != ENOPROTOOPT)
1653
  {
1654
    drizzle_set_error(con->drizzle, "_con_setsockopt",
1655
                      "setsockopt:SO_SNDTIMEO:%d", errno);
1656
    return DRIZZLE_RETURN_ERRNO;
1657
  }
1658
1659
#ifdef _WIN32
1660
  ret= setsockopt(con->fd, SOL_SOCKET, SO_RCVTIMEO, (const char*)&waittime,
1661
                  (socklen_t)sizeof(struct timeval));
1662
#else
1663
  ret= setsockopt(con->fd, SOL_SOCKET, SO_RCVTIMEO, &waittime,
1664
                  (socklen_t)sizeof(struct timeval));
1665
#endif /* _WIN32 */
1666
1667
  if (ret == -1 && errno != ENOPROTOOPT)
1668
  {
1669
    drizzle_set_error(con->drizzle, "_con_setsockopt",
1670
                      "setsockopt:SO_RCVTIMEO:%d", errno);
1671
    return DRIZZLE_RETURN_ERRNO;
1672
  }
1673
1674
  ret= DRIZZLE_DEFAULT_SOCKET_SEND_SIZE;
1675
#ifdef _WIN32
1676
  ret= setsockopt(con->fd, SOL_SOCKET, SO_SNDBUF, (const char*)&ret, (socklen_t)sizeof(int));
1677
#else
1678
  ret= setsockopt(con->fd, SOL_SOCKET, SO_SNDBUF, &ret, (socklen_t)sizeof(int));
1679
#endif /* _WIN32 */
1680
  if (ret == -1)
1681
  {
1682
    drizzle_set_error(con->drizzle, "_con_setsockopt",
1683
                      "setsockopt:SO_SNDBUF:%d", errno);
1684
    return DRIZZLE_RETURN_ERRNO;
1685
  }
1686
1687
  ret= DRIZZLE_DEFAULT_SOCKET_RECV_SIZE;
1688
#ifdef _WIN32
1689
  ret= setsockopt(con->fd, SOL_SOCKET, SO_RCVBUF, (const char*)&ret, (socklen_t)sizeof(int));
1690
#else
1691
  ret= setsockopt(con->fd, SOL_SOCKET, SO_RCVBUF, &ret, (socklen_t)sizeof(int));
1692
#endif /* _WIN32 */
1693
  if (ret == -1)
1694
  {
1695
    drizzle_set_error(con->drizzle, "_con_setsockopt",
1696
                      "setsockopt:SO_RCVBUF:%d", errno);
1697
    return DRIZZLE_RETURN_ERRNO;
1698
  }
1699
1700
#if defined (_WIN32)
1701
  {
1702
    unsigned long asyncmode;
1703
    asyncmode= 1;
1704
    ioctlsocket(con->fd, FIONBIO, &asyncmode);
1705
  }
1706
#else
1707
  ret= fcntl(con->fd, F_GETFL, 0);
1708
  if (ret == -1)
1709
  {
1710
    drizzle_set_error(con->drizzle, "_con_setsockopt", "fcntl:F_GETFL:%d",
1711
                      errno);
1712
    return DRIZZLE_RETURN_ERRNO;
1713
  }
1714
1715
  ret= fcntl(con->fd, F_SETFL, ret | O_NONBLOCK);
1716
  if (ret == -1)
1717
  {
1718
    drizzle_set_error(con->drizzle, "_con_setsockopt", "fcntl:F_SETFL:%d",
1719
                      errno);
1720
    return DRIZZLE_RETURN_ERRNO;
1721
  }
1722
#endif
1723
1724
  return DRIZZLE_RETURN_OK;
1725
}