~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
2464.1.2 by Brian Aker
Fix compiling issues for 1.0, and cleanup header files.
92
  con->options&= int(~DRIZZLE_CON_READY);
1712.1.1 by Monty Taylor
Merged libdrizzle directly into tree.
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
{
2464.1.2 by Brian Aker
Fix compiling issues for 1.0, and cleanup header files.
182
  return drizzle_con_options_t(con->options);
1712.1.1 by Monty Taylor
Merged libdrizzle directly into tree.
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
  {
2464.1.2 by Brian Aker
Fix compiling issues for 1.0, and cleanup header files.
199
    con->options&= int(~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
{
2464.1.2 by Brian Aker
Fix compiling issues for 1.0, and cleanup header files.
359
  return drizzle_capabilities_t(con->capabilities);
1712.1.1 by Monty Taylor
Merged libdrizzle directly into tree.
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);
2464.1.2 by Brian Aker
Fix compiling issues for 1.0, and cleanup header files.
657
  drizzle_con_set_capabilities(con, drizzle_capabilities_t(from->capabilities));
1712.1.1 by Monty Taylor
Merged libdrizzle directly into tree.
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
  size_t offset= 0;
696
  size_t size= 0;
697
2464.1.2 by Brian Aker
Fix compiling issues for 1.0, and cleanup header files.
698
  char *command_data= (char *)drizzle_con_command_read(con, command, &offset, &size, total, ret_ptr);
1712.1.1 by Monty Taylor
Merged libdrizzle directly into tree.
699
  if (*ret_ptr != DRIZZLE_RETURN_OK)
700
    return NULL;
701
702
  if (command_data == NULL)
703
  {
704
    *total= 0;
705
    return NULL;
706
  }
707
708
  if (con->command_buffer == NULL)
709
  {
2464.1.2 by Brian Aker
Fix compiling issues for 1.0, and cleanup header files.
710
    con->command_buffer= (uint8_t*)malloc((*total) + 1);
1712.1.1 by Monty Taylor
Merged libdrizzle directly into tree.
711
    if (con->command_buffer == NULL)
712
    {
713
      drizzle_set_error(con->drizzle, "drizzle_command_buffer", "malloc");
714
      *ret_ptr= DRIZZLE_RETURN_MEMORY;
715
      return NULL;
716
    }
717
  }
718
719
  memcpy(con->command_buffer + offset, command_data, size);
720
721
  while ((offset + size) != (*total))
722
  {
2464.1.2 by Brian Aker
Fix compiling issues for 1.0, and cleanup header files.
723
    command_data= (char *)drizzle_con_command_read(con, command, &offset, &size, total, ret_ptr);
1712.1.1 by Monty Taylor
Merged libdrizzle directly into tree.
724
    if (*ret_ptr != DRIZZLE_RETURN_OK)
725
      return NULL;
726
727
    memcpy(con->command_buffer + offset, command_data, size);
728
  }
729
2464.1.2 by Brian Aker
Fix compiling issues for 1.0, and cleanup header files.
730
  command_data= (char *)con->command_buffer;
1712.1.1 by Monty Taylor
Merged libdrizzle directly into tree.
731
  con->command_buffer= NULL;
732
  command_data[*total]= 0;
733
734
  return command_data;
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);
2269.2.1 by Marc Isambart
Various libdrizzle Windows fixes, including closesocket() instead of close(), snprintf handling and WSAECONNREFUSED mapping
795
    port[NI_MAXSERV-1]= 0;
1712.1.1 by Monty Taylor
Merged libdrizzle directly into tree.
796
797
    memset(&ai, 0, sizeof(struct addrinfo));
798
    ai.ai_socktype= SOCK_STREAM;
799
    ai.ai_protocol= IPPROTO_TCP;
2235.1.3 by Andrew Hutchings
Fix addrinfo flags not set correctly
800
    ai.ai_flags = AI_PASSIVE;
801
    ai.ai_family = AF_UNSPEC;
1712.1.1 by Monty Taylor
Merged libdrizzle directly into tree.
802
803
    if (con->options & DRIZZLE_CON_LISTEN)
804
    {
805
      host= tcp->host;
806
    }
807
    else
808
    {
809
      if (tcp->host == NULL)
810
        host= DRIZZLE_DEFAULT_TCP_HOST;
811
      else
812
        host= tcp->host;
813
    }
814
815
    ret= getaddrinfo(host, port, &ai, &(tcp->addrinfo));
816
    if (ret != 0)
817
    {
818
      drizzle_set_error(con->drizzle, "drizzle_state_addrinfo",
819
                        "getaddrinfo:%s", gai_strerror(ret));
820
      return DRIZZLE_RETURN_GETADDRINFO;
821
    }
822
823
    con->addrinfo_next= tcp->addrinfo;
824
825
    break;
826
827
  case DRIZZLE_CON_SOCKET_UDS:
828
    con->addrinfo_next= &(con->socket.uds.addrinfo);
829
    break;
830
831
  default:
832
    break;
833
  }
834
835
  drizzle_state_pop(con);
836
  return DRIZZLE_RETURN_OK;
837
}
838
839
drizzle_return_t drizzle_state_connect(drizzle_con_st *con)
840
{
841
  int ret;
842
  drizzle_return_t dret;
843
844
  drizzle_log_debug(con->drizzle, "drizzle_state_connect");
845
846
  if (con->fd != -1)
847
  {
2269.2.1 by Marc Isambart
Various libdrizzle Windows fixes, including closesocket() instead of close(), snprintf handling and WSAECONNREFUSED mapping
848
    (void)closesocket(con->fd);
1712.1.1 by Monty Taylor
Merged libdrizzle directly into tree.
849
    con->fd= -1;
850
  }
851
852
  if (con->addrinfo_next == NULL)
853
  {
854
    drizzle_set_error(con->drizzle, "drizzle_state_connect",
855
                      "could not connect");
856
    drizzle_state_reset(con);
857
    return DRIZZLE_RETURN_COULD_NOT_CONNECT;
858
  }
859
860
  con->fd= socket(con->addrinfo_next->ai_family,
861
                  con->addrinfo_next->ai_socktype,
862
                  con->addrinfo_next->ai_protocol);
863
  if (con->fd == -1)
864
  {
865
    drizzle_set_error(con->drizzle, "drizzle_state_connect", "socket:%d",
866
                      errno);
867
    con->drizzle->last_errno= errno;
868
    return DRIZZLE_RETURN_ERRNO;
869
  }
870
871
  dret= _con_setsockopt(con);
872
  if (dret != DRIZZLE_RETURN_OK)
873
  {
874
    con->drizzle->last_errno= errno;
875
    return dret;
876
  }
877
878
  while (1)
879
  {
880
    ret= connect(con->fd, con->addrinfo_next->ai_addr,
881
                 con->addrinfo_next->ai_addrlen);
882
883
#ifdef _WIN32
884
    errno = WSAGetLastError();
885
    switch(errno) {
886
    case WSAEINVAL:
887
    case WSAEALREADY:
888
    case WSAEWOULDBLOCK:
2263.4.1 by Monty Taylor
Updated the windows/posix error mapping as per notes from Marc Isambart.
889
      errno= EINPROGRESS;
890
      break;
2269.2.1 by Marc Isambart
Various libdrizzle Windows fixes, including closesocket() instead of close(), snprintf handling and WSAECONNREFUSED mapping
891
    case WSAECONNREFUSED:
892
      errno= ECONNREFUSED;
893
      break;
2263.4.1 by Monty Taylor
Updated the windows/posix error mapping as per notes from Marc Isambart.
894
    case WSAENETUNREACH:
895
      errno= ENETUNREACH;
896
      break;
897
    case WSAETIMEDOUT:
898
      errno= ETIMEDOUT;
899
      break;
900
    case WSAECONNRESET:
901
      errno= ECONNRESET;
902
      break;
903
    case WSAEADDRINUSE:
904
      errno= EADDRINUSE;
905
      break;
906
    case WSAEOPNOTSUPP:
907
      errno= EOPNOTSUPP;
908
      break;
909
    case WSAENOPROTOOPT:
910
      errno= ENOPROTOOPT;
1712.1.1 by Monty Taylor
Merged libdrizzle directly into tree.
911
      break;
912
    default:
913
      break;
914
    }
915
#endif /* _WIN32 */
916
	
917
    drizzle_log_crazy(con->drizzle, "connect return=%d errno=%d", ret, errno);
918
919
    if (ret == 0)
920
    {
921
      con->addrinfo_next= NULL;
922
      break;
923
    }
924
925
    if (errno == EAGAIN || errno == EINTR)
926
      continue;
927
928
    if (errno == EINPROGRESS)
929
    {
930
      drizzle_state_pop(con);
931
      drizzle_state_push(con, drizzle_state_connecting);
932
      return DRIZZLE_RETURN_OK;
933
    }
934
935
    if (errno == ECONNREFUSED || errno == ENETUNREACH || errno == ETIMEDOUT)
936
    {
937
      con->addrinfo_next= con->addrinfo_next->ai_next;
938
      return DRIZZLE_RETURN_OK;
939
    }
940
941
    drizzle_set_error(con->drizzle, "drizzle_state_connect", "connect:%d",
942
                      errno);
943
    con->drizzle->last_errno= errno;
944
    return DRIZZLE_RETURN_ERRNO;
945
  }
946
947
  drizzle_state_pop(con);
948
  return DRIZZLE_RETURN_OK;
949
}
950
951
drizzle_return_t drizzle_state_connecting(drizzle_con_st *con)
952
{
953
  drizzle_return_t ret;
954
955
  drizzle_log_debug(con->drizzle, "drizzle_state_connecting");
956
957
  while (1)
958
  {
959
    if (con->revents & POLLOUT)
960
    {
961
      drizzle_state_pop(con);
962
      return DRIZZLE_RETURN_OK;
963
    }
964
    else if (con->revents & (POLLERR | POLLHUP | POLLNVAL))
965
    {
966
      con->revents= 0;
967
      drizzle_state_pop(con);
968
      drizzle_state_push(con, drizzle_state_connect);
969
      con->addrinfo_next= con->addrinfo_next->ai_next;
970
      return DRIZZLE_RETURN_OK;
971
    }
972
973
    ret= drizzle_con_set_events(con, POLLOUT);
974
    if (ret != DRIZZLE_RETURN_OK)
975
      return ret;
976
977
    if (con->drizzle->options & DRIZZLE_NON_BLOCKING)
978
      return DRIZZLE_RETURN_IO_WAIT;
979
980
    ret= drizzle_con_wait(con->drizzle);
981
    if (ret != DRIZZLE_RETURN_OK)
982
      return ret;
983
  }
984
}
985
986
drizzle_return_t drizzle_state_read(drizzle_con_st *con)
987
{
988
  drizzle_return_t ret;
989
  ssize_t read_size;
990
991
  drizzle_log_debug(con->drizzle, "drizzle_state_read");
992
993
  if (con->buffer_size == 0)
994
    con->buffer_ptr= con->buffer;
995
  else if ((con->buffer_ptr - con->buffer) > (DRIZZLE_MAX_BUFFER_SIZE / 2))
996
  {
997
    memmove(con->buffer, con->buffer_ptr, con->buffer_size);
998
    con->buffer_ptr= con->buffer;
999
  }
1000
2046.1.2 by Evan Jones
libdrizzle: drizzle_state_read: only call recv() if data is available.
1001
  if ((con->revents & POLLIN) == 0 &&
1002
      (con->drizzle->options & DRIZZLE_NON_BLOCKING))
1003
  {
1004
    /* non-blocking mode: return IO_WAIT instead of attempting to read. This
1005
     * avoids reading immediately after writing a command, which typically
1006
     * returns EAGAIN. This improves performance. */
1007
    ret= drizzle_con_set_events(con, POLLIN);
1008
    if (ret != DRIZZLE_RETURN_OK)
1009
      return ret;
1010
    return DRIZZLE_RETURN_IO_WAIT;
1011
  }
1012
1712.1.1 by Monty Taylor
Merged libdrizzle directly into tree.
1013
  while (1)
1014
  {
2046.1.2 by Evan Jones
libdrizzle: drizzle_state_read: only call recv() if data is available.
1015
    size_t available_buffer= (size_t)DRIZZLE_MAX_BUFFER_SIZE -
1016
        ((size_t)(con->buffer_ptr - con->buffer) + con->buffer_size);
1712.1.1 by Monty Taylor
Merged libdrizzle directly into tree.
1017
    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.
1018
                     available_buffer, 0);
1712.1.1 by Monty Taylor
Merged libdrizzle directly into tree.
1019
#ifdef _WIN32
1020
    errno = WSAGetLastError();
1021
    switch(errno) {
2263.4.1 by Monty Taylor
Updated the windows/posix error mapping as per notes from Marc Isambart.
1022
    case WSAENOTCONN:
1712.1.1 by Monty Taylor
Merged libdrizzle directly into tree.
1023
    case WSAEWOULDBLOCK:
2263.4.1 by Monty Taylor
Updated the windows/posix error mapping as per notes from Marc Isambart.
1024
      errno= EAGAIN;
1025
      break;
1026
    case WSAEINVAL:
1027
    case WSAEALREADY:
2269.2.1 by Marc Isambart
Various libdrizzle Windows fixes, including closesocket() instead of close(), snprintf handling and WSAECONNREFUSED mapping
1028
      errno= EINPROGRESS;
1029
      break;
2263.4.1 by Monty Taylor
Updated the windows/posix error mapping as per notes from Marc Isambart.
1030
    case WSAECONNREFUSED:
2269.2.1 by Marc Isambart
Various libdrizzle Windows fixes, including closesocket() instead of close(), snprintf handling and WSAECONNREFUSED mapping
1031
      errno= ECONNREFUSED;
2263.4.1 by Monty Taylor
Updated the windows/posix error mapping as per notes from Marc Isambart.
1032
      break;
1033
    case WSAENETUNREACH:
1034
      errno= ENETUNREACH;
1035
      break;
1036
    case WSAETIMEDOUT:
1037
      errno= ETIMEDOUT;
1038
      break;
1039
    case WSAECONNRESET:
1040
      errno= ECONNRESET;
1041
      break;
1042
    case WSAEADDRINUSE:
1043
      errno= EADDRINUSE;
1044
      break;
1045
    case WSAEOPNOTSUPP:
1046
      errno= EOPNOTSUPP;
1047
      break;
1048
    case WSAENOPROTOOPT:
1049
      errno= ENOPROTOOPT;
1712.1.1 by Monty Taylor
Merged libdrizzle directly into tree.
1050
      break;
1051
    default:
1052
      break;
1053
    }
1054
#endif /* _WIN32 */	
1055
    drizzle_log_crazy(con->drizzle, "read fd=%d return=%zd errno=%d", con->fd,
1056
                      read_size, errno);
1057
1058
    if (read_size == 0)
1059
    {
1060
      drizzle_set_error(con->drizzle, "drizzle_state_read",
1061
                        "lost connection to server (EOF)");
1062
      return DRIZZLE_RETURN_LOST_CONNECTION;
1063
    }
1064
    else if (read_size == -1)
1065
    {
1066
      if (errno == EAGAIN)
1067
      {
2046.1.2 by Evan Jones
libdrizzle: drizzle_state_read: only call recv() if data is available.
1068
        /* clear the read ready flag */
1069
        con->revents&= ~POLLIN;
1712.1.1 by Monty Taylor
Merged libdrizzle directly into tree.
1070
        ret= drizzle_con_set_events(con, POLLIN);
1071
        if (ret != DRIZZLE_RETURN_OK)
2046.1.1 by Evan Jones
libdrizzle: fix minor errors in drizzle_state_read
1072
          return ret;
1712.1.1 by Monty Taylor
Merged libdrizzle directly into tree.
1073
1074
        if (con->drizzle->options & DRIZZLE_NON_BLOCKING)
1075
          return DRIZZLE_RETURN_IO_WAIT;
1076
1077
        ret= drizzle_con_wait(con->drizzle);
1078
        if (ret != DRIZZLE_RETURN_OK)
1079
          return ret;
1080
1081
        continue;
1082
      }
1083
      else if (errno == ECONNREFUSED)
1084
      {
1085
        con->revents= 0;
1086
        drizzle_state_pop(con);
1087
        drizzle_state_push(con, drizzle_state_connect);
1088
        con->addrinfo_next= con->addrinfo_next->ai_next;
1089
        return DRIZZLE_RETURN_OK;
1090
      }
1091
      else if (errno == EINTR)
1092
        continue;
1093
      else if (errno == EPIPE || errno == ECONNRESET)
1094
      {
1095
        drizzle_set_error(con->drizzle, "drizzle_state_read",
1096
                          "lost connection to server (%d)", errno);
1097
        return DRIZZLE_RETURN_LOST_CONNECTION;
1098
      }
1099
1100
      drizzle_set_error(con->drizzle, "drizzle_state_read", "read:%d", errno);
1101
      con->drizzle->last_errno= errno;
1102
      return DRIZZLE_RETURN_ERRNO;
1103
    }
1104
2046.1.2 by Evan Jones
libdrizzle: drizzle_state_read: only call recv() if data is available.
1105
    /* clear the "read ready" flag if we read all available data. */
1106
    if ((size_t) read_size < available_buffer) con->revents&= ~POLLIN;
1712.1.1 by Monty Taylor
Merged libdrizzle directly into tree.
1107
    con->buffer_size+= (size_t)read_size;
1108
    break;
1109
  }
