~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
 *
1971.2.1 by kalebral at gmail
update files that did not have license or had incorrect license structure
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
 *
1712.1.1 by Monty Taylor
Merged libdrizzle directly into tree.
35
 */
36
1971.2.1 by kalebral at gmail
update files that did not have license or had incorrect license structure
37
1712.1.1 by Monty Taylor
Merged libdrizzle directly into tree.
38
/**
39
 * @file
40
 * @brief Connection Definitions
41
 */
42
2449.1.4 by Brian Aker
Complete update of libdrizzle
43
#include <libdrizzle-1.0/common.h>
1712.1.1 by Monty Taylor
Merged libdrizzle directly into tree.
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
2195.2.2 by Olaf van der Spek
Use closetsocket instead of close
89
  (void)closesocket(con->fd);
1712.1.1 by Monty Taylor
Merged libdrizzle directly into tree.
90
  con->fd= -1;
91
92
  con->options&= (drizzle_con_options_t)~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
1992.6.7 by Monty Taylor
Revert -Wc++-compat change.
180
drizzle_con_options_t drizzle_con_options(const drizzle_con_st *con)
1712.1.1 by Monty Taylor
Merged libdrizzle directly into tree.
181
{
182
  return con->options;
183
}
184
185
void drizzle_con_set_options(drizzle_con_st *con,
1992.6.7 by Monty Taylor
Revert -Wc++-compat change.
186
                             drizzle_con_options_t options)
1712.1.1 by Monty Taylor
Merged libdrizzle directly into tree.
187
{
188
  con->options= options;
189
}
190
191
void drizzle_con_add_options(drizzle_con_st *con,
1992.6.7 by Monty Taylor
Revert -Wc++-compat change.
192
                             drizzle_con_options_t options)
1712.1.1 by Monty Taylor
Merged libdrizzle directly into tree.
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)
2191.1.3 by Brian Aker
Cleanup for interactive
198
  {
1712.1.1 by Monty Taylor
Merged libdrizzle directly into tree.
199
    con->options&= (drizzle_con_options_t)~DRIZZLE_CON_MYSQL;
2191.1.3 by Brian Aker
Cleanup for interactive
200
  }
1712.1.1 by Monty Taylor
Merged libdrizzle directly into tree.
201
}
202
203
void drizzle_con_remove_options(drizzle_con_st *con,
1992.6.7 by Monty Taylor
Revert -Wc++-compat change.
204
                                drizzle_con_options_t options)
