~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to libdrizzle-2.0/libdrizzle/conn.cc

  • Committer: Monty Taylor
  • Date: 2011-03-22 18:39:54 UTC
  • mto: (2246.1.1 build)
  • mto: This revision was merged to the branch mainline in revision 2247.
  • Revision ID: mordred@inaugust.com-20110322183954-fz8ciuywjz2llbyo
Split libdrizzle into 1.0 and 2.0. Applied the C++ changes to 2.0 branch.

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
/**
 
39
 * @file
 
40
 * @brief Connection Definitions
 
41
 */
 
42
 
 
43
#include "common.h"
 
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
  drizzle_return_t ret;
 
74
 
 
75
  con->fd= fd;
 
76
 
 
77
  ret= _con_setsockopt(con);
 
78
  if (ret != DRIZZLE_RETURN_OK)
 
79
    con->drizzle->last_errno= errno;
 
80
 
 
81
  return ret;
 
82
}
 
83
 
 
84
void drizzle_con_close(drizzle_con_st *con)
 
85
{
 
86
  if (con->fd == -1)
 
87
    return;
 
88
 
 
89
  (void)closesocket(con->fd);
 
90
  con->fd= -1;
 
91
 
 
92
  con->options&= ~DRIZZLE_CON_READY;
 
93
  con->packet_number= 0;
 
94
  con->buffer_ptr= con->buffer;
 
95
  con->buffer_size= 0;
 
96
  con->events= 0;
 
97
  con->revents= 0;
 
98
 
 
99
  drizzle_state_reset(con);
 
100
}
 
101
 
 
102
drizzle_return_t drizzle_con_set_events(drizzle_con_st *con, short events)
 
103
{
 
104
  drizzle_return_t ret;
 
105
 
 
106
  if ((con->events | events) == con->events)
 
107
    return DRIZZLE_RETURN_OK;
 
108
 
 
109
  con->events|= events;
 
110
 
 
111
  if (con->drizzle->event_watch_fn != NULL)
 
112
  {
 
113
    ret= con->drizzle->event_watch_fn(con, con->events,
 
114
                                      con->drizzle->event_watch_context);
 
115
    if (ret != DRIZZLE_RETURN_OK)
 
116
    {
 
117
      drizzle_con_close(con);
 
118
      return ret;
 
119
    }
 
120
  }
 
121
 
 
122
  return DRIZZLE_RETURN_OK;
 
123
}
 
124
 
 
125
drizzle_return_t drizzle_con_set_revents(drizzle_con_st *con, short revents)
 
126
{
 
127
  drizzle_return_t ret;
 
128
 
 
129
  if (revents != 0)
 
130
    con->options|= DRIZZLE_CON_IO_READY;
 
131
 
 
132
  con->revents= revents;
 
133
 
 
134
  /* Remove external POLLOUT watch if we didn't ask for it. Otherwise we spin
 
135
     forever until another POLLIN state change. This is much more efficient
 
136
     than removing POLLOUT on every state change since some external polling
 
137
     mechanisms need to use a system call to change flags (like Linux epoll). */
 
138
  if (revents & POLLOUT && !(con->events & POLLOUT) &&
 
139
      con->drizzle->event_watch_fn != NULL)
 
140
  {
 
141
    ret= con->drizzle->event_watch_fn(con, con->events,
 
142
                                      con->drizzle->event_watch_context);
 
143
    if (ret != DRIZZLE_RETURN_OK)
 
144
    {
 
145
      drizzle_con_close(con);
 
146
      return ret;
 
147
    }
 
148
  }
 
149
 
 
150
  con->events&= (short)~revents;
 
151
 
 
152
  return DRIZZLE_RETURN_OK;
 
153
}
 
154
 
 
155
drizzle_st *drizzle_con_drizzle(const drizzle_con_st *con)
 
156
{
 
157
  return con->drizzle;
 
158
}
 
159
 
 
160
const char *drizzle_con_error(const drizzle_con_st *con)
 
161
{
 
162
  return drizzle_error(con->drizzle);
 
163
}
 
164
 
 
165
int drizzle_con_errno(const drizzle_con_st *con)
 
166
{
 
167
  return drizzle_errno(con->drizzle);
 
168
}
 
169
 
 
170
uint16_t drizzle_con_error_code(const drizzle_con_st *con)
 
171
{
 
172
  return drizzle_error_code(con->drizzle);
 
173
}
 
174
 
 
175
const char *drizzle_con_sqlstate(const drizzle_con_st *con)
 
176
{
 
177
  return drizzle_sqlstate(con->drizzle);
 
178
}
 
179
 
 
180
int drizzle_con_options(const drizzle_con_st *con)
 
181
{
 
182
  return con->options;
 
183
}
 
184
 
 
185
void drizzle_con_set_options(drizzle_con_st *con,
 
186
                             int options)
 
187
{
 
188
  con->options= options;
 
189
}
 
190
 
 
191
void drizzle_con_add_options(drizzle_con_st *con,
 
192
                             int options)
 
193
{
 
194
  con->options|= options;
 
195
 
 
196
  /* If asking for the experimental Drizzle protocol, clean the MySQL flag. */
 
197
  if (con->options & DRIZZLE_CON_EXPERIMENTAL)
 
198
    con->options&= ~DRIZZLE_CON_MYSQL;
 
199
}
 
200
 
 
201
void drizzle_con_remove_options(drizzle_con_st *con,
 
202
                                int options)
 
203
{
 
204
  con->options&= ~options;
 
205
}
 
206
 
 
207
const char *drizzle_con_host(const drizzle_con_st *con)
 
208
{
 
209
  if (con->socket_type == DRIZZLE_CON_SOCKET_TCP)
 
210
  {
 
211
    if (con->socket.tcp.host == NULL && !(con->options & DRIZZLE_CON_LISTEN))
 
212
      return DRIZZLE_DEFAULT_TCP_HOST;
 
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)
 
243
    con->socket.tcp.host= NULL;
 
244
  else
 
245
  {
 
246
    con->socket.tcp.host= con->socket.tcp.host_buffer;
 
247
    strncpy(con->socket.tcp.host, host, NI_MAXHOST);
 
248
    con->socket.tcp.host[NI_MAXHOST - 1]= 0;
 
249
  }
 
250
 
 
251
  con->socket.tcp.port= port;
 
252
}
 
253
 
 
254
const char *drizzle_con_user(const drizzle_con_st *con)
 
255
{
 
256
  return con->user;
 
257
}
 
258
 
 
259
const char *drizzle_con_password(const drizzle_con_st *con)
 
260
{
 
261
  return con->password;
 
262
}
 
263
 
 
264
void drizzle_con_set_auth(drizzle_con_st *con, const char *user,
 
265
                          const char *password)
 