1110
2046.1.1 by Evan Jones
libdrizzle: fix minor errors in drizzle_state_read
1111
  drizzle_state_pop(con);
1712.1.1 by Monty Taylor
Merged libdrizzle directly into tree.
1112
  return DRIZZLE_RETURN_OK;
1113
}
1114
1115
drizzle_return_t drizzle_state_write(drizzle_con_st *con)
1116
{
1117
  drizzle_return_t ret;
1118
  ssize_t write_size;
1119
1120
  drizzle_log_debug(con->drizzle, "drizzle_state_write");
1121
1122
  while (con->buffer_size != 0)
1123
  {
1124
  
1877.1.5 by Andrew Hutchings
Fix min() usage for 32bit
1125
    write_size = send(con->fd,(char *) con->buffer_ptr, con->buffer_size, 0);
1712.1.1 by Monty Taylor
Merged libdrizzle directly into tree.
1126
2263.4.1 by Monty Taylor
Updated the windows/posix error mapping as per notes from Marc Isambart.
1127
#ifdef _WIN32
1128
    errno = WSAGetLastError();
1129
    switch(errno) {
1130
    case WSAENOTCONN:
1131
    case WSAEWOULDBLOCK:
1132
      errno= EAGAIN;
1133
      break;
1134
    case WSAEINVAL:
1135
    case WSAEALREADY:
2269.2.1 by Marc Isambart
Various libdrizzle Windows fixes, including closesocket() instead of close(), snprintf handling and WSAECONNREFUSED mapping
1136
      errno= EINPROGRESS;
1137
      break;
2263.4.1 by Monty Taylor
Updated the windows/posix error mapping as per notes from Marc Isambart.
1138
    case WSAECONNREFUSED:
2269.2.1 by Marc Isambart
Various libdrizzle Windows fixes, including closesocket() instead of close(), snprintf handling and WSAECONNREFUSED mapping
1139
      errno= ECONNREFUSED;
2263.4.1 by Monty Taylor
Updated the windows/posix error mapping as per notes from Marc Isambart.
1140
      break;
1141
    case WSAENETUNREACH:
1142
      errno= ENETUNREACH;
1143
      break;
1144
    case WSAETIMEDOUT:
1145
      errno= ETIMEDOUT;
1146
      break;
1147
    case WSAECONNRESET:
1148
      errno= ECONNRESET;
1149
      break;
1150
    case WSAEADDRINUSE:
1151
      errno= EADDRINUSE;
1152
      break;
1153
    case WSAEOPNOTSUPP:
1154
      errno= EOPNOTSUPP;
1155
      break;
1156
    case WSAENOPROTOOPT:
1157
      errno= ENOPROTOOPT;
1158
      break;
1159
    default:
1160
      break;
1161
    }
1162
#endif /* _WIN32 */	
1163
1712.1.1 by Monty Taylor
Merged libdrizzle directly into tree.
1164
    drizzle_log_crazy(con->drizzle, "write fd=%d return=%zd errno=%d", con->fd,
1165
                      write_size, errno);
1166
1167
    if (write_size == 0)
1168
    {
1169
      drizzle_set_error(con->drizzle, "drizzle_state_write",
1170
                        "lost connection to server (EOF)");
1171
      return DRIZZLE_RETURN_LOST_CONNECTION;
1172
    }
1173
    else if (write_size == -1)
1174
    {
1175
      if (errno == EAGAIN)
1176
      {
1177
        ret= drizzle_con_set_events(con, POLLOUT);
1178
        if (ret != DRIZZLE_RETURN_OK)
1179
          return ret;
1180
1181
        if (con->drizzle->options & DRIZZLE_NON_BLOCKING)
1182
          return DRIZZLE_RETURN_IO_WAIT;
1183
1184
        ret= drizzle_con_wait(con->drizzle);
1185
        if (ret != DRIZZLE_RETURN_OK)
1186
          return ret;
1187
1188
        continue;
1189
      }
1190
      else if (errno == EINTR)
1191
        continue;
1192
      else if (errno == EPIPE || errno == ECONNRESET)
1193
      {
1194
        drizzle_set_error(con->drizzle, "drizzle_state_write",
1195
                          "lost connection to server (%d)", errno);
1196
        return DRIZZLE_RETURN_LOST_CONNECTION;
1197
      }
1198
1199
      drizzle_set_error(con->drizzle, "drizzle_state_write", "write:%d", errno);
1200
      con->drizzle->last_errno= errno;
1201
      return DRIZZLE_RETURN_ERRNO;
1202
    }
1203
1204
    con->buffer_ptr+= write_size;
1205
    con->buffer_size-= (size_t)write_size;
1206
    if (con->buffer_size == 0)
1207
      break;
1208
  }
1209
1210
  con->buffer_ptr= con->buffer;
1211
1212
  drizzle_state_pop(con);
1213
  return DRIZZLE_RETURN_OK;
1214
}
1215
1216
drizzle_return_t drizzle_state_listen(drizzle_con_st *con)
1217
{
1218
  char host[NI_MAXHOST];
1219
  char port[NI_MAXSERV];
1220
  int fd;
1221
  int opt;
1222
  drizzle_con_st *new_con;
1223
1224
  for (; con->addrinfo_next != NULL;
1225
       con->addrinfo_next= con->addrinfo_next->ai_next)
1226
  {
2464.1.2 by Brian Aker
Fix compiling issues for 1.0, and cleanup header files.
1227
    int ret= getnameinfo(con->addrinfo_next->ai_addr,
1228
                         con->addrinfo_next->ai_addrlen, host, NI_MAXHOST, port,
1229
                         NI_MAXSERV, NI_NUMERICHOST | NI_NUMERICSERV);
1712.1.1 by Monty Taylor
Merged libdrizzle directly into tree.
1230
    if (ret != 0)
1231
    {
2464.1.2 by Brian Aker
Fix compiling issues for 1.0, and cleanup header files.
1232
      drizzle_set_error(con->drizzle, "drizzle_state_listen", "getnameinfo:%s", gai_strerror(ret));
1712.1.1 by Monty Taylor
Merged libdrizzle directly into tree.
1233
      return DRIZZLE_RETURN_GETADDRINFO;
1234
    }
1235
1236
    /* Call to socket() can fail for some getaddrinfo results, try another. */
1237
    fd= socket(con->addrinfo_next->ai_family, con->addrinfo_next->ai_socktype,
1238
               con->addrinfo_next->ai_protocol);
1239
    if (fd == -1)
1240
    {
1241
      drizzle_log_info(con->drizzle, "could not listen on %s:%s", host, port);
1242
      drizzle_set_error(con->drizzle, "drizzle_state_listen", "socket:%d",
1243
                        errno);
1244
      continue;
1245
    }
1246
	
1247
	opt= 1;
1248
#ifdef _WIN32
1249
        ret= setsockopt(fd, SOL_SOCKET, SO_REUSEADDR,(const char*) &opt, sizeof(opt));
1250
#else
1251
        ret= setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt));
