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)
89
(void)closesocket(con->fd);
92
con->options&= ~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
int drizzle_con_options(const drizzle_con_st *con)
185
void drizzle_con_set_options(drizzle_con_st *con,
188
con->options= options;
191
void drizzle_con_add_options(drizzle_con_st *con,
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_MYSQL;
201
void drizzle_con_remove_options(drizzle_con_st *con,
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
int 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_kill(drizzle_con_st *con,
455
drizzle_result_st *result,
457
drizzle_return_t *ret_ptr)
459
uint32_t sent= htonl(query_id);
460
return drizzle_con_command_write(con, result, DRIZZLE_COMMAND_PROCESS_KILL,
461
&sent, sizeof(uint32_t), sizeof(uint32_t), ret_ptr);
464
drizzle_result_st *drizzle_con_ping(drizzle_con_st *con,
465
drizzle_result_st *result,
466
drizzle_return_t *ret_ptr)
468
return drizzle_con_command_write(con, result, DRIZZLE_COMMAND_PING, NULL, 0,
472
drizzle_result_st *drizzle_ping(drizzle_con_st *con,
473
drizzle_result_st *result,
474
drizzle_return_t *ret_ptr)
476
return drizzle_con_ping(con, result, ret_ptr);
479
drizzle_result_st *drizzle_con_command_write(drizzle_con_st *con,
480
drizzle_result_st *result,
481
drizzle_command_t command,
482
const void *data, size_t size,
484
drizzle_return_t *ret_ptr)
486
drizzle_result_st *old_result;
488
if (!(con->options & DRIZZLE_CON_READY))
490
if (con->options & DRIZZLE_CON_RAW_PACKET)
492
drizzle_set_error(con->drizzle, "drizzle_command_write",
493
"connection not ready");
494
*ret_ptr= DRIZZLE_RETURN_NOT_READY;
498
*ret_ptr= drizzle_con_connect(con);
499
if (*ret_ptr != DRIZZLE_RETURN_OK)
503
if (drizzle_state_none(con))
505
if (con->options & (DRIZZLE_CON_RAW_PACKET | DRIZZLE_CON_NO_RESULT_READ))
509
for (old_result= con->result_list; old_result != NULL; old_result= old_result->next)
511
if (result == old_result)
513
drizzle_set_error(con->drizzle, "drizzle_command_write", "result struct already in use");
514
*ret_ptr= DRIZZLE_RETURN_INTERNAL_ERROR;
519
con->result= drizzle_result_create(con, result);
520
if (con->result == NULL)
522
*ret_ptr= DRIZZLE_RETURN_MEMORY;
527
con->command= command;
528
con->command_data= (uint8_t *)data;
529
con->command_size= size;
530
con->command_offset= 0;
531
con->command_total= total;
533
drizzle_state_push(con, drizzle_state_command_write);
535
else if (con->command_data == NULL)
537
con->command_data= (uint8_t *)data;
538
con->command_size= size;
541
*ret_ptr= drizzle_state_loop(con);
542
if (*ret_ptr == DRIZZLE_RETURN_PAUSE)
543
*ret_ptr= DRIZZLE_RETURN_OK;
544
else if (*ret_ptr != DRIZZLE_RETURN_OK &&
545
*ret_ptr != DRIZZLE_RETURN_IO_WAIT &&
546
*ret_ptr != DRIZZLE_RETURN_ERROR_CODE)
548
drizzle_result_free(con->result);
559
drizzle_return_t drizzle_con_listen(drizzle_con_st *con)
561
if (con->options & DRIZZLE_CON_READY)
562
return DRIZZLE_RETURN_OK;
564
if (drizzle_state_none(con))
566
drizzle_state_push(con, drizzle_state_listen);
567
drizzle_state_push(con, drizzle_state_addrinfo);
570
return drizzle_state_loop(con);
573
int drizzle_con_backlog(const drizzle_con_st *con)
578
void drizzle_con_set_backlog(drizzle_con_st *con, int backlog)
580
con->backlog= backlog;
583
void drizzle_con_set_protocol_version(drizzle_con_st *con,
584
uint8_t protocol_version)
586
con->protocol_version= protocol_version;
589
void drizzle_con_set_server_version(drizzle_con_st *con,
590
const char *server_version)
592
if (server_version == NULL)
593
con->server_version[0]= 0;
596
strncpy(con->server_version, server_version,
597
DRIZZLE_MAX_SERVER_VERSION_SIZE);
598
con->server_version[DRIZZLE_MAX_SERVER_VERSION_SIZE - 1]= 0;
602
void drizzle_con_set_thread_id(drizzle_con_st *con, uint32_t thread_id)
604
con->thread_id= thread_id;
607
void drizzle_con_set_scramble(drizzle_con_st *con, const uint8_t *scramble)
609
if (scramble == NULL)
613
con->scramble= con->scramble_buffer;
614
memcpy(con->scramble, scramble, DRIZZLE_MAX_SCRAMBLE_SIZE);
618
void drizzle_con_set_capabilities(drizzle_con_st *con,
621
con->capabilities= capabilities;
624
void drizzle_con_set_charset(drizzle_con_st *con, drizzle_charset_t charset)
626
con->charset= charset;
629
void drizzle_con_set_status(drizzle_con_st *con, drizzle_con_status_t status)
634
void drizzle_con_set_max_packet_size(drizzle_con_st *con,
635
uint32_t max_packet_size)
637
con->max_packet_size= max_packet_size;
640
void drizzle_con_copy_handshake(drizzle_con_st *con, drizzle_con_st *from)
642
drizzle_con_set_auth(con, from->user, NULL);
643
drizzle_con_set_scramble(con, from->scramble);
644
drizzle_con_set_db(con, from->db);
645
drizzle_con_set_protocol_version(con, from->protocol_version);
646
drizzle_con_set_server_version(con, from->server_version);
647
drizzle_con_set_thread_id(con, from->thread_id);
648
drizzle_con_set_scramble(con, from->scramble);
649
drizzle_con_set_capabilities(con, from->capabilities);
650
drizzle_con_set_charset(con, from->charset);
651
drizzle_con_set_status(con, from->status);
652
drizzle_con_set_max_packet_size(con, from->max_packet_size);
655
void *drizzle_con_command_read(drizzle_con_st *con,
656
drizzle_command_t *command, size_t *offset,
657
size_t *size, size_t *total,
658
drizzle_return_t *ret_ptr)
660
if (drizzle_state_none(con))
662
con->packet_number= 0;
663
con->command_offset= 0;
664
con->command_total= 0;
666
drizzle_state_push(con, drizzle_state_command_read);
667
drizzle_state_push(con, drizzle_state_packet_read);
670
*offset= con->command_offset;
672
*ret_ptr= drizzle_state_loop(con);
673
if (*ret_ptr == DRIZZLE_RETURN_PAUSE)
674
*ret_ptr= DRIZZLE_RETURN_OK;
676
*command= con->command;
677
*size= con->command_size;
678
*total= con->command_total;
680
return con->command_data;
683
void *drizzle_con_command_buffer(drizzle_con_st *con,
684
drizzle_command_t *command, size_t *total,
685
drizzle_return_t *ret_ptr)
690
uint8_t *command_data=
691
static_cast<uint8_t *>(drizzle_con_command_read(con, command, &offset,
692
&size, total, ret_ptr));
693
if (*ret_ptr != DRIZZLE_RETURN_OK)
696
if (command_data == NULL)
702
if (con->command_buffer == NULL)
704
con->command_buffer= new uint8_t[(*total) + 1];
705
if (con->command_buffer == NULL)
707
drizzle_set_error(con->drizzle, "drizzle_command_buffer", "malloc");
708
*ret_ptr= DRIZZLE_RETURN_MEMORY;
713
memcpy(con->command_buffer + offset, command_data, size);
715
while ((offset + size) != (*total))
717
command_data= (uint8_t *)drizzle_con_command_read(con, command, &offset,
718
&size, total, ret_ptr);
719
if (*ret_ptr != DRIZZLE_RETURN_OK)
722
memcpy(con->command_buffer + offset, command_data, size);
725
command_data= con->command_buffer;
726
con->command_buffer= NULL;
727
command_data[*total]= 0;
732
void drizzle_con_command_buffer_free(uint8_t *command_buffer)
734
delete[] command_buffer;
741
void drizzle_con_reset_addrinfo(drizzle_con_st *con)
743
switch (con->socket_type)
745
case DRIZZLE_CON_SOCKET_TCP:
746
if (con->socket.tcp.addrinfo != NULL)
748
freeaddrinfo(con->socket.tcp.addrinfo);
749
con->socket.tcp.addrinfo= NULL;
753
case DRIZZLE_CON_SOCKET_UDS:
754
con->socket.uds.addrinfo.ai_addr= NULL;
761
con->addrinfo_next= NULL;
768
drizzle_return_t drizzle_state_addrinfo(drizzle_con_st *con)
770
drizzle_con_tcp_st *tcp;
772
char port[NI_MAXSERV];
776
drizzle_log_debug(con->drizzle, "drizzle_state_addrinfo");
778
switch (con->socket_type)
780
case DRIZZLE_CON_SOCKET_TCP:
781
tcp= &(con->socket.tcp);
783
if (tcp->addrinfo != NULL)
785
freeaddrinfo(tcp->addrinfo);
790
snprintf(port, NI_MAXSERV, "%u", tcp->port);
791
else if (con->options & DRIZZLE_CON_MYSQL)
792
snprintf(port, NI_MAXSERV, "%u", DRIZZLE_DEFAULT_TCP_PORT_MYSQL);
794
snprintf(port, NI_MAXSERV, "%u", DRIZZLE_DEFAULT_TCP_PORT);
796
ai.ai_socktype= SOCK_STREAM;
797
ai.ai_protocol= IPPROTO_TCP;
798
ai.ai_flags = AI_PASSIVE;
799
ai.ai_family = AF_UNSPEC;
801
if (con->options & DRIZZLE_CON_LISTEN)
807
if (tcp->host == NULL)
808
host= DRIZZLE_DEFAULT_TCP_HOST;
813
ret= getaddrinfo(host, port, &ai, &(tcp->addrinfo));
816
drizzle_set_error(con->drizzle, "drizzle_state_addrinfo",
817
"getaddrinfo:%s", gai_strerror(ret));
818
return DRIZZLE_RETURN_GETADDRINFO;
821
con->addrinfo_next= tcp->addrinfo;
825
case DRIZZLE_CON_SOCKET_UDS:
826
con->addrinfo_next= &(con->socket.uds.addrinfo);
833
drizzle_state_pop(con);
834
return DRIZZLE_RETURN_OK;
837
drizzle_return_t drizzle_state_connect(drizzle_con_st *con)
840
drizzle_return_t dret;
842
drizzle_log_debug(con->drizzle, "drizzle_state_connect");
846
(void)close(con->fd);
850
if (con->addrinfo_next == NULL)
852
drizzle_set_error(con->drizzle, "drizzle_state_connect",
853
"could not connect");
854
drizzle_state_reset(con);
855
return DRIZZLE_RETURN_COULD_NOT_CONNECT;
858
con->fd= socket(con->addrinfo_next->ai_family,
859
con->addrinfo_next->ai_socktype,
860
con->addrinfo_next->ai_protocol);
863
drizzle_set_error(con->drizzle, "drizzle_state_connect", "socket:%d",
865
con->drizzle->last_errno= errno;
866
return DRIZZLE_RETURN_ERRNO;
869
dret= _con_setsockopt(con);
870
if (dret != DRIZZLE_RETURN_OK)
872
con->drizzle->last_errno= errno;
878
ret= connect(con->fd, con->addrinfo_next->ai_addr,
879
con->addrinfo_next->ai_addrlen);
882
/*Mapping windows specific error codes to Posix*/
883
errno = WSAGetLastError();
895
drizzle_log_crazy(con->drizzle, "connect return=%d errno=%d", ret, errno);
899
con->addrinfo_next= NULL;
903
if (errno == EAGAIN || errno == EINTR)
906
if (errno == EINPROGRESS)
908
drizzle_state_pop(con);
909
drizzle_state_push(con, drizzle_state_connecting);
910
return DRIZZLE_RETURN_OK;
913
if (errno == ECONNREFUSED || errno == ENETUNREACH || errno == ETIMEDOUT)
915
con->addrinfo_next= con->addrinfo_next->ai_next;
916
return DRIZZLE_RETURN_OK;
919
drizzle_set_error(con->drizzle, "drizzle_state_connect", "connect:%d",
921
con->drizzle->last_errno= errno;
922
return DRIZZLE_RETURN_ERRNO;
925
drizzle_state_pop(con);
926
return DRIZZLE_RETURN_OK;
929
drizzle_return_t drizzle_state_connecting(drizzle_con_st *con)
931
drizzle_return_t ret;
933
drizzle_log_debug(con->drizzle, "drizzle_state_connecting");
937
if (con->revents & POLLOUT)
939
drizzle_state_pop(con);
940
return DRIZZLE_RETURN_OK;
942
else if (con->revents & (POLLERR | POLLHUP | POLLNVAL))
945
drizzle_state_pop(con);
946
drizzle_state_push(con, drizzle_state_connect);
947
con->addrinfo_next= con->addrinfo_next->ai_next;
948
return DRIZZLE_RETURN_OK;
951
ret= drizzle_con_set_events(con, POLLOUT);
952
if (ret != DRIZZLE_RETURN_OK)
955
if (con->drizzle->options & DRIZZLE_NON_BLOCKING)
956
return DRIZZLE_RETURN_IO_WAIT;
958
ret= drizzle_con_wait(con->drizzle);
959
if (ret != DRIZZLE_RETURN_OK)
964
drizzle_return_t drizzle_state_read(drizzle_con_st *con)
966
drizzle_return_t ret;
969
drizzle_log_debug(con->drizzle, "drizzle_state_read");
971
if (con->buffer_size == 0)
972
con->buffer_ptr= con->buffer;
973
else if ((con->buffer_ptr - con->buffer) > (DRIZZLE_MAX_BUFFER_SIZE / 2))
975
memmove(con->buffer, con->buffer_ptr, con->buffer_size);
976
con->buffer_ptr= con->buffer;
979
if ((con->revents & POLLIN) == 0 &&
980
(con->drizzle->options & DRIZZLE_NON_BLOCKING))
982
/* non-blocking mode: return IO_WAIT instead of attempting to read. This
983
* avoids reading immediately after writing a command, which typically
984
* returns EAGAIN. This improves performance. */
985
ret= drizzle_con_set_events(con, POLLIN);
986
if (ret != DRIZZLE_RETURN_OK)
988
return DRIZZLE_RETURN_IO_WAIT;
993
size_t available_buffer= (size_t)DRIZZLE_MAX_BUFFER_SIZE -
994
((size_t)(con->buffer_ptr - con->buffer) + con->buffer_size);
995
read_size = recv(con->fd, (char *)con->buffer_ptr + con->buffer_size,
996
available_buffer, 0);
998
/*Get windows error codes and map it to Posix*/
999
errno = WSAGetLastError();
1001
case WSAEWOULDBLOCK:
1009
drizzle_log_crazy(con->drizzle, "read fd=%d return=%zd errno=%d", con->fd,
1014
drizzle_set_error(con->drizzle, "drizzle_state_read",
1015
"lost connection to server (EOF)");
1016
return DRIZZLE_RETURN_LOST_CONNECTION;
1018
else if (read_size == -1)
1020
if (errno == EAGAIN)
1022
/* clear the read ready flag */
1023
con->revents&= ~POLLIN;
1024
ret= drizzle_con_set_events(con, POLLIN);
1025
if (ret != DRIZZLE_RETURN_OK)
1028
if (con->drizzle->options & DRIZZLE_NON_BLOCKING)
1029
return DRIZZLE_RETURN_IO_WAIT;
1031
ret= drizzle_con_wait(con->drizzle);
1032
if (ret != DRIZZLE_RETURN_OK)
1037
else if (errno == ECONNREFUSED)
1040
drizzle_state_pop(con);
1041
drizzle_state_push(con, drizzle_state_connect);
1042
con->addrinfo_next= con->addrinfo_next->ai_next;
1043
return DRIZZLE_RETURN_OK;
1045
else if (errno == EINTR)
1047
else if (errno == EPIPE || errno == ECONNRESET)
1049
drizzle_set_error(con->drizzle, "drizzle_state_read",
1050
"lost connection to server (%d)", errno);
1051
return DRIZZLE_RETURN_LOST_CONNECTION;
1054
drizzle_set_error(con->drizzle, "drizzle_state_read", "read:%d", errno);
1055
con->drizzle->last_errno= errno;
1056
return DRIZZLE_RETURN_ERRNO;
1059
/* clear the "read ready" flag if we read all available data. */
1060
if ((size_t) read_size < available_buffer) con->revents&= ~POLLIN;
1061
con->buffer_size+= (size_t)read_size;
1065
drizzle_state_pop(con);
1066
return DRIZZLE_RETURN_OK;
1069
drizzle_return_t drizzle_state_write(drizzle_con_st *con)
1071
drizzle_return_t ret;
1074
drizzle_log_debug(con->drizzle, "drizzle_state_write");
1076
while (con->buffer_size != 0)
1079
write_size = send(con->fd,(char *) con->buffer_ptr, con->buffer_size, 0);
1081
drizzle_log_crazy(con->drizzle, "write fd=%d return=%zd errno=%d", con->fd,
1084
if (write_size == 0)
1086
drizzle_set_error(con->drizzle, "drizzle_state_write",
1087
"lost connection to server (EOF)");
1088
return DRIZZLE_RETURN_LOST_CONNECTION;
1090
else if (write_size == -1)
1092
if (errno == EAGAIN)
1094
ret= drizzle_con_set_events(con, POLLOUT);
1095
if (ret != DRIZZLE_RETURN_OK)
1098
if (con->drizzle->options & DRIZZLE_NON_BLOCKING)
1099
return DRIZZLE_RETURN_IO_WAIT;
1101
ret= drizzle_con_wait(con->drizzle);
1102
if (ret != DRIZZLE_RETURN_OK)
1107
else if (errno == EINTR)
1109
else if (errno == EPIPE || errno == ECONNRESET)
1111
drizzle_set_error(con->drizzle, "drizzle_state_write",
1112
"lost connection to server (%d)", errno);
1113
return DRIZZLE_RETURN_LOST_CONNECTION;
1116
drizzle_set_error(con->drizzle, "drizzle_state_write", "write:%d", errno);
1117
con->drizzle->last_errno= errno;
1118
return DRIZZLE_RETURN_ERRNO;
1121
con->buffer_ptr+= write_size;
1122
con->buffer_size-= (size_t)write_size;
1123
if (con->buffer_size == 0)
1127
con->buffer_ptr= con->buffer;
1129
drizzle_state_pop(con);
1130
return DRIZZLE_RETURN_OK;
1133
drizzle_return_t drizzle_state_listen(drizzle_con_st *con)
1135
char host[NI_MAXHOST];
1136
char port[NI_MAXSERV];
1140
drizzle_con_st *new_con;
1142
for (; con->addrinfo_next != NULL;
1143
con->addrinfo_next= con->addrinfo_next->ai_next)
1145
ret= getnameinfo(con->addrinfo_next->ai_addr,
1146
con->addrinfo_next->ai_addrlen, host, NI_MAXHOST, port,
1147
NI_MAXSERV, NI_NUMERICHOST | NI_NUMERICSERV);
1150
drizzle_set_error(con->drizzle, "drizzle_state_listen", "getnameinfo:%s",
1152
return DRIZZLE_RETURN_GETADDRINFO;
1155
/* Call to socket() can fail for some getaddrinfo results, try another. */
1156
fd= socket(con->addrinfo_next->ai_family, con->addrinfo_next->ai_socktype,
1157
con->addrinfo_next->ai_protocol);
1160
drizzle_log_info(con->drizzle, "could not listen on %s:%s", host, port);
1161
drizzle_set_error(con->drizzle, "drizzle_state_listen", "socket:%d",
1168
ret= setsockopt(fd, SOL_SOCKET, SO_REUSEADDR,(const char*) &opt, sizeof(opt));
1170
ret= setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt));
1175
drizzle_set_error(con->drizzle, "drizzle_state_listen", "setsockopt:%d",
1177
return DRIZZLE_RETURN_ERRNO;
1180
ret= bind(fd, con->addrinfo_next->ai_addr, con->addrinfo_next->ai_addrlen);
1184
drizzle_set_error(con->drizzle, "drizzle_state_listen", "bind:%d", errno);
1185
if (errno == EADDRINUSE)
1189
drizzle_log_info(con->drizzle, "could not listen on %s:%s", host,
1196
return DRIZZLE_RETURN_ERRNO;
1199
if (listen(fd, con->backlog) == -1)
1202
drizzle_set_error(con->drizzle, "drizzle_state_listen", "listen:%d",
1204
return DRIZZLE_RETURN_ERRNO;
1214
new_con= drizzle_con_clone(con->drizzle, NULL, con);
1215
if (new_con == NULL)
1218
return DRIZZLE_RETURN_MEMORY;
1224
/* Wait for read events on the listening socket. */
1225
drizzle_return_t driz_ret= drizzle_con_set_events(new_con, POLLIN);
1226
if (ret != DRIZZLE_RETURN_OK)
1228
drizzle_con_free(new_con);
1232
drizzle_log_info(con->drizzle, "listening on %s:%s", host, port);
1235
/* Report last socket() error if we couldn't find an address to bind. */
1237
return DRIZZLE_RETURN_ERRNO;
1239
drizzle_state_pop(con);
1240
return DRIZZLE_RETURN_OK;
1244
* Static Definitions
1247
static drizzle_return_t _con_setsockopt(drizzle_con_st *con)
1250
struct linger linger;
1251
struct timeval waittime;
1256
ret= setsockopt(con->fd, IPPROTO_TCP, TCP_NODELAY, (const char*)&ret,
1257
(socklen_t)sizeof(int));
1259
ret= setsockopt(con->fd, IPPROTO_TCP, TCP_NODELAY, &ret,
1260
(socklen_t)sizeof(int));
1263
if (ret == -1 && errno != EOPNOTSUPP)
1265
drizzle_set_error(con->drizzle, "_con_setsockopt",
1266
"setsockopt:TCP_NODELAY:%d", errno);
1267
return DRIZZLE_RETURN_ERRNO;
1271
linger.l_linger= DRIZZLE_DEFAULT_SOCKET_TIMEOUT;
1274
ret= setsockopt(con->fd, SOL_SOCKET, SO_LINGER, (const char*)&linger,
1275
(socklen_t)sizeof(struct linger));
1277
ret= setsockopt(con->fd, SOL_SOCKET, SO_LINGER, &linger,
1278
(socklen_t)sizeof(struct linger));
1283
drizzle_set_error(con->drizzle, "_con_setsockopt",
1284
"setsockopt:SO_LINGER:%d", errno);
1285
return DRIZZLE_RETURN_ERRNO;
1288
waittime.tv_sec= DRIZZLE_DEFAULT_SOCKET_TIMEOUT;
1289
waittime.tv_usec= 0;
1292
ret= setsockopt(con->fd, SOL_SOCKET, SO_SNDTIMEO, (const char*)&waittime,
1293
(socklen_t)sizeof(struct timeval));
1295
ret= setsockopt(con->fd, SOL_SOCKET, SO_SNDTIMEO, &waittime,
1296
(socklen_t)sizeof(struct timeval));
1299
if (ret == -1 && errno != ENOPROTOOPT)
1301
drizzle_set_error(con->drizzle, "_con_setsockopt",
1302
"setsockopt:SO_SNDTIMEO:%d", errno);
1303
return DRIZZLE_RETURN_ERRNO;
1307
ret= setsockopt(con->fd, SOL_SOCKET, SO_RCVTIMEO, (const char*)&waittime,
1308
(socklen_t)sizeof(struct timeval));
1310
ret= setsockopt(con->fd, SOL_SOCKET, SO_RCVTIMEO, &waittime,
1311
(socklen_t)sizeof(struct timeval));
1314
if (ret == -1 && errno != ENOPROTOOPT)
1316
drizzle_set_error(con->drizzle, "_con_setsockopt",
1317
"setsockopt:SO_RCVTIMEO:%d", errno);
1318
return DRIZZLE_RETURN_ERRNO;
1321
ret= DRIZZLE_DEFAULT_SOCKET_SEND_SIZE;
1323
ret= setsockopt(con->fd, SOL_SOCKET, SO_SNDBUF, (const char*)&ret, (socklen_t)sizeof(int));
1325
ret= setsockopt(con->fd, SOL_SOCKET, SO_SNDBUF, &ret, (socklen_t)sizeof(int));
1329
drizzle_set_error(con->drizzle, "_con_setsockopt",
1330
"setsockopt:SO_SNDBUF:%d", errno);
1331
return DRIZZLE_RETURN_ERRNO;
1334
ret= DRIZZLE_DEFAULT_SOCKET_RECV_SIZE;
1336
ret= setsockopt(con->fd, SOL_SOCKET, SO_RCVBUF, (const char*)&ret, (socklen_t)sizeof(int));
1338
ret= setsockopt(con->fd, SOL_SOCKET, SO_RCVBUF, &ret, (socklen_t)sizeof(int));
1342
drizzle_set_error(con->drizzle, "_con_setsockopt",
1343
"setsockopt:SO_RCVBUF:%d", errno);
1344
return DRIZZLE_RETURN_ERRNO;
1347
#if defined (_WIN32)
1349
unsigned long asyncmode;
1351
ioctlsocket(con->fd, FIONBIO, &asyncmode);
1354
ret= fcntl(con->fd, F_GETFL, 0);
1357
drizzle_set_error(con->drizzle, "_con_setsockopt", "fcntl:F_GETFL:%d",
1359
return DRIZZLE_RETURN_ERRNO;
1362
ret= fcntl(con->fd, F_SETFL, ret | O_NONBLOCK);
1365
drizzle_set_error(con->drizzle, "_con_setsockopt", "fcntl:F_SETFL:%d",
1367
return DRIZZLE_RETURN_ERRNO;
1371
return DRIZZLE_RETURN_OK;