Drizzled Public API Documentation

conn.cc
Go to the documentation of this file.
1 /* vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
2  *
3  * Drizzle Client & Protocol Library
4  *
5  * Copyright (C) 2008 Eric Day (eday@oddments.org)
6  * All rights reserved.
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions are
10  * met:
11  *
12  * * Redistributions of source code must retain the above copyright
13  * notice, this list of conditions and the following disclaimer.
14  *
15  * * Redistributions in binary form must reproduce the above
16  * copyright notice, this list of conditions and the following disclaimer
17  * in the documentation and/or other materials provided with the
18  * distribution.
19  *
20  * * The names of its contributors may not be used to endorse or
21  * promote products derived from this software without specific prior
22  * written permission.
23  *
24  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
25  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
26  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
27  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
28  * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
29  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
30  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
31  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
32  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
33  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
34  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
35  *
36  */
37 
38 
44 #include <libdrizzle/common.h>
45 
59 static drizzle_return_t _con_setsockopt(drizzle_con_st *con);
60 
61 static bool connect_poll(drizzle_con_st *con)
62 {
63  struct pollfd fds[1];
64  fds[0].fd= con->fd;
65  fds[0].events= POLLOUT;
66 
67  size_t loop_max= 5;
68  while (--loop_max) // Should only loop on cases of ERESTART or EINTR
69  {
70  int error= poll(fds, 1, con->drizzle->timeout);
71  switch (error)
72  {
73  case 1:
74  {
75  int err;
76  socklen_t len= sizeof (err);
77  // We replace errno with err if getsockopt() passes, but err has been
78  // set.
79  if (getsockopt(con->fd, SOL_SOCKET, SO_ERROR, &err, &len) == 0)
80  {
81  // We check the value to see what happened wth the socket.
82  if (err == 0)
83  {
84  return true;
85  }
86  errno= err;
87  }
88 
89  // "getsockopt() failed"
90  return false;
91  }
92 
93  case 0:
94  {
95  // "timeout occurred while trying to connect"
96  return false;
97  }
98 
99  default: // A real error occurred and we need to completely bail
100  switch (get_socket_errno())
101  {
102 #ifdef TARGET_OS_LINUX
103  case ERESTART:
104 #endif
105  case EINTR:
106  continue;
107 
108  case EFAULT:
109  case ENOMEM:
110  // "poll() failure"
111  return false;
112 
113  case EINVAL:
114  // "RLIMIT_NOFILE exceeded, or if OSX the timeout value was invalid"
115  return false;
116 
117  default: // This should not happen
118  if (fds[0].revents & POLLERR)
119  {
120  int err;
121  socklen_t len= sizeof (err);
122  (void)getsockopt(con->fd, SOL_SOCKET, SO_ERROR, &err, &len);
123  errno= err;
124  }
125  else
126  {
127  errno= get_socket_errno();
128  }
129 
130  //"socket error occurred");
131  return false;
132  }
133  }
134  }
135 
136  // This should only be possible from ERESTART or EINTR;
137  // "connection failed (error should be from either ERESTART or EINTR"
138  return false;
139 }
140 
143 /*
144  * Common Definitions
145  */
146 
147 int drizzle_con_fd(const drizzle_con_st *con)
148 {
149  if (con == NULL)
150  {
151  return -1;
152  }
153 
154  return con->fd;
155 }
156 
157 drizzle_return_t drizzle_con_set_fd(drizzle_con_st *con, int fd)
158 {
159  drizzle_return_t ret;
160  if (con == NULL)
161  {
162  return DRIZZLE_RETURN_INVALID_ARGUMENT;
163  }
164 
165  con->fd= fd;
166 
167  ret= _con_setsockopt(con);
168  if (ret != DRIZZLE_RETURN_OK)
169  {
170  con->drizzle->last_errno= errno;
171  }
172 
173  return ret;
174 }
175 
176 void drizzle_con_close(drizzle_con_st *con)
177 {
178  if (con == NULL)
179  {
180  return;
181  }
182 
183  if (con->fd == -1)
184  {
185  return;
186  }
187 
188  (void)closesocket(con->fd);
189  con->fd= -1;
190 
191  con->options&= int(~DRIZZLE_CON_READY);
192  con->packet_number= 0;
193  con->buffer_ptr= con->buffer;
194  con->buffer_size= 0;
195  con->events= 0;
196  con->revents= 0;
197 
198  drizzle_state_reset(con);
199 }
200 
201 drizzle_return_t drizzle_con_set_events(drizzle_con_st *con, short events)
202 {
203  drizzle_return_t ret;
204 
205  if ((con->events | events) == con->events)
206  {
207  return DRIZZLE_RETURN_OK;
208  }
209 
210  con->events|= events;
211 
212  if (con->drizzle->event_watch_fn != NULL)
213  {
214  ret= con->drizzle->event_watch_fn(con, con->events,
215  con->drizzle->event_watch_context);
216  if (ret != DRIZZLE_RETURN_OK)
217  {
218  drizzle_con_close(con);
219  return ret;
220  }
221  }
222 
223  return DRIZZLE_RETURN_OK;
224 }
225 
226 drizzle_return_t drizzle_con_set_revents(drizzle_con_st *con, short revents)
227 {
228  drizzle_return_t ret;
229  if (con == NULL)
230  {
231  return DRIZZLE_RETURN_INVALID_ARGUMENT;
232  }
233 
234  if (revents != 0)
235  con->options|= DRIZZLE_CON_IO_READY;
236 
237  con->revents= revents;
238 
239  /* Remove external POLLOUT watch if we didn't ask for it. Otherwise we spin
240  forever until another POLLIN state change. This is much more efficient
241  than removing POLLOUT on every state change since some external polling
242  mechanisms need to use a system call to change flags (like Linux epoll). */
243  if (revents & POLLOUT && !(con->events & POLLOUT) &&
244  con->drizzle->event_watch_fn != NULL)
245  {
246  ret= con->drizzle->event_watch_fn(con, con->events,
247  con->drizzle->event_watch_context);
248  if (ret != DRIZZLE_RETURN_OK)
249  {
250  drizzle_con_close(con);
251  return ret;
252  }
253  }
254 
255  con->events&= (short)~revents;
256 
257  return DRIZZLE_RETURN_OK;
258 }
259 
260 drizzle_st *drizzle_con_drizzle(const drizzle_con_st *con)
261 {
262  if (con == NULL)
263  {
264  return NULL;
265  }
266  return con->drizzle;
267 }
268 
269 const char *drizzle_con_error(const drizzle_con_st *con)
270 {
271  if (con == NULL)
272  {
273  return NULL;
274  }
275 
276  return drizzle_error(con->drizzle);
277 }
278 
279 int drizzle_con_errno(const drizzle_con_st *con)
280 {
281  if (con == NULL)
282  {
283  return 0;
284  }
285 
286  return drizzle_errno(con->drizzle);
287 }
288 
289 uint16_t drizzle_con_error_code(const drizzle_con_st *con)
290 {
291  if (con == NULL)
292  {
293  return 0;
294  }
295 
296  return drizzle_error_code(con->drizzle);
297 }
298 
299 const char *drizzle_con_sqlstate(const drizzle_con_st *con)
300 {
301  if (con == NULL)
302  {
303  return NULL;
304  }
305 
306  return drizzle_sqlstate(con->drizzle);
307 }
308 
309 drizzle_con_options_t drizzle_con_options(const drizzle_con_st *con)
310 {
311  if (con == NULL)
312  {
313  return drizzle_con_options_t();
314  }
315 
316  return drizzle_con_options_t(con->options);
317 }
318 
319 void drizzle_con_set_options(drizzle_con_st *con,
320  drizzle_con_options_t options)
321 {
322  if (con == NULL)
323  {
324  return;
325  }
326 
327  con->options= options;
328 }
329 
330 void drizzle_con_add_options(drizzle_con_st *con,
331  drizzle_con_options_t options)
332 {
333  if (con == NULL)
334  {
335  return;
336  }
337 
338  con->options|= options;
339 
340  /* If asking for the experimental Drizzle protocol, clean the MySQL flag. */
341  if (con->options & DRIZZLE_CON_EXPERIMENTAL)
342  {
343  con->options&= int(~DRIZZLE_CON_MYSQL);
344  }
345 }
346 
347 void drizzle_con_remove_options(drizzle_con_st *con,
348  drizzle_con_options_t options)
349 {
350  if (con == NULL)
351  {
352  return;
353  }
354 
355  con->options&= ~options;
356 }
357 
358 const char *drizzle_con_host(const drizzle_con_st *con)
359 {
360  if (con == NULL)
361  {
362  return NULL;
363  }
364 
365  if (con->socket_type == DRIZZLE_CON_SOCKET_TCP)
366  {
367  if (con->socket.tcp.host == NULL && !(con->options & DRIZZLE_CON_LISTEN))
368  return DRIZZLE_DEFAULT_TCP_HOST;
369 
370  return con->socket.tcp.host;
371  }
372 
373  return NULL;
374 }
375 
376 in_port_t drizzle_con_port(const drizzle_con_st *con)
377 {
378  if (con and con->socket_type == DRIZZLE_CON_SOCKET_TCP)
379  {
380  if (con->socket.tcp.port != 0)
381  {
382  return con->socket.tcp.port;
383  }
384 
385  if (con->options & DRIZZLE_CON_MYSQL)
386  {
387  return DRIZZLE_DEFAULT_TCP_PORT_MYSQL;
388  }
389 
390  return DRIZZLE_DEFAULT_TCP_PORT;
391  }
392 
393  return in_port_t(0);
394 }
395 
396 void drizzle_con_set_tcp(drizzle_con_st *con, const char *host, in_port_t port)
397 {
398  if (con == NULL)
399  {
400  return;
401  }
402 
404 
405  con->socket_type= DRIZZLE_CON_SOCKET_TCP;
406 
407  if (host == NULL)
408  {
409  con->socket.tcp.host= NULL;
410  }
411  else
412  {
413  con->socket.tcp.host= con->socket.tcp.host_buffer;
414  strncpy(con->socket.tcp.host, host, NI_MAXHOST);
415  con->socket.tcp.host[NI_MAXHOST - 1]= 0;
416  }
417 
418  con->socket.tcp.port= port;
419 }
420 
421 const char *drizzle_con_user(const drizzle_con_st *con)
422 {
423  if (con == NULL)
424  {
425  return NULL;
426  }
427 
428  return con->user;
429 }
430 
431 const char *drizzle_con_password(const drizzle_con_st *con)
432 {
433  if (con == NULL)
434  {
435  return NULL;
436  }
437 
438  return con->password;
439 }
440 
441 void drizzle_con_set_auth(drizzle_con_st *con, const char *user,
442  const char *password)
443 {
444  if (con == NULL)
445  {
446  return;
447  }
448 
449  if (user == NULL)
450  {
451  con->user[0]= 0;
452  }
453  else
454  {
455  strncpy(con->user, user, DRIZZLE_MAX_USER_SIZE);
456  con->user[DRIZZLE_MAX_USER_SIZE - 1]= 0;
457  }
458 
459  if (password == NULL)
460  {
461  con->password[0]= 0;
462  }
463  else
464  {
465  strncpy(con->password, password, DRIZZLE_MAX_PASSWORD_SIZE);
466  con->password[DRIZZLE_MAX_PASSWORD_SIZE - 1]= 0;
467  }
468 }
469 
470 const char *drizzle_con_db(const drizzle_con_st *con)
471 {
472  if (con == NULL)
473  {
474  return NULL;
475  }
476 
477  return con->db;
478 }
479 
480 void drizzle_con_set_db(drizzle_con_st *con, const char *db)
481 {
482  if (con == NULL)
483  {
484  return;
485  }
486 
487  if (db == NULL)
488  {
489  con->db[0]= 0;
490  }
491  else
492  {
493  strncpy(con->db, db, DRIZZLE_MAX_DB_SIZE);
494  con->db[DRIZZLE_MAX_DB_SIZE - 1]= 0;
495  }
496 }
497 
498 void *drizzle_con_context(const drizzle_con_st *con)
499 {
500  if (con == NULL)
501  {
502  return NULL;
503  }
504 
505  return con->context;
506 }
507 
508 void drizzle_con_set_context(drizzle_con_st *con, void *context)
509 {
510  if (con == NULL)
511  {
512  return;
513  }
514 
515  con->context= context;
516 }
517 
518 void drizzle_con_set_context_free_fn(drizzle_con_st *con,
519  drizzle_con_context_free_fn *function)
520 {
521  if (con == NULL)
522  {
523  return;
524  }
525 
526  con->context_free_fn= function;
527 }
528 
529 uint8_t drizzle_con_protocol_version(const drizzle_con_st *con)
530 {
531  if (con == NULL)
532  {
533  return 0;
534  }
535 
536  return con->protocol_version;
537 }
538 
539 const char *drizzle_con_server_version(const drizzle_con_st *con)
540 {
541  if (con == NULL)
542  {
543  return NULL;
544  }
545 
546  return con->server_version;
547 }
548 
549 uint32_t drizzle_con_server_version_number(const drizzle_con_st *con)
550 {
551  if (con)
552  {
553  const char *current= con->server_version;
554  char *end;
555 
556  uint32_t major= (uint32_t)strtoul(current, &end, 10);
557  current= end +1;
558  uint32_t minor= (uint32_t)strtoul(current, &end, 10);
559  current= end +1;
560  uint32_t version= (uint32_t)strtoul(current, &end, 10);
561 
562  return (major * 10000) +(minor * 100) +version;
563  }
564 
565  return 0;
566 }
567 
568 uint32_t drizzle_con_thread_id(const drizzle_con_st *con)
569 {
570  if (con == NULL)
571  {
572  return 0;
573  }
574 
575  return con->thread_id;
576 }
577 
578 const uint8_t *drizzle_con_scramble(const drizzle_con_st *con)
579 {
580  if (con == NULL)
581  {
582  return NULL;
583  }
584 
585  return con->scramble;
586 }
587 
588 drizzle_capabilities_t drizzle_con_capabilities(const drizzle_con_st *con)
589 {
590  if (con == NULL)
591  {
592  return drizzle_capabilities_t();
593  }
594 
595  return drizzle_capabilities_t(con->capabilities);
596 }
597 
598 drizzle_charset_t drizzle_con_charset(const drizzle_con_st *con)
599 {
600  if (con == NULL)
601  {
602  return drizzle_charset_t();
603  }
604 
605  return con->charset;
606 }
607 
608 drizzle_con_status_t drizzle_con_status(const drizzle_con_st *con)
609 {
610  if (con == NULL)
611  {
612  return drizzle_con_status_t();
613  }
614 
615  return con->status;
616 }
617 
618 uint32_t drizzle_con_max_packet_size(const drizzle_con_st *con)
619 {
620  if (con == NULL)
621  {
622  return 0;
623  }
624 
625  return con->max_packet_size;
626 }
627 
628 /*
629  * Client Definitions
630  */
631 
632 drizzle_return_t drizzle_con_connect(drizzle_con_st *con)
633 {
634  if (con == NULL)
635  {
636  return DRIZZLE_RETURN_INVALID_ARGUMENT;
637  }
638 
639  if (con->options & DRIZZLE_CON_READY)
640  {
641  return DRIZZLE_RETURN_OK;
642  }
643 
644  if (drizzle_state_none(con))
645  {
646  if (!(con->options & DRIZZLE_CON_RAW_PACKET))
647  {
648  drizzle_state_push(con, drizzle_state_handshake_server_read);
649  drizzle_state_push(con, drizzle_state_packet_read);
650  }
651 
652  drizzle_state_push(con, drizzle_state_connect);
653  drizzle_state_push(con, drizzle_state_addrinfo);
654  }
655 
656  return drizzle_state_loop(con);
657 }
658 
659 drizzle_result_st *drizzle_con_quit(drizzle_con_st *con,
660  drizzle_result_st *result,
661  drizzle_return_t *ret_ptr)
662 {
663  return drizzle_con_command_write(con, result, DRIZZLE_COMMAND_QUIT, NULL, 0,
664  0, ret_ptr);
665 }
666 
667 drizzle_result_st *drizzle_quit(drizzle_con_st *con,
668  drizzle_result_st *result,
669  drizzle_return_t *ret_ptr)
670 {
671  return drizzle_con_quit(con, result, ret_ptr);
672 }
673 
674 drizzle_result_st *drizzle_con_select_db(drizzle_con_st *con,
675  drizzle_result_st *result,
676  const char *db,
677  drizzle_return_t *ret_ptr)
678 {
679  drizzle_con_set_db(con, db);
680  return drizzle_con_command_write(con, result, DRIZZLE_COMMAND_INIT_DB,
681  db, strlen(db), strlen(db), ret_ptr);
682 }
683 
684 drizzle_result_st *drizzle_select_db(drizzle_con_st *con,
685  drizzle_result_st *result,
686  const char *db,
687  drizzle_return_t *ret_ptr)
688 {
689  return drizzle_con_select_db(con, result, db, ret_ptr);
690 }
691 
692 drizzle_result_st *drizzle_con_shutdown(drizzle_con_st *con,
693  drizzle_result_st *result,
694  drizzle_return_t *ret_ptr)
695 {
696  drizzle_return_t unused;
697  if (ret_ptr == NULL)
698  {
699  ret_ptr= &unused;
700  }
701 
702  if (con and con->options & DRIZZLE_CON_MYSQL)
703  {
704  return drizzle_con_command_write(con, result, DRIZZLE_COMMAND_SHUTDOWN,
705  "0", 1, 1, ret_ptr);
706  }
707 
708  return drizzle_con_command_write(con, result, DRIZZLE_COMMAND_SHUTDOWN, NULL,
709  0, 0, ret_ptr);
710 }
711 
712 drizzle_result_st *drizzle_shutdown(drizzle_con_st *con,
713  drizzle_result_st *result, uint32_t, // level is unused
714  drizzle_return_t *ret_ptr)
715 {
716  return drizzle_con_shutdown(con, result, ret_ptr);
717 }
718 
719 drizzle_result_st *drizzle_kill(drizzle_con_st *con,
720  drizzle_result_st *result,
721  uint32_t query_id,
722  drizzle_return_t *ret_ptr)
723 {
724  drizzle_return_t unused;
725  if (ret_ptr == NULL)
726  {
727  ret_ptr= &unused;
728  }
729 
730  uint32_t sent= htonl(query_id);
731  return drizzle_con_command_write(con, result, DRIZZLE_COMMAND_PROCESS_KILL,
732  &sent, sizeof(uint32_t), sizeof(uint32_t), ret_ptr);
733 }
734 
735 drizzle_result_st *drizzle_con_ping(drizzle_con_st *con,
736  drizzle_result_st *result,
737  drizzle_return_t *ret_ptr)
738 {
739  return drizzle_con_command_write(con, result, DRIZZLE_COMMAND_PING, NULL, 0,
740  0, ret_ptr);
741 }
742 
743 drizzle_result_st *drizzle_ping(drizzle_con_st *con,
744  drizzle_result_st *result,
745  drizzle_return_t *ret_ptr)
746 {
747  return drizzle_con_ping(con, result, ret_ptr);
748 }
749 
750 drizzle_result_st *drizzle_con_command_write(drizzle_con_st *con,
751  drizzle_result_st *result,
752  drizzle_command_t command,
753  const void *data, size_t size,
754  size_t total,
755  drizzle_return_t *ret_ptr)
756 {
757  drizzle_return_t unused;
758  if (ret_ptr == NULL)
759  {
760  ret_ptr= &unused;
761  }
762 
763  if (con == NULL)
764  {
765  *ret_ptr= DRIZZLE_RETURN_INVALID_ARGUMENT;
766  return NULL;
767  }
768 
769  drizzle_result_st *old_result;
770 
771  if (!(con->options & DRIZZLE_CON_READY))
772  {
773  if (con->options & DRIZZLE_CON_RAW_PACKET)
774  {
775  drizzle_set_error(con->drizzle, "drizzle_command_write",
776  "connection not ready");
777  *ret_ptr= DRIZZLE_RETURN_NOT_READY;
778  return result;
779  }
780 
781  *ret_ptr= drizzle_con_connect(con);
782  if (*ret_ptr != DRIZZLE_RETURN_OK)
783  {
784  return result;
785  }
786  }
787 
788  if (drizzle_state_none(con))
789  {
790  if (con->options & (DRIZZLE_CON_RAW_PACKET | DRIZZLE_CON_NO_RESULT_READ))
791  {
792  con->result= NULL;
793  }
794  else
795  {
796  for (old_result= con->result_list; old_result != NULL; old_result= old_result->next)
797  {
798  if (result == old_result)
799  {
800  drizzle_set_error(con->drizzle, "drizzle_command_write", "result struct already in use");
801  *ret_ptr= DRIZZLE_RETURN_INTERNAL_ERROR;
802  return result;
803  }
804  }
805 
806  con->result= drizzle_result_create(con, result);
807  if (con->result == NULL)
808  {
809  *ret_ptr= DRIZZLE_RETURN_MEMORY;
810  return NULL;
811  }
812  }
813 
814  con->command= command;
815  con->command_data= (uint8_t *)data;
816  con->command_size= size;
817  con->command_offset= 0;
818  con->command_total= total;
819 
820  drizzle_state_push(con, drizzle_state_command_write);
821  }
822  else if (con->command_data == NULL)
823  {
824  con->command_data= (uint8_t *)data;
825  con->command_size= size;
826  }
827 
828  *ret_ptr= drizzle_state_loop(con);
829  if (*ret_ptr == DRIZZLE_RETURN_PAUSE)
830  {
831  *ret_ptr= DRIZZLE_RETURN_OK;
832  }
833  else if (*ret_ptr != DRIZZLE_RETURN_OK &&
834  *ret_ptr != DRIZZLE_RETURN_IO_WAIT &&
835  *ret_ptr != DRIZZLE_RETURN_ERROR_CODE)
836  {
837  drizzle_result_free(con->result);
838  con->result= result;
839  }
840 
841  return con->result;
842 }
843 
844 /*
845  * Server Definitions
846  */
847 
848 drizzle_return_t drizzle_con_listen(drizzle_con_st *con)
849 {
850  if (con == NULL)
851  {
852  return DRIZZLE_RETURN_INVALID_ARGUMENT;
853  }
854 
855  if (con->options & DRIZZLE_CON_READY)
856  {
857  return DRIZZLE_RETURN_OK;
858  }
859 
860  if (drizzle_state_none(con))
861  {
862  drizzle_state_push(con, drizzle_state_listen);
863  drizzle_state_push(con, drizzle_state_addrinfo);
864  }
865 
866  return drizzle_state_loop(con);
867 }
868 
869 int drizzle_con_backlog(const drizzle_con_st *con)
870 {
871  if (con == NULL)
872  {
873  return 0;
874  }
875 
876  return con->backlog;
877 }
878 
879 void drizzle_con_set_backlog(drizzle_con_st *con, int backlog)
880 {
881  if (con == NULL)
882  {
883  return;
884  }
885 
886  con->backlog= backlog;
887 }
888 
889 void drizzle_con_set_protocol_version(drizzle_con_st *con,
890  uint8_t protocol_version)
891 {
892  if (con == NULL)
893  {
894  return;
895  }
896 
897  con->protocol_version= protocol_version;
898 }
899 
900 void drizzle_con_set_server_version(drizzle_con_st *con,
901  const char *server_version)
902 {
903  if (con == NULL)
904  {
905  return;
906  }
907 
908  if (server_version == NULL)
909  {
910  con->server_version[0]= 0;
911  }
912  else
913  {
914  strncpy(con->server_version, server_version,
915  DRIZZLE_MAX_SERVER_VERSION_SIZE);
916  con->server_version[DRIZZLE_MAX_SERVER_VERSION_SIZE - 1]= 0;
917  }
918 }
919 
920 void drizzle_con_set_thread_id(drizzle_con_st *con, uint32_t thread_id)
921 {
922  if (con == NULL)
923  {
924  return;
925  }
926 
927  con->thread_id= thread_id;
928 }
929 
930 void drizzle_con_set_scramble(drizzle_con_st *con, const uint8_t *scramble)
931 {
932  if (con == NULL)
933  {
934  return;
935  }
936 
937  if (scramble == NULL)
938  {
939  con->scramble= NULL;
940  }
941  else
942  {
943  con->scramble= con->scramble_buffer;
944  memcpy(con->scramble, scramble, DRIZZLE_MAX_SCRAMBLE_SIZE);
945  }
946 }
947 
948 void drizzle_con_set_capabilities(drizzle_con_st *con,
949  drizzle_capabilities_t capabilities)
950 {
951  if (con == NULL)
952  {
953  return;
954  }
955 
956  con->capabilities= capabilities;
957 }
958 
959 void drizzle_con_set_charset(drizzle_con_st *con, drizzle_charset_t charset)
960 {
961  if (con == NULL)
962  {
963  return;
964  }
965 
966  con->charset= charset;
967 }
968 
969 void drizzle_con_set_status(drizzle_con_st *con, drizzle_con_status_t status)
970 {
971  if (con == NULL)
972  {
973  return;
974  }
975 
976  con->status= status;
977 }
978 
979 void drizzle_con_set_max_packet_size(drizzle_con_st *con,
980  uint32_t max_packet_size)
981 {
982  if (con == NULL)
983  {
984  return;
985  }
986 
987  con->max_packet_size= max_packet_size;
988 }
989 
990 void drizzle_con_copy_handshake(drizzle_con_st *con, drizzle_con_st *from)
991 {
992  drizzle_con_set_auth(con, from->user, NULL);
993  drizzle_con_set_scramble(con, from->scramble);
994  drizzle_con_set_db(con, from->db);
995  drizzle_con_set_protocol_version(con, from->protocol_version);
996  drizzle_con_set_server_version(con, from->server_version);
997  drizzle_con_set_thread_id(con, from->thread_id);
998  drizzle_con_set_scramble(con, from->scramble);
999  drizzle_con_set_capabilities(con, drizzle_capabilities_t(from->capabilities));
1000  drizzle_con_set_charset(con, from->charset);
1001  drizzle_con_set_status(con, from->status);
1002  drizzle_con_set_max_packet_size(con, from->max_packet_size);
1003 }
1004 
1005 void *drizzle_con_command_read(drizzle_con_st *con,
1006  drizzle_command_t *command, size_t *offset,
1007  size_t *size, size_t *total,
1008  drizzle_return_t *ret_ptr)
1009 {
1010  drizzle_return_t unused_ret;
1011  if (ret_ptr == NULL)
1012  {
1013  ret_ptr= &unused_ret;
1014  }
1015 
1016  if (con == NULL)
1017  {
1018  *ret_ptr= DRIZZLE_RETURN_INVALID_ARGUMENT;
1019  return NULL;
1020  }
1021 
1022  if (drizzle_state_none(con))
1023  {
1024  con->packet_number= 0;
1025  con->command_offset= 0;
1026  con->command_total= 0;
1027 
1028  drizzle_state_push(con, drizzle_state_command_read);
1029  drizzle_state_push(con, drizzle_state_packet_read);
1030  }
1031 
1032  if (offset)
1033  {
1034  *offset= con->command_offset;
1035  }
1036 
1037  *ret_ptr= drizzle_state_loop(con);
1038  if (*ret_ptr == DRIZZLE_RETURN_PAUSE)
1039  {
1040  *ret_ptr= DRIZZLE_RETURN_OK;
1041  }
1042 
1043  if (command)
1044  {
1045  *command= con->command;
1046  }
1047 
1048  if (size)
1049  {
1050  *size= con->command_size;
1051  }
1052 
1053  if (total)
1054  {
1055  *total= con->command_total;
1056  }
1057 
1058  return con->command_data;
1059 }
1060 
1061 void *drizzle_con_command_buffer(drizzle_con_st *con,
1062  drizzle_command_t *command, size_t *total,
1063  drizzle_return_t *ret_ptr)
1064 {
1065  size_t offset= 0;
1066  size_t size= 0;
1067 
1068  drizzle_return_t unused_ret;
1069  if (ret_ptr == NULL)
1070  {
1071  ret_ptr= &unused_ret;
1072  }
1073 
1074  size_t unused_total;
1075  if (total == NULL)
1076  {
1077  total= &unused_total;
1078  }
1079 
1080  if (con == NULL)
1081  {
1082  *ret_ptr= DRIZZLE_RETURN_INVALID_ARGUMENT;
1083  return NULL;
1084  }
1085 
1086  char *command_data= (char *)drizzle_con_command_read(con, command, &offset, &size, total, ret_ptr);
1087  if (*ret_ptr != DRIZZLE_RETURN_OK)
1088  {
1089  return NULL;
1090  }
1091 
1092  if (command_data == NULL)
1093  {
1094  *total= 0;
1095  return NULL;
1096  }
1097 
1098  if (con->command_buffer == NULL)
1099  {
1100  con->command_buffer= (uint8_t*)realloc(NULL, (*total) +1);
1101  if (con->command_buffer == NULL)
1102  {
1103  drizzle_set_error(con->drizzle, __func__, "Failed to allocate.");
1104  *ret_ptr= DRIZZLE_RETURN_MEMORY;
1105  return NULL;
1106  }
1107  }
1108 
1109  memcpy(con->command_buffer + offset, command_data, size);
1110 
1111  while ((offset + size) != (*total))
1112  {
1113  command_data= (char *)drizzle_con_command_read(con, command, &offset, &size, total, ret_ptr);
1114  if (*ret_ptr != DRIZZLE_RETURN_OK)
1115  {
1116  return NULL;
1117  }
1118 
1119  memcpy(con->command_buffer + offset, command_data, size);
1120  }
1121 
1122  command_data= (char *)con->command_buffer;
1123  con->command_buffer= NULL;
1124  command_data[*total]= 0;
1125 
1126  return command_data;
1127 }
1128 
1129 /*
1130  * Local Definitions
1131  */
1132 
1133 void drizzle_con_reset_addrinfo(drizzle_con_st *con)
1134 {
1135  if (con == NULL)
1136  {
1137  return;
1138  }
1139 
1140  switch (con->socket_type)
1141  {
1142  case DRIZZLE_CON_SOCKET_TCP:
1143  if (con->socket.tcp.addrinfo != NULL)
1144  {
1145  freeaddrinfo(con->socket.tcp.addrinfo);
1146  con->socket.tcp.addrinfo= NULL;
1147  }
1148  break;
1149 
1150  case DRIZZLE_CON_SOCKET_UDS:
1151  con->socket.uds.path_buffer[0]= 0;
1152  break;
1153 
1154  default:
1155  break;
1156  }
1157 
1158  con->addrinfo_next= NULL;
1159 }
1160 
1161 /*
1162  * State Definitions
1163  */
1164 
1165 drizzle_return_t drizzle_state_addrinfo(drizzle_con_st *con)
1166 {
1167  drizzle_con_tcp_st *tcp;
1168  const char *host;
1169  char port[NI_MAXSERV];
1170  struct addrinfo ai;
1171  int ret;
1172 
1173  if (con == NULL)
1174  {
1175  return DRIZZLE_RETURN_INVALID_ARGUMENT;
1176  }
1177 
1178  drizzle_log_debug(con->drizzle, __func__);
1179 
1180  switch (con->socket_type)
1181  {
1182  case DRIZZLE_CON_SOCKET_TCP:
1183  tcp= &(con->socket.tcp);
1184 
1185  if (tcp->addrinfo != NULL)
1186  {
1187  freeaddrinfo(tcp->addrinfo);
1188  tcp->addrinfo= NULL;
1189  }
1190 
1191  if (tcp->port != 0)
1192  {
1193  snprintf(port, NI_MAXSERV, "%u", tcp->port);
1194  }
1195  else if (con->options & DRIZZLE_CON_MYSQL)
1196  {
1197  snprintf(port, NI_MAXSERV, "%u", DRIZZLE_DEFAULT_TCP_PORT_MYSQL);
1198  }
1199  else
1200  {
1201  snprintf(port, NI_MAXSERV, "%u", DRIZZLE_DEFAULT_TCP_PORT);
1202  }
1203  port[NI_MAXSERV-1]= 0;
1204 
1205  memset(&ai, 0, sizeof(struct addrinfo));
1206  ai.ai_socktype= SOCK_STREAM;
1207  ai.ai_protocol= IPPROTO_TCP;
1208  ai.ai_flags = AI_PASSIVE;
1209  ai.ai_family = AF_UNSPEC;
1210 
1211  if (con->options & DRIZZLE_CON_LISTEN)
1212  {
1213  host= tcp->host;
1214  }
1215  else
1216  {
1217  if (tcp->host == NULL)
1218  {
1219  host= DRIZZLE_DEFAULT_TCP_HOST;
1220  }
1221  else
1222  {
1223  host= tcp->host;
1224  }
1225  }
1226 
1227  ret= getaddrinfo(host, port, &ai, &(tcp->addrinfo));
1228  if (ret != 0)
1229  {
1230  drizzle_set_error(con->drizzle, "drizzle_state_addrinfo", "getaddrinfo:%s", gai_strerror(ret));
1231  return DRIZZLE_RETURN_GETADDRINFO;
1232  }
1233 
1234  con->addrinfo_next= tcp->addrinfo;
1235 
1236  break;
1237 
1238  case DRIZZLE_CON_SOCKET_UDS:
1239  break;
1240 
1241  default:
1242  break;
1243  }
1244 
1245  drizzle_state_pop(con);
1246  return DRIZZLE_RETURN_OK;
1247 }
1248 
1249 drizzle_return_t drizzle_state_connect(drizzle_con_st *con)
1250 {
1251  int ret;
1252  drizzle_return_t dret;
1253 
1254  if (con == NULL)
1255  {
1256  return DRIZZLE_RETURN_INVALID_ARGUMENT;
1257  }
1258 
1259  drizzle_log_debug(con->drizzle, "drizzle_state_connect");
1260 
1261  if (con->fd != -1)
1262  {
1263  (void)closesocket(con->fd);
1264  con->fd= -1;
1265  }
1266 
1267  if (con->socket_type == DRIZZLE_CON_SOCKET_UDS)
1268  {
1269 #ifndef WIN32
1270  if ((con->fd= socket(AF_UNIX, SOCK_STREAM, 0)) < 0)
1271  {
1272  con->drizzle->last_errno= errno;
1273  return DRIZZLE_RETURN_COULD_NOT_CONNECT;
1274  }
1275 
1276  struct sockaddr_un servAddr;
1277 
1278  memset(&servAddr, 0, sizeof (struct sockaddr_un));
1279  servAddr.sun_family= AF_UNIX;
1280  strncpy(servAddr.sun_path, con->socket.uds.path_buffer, sizeof(servAddr.sun_path)); /* Copy filename */
1281 
1282  do {
1283  if (connect(con->fd, (struct sockaddr *)&servAddr, sizeof(servAddr)) < 0)
1284  {
1285  switch (errno)
1286  {
1287  case EINPROGRESS:
1288  case EALREADY:
1289  case EINTR:
1290  continue;
1291 
1292  case EISCONN: /* We were spinning waiting on connect */
1293  {
1294  break;
1295  }
1296 
1297  default:
1298  con->drizzle->last_errno= errno;
1299  return DRIZZLE_RETURN_COULD_NOT_CONNECT;
1300  }
1301  }
1302  } while (0);
1303 
1304  return DRIZZLE_RETURN_OK;
1305 #else
1306  return DRIZZLE_RETURN_COULD_NOT_CONNECT;
1307 #endif
1308  }
1309  else
1310  {
1311  if (con->addrinfo_next == NULL)
1312  {
1313  drizzle_set_error(con->drizzle, __func__, "could not connect");
1314  drizzle_state_reset(con);
1315  return DRIZZLE_RETURN_COULD_NOT_CONNECT;
1316  }
1317 
1318  con->fd= socket(con->addrinfo_next->ai_family,
1319  con->addrinfo_next->ai_socktype,
1320  con->addrinfo_next->ai_protocol);
1321  if (con->fd == -1)
1322  {
1323  drizzle_set_error(con->drizzle, __func__, "socket:%s", strerror(errno));
1324  con->drizzle->last_errno= errno;
1325  return DRIZZLE_RETURN_COULD_NOT_CONNECT;
1326  }
1327 
1328  dret= _con_setsockopt(con);
1329  if (dret != DRIZZLE_RETURN_OK)
1330  {
1331  con->drizzle->last_errno= errno;
1332  return DRIZZLE_RETURN_COULD_NOT_CONNECT;
1333  }
1334 
1335  while (1)
1336  {
1337  ret= connect(con->fd, con->addrinfo_next->ai_addr,
1338  con->addrinfo_next->ai_addrlen);
1339 
1340 #ifdef _WIN32
1341  errno = WSAGetLastError();
1342  switch(errno) {
1343  case WSAEINVAL:
1344  case WSAEALREADY:
1345  case WSAEWOULDBLOCK:
1346  errno= EINPROGRESS;
1347  break;
1348  case WSAECONNREFUSED:
1349  errno= ECONNREFUSED;
1350  break;
1351  case WSAENETUNREACH:
1352  errno= ENETUNREACH;
1353  break;
1354  case WSAETIMEDOUT:
1355  errno= ETIMEDOUT;
1356  break;
1357  case WSAECONNRESET:
1358  errno= ECONNRESET;
1359  break;
1360  case WSAEADDRINUSE:
1361  errno= EADDRINUSE;
1362  break;
1363  case WSAEOPNOTSUPP:
1364  errno= EOPNOTSUPP;
1365  break;
1366  case WSAENOPROTOOPT:
1367  errno= ENOPROTOOPT;
1368  break;
1369  default:
1370  break;
1371  }
1372 #endif /* _WIN32 */
1373 
1374  drizzle_log_crazy(con->drizzle, "connect return=%d errno=%s", ret, strerror(errno));
1375 
1376  if (ret == 0)
1377  {
1378  con->addrinfo_next= NULL;
1379  break;
1380  }
1381 
1382  if (errno == EAGAIN || errno == EINTR)
1383  {
1384  continue;
1385  }
1386 
1387  if (errno == EINPROGRESS)
1388  {
1389  if (connect_poll(con))
1390  {
1391  drizzle_state_pop(con);
1392  return DRIZZLE_RETURN_OK;
1393  }
1394  }
1395  else if (errno == ECONNREFUSED || errno == ENETUNREACH || errno == ETIMEDOUT)
1396  {
1397  con->addrinfo_next= con->addrinfo_next->ai_next;
1398  return DRIZZLE_RETURN_OK;
1399  }
1400 
1401  drizzle_set_error(con->drizzle, __func__, "connect:%s", strerror(errno));
1402  con->drizzle->last_errno= errno;
1403  return DRIZZLE_RETURN_COULD_NOT_CONNECT;
1404  }
1405 
1406  drizzle_state_pop(con);
1407  }
1408 
1409  return DRIZZLE_RETURN_OK;
1410 }
1411 
1412 drizzle_return_t drizzle_state_connecting(drizzle_con_st *con)
1413 {
1414  drizzle_return_t ret;
1415 
1416  if (con == NULL)
1417  {
1418  return DRIZZLE_RETURN_INVALID_ARGUMENT;
1419  }
1420 
1421  drizzle_log_debug(con->drizzle, "drizzle_state_connecting");
1422 
1423  while (1)
1424  {
1425  int error= 0;
1426  if (con->revents & POLLOUT)
1427  {
1428  drizzle_state_pop(con);
1429  socklen_t error_length= sizeof(error);
1430  int getsockopt_error;
1431  if ((getsockopt_error= getsockopt(con->fd, SOL_SOCKET, SO_ERROR, (void*)&error, &error_length)) < 1)
1432  {
1433  drizzle_set_error(con->drizzle, __func__, strerror(getsockopt_error));
1434  return DRIZZLE_RETURN_COULD_NOT_CONNECT;
1435  }
1436 
1437  if (error == 0)
1438  {
1439  drizzle_state_pop(con);
1440  return DRIZZLE_RETURN_OK;
1441  }
1442  }
1443  else if (con->revents & (POLLERR | POLLHUP | POLLNVAL))
1444  {
1445  error= 1;
1446  }
1447 
1448  if (error)
1449  {
1450  con->revents= 0;
1451  drizzle_state_pop(con);
1452  drizzle_state_push(con, drizzle_state_connect);
1453  con->addrinfo_next= con->addrinfo_next->ai_next;
1454  return DRIZZLE_RETURN_OK;
1455  }
1456 
1457  ret= drizzle_con_set_events(con, POLLOUT);
1458  if (ret != DRIZZLE_RETURN_OK)
1459  {
1460  return ret;
1461  }
1462 
1463  if (con->drizzle->options & DRIZZLE_NON_BLOCKING)
1464  {
1465  return DRIZZLE_RETURN_IO_WAIT;
1466  }
1467 
1468  ret= drizzle_con_wait(con->drizzle);
1469  if (ret != DRIZZLE_RETURN_OK)
1470  {
1471  return ret;
1472  }
1473  }
1474 }
1475 
1476 drizzle_return_t drizzle_state_read(drizzle_con_st *con)
1477 {
1478  drizzle_return_t ret;
1479  ssize_t read_size;
1480 
1481  if (con == NULL)
1482  {
1483  return DRIZZLE_RETURN_INVALID_ARGUMENT;
1484  }
1485 
1486  drizzle_log_debug(con->drizzle, "drizzle_state_read");
1487 
1488  if (con->buffer_size == 0)
1489  con->buffer_ptr= con->buffer;
1490  else if ((con->buffer_ptr - con->buffer) > (DRIZZLE_MAX_BUFFER_SIZE / 2))
1491  {
1492  memmove(con->buffer, con->buffer_ptr, con->buffer_size);
1493  con->buffer_ptr= con->buffer;
1494  }
1495 
1496  if ((con->revents & POLLIN) == 0 &&
1497  (con->drizzle->options & DRIZZLE_NON_BLOCKING))
1498  {
1499  /* non-blocking mode: return IO_WAIT instead of attempting to read. This
1500  * avoids reading immediately after writing a command, which typically
1501  * returns EAGAIN. This improves performance. */
1502  ret= drizzle_con_set_events(con, POLLIN);
1503  if (ret != DRIZZLE_RETURN_OK)
1504  return ret;
1505  return DRIZZLE_RETURN_IO_WAIT;
1506  }
1507 
1508  while (1)
1509  {
1510  size_t available_buffer= (size_t)DRIZZLE_MAX_BUFFER_SIZE -
1511  ((size_t)(con->buffer_ptr - con->buffer) + con->buffer_size);
1512  read_size = recv(con->fd, (char *)con->buffer_ptr + con->buffer_size,
1513  available_buffer, 0);
1514 #ifdef _WIN32
1515  errno = WSAGetLastError();
1516  switch(errno) {
1517  case WSAENOTCONN:
1518  case WSAEWOULDBLOCK:
1519  errno= EAGAIN;
1520  break;
1521  case WSAEINVAL:
1522  case WSAEALREADY:
1523  errno= EINPROGRESS;
1524  break;
1525  case WSAECONNREFUSED:
1526  errno= ECONNREFUSED;
1527  break;
1528  case WSAENETUNREACH:
1529  errno= ENETUNREACH;
1530  break;
1531  case WSAETIMEDOUT:
1532  errno= ETIMEDOUT;
1533  break;
1534  case WSAECONNRESET:
1535  errno= ECONNRESET;
1536  break;
1537  case WSAEADDRINUSE:
1538  errno= EADDRINUSE;
1539  break;
1540  case WSAEOPNOTSUPP:
1541  errno= EOPNOTSUPP;
1542  break;
1543  case WSAENOPROTOOPT:
1544  errno= ENOPROTOOPT;
1545  break;
1546  default:
1547  break;
1548  }
1549 #endif /* _WIN32 */
1550  drizzle_log_crazy(con->drizzle, "read fd=%d return=%zd errno=%s", con->fd,
1551  read_size, strerror(errno));
1552 
1553  if (read_size == 0)
1554  {
1555  drizzle_set_error(con->drizzle, __func__,
1556  "%s:%d lost connection to server (EOF)", __FILE__, __LINE__);
1557  return DRIZZLE_RETURN_LOST_CONNECTION;
1558  }
1559  else if (read_size == -1)
1560  {
1561  if (errno == EAGAIN)
1562  {
1563  /* clear the read ready flag */
1564  con->revents&= ~POLLIN;
1565  ret= drizzle_con_set_events(con, POLLIN);
1566  if (ret != DRIZZLE_RETURN_OK)
1567  return ret;
1568 
1569  if (con->drizzle->options & DRIZZLE_NON_BLOCKING)
1570  return DRIZZLE_RETURN_IO_WAIT;
1571 
1572  ret= drizzle_con_wait(con->drizzle);
1573  if (ret != DRIZZLE_RETURN_OK)
1574  return ret;
1575 
1576  continue;
1577  }
1578  else if (errno == ECONNREFUSED)
1579  {
1580  con->revents= 0;
1581  drizzle_state_pop(con);
1582  drizzle_state_push(con, drizzle_state_connect);
1583  con->addrinfo_next= con->addrinfo_next->ai_next;
1584  return DRIZZLE_RETURN_OK;
1585  }
1586  else if (errno == EINTR)
1587  {
1588  continue;
1589  }
1590  else if (errno == EPIPE || errno == ECONNRESET)
1591  {
1592  drizzle_set_error(con->drizzle, __func__,
1593  "%s:%d lost connection to server (%s)",
1594  __FILE__, __LINE__, strerror(errno));
1595  return DRIZZLE_RETURN_LOST_CONNECTION;
1596  }
1597 
1598  drizzle_set_error(con->drizzle, __func__, "read:%s", strerror(errno));
1599  con->drizzle->last_errno= errno;
1600  return DRIZZLE_RETURN_ERRNO;
1601  }
1602 
1603  /* clear the "read ready" flag if we read all available data. */
1604  if ((size_t) read_size < available_buffer)
1605  {
1606  con->revents&= ~POLLIN;
1607  }
1608  con->buffer_size+= (size_t)read_size;
1609  break;
1610  }
1611 
1612  drizzle_state_pop(con);
1613 
1614  return DRIZZLE_RETURN_OK;
1615 }
1616 
1617 drizzle_return_t drizzle_state_write(drizzle_con_st *con)
1618 {
1619  drizzle_return_t ret;
1620  ssize_t write_size;
1621 
1622  if (con == NULL)
1623  {
1624  return DRIZZLE_RETURN_INVALID_ARGUMENT;
1625  }
1626 
1627  drizzle_log_debug(con->drizzle, "drizzle_state_write");
1628 
1629  while (con->buffer_size != 0)
1630  {
1631 
1632  write_size = send(con->fd,(char *) con->buffer_ptr, con->buffer_size, 0);
1633 
1634 #ifdef _WIN32
1635  errno = WSAGetLastError();
1636  switch(errno) {
1637  case WSAENOTCONN:
1638  case WSAEWOULDBLOCK:
1639  errno= EAGAIN;
1640  break;
1641  case WSAEINVAL:
1642  case WSAEALREADY:
1643  errno= EINPROGRESS;
1644  break;
1645  case WSAECONNREFUSED:
1646  errno= ECONNREFUSED;
1647  break;
1648  case WSAENETUNREACH:
1649  errno= ENETUNREACH;
1650  break;
1651  case WSAETIMEDOUT:
1652  errno= ETIMEDOUT;
1653  break;
1654  case WSAECONNRESET:
1655  errno= ECONNRESET;
1656  break;
1657  case WSAEADDRINUSE:
1658  errno= EADDRINUSE;
1659  break;
1660  case WSAEOPNOTSUPP:
1661  errno= EOPNOTSUPP;
1662  break;
1663  case WSAENOPROTOOPT:
1664  errno= ENOPROTOOPT;
1665  break;
1666  default:
1667  break;
1668  }
1669 #endif /* _WIN32 */
1670 
1671  drizzle_log_crazy(con->drizzle, "write fd=%d return=%zd errno=%s", con->fd,
1672  write_size, strerror(errno));
1673 
1674  if (write_size == 0)
1675  { }
1676  else if (write_size == -1)
1677  {
1678  if (errno == EAGAIN)
1679  {
1680  ret= drizzle_con_set_events(con, POLLOUT);
1681  if (ret != DRIZZLE_RETURN_OK)
1682  {
1683  return ret;
1684  }
1685 
1686  if (con->drizzle->options & DRIZZLE_NON_BLOCKING)
1687  {
1688  return DRIZZLE_RETURN_IO_WAIT;
1689  }
1690 
1691  ret= drizzle_con_wait(con->drizzle);
1692  if (ret != DRIZZLE_RETURN_OK)
1693  {
1694  return ret;
1695  }
1696 
1697  continue;
1698  }
1699  else if (errno == EINTR)
1700  {
1701  continue;
1702  }
1703  else if (errno == EPIPE || errno == ECONNRESET)
1704  {
1705  drizzle_set_error(con->drizzle, __func__, "%s:%d lost connection to server (%s)",
1706  __FILE__, __LINE__, strerror(errno));
1707  return DRIZZLE_RETURN_LOST_CONNECTION;
1708  }
1709 
1710  drizzle_set_error(con->drizzle, "drizzle_state_write", "write:%s", strerror(errno));
1711  con->drizzle->last_errno= errno;
1712  return DRIZZLE_RETURN_ERRNO;
1713  }
1714 
1715  con->buffer_ptr+= write_size;
1716  con->buffer_size-= (size_t)write_size;
1717  if (con->buffer_size == 0)
1718  break;
1719  }
1720 
1721  con->buffer_ptr= con->buffer;
1722 
1723  drizzle_state_pop(con);
1724 
1725  return DRIZZLE_RETURN_OK;
1726 }
1727 
1728 drizzle_return_t drizzle_state_listen(drizzle_con_st *con)
1729 {
1730  char host[NI_MAXHOST];
1731  char port[NI_MAXSERV];
1732  int fd;
1733  int opt;
1734  drizzle_con_st *new_con;
1735 
1736  if (con == NULL)
1737  {
1738  return DRIZZLE_RETURN_INVALID_ARGUMENT;
1739  }
1740 
1741  for (; con->addrinfo_next != NULL;
1742  con->addrinfo_next= con->addrinfo_next->ai_next)
1743  {
1744  int ret= getnameinfo(con->addrinfo_next->ai_addr,
1745  con->addrinfo_next->ai_addrlen, host, NI_MAXHOST, port,
1746  NI_MAXSERV, NI_NUMERICHOST | NI_NUMERICSERV);
1747  if (ret != 0)
1748  {
1749  drizzle_set_error(con->drizzle, __func__, "getnameinfo:%s", gai_strerror(ret));
1750  return DRIZZLE_RETURN_GETADDRINFO;
1751  }
1752 
1753  /* Call to socket() can fail for some getaddrinfo results, try another. */
1754  fd= socket(con->addrinfo_next->ai_family, con->addrinfo_next->ai_socktype,
1755  con->addrinfo_next->ai_protocol);
1756  if (fd == -1)
1757  {
1758  drizzle_log_info(con->drizzle, "could not listen on %s:%s", host, port);
1759  drizzle_set_error(con->drizzle, __func__, "socket:%s", strerror(errno));
1760  continue;
1761  }
1762 
1763  opt= 1;
1764 #ifdef _WIN32
1765  ret= setsockopt(fd, SOL_SOCKET, SO_REUSEADDR,(const char*) &opt, sizeof(opt));
1766 #else
1767  ret= setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt));
1768 #endif /* _WIN32 */
1769  if (ret == -1)
1770  {
1771  closesocket(fd);
1772  drizzle_set_error(con->drizzle, __func__, "setsockopt:%s", strerror(errno));
1773  return DRIZZLE_RETURN_COULD_NOT_CONNECT;
1774  }
1775 
1776  ret= bind(fd, con->addrinfo_next->ai_addr, con->addrinfo_next->ai_addrlen);
1777  if (ret == -1)
1778  {
1779  closesocket(fd);
1780  drizzle_set_error(con->drizzle, __func__, "bind:%s", strerror(errno));
1781  if (errno == EADDRINUSE)
1782  {
1783  if (con->fd == -1)
1784  {
1785  drizzle_log_info(con->drizzle, "could not listen on %s:%s", host,
1786  port);
1787  }
1788 
1789  continue;
1790  }
1791 
1792  return DRIZZLE_RETURN_ERRNO;
1793  }
1794 
1795  if (listen(fd, con->backlog) == -1)
1796  {
1797  closesocket(fd);
1798  drizzle_set_error(con->drizzle, __func__, "listen:%s", strerror(errno));
1799  return DRIZZLE_RETURN_COULD_NOT_CONNECT;
1800  }
1801 
1802  if (con->fd == -1)
1803  {
1804  con->fd= fd;
1805  new_con= con;
1806  }
1807  else
1808  {
1809  new_con= drizzle_con_clone(con->drizzle, NULL, con);
1810  if (new_con == NULL)
1811  {
1812  closesocket(fd);
1813  return DRIZZLE_RETURN_MEMORY;
1814  }
1815 
1816  new_con->fd= fd;
1817  }
1818 
1819  /* Wait for read events on the listening socket. */
1820  drizzle_return_t local_ret= drizzle_con_set_events(new_con, POLLIN);
1821  if (local_ret != DRIZZLE_RETURN_OK)
1822  {
1823  drizzle_con_free(new_con);
1824  return local_ret;
1825  }
1826 
1827  drizzle_log_info(con->drizzle, "listening on %s:%s", host, port);
1828  }
1829 
1830  /* Report last socket() error if we couldn't find an address to bind. */
1831  if (con->fd == -1)
1832  {
1833  return DRIZZLE_RETURN_COULD_NOT_CONNECT;
1834  }
1835 
1836  drizzle_state_pop(con);
1837 
1838  return DRIZZLE_RETURN_OK;
1839 }
1840 
1841 /*
1842  * Static Definitions
1843  */
1844 
1845 static drizzle_return_t _con_setsockopt(drizzle_con_st *con)
1846 {
1847  struct linger linger;
1848  struct timeval waittime;
1849 
1850  assert(con);
1851 
1852  int ret= 1;
1853 
1854 #ifdef _WIN32
1855  ret= setsockopt(con->fd, IPPROTO_TCP, TCP_NODELAY, (const char*)&ret, (socklen_t)sizeof(int));
1856 #else
1857  ret= setsockopt(con->fd, IPPROTO_TCP, TCP_NODELAY, &ret, (socklen_t)sizeof(int));
1858 #endif /* _WIN32 */
1859 
1860  if (ret == -1 && errno != EOPNOTSUPP)
1861  {
1862  drizzle_set_error(con->drizzle, __func__, "setsockopt:TCP_NODELAY:%s", strerror(errno));
1863  return DRIZZLE_RETURN_ERRNO;
1864  }
1865 
1866  linger.l_onoff= 1;
1867  linger.l_linger= DRIZZLE_DEFAULT_SOCKET_TIMEOUT;
1868 
1869 #ifdef _WIN32
1870  ret= setsockopt(con->fd, SOL_SOCKET, SO_LINGER, (const char*)&linger,
1871  (socklen_t)sizeof(struct linger));
1872 #else
1873  ret= setsockopt(con->fd, SOL_SOCKET, SO_LINGER, &linger,
1874  (socklen_t)sizeof(struct linger));
1875 #endif /* _WIN32 */
1876 
1877  if (ret == -1)
1878  {
1879  drizzle_set_error(con->drizzle, __func__, "setsockopt:SO_LINGER:%s", strerror(errno));
1880  return DRIZZLE_RETURN_ERRNO;
1881  }
1882 
1883  waittime.tv_sec= DRIZZLE_DEFAULT_SOCKET_TIMEOUT;
1884  waittime.tv_usec= 0;
1885 
1886 #ifdef _WIN32
1887  ret= setsockopt(con->fd, SOL_SOCKET, SO_SNDTIMEO, (const char*)&waittime,
1888  (socklen_t)sizeof(struct timeval));
1889 #else
1890  ret= setsockopt(con->fd, SOL_SOCKET, SO_SNDTIMEO, &waittime,
1891  (socklen_t)sizeof(struct timeval));
1892 #endif /* _WIN32 */
1893 
1894  if (ret == -1 && errno != ENOPROTOOPT)
1895  {
1896  drizzle_set_error(con->drizzle, __func__, "setsockopt:SO_SNDTIMEO:%s", strerror(errno));
1897  return DRIZZLE_RETURN_ERRNO;
1898  }
1899 
1900 #ifdef _WIN32
1901  ret= setsockopt(con->fd, SOL_SOCKET, SO_RCVTIMEO, (const char*)&waittime,
1902  (socklen_t)sizeof(struct timeval));
1903 #else
1904  ret= setsockopt(con->fd, SOL_SOCKET, SO_RCVTIMEO, &waittime,
1905  (socklen_t)sizeof(struct timeval));
1906 #endif /* _WIN32 */
1907 
1908  if (ret == -1 && errno != ENOPROTOOPT)
1909  {
1910  drizzle_set_error(con->drizzle, __func__,
1911  "setsockopt:SO_RCVTIMEO:%s", strerror(errno));
1912  return DRIZZLE_RETURN_ERRNO;
1913  }
1914 
1915  ret= DRIZZLE_DEFAULT_SOCKET_SEND_SIZE;
1916 #ifdef _WIN32
1917  ret= setsockopt(con->fd, SOL_SOCKET, SO_SNDBUF, (const char*)&ret, (socklen_t)sizeof(int));
1918 #else
1919  ret= setsockopt(con->fd, SOL_SOCKET, SO_SNDBUF, &ret, (socklen_t)sizeof(int));
1920 #endif /* _WIN32 */
1921  if (ret == -1)
1922  {
1923  drizzle_set_error(con->drizzle, __func__, "setsockopt:SO_SNDBUF:%s", strerror(errno));
1924  return DRIZZLE_RETURN_ERRNO;
1925  }
1926 
1927  ret= DRIZZLE_DEFAULT_SOCKET_RECV_SIZE;
1928 #ifdef _WIN32
1929  ret= setsockopt(con->fd, SOL_SOCKET, SO_RCVBUF, (const char*)&ret, (socklen_t)sizeof(int));
1930 #else
1931  ret= setsockopt(con->fd, SOL_SOCKET, SO_RCVBUF, &ret, (socklen_t)sizeof(int));
1932 #endif /* _WIN32 */
1933  if (ret == -1)
1934  {
1935  drizzle_set_error(con->drizzle, __func__, "setsockopt:SO_RCVBUF:%s", strerror(errno));
1936  return DRIZZLE_RETURN_ERRNO;
1937  }
1938 
1939 #if defined (_WIN32)
1940  {
1941  unsigned long asyncmode;
1942  asyncmode= 1;
1943  ioctlsocket(con->fd, FIONBIO, &asyncmode);
1944  }
1945 #else
1946  ret= fcntl(con->fd, F_GETFL, 0);
1947  if (ret == -1)
1948  {
1949  drizzle_set_error(con->drizzle, __func__, "fcntl:F_GETFL:%s", strerror(errno));
1950  return DRIZZLE_RETURN_ERRNO;
1951  }
1952 
1953  ret= fcntl(con->fd, F_SETFL, ret | O_NONBLOCK);
1954  if (ret == -1)
1955  {
1956  drizzle_set_error(con->drizzle, __func__, "fcntl:F_SETFL:%s", strerror(errno));
1957  return DRIZZLE_RETURN_ERRNO;
1958  }
1959 #endif
1960 
1961  return DRIZZLE_RETURN_OK;
1962 }