libdrizzle Developer Documentation

conn.c
Go to the documentation of this file.
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 
16 #include "common.h"
17 
32 
35 /*
36  * Common Definitions
37  */
38 
40 {
41  return con->fd;
42 }
43 
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 
58 {
59  if (con->fd == -1)
60  return;
61 
62  (void)close(con->fd);
63  con->fd= -1;
64 
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 
73 }
74 
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,
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 
99 {
100  drizzle_return_t ret;
101 
102  if (revents != 0)
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,
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 
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 
139 {
140  return drizzle_errno(con->drizzle);
141 }
142 
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 
154 {
155  return con->options;
156 }
157 
159  drizzle_con_options_t options)
160 {
161  con->options= options;
162 }
163 
165  drizzle_con_options_t options)
166 {
167  con->options|= options;
168 
169  /* If asking for the experimental Drizzle protocol, clean the MySQL flag. */
172 }
173 
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 {
183  {
184  if (con->socket.tcp.host == NULL && !(con->options & DRIZZLE_CON_LISTEN))
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 {
196  {
197  if (con->socket.tcp.port != 0)
198  return con->socket.tcp.port;
199 
200  if (con->options & DRIZZLE_CON_MYSQL)
202 
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 {
212 
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 
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 
284  drizzle_con_context_free_fn *function)
285 {
286  con->context_free_fn= function;
287 }
288 
290 {
291  return con->protocol_version;
292 }
293 
295 {
296  return con->server_version;
297 }
298 
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 
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 
329 {
330  return con->capabilities;
331 }
332 
334 {
335  return con->charset;
336 }
337 
339 {
340  return con->status;
341 }
342 
344 {
345  return con->max_packet_size;
346 }
347 
348 /*
349  * Client Definitions
350  */
351 
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  {
363  }
364 
367  }
368 
369  return drizzle_state_loop(con);
370 }
371 
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 
381  drizzle_result_st *result,
382  drizzle_return_t *ret_ptr)
383 {
384  return drizzle_con_quit(con, result, ret_ptr);
385 }
386 
388  drizzle_result_st *result,
389  const char *db,
390  drizzle_return_t *ret_ptr)
391 {
392  drizzle_con_set_db(con, db);
394  db, strlen(db), strlen(db), ret_ptr);
395 }
396 
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 
406  drizzle_result_st *result,
407  drizzle_return_t *ret_ptr)
408 {
409  if (con->options & DRIZZLE_CON_MYSQL)
410  {
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 
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 
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 
436  drizzle_result_st *result,
437  drizzle_return_t *ret_ptr)
438 {
439  return drizzle_con_ping(con, result, ret_ptr);
440 }
441 
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  {
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 
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  {
500  con->result= result;
501  }
502 
503  return con->result;
504 }
505 
506 /*
507  * Server Definitions
508  */
509 
511 {
512  if (con->options & DRIZZLE_CON_READY)
513  return DRIZZLE_RETURN_OK;
514 
515  if (drizzle_state_none(con))
516  {
519  }
520 
521  return drizzle_state_loop(con);
522 }
523 
525 {
526  return con->backlog;
527 }
528 
530 {
531  con->backlog= backlog;
532 }
533 
535  uint8_t protocol_version)
536 {
537  con->protocol_version= protocol_version;
538 }
539 
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,
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 
570  drizzle_capabilities_t capabilities)
571 {
572  con->capabilities= capabilities;
573 }
574 
576 {
577  con->charset= charset;
578 }
579 
581 {
582  con->status= status;
583 }
584 
586  uint32_t max_packet_size)
587 {
588  con->max_packet_size= max_packet_size;
589 }
590 
592 {
593  drizzle_con_set_auth(con, from->user, NULL);
595  drizzle_con_set_db(con, from->db);
601  drizzle_con_set_charset(con, from->charset);
602  drizzle_con_set_status(con, from->status);
604 }
605 
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 
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 
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 
688 {
689  switch (con->socket_type)
690  {
692  if (con->socket.tcp.addrinfo != NULL)
693  {
694  freeaddrinfo(con->socket.tcp.addrinfo);
695  con->socket.tcp.addrinfo= NULL;
696  }
697  break;
698 
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 
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  {
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)
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));
766  }
767 
768  con->addrinfo_next= tcp->addrinfo;
769 
770  break;
771 
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 
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);
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  drizzle_log_crazy(con->drizzle, "connect return=%d errno=%d", ret, errno);
829 
830  if (ret == 0)
831  {
832  con->addrinfo_next= NULL;
833  break;
834  }
835 
836  if (errno == EAGAIN || errno == EINTR)
837  continue;
838 
839  if (errno == EINPROGRESS)
840  {
841  drizzle_state_pop(con);
843  return DRIZZLE_RETURN_OK;
844  }
845 
846  if (errno == ECONNREFUSED || errno == ENETUNREACH || errno == ETIMEDOUT)
847  {
848  con->addrinfo_next= con->addrinfo_next->ai_next;
849  return DRIZZLE_RETURN_OK;
850  }
851 
852  drizzle_set_error(con->drizzle, "drizzle_state_connect", "connect:%d",
853  errno);
854  con->drizzle->last_errno= errno;
855  return DRIZZLE_RETURN_ERRNO;
856  }
857 
858  drizzle_state_pop(con);
859  return DRIZZLE_RETURN_OK;
860 }
861 
863 {
864  drizzle_return_t ret;
865 
866  drizzle_log_debug(con->drizzle, "drizzle_state_connecting");
867 
868  while (1)
869  {
870  if (con->revents & POLLOUT)
871  {
872  drizzle_state_pop(con);
873  return DRIZZLE_RETURN_OK;
874  }
875  else if (con->revents & (POLLERR | POLLHUP | POLLNVAL))
876  {
877  con->revents= 0;
878  drizzle_state_pop(con);
880  con->addrinfo_next= con->addrinfo_next->ai_next;
881  return DRIZZLE_RETURN_OK;
882  }
883 
884  ret= drizzle_con_set_events(con, POLLOUT);
885  if (ret != DRIZZLE_RETURN_OK)
886  return ret;
887 
889  return DRIZZLE_RETURN_IO_WAIT;
890 
891  ret= drizzle_con_wait(con->drizzle);
892  if (ret != DRIZZLE_RETURN_OK)
893  return ret;
894  }
895 }
896 
898 {
899  drizzle_return_t ret;
900  ssize_t read_size;
901 
902  drizzle_log_debug(con->drizzle, "drizzle_state_read");
903 
904  if (con->buffer_size == 0)
905  con->buffer_ptr= con->buffer;
906  else if ((con->buffer_ptr - con->buffer) > (DRIZZLE_MAX_BUFFER_SIZE / 2))
907  {
908  memmove(con->buffer, con->buffer_ptr, con->buffer_size);
909  con->buffer_ptr= con->buffer;
910  }
911 
912  while (1)
913  {
914  read_size= read(con->fd, con->buffer_ptr + con->buffer_size,
915  (size_t)DRIZZLE_MAX_BUFFER_SIZE -
916  ((size_t)(con->buffer_ptr - con->buffer) +
917  con->buffer_size));
918 
919  drizzle_log_crazy(con->drizzle, "read fd=%d return=%zd errno=%d", con->fd,
920  read_size, errno);
921 
922  if (read_size == 0)
923  {
924  drizzle_set_error(con->drizzle, "drizzle_state_read",
925  "lost connection to server (EOF)");
927  }
928  else if (read_size == -1)
929  {
930  if (errno == EAGAIN)
931  {
932  ret= drizzle_con_set_events(con, POLLIN);
933  if (ret != DRIZZLE_RETURN_OK)
934  return 0;
935 
937  return DRIZZLE_RETURN_IO_WAIT;
938 
939  ret= drizzle_con_wait(con->drizzle);
940  if (ret != DRIZZLE_RETURN_OK)
941  return ret;
942 
943  continue;
944  }
945  else if (errno == ECONNREFUSED)
946  {
947  con->revents= 0;
948  drizzle_state_pop(con);
950  con->addrinfo_next= con->addrinfo_next->ai_next;
951  return DRIZZLE_RETURN_OK;
952  }
953  else if (errno == EINTR)
954  continue;
955  else if (errno == EPIPE || errno == ECONNRESET)
956  {
957  drizzle_set_error(con->drizzle, "drizzle_state_read",
958  "lost connection to server (%d)", errno);
960  }
961 
962  drizzle_set_error(con->drizzle, "drizzle_state_read", "read:%d", errno);
963  con->drizzle->last_errno= errno;
964  return DRIZZLE_RETURN_ERRNO;
965  }
966 
967  con->buffer_size+= (size_t)read_size;
968  break;
969  }
970 
971  drizzle_state_pop(con);;
972  return DRIZZLE_RETURN_OK;
973 }
974 
976 {
977  drizzle_return_t ret;
978  ssize_t write_size;
979 
980  drizzle_log_debug(con->drizzle, "drizzle_state_write");
981 
982  while (con->buffer_size != 0)
983  {
984  write_size= write(con->fd, con->buffer_ptr, con->buffer_size);
985 
986  drizzle_log_crazy(con->drizzle, "write fd=%d return=%zd errno=%d", con->fd,
987  write_size, errno);
988 
989  if (write_size == 0)
990  {
991  drizzle_set_error(con->drizzle, "drizzle_state_write",
992  "lost connection to server (EOF)");
994  }
995  else if (write_size == -1)
996  {
997  if (errno == EAGAIN)
998  {
999  ret= drizzle_con_set_events(con, POLLOUT);
1000  if (ret != DRIZZLE_RETURN_OK)
1001  return ret;
1002 
1003  if (con->drizzle->options & DRIZZLE_NON_BLOCKING)
1004  return DRIZZLE_RETURN_IO_WAIT;
1005 
1006  ret= drizzle_con_wait(con->drizzle);
1007  if (ret != DRIZZLE_RETURN_OK)
1008  return ret;
1009 
1010  continue;
1011  }
1012  else if (errno == EINTR)
1013  continue;
1014  else if (errno == EPIPE || errno == ECONNRESET)
1015  {
1016  drizzle_set_error(con->drizzle, "drizzle_state_write",
1017  "lost connection to server (%d)", errno);
1019  }
1020 
1021  drizzle_set_error(con->drizzle, "drizzle_state_write", "write:%d", errno);
1022  con->drizzle->last_errno= errno;
1023  return DRIZZLE_RETURN_ERRNO;
1024  }
1025 
1026  con->buffer_ptr+= write_size;
1027  con->buffer_size-= (size_t)write_size;
1028  if (con->buffer_size == 0)
1029  break;
1030  }
1031 
1032  con->buffer_ptr= con->buffer;
1033 
1034  drizzle_state_pop(con);
1035  return DRIZZLE_RETURN_OK;
1036 }
1037 
1039 {
1040  char host[NI_MAXHOST];
1041  char port[NI_MAXSERV];
1042  int ret;
1043  int fd;
1044  int opt;
1045  drizzle_con_st *new_con;
1046 
1047  for (; con->addrinfo_next != NULL;
1048  con->addrinfo_next= con->addrinfo_next->ai_next)
1049  {
1050  ret= getnameinfo(con->addrinfo_next->ai_addr,
1051  con->addrinfo_next->ai_addrlen, host, NI_MAXHOST, port,
1052  NI_MAXSERV, NI_NUMERICHOST | NI_NUMERICSERV);
1053  if (ret != 0)
1054  {
1055  drizzle_set_error(con->drizzle, "drizzle_state_listen", "getnameinfo:%s",
1056  gai_strerror(ret));
1058  }
1059 
1060  /* Call to socket() can fail for some getaddrinfo results, try another. */
1061  fd= socket(con->addrinfo_next->ai_family, con->addrinfo_next->ai_socktype,
1062  con->addrinfo_next->ai_protocol);
1063  if (fd == -1)
1064  {
1065  drizzle_log_info(con->drizzle, "could not listen on %s:%s", host, port);
1066  drizzle_set_error(con->drizzle, "drizzle_state_listen", "socket:%d",
1067  errno);
1068  continue;
1069  }
1070 
1071  opt= 1;
1072  ret= setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt));
1073  if (ret == -1)
1074  {
1075  close(fd);
1076  drizzle_set_error(con->drizzle, "drizzle_state_listen", "setsockopt:%d",
1077  errno);
1078  return DRIZZLE_RETURN_ERRNO;
1079  }
1080 
1081  ret= bind(fd, con->addrinfo_next->ai_addr, con->addrinfo_next->ai_addrlen);
1082  if (ret == -1)
1083  {
1084  close(fd);
1085  drizzle_set_error(con->drizzle, "drizzle_state_listen", "bind:%d", errno);
1086  if (errno == EADDRINUSE)
1087  {
1088  if (con->fd == -1)
1089  {
1090  drizzle_log_info(con->drizzle, "could not listen on %s:%s", host,
1091  port);
1092  }
1093 
1094  continue;
1095  }
1096 
1097  return DRIZZLE_RETURN_ERRNO;
1098  }
1099 
1100  if (listen(fd, con->backlog) == -1)
1101  {
1102  close(fd);
1103  drizzle_set_error(con->drizzle, "drizzle_state_listen", "listen:%d",
1104  errno);
1105  return DRIZZLE_RETURN_ERRNO;
1106  }
1107 
1108  if (con->fd == -1)
1109  {
1110  con->fd= fd;
1111  new_con= con;
1112  }
1113  else
1114  {
1115  new_con= drizzle_con_clone(con->drizzle, NULL, con);
1116  if (new_con == NULL)
1117  {
1118  close(fd);
1119  return DRIZZLE_RETURN_MEMORY;
1120  }
1121 
1122  new_con->fd= fd;
1123  }
1124 
1125  /* Wait for read events on the listening socket. */
1126  ret= drizzle_con_set_events(new_con, POLLIN);
1127  if (ret != DRIZZLE_RETURN_OK)
1128  {
1129  drizzle_con_free(new_con);
1130  return ret;
1131  }
1132 
1133  drizzle_log_info(con->drizzle, "listening on %s:%s", host, port);
1134  }
1135 
1136  /* Report last socket() error if we couldn't find an address to bind. */
1137  if (con->fd == -1)
1138  return DRIZZLE_RETURN_ERRNO;
1139 
1140  drizzle_state_pop(con);
1141  return DRIZZLE_RETURN_OK;
1142 }
1143 
1144 /*
1145  * Static Definitions
1146  */
1147 
1149 {
1150  int ret;
1151  struct linger linger;
1152  struct timeval waittime;
1153 
1154  ret= 1;
1155  ret= setsockopt(con->fd, IPPROTO_TCP, TCP_NODELAY, &ret,
1156  (socklen_t)sizeof(int));
1157  if (ret == -1 && errno != EOPNOTSUPP)
1158  {
1159  drizzle_set_error(con->drizzle, "_con_setsockopt",
1160  "setsockopt:TCP_NODELAY:%d", errno);
1161  return DRIZZLE_RETURN_ERRNO;
1162  }
1163 
1164  linger.l_onoff= 1;
1165  linger.l_linger= DRIZZLE_DEFAULT_SOCKET_TIMEOUT;
1166  ret= setsockopt(con->fd, SOL_SOCKET, SO_LINGER, &linger,
1167  (socklen_t)sizeof(struct linger));
1168  if (ret == -1)
1169  {
1170  drizzle_set_error(con->drizzle, "_con_setsockopt",
1171  "setsockopt:SO_LINGER:%d", errno);
1172  return DRIZZLE_RETURN_ERRNO;
1173  }
1174 
1175  waittime.tv_sec= DRIZZLE_DEFAULT_SOCKET_TIMEOUT;
1176  waittime.tv_usec= 0;
1177  ret= setsockopt(con->fd, SOL_SOCKET, SO_SNDTIMEO, &waittime,
1178  (socklen_t)sizeof(struct timeval));
1179  if (ret == -1 && errno != ENOPROTOOPT)
1180  {
1181  drizzle_set_error(con->drizzle, "_con_setsockopt",
1182  "setsockopt:SO_SNDTIMEO:%d", errno);
1183  return DRIZZLE_RETURN_ERRNO;
1184  }
1185 
1186  ret= setsockopt(con->fd, SOL_SOCKET, SO_RCVTIMEO, &waittime,
1187  (socklen_t)sizeof(struct timeval));
1188  if (ret == -1 && errno != ENOPROTOOPT)
1189  {
1190  drizzle_set_error(con->drizzle, "_con_setsockopt",
1191  "setsockopt:SO_RCVTIMEO:%d", errno);
1192  return DRIZZLE_RETURN_ERRNO;
1193  }
1194 
1196  ret= setsockopt(con->fd, SOL_SOCKET, SO_SNDBUF, &ret, (socklen_t)sizeof(int));
1197  if (ret == -1)
1198  {
1199  drizzle_set_error(con->drizzle, "_con_setsockopt",
1200  "setsockopt:SO_SNDBUF:%d", errno);
1201  return DRIZZLE_RETURN_ERRNO;
1202  }
1203 
1205  ret= setsockopt(con->fd, SOL_SOCKET, SO_RCVBUF, &ret, (socklen_t)sizeof(int));
1206  if (ret == -1)
1207  {
1208  drizzle_set_error(con->drizzle, "_con_setsockopt",
1209  "setsockopt:SO_RCVBUF:%d", errno);
1210  return DRIZZLE_RETURN_ERRNO;
1211  }
1212 
1213  ret= fcntl(con->fd, F_GETFL, 0);
1214  if (ret == -1)
1215  {
1216  drizzle_set_error(con->drizzle, "_con_setsockopt", "fcntl:F_GETFL:%d",
1217  errno);
1218  return DRIZZLE_RETURN_ERRNO;
1219  }
1220 
1221  ret= fcntl(con->fd, F_SETFL, ret | O_NONBLOCK);
1222  if (ret == -1)
1223  {
1224  drizzle_set_error(con->drizzle, "_con_setsockopt", "fcntl:F_SETFL:%d",
1225  errno);
1226  return DRIZZLE_RETURN_ERRNO;
1227  }
1228 
1229  return DRIZZLE_RETURN_OK;
1230 }