1252
#endif /* _WIN32 */
1253
    if (ret == -1)
1254
    {
2269.2.1 by Marc Isambart
Various libdrizzle Windows fixes, including closesocket() instead of close(), snprintf handling and WSAECONNREFUSED mapping
1255
      closesocket(fd);
1712.1.1 by Monty Taylor
Merged libdrizzle directly into tree.
1256
      drizzle_set_error(con->drizzle, "drizzle_state_listen", "setsockopt:%d",
1257
                        errno);
1258
      return DRIZZLE_RETURN_ERRNO;
1259
    }
1260
1261
    ret= bind(fd, con->addrinfo_next->ai_addr, con->addrinfo_next->ai_addrlen);
1262
    if (ret == -1)
1263
    {
2269.2.1 by Marc Isambart
Various libdrizzle Windows fixes, including closesocket() instead of close(), snprintf handling and WSAECONNREFUSED mapping
1264
      closesocket(fd);
1712.1.1 by Monty Taylor
Merged libdrizzle directly into tree.
1265
      drizzle_set_error(con->drizzle, "drizzle_state_listen", "bind:%d", errno);
1266
      if (errno == EADDRINUSE)
1267
      {
1268
        if (con->fd == -1)
1269
        {
1270
          drizzle_log_info(con->drizzle, "could not listen on %s:%s", host,
1271
                           port);
1272
        }
1273
1274
        continue;
1275
      }
1276
1277
      return DRIZZLE_RETURN_ERRNO;
1278
    }
