libdrizzle Developer Documentation

libdrizzle/conn.c
Go to the documentation of this file.
00001 /*
00002  * Drizzle Client & Protocol Library
00003  *
00004  * Copyright (C) 2008 Eric Day (eday@oddments.org)
00005  * All rights reserved.
00006  *
00007  * Use and distribution licensed under the BSD license.  See
00008  * the COPYING file in this directory for full text.
00009  */
00010 
00016 #include "common.h"
00017 
00031 static drizzle_return_t _con_setsockopt(drizzle_con_st *con);
00032 
00035 /*
00036  * Common Definitions
00037  */
00038 
00039 int drizzle_con_fd(const drizzle_con_st *con)
00040 {
00041   return con->fd;
00042 }
00043 
00044 drizzle_return_t drizzle_con_set_fd(drizzle_con_st *con, int fd)
00045 {
00046   drizzle_return_t ret;
00047 
00048   con->fd= fd;
00049 
00050   ret= _con_setsockopt(con);
00051   if (ret != DRIZZLE_RETURN_OK)
00052     con->drizzle->last_errno= errno;
00053 
00054   return ret;
00055 }
00056 
00057 void drizzle_con_close(drizzle_con_st *con)
00058 {
00059   if (con->fd == -1)
00060     return;
00061 
00062   (void)close(con->fd);
00063   con->fd= -1;
00064 
00065   con->options&= (drizzle_con_options_t)~DRIZZLE_CON_READY;
00066   con->packet_number= 0;
00067   con->buffer_ptr= con->buffer;
00068   con->buffer_size= 0;
00069   con->events= 0;
00070   con->revents= 0;
00071 
00072   drizzle_state_reset(con);
00073 }
00074 
00075 drizzle_return_t drizzle_con_set_events(drizzle_con_st *con, short events)
00076 {
00077   drizzle_return_t ret;
00078 
00079   if ((con->events | events) == con->events)
00080     return DRIZZLE_RETURN_OK;
00081 
00082   con->events|= events;
00083 
00084   if (con->drizzle->event_watch_fn != NULL)
00085   {
00086     ret= con->drizzle->event_watch_fn(con, con->events,
00087                                       con->drizzle->event_watch_context);
00088     if (ret != DRIZZLE_RETURN_OK)
00089     {
00090       drizzle_con_close(con);
00091       return ret;
00092     }
00093   }
00094 
00095   return DRIZZLE_RETURN_OK;
00096 }
00097 
00098 drizzle_return_t drizzle_con_set_revents(drizzle_con_st *con, short revents)
00099 {
00100   drizzle_return_t ret;
00101 
00102   if (revents != 0)
00103     con->options|= DRIZZLE_CON_IO_READY;
00104 
00105   con->revents= revents;
00106 
00107   /* Remove external POLLOUT watch if we didn't ask for it. Otherwise we spin
00108      forever until another POLLIN state change. This is much more efficient
00109      than removing POLLOUT on every state change since some external polling
00110      mechanisms need to use a system call to change flags (like Linux epoll). */
00111   if (revents & POLLOUT && !(con->events & POLLOUT) &&
00112       con->drizzle->event_watch_fn != NULL)
00113   {
00114     ret= con->drizzle->event_watch_fn(con, con->events,
00115                                       con->drizzle->event_watch_context);
00116     if (ret != DRIZZLE_RETURN_OK)
00117     {
00118       drizzle_con_close(con);
00119       return ret;
00120     }
00121   }
00122 
00123   con->events&= (short)~revents;
00124 
00125   return DRIZZLE_RETURN_OK;
00126 }
00127 
00128 drizzle_st *drizzle_con_drizzle(const drizzle_con_st *con)
00129 {
00130   return con->drizzle;
00131 }
00132 
00133 const char *drizzle_con_error(const drizzle_con_st *con)
00134 {
00135   return drizzle_error(con->drizzle);
00136 }
00137 
00138 int drizzle_con_errno(const drizzle_con_st *con)
00139 {
00140   return drizzle_errno(con->drizzle);
00141 }
00142 
00143 uint16_t drizzle_con_error_code(const drizzle_con_st *con)
00144 {
00145   return drizzle_error_code(con->drizzle);
00146 }
00147 
00148 const char *drizzle_con_sqlstate(const drizzle_con_st *con)
00149 {
00150   return drizzle_sqlstate(con->drizzle);
00151 }
00152 
00153 drizzle_con_options_t drizzle_con_options(const drizzle_con_st *con)
00154 {
00155   return con->options;
00156 }
00157 
00158 void drizzle_con_set_options(drizzle_con_st *con,
00159                              drizzle_con_options_t options)
00160 {
00161   con->options= options;
00162 }
00163 
00164 void drizzle_con_add_options(drizzle_con_st *con,
00165                              drizzle_con_options_t options)
00166 {
00167   con->options|= options;
00168 
00169   /* If asking for the experimental Drizzle protocol, clean the MySQL flag. */
00170   if (con->options & DRIZZLE_CON_EXPERIMENTAL)
00171     con->options&= (drizzle_con_options_t)~DRIZZLE_CON_MYSQL;
00172 }
00173 
00174 void drizzle_con_remove_options(drizzle_con_st *con,
00175                                 drizzle_con_options_t options)
00176 {
00177   con->options&= ~options;
00178 }
00179 
00180 const char *drizzle_con_host(const drizzle_con_st *con)
00181 {
00182   if (con->socket_type == DRIZZLE_CON_SOCKET_TCP)
00183   {
00184     if (con->socket.tcp.host == NULL && !(con->options & DRIZZLE_CON_LISTEN))
00185       return DRIZZLE_DEFAULT_TCP_HOST;
00186 
00187     return con->socket.tcp.host;
00188   }
00189 
00190   return NULL;
00191 }
00192 
00193 in_port_t drizzle_con_port(const drizzle_con_st *con)
00194 {
00195   if (con->socket_type == DRIZZLE_CON_SOCKET_TCP)
00196   {
00197     if (con->socket.tcp.port != 0)
00198       return con->socket.tcp.port;
00199 
00200     if (con->options & DRIZZLE_CON_MYSQL)
00201       return DRIZZLE_DEFAULT_TCP_PORT_MYSQL;
00202 
00203     return DRIZZLE_DEFAULT_TCP_PORT;
00204   }
00205 
00206   return 0;
00207 }
00208 
00209 void drizzle_con_set_tcp(drizzle_con_st *con, const char *host, in_port_t port)
00210 {
00211   drizzle_con_reset_addrinfo(con);
00212 
00213   con->socket_type= DRIZZLE_CON_SOCKET_TCP;
00214 
00215   if (host == NULL)
00216     con->socket.tcp.host= NULL;
00217   else
00218   {
00219     con->socket.tcp.host= con->socket.tcp.host_buffer;
00220     strncpy(con->socket.tcp.host, host, NI_MAXHOST);
00221     con->socket.tcp.host[NI_MAXHOST - 1]= 0;
00222   }
00223 
00224   con->socket.tcp.port= port;
00225 }
00226 
00227 const char *drizzle_con_user(const drizzle_con_st *con)
00228 {
00229   return con->user;
00230 }
00231 
00232 const char *drizzle_con_password(const drizzle_con_st *con)
00233 {
00234   return con->password;
00235 }
00236 
00237 void drizzle_con_set_auth(drizzle_con_st *con, const char *user,
00238                           const char *password)
00239 {
00240   if (user == NULL)
00241     con->user[0]= 0;
00242   else
00243   {
00244     strncpy(con->user, user, DRIZZLE_MAX_USER_SIZE);
00245     con->user[DRIZZLE_MAX_USER_SIZE - 1]= 0;
00246   }
00247 
00248   if (password == NULL)
00249     con->password[0]= 0;
00250   else
00251   {
00252     strncpy(con->password, password, DRIZZLE_MAX_PASSWORD_SIZE);
00253     con->password[DRIZZLE_MAX_PASSWORD_SIZE - 1]= 0;
00254   }
00255 }
00256 
00257 const char *drizzle_con_db(const drizzle_con_st *con)
00258 {
00259   return con->db;
00260 }
00261 
00262 void drizzle_con_set_db(drizzle_con_st *con, const char *db)
00263 {
00264   if (db == NULL)
00265     con->db[0]= 0;
00266   else
00267   {
00268     strncpy(con->db, db, DRIZZLE_MAX_DB_SIZE);
00269     con->db[DRIZZLE_MAX_DB_SIZE - 1]= 0;
00270   }
00271 }
00272 
00273 void *drizzle_con_context(const drizzle_con_st *con)
00274 {
00275   return con->context;
00276 }
00277 
00278 void drizzle_con_set_context(drizzle_con_st *con, void *context)
00279 {
00280   con->context= context;
00281 }
00282 
00283 void drizzle_con_set_context_free_fn(drizzle_con_st *con,
00284                                      drizzle_con_context_free_fn *function)
00285 {
00286   con->context_free_fn= function;
00287 }
00288 
00289 uint8_t drizzle_con_protocol_version(const drizzle_con_st *con)
00290 {
00291   return con->protocol_version;
00292 }
00293 
00294 const char *drizzle_con_server_version(const drizzle_con_st *con)
00295 {
00296   return con->server_version;
00297 }
00298 
00299 uint32_t drizzle_con_server_version_number(const drizzle_con_st *con)
00300 {
00301   uint32_t major;
00302   uint32_t minor;
00303   uint32_t version;
00304   const char *current;
00305   char *end;
00306 
00307   current= con->server_version;
00308 
00309   major= (uint32_t)strtoul(current, &end, 10);
00310   current= end + 1;
00311   minor= (uint32_t)strtoul(current, &end, 10);
00312   current= end + 1;
00313   version= (uint32_t)strtoul(current, &end, 10);
00314 
00315   return (major * 10000) + (minor * 100) + version;
00316 }
00317 
00318 uint32_t drizzle_con_thread_id(const drizzle_con_st *con)
00319 {
00320   return con->thread_id;
00321 }
00322 
00323 const uint8_t *drizzle_con_scramble(const drizzle_con_st *con)
00324 {
00325   return con->scramble;
00326 }
00327 
00328 drizzle_capabilities_t drizzle_con_capabilities(const drizzle_con_st *con)
00329 {
00330   return con->capabilities;
00331 }
00332 
00333 drizzle_charset_t drizzle_con_charset(const drizzle_con_st *con)
00334 {
00335   return con->charset;
00336 }
00337 
00338 drizzle_con_status_t drizzle_con_status(const drizzle_con_st *con)
00339 {
00340   return con->status;
00341 }
00342 
00343 uint32_t drizzle_con_max_packet_size(const drizzle_con_st *con)
00344 {
00345   return con->max_packet_size;
00346 }
00347 
00348 /*
00349  * Client Definitions
00350  */
00351 
00352 drizzle_return_t drizzle_con_connect(drizzle_con_st *con)
00353 {
00354   if (con->options & DRIZZLE_CON_READY)
00355     return DRIZZLE_RETURN_OK;
00356 
00357   if (drizzle_state_none(con))
00358   {
00359     if (!(con->options & DRIZZLE_CON_RAW_PACKET))
00360     {
00361       drizzle_state_push(con, drizzle_state_handshake_server_read);
00362       drizzle_state_push(con, drizzle_state_packet_read);
00363     }
00364 
00365     drizzle_state_push(con, drizzle_state_connect);
00366     drizzle_state_push(con, drizzle_state_addrinfo);
00367   }
00368 
00369   return drizzle_state_loop(con);
00370 }
00371 
00372 drizzle_result_st *drizzle_con_quit(drizzle_con_st *con,
00373                                     drizzle_result_st *result,
00374                                     drizzle_return_t *ret_ptr)
00375 {
00376   return drizzle_con_command_write(con, result, DRIZZLE_COMMAND_QUIT, NULL, 0,
00377                                    0, ret_ptr);
00378 }
00379 
00380 drizzle_result_st *drizzle_quit(drizzle_con_st *con,
00381                                 drizzle_result_st *result,
00382                                 drizzle_return_t *ret_ptr)
00383 {
00384   return drizzle_con_quit(con, result, ret_ptr);
00385 }
00386 
00387 drizzle_result_st *drizzle_con_select_db(drizzle_con_st *con,
00388                                          drizzle_result_st *result,
00389                                          const char *db,
00390                                          drizzle_return_t *ret_ptr)
00391 {
00392   drizzle_con_set_db(con, db);
00393   return drizzle_con_command_write(con, result, DRIZZLE_COMMAND_INIT_DB,
00394                                    db, strlen(db), strlen(db), ret_ptr);
00395 }
00396 
00397 drizzle_result_st *drizzle_select_db(drizzle_con_st *con,
00398                                      drizzle_result_st *result,
00399                                      const char *db,
00400                                      drizzle_return_t *ret_ptr)
00401 {
00402   return drizzle_con_select_db(con, result, db, ret_ptr);
00403 }
00404 
00405 drizzle_result_st *drizzle_con_shutdown(drizzle_con_st *con,
00406                                         drizzle_result_st *result,
00407                                         drizzle_return_t *ret_ptr)
00408 {
00409   if (con->options & DRIZZLE_CON_MYSQL)
00410   {
00411     return drizzle_con_command_write(con, result, DRIZZLE_COMMAND_SHUTDOWN,
00412                                      "0", 1, 1, ret_ptr);
00413   }
00414 
00415   return drizzle_con_command_write(con, result, DRIZZLE_COMMAND_SHUTDOWN, NULL,
00416                                    0, 0, ret_ptr);
00417 }
00418 
00419 drizzle_result_st *drizzle_shutdown(drizzle_con_st *con,
00420                                     drizzle_result_st *result, uint32_t level,
00421                                     drizzle_return_t *ret_ptr)
00422 {
00423   (void) level;
00424   return drizzle_con_shutdown(con, result, ret_ptr);
00425 }
00426 
00427 drizzle_result_st *drizzle_con_ping(drizzle_con_st *con,
00428                                     drizzle_result_st *result,
00429                                     drizzle_return_t *ret_ptr)
00430 {
00431   return drizzle_con_command_write(con, result, DRIZZLE_COMMAND_PING, NULL, 0,
00432                                    0, ret_ptr);
00433 }
00434 
00435 drizzle_result_st *drizzle_ping(drizzle_con_st *con,
00436                                 drizzle_result_st *result,
00437                                 drizzle_return_t *ret_ptr)
00438 {
00439   return drizzle_con_ping(con, result, ret_ptr);
00440 }
00441 
00442 drizzle_result_st *drizzle_con_command_write(drizzle_con_st *con,
00443                                              drizzle_result_st *result,
00444                                              drizzle_command_t command,
00445                                              const void *data, size_t size,
00446                                              size_t total,
00447                                              drizzle_return_t *ret_ptr)
00448 {
00449   if (!(con->options & DRIZZLE_CON_READY))
00450   {
00451     if (con->options & DRIZZLE_CON_RAW_PACKET)
00452     {
00453       drizzle_set_error(con->drizzle, "drizzle_command_write",
00454                         "connection not ready");
00455       *ret_ptr= DRIZZLE_RETURN_NOT_READY;
00456       return result;
00457     }
00458 
00459     *ret_ptr= drizzle_con_connect(con);
00460     if (*ret_ptr != DRIZZLE_RETURN_OK)
00461       return result;
00462   }
00463 
00464   if (drizzle_state_none(con))
00465   {
00466     if (con->options & (DRIZZLE_CON_RAW_PACKET | DRIZZLE_CON_NO_RESULT_READ))
00467       con->result= NULL;
00468     else
00469     {
00470       con->result= drizzle_result_create(con, result);
00471       if (con->result == NULL)
00472       {
00473         *ret_ptr= DRIZZLE_RETURN_MEMORY;
00474         return NULL;
00475       }
00476     }
00477 
00478     con->command= command;
00479     con->command_data= (uint8_t *)data;
00480     con->command_size= size;
00481     con->command_offset= 0;
00482     con->command_total= total;
00483 
00484     drizzle_state_push(con, drizzle_state_command_write);
00485   }
00486   else if (con->command_data == NULL)
00487   {
00488     con->command_data= (uint8_t *)data;
00489     con->command_size= size;
00490   }
00491 
00492   *ret_ptr= drizzle_state_loop(con);
00493   if (*ret_ptr == DRIZZLE_RETURN_PAUSE)
00494     *ret_ptr= DRIZZLE_RETURN_OK;
00495   else if (*ret_ptr != DRIZZLE_RETURN_OK &&
00496            *ret_ptr != DRIZZLE_RETURN_IO_WAIT &&
00497            *ret_ptr != DRIZZLE_RETURN_ERROR_CODE)
00498   {
00499     drizzle_result_free(con->result);
00500     con->result= result;
00501   }
00502 
00503   return con->result;
00504 }
00505 
00506 /*
00507  * Server Definitions
00508  */
00509 
00510 drizzle_return_t drizzle_con_listen(drizzle_con_st *con)
00511 {
00512   if (con->options & DRIZZLE_CON_READY)
00513     return DRIZZLE_RETURN_OK;
00514 
00515   if (drizzle_state_none(con))
00516   {
00517     drizzle_state_push(con, drizzle_state_listen);
00518     drizzle_state_push(con, drizzle_state_addrinfo);
00519   }
00520 
00521   return drizzle_state_loop(con);
00522 }
00523 
00524 int drizzle_con_backlog(const drizzle_con_st *con)
00525 {
00526   return con->backlog;
00527 }
00528 
00529 void drizzle_con_set_backlog(drizzle_con_st *con, int backlog)
00530 {
00531   con->backlog= backlog;
00532 }
00533 
00534 void drizzle_con_set_protocol_version(drizzle_con_st *con,
00535                                       uint8_t protocol_version)
00536 {
00537   con->protocol_version= protocol_version;
00538 }
00539 
00540 void drizzle_con_set_server_version(drizzle_con_st *con,
00541                                     const char *server_version)
00542 {
00543   if (server_version == NULL)
00544     con->server_version[0]= 0;
00545   else
00546   {
00547     strncpy(con->server_version, server_version,
00548             DRIZZLE_MAX_SERVER_VERSION_SIZE);
00549     con->server_version[DRIZZLE_MAX_SERVER_VERSION_SIZE - 1]= 0;
00550   }
00551 }
00552 
00553 void drizzle_con_set_thread_id(drizzle_con_st *con, uint32_t thread_id)
00554 {
00555   con->thread_id= thread_id;
00556 }
00557 
00558 void drizzle_con_set_scramble(drizzle_con_st *con, const uint8_t *scramble)
00559 {
00560   if (scramble == NULL)
00561     con->scramble= NULL;
00562   else
00563   {
00564     con->scramble= con->scramble_buffer;
00565     memcpy(con->scramble, scramble, DRIZZLE_MAX_SCRAMBLE_SIZE);
00566   }
00567 }
00568 
00569 void drizzle_con_set_capabilities(drizzle_con_st *con,
00570                                   drizzle_capabilities_t capabilities)
00571 {
00572   con->capabilities= capabilities;
00573 }
00574 
00575 void drizzle_con_set_charset(drizzle_con_st *con, drizzle_charset_t charset)
00576 {
00577   con->charset= charset;
00578 }
00579 
00580 void drizzle_con_set_status(drizzle_con_st *con, drizzle_con_status_t status)
00581 {
00582   con->status= status;
00583 }
00584 
00585 void drizzle_con_set_max_packet_size(drizzle_con_st *con,
00586                                      uint32_t max_packet_size)
00587 {
00588   con->max_packet_size= max_packet_size;
00589 }
00590 
00591 void drizzle_con_copy_handshake(drizzle_con_st *con, drizzle_con_st *from)
00592 {
00593   drizzle_con_set_auth(con, from->user, NULL);
00594   drizzle_con_set_scramble(con, from->scramble);
00595   drizzle_con_set_db(con, from->db);
00596   drizzle_con_set_protocol_version(con, from->protocol_version);
00597   drizzle_con_set_server_version(con, from->server_version);
00598   drizzle_con_set_thread_id(con, from->thread_id);
00599   drizzle_con_set_scramble(con, from->scramble);
00600   drizzle_con_set_capabilities(con, from->capabilities);
00601   drizzle_con_set_charset(con, from->charset);
00602   drizzle_con_set_status(con, from->status);
00603   drizzle_con_set_max_packet_size(con, from->max_packet_size);
00604 }
00605 
00606 void *drizzle_con_command_read(drizzle_con_st *con,
00607                                drizzle_command_t *command, size_t *offset,
00608                                size_t *size, size_t *total,
00609                                drizzle_return_t *ret_ptr)
00610 {
00611   if (drizzle_state_none(con))
00612   {
00613     con->packet_number= 0;
00614     con->command_offset= 0;
00615     con->command_total= 0;
00616 
00617     drizzle_state_push(con, drizzle_state_command_read);
00618     drizzle_state_push(con, drizzle_state_packet_read);
00619   }
00620 
00621   *offset= con->command_offset;
00622 
00623   *ret_ptr= drizzle_state_loop(con);
00624   if (*ret_ptr == DRIZZLE_RETURN_PAUSE)
00625     *ret_ptr= DRIZZLE_RETURN_OK;
00626 
00627   *command= con->command;
00628   *size= con->command_size;
00629   *total= con->command_total;
00630 
00631   return con->command_data;
00632 }
00633 
00634 void *drizzle_con_command_buffer(drizzle_con_st *con,
00635                                  drizzle_command_t *command, size_t *total,
00636                                  drizzle_return_t *ret_ptr)
00637 {
00638   uint8_t *command_data;
00639   size_t offset= 0;
00640   size_t size= 0;
00641 
00642   command_data= drizzle_con_command_read(con, command, &offset, &size, total,
00643                                          ret_ptr);
00644   if (*ret_ptr != DRIZZLE_RETURN_OK)
00645     return NULL;
00646 
00647   if (command_data == NULL)
00648   {
00649     *total= 0;
00650     return NULL;
00651   }
00652 
00653   if (con->command_buffer == NULL)
00654   {
00655     con->command_buffer= malloc((*total) + 1);
00656     if (con->command_buffer == NULL)
00657     {
00658       drizzle_set_error(con->drizzle, "drizzle_command_buffer", "malloc");
00659       *ret_ptr= DRIZZLE_RETURN_MEMORY;
00660       return NULL;
00661     }
00662   }
00663 
00664   memcpy(con->command_buffer + offset, command_data, size);
00665 
00666   while ((offset + size) != (*total))
00667   {
00668     command_data= drizzle_con_command_read(con, command, &offset, &size, total,
00669                                            ret_ptr);
00670     if (*ret_ptr != DRIZZLE_RETURN_OK)
00671       return NULL;
00672 
00673     memcpy(con->command_buffer + offset, command_data, size);
00674   }
00675 
00676   command_data= con->command_buffer;
00677   con->command_buffer= NULL;
00678   command_data[*total]= 0;
00679 
00680   return command_data;
00681 }
00682 
00683 /*
00684  * Local Definitions
00685  */
00686 
00687 void drizzle_con_reset_addrinfo(drizzle_con_st *con)
00688 {
00689   switch (con->socket_type)
00690   {
00691   case DRIZZLE_CON_SOCKET_TCP:
00692     if (con->socket.tcp.addrinfo != NULL)
00693     {
00694       freeaddrinfo(con->socket.tcp.addrinfo);
00695       con->socket.tcp.addrinfo= NULL;
00696     }
00697     break;
00698 
00699   case DRIZZLE_CON_SOCKET_UDS:
00700     con->socket.uds.addrinfo.ai_addr= NULL;
00701     break;
00702 
00703   default:
00704     break;
00705   }
00706 
00707   con->addrinfo_next= NULL;
00708 }
00709 
00710 /*
00711  * State Definitions
00712  */
00713 
00714 drizzle_return_t drizzle_state_addrinfo(drizzle_con_st *con)
00715 {
00716   drizzle_con_tcp_st *tcp;
00717   const char *host;
00718   char port[NI_MAXSERV];
00719   struct addrinfo ai;
00720   int ret;
00721 
00722   drizzle_log_debug(con->drizzle, "drizzle_state_addrinfo");
00723 
00724   switch (con->socket_type)
00725   {
00726   case DRIZZLE_CON_SOCKET_TCP:
00727     tcp= &(con->socket.tcp);
00728 
00729     if (tcp->addrinfo != NULL)
00730     {
00731       freeaddrinfo(tcp->addrinfo);
00732       tcp->addrinfo= NULL;
00733     }
00734 
00735     if (tcp->port != 0)
00736       snprintf(port, NI_MAXSERV, "%u", tcp->port);
00737     else if (con->options & DRIZZLE_CON_MYSQL)
00738       snprintf(port, NI_MAXSERV, "%u", DRIZZLE_DEFAULT_TCP_PORT_MYSQL);
00739     else
00740       snprintf(port, NI_MAXSERV, "%u", DRIZZLE_DEFAULT_TCP_PORT);
00741 
00742     memset(&ai, 0, sizeof(struct addrinfo));
00743     ai.ai_socktype= SOCK_STREAM;
00744     ai.ai_protocol= IPPROTO_TCP;
00745 
00746     if (con->options & DRIZZLE_CON_LISTEN)
00747     {
00748       ai.ai_flags = AI_PASSIVE;
00749       ai.ai_family = AF_UNSPEC;
00750       host= tcp->host;
00751     }
00752     else
00753     {
00754       if (tcp->host == NULL)
00755         host= DRIZZLE_DEFAULT_TCP_HOST;
00756       else
00757         host= tcp->host;
00758     }
00759 
00760     ret= getaddrinfo(host, port, &ai, &(tcp->addrinfo));
00761     if (ret != 0)
00762     {
00763       drizzle_set_error(con->drizzle, "drizzle_state_addrinfo",
00764                         "getaddrinfo:%s", gai_strerror(ret));
00765       return DRIZZLE_RETURN_GETADDRINFO;
00766     }
00767 
00768     con->addrinfo_next= tcp->addrinfo;
00769 
00770     break;
00771 
00772   case DRIZZLE_CON_SOCKET_UDS:
00773     con->addrinfo_next= &(con->socket.uds.addrinfo);
00774     break;
00775 
00776   default:
00777     break;
00778   }
00779 
00780   drizzle_state_pop(con);
00781   return DRIZZLE_RETURN_OK;
00782 }
00783 
00784 drizzle_return_t drizzle_state_connect(drizzle_con_st *con)
00785 {
00786   int ret;
00787   drizzle_return_t dret;
00788 
00789   drizzle_log_debug(con->drizzle, "drizzle_state_connect");
00790 
00791   if (con->fd != -1)
00792   {
00793     (void)close(con->fd);
00794     con->fd= -1;
00795   }
00796 
00797   if (con->addrinfo_next == NULL)
00798   {
00799     drizzle_set_error(con->drizzle, "drizzle_state_connect",
00800                       "could not connect");
00801     drizzle_state_reset(con);
00802     return DRIZZLE_RETURN_COULD_NOT_CONNECT;
00803   }
00804 
00805   con->fd= socket(con->addrinfo_next->ai_family,
00806                   con->addrinfo_next->ai_socktype,
00807                   con->addrinfo_next->ai_protocol);
00808   if (con->fd == -1)
00809   {
00810     drizzle_set_error(con->drizzle, "drizzle_state_connect", "socket:%d",
00811                       errno);
00812     con->drizzle->last_errno= errno;
00813     return DRIZZLE_RETURN_ERRNO;
00814   }
00815 
00816   dret= _con_setsockopt(con);
00817   if (dret != DRIZZLE_RETURN_OK)
00818   {
00819     con->drizzle->last_errno= errno;
00820     return dret;
00821   }
00822 
00823   while (1)
00824   {
00825     ret= connect(con->fd, con->addrinfo_next->ai_addr,
00826                  con->addrinfo_next->ai_addrlen);
00827 
00828     drizzle_log_crazy(con->drizzle, "connect return=%d errno=%d", ret, errno);
00829 
00830     if (ret == 0)
00831     {
00832       con->addrinfo_next= NULL;
00833       break;
00834     }
00835 
00836     if (errno == EAGAIN || errno == EINTR)
00837       continue;
00838 
00839     if (errno == EINPROGRESS)
00840     {
00841       drizzle_state_pop(con);
00842       drizzle_state_push(con, drizzle_state_connecting);
00843       return DRIZZLE_RETURN_OK;
00844     }
00845 
00846     if (errno == ECONNREFUSED || errno == ENETUNREACH || errno == ETIMEDOUT)
00847     {
00848       con->addrinfo_next= con->addrinfo_next->ai_next;
00849       return DRIZZLE_RETURN_OK;
00850     }
00851 
00852     drizzle_set_error(con->drizzle, "drizzle_state_connect", "connect:%d",
00853                       errno);
00854     con->drizzle->last_errno= errno;
00855     return DRIZZLE_RETURN_ERRNO;
00856   }
00857 
00858   drizzle_state_pop(con);
00859   return DRIZZLE_RETURN_OK;
00860 }
00861 
00862 drizzle_return_t drizzle_state_connecting(drizzle_con_st *con)
00863 {
00864   drizzle_return_t ret;
00865 
00866   drizzle_log_debug(con->drizzle, "drizzle_state_connecting");
00867 
00868   while (1)
00869   {
00870     if (con->revents & POLLOUT)
00871     {
00872       drizzle_state_pop(con);
00873       return DRIZZLE_RETURN_OK;
00874     }
00875     else if (con->revents & (POLLERR | POLLHUP | POLLNVAL))
00876     {
00877       con->revents= 0;
00878       drizzle_state_pop(con);
00879       drizzle_state_push(con, drizzle_state_connect);
00880       con->addrinfo_next= con->addrinfo_next->ai_next;
00881       return DRIZZLE_RETURN_OK;
00882     }
00883 
00884     ret= drizzle_con_set_events(con, POLLOUT);
00885     if (ret != DRIZZLE_RETURN_OK)
00886       return ret;
00887 
00888     if (con->drizzle->options & DRIZZLE_NON_BLOCKING)
00889       return DRIZZLE_RETURN_IO_WAIT;
00890 
00891     ret= drizzle_con_wait(con->drizzle);
00892     if (ret != DRIZZLE_RETURN_OK)
00893       return ret;
00894   }
00895 }
00896 
00897 drizzle_return_t drizzle_state_read(drizzle_con_st *con)
00898 {
00899   drizzle_return_t ret;
00900   ssize_t read_size;
00901 
00902   drizzle_log_debug(con->drizzle, "drizzle_state_read");
00903 
00904   if (con->buffer_size == 0)
00905     con->buffer_ptr= con->buffer;
00906   else if ((con->buffer_ptr - con->buffer) > (DRIZZLE_MAX_BUFFER_SIZE / 2))
00907   {
00908     memmove(con->buffer, con->buffer_ptr, con->buffer_size);
00909     con->buffer_ptr= con->buffer;
00910   }
00911 
00912   while (1)
00913   {
00914     read_size= read(con->fd, con->buffer_ptr + con->buffer_size,
00915                     (size_t)DRIZZLE_MAX_BUFFER_SIZE -
00916                     ((size_t)(con->buffer_ptr - con->buffer) +
00917                      con->buffer_size));
00918 
00919     drizzle_log_crazy(con->drizzle, "read fd=%d return=%zd errno=%d", con->fd,
00920                       read_size, errno);
00921 
00922     if (read_size == 0)
00923     {
00924       drizzle_set_error(con->drizzle, "drizzle_state_read",
00925                         "lost connection to server (EOF)");
00926       return DRIZZLE_RETURN_LOST_CONNECTION;
00927     }
00928     else if (read_size == -1)
00929     {
00930       if (errno == EAGAIN)
00931       {
00932         ret= drizzle_con_set_events(con, POLLIN);
00933         if (ret != DRIZZLE_RETURN_OK)
00934           return 0;
00935 
00936         if (con->drizzle->options & DRIZZLE_NON_BLOCKING)
00937           return DRIZZLE_RETURN_IO_WAIT;
00938 
00939         ret= drizzle_con_wait(con->drizzle);
00940         if (ret != DRIZZLE_RETURN_OK)
00941           return ret;
00942 
00943         continue;
00944       }
00945       else if (errno == ECONNREFUSED)
00946       {
00947         con->revents= 0;
00948         drizzle_state_pop(con);
00949         drizzle_state_push(con, drizzle_state_connect);
00950         con->addrinfo_next= con->addrinfo_next->ai_next;
00951         return DRIZZLE_RETURN_OK;
00952       }
00953       else if (errno == EINTR)
00954         continue;
00955       else if (errno == EPIPE || errno == ECONNRESET)
00956       {
00957         drizzle_set_error(con->drizzle, "drizzle_state_read",
00958                           "lost connection to server (%d)", errno);
00959         return DRIZZLE_RETURN_LOST_CONNECTION;
00960       }
00961 
00962       drizzle_set_error(con->drizzle, "drizzle_state_read", "read:%d", errno);
00963       con->drizzle->last_errno= errno;
00964       return DRIZZLE_RETURN_ERRNO;
00965     }
00966 
00967     con->buffer_size+= (size_t)read_size;
00968     break;
00969   }
00970 
00971   drizzle_state_pop(con);;
00972   return DRIZZLE_RETURN_OK;
00973 }
00974 
00975 drizzle_return_t drizzle_state_write(drizzle_con_st *con)
00976 {
00977   drizzle_return_t ret;
00978   ssize_t write_size;
00979 
00980   drizzle_log_debug(con->drizzle, "drizzle_state_write");
00981 
00982   while (con->buffer_size != 0)
00983   {
00984     write_size= write(con->fd, con->buffer_ptr, con->buffer_size);
00985 
00986     drizzle_log_crazy(con->drizzle, "write fd=%d return=%zd errno=%d", con->fd,
00987                       write_size, errno);
00988 
00989     if (write_size == 0)
00990     {
00991       drizzle_set_error(con->drizzle, "drizzle_state_write",
00992                         "lost connection to server (EOF)");
00993       return DRIZZLE_RETURN_LOST_CONNECTION;
00994     }
00995     else if (write_size == -1)
00996     {
00997       if (errno == EAGAIN)
00998       {
00999         ret= drizzle_con_set_events(con, POLLOUT);
01000         if (ret != DRIZZLE_RETURN_OK)
01001           return ret;
01002 
01003         if (con->drizzle->options & DRIZZLE_NON_BLOCKING)
01004           return DRIZZLE_RETURN_IO_WAIT;
01005 
01006         ret= drizzle_con_wait(con->drizzle);
01007         if (ret != DRIZZLE_RETURN_OK)
01008           return ret;
01009 
01010         continue;
01011       }
01012       else if (errno == EINTR)
01013         continue;
01014       else if (errno == EPIPE || errno == ECONNRESET)
01015       {
01016         drizzle_set_error(con->drizzle, "drizzle_state_write",
01017                           "lost connection to server (%d)", errno);
01018         return DRIZZLE_RETURN_LOST_CONNECTION;
01019       }
01020 
01021       drizzle_set_error(con->drizzle, "drizzle_state_write", "write:%d", errno);
01022       con->drizzle->last_errno= errno;
01023       return DRIZZLE_RETURN_ERRNO;
01024     }
01025 
01026     con->buffer_ptr+= write_size;
01027     con->buffer_size-= (size_t)write_size;
01028     if (con->buffer_size == 0)
01029       break;
01030   }
01031 
01032   con->buffer_ptr= con->buffer;
01033 
01034   drizzle_state_pop(con);
01035   return DRIZZLE_RETURN_OK;
01036 }
01037 
01038 drizzle_return_t drizzle_state_listen(drizzle_con_st *con)
01039 {
01040   char host[NI_MAXHOST];
01041   char port[NI_MAXSERV];
01042   int ret;
01043   int fd;
01044   int opt;
01045   drizzle_con_st *new_con;
01046 
01047   for (; con->addrinfo_next != NULL;
01048        con->addrinfo_next= con->addrinfo_next->ai_next)
01049   {
01050     ret= getnameinfo(con->addrinfo_next->ai_addr,
01051                      con->addrinfo_next->ai_addrlen, host, NI_MAXHOST, port,
01052                      NI_MAXSERV, NI_NUMERICHOST | NI_NUMERICSERV);
01053     if (ret != 0)
01054     {
01055       drizzle_set_error(con->drizzle, "drizzle_state_listen", "getnameinfo:%s",
01056                         gai_strerror(ret));
01057       return DRIZZLE_RETURN_GETADDRINFO;
01058     }
01059 
01060     /* Call to socket() can fail for some getaddrinfo results, try another. */
01061     fd= socket(con->addrinfo_next->ai_family, con->addrinfo_next->ai_socktype,
01062                con->addrinfo_next->ai_protocol);
01063     if (fd == -1)
01064     {
01065       drizzle_log_info(con->drizzle, "could not listen on %s:%s", host, port);
01066       drizzle_set_error(con->drizzle, "drizzle_state_listen", "socket:%d",
01067                         errno);
01068       continue;
01069     }
01070 
01071     opt= 1;
01072     ret= setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt));
01073     if (ret == -1)
01074     {
01075       close(fd);
01076       drizzle_set_error(con->drizzle, "drizzle_state_listen", "setsockopt:%d",
01077                         errno);
01078       return DRIZZLE_RETURN_ERRNO;
01079     }
01080 
01081     ret= bind(fd, con->addrinfo_next->ai_addr, con->addrinfo_next->ai_addrlen);
01082     if (ret == -1)
01083     {
01084       close(fd);
01085       drizzle_set_error(con->drizzle, "drizzle_state_listen", "bind:%d", errno);
01086       if (errno == EADDRINUSE)
01087       {
01088         if (con->fd == -1)
01089         {
01090           drizzle_log_info(con->drizzle, "could not listen on %s:%s", host,
01091                            port);
01092         }
01093 
01094         continue;
01095       }
01096 
01097       return DRIZZLE_RETURN_ERRNO;
01098     }
01099 
01100     if (listen(fd, con->backlog) == -1)
01101     {
01102       close(fd);
01103       drizzle_set_error(con->drizzle, "drizzle_state_listen", "listen:%d",
01104                         errno);
01105       return DRIZZLE_RETURN_ERRNO;
01106     }
01107 
01108     if (con->fd == -1)
01109     {
01110       con->fd= fd;
01111       new_con= con;
01112     }
01113     else
01114     {
01115       new_con= drizzle_con_clone(con->drizzle, NULL, con);
01116       if (new_con == NULL)
01117       {
01118         close(fd);
01119         return DRIZZLE_RETURN_MEMORY;
01120       }
01121 
01122       new_con->fd= fd;
01123     }
01124 
01125     /* Wait for read events on the listening socket. */
01126     ret= drizzle_con_set_events(new_con, POLLIN);
01127     if (ret != DRIZZLE_RETURN_OK)
01128     {
01129       drizzle_con_free(new_con);
01130       return ret;
01131     }
01132 
01133     drizzle_log_info(con->drizzle, "listening on %s:%s", host, port);
01134   }
01135 
01136   /* Report last socket() error if we couldn't find an address to bind. */
01137   if (con->fd == -1)
01138     return DRIZZLE_RETURN_ERRNO;
01139 
01140   drizzle_state_pop(con);
01141   return DRIZZLE_RETURN_OK;
01142 }
01143 
01144 /*
01145  * Static Definitions
01146  */
01147 
01148 static drizzle_return_t _con_setsockopt(drizzle_con_st *con)
01149 {
01150   int ret;
01151   struct linger linger;
01152   struct timeval waittime;
01153 
01154   ret= 1;
01155   ret= setsockopt(con->fd, IPPROTO_TCP, TCP_NODELAY, &ret,
01156                   (socklen_t)sizeof(int));
01157   if (ret == -1 && errno != EOPNOTSUPP)
01158   {
01159     drizzle_set_error(con->drizzle, "_con_setsockopt",
01160                       "setsockopt:TCP_NODELAY:%d", errno);
01161     return DRIZZLE_RETURN_ERRNO;
01162   }
01163 
01164   linger.l_onoff= 1;
01165   linger.l_linger= DRIZZLE_DEFAULT_SOCKET_TIMEOUT;
01166   ret= setsockopt(con->fd, SOL_SOCKET, SO_LINGER, &linger,
01167                   (socklen_t)sizeof(struct linger));
01168   if (ret == -1)
01169   {
01170     drizzle_set_error(con->drizzle, "_con_setsockopt",
01171                       "setsockopt:SO_LINGER:%d", errno);
01172     return DRIZZLE_RETURN_ERRNO;
01173   }
01174 
01175   waittime.tv_sec= DRIZZLE_DEFAULT_SOCKET_TIMEOUT;
01176   waittime.tv_usec= 0;
01177   ret= setsockopt(con->fd, SOL_SOCKET, SO_SNDTIMEO, &waittime,
01178                   (socklen_t)sizeof(struct timeval));
01179   if (ret == -1 && errno != ENOPROTOOPT)
01180   {
01181     drizzle_set_error(con->drizzle, "_con_setsockopt",
01182                       "setsockopt:SO_SNDTIMEO:%d", errno);
01183     return DRIZZLE_RETURN_ERRNO;
01184   }
01185 
01186   ret= setsockopt(con->fd, SOL_SOCKET, SO_RCVTIMEO, &waittime,
01187                   (socklen_t)sizeof(struct timeval));
01188   if (ret == -1 && errno != ENOPROTOOPT)
01189   {
01190     drizzle_set_error(con->drizzle, "_con_setsockopt",
01191                       "setsockopt:SO_RCVTIMEO:%d", errno);
01192     return DRIZZLE_RETURN_ERRNO;
01193   }
01194 
01195   ret= DRIZZLE_DEFAULT_SOCKET_SEND_SIZE;
01196   ret= setsockopt(con->fd, SOL_SOCKET, SO_SNDBUF, &ret, (socklen_t)sizeof(int));
01197   if (ret == -1)
01198   {
01199     drizzle_set_error(con->drizzle, "_con_setsockopt",
01200                       "setsockopt:SO_SNDBUF:%d", errno);
01201     return DRIZZLE_RETURN_ERRNO;
01202   }
01203 
01204   ret= DRIZZLE_DEFAULT_SOCKET_RECV_SIZE;
01205   ret= setsockopt(con->fd, SOL_SOCKET, SO_RCVBUF, &ret, (socklen_t)sizeof(int));
01206   if (ret == -1)
01207   {
01208     drizzle_set_error(con->drizzle, "_con_setsockopt",
01209                       "setsockopt:SO_RCVBUF:%d", errno);
01210     return DRIZZLE_RETURN_ERRNO;
01211   }
01212 
01213   ret= fcntl(con->fd, F_GETFL, 0);
01214   if (ret == -1)
01215   {
01216     drizzle_set_error(con->drizzle, "_con_setsockopt", "fcntl:F_GETFL:%d",
01217                       errno);
01218     return DRIZZLE_RETURN_ERRNO;
01219   }
01220 
01221   ret= fcntl(con->fd, F_SETFL, ret | O_NONBLOCK);
01222   if (ret == -1)
01223   {
01224     drizzle_set_error(con->drizzle, "_con_setsockopt", "fcntl:F_SETFL:%d",
01225                       errno);
01226     return DRIZZLE_RETURN_ERRNO;
01227   }
01228 
01229   return DRIZZLE_RETURN_OK;
01230 }