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;
955
read_size = recv(con->fd, (char *)con->buffer_ptr + con->buffer_size,
956
(size_t)DRIZZLE_MAX_BUFFER_SIZE -
957
((size_t)(con->buffer_ptr - con->buffer) +
958
con->buffer_size),0);
960
/*Get windows error codes and map it to Posix*/
961
errno = WSAGetLastError();
971
drizzle_log_crazy(con->drizzle, "read fd=%d return=%zd errno=%d", con->fd,
976
drizzle_set_error(con->drizzle, "drizzle_state_read",
977
"lost connection to server (EOF)");
978
return DRIZZLE_RETURN_LOST_CONNECTION;
980
else if (read_size == -1)
984
ret= drizzle_con_set_events(con, POLLIN);
985
if (ret != DRIZZLE_RETURN_OK)
988
if (con->drizzle->options & DRIZZLE_NON_BLOCKING)
989
return DRIZZLE_RETURN_IO_WAIT;
991
ret= drizzle_con_wait(con->drizzle);
992
if (ret != DRIZZLE_RETURN_OK)
997
else if (errno == ECONNREFUSED)
1000
drizzle_state_pop(con);
1001
drizzle_state_push(con, drizzle_state_connect);
1002
con->addrinfo_next= con->addrinfo_next->ai_next;
1003
return DRIZZLE_RETURN_OK;
1005
else if (errno == EINTR)
1007
else if (errno == EPIPE || errno == ECONNRESET)
1009
drizzle_set_error(con->drizzle, "drizzle_state_read",
1010
"lost connection to server (%d)", errno);
1011
return DRIZZLE_RETURN_LOST_CONNECTION;
1014
drizzle_set_error(con->drizzle, "drizzle_state_read", "read:%d", errno);
1015
con->drizzle->last_errno= errno;
1016
return DRIZZLE_RETURN_ERRNO;
1019
con->buffer_size+= (size_t)read_size;
1023
drizzle_state_pop(con);;
1024
return DRIZZLE_RETURN_OK;
1027
drizzle_return_t drizzle_state_write(drizzle_con_st *con)
1029
drizzle_return_t ret;
1032
drizzle_log_debug(con->drizzle, "drizzle_state_write");
1034
while (con->buffer_size != 0)
1037
write_size = send(con->fd,(char *) con->buffer_ptr, con->buffer_size, 0);
1039
drizzle_log_crazy(con->drizzle, "write fd=%d return=%zd errno=%d", con->fd,
1042
if (write_size == 0)
1044
drizzle_set_error(con->drizzle, "drizzle_state_write",
1045
"lost connection to server (EOF)");
1046
return DRIZZLE_RETURN_LOST_CONNECTION;
1048
else if (write_size == -1)
1050
if (errno == EAGAIN)
1052
ret= drizzle_con_set_events(con, POLLOUT);
1053
if (ret != DRIZZLE_RETURN_OK)
1056
if (con->drizzle->options & DRIZZLE_NON_BLOCKING)
1057
return DRIZZLE_RETURN_IO_WAIT;
1059
ret= drizzle_con_wait(con->drizzle);
1060
if (ret != DRIZZLE_RETURN_OK)
1065
else if (errno == EINTR)
1067
else if (errno == EPIPE || errno == ECONNRESET)
1069
drizzle_set_error(con->drizzle, "drizzle_state_write",
1070
"lost connection to server (%d)", errno);
1071
return DRIZZLE_RETURN_LOST_CONNECTION;
1074
drizzle_set_error(con->drizzle, "drizzle_state_write", "write:%d", errno);
1075
con->drizzle->last_errno= errno;
1076
return DRIZZLE_RETURN_ERRNO;
1079
con->buffer_ptr+= write_size;
1080
con->buffer_size-= (size_t)write_size;
1081
if (con->buffer_size == 0)
1085
con->buffer_ptr= con->buffer;
1087
drizzle_state_pop(con);
1088
return DRIZZLE_RETURN_OK;
1091
drizzle_return_t drizzle_state_listen(drizzle_con_st *con)
1093
char host[NI_MAXHOST];
1094
char port[NI_MAXSERV];
1098
drizzle_con_st *new_con;
1100
for (; con->addrinfo_next != NULL;
1101
con->addrinfo_next= con->addrinfo_next->ai_next)
1103
ret= getnameinfo(con->addrinfo_next->ai_addr,
1104
con->addrinfo_next->ai_addrlen, host, NI_MAXHOST, port,
1105
NI_MAXSERV, NI_NUMERICHOST | NI_NUMERICSERV);
1108
drizzle_set_error(con->drizzle, "drizzle_state_listen", "getnameinfo:%s",
1110
return DRIZZLE_RETURN_GETADDRINFO;
1113
/* Call to socket() can fail for some getaddrinfo results, try another. */
1114
fd= socket(con->addrinfo_next->ai_family, con->addrinfo_next->ai_socktype,
1115
con->addrinfo_next->ai_protocol);
1118
drizzle_log_info(con->drizzle, "could not listen on %s:%s", host, port);
1119
drizzle_set_error(con->drizzle, "drizzle_state_listen", "socket:%d",
1126
ret= setsockopt(fd, SOL_SOCKET, SO_REUSEADDR,(const char*) &opt, sizeof(opt));
1128
ret= setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt));
1133
drizzle_set_error(con->drizzle, "drizzle_state_listen", "setsockopt:%d",
1135
return DRIZZLE_RETURN_ERRNO;
1138
ret= bind(fd, con->addrinfo_next->ai_addr, con->addrinfo_next->ai_addrlen);
1142
drizzle_set_error(con->drizzle, "drizzle_state_listen", "bind:%d", errno);
1143
if (errno == EADDRINUSE)
1147
drizzle_log_info(con->drizzle, "could not listen on %s:%s", host,
1154
return DRIZZLE_RETURN_ERRNO;
1157
if (listen(fd, con->backlog) == -1)
1160
drizzle_set_error(con->drizzle, "drizzle_state_listen", "listen:%d",
1162
return DRIZZLE_RETURN_ERRNO;
1172
new_con= drizzle_con_clone(con->drizzle, NULL, con);
1173
if (new_con == NULL)
1176
return DRIZZLE_RETURN_MEMORY;
1182
/* Wait for read events on the listening socket. */
1183
ret= drizzle_con_set_events(new_con, POLLIN);
1184
if (ret != DRIZZLE_RETURN_OK)
1186
drizzle_con_free(new_con);
1190
drizzle_log_info(con->drizzle, "listening on %s:%s", host, port);
1193
/* Report last socket() error if we couldn't find an address to bind. */
1195
return DRIZZLE_RETURN_ERRNO;
1197
drizzle_state_pop(con);
1198
return DRIZZLE_RETURN_OK;
1202
* Static Definitions
1205
static drizzle_return_t _con_setsockopt(drizzle_con_st *con)
1208
struct linger linger;
1209
struct timeval waittime;
1214
ret= setsockopt(con->fd, IPPROTO_TCP, TCP_NODELAY, (const char*)&ret,
1215
(socklen_t)sizeof(int));
1217
ret= setsockopt(con->fd, IPPROTO_TCP, TCP_NODELAY, &ret,
1218
(socklen_t)sizeof(int));
1221
if (ret == -1 && errno != EOPNOTSUPP)
1223
drizzle_set_error(con->drizzle, "_con_setsockopt",
1224
"setsockopt:TCP_NODELAY:%d", errno);
1225
return DRIZZLE_RETURN_ERRNO;
1229
linger.l_linger= DRIZZLE_DEFAULT_SOCKET_TIMEOUT;
1232
ret= setsockopt(con->fd, SOL_SOCKET, SO_LINGER, (const char*)&linger,
1233
(socklen_t)sizeof(struct linger));
1235
ret= setsockopt(con->fd, SOL_SOCKET, SO_LINGER, &linger,
1236
(socklen_t)sizeof(struct linger));
1241
drizzle_set_error(con->drizzle, "_con_setsockopt",
1242
"setsockopt:SO_LINGER:%d", errno);
1243
return DRIZZLE_RETURN_ERRNO;
1246
waittime.tv_sec= DRIZZLE_DEFAULT_SOCKET_TIMEOUT;
1247
waittime.tv_usec= 0;
1250
ret= setsockopt(con->fd, SOL_SOCKET, SO_SNDTIMEO, (const char*)&waittime,
1251
(socklen_t)sizeof(struct timeval));
1253
ret= setsockopt(con->fd, SOL_SOCKET, SO_SNDTIMEO, &waittime,
1254
(socklen_t)sizeof(struct timeval));
1257
if (ret == -1 && errno != ENOPROTOOPT)
1259
drizzle_set_error(con->drizzle, "_con_setsockopt",
1260
"setsockopt:SO_SNDTIMEO:%d", errno);
1261
return DRIZZLE_RETURN_ERRNO;
1265
ret= setsockopt(con->fd, SOL_SOCKET, SO_RCVTIMEO, (const char*)&waittime,
1266
(socklen_t)sizeof(struct timeval));
1268
ret= setsockopt(con->fd, SOL_SOCKET, SO_RCVTIMEO, &waittime,
1269
(socklen_t)sizeof(struct timeval));
1272
if (ret == -1 && errno != ENOPROTOOPT)
1274
drizzle_set_error(con->drizzle, "_con_setsockopt",
1275
"setsockopt:SO_RCVTIMEO:%d", errno);
1276
return DRIZZLE_RETURN_ERRNO;
1279
ret= DRIZZLE_DEFAULT_SOCKET_SEND_SIZE;
1281
ret= setsockopt(con->fd, SOL_SOCKET, SO_SNDBUF, (const char*)&ret, (socklen_t)sizeof(int));
1283
ret= setsockopt(con->fd, SOL_SOCKET, SO_SNDBUF, &ret, (socklen_t)sizeof(int));
1287
drizzle_set_error(con->drizzle, "_con_setsockopt",
1288
"setsockopt:SO_SNDBUF:%d", errno);
1289
return DRIZZLE_RETURN_ERRNO;
1292
ret= DRIZZLE_DEFAULT_SOCKET_RECV_SIZE;
1294
ret= setsockopt(con->fd, SOL_SOCKET, SO_RCVBUF, (const char*)&ret, (socklen_t)sizeof(int));
1296
ret= setsockopt(con->fd, SOL_SOCKET, SO_RCVBUF, &ret, (socklen_t)sizeof(int));
1300
drizzle_set_error(con->drizzle, "_con_setsockopt",
1301
"setsockopt:SO_RCVBUF:%d", errno);
1302
return DRIZZLE_RETURN_ERRNO;
1305
#if defined (_WIN32)
1306
unsigned long asyncmode = 1;
1307
ioctlsocket(con->fd, FIONBIO, &asyncmode);
1309
ret= fcntl(con->fd, F_GETFL, 0);
1312
drizzle_set_error(con->drizzle, "_con_setsockopt", "fcntl:F_GETFL:%d",
1314
return DRIZZLE_RETURN_ERRNO;
1317
ret= fcntl(con->fd, F_SETFL, ret | O_NONBLOCK);
1320
drizzle_set_error(con->drizzle, "_con_setsockopt", "fcntl:F_SETFL:%d",
1322
return DRIZZLE_RETURN_ERRNO;
1326
return DRIZZLE_RETURN_OK;