266
{
 
267
  if (user == NULL)
 
268
    con->user[0]= 0;
 
269
  else
 
270
  {
 
271
    strncpy(con->user, user, DRIZZLE_MAX_USER_SIZE);
 
272
    con->user[DRIZZLE_MAX_USER_SIZE - 1]= 0;
 
273
  }
 
274
 
 
275
  if (password == NULL)
 
276
    con->password[0]= 0;
 
277
  else
 
278
  {
 
279
    strncpy(con->password, password, DRIZZLE_MAX_PASSWORD_SIZE);
 
280
    con->password[DRIZZLE_MAX_PASSWORD_SIZE - 1]= 0;
 
281
  }
 
282
}
 
283
 
 
284
const char *drizzle_con_db(const drizzle_con_st *con)
 
285
{
 
286
  return con->db;
 
287
}
 
288
 
 
289
void drizzle_con_set_db(drizzle_con_st *con, const char *db)
 
290
{
 
291
  if (db == NULL)
 
292
    con->db[0]= 0;
 
293
  else
 
294
  {
 
295
    strncpy(con->db, db, DRIZZLE_MAX_DB_SIZE);
 
296
    con->db[DRIZZLE_MAX_DB_SIZE - 1]= 0;
 
297
  }
 
298
}
 
299
 
 
300
void *drizzle_con_context(const drizzle_con_st *con)
 
301
{
 
302
  return con->context;
 
303
}
 
304
 
 
305
void drizzle_con_set_context(drizzle_con_st *con, void *context)
 
306
{
 
307
  con->context= context;
 
308
}
 
309
 
 
310
void drizzle_con_set_context_free_fn(drizzle_con_st *con,
 
311
                                     drizzle_con_context_free_fn *function)
 
312
{
 
313
  con->context_free_fn= function;
 
314
}
 
315
 
 
316
uint8_t drizzle_con_protocol_version(const drizzle_con_st *con)
 
317
{
 
318
  return con->protocol_version;
 
319
}
 
320
 
 
321
const char *drizzle_con_server_version(const drizzle_con_st *con)
 
322
{
 
323
  return con->server_version;
 
324
}
 
325
 
 
326
uint32_t drizzle_con_server_version_number(const drizzle_con_st *con)
 
327
{
 
328
  uint32_t major;
 
329
  uint32_t minor;
 
330
  uint32_t version;
 
331
  const char *current;
 
332
  char *end;
 
333
 
 
334
  current= con->server_version;
 
335
 
 
336
  major= (uint32_t)strtoul(current, &end, 10);
 
337
  current= end + 1;
 
338
  minor= (uint32_t)strtoul(current, &end, 10);
 
339
  current= end + 1;
 
340
  version= (uint32_t)strtoul(current, &end, 10);
 
341
 
 
342
  return (major * 10000) + (minor * 100) + version;
 
343
}
 
344
 
 
345
uint32_t drizzle_con_thread_id(const drizzle_con_st *con)
 
346
{
 
347
  return con->thread_id;
 
348
}
 
349
 
 
350
const uint8_t *drizzle_con_scramble(const drizzle_con_st *con)
 
351
{
 
352
  return con->scramble;
 
353
}
 
354
 
 
355
int drizzle_con_capabilities(const drizzle_con_st *con)
 
356
{
 
357
  return con->capabilities;
 
358
}
 
359
 
 
360
drizzle_charset_t drizzle_con_charset(const drizzle_con_st *con)
 
361
{
 
362
  return con->charset;
 
363
}
 
364
 
 
365
drizzle_con_status_t drizzle_con_status(const drizzle_con_st *con)
 
366
{
 
367
  return con->status;
 
368
}
 
369
 
 
370
uint32_t drizzle_con_max_packet_size(const drizzle_con_st *con)
 
371
{
 
372
  return con->max_packet_size;
 
373
}
 
374
 
 
375
/*
 
376
 * Client Definitions
 
377
 */
 
378
 
 
379
drizzle_return_t drizzle_con_connect(drizzle_con_st *con)
 
380
{
 
381
  if (con->options & DRIZZLE_CON_READY)
 
382
    return DRIZZLE_RETURN_OK;
 
383
 
 
384
  if (drizzle_state_none(con))
 
385
  {
 
386
    if (!(con->options & DRIZZLE_CON_RAW_PACKET))
 
387
    {
 
388
      drizzle_state_push(con, drizzle_state_handshake_server_read);
 
389
      drizzle_state_push(con, drizzle_state_packet_read);
 
390
    }
 
391
 
 
392
    drizzle_state_push(con, drizzle_state_connect);
 
393
    drizzle_state_push(con, drizzle_state_addrinfo);
 
394
  }
 
395
 
 
396
  return drizzle_state_loop(con);
 
397
}
 
398
 
 
399
drizzle_result_st *drizzle_con_quit(drizzle_con_st *con,
 
400
                                    drizzle_result_st *result,
 
401
                                    drizzle_return_t *ret_ptr)
 
402
{
 
403
  return drizzle_con_command_write(con, result, DRIZZLE_COMMAND_QUIT, NULL, 0,
 
404
                                   0, ret_ptr);
 
405
}
 
406
 
 
407
drizzle_result_st *drizzle_quit(drizzle_con_st *con,
 
408
                                drizzle_result_st *result,
 
409
                                drizzle_return_t *ret_ptr)
 
410
{
 
411
  return drizzle_con_quit(con, result, ret_ptr);
 
412
}
 
413
 
 
414
drizzle_result_st *drizzle_con_select_db(drizzle_con_st *con,
 
415
                                         drizzle_result_st *result,
 
416
                                         const char *db,
 
417
                                         drizzle_return_t *ret_ptr)
 
418
{
 
419
  drizzle_con_set_db(con, db);
 
420
  return drizzle_con_command_write(con, result, DRIZZLE_COMMAND_INIT_DB,
 
421
                                   db, strlen(db), strlen(db), ret_ptr);
 
422
}
 
423
 
 
424
drizzle_result_st *drizzle_select_db(drizzle_con_st *con,
 
425
                                     drizzle_result_st *result,
 
426
                                     const char *db,
 
427
                                     drizzle_return_t *ret_ptr)
 
428
{
 
429
  return drizzle_con_select_db(con, result, db, ret_ptr);
 
430
}
 
431
 
 
432
drizzle_result_st *drizzle_con_shutdown(drizzle_con_st *con,
 
433
                                        drizzle_result_st *result,
 
434
                                        drizzle_return_t *ret_ptr)
 
435
{
 
436
  if (con->options & DRIZZLE_CON_MYSQL)
 
437
  {
 
438
    return drizzle_con_command_write(con, result, DRIZZLE_COMMAND_SHUTDOWN,
 
439
                                     "0", 1, 1, ret_ptr);
 
440
  }
 
441
 
 
442
  return drizzle_con_command_write(con, result, DRIZZLE_COMMAND_SHUTDOWN, NULL,
 
443
                                   0, 0, ret_ptr);
 
444
}
 
