~clint-fewbar/drizzle/authorize-default-deny

« back to all changes in this revision

Viewing changes to libdrizzle/conn.c

  • Committer: Monty Taylor
  • Date: 2010-08-12 20:27:32 UTC
  • mto: (1720.1.5 build)
  • mto: This revision was merged to the branch mainline in revision 1722.
  • Revision ID: mordred@inaugust.com-20100812202732-9kzchbkvkyki4n3u
Merged libdrizzle directly into tree.

Show diffs side-by-side

added added

removed removed

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