1279
1280
    if (listen(fd, con->backlog) == -1)
1281
    {
2269.2.1 by Marc Isambart
Various libdrizzle Windows fixes, including closesocket() instead of close(), snprintf handling and WSAECONNREFUSED mapping
1282
      closesocket(fd);
1712.1.1 by Monty Taylor
Merged libdrizzle directly into tree.
1283
      drizzle_set_error(con->drizzle, "drizzle_state_listen", "listen:%d",
1284
                        errno);
1285
      return DRIZZLE_RETURN_ERRNO;
1286
    }
1287
1288
    if (con->fd == -1)
1289
    {
1290
      con->fd= fd;
1291
      new_con= con;
1292
    }
1293
    else
1294
    {
1295
      new_con= drizzle_con_clone(con->drizzle, NULL, con);
1296
      if (new_con == NULL)
1297
      {
2269.2.1 by Marc Isambart
Various libdrizzle Windows fixes, including closesocket() instead of close(), snprintf handling and WSAECONNREFUSED mapping
1298
        closesocket(fd);
1712.1.1 by Monty Taylor
Merged libdrizzle directly into tree.
1299
        return DRIZZLE_RETURN_MEMORY;
1300
      }
1301
1302
      new_con->fd= fd;
1303
    }
1304
1305
    /* Wait for read events on the listening socket. */
