~drizzle-trunk/drizzle/development

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