445
 
 
446
drizzle_result_st *drizzle_shutdown(drizzle_con_st *con,
 
447
                                    drizzle_result_st *result, uint32_t level,
 
448
                                    drizzle_return_t *ret_ptr)
 
449
{
 
450
  (void) level;
 
451
  return drizzle_con_shutdown(con, result, ret_ptr);
 
452
}
 
453
 
 
454
drizzle_result_st *drizzle_kill(drizzle_con_st *con,
 
455
                                drizzle_result_st *result,
 
456
                                uint32_t query_id,
 
457
                                drizzle_return_t *ret_ptr)
 
458
{
 
459
  uint32_t sent= htonl(query_id);
 
460
  return drizzle_con_command_write(con, result, DRIZZLE_COMMAND_PROCESS_KILL,
 
461
                                   &sent, sizeof(uint32_t), sizeof(uint32_t), ret_ptr);
 
462
}
 
463
 
 
464
drizzle_result_st *drizzle_con_ping(drizzle_con_st *con,
 
465
                                    drizzle_result_st *result,
 
466
                                    drizzle_return_t *ret_ptr)
 
467
{
 
468
  return drizzle_con_command_write(con, result, DRIZZLE_COMMAND_PING, NULL, 0,
 
469
                                   0, ret_ptr);
 
470
}
 
471
 
 
472
drizzle_result_st *drizzle_ping(drizzle_con_st *con,
 
473
                                drizzle_result_st *result,
 
474
                                drizzle_return_t *ret_ptr)
 
475
{
 
476
  return drizzle_con_ping(con, result, ret_ptr);
 
477
}
 
478
 
 
479
drizzle_result_st *drizzle_con_command_write(drizzle_con_st *con,
 
480
                                             drizzle_result_st *result,
 
481
                                             drizzle_command_t command,
 
482
                                             const void *data, size_t size,
 
483
                                             size_t total,
 
484
                                             drizzle_return_t *ret_ptr)
 
485
{
 
486
  drizzle_result_st *old_result;
 
487
 
 
488
  if (!(con->options & DRIZZLE_CON_READY))
 
489
  {
 
490
    if (con->options & DRIZZLE_CON_RAW_PACKET)
 
491
    {
 
492
      drizzle_set_error(con->drizzle, "drizzle_command_write",
 
493
                        "connection not ready");
 
494
      *ret_ptr= DRIZZLE_RETURN_NOT_READY;
 
495
      return result;
 
496
    }
 
497
 
 
498
    *ret_ptr= drizzle_con_connect(con);
 
499
    if (*ret_ptr != DRIZZLE_RETURN_OK)
 
500
      return result;
 
501
  }
 
502
 
 
503
  if (drizzle_state_none(con))
 
504
  {
 
505
    if (con->options & (DRIZZLE_CON_RAW_PACKET | DRIZZLE_CON_NO_RESULT_READ))
 
506
      con->result= NULL;
 
507
    else
 
508
    {
 
509
      for (old_result= con->result_list; old_result != NULL; old_result= old_result->next)
 
510
      {
 
511
        if (result == old_result)
 
512
        {
 
513
          drizzle_set_error(con->drizzle, "drizzle_command_write", "result struct already in use");
 
514
          *ret_ptr= DRIZZLE_RETURN_INTERNAL_ERROR;
 
515
          return result;
 
516
        }
 
517
      }
 
518
 
 
519
      con->result= drizzle_result_create(con, result);
 
520
      if (con->result == NULL)
 
521
      {
 
522
        *ret_ptr= DRIZZLE_RETURN_MEMORY;
 
523
        return NULL;
 
524
      }
 
525
    }
 
526
 
 
527
    con->command= command;
 
528
    con->command_data= (uint8_t *)data;
 
529
    con->command_size= size;
 
530
    con->command_offset= 0;
 
531
    con->command_total= total;
 
532
 
 
533
    drizzle_state_push(con, drizzle_state_command_write);
 
534
  }
 
535
  else if (con->command_data == NULL)
 
536
  {
 
537
    con->command_data= (uint8_t *)data;
 
538
    con->command_size= size;
 
539
  }
 
540
 
 
541
  *ret_ptr= drizzle_state_loop(con);
 
542
  if (*ret_ptr == DRIZZLE_RETURN_PAUSE)
 
543
    *ret_ptr= DRIZZLE_RETURN_OK;
 
544
  else if (*ret_ptr != DRIZZLE_RETURN_OK &&
 
545
           *ret_ptr != DRIZZLE_RETURN_IO_WAIT &&
 
546
           *ret_ptr != DRIZZLE_RETURN_ERROR_CODE)
 
547
  {
 
548
    drizzle_result_free(con->result);
 
549
    con->result= result;
 
550
  }
 
551
 
 
552
  return con->result;
 
553
}
 
554
 
 
555
/*
 
556
 * Server Definitions
 
557
 */
 
558
 
 
559
drizzle_return_t drizzle_con_listen(drizzle_con_st *con)
 
560
{
 
561
  if (con->options & DRIZZLE_CON_READY)
 
562
    return DRIZZLE_RETURN_OK;
 
563
 
 
564
  if (drizzle_state_none(con))
 
565
  {
 
566
    drizzle_state_push(con, drizzle_state_listen);
 
567
    drizzle_state_push(con, drizzle_state_addrinfo);
 
568
  }
 
569
 
 
570
  return drizzle_state_loop(con);
 
571
}
 
572
 
 
573
int drizzle_con_backlog(const drizzle_con_st *con)
 
574
{
 
575
  return con->backlog;
 
576
}
 
577
 
 
578
void drizzle_con_set_backlog(drizzle_con_st *con, int backlog)
 
579
{
 
580
  con->backlog= backlog;
 
581
}
 
582
 
 
583
void drizzle_con_set_protocol_version(drizzle_con_st *con,
 
584
                                      uint8_t protocol_version)
 
585
{
 
586
  con->protocol_version= protocol_version;
 
587
}
 
588
 
 
589
void drizzle_con_set_server_version(drizzle_con_st *con,
 
590
                                    const char *server_version)
 
591
{
 
592
  if (server_version == NULL)
 
593
    con->server_version[0]= 0;
 
594
  else
 
595
  {
 
596
    strncpy(con->server_version, server_version,
 
597
            DRIZZLE_MAX_SERVER_VERSION_SIZE);
 
598
    con->server_version[DRIZZLE_MAX_SERVER_VERSION_SIZE - 1]= 0;
 
599
  }
 
600
}
 
601
 
 
602
void drizzle_con_set_thread_id(drizzle_con_st *con, uint32_t thread_id)
 
603
{
 
604
  con->thread_id= thread_id;
 
605
}
 
