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  if (con->ssl)
1407  {
1408  SSL_set_fd(con->ssl, con->fd);
1409  }
1410 
1411  drizzle_state_pop(con);
1412  }
1413 
1414  return DRIZZLE_RETURN_OK;
1415 }
1416 
1417 drizzle_return_t drizzle_state_connecting(drizzle_con_st *con)
1418 {
1419  drizzle_return_t ret;
1420 
1421  if (con == NULL)
1422  {
1423  return DRIZZLE_RETURN_INVALID_ARGUMENT;
1424  }
1425 
1426  drizzle_log_debug(con->drizzle, "drizzle_state_connecting");
1427 
1428  while (1)
1429  {
1430  int error= 0;
1431  if (con->revents & POLLOUT)
1432  {
1433  drizzle_state_pop(con);
1434  socklen_t error_length= sizeof(error);
1435  int getsockopt_error;
1436  if ((getsockopt_error= getsockopt(con->fd, SOL_SOCKET, SO_ERROR, (void*)&error, &error_length)) < 1)
1437  {
1438  drizzle_set_error(con->drizzle, __func__, strerror(getsockopt_error));
1439  return DRIZZLE_RETURN_COULD_NOT_CONNECT;
1440  }
1441 
1442  if (error == 0)
1443  {
1444  drizzle_state_pop(con);
1445  return DRIZZLE_RETURN_OK;
1446  }
1447  }
1448  else if (con->revents & (POLLERR | POLLHUP | POLLNVAL))
1449  {
1450  error= 1;
1451  }
1452 
1453  if (error)
1454  {
1455  con->revents= 0;
1456  drizzle_state_pop(con);
1457  drizzle_state_push(con, drizzle_state_connect);
1458  con->addrinfo_next= con->addrinfo_next->ai_next;
1459  return DRIZZLE_RETURN_OK;
1460  }
1461 
1462  ret= drizzle_con_set_events(con, POLLOUT);
1463  if (ret != DRIZZLE_RETURN_OK)
1464  {
1465  return ret;
1466  }
1467 
1468  if (con->drizzle->options & DRIZZLE_NON_BLOCKING)
1469  {
1470  return DRIZZLE_RETURN_IO_WAIT;
1471  }
1472 
1473  ret= drizzle_con_wait(con->drizzle);
1474  if (ret != DRIZZLE_RETURN_OK)
1475  {
1476  return ret;
1477  }
1478  }
1479 }
1480 
1481 drizzle_return_t drizzle_state_read(drizzle_con_st *con)
1482 {
1483  drizzle_return_t ret;
1484  ssize_t read_size;
1485 
1486  if (con == NULL)
1487  {
1488  return DRIZZLE_RETURN_INVALID_ARGUMENT;
1489  }
1490 
1491  drizzle_log_debug(con->drizzle, "drizzle_state_read");
1492 
1493  if (con->buffer_size == 0)
1494  con->buffer_ptr= con->buffer;
1495  else if ((con->buffer_ptr - con->buffer) > (DRIZZLE_MAX_BUFFER_SIZE / 2))
1496  {
1497  memmove(con->buffer, con->buffer_ptr, con->buffer_size);
1498  con->buffer_ptr= con->buffer;
1499  }
1500 
1501  if ((con->revents & POLLIN) == 0 &&
1502  (con->drizzle->options & DRIZZLE_NON_BLOCKING))
1503  {
1504  /* non-blocking mode: return IO_WAIT instead of attempting to read. This
1505  * avoids reading immediately after writing a command, which typically
1506  * returns EAGAIN. This improves performance. */
1507  ret= drizzle_con_set_events(con, POLLIN);
1508  if (ret != DRIZZLE_RETURN_OK)
1509  return ret;
1510  return DRIZZLE_RETURN_IO_WAIT;
1511  }
1512 
1513  while (1)
1514  {
1515  size_t available_buffer= (size_t)DRIZZLE_MAX_BUFFER_SIZE -
1516  ((size_t)(con->buffer_ptr - con->buffer) + con->buffer_size);
1517 
1518  if (con->ssl_state == DRIZZLE_SSL_STATE_HANDSHAKE_COMPLETE)
1519  read_size= SSL_read(con->ssl, (char*)con->buffer_ptr + con->buffer_size, available_buffer);
1520  else
1521  read_size = recv(con->fd, (char *)con->buffer_ptr + con->buffer_size,
1522  available_buffer, 0);
1523 #ifdef _WIN32
1524  errno = WSAGetLastError();
1525  switch(errno) {
1526  case WSAENOTCONN:
1527  case WSAEWOULDBLOCK:
1528  errno= EAGAIN;
1529  break;
1530  case WSAEINVAL:
1531  case WSAEALREADY:
1532  errno= EINPROGRESS;
1533  break;
1534  case WSAECONNREFUSED:
1535  errno= ECONNREFUSED;
1536  break;
1537  case WSAENETUNREACH:
1538  errno= ENETUNREACH;
1539  break;
1540  case WSAETIMEDOUT:
1541  errno= ETIMEDOUT;
1542  break;
1543  case WSAECONNRESET:
1544  errno= ECONNRESET;
1545  break;
1546  case WSAEADDRINUSE:
1547  errno= EADDRINUSE;
1548  break;
1549  case WSAEOPNOTSUPP:
1550  errno= EOPNOTSUPP;
1551  break;
1552  case WSAENOPROTOOPT:
1553  errno= ENOPROTOOPT;
1554  break;
1555  default:
1556  break;
1557  }
1558 #endif /* _WIN32 */
1559  drizzle_log_crazy(con->drizzle, "read fd=%d return=%zd ssl= %d errno=%s",
1560  con->fd, read_size,
1561  (con->ssl_state == DRIZZLE_SSL_STATE_HANDSHAKE_COMPLETE) ? 1 : 0,
1562  strerror(errno));
1563 
1564  if (read_size == 0)
1565  {
1566  drizzle_set_error(con->drizzle, __func__,
1567  "%s:%d lost connection to server (EOF)", __FILE__, __LINE__);
1568  return DRIZZLE_RETURN_LOST_CONNECTION;
1569  }
1570  else if (read_size == -1)
1571  {
1572  if (errno == EAGAIN)
1573  {
1574  /* clear the read ready flag */
1575  con->revents&= ~POLLIN;
1576  ret= drizzle_con_set_events(con, POLLIN);
1577  if (ret != DRIZZLE_RETURN_OK)
1578  return ret;
1579 
1580  if (con->drizzle->options & DRIZZLE_NON_BLOCKING)
1581  return DRIZZLE_RETURN_IO_WAIT;
1582 
1583  ret= drizzle_con_wait(con->drizzle);
1584  if (ret != DRIZZLE_RETURN_OK)
1585  return ret;
1586 
1587  continue;
1588  }
1589  else if (errno == ECONNREFUSED)
1590  {
1591  con->revents= 0;
1592  drizzle_state_pop(con);
1593  drizzle_state_push(con, drizzle_state_connect);
1594  con->addrinfo_next= con->addrinfo_next->ai_next;
1595  return DRIZZLE_RETURN_OK;
1596  }
1597  else if (errno == EINTR)
1598  {
1599  continue;
1600  }
1601  else if (errno == EPIPE || errno == ECONNRESET)
1602  {
1603  drizzle_set_error(con->drizzle, __func__,
1604  "%s:%d lost connection to server (%s)",
1605  __FILE__, __LINE__, strerror(errno));
1606  return DRIZZLE_RETURN_LOST_CONNECTION;
1607  }
1608 
1609  drizzle_set_error(con->drizzle, __func__, "read:%s", strerror(errno));
1610  con->drizzle->last_errno= errno;
1611  return DRIZZLE_RETURN_ERRNO;
1612  }
1613 
1614  /* clear the "read ready" flag if we read all available data. */
1615  if ((size_t) read_size < available_buffer)
1616  {
1617  con->revents&= ~POLLIN;
1618  }
1619  con->buffer_size+= (size_t)read_size;
1620  break;
1621  }
1622 
1623  drizzle_state_pop(con);
1624 
1625  return DRIZZLE_RETURN_OK;
1626 }
1627 
1628 drizzle_return_t drizzle_state_write(drizzle_con_st *con)
1629 {
1630  drizzle_return_t ret;
1631  ssize_t write_size;
1632 
1633  if (con == NULL)
1634  {
1635  return DRIZZLE_RETURN_INVALID_ARGUMENT;
1636  }
1637 
1638  drizzle_log_debug(con->drizzle, "drizzle_state_write");
1639 
1640  while (con->buffer_size != 0)
1641  {
1642  if (con->ssl_state == DRIZZLE_SSL_STATE_HANDSHAKE_COMPLETE)
1643  write_size= SSL_write(con->ssl, con->buffer_ptr, con->buffer_size);
1644  else
1645  write_size = send(con->fd,(char *) con->buffer_ptr, con->buffer_size, 0);
1646 
1647 #ifdef _WIN32
1648  errno = WSAGetLastError();
1649  switch(errno) {
1650  case WSAENOTCONN:
1651  case WSAEWOULDBLOCK:
1652  errno= EAGAIN;
1653  break;
1654  case WSAEINVAL:
1655  case WSAEALREADY:
1656  errno= EINPROGRESS;
1657  break;
1658  case WSAECONNREFUSED:
1659  errno= ECONNREFUSED;
1660  break;
1661  case WSAENETUNREACH:
1662  errno= ENETUNREACH;
1663  break;
1664  case WSAETIMEDOUT:
1665  errno= ETIMEDOUT;
1666  break;
1667  case WSAECONNRESET:
1668  errno= ECONNRESET;
1669  break;
1670  case WSAEADDRINUSE:
1671  errno= EADDRINUSE;
1672  break;
1673  case WSAEOPNOTSUPP:
1674  errno= EOPNOTSUPP;
1675  break;
1676  case WSAENOPROTOOPT:
1677  errno= ENOPROTOOPT;
1678  break;
1679  default:
1680  break;
1681  }
1682 #endif /* _WIN32 */
1683 
1684  drizzle_log_crazy(con->drizzle, "write fd=%d return=%zd ssl=%d errno=%s",
1685  con->fd, write_size,
1686  (con->ssl_state == DRIZZLE_SSL_STATE_HANDSHAKE_COMPLETE) ? 1 : 0,
1687  strerror(errno));
1688 
1689  if (write_size == 0)
1690  { }
1691  else if (write_size == -1)
1692  {
1693  if (errno == EAGAIN)
1694  {
1695  ret= drizzle_con_set_events(con, POLLOUT);
1696  if (ret != DRIZZLE_RETURN_OK)
1697  {
1698  return ret;
1699  }
1700 
1701  if (con->drizzle->options & DRIZZLE_NON_BLOCKING)
1702  {
1703  return DRIZZLE_RETURN_IO_WAIT;
1704  }
1705 
1706  ret= drizzle_con_wait(con->drizzle);
1707  if (ret != DRIZZLE_RETURN_OK)
1708  {
1709  return ret;
1710  }
1711 
1712  continue;
1713  }
1714  else if (errno == EINTR)
1715  {
1716  continue;
1717  }
1718  else if (errno == EPIPE || errno == ECONNRESET)
1719  {
1720  drizzle_set_error(con->drizzle, __func__, "%s:%d lost connection to server (%s)",
1721  __FILE__, __LINE__, strerror(errno));
1722  return DRIZZLE_RETURN_LOST_CONNECTION;
1723  }
1724 
1725  drizzle_set_error(con->drizzle, "drizzle_state_write", "write:%s", strerror(errno));
1726  con->drizzle->last_errno= errno;
1727  return DRIZZLE_RETURN_ERRNO;
1728  }
1729 
1730  con->buffer_ptr+= write_size;
1731  con->buffer_size-= (size_t)write_size;
1732  if (con->buffer_size == 0)
1733  break;
1734  }
1735 
1736  con->buffer_ptr= con->buffer;
1737 
1738  drizzle_state_pop(con);
1739 
1740  return DRIZZLE_RETURN_OK;
1741 }
1742 
1743 drizzle_return_t drizzle_state_listen(drizzle_con_st *con)
1744 {
1745  char host[NI_MAXHOST];
1746  char port[NI_MAXSERV];
1747  int fd;
1748  int opt;
1749  drizzle_con_st *new_con;
1750 
1751  if (con == NULL)
1752  {
1753  return DRIZZLE_RETURN_INVALID_ARGUMENT;
1754  }
1755 
1756  for (; con->addrinfo_next != NULL;
1757  con->addrinfo_next= con->addrinfo_next->ai_next)
1758  {
1759  int ret= getnameinfo(con->addrinfo_next->ai_addr,
1760  con->addrinfo_next->ai_addrlen, host, NI_MAXHOST, port,
1761  NI_MAXSERV, NI_NUMERICHOST | NI_NUMERICSERV);
1762  if (ret != 0)
1763  {
1764  drizzle_set_error(con->drizzle, __func__, "getnameinfo:%s", gai_strerror(ret));
1765  return DRIZZLE_RETURN_GETADDRINFO;
1766  }
1767 
1768  /* Call to socket() can fail for some getaddrinfo results, try another. */
1769  fd= socket(con->addrinfo_next->ai_family, con->addrinfo_next->ai_socktype,
1770  con->addrinfo_next->ai_protocol);
1771  if (fd == -1)
1772  {
1773  drizzle_log_info(con->drizzle, "could not listen on %s:%s", host, port);
1774  drizzle_set_error(con->drizzle, __func__, "socket:%s", strerror(errno));
1775  continue;
1776  }
1777 
1778  opt= 1;
1779 #ifdef _WIN32
1780  ret= setsockopt(fd, SOL_SOCKET, SO_REUSEADDR,(const char*) &opt, sizeof(opt));
1781 #else
1782  ret= setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt));
1783 #endif /* _WIN32 */
1784  if (ret == -1)
1785  {
1786  closesocket(fd);
1787  drizzle_set_error(con->drizzle, __func__, "setsockopt:%s", strerror(errno));
1788  return DRIZZLE_RETURN_COULD_NOT_CONNECT;
1789  }
1790 
1791  ret= bind(fd, con->addrinfo_next->ai_addr, con->addrinfo_next->ai_addrlen);
1792  if (ret == -1)
1793  {
1794  closesocket(fd);
1795  drizzle_set_error(con->drizzle, __func__, "bind:%s", strerror(errno));
1796  if (errno == EADDRINUSE)
1797  {
1798  if (con->fd == -1)
1799  {
1800  drizzle_log_info(con->drizzle, "could not listen on %s:%s", host,
1801  port);
1802  }
1803 
1804  continue;
1805  }
1806 
1807  return DRIZZLE_RETURN_ERRNO;
1808  }
1809 
1810  if (listen(fd, con->backlog) == -1)
1811  {
1812  closesocket(fd);
1813  drizzle_set_error(con->drizzle, __func__, "listen:%s", strerror(errno));
1814  return DRIZZLE_RETURN_COULD_NOT_CONNECT;
1815  }
1816 
1817  if (con->fd == -1)
1818  {
1819  con->fd= fd;
1820  new_con= con;
1821  }
1822  else
1823  {
1824  new_con= drizzle_con_clone(con->drizzle, NULL, con);
1825  if (new_con == NULL)
1826  {
1827  closesocket(fd);
1828  return DRIZZLE_RETURN_MEMORY;
1829  }
1830 
1831  new_con->fd= fd;
1832  }
1833 
1834  /* Wait for read events on the listening socket. */
1835  drizzle_return_t local_ret= drizzle_con_set_events(new_con, POLLIN);
1836  if (local_ret != DRIZZLE_RETURN_OK)
1837  {
1838  drizzle_con_free(new_con);
1839  return local_ret;
1840  }
1841 
1842  drizzle_log_info(con->drizzle, "listening on %s:%s", host, port);
1843  }
1844 
1845  /* Report last socket() error if we couldn't find an address to bind. */
1846  if (con->fd == -1)
1847  {
1848  return DRIZZLE_RETURN_COULD_NOT_CONNECT;
1849  }
1850 
1851  drizzle_state_pop(con);
1852 
1853  return DRIZZLE_RETURN_OK;
1854 }
1855 
1856 /*
1857  * Static Definitions
1858  */
1859 
1860 static drizzle_return_t _con_setsockopt(drizzle_con_st *con)
1861 {
1862  struct linger linger;
1863  struct timeval waittime;
1864 
1865  assert(con);
1866 
1867  int ret= 1;
1868 
1869 #ifdef _WIN32
1870  ret= setsockopt(con->fd, IPPROTO_TCP, TCP_NODELAY, (const char*)&ret, (socklen_t)sizeof(int));
1871 #else
1872  ret= setsockopt(con->fd, IPPROTO_TCP, TCP_NODELAY, &ret, (socklen_t)sizeof(int));
1873 #endif /* _WIN32 */
1874 
1875  if (ret == -1 && errno != EOPNOTSUPP)
1876  {
1877  drizzle_set_error(con->drizzle, __func__, "setsockopt:TCP_NODELAY:%s", strerror(errno));
1878  return DRIZZLE_RETURN_ERRNO;
1879  }
1880 
1881  linger.l_onoff= 1;
1882  linger.l_linger= DRIZZLE_DEFAULT_SOCKET_TIMEOUT;
1883 
1884 #ifdef _WIN32
1885  ret= setsockopt(con->fd, SOL_SOCKET, SO_LINGER, (const char*)&linger,
1886  (socklen_t)sizeof(struct linger));
1887 #else
1888  ret= setsockopt(con->fd, SOL_SOCKET, SO_LINGER, &linger,
1889  (socklen_t)sizeof(struct linger));
1890 #endif /* _WIN32 */
1891 
1892  if (ret == -1)
1893  {
1894  drizzle_set_error(con->drizzle, __func__, "setsockopt:SO_LINGER:%s", strerror(errno));
1895  return DRIZZLE_RETURN_ERRNO;
1896  }
1897 
1898  waittime.tv_sec= DRIZZLE_DEFAULT_SOCKET_TIMEOUT;
1899  waittime.tv_usec= 0;
1900 
1901 #ifdef _WIN32
1902  ret= setsockopt(con->fd, SOL_SOCKET, SO_SNDTIMEO, (const char*)&waittime,
1903  (socklen_t)sizeof(struct timeval));
1904 #else
1905  ret= setsockopt(con->fd, SOL_SOCKET, SO_SNDTIMEO, &waittime,
1906  (socklen_t)sizeof(struct timeval));
1907 #endif /* _WIN32 */
1908 
1909  if (ret == -1 && errno != ENOPROTOOPT)
1910  {
1911  drizzle_set_error(con->drizzle, __func__, "setsockopt:SO_SNDTIMEO:%s", strerror(errno));
1912  return DRIZZLE_RETURN_ERRNO;
1913  }
1914 
1915 #ifdef _WIN32
1916  ret= setsockopt(con->fd, SOL_SOCKET, SO_RCVTIMEO, (const char*)&waittime,
1917  (socklen_t)sizeof(struct timeval));
1918 #else
1919  ret= setsockopt(con->fd, SOL_SOCKET, SO_RCVTIMEO, &waittime,
1920  (socklen_t)sizeof(struct timeval));
1921 #endif /* _WIN32 */
1922 
1923  if (ret == -1 && errno != ENOPROTOOPT)
1924  {
1925  drizzle_set_error(con->drizzle, __func__,
1926  "setsockopt:SO_RCVTIMEO:%s", strerror(errno));
1927  return DRIZZLE_RETURN_ERRNO;
1928  }
1929 
1930  ret= DRIZZLE_DEFAULT_SOCKET_SEND_SIZE;
1931 #ifdef _WIN32
1932  ret= setsockopt(con->fd, SOL_SOCKET, SO_SNDBUF, (const char*)&ret, (socklen_t)sizeof(int));
1933 #else
1934  ret= setsockopt(con->fd, SOL_SOCKET, SO_SNDBUF, &ret, (socklen_t)sizeof(int));
1935 #endif /* _WIN32 */
1936  if (ret == -1)
1937  {
1938  drizzle_set_error(con->drizzle, __func__, "setsockopt:SO_SNDBUF:%s", strerror(errno));
1939  return DRIZZLE_RETURN_ERRNO;
1940  }
1941 
1942  ret= DRIZZLE_DEFAULT_SOCKET_RECV_SIZE;
1943 #ifdef _WIN32
1944  ret= setsockopt(con->fd, SOL_SOCKET, SO_RCVBUF, (const char*)&ret, (socklen_t)sizeof(int));
1945 #else
1946  ret= setsockopt(con->fd, SOL_SOCKET, SO_RCVBUF, &ret, (socklen_t)sizeof(int));
1947 #endif /* _WIN32 */
1948  if (ret == -1)
1949  {
1950  drizzle_set_error(con->drizzle, __func__, "setsockopt:SO_RCVBUF:%s", strerror(errno));
1951  return DRIZZLE_RETURN_ERRNO;
1952  }
1953 
1954 #if defined (_WIN32)
1955  {
1956  unsigned long asyncmode;
1957  asyncmode= 1;
1958  ioctlsocket(con->fd, FIONBIO, &asyncmode);
1959  }
1960 #else
1961  if (!con->ssl)
1962  {
1963  ret= fcntl(con->fd, F_GETFL, 0);
1964  if (ret == -1)
1965  {
1966  drizzle_set_error(con->drizzle, __func__, "fcntl:F_GETFL:%s", strerror(errno));
1967  return DRIZZLE_RETURN_ERRNO;
1968  }
1969 
1970  ret= fcntl(con->fd, F_SETFL, ret | O_NONBLOCK);
1971  if (ret == -1)
1972  {
1973  drizzle_set_error(con->drizzle, __func__, "fcntl:F_SETFL:%s", strerror(errno));
1974  return DRIZZLE_RETURN_ERRNO;
1975  }
1976  }
1977 #endif
1978 
1979  return DRIZZLE_RETURN_OK;
1980 }