2464.1.2 by Brian Aker
Fix compiling issues for 1.0, and cleanup header files.
1306
    drizzle_return_t local_ret= drizzle_con_set_events(new_con, POLLIN);
1307
    if (local_ret != DRIZZLE_RETURN_OK)
1712.1.1 by Monty Taylor
Merged libdrizzle directly into tree.
1308
    {
1309
      drizzle_con_free(new_con);
2464.1.2 by Brian Aker
Fix compiling issues for 1.0, and cleanup header files.
1310
      return local_ret;
1712.1.1 by Monty Taylor
Merged libdrizzle directly into tree.
1311
    }
1312
1313
    drizzle_log_info(con->drizzle, "listening on %s:%s", host, port);
1314
  }
1315
1316
  /* Report last socket() error if we couldn't find an address to bind. */
1317
  if (con->fd == -1)
1318
    return DRIZZLE_RETURN_ERRNO;
1319
1320
  drizzle_state_pop(con);
1321
  return DRIZZLE_RETURN_OK;
1322
}
1323
1324
/*
1325
 * Static Definitions
1326
 */
1327
1328
static drizzle_return_t _con_setsockopt(drizzle_con_st *con)
1329
{
1330
  int ret;
1331
  struct linger linger;
1332
  struct timeval waittime;
1333
1334
  ret= 1;
1335
1336
#ifdef _WIN32
1337
  ret= setsockopt(con->fd, IPPROTO_TCP, TCP_NODELAY, (const char*)&ret,
1338
                  (socklen_t)sizeof(int));
1339
#else
1340
  ret= setsockopt(con->fd, IPPROTO_TCP, TCP_NODELAY, &ret,
1341
                  (socklen_t)sizeof(int));
1342
#endif /* _WIN32 */
1343
1344
  if (ret == -1 && errno != EOPNOTSUPP)
1345
  {
1346
    drizzle_set_error(con->drizzle, "_con_setsockopt",
1347
                      "setsockopt:TCP_NODELAY:%d", errno);
1348
    return DRIZZLE_RETURN_ERRNO;
1349
  }
1350
1351
  linger.l_onoff= 1;
1352
  linger.l_linger= DRIZZLE_DEFAULT_SOCKET_TIMEOUT;
1353
1354
#ifdef _WIN32
1355
  ret= setsockopt(con->fd, SOL_SOCKET, SO_LINGER, (const char*)&linger,
1356
                  (socklen_t)sizeof(struct linger));
1357
#else
1358
  ret= setsockopt(con->fd, SOL_SOCKET, SO_LINGER, &linger,
1359
                  (socklen_t)sizeof(struct linger));
1360
#endif /* _WIN32 */
1361
1362
  if (ret == -1)
1363
  {
1364
    drizzle_set_error(con->drizzle, "_con_setsockopt",
1365
                      "setsockopt:SO_LINGER:%d", errno);
1366
    return DRIZZLE_RETURN_ERRNO;
1367
  }
1368
1369
  waittime.tv_sec= DRIZZLE_DEFAULT_SOCKET_TIMEOUT;
1370
  waittime.tv_usec= 0;
1371
1372
#ifdef _WIN32
1373
  ret= setsockopt(con->fd, SOL_SOCKET, SO_SNDTIMEO, (const char*)&waittime,
1374
                  (socklen_t)sizeof(struct timeval));
1375
#else
1376
  ret= setsockopt(con->fd, SOL_SOCKET, SO_SNDTIMEO, &waittime,
1377
                  (socklen_t)sizeof(struct timeval));
1378
#endif /* _WIN32 */
1379
1380
  if (ret == -1 && errno != ENOPROTOOPT)
1381
  {
1382
    drizzle_set_error(con->drizzle, "_con_setsockopt",
1383
                      "setsockopt:SO_SNDTIMEO:%d", errno);
1384
    return DRIZZLE_RETURN_ERRNO;
1385
  }
1386
1387
#ifdef _WIN32
1388
  ret= setsockopt(con->fd, SOL_SOCKET, SO_RCVTIMEO, (const char*)&waittime,
1389
                  (socklen_t)sizeof(struct timeval));
1390
#else
1391
  ret= setsockopt(con->fd, SOL_SOCKET, SO_RCVTIMEO, &waittime,
1392
                  (socklen_t)sizeof(struct timeval));
1393
#endif /* _WIN32 */
1394
1395
  if (ret == -1 && errno != ENOPROTOOPT)
1396
  {
1397
    drizzle_set_error(con->drizzle, "_con_setsockopt",
1398
                      "setsockopt:SO_RCVTIMEO:%d", errno);
1399
    return DRIZZLE_RETURN_ERRNO;
1400
  }
1401
1402
  ret= DRIZZLE_DEFAULT_SOCKET_SEND_SIZE;
1403
#ifdef _WIN32
1404
  ret= setsockopt(con->fd, SOL_SOCKET, SO_SNDBUF, (const char*)&ret, (socklen_t)sizeof(int));
1405
#else
1406
  ret= setsockopt(con->fd, SOL_SOCKET, SO_SNDBUF, &ret, (socklen_t)sizeof(int));
1407
#endif /* _WIN32 */
1408
  if (ret == -1)
1409
  {
1410
    drizzle_set_error(con->drizzle, "_con_setsockopt",
1411
                      "setsockopt:SO_SNDBUF:%d", errno);
1412
    return DRIZZLE_RETURN_ERRNO;
1413
  }
1414
1415
  ret= DRIZZLE_DEFAULT_SOCKET_RECV_SIZE;
1416
#ifdef _WIN32
1417
  ret= setsockopt(con->fd, SOL_SOCKET, SO_RCVBUF, (const char*)&ret, (socklen_t)sizeof(int));
1418
#else
1419
  ret= setsockopt(con->fd, SOL_SOCKET, SO_RCVBUF, &ret, (socklen_t)sizeof(int));
1420
#endif /* _WIN32 */
1421
  if (ret == -1)
1422
  {
1423
    drizzle_set_error(con->drizzle, "_con_setsockopt",
1424
                      "setsockopt:SO_RCVBUF:%d", errno);
1425
    return DRIZZLE_RETURN_ERRNO;
1426
  }
1427
1428
#if defined (_WIN32)
2164.1.1 by Monty Taylor
Merged in outstanding changes from the win32 work.
1429
  {
1430
    unsigned long asyncmode;
1431
    asyncmode= 1;
1432
    ioctlsocket(con->fd, FIONBIO, &asyncmode);
1433
  }
1712.1.1 by Monty Taylor
Merged libdrizzle directly into tree.
1434
#else
1435
  ret= fcntl(con->fd, F_GETFL, 0);
1436
  if (ret == -1)
1437
  {
1438
    drizzle_set_error(con->drizzle, "_con_setsockopt", "fcntl:F_GETFL:%d",
1439
                      errno);
1440
    return DRIZZLE_RETURN_ERRNO;
1441
  }
1442
1443
  ret= fcntl(con->fd, F_SETFL, ret | O_NONBLOCK);
1444
  if (ret == -1)
1445
  {
1446
    drizzle_set_error(con->drizzle, "_con_setsockopt", "fcntl:F_SETFL:%d",
1447
                      errno);
1448
    return DRIZZLE_RETURN_ERRNO;
1449
  }
1450
#endif
1451
1452
  return DRIZZLE_RETURN_OK;
1453
}