~drizzle-trunk/drizzle/development

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