606
 
 
607
void drizzle_con_set_scramble(drizzle_con_st *con, const uint8_t *scramble)
 
608
{
 
609
  if (scramble == NULL)
 
610
    con->scramble= NULL;
 
611
  else
 
612
  {
 
613
    con->scramble= con->scramble_buffer;
 
614
    memcpy(con->scramble, scramble, DRIZZLE_MAX_SCRAMBLE_SIZE);
 
615
  }
 
616
}
 
617
 
 
618
void drizzle_con_set_capabilities(drizzle_con_st *con,
 
619
                                  int capabilities)
 
620
{
 
621
  con->capabilities= capabilities;
 
622
}
 
623
 
 
624
void drizzle_con_set_charset(drizzle_con_st *con, drizzle_charset_t charset)
 
625
{
 
626
  con->charset= charset;
 
627
}
 
628
 
 
629
void drizzle_con_set_status(drizzle_con_st *con, drizzle_con_status_t status)
 
630
{
 
631
  con->status= status;
 
632
}
 
633
 
 
634
void drizzle_con_set_max_packet_size(drizzle_con_st *con,
 
635
                                     uint32_t max_packet_size)
 
636
{
 
637
  con->max_packet_size= max_packet_size;
 
638
}
 
639
 
 
640
void drizzle_con_copy_handshake(drizzle_con_st *con, drizzle_con_st *from)
 
641
{
 
642
  drizzle_con_set_auth(con, from->user, NULL);
 
643
  drizzle_con_set_scramble(con, from->scramble);
 
644
  drizzle_con_set_db(con, from->db);
 
645
  drizzle_con_set_protocol_version(con, from->protocol_version);
 
646
  drizzle_con_set_server_version(con, from->server_version);
 
647
  drizzle_con_set_thread_id(con, from->thread_id);
 
648
  drizzle_con_set_scramble(con, from->scramble);
 
649
  drizzle_con_set_capabilities(con, from->capabilities);
 
650
  drizzle_con_set_charset(con, from->charset);
 
651
  drizzle_con_set_status(con, from->status);
 
652
  drizzle_con_set_max_packet_size(con, from->max_packet_size);
 
653
}
 
654
 
 
655
void *drizzle_con_command_read(drizzle_con_st *con,
 
656
                               drizzle_command_t *command, size_t *offset,
 
657
                               size_t *size, size_t *total,
 
658
                               drizzle_return_t *ret_ptr)
 
659
{
 
660
  if (drizzle_state_none(con))
 
661
  {
 
662
    con->packet_number= 0;
 
663
    con->command_offset= 0;
 
664
    con->command_total= 0;
 
665
 
 
666
    drizzle_state_push(con, drizzle_state_command_read);
 
667
    drizzle_state_push(con, drizzle_state_packet_read);
 
668
  }
 
669
 
 
670
  *offset= con->command_offset;
 
671
 
 
672
  *ret_ptr= drizzle_state_loop(con);
 
673
  if (*ret_ptr == DRIZZLE_RETURN_PAUSE)
 
674
    *ret_ptr= DRIZZLE_RETURN_OK;
 
675
 
 
676
  *command= con->command;
 
677
  *size= con->command_size;
 
678
  *total= con->command_total;
 
679
 
 
680
  return con->command_data;
 
681
}
 
682
 
 
683
void *drizzle_con_command_buffer(drizzle_con_st *con,
 
684
                                 drizzle_command_t *command, size_t *total,
 
685
                                 drizzle_return_t *ret_ptr)
 
686
{
 
687
  size_t offset= 0;
 
688
  size_t size= 0;
 
689
 
 
690
  uint8_t *command_data=
 
691
    static_cast<uint8_t *>(drizzle_con_command_read(con, command, &offset,
 
692
                                                    &size, total, ret_ptr));
 
693
  if (*ret_ptr != DRIZZLE_RETURN_OK)
 
694
    return NULL;
 
695
 
 
696
  if (command_data == NULL)
 
697
  {
 
698
    *total= 0;
 
699
    return NULL;
 
700
  }
 
701
 
 
702
  if (con->command_buffer == NULL)
 
703
  {
 
704
    con->command_buffer= new uint8_t[(*total) + 1];
 
705
    if (con->command_buffer == NULL)
 
706
    {
 
707
      drizzle_set_error(con->drizzle, "drizzle_command_buffer", "malloc");
 
708
      *ret_ptr= DRIZZLE_RETURN_MEMORY;
 
709
      return NULL;
 
710
    }
 
711
  }
 
712
 
 
713
  memcpy(con->command_buffer + offset, command_data, size);
 
714
 
 
715
  while ((offset + size) != (*total))
 
716
  {
 
717
    command_data= (uint8_t *)drizzle_con_command_read(con, command, &offset,
 
718
                                                      &size, total, ret_ptr);
 
719
    if (*ret_ptr != DRIZZLE_RETURN_OK)
 
720
      return NULL;
 
721
 
 
722
    memcpy(con->command_buffer + offset, command_data, size);
 
723
  }
 
724
 
 
725
  command_data= con->command_buffer;
 
726
  con->command_buffer= NULL;
 
727
  command_data[*total]= 0;
 
728
 
 
729
  return command_data;
 
730
}
 
731
 
 
732
void drizzle_con_command_buffer_free(uint8_t *command_buffer)
 
733
{
 
734
  delete[] command_buffer;
 
735
}
 
736
 
 
737
/*
 
738
 * Local Definitions
 
739
 */
 
740
 
 
741
void drizzle_con_reset_addrinfo(drizzle_con_st *con)
 
742
{
 
743
  switch (con->socket_type)
 
744
  {
 
745
  case DRIZZLE_CON_SOCKET_TCP:
 
746
    if (con->socket.tcp.addrinfo != NULL)
 
747
    {
 
748
      freeaddrinfo(con->socket.tcp.addrinfo);
 
749
      con->socket.tcp.addrinfo= NULL;
 
750
    }
 
751
    break;
 
752
 
 
753
  case DRIZZLE_CON_SOCKET_UDS:
 
754
    con->socket.uds.addrinfo.ai_addr= NULL;
 
755
    break;
 
756
 
 
757
  default:
 
758
    break;
 
759
  }
 
760
 
 
761
  con->addrinfo_next= NULL;
 
762
}
 
763
 
 
764
/*
 
765
 * State Definitions
 
766
 */
 
767
 
 
768
drizzle_return_t drizzle_state_addrinfo(drizzle_con_st *con)
 
