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