1712.1.1 by Monty Taylor
Merged libdrizzle directly into tree.
205
{
206
  con->options&= ~options;
207
}
208
209
const char *drizzle_con_host(const drizzle_con_st *con)
210
{
211
  if (con->socket_type == DRIZZLE_CON_SOCKET_TCP)
212
  {
213
    if (con->socket.tcp.host == NULL && !(con->options & DRIZZLE_CON_LISTEN))
214
      return DRIZZLE_DEFAULT_TCP_HOST;
215
216
    return con->socket.tcp.host;
217
  }
218
219
  return NULL;
220
}
221
222
in_port_t drizzle_con_port(const drizzle_con_st *con)
223
{
224
  if (con->socket_type == DRIZZLE_CON_SOCKET_TCP)
225
  {
226
    if (con->socket.tcp.port != 0)
227
      return con->socket.tcp.port;
228
229
    if (con->options & DRIZZLE_CON_MYSQL)
230
      return DRIZZLE_DEFAULT_TCP_PORT_MYSQL;
231
232
    return DRIZZLE_DEFAULT_TCP_PORT;
233
  }
234
235
  return 0;
236
}
237
238
void drizzle_con_set_tcp(drizzle_con_st *con, const char *host, in_port_t port)
239
{
240
  drizzle_con_reset_addrinfo(con);
241
242
  con->socket_type= DRIZZLE_CON_SOCKET_TCP;
243
244
  if (host == NULL)
245
    con->socket.tcp.host= NULL;
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
{
258
  return con->user;
259
}
260
261
const char *drizzle_con_password(const drizzle_con_st *con)
262
{
263
  return con->password;
264
}
265
266
void drizzle_con_set_auth(drizzle_con_st *con, const char *user,
267
                          const char *password)
268
{
269
  if (user == NULL)
270
    con->user[0]= 0;
271
  else
272
  {
273
    strncpy(con->user, user, DRIZZLE_MAX_USER_SIZE);
274
    con->user[DRIZZLE_MAX_USER_SIZE - 1]= 0;
275
  }
276
277
  if (password == NULL)
278
    con->password[0]= 0;
279
  else
280
  {
281
    strncpy(con->password, password, DRIZZLE_MAX_PASSWORD_SIZE);
282
    con->password[DRIZZLE_MAX_PASSWORD_SIZE - 1]= 0;
283
  }
284
}
285
286
const char *drizzle_con_db(const drizzle_con_st *con)
287
{
288
  return con->db;
289
}
290
291
void drizzle_con_set_db(drizzle_con_st *con, const char *db)
292
{
293
  if (db == NULL)
294
    con->db[0]= 0;
295
  else
296
  {
297
    strncpy(con->db, db, DRIZZLE_MAX_DB_SIZE);
298
    con->db[DRIZZLE_MAX_DB_SIZE - 1]= 0;
299
  }
300
}
301
302
void *drizzle_con_context(const drizzle_con_st *con)
303
{
304
  return con->context;
305
}
306
307
void drizzle_con_set_context(drizzle_con_st *con, void *context)
308
{
309
  con->context= context;
310
}
311
312
void drizzle_con_set_context_free_fn(drizzle_con_st *con,
313
                                     drizzle_con_context_free_fn *function)
314
{
315
  con->context_free_fn= function;
316
}
317
318
uint8_t drizzle_con_protocol_version(const drizzle_con_st *con)
319
{
320
  return con->protocol_version;
321
}
322
323
const char *drizzle_con_server_version(const drizzle_con_st *con)
324
{
325
  return con->server_version;
326
}
327
328
uint32_t drizzle_con_server_version_number(const drizzle_con_st *con)
329
{
330
  uint32_t major;
331
  uint32_t minor;
332
  uint32_t version;
333
  const char *current;
334
  char *end;
335
336
  current= con->server_version;
337
338
  major= (uint32_t)strtoul(current, &end, 10);
339
  current= end + 1;
340
  minor= (uint32_t)strtoul(current, &end, 10);
341
  current= end + 1;
342
  version= (uint32_t)strtoul(current, &end, 10);
343
344
  return (major * 10000) + (minor * 100) + version;
345
}
346
347
uint32_t drizzle_con_thread_id(const drizzle_con_st *con)
348
{
349
  return con->thread_id;
350
}
351
352
const uint8_t *drizzle_con_scramble(const drizzle_con_st *con)
353
{
354
  return con->scramble;
355
}
356
1992.6.7 by Monty Taylor
Revert -Wc++-compat change.
357
drizzle_capabilities_t drizzle_con_capabilities(const drizzle_con_st *con)
1712.1.1 by Monty Taylor
Merged libdrizzle directly into tree.
358
{
359
  return con->capabilities;
360
}
361
362
drizzle_charset_t drizzle_con_charset(const drizzle_con_st *con)
363
{
364
  return con->charset;
365
}
366
367
drizzle_con_status_t drizzle_con_status(const drizzle_con_st *con)
368
{
369
  return con->status;
370
}
371
372
uint32_t drizzle_con_max_packet_size(const drizzle_con_st *con)
373
{
374
  return con->max_packet_size;
375
}
376
377
/*
378
 * Client Definitions
379
 */
380
381
drizzle_return_t drizzle_con_connect(drizzle_con_st *con)
382
{
383
  if (con->options & DRIZZLE_CON_READY)
384
    return DRIZZLE_RETURN_OK;
385
386
  if (drizzle_state_none(con))
387
  {
388
    if (!(con->options & DRIZZLE_CON_RAW_PACKET))
389
    {
390
      drizzle_state_push(con, drizzle_state_handshake_server_read);
391
      drizzle_state_push(con, drizzle_state_packet_read);
392
    }
393
394
    drizzle_state_push(con, drizzle_state_connect);
395
    drizzle_state_push(con, drizzle_state_addrinfo);
396
  }
397
398
  return drizzle_state_loop(con);
399
}
400
401
drizzle_result_st *drizzle_con_quit(drizzle_con_st *con,
402
                                    drizzle_result_st *result,
403
                                    drizzle_return_t *ret_ptr)
404
{
405
  return drizzle_con_command_write(con, result, DRIZZLE_COMMAND_QUIT, NULL, 0,
406
                                   0, ret_ptr);
407
}
408
409
drizzle_result_st *drizzle_quit(drizzle_con_st *con,
410
                                drizzle_result_st *result,
411
                                drizzle_return_t *ret_ptr)
412
{
413
  return drizzle_con_quit(con, result, ret_ptr);
414
}
415
416
drizzle_result_st *drizzle_con_select_db(drizzle_con_st *con,
417
                                         drizzle_result_st *result,
418
                                         const char *db,
419
                                         drizzle_return_t *ret_ptr)
420
{
421
  drizzle_con_set_db(con, db);
422
  return drizzle_con_command_write(con, result, DRIZZLE_COMMAND_INIT_DB,
423
                                   db, strlen(db), strlen(db), ret_ptr);
424
}
425
426
drizzle_result_st *drizzle_select_db(drizzle_con_st *con,
427
                                     drizzle_result_st *result,
428
                                     const char *db,
429
                                     drizzle_return_t *ret_ptr)
430
{
431
  return drizzle_con_select_db(con, result, db, ret_ptr);
432
}
433
434
drizzle_result_st *drizzle_con_shutdown(drizzle_con_st *con,
435
                                        drizzle_result_st *result,
436
                                        drizzle_return_t *ret_ptr)
437
{
438
  if (con->options & DRIZZLE_CON_MYSQL)
439
  {
440
    return drizzle_con_command_write(con, result, DRIZZLE_COMMAND_SHUTDOWN,
441
                                     "0", 1, 1, ret_ptr);
442
  }
443
444
  return drizzle_con_command_write(con, result, DRIZZLE_COMMAND_SHUTDOWN, NULL,
445
                                   0, 0, ret_ptr);
446
}
447
448
drizzle_result_st *drizzle_shutdown(drizzle_con_st *con,
449
                                    drizzle_result_st *result, uint32_t level,
450
                                    drizzle_return_t *ret_ptr)
451
{
452
  (void) level;
453
  return drizzle_con_shutdown(con, result, ret_ptr);
454
}
455
2191.1.1 by Brian Aker
Add in KILL protocol support.
456
drizzle_result_st *drizzle_kill(drizzle_con_st *con,
457
                                drizzle_result_st *result,
458
                                uint32_t query_id,
459
                                drizzle_return_t *ret_ptr)
460
{
461
  uint32_t sent= htonl(query_id);
462
  return drizzle_con_command_write(con, result, DRIZZLE_COMMAND_PROCESS_KILL,
463
                                   &sent, sizeof(uint32_t), sizeof(uint32_t), ret_ptr);
464
}
465
1712.1.1 by Monty Taylor
Merged libdrizzle directly into tree.
466
drizzle_result_st *drizzle_con_ping(drizzle_con_st *con,
467
                                    drizzle_result_st *result,
468
                                    drizzle_return_t *ret_ptr)
469
{
470
  return drizzle_con_command_write(con, result, DRIZZLE_COMMAND_PING, NULL, 0,
471
                                   0, ret_ptr);
472
}
473
474
drizzle_result_st *drizzle_ping(drizzle_con_st *con,
475
                                drizzle_result_st *result,
476
                                drizzle_return_t *ret_ptr)
477
{
478
  return drizzle_con_ping(con, result, ret_ptr);
479
}
480
481
drizzle_result_st *drizzle_con_command_write(drizzle_con_st *con,
482
                                             drizzle_result_st *result,
483
                                             drizzle_command_t command,
484
                                             const void *data, size_t size,
485
                                             size_t total,
486
                                             drizzle_return_t *ret_ptr)
487
{
2217.1.3 by Andrew Hutchings
Fix for ICC?
488
  drizzle_result_st *old_result;
489
2449.1.4 by Brian Aker
Complete update of libdrizzle
490
  drizzle_return_t unused;
491
  if (ret_ptr == NULL)
492
  {
493
    ret_ptr= &unused;
494
  }
495
1712.1.1 by Monty Taylor
Merged libdrizzle directly into tree.
496
  if (!(con->options & DRIZZLE_CON_READY))
497
  {
498
    if (con->options & DRIZZLE_CON_RAW_PACKET)
499
    {
500
      drizzle_set_error(con->drizzle, "drizzle_command_write",
501
                        "connection not ready");
502
      *ret_ptr= DRIZZLE_RETURN_NOT_READY;
503
      return result;
504
    }
505
506
    *ret_ptr= drizzle_con_connect(con);
507
    if (*ret_ptr != DRIZZLE_RETURN_OK)
508
      return result;
509
  }
510
511
  if (drizzle_state_none(con))
512
  {
513
    if (con->options & (DRIZZLE_CON_RAW_PACKET | DRIZZLE_CON_NO_RESULT_READ))
514
      con->result= NULL;
515
    else
516
    {
2221.3.1 by Andrew Hutchings
Fixing result re-use issues broke drizzle_query_run_all(). This fixes that too.
517
      for (old_result= con->result_list; old_result != NULL; old_result= old_result->next)
518
      {
519
        if (result == old_result)
520
        {
521
          drizzle_set_error(con->drizzle, "drizzle_command_write", "result struct already in use");
522
          *ret_ptr= DRIZZLE_RETURN_INTERNAL_ERROR;
523
          return result;
524
        }
525
      }
526
1712.1.1 by Monty Taylor
Merged libdrizzle directly into tree.
527
      con->result= drizzle_result_create(con, result);
528
      if (con->result == NULL)
529
      {
530
        *ret_ptr= DRIZZLE_RETURN_MEMORY;
531
        return NULL;
532
      }
533
    }
534
535
    con->command= command;
536
    con->command_data= (uint8_t *)data;
537
    con->command_size= size;
538
    con->command_offset= 0;
539
    con->command_total= total;
540
541
    drizzle_state_push(con, drizzle_state_command_write);
542
  }
543
  else if (con->command_data == NULL)
544
  {
545
    con->command_data= (uint8_t *)data;
546
    con->command_size= size;
547
  }
548
549
  *ret_ptr= drizzle_state_loop(con);
550
  if (*ret_ptr == DRIZZLE_RETURN_PAUSE)
551
    *ret_ptr= DRIZZLE_RETURN_OK;
552
  else if (*ret_ptr != DRIZZLE_RETURN_OK &&
553
           *ret_ptr != DRIZZLE_RETURN_IO_WAIT &&
554
           *ret_ptr != DRIZZLE_RETURN_ERROR_CODE)
555
  {
556
    drizzle_result_free(con->result);
557
    con->result= result;
558
  }
559
560
  return con->result;
561
}
562
563
/*
564
 * Server Definitions
565
 */
566
567
drizzle_return_t drizzle_con_listen(drizzle_con_st *con)
568
{
569
  if (con->options & DRIZZLE_CON_READY)
570
    return DRIZZLE_RETURN_OK;
571
572
  if (drizzle_state_none(con))
573
  {
574
    drizzle_state_push(con, drizzle_state_listen);
575
    drizzle_state_push(con, drizzle_state_addrinfo);
576
  }
577
578
  return drizzle_state_loop(con);
579
}
580
581
int drizzle_con_backlog(const drizzle_con_st *con)
582
{
583
  return con->backlog;
584
}
585
586
void drizzle_con_set_backlog(drizzle_con_st *con, int backlog)
587
{
588
  con->backlog= backlog;
589
}
590
591
void drizzle_con_set_protocol_version(drizzle_con_st *con,
592
                                      uint8_t protocol_version)
593
{
594
  con->protocol_version= protocol_version;
595
}
596
597
void drizzle_con_set_server_version(drizzle_con_st *con,
598
                                    const char *server_version)
599
{
600
  if (server_version == NULL)
601
    con->server_version[0]= 0;
602
  else
603
  {
604
    strncpy(con->server_version, server_version,
605
            DRIZZLE_MAX_SERVER_VERSION_SIZE);
606
    con->server_version[DRIZZLE_MAX_SERVER_VERSION_SIZE - 1]= 0;
607
  }
608
}
609
610
void drizzle_con_set_thread_id(drizzle_con_st *con, uint32_t thread_id)
611
{
612
  con->thread_id= thread_id;
613
}
614
615
void drizzle_con_set_scramble(drizzle_con_st *con, const uint8_t *scramble)
616
{
617
  if (scramble == NULL)
618
    con->scramble= NULL;
619
  else
620
  {
621
    con->scramble= con->scramble_buffer;
622
    memcpy(con->scramble, scramble, DRIZZLE_MAX_SCRAMBLE_SIZE);
623
  }
624
}
625
626
void drizzle_con_set_capabilities(drizzle_con_st *con,
1992.6.7 by Monty Taylor
Revert -Wc++-compat change.
627
                                  drizzle_capabilities_t capabilities)
1712.1.1 by Monty Taylor
Merged libdrizzle directly into tree.
628
{
629
  con->capabilities= capabilities;
630
}
631
632
void drizzle_con_set_charset(drizzle_con_st *con, drizzle_charset_t charset)
633
{
634
  con->charset= charset;
635
}
636
637
void drizzle_con_set_status(drizzle_con_st *con, drizzle_con_status_t status)
638
{
639
  con->status= status;
640
}
641
642
void drizzle_con_set_max_packet_size(drizzle_con_st *con,
643
                                     uint32_t max_packet_size)
644
{
645
  con->max_packet_size= max_packet_size;
646
}
647
648
void drizzle_con_copy_handshake(drizzle_con_st *con, drizzle_con_st *from)
649
{
650
  drizzle_con_set_auth(con, from->user, NULL);
651
  drizzle_con_set_scramble(con, from->scramble);
652
  drizzle_con_set_db(con, from->db);
653
  drizzle_con_set_protocol_version(con, from->protocol_version);
654
  drizzle_con_set_server_version(con, from->server_version);
655
  drizzle_con_set_thread_id(con, from->thread_id);
656
  drizzle_con_set_scramble(con, from->scramble);
657
  drizzle_con_set_capabilities(con, from->capabilities);
658
  drizzle_con_set_charset(con, from->charset);
659
  drizzle_con_set_status(con, from->status);
660
  drizzle_con_set_max_packet_size(con, from->max_packet_size);
661
}
662
663
void *drizzle_con_command_read(drizzle_con_st *con,
664
                               drizzle_command_t *command, size_t *offset,
665
                               size_t *size, size_t *total,
666
                               drizzle_return_t *ret_ptr)
667
{
668
  if (drizzle_state_none(con))
669
  {
670
    con->packet_number= 0;
671
    con->command_offset= 0;
672
    con->command_total= 0;
673
674
    drizzle_state_push(con, drizzle_state_command_read);
675
    drizzle_state_push(con, drizzle_state_packet_read);
676
  }
677
678
  *offset= con->command_offset;
679
680
  *ret_ptr= drizzle_state_loop(con);
681
  if (*ret_ptr == DRIZZLE_RETURN_PAUSE)
682
    *ret_ptr= DRIZZLE_RETURN_OK;
683
684
  *command= con->command;
685
  *size= con->command_size;
686
  *total= con->command_total;
687
688
  return con->command_data;
689
}
690
691
void *drizzle_con_command_buffer(drizzle_con_st *con,
692
                                 drizzle_command_t *command, size_t *total,
693
                                 drizzle_return_t *ret_ptr)
694
{
695
  uint8_t *command_data;
696
  size_t offset= 0;
697
  size_t size= 0;
698
2191.1.4 by Brian Aker
Add in interactive mode back to protocol.
699
  command_data= drizzle_con_command_read(con, command, &offset, &size, total, ret_ptr);
1712.1.1 by Monty Taylor
Merged libdrizzle directly into tree.
700
  if (*ret_ptr != DRIZZLE_RETURN_OK)
701
    return NULL;
702
703
  if (command_data == NULL)
704
  {
705
    *total= 0;
706
    return NULL;
707
  }
708
709
  if (con->command_buffer == NULL)
710
  {
1992.6.7 by Monty Taylor
Revert -Wc++-compat change.
711
    con->command_buffer= malloc((*total) + 1);
1712.1.1 by Monty Taylor
Merged libdrizzle directly into tree.
712
    if (con->command_buffer == NULL)
713
    {
714
      drizzle_set_error(con->drizzle, "drizzle_command_buffer", "malloc");
715
      *ret_ptr= DRIZZLE_RETURN_MEMORY;
716
      return NULL;
717
    }
718
  }
719
720
  memcpy(con->command_buffer + offset, command_data, size);
721
722
  while ((offset + size) != (*total))
723
  {
1992.6.7 by Monty Taylor
Revert -Wc++-compat change.
724
    command_data= drizzle_con_command_read(con, command, &offset, &size, total,
725
                                           ret_ptr);
1712.1.1 by Monty Taylor
Merged libdrizzle directly into tree.
726
    if (*ret_ptr != DRIZZLE_RETURN_OK)
727
      return NULL;
728
729
    memcpy(con->command_buffer + offset, command_data, size);
730
  }
731
732
  command_data= con->command_buffer;
733
  con->command_buffer= NULL;
734
  command_data[*total]= 0;
735
736
  return command_data;
737
}
738
739
/*
740
 * Local Definitions
741
 */
742
743
void drizzle_con_reset_addrinfo(drizzle_con_st *con)
744
{
745
  switch (con->socket_type)
746
  {
747
  case DRIZZLE_CON_SOCKET_TCP:
748
    if (con->socket.tcp.addrinfo != NULL)
749
    {
750
      freeaddrinfo(con->socket.tcp.addrinfo);
751
      con->socket.tcp.addrinfo= NULL;
752
    }
753
    break;
754
755
  case DRIZZLE_CON_SOCKET_UDS:
756
    con->socket.uds.addrinfo.ai_addr= NULL;
757
    break;
758
759
  default:
760
    break;
761
  }
762
763
  con->addrinfo_next= NULL;
764
}
765
766
/*
767
 * State Definitions
768
 */
769
770
drizzle_return_t drizzle_state_addrinfo(drizzle_con_st *con)
771
{
772
  drizzle_con_tcp_st *tcp;
773
  const char *host;
774
  char port[NI_MAXSERV];
775
  struct addrinfo ai;
776
  int ret;
777
778
  drizzle_log_debug(con->drizzle, "drizzle_state_addrinfo");
779
780
  switch (con->socket_type)
781
  {
782
  case DRIZZLE_CON_SOCKET_TCP:
783
    tcp= &(con->socket.tcp);
784
785
    if (tcp->addrinfo != NULL)
786
    {
787
      freeaddrinfo(tcp->addrinfo);
788
      tcp->addrinfo= NULL;
789
    }
790
791
    if (tcp->port != 0)
792
      snprintf(port, NI_MAXSERV, "%u", tcp->port);
793
    else if (con->options & DRIZZLE_CON_MYSQL)
794
      snprintf(port, NI_MAXSERV, "%u", DRIZZLE_DEFAULT_TCP_PORT_MYSQL);
795
    else
796
      snprintf(port, NI_MAXSERV, "%u", DRIZZLE_DEFAULT_TCP_PORT);
2269.2.1 by Marc Isambart
Various libdrizzle Windows fixes, including closesocket() instead of close(), snprintf handling and WSAECONNREFUSED mapping
797
    port[NI_MAXSERV-1]= 0;
1712.1.1 by Monty Taylor
Merged libdrizzle directly into tree.
798
799
    memset(&ai, 0, sizeof(struct addrinfo));
800
    ai.ai_socktype= SOCK_STREAM;
801
    ai.ai_protocol= IPPROTO_TCP;
2235.1.3 by Andrew Hutchings
Fix addrinfo flags not set correctly
802
    ai.ai_flags = AI_PASSIVE;
803
    ai.ai_family = AF_UNSPEC;
1712.1.1 by Monty Taylor
Merged libdrizzle directly into tree.
804
805
    if (con->options & DRIZZLE_CON_LISTEN)
806
    {
807
      host= tcp->host;
808
    }
809
    else
810
    {
811
      if (tcp->host == NULL)
812
        host= DRIZZLE_DEFAULT_TCP_HOST;
813
      else
814
        host= tcp->host;
815
    }
816
817
    ret= getaddrinfo(host, port, &ai, &(tcp->addrinfo));
818
    if (ret != 0)
819
    {
820
      drizzle_set_error(con->drizzle, "drizzle_state_addrinfo",
821
                        "getaddrinfo:%s", gai_strerror(ret));
822
      return DRIZZLE_RETURN_GETADDRINFO;
823
    }
824
825
    con->addrinfo_next= tcp->addrinfo;
826
827
    break;
828
829
  case DRIZZLE_CON_SOCKET_UDS:
830
    con->addrinfo_next= &(con->socket.uds.addrinfo);
831
    break;
832
833
  default:
834
    break;
835
  }
836
837
  drizzle_state_pop(con);
838
  return DRIZZLE_RETURN_OK;
839
}
840
841
drizzle_return_t drizzle_state_connect(drizzle_con_st *con)
842
{
843
  int ret;
844
  drizzle_return_t dret;
845
846
  drizzle_log_debug(con->drizzle, "drizzle_state_connect");
847
848
  if (con->fd != -1)
849
  {
2269.2.1 by Marc Isambart
Various libdrizzle Windows fixes, including closesocket() instead of close(), snprintf handling and WSAECONNREFUSED mapping
850
    (void)closesocket(con->fd);
1712.1.1 by Monty Taylor
Merged libdrizzle directly into tree.
851
    con->fd= -1;
852
  }
853
854
  if (con->addrinfo_next == NULL)
855
  {
856
    drizzle_set_error(con->drizzle, "drizzle_state_connect",
857
                      "could not connect");
858
    drizzle_state_reset(con);
859
    return DRIZZLE_RETURN_COULD_NOT_CONNECT;
860
  }
861
862
  con->fd= socket(con->addrinfo_next->ai_family,
863
                  con->addrinfo_next->ai_socktype,
864
                  con->addrinfo_next->ai_protocol);
865
  if (con->fd == -1)
866
  {
867
    drizzle_set_error(con->drizzle, "drizzle_state_connect", "socket:%d",
868
                      errno);
869
    con->drizzle->last_errno= errno;
870
    return DRIZZLE_RETURN_ERRNO;
871
  }
872
873
  dret= _con_setsockopt(con);
874
  if (dret != DRIZZLE_RETURN_OK)
875
  {
876
    con->drizzle->last_errno= errno;
877
    return dret;
878
  }
879
880
  while (1)
881
  {
882
    ret= connect(con->fd, con->addrinfo_next->ai_addr,
883
                 con->addrinfo_next->ai_addrlen);
884
885
#ifdef _WIN32
886
    errno = WSAGetLastError();
887
    switch(errno) {
888
    case WSAEINVAL:
889
    case WSAEALREADY:
890
    case WSAEWOULDBLOCK:
2263.4.1 by Monty Taylor
Updated the windows/posix error mapping as per notes from Marc Isambart.
891
      errno= EINPROGRESS;
892
      break;
2269.2.1 by Marc Isambart
Various libdrizzle Windows fixes, including closesocket() instead of close(), snprintf handling and WSAECONNREFUSED mapping
893
    case WSAECONNREFUSED:
894
      errno= ECONNREFUSED;
895
      break;
2263.4.1 by Monty Taylor
Updated the windows/posix error mapping as per notes from Marc Isambart.
896
    case WSAENETUNREACH:
897
      errno= ENETUNREACH;
898
      break;
899
    case WSAETIMEDOUT:
900
      errno= ETIMEDOUT;
901
      break;
902
    case WSAECONNRESET:
903
      errno= ECONNRESET;
904
      break;
905
    case WSAEADDRINUSE:
906
      errno= EADDRINUSE;
907
      break;
908
    case WSAEOPNOTSUPP:
909
      errno= EOPNOTSUPP;
910
      break;
911
    case WSAENOPROTOOPT:
912
      errno= ENOPROTOOPT;
1712.1.1 by Monty Taylor
Merged libdrizzle directly into tree.
913
      break;
914
    default:
915
      break;
916
    }
917
#endif /* _WIN32 */
918
	
919
    drizzle_log_crazy(con->drizzle, "connect return=%d errno=%d", ret, errno);
920
921
    if (ret == 0)
922
    {
923
      con->addrinfo_next= NULL;
924
      break;
925
    }
926
927
    if (errno == EAGAIN || errno == EINTR)
928
      continue;
929
930
    if (errno == EINPROGRESS)
931
    {
932
      drizzle_state_pop(con);
933
      drizzle_state_push(con, drizzle_state_connecting);
934
      return DRIZZLE_RETURN_OK;
935
    }
936
937
    if (errno == ECONNREFUSED || errno == ENETUNREACH || errno == ETIMEDOUT)
938
    {
939
      con->addrinfo_next= con->addrinfo_next->ai_next;
940
      return DRIZZLE_RETURN_OK;
941
    }
942
943
    drizzle_set_error(con->drizzle, "drizzle_state_connect", "connect:%d",
944
                      errno);
945
    con->drizzle->last_errno= errno;
946
    return DRIZZLE_RETURN_ERRNO;
947
  }
948
949
  drizzle_state_pop(con);
950
  return DRIZZLE_RETURN_OK;
951
}
952
953
drizzle_return_t drizzle_state_connecting(drizzle_con_st *con)
954
{
955
  drizzle_return_t ret;
956
957
  drizzle_log_debug(con->drizzle, "drizzle_state_connecting");
958
959
  while (1)
960
  {
961
    if (con->revents & POLLOUT)
962
    {
963
      drizzle_state_pop(con);
964
      return DRIZZLE_RETURN_OK;
965
    }
966
    else if (con->revents & (POLLERR | POLLHUP | POLLNVAL))
967
    {
968
      con->revents= 0;
969
      drizzle_state_pop(con);
970
      drizzle_state_push(con, drizzle_state_connect);
971
      con->addrinfo_next= con->addrinfo_next->ai_next;
972
      return DRIZZLE_RETURN_OK;
973
    }
974
975
    ret= drizzle_con_set_events(con, POLLOUT);
976
    if (ret != DRIZZLE_RETURN_OK)
977
      return ret;
978
979
    if (con->drizzle->options & DRIZZLE_NON_BLOCKING)
980
      return DRIZZLE_RETURN_IO_WAIT;
981
982
    ret= drizzle_con_wait(con->drizzle);
983
    if (ret != DRIZZLE_RETURN_OK)
984
      return ret;
985
  }
986
}
987
988
drizzle_return_t drizzle_state_read(drizzle_con_st *con)
989
{
990
  drizzle_return_t ret;
991
  ssize_t read_size;
992
993
  drizzle_log_debug(con->drizzle, "drizzle_state_read");
994
995
  if (con->buffer_size == 0)
996
    con->buffer_ptr= con->buffer;
997
  else if ((con->buffer_ptr - con->buffer) > (DRIZZLE_MAX_BUFFER_SIZE / 2))
998
  {
999
    memmove(con->buffer, con->buffer_ptr, con->buffer_size);
1000
    con->buffer_ptr= con->buffer;
1001
  }
1002
2046.1.2 by Evan Jones
libdrizzle: drizzle_state_read: only call recv() if data is available.
1003
  if ((con->revents & POLLIN) == 0 &&
1004
      (con->drizzle->options & DRIZZLE_NON_BLOCKING))
1005
  {
1006
    /* non-blocking mode: return IO_WAIT instead of attempting to read. This
1007
     * avoids reading immediately after writing a command, which typically
1008
     * returns EAGAIN. This improves performance. */
1009
    ret= drizzle_con_set_events(con, POLLIN);
1010
    if (ret != DRIZZLE_RETURN_OK)
1011
      return ret;
1012
    return DRIZZLE_RETURN_IO_WAIT;
1013
  }
1014
1712.1.1 by Monty Taylor
Merged libdrizzle directly into tree.
1015
  while (1)
1016
  {
2046.1.2 by Evan Jones
libdrizzle: drizzle_state_read: only call recv() if data is available.
1017
    size_t available_buffer= (size_t)DRIZZLE_MAX_BUFFER_SIZE -
1018
        ((size_t)(con->buffer_ptr - con->buffer) + con->buffer_size);
1712.1.1 by Monty Taylor
Merged libdrizzle directly into tree.
1019
    read_size = recv(con->fd, (char *)con->buffer_ptr + con->buffer_size,
2046.1.2 by Evan Jones
libdrizzle: drizzle_state_read: only call recv() if data is available.
1020
                     available_buffer, 0);
1712.1.1 by Monty Taylor
Merged libdrizzle directly into tree.
1021
#ifdef _WIN32
1022
    errno = WSAGetLastError();
1023
    switch(errno) {
2263.4.1 by Monty Taylor
Updated the windows/posix error mapping as per notes from Marc Isambart.
1024
    case WSAENOTCONN:
1712.1.1 by Monty Taylor
Merged libdrizzle directly into tree.
1025
    case WSAEWOULDBLOCK:
2263.4.1 by Monty Taylor
Updated the windows/posix error mapping as per notes from Marc Isambart.
1026
      errno= EAGAIN;
1027
      break;
1028
    case WSAEINVAL:
1029
    case WSAEALREADY:
2269.2.1 by Marc Isambart
Various libdrizzle Windows fixes, including closesocket() instead of close(), snprintf handling and WSAECONNREFUSED mapping
1030
      errno= EINPROGRESS;
1031
      break;
2263.4.1 by Monty Taylor
Updated the windows/posix error mapping as per notes from Marc Isambart.
1032
    case WSAECONNREFUSED:
2269.2.1 by Marc Isambart
Various libdrizzle Windows fixes, including closesocket() instead of close(), snprintf handling and WSAECONNREFUSED mapping
1033
      errno= ECONNREFUSED;
2263.4.1 by Monty Taylor
Updated the windows/posix error mapping as per notes from Marc Isambart.
1034
      break;
1035
    case WSAENETUNREACH:
1036
      errno= ENETUNREACH;
1037
      break;
1038
    case WSAETIMEDOUT:
1039
      errno= ETIMEDOUT;
1040
      break;
1041
    case WSAECONNRESET:
1042
      errno= ECONNRESET;
1043
      break;
1044
    case WSAEADDRINUSE:
1045
      errno= EADDRINUSE;
1046
      break;
1047
    case WSAEOPNOTSUPP:
1048
      errno= EOPNOTSUPP;
1049
      break;
1050
    case WSAENOPROTOOPT:
1051
      errno= ENOPROTOOPT;
1712.1.1 by Monty Taylor
Merged libdrizzle directly into tree.
1052
      break;
1053
    default:
1054
      break;
1055
    }
1056
#endif /* _WIN32 */	
1057
    drizzle_log_crazy(con->drizzle, "read fd=%d return=%zd errno=%d", con->fd,
1058
                      read_size, errno);
1059
1060
    if (read_size == 0)
1061
    {
1062
      drizzle_set_error(con->drizzle, "drizzle_state_read",
1063
                        "lost connection to server (EOF)");
1064
      return DRIZZLE_RETURN_LOST_CONNECTION;
1065
    }
1066
    else if (read_size == -1)
1067
    {
1068
      if (errno == EAGAIN)
1069
      {
2046.1.2 by Evan Jones
libdrizzle: drizzle_state_read: only call recv() if data is available.
1070
        /* clear the read ready flag */
1071
        con->revents&= ~POLLIN;
1712.1.1 by Monty Taylor
Merged libdrizzle directly into tree.
1072
        ret= drizzle_con_set_events(con, POLLIN);
1073
        if (ret != DRIZZLE_RETURN_OK)
2046.1.1 by Evan Jones
libdrizzle: fix minor errors in drizzle_state_read
1074
          return ret;
1712.1.1 by Monty Taylor
Merged libdrizzle directly into tree.
1075
1076
        if (con->drizzle->options & DRIZZLE_NON_BLOCKING)
1077
          return DRIZZLE_RETURN_IO_WAIT;
1078
1079
        ret= drizzle_con_wait(con->drizzle);
1080
        if (ret != DRIZZLE_RETURN_OK)
1081
          return ret;
1082
1083
        continue;
1084
      }
1085
      else if (errno == ECONNREFUSED)
1086
      {
1087
        con->revents= 0;
1088
        drizzle_state_pop(con);
1089
        drizzle_state_push(con, drizzle_state_connect);
1090
        con->addrinfo_next= con->addrinfo_next->ai_next;
1091
        return DRIZZLE_RETURN_OK;
1092
      }
1093
      else if (errno == EINTR)
1094
        continue;
1095
      else if (errno == EPIPE || errno == ECONNRESET)
1096
      {
1097
        drizzle_set_error(con->drizzle, "drizzle_state_read",
1098
                          "lost connection to server (%d)", errno);
1099
        return DRIZZLE_RETURN_LOST_CONNECTION;
1100
      }
1101
1102
      drizzle_set_error(con->drizzle, "drizzle_state_read", "read:%d", errno);
1103
      con->drizzle->last_errno= errno;
1104
      return DRIZZLE_RETURN_ERRNO;
1105
    }
1106
2046.1.2 by Evan Jones
libdrizzle: drizzle_state_read: only call recv() if data is available.
1107
    /* clear the "read ready" flag if we read all available data. */
1108
    if ((size_t) read_size < available_buffer) con->revents&= ~POLLIN;
1712.1.1 by Monty Taylor
Merged libdrizzle directly into tree.
1109
    con->buffer_size+= (size_t)read_size;
1110
    break;
1111
  }
1112
2046.1.1 by Evan Jones
libdrizzle: fix minor errors in drizzle_state_read
1113
  drizzle_state_pop(con);
1712.1.1 by Monty Taylor
Merged libdrizzle directly into tree.
1114
  return DRIZZLE_RETURN_OK;
1115
}
1116
1117
drizzle_return_t drizzle_state_write(drizzle_con_st *con)
1118
{
1119
  drizzle_return_t ret;
1120
  ssize_t write_size;
1121
1122
  drizzle_log_debug(con->drizzle, "drizzle_state_write");
1123
1124
  while (con->buffer_size != 0)
1125
  {
1126
  
1877.1.5 by Andrew Hutchings
Fix min() usage for 32bit
1127
    write_size = send(con->fd,(char *) con->buffer_ptr, con->buffer_size, 0);
1712.1.1 by Monty Taylor
Merged libdrizzle directly into tree.
1128
2263.4.1 by Monty Taylor
Updated the windows/posix error mapping as per notes from Marc Isambart.
1129
#ifdef _WIN32
1130
    errno = WSAGetLastError();
1131
    switch(errno) {
1132
    case WSAENOTCONN:
1133
    case WSAEWOULDBLOCK:
1134
      errno= EAGAIN;
1135
      break;
1136
    case WSAEINVAL:
1137
    case WSAEALREADY:
2269.2.1 by Marc Isambart
Various libdrizzle Windows fixes, including closesocket() instead of close(), snprintf handling and WSAECONNREFUSED mapping
1138
      errno= EINPROGRESS;
1139
      break;
2263.4.1 by Monty Taylor
Updated the windows/posix error mapping as per notes from Marc Isambart.
1140
    case WSAECONNREFUSED:
2269.2.1 by Marc Isambart
Various libdrizzle Windows fixes, including closesocket() instead of close(), snprintf handling and WSAECONNREFUSED mapping
1141
      errno= ECONNREFUSED;
2263.4.1 by Monty Taylor
Updated the windows/posix error mapping as per notes from Marc Isambart.
1142
      break;
1143
    case WSAENETUNREACH:
1144
      errno= ENETUNREACH;
1145
      break;
1146
    case WSAETIMEDOUT:
1147
      errno= ETIMEDOUT;
1148
      break;
1149
    case WSAECONNRESET:
1150
      errno= ECONNRESET;
1151
      break;
1152
    case WSAEADDRINUSE:
1153
      errno= EADDRINUSE;
1154
      break;
1155
    case WSAEOPNOTSUPP:
1156
      errno= EOPNOTSUPP;
1157
      break;
1158
    case WSAENOPROTOOPT:
1159
      errno= ENOPROTOOPT;
1160
      break;
1161
    default:
1162
      break;
1163
    }
1164
#endif /* _WIN32 */	
1165
1712.1.1 by Monty Taylor
Merged libdrizzle directly into tree.
1166
    drizzle_log_crazy(con->drizzle, "write fd=%d return=%zd errno=%d", con->fd,
1167
                      write_size, errno);
1168
1169
    if (write_size == 0)
1170
    {
1171
      drizzle_set_error(con->drizzle, "drizzle_state_write",
1172
                        "lost connection to server (EOF)");
1173
      return DRIZZLE_RETURN_LOST_CONNECTION;
1174
    }
1175
    else if (write_size == -1)
1176
    {
1177
      if (errno == EAGAIN)
1178
      {
1179
        ret= drizzle_con_set_events(con, POLLOUT);
1180
        if (ret != DRIZZLE_RETURN_OK)
1181
          return ret;
1182
1183
        if (con->drizzle->options & DRIZZLE_NON_BLOCKING)
1184
          return DRIZZLE_RETURN_IO_WAIT;
1185
1186
        ret= drizzle_con_wait(con->drizzle);
1187
        if (ret != DRIZZLE_RETURN_OK)
1188
          return ret;
1189
1190
        continue;
1191
      }
1192
      else if (errno == EINTR)
1193
        continue;
1194
      else if (errno == EPIPE || errno == ECONNRESET)
1195
      {
1196
        drizzle_set_error(con->drizzle, "drizzle_state_write",
1197
                          "lost connection to server (%d)", errno);
1198
        return DRIZZLE_RETURN_LOST_CONNECTION;
1199
      }
1200
1201
      drizzle_set_error(con->drizzle, "drizzle_state_write", "write:%d", errno);
1202
      con->drizzle->last_errno= errno;
1203
      return DRIZZLE_RETURN_ERRNO;
1204
    }
1205
1206
    con->buffer_ptr+= write_size;
1207
    con->buffer_size-= (size_t)write_size;
1208
    if (con->buffer_size == 0)
1209
      break;
1210
  }
1211
1212
  con->buffer_ptr= con->buffer;
1213
1214
  drizzle_state_pop(con);
1215
  return DRIZZLE_RETURN_OK;
1216
}
1217
1218
drizzle_return_t drizzle_state_listen(drizzle_con_st *con)
1219
{
1220
  char host[NI_MAXHOST];
1221
  char port[NI_MAXSERV];
1222
  int ret;
1223
  int fd;
1224
  int opt;
1225
  drizzle_con_st *new_con;
1226
1227
  for (; con->addrinfo_next != NULL;
1228
       con->addrinfo_next= con->addrinfo_next->ai_next)
1229
  {
1230
    ret= getnameinfo(con->addrinfo_next->ai_addr,
1231
                     con->addrinfo_next->ai_addrlen, host, NI_MAXHOST, port,
1232
                     NI_MAXSERV, NI_NUMERICHOST | NI_NUMERICSERV);
1233
    if (ret != 0)
1234
    {
1235
      drizzle_set_error(con->drizzle, "drizzle_state_listen", "getnameinfo:%s",
1236
                        gai_strerror(ret));
1237
      return DRIZZLE_RETURN_GETADDRINFO;
1238
    }
1239
1240
    /* Call to socket() can fail for some getaddrinfo results, try another. */
1241
    fd= socket(con->addrinfo_next->ai_family, con->addrinfo_next->ai_socktype,
1242
               con->addrinfo_next->ai_protocol);
1243
    if (fd == -1)
1244
    {
1245
      drizzle_log_info(con->drizzle, "could not listen on %s:%s", host, port);
1246
      drizzle_set_error(con->drizzle, "drizzle_state_listen", "socket:%d",
1247
                        errno);
1248
      continue;
1249
    }
1250
	
1251
	opt= 1;
1252
#ifdef _WIN32
1253
        ret= setsockopt(fd, SOL_SOCKET, SO_REUSEADDR,(const char*) &opt, sizeof(opt));
1254
#else
1255
        ret= setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt));
1256
#endif /* _WIN32 */
1257
    if (ret == -1)
1258
    {
2269.2.1 by Marc Isambart
Various libdrizzle Windows fixes, including closesocket() instead of close(), snprintf handling and WSAECONNREFUSED mapping
1259
      closesocket(fd);
1712.1.1 by Monty Taylor
Merged libdrizzle directly into tree.
1260
      drizzle_set_error(con->drizzle, "drizzle_state_listen", "setsockopt:%d",
1261
                        errno);
1262
      return DRIZZLE_RETURN_ERRNO;
1263
    }
1264
1265
    ret= bind(fd, con->addrinfo_next->ai_addr, con->addrinfo_next->ai_addrlen);
1266
    if (ret == -1)
1267
    {
2269.2.1 by Marc Isambart
Various libdrizzle Windows fixes, including closesocket() instead of close(), snprintf handling and WSAECONNREFUSED mapping
1268
      closesocket(fd);
1712.1.1 by Monty Taylor
Merged libdrizzle directly into tree.
1269
      drizzle_set_error(con->drizzle, "drizzle_state_listen", "bind:%d", errno);
1270
      if (errno == EADDRINUSE)
1271
      {
1272
        if (con->fd == -1)
1273
        {
1274
          drizzle_log_info(con->drizzle, "could not listen on %s:%s", host,
1275
                           port);
1276
        }
1277
1278
        continue;
1279
      }
1280
1281
      return DRIZZLE_RETURN_ERRNO;
1282
    }
1283
1284
    if (listen(fd, con->backlog) == -1)
1285
    {
2269.2.1 by Marc Isambart
Various libdrizzle Windows fixes, including closesocket() instead of close(), snprintf handling and WSAECONNREFUSED mapping
1286
      closesocket(fd);
1712.1.1 by Monty Taylor
Merged libdrizzle directly into tree.
1287
      drizzle_set_error(con->drizzle, "drizzle_state_listen", "listen:%d",
1288
                        errno);
1289
      return DRIZZLE_RETURN_ERRNO;
1290
    }
1291
1292
    if (con->fd == -1)
1293
    {
1294
      con->fd= fd;
1295
      new_con= con;
1296
    }
1297
    else
1298
    {
1299
      new_con= drizzle_con_clone(con->drizzle, NULL, con);
1300
      if (new_con == NULL)
1301
      {
2269.2.1 by Marc Isambart
Various libdrizzle Windows fixes, including closesocket() instead of close(), snprintf handling and WSAECONNREFUSED mapping
1302
        closesocket(fd);
1712.1.1 by Monty Taylor
Merged libdrizzle directly into tree.
1303
        return DRIZZLE_RETURN_MEMORY;
1304
      }
1305
1306
      new_con->fd= fd;
1307
    }
1308
1309
    /* Wait for read events on the listening socket. */
1992.6.7 by Monty Taylor
Revert -Wc++-compat change.
1310
    ret= drizzle_con_set_events(new_con, POLLIN);
1712.1.1 by Monty Taylor
Merged libdrizzle directly into tree.
1311
    if (ret != DRIZZLE_RETURN_OK)
1312
    {
1313
      drizzle_con_free(new_con);
1992.6.7 by Monty Taylor
Revert -Wc++-compat change.
1314
      return ret;
1712.1.1 by Monty Taylor
Merged libdrizzle directly into tree.
1315
    }
1316
1317
    drizzle_log_info(con->drizzle, "listening on %s:%s", host, port);
1318
  }