769
{
 
770
  drizzle_con_tcp_st *tcp;
 
771
  const char *host;
 
772
  char port[NI_MAXSERV];
 
773
  struct addrinfo ai;
 
774
  int ret;
 
775
 
 
776
  drizzle_log_debug(con->drizzle, "drizzle_state_addrinfo");
 
777
 
 
778
  switch (con->socket_type)
 
779
  {
 
780
  case DRIZZLE_CON_SOCKET_TCP:
 
781
    tcp= &(con->socket.tcp);
 
782
 
 
783
    if (tcp->addrinfo != NULL)
 
784
    {
 
785
      freeaddrinfo(tcp->addrinfo);
 
786
      tcp->addrinfo= NULL;
 
787
    }
 
788
 
 
789
    if (tcp->port != 0)
 
790
      snprintf(port, NI_MAXSERV, "%u", tcp->port);
 
791
    else if (con->options & DRIZZLE_CON_MYSQL)
 
792
      snprintf(port, NI_MAXSERV, "%u", DRIZZLE_DEFAULT_TCP_PORT_MYSQL);
 
793
    else
 
794
      snprintf(port, NI_MAXSERV, "%u", DRIZZLE_DEFAULT_TCP_PORT);
 
795
 
 
796
    ai.ai_socktype= SOCK_STREAM;
 
797
    ai.ai_protocol= IPPROTO_TCP;
 
798
    ai.ai_flags = AI_PASSIVE;
 
799
    ai.ai_family = AF_UNSPEC;
 
800
 
 
801
    if (con->options & DRIZZLE_CON_LISTEN)
 
802
    {
 
803
      host= tcp->host;
 
804
    }
 
805
    else
 
806
    {
 
807
      if (tcp->host == NULL)
 
808
        host= DRIZZLE_DEFAULT_TCP_HOST;
 
809
      else
 
810
        host= tcp->host;
 
811
    }
 
812
 
 
813
    ret= getaddrinfo(host, port, &ai, &(tcp->addrinfo));
 
814
    if (ret != 0)
 
815
    {
 
816
      drizzle_set_error(con->drizzle, "drizzle_state_addrinfo",
 
817
                        "getaddrinfo:%s", gai_strerror(ret));
 
818
      return DRIZZLE_RETURN_GETADDRINFO;
 
819
    }
 
820
 
 
821
    con->addrinfo_next= tcp->addrinfo;
 
822
 
 
823
    break;
 
824
 
 
825
  case DRIZZLE_CON_SOCKET_UDS:
 
826
    con->addrinfo_next= &(con->socket.uds.addrinfo);
 
827
    break;
 
828
 
 
829
  default:
 
830
    break;
 
831
  }
 
832
 
 
833
  drizzle_state_pop(con);
 
834
  return DRIZZLE_RETURN_OK;
 
835
}
 
836
 
 
837
drizzle_return_t drizzle_state_connect(drizzle_con_st *con)
 
838
{
 
839
  int ret;
 
840
  drizzle_return_t dret;
 
841
 
 
842
  drizzle_log_debug(con->drizzle, "drizzle_state_connect");
 
843
 
 
844
  if (con->fd != -1)
 
845
  {
 
846
    (void)close(con->fd);
 
847
    con->fd= -1;
 
848
  }
 
849
 
 
850
  if (con->addrinfo_next == NULL)
 
851
  {
 
852
    drizzle_set_error(con->drizzle, "drizzle_state_connect",
 
853
                      "could not connect");
 
854
    drizzle_state_reset(con);
 
855
    return DRIZZLE_RETURN_COULD_NOT_CONNECT;
 
856
  }
 
857
 
 
858
  con->fd= socket(con->addrinfo_next->ai_family,
 
859
                  con->addrinfo_next->ai_socktype,
 
860
                  con->addrinfo_next->ai_protocol);
 
861
  if (con->fd == -1)
 
862
  {
 
863
    drizzle_set_error(con->drizzle, "drizzle_state_connect", "socket:%d",
 
864
                      errno);
 
865
    con->drizzle->last_errno= errno;
 
866
    return DRIZZLE_RETURN_ERRNO;
 
867
  }
 
868
 
 
869
  dret= _con_setsockopt(con);
 
870
  if (dret != DRIZZLE_RETURN_OK)
 
871
  {
 
872
    con->drizzle->last_errno= errno;
 
873
    return dret;
 
874
  }
 
875
 
 
876
  while (1)
 
877
  {
 
878
    ret= connect(con->fd, con->addrinfo_next->ai_addr,
 
879
                 con->addrinfo_next->ai_addrlen);
 
880
 
 
881
#ifdef _WIN32
 
882
    /*Mapping windows specific error codes to Posix*/
 
883
    errno = WSAGetLastError();
 
884
    switch(errno) {
 
885
    case WSAEINVAL:
 
886
    case WSAEALREADY:
 
887
    case WSAEWOULDBLOCK:
 
888
      errno = EINPROGRESS;
 
889
      break;
 
890
    default:
 
891
      break;
 
892
    }
 
893
#endif /* _WIN32 */
 
894
        
 
895
    drizzle_log_crazy(con->drizzle, "connect return=%d errno=%d", ret, errno);
 
896
 
 
897
    if (ret == 0)
 
898
    {
 
899
      con->addrinfo_next= NULL;
 
900
      break;
 
901
    }
 
902
 
 
903
    if (errno == EAGAIN || errno == EINTR)
 
904
      continue;
 
905
 
 
906
    if (errno == EINPROGRESS)
 
907
    {
 
908
      drizzle_state_pop(con);
 
909
      drizzle_state_push(con, drizzle_state_connecting);
 
910
      return DRIZZLE_RETURN_OK;
 
911
    }
 
912
 
 
913
    if (errno == ECONNREFUSED || errno == ENETUNREACH || errno == ETIMEDOUT)
 
914
    {
 
915
      con->addrinfo_next= con->addrinfo_next->ai_next;
 
916
      return DRIZZLE_RETURN_OK;
 
917
    }
 
918
 
 
919
    drizzle_set_error(con->drizzle, "drizzle_state_connect", "connect:%d",
 
920
                      errno);
 
921
    con->drizzle->last_errno= errno;
 
922
    return DRIZZLE_RETURN_ERRNO;
 
923
  }
 
924
 
 
925
  drizzle_state_pop(con);
 
926
  return DRIZZLE_RETURN_OK;
 
927
}
 
928
 
 
929
drizzle_return_t drizzle_state_connecting(drizzle_con_st *con)
 
