2
* Drizzle Client & Protocol Library
4
* Copyright (C) 2008 Eric Day (eday@oddments.org)
7
* Redistribution and use in source and binary forms, with or without
8
* modification, are permitted provided that the following conditions are
11
* * Redistributions of source code must retain the above copyright
12
* notice, this list of conditions and the following disclaimer.
14
* * Redistributions in binary form must reproduce the above
15
* copyright notice, this list of conditions and the following disclaimer
16
* in the documentation and/or other materials provided with the
19
* * The names of its contributors may not be used to endorse or
20
* promote products derived from this software without specific prior
23
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
24
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
25
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
26
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
27
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
28
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
29
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
30
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
31
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
33
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
40
* @brief Connection Definitions
46
* @addtogroup drizzle_con_static Static Connection Declarations
47
* @ingroup drizzle_con
52
* Set socket options for a connection.
54
* @param[in] con Connection structure previously initialized with
55
* drizzle_con_create(), drizzle_con_clone(), or related functions.
56
* @return Standard drizzle return value.
58
static drizzle_return_t _con_setsockopt(drizzle_con_st *con);
66
int drizzle_con_fd(const drizzle_con_st *con)
71
drizzle_return_t drizzle_con_set_fd(drizzle_con_st *con, int fd)
77
ret= _con_setsockopt(con);
78
if (ret != DRIZZLE_RETURN_OK)
79
con->drizzle->last_errno= errno;
84
void drizzle_con_close(drizzle_con_st *con)
92
con->options&= (drizzle_con_options_t)~DRIZZLE_CON_READY;
93
con->packet_number= 0;
94
con->buffer_ptr= con->buffer;
99
drizzle_state_reset(con);
102
drizzle_return_t drizzle_con_set_events(drizzle_con_st *con, short events)
104
drizzle_return_t ret;
106
if ((con->events | events) == con->events)
107
return DRIZZLE_RETURN_OK;
109
con->events|= events;
111
if (con->drizzle->event_watch_fn != NULL)
113
ret= con->drizzle->event_watch_fn(con, con->events,
114
con->drizzle->event_watch_context);
115
if (ret != DRIZZLE_RETURN_OK)
117
drizzle_con_close(con);
122
return DRIZZLE_RETURN_OK;
125
drizzle_return_t drizzle_con_set_revents(drizzle_con_st *con, short revents)
127
drizzle_return_t ret;
130
con->options|= DRIZZLE_CON_IO_READY;
132
con->revents= revents;
134
/* Remove external POLLOUT watch if we didn't ask for it. Otherwise we spin
135
forever until another POLLIN state change. This is much more efficient
136
than removing POLLOUT on every state change since some external polling
137
mechanisms need to use a system call to change flags (like Linux epoll). */
138
if (revents & POLLOUT && !(con->events & POLLOUT) &&
139
con->drizzle->event_watch_fn != NULL)
141
ret= con->drizzle->event_watch_fn(con, con->events,
142
con->drizzle->event_watch_context);
143
if (ret != DRIZZLE_RETURN_OK)
145
drizzle_con_close(con);
150
con->events&= (short)~revents;
152
return DRIZZLE_RETURN_OK;
155
drizzle_st *drizzle_con_drizzle(const drizzle_con_st *con)
160
const char *drizzle_con_error(const drizzle_con_st *con)
162
return drizzle_error(con->drizzle);
165
int drizzle_con_errno(const drizzle_con_st *con)
167
return drizzle_errno(con->drizzle);
170
uint16_t drizzle_con_error_code(const drizzle_con_st *con)
172
return drizzle_error_code(con->drizzle);
175
const char *drizzle_con_sqlstate(const drizzle_con_st *con)
177
return drizzle_sqlstate(con->drizzle);
180
drizzle_con_options_t drizzle_con_options(const drizzle_con_st *con)
185
void drizzle_con_set_options(drizzle_con_st *con,
186
drizzle_con_options_t options)
188
con->options= options;
191
void drizzle_con_add_options(drizzle_con_st *con,
192
drizzle_con_options_t options)
194
con->options|= options;
196
/* If asking for the experimental Drizzle protocol, clean the MySQL flag. */
197
if (con->options & DRIZZLE_CON_EXPERIMENTAL)
198
con->options&= (drizzle_con_options_t)~DRIZZLE_CON_MYSQL;
201
void drizzle_con_remove_options(drizzle_con_st *con,
202
drizzle_con_options_t options)
204
con->options&= ~options;
207
const char *drizzle_con_host(const drizzle_con_st *con)
209
if (con->socket_type == DRIZZLE_CON_SOCKET_TCP)
211
if (con->socket.tcp.host == NULL && !(con->options & DRIZZLE_CON_LISTEN))
212
return DRIZZLE_DEFAULT_TCP_HOST;
214
return con->socket.tcp.host;
220
in_port_t drizzle_con_port(const drizzle_con_st *con)
222
if (con->socket_type == DRIZZLE_CON_SOCKET_TCP)
224
if (con->socket.tcp.port != 0)
225
return con->socket.tcp.port;
227
if (con->options & DRIZZLE_CON_MYSQL)
228
return DRIZZLE_DEFAULT_TCP_PORT_MYSQL;
230
return DRIZZLE_DEFAULT_TCP_PORT;
236
void drizzle_con_set_tcp(drizzle_con_st *con, const char *host, in_port_t port)
238
drizzle_con_reset_addrinfo(con);
240
con->socket_type= DRIZZLE_CON_SOCKET_TCP;
243
con->socket.tcp.host= NULL;
246
con->socket.tcp.host= con->socket.tcp.host_buffer;
247
strncpy(con->socket.tcp.host, host, NI_MAXHOST);
248
con->socket.tcp.host[NI_MAXHOST - 1]= 0;
251
con->socket.tcp.port= port;
254
const char *drizzle_con_user(const drizzle_con_st *con)
259
const char *drizzle_con_password(const drizzle_con_st *con)
261
return con->password;
264
void drizzle_con_set_auth(drizzle_con_st *con, const char *user,
265
const char *password)
271
strncpy(con->user, user, DRIZZLE_MAX_USER_SIZE);
272
con->user[DRIZZLE_MAX_USER_SIZE - 1]= 0;
275
if (password == NULL)
279
strncpy(con->password, password, DRIZZLE_MAX_PASSWORD_SIZE);
280
con->password[DRIZZLE_MAX_PASSWORD_SIZE - 1]= 0;
284
const char *drizzle_con_db(const drizzle_con_st *con)
289
void drizzle_con_set_db(drizzle_con_st *con, const char *db)
295
strncpy(con->db, db, DRIZZLE_MAX_DB_SIZE);
296
con->db[DRIZZLE_MAX_DB_SIZE - 1]= 0;
300
void *drizzle_con_context(const drizzle_con_st *con)
305
void drizzle_con_set_context(drizzle_con_st *con, void *context)
307
con->context= context;
310
void drizzle_con_set_context_free_fn(drizzle_con_st *con,
311
drizzle_con_context_free_fn *function)
313
con->context_free_fn= function;
316
uint8_t drizzle_con_protocol_version(const drizzle_con_st *con)
318
return con->protocol_version;
321
const char *drizzle_con_server_version(const drizzle_con_st *con)
323
return con->server_version;
326
uint32_t drizzle_con_server_version_number(const drizzle_con_st *con)
334
current= con->server_version;
336
major= (uint32_t)strtoul(current, &end, 10);
338
minor= (uint32_t)strtoul(current, &end, 10);
340
version= (uint32_t)strtoul(current, &end, 10);
342
return (major * 10000) + (minor * 100) + version;
345
uint32_t drizzle_con_thread_id(const drizzle_con_st *con)
347
return con->thread_id;
350
const uint8_t *drizzle_con_scramble(const drizzle_con_st *con)
352
return con->scramble;
355
drizzle_capabilities_t drizzle_con_capabilities(const drizzle_con_st *con)
357
return con->capabilities;
360
drizzle_charset_t drizzle_con_charset(const drizzle_con_st *con)
365
drizzle_con_status_t drizzle_con_status(const drizzle_con_st *con)
370
uint32_t drizzle_con_max_packet_size(const drizzle_con_st *con)
372
return con->max_packet_size;
379
drizzle_return_t drizzle_con_connect(drizzle_con_st *con)
381
if (con->options & DRIZZLE_CON_READY)
382
return DRIZZLE_RETURN_OK;
384
if (drizzle_state_none(con))
386
if (!(con->options & DRIZZLE_CON_RAW_PACKET))
388
drizzle_state_push(con, drizzle_state_handshake_server_read);
389
drizzle_state_push(con, drizzle_state_packet_read);
392
drizzle_state_push(con, drizzle_state_connect);
393
drizzle_state_push(con, drizzle_state_addrinfo);
396
return drizzle_state_loop(con);
399
drizzle_result_st *drizzle_con_quit(drizzle_con_st *con,
400
drizzle_result_st *result,
401
drizzle_return_t *ret_ptr)
403
return drizzle_con_command_write(con, result, DRIZZLE_COMMAND_QUIT, NULL, 0,
407
drizzle_result_st *drizzle_quit(drizzle_con_st *con,
408
drizzle_result_st *result,
409
drizzle_return_t *ret_ptr)
411
return drizzle_con_quit(con, result, ret_ptr);
414
drizzle_result_st *drizzle_con_select_db(drizzle_con_st *con,
415
drizzle_result_st *result,
417
drizzle_return_t *ret_ptr)
419
drizzle_con_set_db(con, db);
420
return drizzle_con_command_write(con, result, DRIZZLE_COMMAND_INIT_DB,
421
db, strlen(db), strlen(db), ret_ptr);
424
drizzle_result_st *drizzle_select_db(drizzle_con_st *con,
425
drizzle_result_st *result,
427
drizzle_return_t *ret_ptr)
429
return drizzle_con_select_db(con, result, db, ret_ptr);
432
drizzle_result_st *drizzle_con_shutdown(drizzle_con_st *con,
433
drizzle_result_st *result,
434
drizzle_return_t *ret_ptr)
436
if (con->options & DRIZZLE_CON_MYSQL)
438
return drizzle_con_command_write(con, result, DRIZZLE_COMMAND_SHUTDOWN,
442
return drizzle_con_command_write(con, result, DRIZZLE_COMMAND_SHUTDOWN, NULL,
446
drizzle_result_st *drizzle_shutdown(drizzle_con_st *con,
447
drizzle_result_st *result, uint32_t level,
448
drizzle_return_t *ret_ptr)
451
return drizzle_con_shutdown(con, result, ret_ptr);
454
drizzle_result_st *drizzle_con_ping(drizzle_con_st *con,
455
drizzle_result_st *result,
456
drizzle_return_t *ret_ptr)
458
return drizzle_con_command_write(con, result, DRIZZLE_COMMAND_PING, NULL, 0,
462
drizzle_result_st *drizzle_ping(drizzle_con_st *con,
463
drizzle_result_st *result,
464
drizzle_return_t *ret_ptr)
466
return drizzle_con_ping(con, result, ret_ptr);
469
drizzle_result_st *drizzle_con_command_write(drizzle_con_st *con,
470
drizzle_result_st *result,
471
drizzle_command_t command,
472
const void *data, size_t size,
474
drizzle_return_t *ret_ptr)
476
if (!(con->options & DRIZZLE_CON_READY))
478
if (con->options & DRIZZLE_CON_RAW_PACKET)
480
drizzle_set_error(con->drizzle, "drizzle_command_write",
481
"connection not ready");
482
*ret_ptr= DRIZZLE_RETURN_NOT_READY;
486
*ret_ptr= drizzle_con_connect(con);
487
if (*ret_ptr != DRIZZLE_RETURN_OK)
491
if (drizzle_state_none(con))
493
if (con->options & (DRIZZLE_CON_RAW_PACKET | DRIZZLE_CON_NO_RESULT_READ))
497
con->result= drizzle_result_create(con, result);
498
if (con->result == NULL)
500
*ret_ptr= DRIZZLE_RETURN_MEMORY;
505
con->command= command;
506
con->command_data= (uint8_t *)data;
507
con->command_size= size;
508
con->command_offset= 0;
509
con->command_total= total;
511
drizzle_state_push(con, drizzle_state_command_write);
513
else if (con->command_data == NULL)
515
con->command_data= (uint8_t *)data;
516
con->command_size= size;
519
*ret_ptr= drizzle_state_loop(con);
520
if (*ret_ptr == DRIZZLE_RETURN_PAUSE)
521
*ret_ptr= DRIZZLE_RETURN_OK;
522
else if (*ret_ptr != DRIZZLE_RETURN_OK &&
523
*ret_ptr != DRIZZLE_RETURN_IO_WAIT &&
524
*ret_ptr != DRIZZLE_RETURN_ERROR_CODE)
526
drizzle_result_free(con->result);
537
drizzle_return_t drizzle_con_listen(drizzle_con_st *con)
539
if (con->options & DRIZZLE_CON_READY)
540
return DRIZZLE_RETURN_OK;
542
if (drizzle_state_none(con))
544
drizzle_state_push(con, drizzle_state_listen);
545
drizzle_state_push(con, drizzle_state_addrinfo);
548
return drizzle_state_loop(con);
551
int drizzle_con_backlog(const drizzle_con_st *con)
556
void drizzle_con_set_backlog(drizzle_con_st *con, int backlog)
558
con->backlog= backlog;
561
void drizzle_con_set_protocol_version(drizzle_con_st *con,
562
uint8_t protocol_version)
564
con->protocol_version= protocol_version;
567
void drizzle_con_set_server_version(drizzle_con_st *con,
568
const char *server_version)
570
if (server_version == NULL)
571
con->server_version[0]= 0;
574
strncpy(con->server_version, server_version,
575
DRIZZLE_MAX_SERVER_VERSION_SIZE);
576
con->server_version[DRIZZLE_MAX_SERVER_VERSION_SIZE - 1]= 0;
580
void drizzle_con_set_thread_id(drizzle_con_st *con, uint32_t thread_id)
582
con->thread_id= thread_id;
585
void drizzle_con_set_scramble(drizzle_con_st *con, const uint8_t *scramble)
587
if (scramble == NULL)
591
con->scramble= con->scramble_buffer;
592
memcpy(con->scramble, scramble, DRIZZLE_MAX_SCRAMBLE_SIZE);
596
void drizzle_con_set_capabilities(drizzle_con_st *con,
597
drizzle_capabilities_t capabilities)
599
con->capabilities= capabilities;
602
void drizzle_con_set_charset(drizzle_con_st *con, drizzle_charset_t charset)
604
con->charset= charset;
607
void drizzle_con_set_status(drizzle_con_st *con, drizzle_con_status_t status)
612
void drizzle_con_set_max_packet_size(drizzle_con_st *con,
613
uint32_t max_packet_size)
615
con->max_packet_size= max_packet_size;
618
void drizzle_con_copy_handshake(drizzle_con_st *con, drizzle_con_st *from)
620
drizzle_con_set_auth(con, from->user, NULL);
621
drizzle_con_set_scramble(con, from->scramble);
622
drizzle_con_set_db(con, from->db);
623
drizzle_con_set_protocol_version(con, from->protocol_version);
624
drizzle_con_set_server_version(con, from->server_version);
625
drizzle_con_set_thread_id(con, from->thread_id);
626
drizzle_con_set_scramble(con, from->scramble);
627
drizzle_con_set_capabilities(con, from->capabilities);
628
drizzle_con_set_charset(con, from->charset);
629
drizzle_con_set_status(con, from->status);
630
drizzle_con_set_max_packet_size(con, from->max_packet_size);
633
void *drizzle_con_command_read(drizzle_con_st *con,
634
drizzle_command_t *command, size_t *offset,
635
size_t *size, size_t *total,
636
drizzle_return_t *ret_ptr)
638
if (drizzle_state_none(con))
640
con->packet_number= 0;
641
con->command_offset= 0;
642
con->command_total= 0;
644
drizzle_state_push(con, drizzle_state_command_read);
645
drizzle_state_push(con, drizzle_state_packet_read);
648
*offset= con->command_offset;
650
*ret_ptr= drizzle_state_loop(con);
651
if (*ret_ptr == DRIZZLE_RETURN_PAUSE)
652
*ret_ptr= DRIZZLE_RETURN_OK;
654
*command= con->command;
655
*size= con->command_size;
656
*total= con->command_total;
658
return con->command_data;
661
void *drizzle_con_command_buffer(drizzle_con_st *con,
662
drizzle_command_t *command, size_t *total,
663
drizzle_return_t *ret_ptr)
665
uint8_t *command_data;
669
command_data= drizzle_con_command_read(con, command, &offset, &size, total,
671
if (*ret_ptr != DRIZZLE_RETURN_OK)
674
if (command_data == NULL)
680
if (con->command_buffer == NULL)
682
con->command_buffer= malloc((*total) + 1);
683
if (con->command_buffer == NULL)
685
drizzle_set_error(con->drizzle, "drizzle_command_buffer", "malloc");
686
*ret_ptr= DRIZZLE_RETURN_MEMORY;
691
memcpy(con->command_buffer + offset, command_data, size);
693
while ((offset + size) != (*total))
695
command_data= drizzle_con_command_read(con, command, &offset, &size, total,
697
if (*ret_ptr != DRIZZLE_RETURN_OK)
700
memcpy(con->command_buffer + offset, command_data, size);
703
command_data= con->command_buffer;
704
con->command_buffer= NULL;
705
command_data[*total]= 0;
714
void drizzle_con_reset_addrinfo(drizzle_con_st *con)
716
switch (con->socket_type)
718
case DRIZZLE_CON_SOCKET_TCP:
719
if (con->socket.tcp.addrinfo != NULL)
721
freeaddrinfo(con->socket.tcp.addrinfo);
722
con->socket.tcp.addrinfo= NULL;
726
case DRIZZLE_CON_SOCKET_UDS:
727
con->socket.uds.addrinfo.ai_addr= NULL;
734
con->addrinfo_next= NULL;
741
drizzle_return_t drizzle_state_addrinfo(drizzle_con_st *con)
743
drizzle_con_tcp_st *tcp;
745
char port[NI_MAXSERV];
749
drizzle_log_debug(con->drizzle, "drizzle_state_addrinfo");
751
switch (con->socket_type)
753
case DRIZZLE_CON_SOCKET_TCP:
754
tcp= &(con->socket.tcp);
756
if (tcp->addrinfo != NULL)
758
freeaddrinfo(tcp->addrinfo);
763
snprintf(port, NI_MAXSERV, "%u", tcp->port);
764
else if (con->options & DRIZZLE_CON_MYSQL)
765
snprintf(port, NI_MAXSERV, "%u", DRIZZLE_DEFAULT_TCP_PORT_MYSQL);
767
snprintf(port, NI_MAXSERV, "%u", DRIZZLE_DEFAULT_TCP_PORT);
769
memset(&ai, 0, sizeof(struct addrinfo));
770
ai.ai_socktype= SOCK_STREAM;
771
ai.ai_protocol= IPPROTO_TCP;
773
if (con->options & DRIZZLE_CON_LISTEN)
775
ai.ai_flags = AI_PASSIVE;
776
ai.ai_family = AF_UNSPEC;
781
if (tcp->host == NULL)
782
host= DRIZZLE_DEFAULT_TCP_HOST;
787
ret= getaddrinfo(host, port, &ai, &(tcp->addrinfo));
790
drizzle_set_error(con->drizzle, "drizzle_state_addrinfo",
791
"getaddrinfo:%s", gai_strerror(ret));
792
return DRIZZLE_RETURN_GETADDRINFO;
795
con->addrinfo_next= tcp->addrinfo;
799
case DRIZZLE_CON_SOCKET_UDS:
800
con->addrinfo_next= &(con->socket.uds.addrinfo);
807
drizzle_state_pop(con);
808
return DRIZZLE_RETURN_OK;
811
drizzle_return_t drizzle_state_connect(drizzle_con_st *con)
814
drizzle_return_t dret;
816
drizzle_log_debug(con->drizzle, "drizzle_state_connect");
820
(void)close(con->fd);
824
if (con->addrinfo_next == NULL)
826
drizzle_set_error(con->drizzle, "drizzle_state_connect",
827
"could not connect");
828
drizzle_state_reset(con);
829
return DRIZZLE_RETURN_COULD_NOT_CONNECT;
832
con->fd= socket(con->addrinfo_next->ai_family,
833
con->addrinfo_next->ai_socktype,
834
con->addrinfo_next->ai_protocol);
837
drizzle_set_error(con->drizzle, "drizzle_state_connect", "socket:%d",
839
con->drizzle->last_errno= errno;
840
return DRIZZLE_RETURN_ERRNO;
843
dret= _con_setsockopt(con);
844
if (dret != DRIZZLE_RETURN_OK)
846
con->drizzle->last_errno= errno;
852
ret= connect(con->fd, con->addrinfo_next->ai_addr,
853
con->addrinfo_next->ai_addrlen);
856
/*Mapping windows specific error codes to Posix*/
857
errno = WSAGetLastError();
869
drizzle_log_crazy(con->drizzle, "connect return=%d errno=%d", ret, errno);
873
con->addrinfo_next= NULL;
877
if (errno == EAGAIN || errno == EINTR)
880
if (errno == EINPROGRESS)
882
drizzle_state_pop(con);
883
drizzle_state_push(con, drizzle_state_connecting);
884
return DRIZZLE_RETURN_OK;
887
if (errno == ECONNREFUSED || errno == ENETUNREACH || errno == ETIMEDOUT)
889
con->addrinfo_next= con->addrinfo_next->ai_next;
890
return DRIZZLE_RETURN_OK;
893
drizzle_set_error(con->drizzle, "drizzle_state_connect", "connect:%d",
895
con->drizzle->last_errno= errno;
896
return DRIZZLE_RETURN_ERRNO;
899
drizzle_state_pop(con);
900
return DRIZZLE_RETURN_OK;
903
drizzle_return_t drizzle_state_connecting(drizzle_con_st *con)
905
drizzle_return_t ret;
907
drizzle_log_debug(con->drizzle, "drizzle_state_connecting");
911
if (con->revents & POLLOUT)
913
drizzle_state_pop(con);
914
return DRIZZLE_RETURN_OK;
916
else if (con->revents & (POLLERR | POLLHUP | POLLNVAL))
919
drizzle_state_pop(con);
920
drizzle_state_push(con, drizzle_state_connect);
921
con->addrinfo_next= con->addrinfo_next->ai_next;
922
return DRIZZLE_RETURN_OK;
925
ret= drizzle_con_set_events(con, POLLOUT);
926
if (ret != DRIZZLE_RETURN_OK)
929
if (con->drizzle->options & DRIZZLE_NON_BLOCKING)
930
return DRIZZLE_RETURN_IO_WAIT;
932
ret= drizzle_con_wait(con->drizzle);
933
if (ret != DRIZZLE_RETURN_OK)
938
drizzle_return_t drizzle_state_read(drizzle_con_st *con)
940
drizzle_return_t ret;
943
drizzle_log_debug(con->drizzle, "drizzle_state_read");
945
if (con->buffer_size == 0)
946
con->buffer_ptr= con->buffer;
947
else if ((con->buffer_ptr - con->buffer) > (DRIZZLE_MAX_BUFFER_SIZE / 2))
949
memmove(con->buffer, con->buffer_ptr, con->buffer_size);
950
con->buffer_ptr= con->buffer;
953
if ((con->revents & POLLIN) == 0 &&
954
(con->drizzle->options & DRIZZLE_NON_BLOCKING))
956
/* non-blocking mode: return IO_WAIT instead of attempting to read. This
957
* avoids reading immediately after writing a command, which typically
958
* returns EAGAIN. This improves performance. */
959
ret= drizzle_con_set_events(con, POLLIN);
960
if (ret != DRIZZLE_RETURN_OK)
962
return DRIZZLE_RETURN_IO_WAIT;
967
size_t available_buffer= (size_t)DRIZZLE_MAX_BUFFER_SIZE -
968
((size_t)(con->buffer_ptr - con->buffer) + con->buffer_size);
969
read_size = recv(con->fd, (char *)con->buffer_ptr + con->buffer_size,
970
available_buffer, 0);
972
/*Get windows error codes and map it to Posix*/
973
errno = WSAGetLastError();
983
drizzle_log_crazy(con->drizzle, "read fd=%d return=%zd errno=%d", con->fd,
988
drizzle_set_error(con->drizzle, "drizzle_state_read",
989
"lost connection to server (EOF)");
990
return DRIZZLE_RETURN_LOST_CONNECTION;
992
else if (read_size == -1)
996
/* clear the read ready flag */
997
con->revents&= ~POLLIN;
998
ret= drizzle_con_set_events(con, POLLIN);
999
if (ret != DRIZZLE_RETURN_OK)
1002
if (con->drizzle->options & DRIZZLE_NON_BLOCKING)
1003
return DRIZZLE_RETURN_IO_WAIT;
1005
ret= drizzle_con_wait(con->drizzle);
1006
if (ret != DRIZZLE_RETURN_OK)
1011
else if (errno == ECONNREFUSED)
1014
drizzle_state_pop(con);
1015
drizzle_state_push(con, drizzle_state_connect);
1016
con->addrinfo_next= con->addrinfo_next->ai_next;
1017
return DRIZZLE_RETURN_OK;
1019
else if (errno == EINTR)
1021
else if (errno == EPIPE || errno == ECONNRESET)
1023
drizzle_set_error(con->drizzle, "drizzle_state_read",
1024
"lost connection to server (%d)", errno);
1025
return DRIZZLE_RETURN_LOST_CONNECTION;
1028
drizzle_set_error(con->drizzle, "drizzle_state_read", "read:%d", errno);
1029
con->drizzle->last_errno= errno;
1030
return DRIZZLE_RETURN_ERRNO;
1033
/* clear the "read ready" flag if we read all available data. */
1034
if ((size_t) read_size < available_buffer) con->revents&= ~POLLIN;
1035
con->buffer_size+= (size_t)read_size;
1039
drizzle_state_pop(con);
1040
return DRIZZLE_RETURN_OK;
1043
drizzle_return_t drizzle_state_write(drizzle_con_st *con)
1045
drizzle_return_t ret;
1048
drizzle_log_debug(con->drizzle, "drizzle_state_write");
1050
while (con->buffer_size != 0)
1053
write_size = send(con->fd,(char *) con->buffer_ptr, con->buffer_size, 0);
1055
drizzle_log_crazy(con->drizzle, "write fd=%d return=%zd errno=%d", con->fd,
1058
if (write_size == 0)
1060
drizzle_set_error(con->drizzle, "drizzle_state_write",
1061
"lost connection to server (EOF)");
1062
return DRIZZLE_RETURN_LOST_CONNECTION;
1064
else if (write_size == -1)
1066
if (errno == EAGAIN)
1068
ret= drizzle_con_set_events(con, POLLOUT);
1069
if (ret != DRIZZLE_RETURN_OK)
1072
if (con->drizzle->options & DRIZZLE_NON_BLOCKING)
1073
return DRIZZLE_RETURN_IO_WAIT;
1075
ret= drizzle_con_wait(con->drizzle);
1076
if (ret != DRIZZLE_RETURN_OK)
1081
else if (errno == EINTR)
1083
else if (errno == EPIPE || errno == ECONNRESET)
1085
drizzle_set_error(con->drizzle, "drizzle_state_write",
1086
"lost connection to server (%d)", errno);
1087
return DRIZZLE_RETURN_LOST_CONNECTION;
1090
drizzle_set_error(con->drizzle, "drizzle_state_write", "write:%d", errno);
1091
con->drizzle->last_errno= errno;
1092
return DRIZZLE_RETURN_ERRNO;
1095
con->buffer_ptr+= write_size;
1096
con->buffer_size-= (size_t)write_size;
1097
if (con->buffer_size == 0)
1101
con->buffer_ptr= con->buffer;
1103
drizzle_state_pop(con);
1104
return DRIZZLE_RETURN_OK;
1107
drizzle_return_t drizzle_state_listen(drizzle_con_st *con)
1109
char host[NI_MAXHOST];
1110
char port[NI_MAXSERV];
1114
drizzle_con_st *new_con;
1116
for (; con->addrinfo_next != NULL;
1117
con->addrinfo_next= con->addrinfo_next->ai_next)
1119
ret= getnameinfo(con->addrinfo_next->ai_addr,
1120
con->addrinfo_next->ai_addrlen, host, NI_MAXHOST, port,
1121
NI_MAXSERV, NI_NUMERICHOST | NI_NUMERICSERV);
1124
drizzle_set_error(con->drizzle, "drizzle_state_listen", "getnameinfo:%s",
1126
return DRIZZLE_RETURN_GETADDRINFO;
1129
/* Call to socket() can fail for some getaddrinfo results, try another. */
1130
fd= socket(con->addrinfo_next->ai_family, con->addrinfo_next->ai_socktype,
1131
con->addrinfo_next->ai_protocol);
1134
drizzle_log_info(con->drizzle, "could not listen on %s:%s", host, port);
1135
drizzle_set_error(con->drizzle, "drizzle_state_listen", "socket:%d",
1142
ret= setsockopt(fd, SOL_SOCKET, SO_REUSEADDR,(const char*) &opt, sizeof(opt));
1144
ret= setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt));
1149
drizzle_set_error(con->drizzle, "drizzle_state_listen", "setsockopt:%d",
1151
return DRIZZLE_RETURN_ERRNO;
1154
ret= bind(fd, con->addrinfo_next->ai_addr, con->addrinfo_next->ai_addrlen);
1158
drizzle_set_error(con->drizzle, "drizzle_state_listen", "bind:%d", errno);
1159
if (errno == EADDRINUSE)
1163
drizzle_log_info(con->drizzle, "could not listen on %s:%s", host,
1170
return DRIZZLE_RETURN_ERRNO;
1173
if (listen(fd, con->backlog) == -1)
1176
drizzle_set_error(con->drizzle, "drizzle_state_listen", "listen:%d",
1178
return DRIZZLE_RETURN_ERRNO;
1188
new_con= drizzle_con_clone(con->drizzle, NULL, con);
1189
if (new_con == NULL)
1192
return DRIZZLE_RETURN_MEMORY;
1198
/* Wait for read events on the listening socket. */
1199
ret= drizzle_con_set_events(new_con, POLLIN);
1200
if (ret != DRIZZLE_RETURN_OK)
1202
drizzle_con_free(new_con);
1206
drizzle_log_info(con->drizzle, "listening on %s:%s", host, port);
1209
/* Report last socket() error if we couldn't find an address to bind. */
1211
return DRIZZLE_RETURN_ERRNO;
1213
drizzle_state_pop(con);
1214
return DRIZZLE_RETURN_OK;
1218
* Static Definitions
1221
static drizzle_return_t _con_setsockopt(drizzle_con_st *con)
1224
struct linger linger;
1225
struct timeval waittime;
1230
ret= setsockopt(con->fd, IPPROTO_TCP, TCP_NODELAY, (const char*)&ret,
1231
(socklen_t)sizeof(int));
1233
ret= setsockopt(con->fd, IPPROTO_TCP, TCP_NODELAY, &ret,
1234
(socklen_t)sizeof(int));
1237
if (ret == -1 && errno != EOPNOTSUPP)
1239
drizzle_set_error(con->drizzle, "_con_setsockopt",
1240
"setsockopt:TCP_NODELAY:%d", errno);
1241
return DRIZZLE_RETURN_ERRNO;
1245
linger.l_linger= DRIZZLE_DEFAULT_SOCKET_TIMEOUT;
1248
ret= setsockopt(con->fd, SOL_SOCKET, SO_LINGER, (const char*)&linger,
1249
(socklen_t)sizeof(struct linger));
1251
ret= setsockopt(con->fd, SOL_SOCKET, SO_LINGER, &linger,
1252
(socklen_t)sizeof(struct linger));
1257
drizzle_set_error(con->drizzle, "_con_setsockopt",
1258
"setsockopt:SO_LINGER:%d", errno);
1259
return DRIZZLE_RETURN_ERRNO;
1262
waittime.tv_sec= DRIZZLE_DEFAULT_SOCKET_TIMEOUT;
1263
waittime.tv_usec= 0;
1266
ret= setsockopt(con->fd, SOL_SOCKET, SO_SNDTIMEO, (const char*)&waittime,
1267
(socklen_t)sizeof(struct timeval));
1269
ret= setsockopt(con->fd, SOL_SOCKET, SO_SNDTIMEO, &waittime,
1270
(socklen_t)sizeof(struct timeval));
1273
if (ret == -1 && errno != ENOPROTOOPT)
1275
drizzle_set_error(con->drizzle, "_con_setsockopt",
1276
"setsockopt:SO_SNDTIMEO:%d", errno);
1277
return DRIZZLE_RETURN_ERRNO;
1281
ret= setsockopt(con->fd, SOL_SOCKET, SO_RCVTIMEO, (const char*)&waittime,
1282
(socklen_t)sizeof(struct timeval));
1284
ret= setsockopt(con->fd, SOL_SOCKET, SO_RCVTIMEO, &waittime,
1285
(socklen_t)sizeof(struct timeval));
1288
if (ret == -1 && errno != ENOPROTOOPT)
1290
drizzle_set_error(con->drizzle, "_con_setsockopt",
1291
"setsockopt:SO_RCVTIMEO:%d", errno);
1292
return DRIZZLE_RETURN_ERRNO;
1295
ret= DRIZZLE_DEFAULT_SOCKET_SEND_SIZE;
1297
ret= setsockopt(con->fd, SOL_SOCKET, SO_SNDBUF, (const char*)&ret, (socklen_t)sizeof(int));
1299
ret= setsockopt(con->fd, SOL_SOCKET, SO_SNDBUF, &ret, (socklen_t)sizeof(int));
1303
drizzle_set_error(con->drizzle, "_con_setsockopt",
1304
"setsockopt:SO_SNDBUF:%d", errno);
1305
return DRIZZLE_RETURN_ERRNO;
1308
ret= DRIZZLE_DEFAULT_SOCKET_RECV_SIZE;
1310
ret= setsockopt(con->fd, SOL_SOCKET, SO_RCVBUF, (const char*)&ret, (socklen_t)sizeof(int));
1312
ret= setsockopt(con->fd, SOL_SOCKET, SO_RCVBUF, &ret, (socklen_t)sizeof(int));
1316
drizzle_set_error(con->drizzle, "_con_setsockopt",
1317
"setsockopt:SO_RCVBUF:%d", errno);
1318
return DRIZZLE_RETURN_ERRNO;
1321
#if defined (_WIN32)
1323
unsigned long asyncmode;
1325
ioctlsocket(con->fd, FIONBIO, &asyncmode);
1328
ret= fcntl(con->fd, F_GETFL, 0);
1331
drizzle_set_error(con->drizzle, "_con_setsockopt", "fcntl:F_GETFL:%d",
1333
return DRIZZLE_RETURN_ERRNO;
1336
ret= fcntl(con->fd, F_SETFL, ret | O_NONBLOCK);
1339
drizzle_set_error(con->drizzle, "_con_setsockopt", "fcntl:F_SETFL:%d",
1341
return DRIZZLE_RETURN_ERRNO;
1345
return DRIZZLE_RETURN_OK;