1319
1320
  /* Report last socket() error if we couldn't find an address to bind. */
1321
  if (con->fd == -1)
1322
    return DRIZZLE_RETURN_ERRNO;
1323
1324
  drizzle_state_pop(con);
1325
  return DRIZZLE_RETURN_OK;
1326
}
1327
1328
/*
1329
 * Static Definitions
1330
 */
1331
1332
static drizzle_return_t _con_setsockopt(drizzle_con_st *con)
1333
{
1334
  int ret;
1335
  struct linger linger;
1336
  struct timeval waittime;
1337
1338
  ret= 1;
1339
1340
#ifdef _WIN32
1341
  ret= setsockopt(con->fd, IPPROTO_TCP, TCP_NODELAY, (const char*)&ret,
1342
                  (socklen_t)sizeof(int));
1343
#else
1344
  ret= setsockopt(con->fd, IPPROTO_TCP, TCP_NODELAY, &ret,
1345
                  (socklen_t)sizeof(int));
1346
#endif /* _WIN32 */
1347
1348
  if (ret == -1 && errno != EOPNOTSUPP)
1349
  {
1350
    drizzle_set_error(con->drizzle, "_con_setsockopt",
1351
                      "setsockopt:TCP_NODELAY:%d", errno);
1352
    return DRIZZLE_RETURN_ERRNO;
1353
  }
1354
1355
  linger.l_onoff= 1;
1356
  linger.l_linger= DRIZZLE_DEFAULT_SOCKET_TIMEOUT;
1357
1358
#ifdef _WIN32
1359
  ret= setsockopt(con->fd, SOL_SOCKET, SO_LINGER, (const char*)&linger,
1360
                  (socklen_t)sizeof(struct linger));
1361
#else
1362
  ret= setsockopt(con->fd, SOL_SOCKET, SO_LINGER, &linger,
1363
                  (socklen_t)sizeof(struct linger));
1364
#endif /* _WIN32 */
1365
1366
  if (ret == -1)
1367
  {
1368
    drizzle_set_error(con->drizzle, "_con_setsockopt",
1369
                      "setsockopt:SO_LINGER:%d", errno);
1370
    return DRIZZLE_RETURN_ERRNO;
1371
  }
1372
1373
  waittime.tv_sec= DRIZZLE_DEFAULT_SOCKET_TIMEOUT;
1374
  waittime.tv_usec= 0;
1375
1376
#ifdef _WIN32
1377
  ret= setsockopt(con->fd, SOL_SOCKET, SO_SNDTIMEO, (const char*)&waittime,
1378
                  (socklen_t)sizeof(struct timeval));
1379
#else
1380
  ret= setsockopt(con->fd, SOL_SOCKET, SO_SNDTIMEO, &waittime,
1381
                  (socklen_t)sizeof(struct timeval));
1382
#endif /* _WIN32 */
1383
1384
  if (ret == -1 && errno != ENOPROTOOPT)
1385
  {
1386
    drizzle_set_error(con->drizzle, "_con_setsockopt",
1387
                      "setsockopt:SO_SNDTIMEO:%d", errno);
1388
    return DRIZZLE_RETURN_ERRNO;
1389
  }
1390
1391
#ifdef _WIN32
1392
  ret= setsockopt(con->fd, SOL_SOCKET, SO_RCVTIMEO, (const char*)&waittime,
1393
                  (socklen_t)sizeof(struct timeval));
1394
#else
1395
  ret= setsockopt(con->fd, SOL_SOCKET, SO_RCVTIMEO, &waittime,
1396
                  (socklen_t)sizeof(struct timeval));
1397
#endif /* _WIN32 */
1398
1399
  if (ret == -1 && errno != ENOPROTOOPT)
1400
  {
1401
    drizzle_set_error(con->drizzle, "_con_setsockopt",
1402
                      "setsockopt:SO_RCVTIMEO:%d", errno);
1403
    return DRIZZLE_RETURN_ERRNO;
1404
  }
1405
1406
  ret= DRIZZLE_DEFAULT_SOCKET_SEND_SIZE;
1407
#ifdef _WIN32
1408
  ret= setsockopt(con->fd, SOL_SOCKET, SO_SNDBUF, (const char*)&ret, (socklen_t)sizeof(int));
1409
#else
1410
  ret= setsockopt(con->fd, SOL_SOCKET, SO_SNDBUF, &ret, (socklen_t)sizeof(int));
1411
#endif /* _WIN32 */
1412
  if (ret == -1)
1413
  {
1414
    drizzle_set_error(con->drizzle, "_con_setsockopt",
1415
                      "setsockopt:SO_SNDBUF:%d", errno);
1416
    return DRIZZLE_RETURN_ERRNO;
1417
  }
1418
1419
  ret= DRIZZLE_DEFAULT_SOCKET_RECV_SIZE;
1420
#ifdef _WIN32
1421
  ret= setsockopt(con->fd, SOL_SOCKET, SO_RCVBUF, (const char*)&ret, (socklen_t)sizeof(int));
1422
#else
1423
  ret= setsockopt(con->fd, SOL_SOCKET, SO_RCVBUF, &ret, (socklen_t)sizeof(int));
1424
#endif /* _WIN32 */
1425
  if (ret == -1)
1426
  {
1427
    drizzle_set_error(con->drizzle, "_con_setsockopt",
1428
                      "setsockopt:SO_RCVBUF:%d", errno);
1429
    return DRIZZLE_RETURN_ERRNO;
1430
  }
1431
1432
#if defined (_WIN32)
2164.1.1 by Monty Taylor
Merged in outstanding changes from the win32 work.
1433
  {
1434
    unsigned long asyncmode;
1435
    asyncmode= 1;
1436
    ioctlsocket(con->fd, FIONBIO, &asyncmode);
1437
  }
1712.1.1 by Monty Taylor
Merged libdrizzle directly into tree.
1438
#else
1439
  ret= fcntl(con->fd, F_GETFL, 0);
1440
  if (ret == -1)
1441
  {
1442
    drizzle_set_error(con->drizzle, "_con_setsockopt", "fcntl:F_GETFL:%d",
1443
                      errno);
1444
    return DRIZZLE_RETURN_ERRNO;
1445
  }
1446
1447
  ret= fcntl(con->fd, F_SETFL, ret | O_NONBLOCK);
1448
  if (ret == -1)
1449
  {
1450
    drizzle_set_error(con->drizzle, "_con_setsockopt", "fcntl:F_SETFL:%d",
1451
                      errno);
1452
    return DRIZZLE_RETURN_ERRNO;
1453
  }
1454
#endif
1455
1456
  return DRIZZLE_RETURN_OK;
1457
}