930
{
 
931
  drizzle_return_t ret;
 
932
 
 
933
  drizzle_log_debug(con->drizzle, "drizzle_state_connecting");
 
934
 
 
935
  while (1)
 
936
  {
 
937
    if (con->revents & POLLOUT)
 
938
    {
 
939
      drizzle_state_pop(con);
 
940
      return DRIZZLE_RETURN_OK;
 
941
    }
 
942
    else if (con->revents & (POLLERR | POLLHUP | POLLNVAL))
 
943
    {
 
944
      con->revents= 0;
 
945
      drizzle_state_pop(con);
 
946
      drizzle_state_push(con, drizzle_state_connect);
 
947
      con->addrinfo_next= con->addrinfo_next->ai_next;
 
948
      return DRIZZLE_RETURN_OK;
 
949
    }
 
950
 
 
951
    ret= drizzle_con_set_events(con, POLLOUT);
 
952
    if (ret != DRIZZLE_RETURN_OK)
 
953
      return ret;
 
954
 
 
955
    if (con->drizzle->options & DRIZZLE_NON_BLOCKING)
 
956
      return DRIZZLE_RETURN_IO_WAIT;
 
957
 
 
958
    ret= drizzle_con_wait(con->drizzle);
 
959
    if (ret != DRIZZLE_RETURN_OK)
 
960
      return ret;
 
961
  }
 
962
}
 
963
 
 
964
drizzle_return_t drizzle_state_read(drizzle_con_st *con)
 
965
{
 
966
  drizzle_return_t ret;
 
967
  ssize_t read_size;
 
968
 
 
969
  drizzle_log_debug(con->drizzle, "drizzle_state_read");
 
970
 
 
971
  if (con->buffer_size == 0)
 
972
    con->buffer_ptr= con->buffer;
 
973
  else if ((con->buffer_ptr - con->buffer) > (DRIZZLE_MAX_BUFFER_SIZE / 2))
 
974
  {
 
975
    memmove(con->buffer, con->buffer_ptr, con->buffer_size);
 
976
    con->buffer_ptr= con->buffer;
 
977
  }
 
978
 
 
979
  if ((con->revents & POLLIN) == 0 &&
 
980
      (con->drizzle->options & DRIZZLE_NON_BLOCKING))
 
981
  {
 
982
    /* non-blocking mode: return IO_WAIT instead of attempting to read. This
 
983
     * avoids reading immediately after writing a command, which typically
 
984
     * returns EAGAIN. This improves performance. */
 
985
    ret= drizzle_con_set_events(con, POLLIN);
 
986
    if (ret != DRIZZLE_RETURN_OK)
 
987
      return ret;
 
988
    return DRIZZLE_RETURN_IO_WAIT;
 
989
  }
 
990
 
 
991
  while (1)
 
992
  {
 
993
    size_t available_buffer= (size_t)DRIZZLE_MAX_BUFFER_SIZE -
 
994
        ((size_t)(con->buffer_ptr - con->buffer) + con->buffer_size);
 
995
    read_size = recv(con->fd, (char *)con->buffer_ptr + con->buffer_size,
 
996
                     available_buffer, 0);
 
997
#ifdef _WIN32
 
998
    /*Get windows error codes and map it to Posix*/
 
999
    errno = WSAGetLastError();
 
1000
    switch(errno) {
 
1001
    case WSAEWOULDBLOCK:
 
1002
    case 10057:
 
1003
      errno = EAGAIN;
 
1004
      break;
 
1005
    default:
 
1006
      break;
 
1007
    }
 
1008
#endif /* _WIN32 */     
 
1009
    drizzle_log_crazy(con->drizzle, "read fd=%d return=%zd errno=%d", con->fd,
 
1010
                      read_size, errno);
 
1011
 
 
1012
    if (read_size == 0)
 
1013
    {
 
1014
      drizzle_set_error(con->drizzle, "drizzle_state_read",
 
1015
                        "lost connection to server (EOF)");
 
1016
      return DRIZZLE_RETURN_LOST_CONNECTION;
 
1017
    }
 
1018
    else if (read_size == -1)
 
1019
    {
 
1020
      if (errno == EAGAIN)
 
1021
      {
 
1022
        /* clear the read ready flag */
 
1023
        con->revents&= ~POLLIN;
 
1024
        ret= drizzle_con_set_events(con, POLLIN);
 
1025
        if (ret != DRIZZLE_RETURN_OK)
 
1026
          return ret;
 
1027
 
 
1028
        if (con->drizzle->options & DRIZZLE_NON_BLOCKING)
 
1029
          return DRIZZLE_RETURN_IO_WAIT;
 
1030
 
 
1031
        ret= drizzle_con_wait(con->drizzle);
 
1032
        if (ret != DRIZZLE_RETURN_OK)
 
1033
          return ret;
 
1034
 
 
1035
        continue;
 
1036
      }
 
1037
      else if (errno == ECONNREFUSED)
 
1038
      {
 
1039
        con->revents= 0;
 
1040
        drizzle_state_pop(con);
 
1041
        drizzle_state_push(con, drizzle_state_connect);
 
1042
        con->addrinfo_next= con->addrinfo_next->ai_next;
 
1043
        return DRIZZLE_RETURN_OK;
 
1044
      }
 
1045
      else if (errno == EINTR)
 
1046
        continue;
 
1047
      else if (errno == EPIPE || errno == ECONNRESET)
 
1048
      {
 
1049
        drizzle_set_error(con->drizzle, "drizzle_state_read",
 
1050
                          "lost connection to server (%d)", errno);
 
1051
        return DRIZZLE_RETURN_LOST_CONNECTION;
 
1052
      }
 
1053
 
 
1054
      drizzle_set_error(con->drizzle, "drizzle_state_read", "read:%d", errno);
 
1055
      con->drizzle->last_errno= errno;
 
1056
      return DRIZZLE_RETURN_ERRNO;
 
1057
    }
 
1058
 
 
1059
    /* clear the "read ready" flag if we read all available data. */
 
1060
    if ((size_t) read_size < available_buffer) con->revents&= ~POLLIN;
 
1061
    con->buffer_size+= (size_t)read_size;
 
1062
    break;
 
1063
  }
 
1064
 
 
1065
  drizzle_state_pop(con);
 
1066
  return DRIZZLE_RETURN_OK;
 
1067
}
 
1068
 
 
1069
drizzle_return_t drizzle_state_write(drizzle_con_st *con)
 
1070
{
 
1071
  drizzle_return_t ret;
 
1072
  ssize_t write_size;
 
1073
 
 
1074
  drizzle_log_debug(con->drizzle, "drizzle_state_write");
 
1075
 
 
1076
  while (con->buffer_size != 0)
 
1077
  {
 
1078
  
 
1079
    write_size = send(con->fd,(char *) con->buffer_ptr, con->buffer_size, 0);
 
1080
 
 
1081
    drizzle_log_crazy(con->drizzle, "write fd=%d return=%zd errno=%d", con->fd,
 
1082
                      write_size, errno);
 
1083
 
 
1084
    if (write_size == 0)
 
1085
    {
 
1086
      drizzle_set_error(con->drizzle, "drizzle_state_write",
 
1087
                        "lost connection to server (EOF)");
 
1088
      return DRIZZLE_RETURN_LOST_CONNECTION;
 
1089
    }
 
1090
    else if (write_size == -1)
 
1091
    {
 
1092
      if (errno == EAGAIN)
 
1093
      {
 
1094
        ret= drizzle_con_set_events(con, POLLOUT);
 
1095
        if (ret != DRIZZLE_RETURN_OK)
 
1096
          return ret;
 
1097
 
 
1098
        if (con->drizzle->options & DRIZZLE_NON_BLOCKING)
 
1099
          return DRIZZLE_RETURN_IO_WAIT;
 
1100
 
 
1101
        ret= drizzle_con_wait(con->drizzle);
 
1102
        if (ret != DRIZZLE_RETURN_OK)
 
1103
          return ret;
 
1104
 
 
1105
        continue;
 
1106
      }
 
1107
      else if (errno == EINTR)
 
1108
        continue;
 
1109
      else if (errno == EPIPE || errno == ECONNRESET)
 
1110
      {
 
1111
        drizzle_set_error(con->drizzle, "drizzle_state_write",
 
1112
                          "lost connection to server (%d)", errno);
 
1113
        return DRIZZLE_RETURN_LOST_CONNECTION;
 
1114
      }
 
1115
 
 
1116
      drizzle_set_error(con->drizzle, "drizzle_state_write", "write:%d", errno);
 
1117
      con->drizzle->last_errno= errno;
 
1118
      return DRIZZLE_RETURN_ERRNO;
 
1119
    }
 
1120
 
 
1121
    con->buffer_ptr+= write_size;
 
1122
    con->buffer_size-= (size_t)write_size;
 
1123
    if (con->buffer_size == 0)
 
1124
      break;
 
1125
  }
 
1126
 
 
1127
  con->buffer_ptr= con->buffer;
 
1128
 
 
1129
  drizzle_state_pop(con);
 
1130
  return DRIZZLE_RETURN_OK;
 
1131
}
 
1132
 
 
1133
drizzle_return_t drizzle_state_listen(drizzle_con_st *con)
 
1134
{
 
1135
  char host[NI_MAXHOST];
 
1136
  char port[NI_MAXSERV];
 
1137
  int ret;
 
1138
  int fd;
 
1139
  int opt;
 
1140
  drizzle_con_st *new_con;
 
1141
 
 
1142
  for (; con->addrinfo_next != NULL;
 
1143
       con->addrinfo_next= con->addrinfo_next->ai_next)
 
1144
  {
 
1145
    ret= getnameinfo(con->addrinfo_next->ai_addr,
 
1146
                     con->addrinfo_next->ai_addrlen, host, NI_MAXHOST, port,
 
1147
                     NI_MAXSERV, NI_NUMERICHOST | NI_NUMERICSERV);
 
1148
    if (ret != 0)
 
1149
    {
 
1150
      drizzle_set_error(con->drizzle, "drizzle_state_listen", "getnameinfo:%s",
 
1151
                        gai_strerror(ret));
 
1152
      return DRIZZLE_RETURN_GETADDRINFO;
 
1153
    }
 
1154
 
 
1155
    /* Call to socket() can fail for some getaddrinfo results, try another. */
 
1156
    fd= socket(con->addrinfo_next->ai_family, con->addrinfo_next->ai_socktype,
 
1157
               con->addrinfo_next->ai_protocol);
 
1158
    if (fd == -1)
 
1159
    {
 
1160
      drizzle_log_info(con->drizzle, "could not listen on %s:%s", host, port);
 
1161
      drizzle_set_error(con->drizzle, "drizzle_state_listen", "socket:%d",
 
1162
                        errno);
 
1163
      continue;
 
1164
    }
 
1165
        
 
1166
        opt= 1;
 
1167
#ifdef _WIN32
 
1168
        ret= setsockopt(fd, SOL_SOCKET, SO_REUSEADDR,(const char*) &opt, sizeof(opt));
 
1169
#else
 
1170
        ret= setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt));
 
1171
#endif /* _WIN32 */
 
1172
    if (ret == -1)
 
1173
    {
 
1174
      close(fd);
 
1175
      drizzle_set_error(con->drizzle, "drizzle_state_listen", "setsockopt:%d",
 
1176
                        errno);
 
1177
      return DRIZZLE_RETURN_ERRNO;
 
1178
    }
 
1179
 
 
1180
    ret= bind(fd, con->addrinfo_next->ai_addr, con->addrinfo_next->ai_addrlen);
 
1181
    if (ret == -1)
 
1182
    {
 
1183
      close(fd);
 
1184
      drizzle_set_error(con->drizzle, "drizzle_state_listen", "bind:%d", errno);
 
1185
      if (errno == EADDRINUSE)
 
1186
      {
 
1187
        if (con->fd == -1)
 
1188
        {
 
1189
          drizzle_log_info(con->drizzle, "could not listen on %s:%s", host,
 
1190
                           port);
 
1191
        }
 
1192
 
 
1193
        continue;
 
1194
      }
 
1195
 
 
1196
      return DRIZZLE_RETURN_ERRNO;
 
1197
    }
 
1198
 
 
1199
    if (listen(fd, con->backlog) == -1)
 
1200
    {
 
1201
      close(fd);
 
1202
      drizzle_set_error(con->drizzle, "drizzle_state_listen", "listen:%d",
 
1203
                        errno);
 
1204
      return DRIZZLE_RETURN_ERRNO;
 
1205
    }
 
1206
 
 
1207
    if (con->fd == -1)
 
1208
    {
 
1209
      con->fd= fd;
 
1210
      new_con= con;
 
1211
    }
 
1212
    else
 
1213
    {
 
1214
      new_con= drizzle_con_clone(con->drizzle, NULL, con);
 
1215
      if (new_con == NULL)
 
1216
      {
 
1217
        close(fd);
 
1218
        return DRIZZLE_RETURN_MEMORY;
 
1219
      }
 
1220
 
 
1221
      new_con->fd= fd;
 
1222
    }
 
1223
 
 
1224
    /* Wait for read events on the listening socket. */
 
1225
    drizzle_return_t driz_ret= drizzle_con_set_events(new_con, POLLIN);
 
1226
    if (ret != DRIZZLE_RETURN_OK)
 
1227
    {
 
1228
      drizzle_con_free(new_con);
 
1229
      return driz_ret;
 
1230
    }
 
1231
 
 
1232
    drizzle_log_info(con->drizzle, "listening on %s:%s", host, port);
 
1233
  }
 
1234
 
 
1235
  /* Report last socket() error if we couldn't find an address to bind. */
 
1236
  if (con->fd == -1)
 
1237
    return DRIZZLE_RETURN_ERRNO;
 
1238
 
 
1239
  drizzle_state_pop(con);
 
1240
  return DRIZZLE_RETURN_OK;
 
1241
}
 
1242
 
 
1243
/*
 
1244
 * Static Definitions
 
1245
 */
 
1246
 
 
1247
static drizzle_return_t _con_setsockopt(drizzle_con_st *con)
 
1248
{
 
1249
  int ret;
 
1250
  struct linger linger;
 
1251
  struct timeval waittime;
 
1252
 
 
1253
  ret= 1;
 
1254
 
 
1255
#ifdef _WIN32
 
1256
  ret= setsockopt(con->fd, IPPROTO_TCP, TCP_NODELAY, (const char*)&ret,
 
1257
                  (socklen_t)sizeof(int));
 
1258
#else
 
1259
  ret= setsockopt(con->fd, IPPROTO_TCP, TCP_NODELAY, &ret,
 
1260
                  (socklen_t)sizeof(int));
 
1261
#endif /* _WIN32 */
 
1262
 
 
1263
  if (ret == -1 && errno != EOPNOTSUPP)
 
1264
  {
 
1265
    drizzle_set_error(con->drizzle, "_con_setsockopt",
 
1266
                      "setsockopt:TCP_NODELAY:%d", errno);
 
1267
    return DRIZZLE_RETURN_ERRNO;
 
1268
  }
 
1269
 
 
1270
  linger.l_onoff= 1;
 
1271
  linger.l_linger= DRIZZLE_DEFAULT_SOCKET_TIMEOUT;
 
1272
 
 
1273
#ifdef _WIN32
 
1274
  ret= setsockopt(con->fd, SOL_SOCKET, SO_LINGER, (const char*)&linger,
 
1275
                  (socklen_t)sizeof(struct linger));
 
1276
#else
 
1277
  ret= setsockopt(con->fd, SOL_SOCKET, SO_LINGER, &linger,
 
1278
                  (socklen_t)sizeof(struct linger));
 
1279
#endif /* _WIN32 */
 
1280
 
 
1281
  if (ret == -1)
 
1282
  {
 
1283
    drizzle_set_error(con->drizzle, "_con_setsockopt",
 
1284
                      "setsockopt:SO_LINGER:%d", errno);
 
1285
    return DRIZZLE_RETURN_ERRNO;
 
1286
  }
 
1287
 
 
1288
  waittime.tv_sec= DRIZZLE_DEFAULT_SOCKET_TIMEOUT;
 
1289
  waittime.tv_usec= 0;
 
1290
 
 
1291
#ifdef _WIN32
 
1292
  ret= setsockopt(con->fd, SOL_SOCKET, SO_SNDTIMEO, (const char*)&waittime,
 
1293
                  (socklen_t)sizeof(struct timeval));
 
1294
#else
 
1295
  ret= setsockopt(con->fd, SOL_SOCKET, SO_SNDTIMEO, &waittime,
 
1296
                  (socklen_t)sizeof(struct timeval));
 
1297
#endif /* _WIN32 */
 
1298
 
 
1299
  if (ret == -1 && errno != ENOPROTOOPT)
 
1300
  {
 
1301
    drizzle_set_error(con->drizzle, "_con_setsockopt",
 
1302
                      "setsockopt:SO_SNDTIMEO:%d", errno);
 
1303
    return DRIZZLE_RETURN_ERRNO;
 
1304
  }
 
1305
 
 
1306
#ifdef _WIN32
 
1307
  ret= setsockopt(con->fd, SOL_SOCKET, SO_RCVTIMEO, (const char*)&waittime,
 
1308
                  (socklen_t)sizeof(struct timeval));
 
1309
#else
 
1310
  ret= setsockopt(con->fd, SOL_SOCKET, SO_RCVTIMEO, &waittime,
 
1311
                  (socklen_t)sizeof(struct timeval));
 
1312
#endif /* _WIN32 */
 
1313
 
 
1314
  if (ret == -1 && errno != ENOPROTOOPT)
 
1315
  {
 
1316
    drizzle_set_error(con->drizzle, "_con_setsockopt",
 
1317
                      "setsockopt:SO_RCVTIMEO:%d", errno);
 
1318
    return DRIZZLE_RETURN_ERRNO;
 
1319
  }
 
1320
 
 
1321
  ret= DRIZZLE_DEFAULT_SOCKET_SEND_SIZE;
 
1322
#ifdef _WIN32
 
1323
  ret= setsockopt(con->fd, SOL_SOCKET, SO_SNDBUF, (const char*)&ret, (socklen_t)sizeof(int));
 
1324
#else
 
1325
  ret= setsockopt(con->fd, SOL_SOCKET, SO_SNDBUF, &ret, (socklen_t)sizeof(int));
 
1326
#endif /* _WIN32 */
 
1327
  if (ret == -1)
 
1328
  {
 
1329
    drizzle_set_error(con->drizzle, "_con_setsockopt",
 
1330
                      "setsockopt:SO_SNDBUF:%d", errno);
 
1331
    return DRIZZLE_RETURN_ERRNO;
 
1332
  }
 
1333
 
 
1334
  ret= DRIZZLE_DEFAULT_SOCKET_RECV_SIZE;
 
1335
#ifdef _WIN32
 
1336
  ret= setsockopt(con->fd, SOL_SOCKET, SO_RCVBUF, (const char*)&ret, (socklen_t)sizeof(int));
 
1337
#else
 
1338
  ret= setsockopt(con->fd, SOL_SOCKET, SO_RCVBUF, &ret, (socklen_t)sizeof(int));
 
1339
#endif /* _WIN32 */
 
1340
  if (ret == -1)
 
1341
  {
 
1342
    drizzle_set_error(con->drizzle, "_con_setsockopt",
 
1343
                      "setsockopt:SO_RCVBUF:%d", errno);
 
1344
    return DRIZZLE_RETURN_ERRNO;
 
1345
  }
 
1346
 
 
1347
#if defined (_WIN32)
 
1348
  {
 
1349
    unsigned long asyncmode;
 
1350
    asyncmode= 1;
 
1351
    ioctlsocket(con->fd, FIONBIO, &asyncmode);
 
1352
  }
 
1353
#else
 
1354
  ret= fcntl(con->fd, F_GETFL, 0);
 
1355
  if (ret == -1)
 
1356
  {
 
1357
    drizzle_set_error(con->drizzle, "_con_setsockopt", "fcntl:F_GETFL:%d",
 
1358
                      errno);
 
1359
    return DRIZZLE_RETURN_ERRNO;
 
1360
  }
 
1361
 
 
1362
  ret= fcntl(con->fd, F_SETFL, ret | O_NONBLOCK);
 
1363
  if (ret == -1)
 
1364
  {
 
1365
    drizzle_set_error(con->drizzle, "_con_setsockopt", "fcntl:F_SETFL:%d",
 
1366
                      errno);
 
1367
    return DRIZZLE_RETURN_ERRNO;
 
1368
  }
 
1369
#endif
 
1370
 
 
1371
  return DRIZZLE_RETURN_OK;
 
1372
}