Drizzled Public API Documentation

conn.cc
Go to the documentation of this file.
00001 /* vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
00002  *
00003  * Drizzle Client & Protocol Library
00004  *
00005  * Copyright (C) 2008 Eric Day (eday@oddments.org)
00006  * All rights reserved.
00007  *
00008  * Redistribution and use in source and binary forms, with or without
00009  * modification, are permitted provided that the following conditions are
00010  * met:
00011  *
00012  *     * Redistributions of source code must retain the above copyright
00013  * notice, this list of conditions and the following disclaimer.
00014  *
00015  *     * Redistributions in binary form must reproduce the above
00016  * copyright notice, this list of conditions and the following disclaimer
00017  * in the documentation and/or other materials provided with the
00018  * distribution.
00019  *
00020  *     * The names of its contributors may not be used to endorse or
00021  * promote products derived from this software without specific prior
00022  * written permission.
00023  *
00024  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
00025  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
00026  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
00027  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
00028  * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
00029  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
00030  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
00031  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
00032  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
00033  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
00034  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00035  *
00036  */
00037 
00038 
00044 #include <libdrizzle/common.h>
00045 
00059 static drizzle_return_t _con_setsockopt(drizzle_con_st *con);
00060 
00063 /*
00064  * Common Definitions
00065  */
00066 
00067 int drizzle_con_fd(const drizzle_con_st *con)
00068 {
00069   if (con == NULL)
00070   {
00071     return -1;
00072   }
00073 
00074   return con->fd;
00075 }
00076 
00077 drizzle_return_t drizzle_con_set_fd(drizzle_con_st *con, int fd)
00078 {
00079   drizzle_return_t ret;
00080   if (con == NULL)
00081   {
00082     return DRIZZLE_RETURN_INVALID_ARGUMENT;
00083   }
00084 
00085   con->fd= fd;
00086 
00087   ret= _con_setsockopt(con);
00088   if (ret != DRIZZLE_RETURN_OK)
00089   {
00090     con->drizzle->last_errno= errno;
00091   }
00092 
00093   return ret;
00094 }
00095 
00096 void drizzle_con_close(drizzle_con_st *con)
00097 {
00098   if (con == NULL)
00099   {
00100     return;
00101   }
00102 
00103   if (con->fd == -1)
00104   {
00105     return;
00106   }
00107 
00108   (void)closesocket(con->fd);
00109   con->fd= -1;
00110 
00111   con->options&= int(~DRIZZLE_CON_READY);
00112   con->packet_number= 0;
00113   con->buffer_ptr= con->buffer;
00114   con->buffer_size= 0;
00115   con->events= 0;
00116   con->revents= 0;
00117 
00118   drizzle_state_reset(con);
00119 }
00120 
00121 drizzle_return_t drizzle_con_set_events(drizzle_con_st *con, short events)
00122 {
00123   drizzle_return_t ret;
00124 
00125   if ((con->events | events) == con->events)
00126   {
00127     return DRIZZLE_RETURN_OK;
00128   }
00129 
00130   con->events|= events;
00131 
00132   if (con->drizzle->event_watch_fn != NULL)
00133   {
00134     ret= con->drizzle->event_watch_fn(con, con->events,
00135                                       con->drizzle->event_watch_context);
00136     if (ret != DRIZZLE_RETURN_OK)
00137     {
00138       drizzle_con_close(con);
00139       return ret;
00140     }
00141   }
00142 
00143   return DRIZZLE_RETURN_OK;
00144 }
00145 
00146 drizzle_return_t drizzle_con_set_revents(drizzle_con_st *con, short revents)
00147 {
00148   drizzle_return_t ret;
00149   if (con == NULL)
00150   {
00151     return DRIZZLE_RETURN_INVALID_ARGUMENT;
00152   }
00153 
00154   if (revents != 0)
00155     con->options|= DRIZZLE_CON_IO_READY;
00156 
00157   con->revents= revents;
00158 
00159   /* Remove external POLLOUT watch if we didn't ask for it. Otherwise we spin
00160      forever until another POLLIN state change. This is much more efficient
00161      than removing POLLOUT on every state change since some external polling
00162      mechanisms need to use a system call to change flags (like Linux epoll). */
00163   if (revents & POLLOUT && !(con->events & POLLOUT) &&
00164       con->drizzle->event_watch_fn != NULL)
00165   {
00166     ret= con->drizzle->event_watch_fn(con, con->events,
00167                                       con->drizzle->event_watch_context);
00168     if (ret != DRIZZLE_RETURN_OK)
00169     {
00170       drizzle_con_close(con);
00171       return ret;
00172     }
00173   }
00174 
00175   con->events&= (short)~revents;
00176 
00177   return DRIZZLE_RETURN_OK;
00178 }
00179 
00180 drizzle_st *drizzle_con_drizzle(const drizzle_con_st *con)
00181 {
00182   if (con == NULL)
00183   {
00184     return NULL;
00185   }
00186   return con->drizzle;
00187 }
00188 
00189 const char *drizzle_con_error(const drizzle_con_st *con)
00190 {
00191   if (con == NULL)
00192   {
00193     return NULL;
00194   }
00195 
00196   return drizzle_error(con->drizzle);
00197 }
00198 
00199 int drizzle_con_errno(const drizzle_con_st *con)
00200 {
00201   if (con == NULL)
00202   {
00203     return 0;
00204   }
00205 
00206   return drizzle_errno(con->drizzle);
00207 }
00208 
00209 uint16_t drizzle_con_error_code(const drizzle_con_st *con)
00210 {
00211   if (con == NULL)
00212   {
00213     return 0;
00214   }
00215 
00216   return drizzle_error_code(con->drizzle);
00217 }
00218 
00219 const char *drizzle_con_sqlstate(const drizzle_con_st *con)
00220 {
00221   if (con == NULL)
00222   {
00223     return NULL;
00224   }
00225 
00226   return drizzle_sqlstate(con->drizzle);
00227 }
00228 
00229 drizzle_con_options_t drizzle_con_options(const drizzle_con_st *con)
00230 {
00231   if (con == NULL)
00232   {
00233     return drizzle_con_options_t();
00234   }
00235 
00236   return drizzle_con_options_t(con->options);
00237 }
00238 
00239 void drizzle_con_set_options(drizzle_con_st *con,
00240                              drizzle_con_options_t options)
00241 {
00242   if (con == NULL)
00243   {
00244     return;
00245   }
00246 
00247   con->options= options;
00248 }
00249 
00250 void drizzle_con_add_options(drizzle_con_st *con,
00251                              drizzle_con_options_t options)
00252 {
00253   if (con == NULL)
00254   {
00255     return;
00256   }
00257 
00258   con->options|= options;
00259 
00260   /* If asking for the experimental Drizzle protocol, clean the MySQL flag. */
00261   if (con->options & DRIZZLE_CON_EXPERIMENTAL)
00262   {
00263     con->options&= int(~DRIZZLE_CON_MYSQL);
00264   }
00265 }
00266 
00267 void drizzle_con_remove_options(drizzle_con_st *con,
00268                                 drizzle_con_options_t options)
00269 {
00270   if (con == NULL)
00271   {
00272     return;
00273   }
00274 
00275   con->options&= ~options;
00276 }
00277 
00278 const char *drizzle_con_host(const drizzle_con_st *con)
00279 {
00280   if (con == NULL)
00281   {
00282     return NULL;
00283   }
00284 
00285   if (con->socket_type == DRIZZLE_CON_SOCKET_TCP)
00286   {
00287     if (con->socket.tcp.host == NULL && !(con->options & DRIZZLE_CON_LISTEN))
00288       return DRIZZLE_DEFAULT_TCP_HOST;
00289 
00290     return con->socket.tcp.host;
00291   }
00292 
00293   return NULL;
00294 }
00295 
00296 in_port_t drizzle_con_port(const drizzle_con_st *con)
00297 {
00298   if (con and con->socket_type == DRIZZLE_CON_SOCKET_TCP)
00299   {
00300     if (con->socket.tcp.port != 0)
00301     {
00302       return con->socket.tcp.port;
00303     }
00304 
00305     if (con->options & DRIZZLE_CON_MYSQL)
00306     {
00307       return DRIZZLE_DEFAULT_TCP_PORT_MYSQL;
00308     }
00309 
00310     return DRIZZLE_DEFAULT_TCP_PORT;
00311   }
00312 
00313   return in_port_t(0);
00314 }
00315 
00316 void drizzle_con_set_tcp(drizzle_con_st *con, const char *host, in_port_t port)
00317 {
00318   if (con == NULL)
00319   {
00320     return;
00321   }
00322 
00323   drizzle_con_reset_addrinfo(con);
00324 
00325   con->socket_type= DRIZZLE_CON_SOCKET_TCP;
00326 
00327   if (host == NULL)
00328   {
00329     con->socket.tcp.host= NULL;
00330   }
00331   else
00332   {
00333     con->socket.tcp.host= con->socket.tcp.host_buffer;
00334     strncpy(con->socket.tcp.host, host, NI_MAXHOST);
00335     con->socket.tcp.host[NI_MAXHOST - 1]= 0;
00336   }
00337 
00338   con->socket.tcp.port= port;
00339 }
00340 
00341 const char *drizzle_con_user(const drizzle_con_st *con)
00342 {
00343   if (con == NULL)
00344   {
00345     return NULL;
00346   }
00347 
00348   return con->user;
00349 }
00350 
00351 const char *drizzle_con_password(const drizzle_con_st *con)
00352 {
00353   if (con == NULL)
00354   {
00355     return NULL;
00356   }
00357 
00358   return con->password;
00359 }
00360 
00361 void drizzle_con_set_auth(drizzle_con_st *con, const char *user,
00362                           const char *password)
00363 {
00364   if (con == NULL)
00365   {
00366     return;
00367   }
00368 
00369   if (user == NULL)
00370   {
00371     con->user[0]= 0;
00372   }
00373   else
00374   {
00375     strncpy(con->user, user, DRIZZLE_MAX_USER_SIZE);
00376     con->user[DRIZZLE_MAX_USER_SIZE - 1]= 0;
00377   }
00378 
00379   if (password == NULL)
00380   {
00381     con->password[0]= 0;
00382   }
00383   else
00384   {
00385     strncpy(con->password, password, DRIZZLE_MAX_PASSWORD_SIZE);
00386     con->password[DRIZZLE_MAX_PASSWORD_SIZE - 1]= 0;
00387   }
00388 }
00389 
00390 const char *drizzle_con_db(const drizzle_con_st *con)
00391 {
00392   if (con == NULL)
00393   {
00394     return NULL;
00395   }
00396 
00397   return con->db;
00398 }
00399 
00400 void drizzle_con_set_db(drizzle_con_st *con, const char *db)
00401 {
00402   if (con == NULL)
00403   {
00404     return;
00405   }
00406 
00407   if (db == NULL)
00408   {
00409     con->db[0]= 0;
00410   }
00411   else
00412   {
00413     strncpy(con->db, db, DRIZZLE_MAX_DB_SIZE);
00414     con->db[DRIZZLE_MAX_DB_SIZE - 1]= 0;
00415   }
00416 }
00417 
00418 void *drizzle_con_context(const drizzle_con_st *con)
00419 {
00420   if (con == NULL)
00421   {
00422     return NULL;
00423   }
00424 
00425   return con->context;
00426 }
00427 
00428 void drizzle_con_set_context(drizzle_con_st *con, void *context)
00429 {
00430   if (con == NULL)
00431   {
00432     return;
00433   }
00434 
00435   con->context= context;
00436 }
00437 
00438 void drizzle_con_set_context_free_fn(drizzle_con_st *con,
00439                                      drizzle_con_context_free_fn *function)
00440 {
00441   if (con == NULL)
00442   {
00443     return;
00444   }
00445 
00446   con->context_free_fn= function;
00447 }
00448 
00449 uint8_t drizzle_con_protocol_version(const drizzle_con_st *con)
00450 {
00451   if (con == NULL)
00452   {
00453     return 0;
00454   }
00455 
00456   return con->protocol_version;
00457 }
00458 
00459 const char *drizzle_con_server_version(const drizzle_con_st *con)
00460 {
00461   if (con == NULL)
00462   {
00463     return NULL;
00464   }
00465 
00466   return con->server_version;
00467 }
00468 
00469 uint32_t drizzle_con_server_version_number(const drizzle_con_st *con)
00470 {
00471   if (con)
00472   {
00473     const char *current= con->server_version;
00474     char *end;
00475 
00476     uint32_t major= (uint32_t)strtoul(current, &end, 10);
00477     current= end +1;
00478     uint32_t minor= (uint32_t)strtoul(current, &end, 10);
00479     current= end +1;
00480     uint32_t version= (uint32_t)strtoul(current, &end, 10);
00481 
00482     return (major * 10000) +(minor * 100) +version;
00483   }
00484 
00485   return 0;
00486 }
00487 
00488 uint32_t drizzle_con_thread_id(const drizzle_con_st *con)
00489 {
00490   if (con == NULL)
00491   {
00492     return 0;
00493   }
00494 
00495   return con->thread_id;
00496 }
00497 
00498 const uint8_t *drizzle_con_scramble(const drizzle_con_st *con)
00499 {
00500   if (con == NULL)
00501   {
00502     return NULL;
00503   }
00504 
00505   return con->scramble;
00506 }
00507 
00508 drizzle_capabilities_t drizzle_con_capabilities(const drizzle_con_st *con)
00509 {
00510   if (con == NULL)
00511   {
00512     return drizzle_capabilities_t();
00513   }
00514 
00515   return drizzle_capabilities_t(con->capabilities);
00516 }
00517 
00518 drizzle_charset_t drizzle_con_charset(const drizzle_con_st *con)
00519 {
00520   if (con == NULL)
00521   {
00522     return drizzle_charset_t();
00523   }
00524 
00525   return con->charset;
00526 }
00527 
00528 drizzle_con_status_t drizzle_con_status(const drizzle_con_st *con)
00529 {
00530   if (con == NULL)
00531   {
00532     return drizzle_con_status_t();
00533   }
00534 
00535   return con->status;
00536 }
00537 
00538 uint32_t drizzle_con_max_packet_size(const drizzle_con_st *con)
00539 {
00540   if (con == NULL)
00541   {
00542     return 0;
00543   }
00544 
00545   return con->max_packet_size;
00546 }
00547 
00548 /*
00549  * Client Definitions
00550  */
00551 
00552 drizzle_return_t drizzle_con_connect(drizzle_con_st *con)
00553 {
00554   if (con == NULL)
00555   {
00556     return DRIZZLE_RETURN_INVALID_ARGUMENT;
00557   }
00558 
00559   if (con->options & DRIZZLE_CON_READY)
00560   {
00561     return DRIZZLE_RETURN_OK;
00562   }
00563 
00564   if (drizzle_state_none(con))
00565   {
00566     if (!(con->options & DRIZZLE_CON_RAW_PACKET))
00567     {
00568       drizzle_state_push(con, drizzle_state_handshake_server_read);
00569       drizzle_state_push(con, drizzle_state_packet_read);
00570     }
00571 
00572     drizzle_state_push(con, drizzle_state_connect);
00573     drizzle_state_push(con, drizzle_state_addrinfo);
00574   }
00575 
00576   return drizzle_state_loop(con);
00577 }
00578 
00579 drizzle_result_st *drizzle_con_quit(drizzle_con_st *con,
00580                                     drizzle_result_st *result,
00581                                     drizzle_return_t *ret_ptr)
00582 {
00583   return drizzle_con_command_write(con, result, DRIZZLE_COMMAND_QUIT, NULL, 0,
00584                                    0, ret_ptr);
00585 }
00586 
00587 drizzle_result_st *drizzle_quit(drizzle_con_st *con,
00588                                 drizzle_result_st *result,
00589                                 drizzle_return_t *ret_ptr)
00590 {
00591   return drizzle_con_quit(con, result, ret_ptr);
00592 }
00593 
00594 drizzle_result_st *drizzle_con_select_db(drizzle_con_st *con,
00595                                          drizzle_result_st *result,
00596                                          const char *db,
00597                                          drizzle_return_t *ret_ptr)
00598 {
00599   drizzle_con_set_db(con, db);
00600   return drizzle_con_command_write(con, result, DRIZZLE_COMMAND_INIT_DB,
00601                                    db, strlen(db), strlen(db), ret_ptr);
00602 }
00603 
00604 drizzle_result_st *drizzle_select_db(drizzle_con_st *con,
00605                                      drizzle_result_st *result,
00606                                      const char *db,
00607                                      drizzle_return_t *ret_ptr)
00608 {
00609   return drizzle_con_select_db(con, result, db, ret_ptr);
00610 }
00611 
00612 drizzle_result_st *drizzle_con_shutdown(drizzle_con_st *con,
00613                                         drizzle_result_st *result,
00614                                         drizzle_return_t *ret_ptr)
00615 {
00616   drizzle_return_t unused;
00617   if (ret_ptr == NULL)
00618   {
00619     ret_ptr= &unused;
00620   }
00621 
00622   if (con and con->options & DRIZZLE_CON_MYSQL)
00623   {
00624     return drizzle_con_command_write(con, result, DRIZZLE_COMMAND_SHUTDOWN,
00625                                      "0", 1, 1, ret_ptr);
00626   }
00627 
00628   return drizzle_con_command_write(con, result, DRIZZLE_COMMAND_SHUTDOWN, NULL,
00629                                    0, 0, ret_ptr);
00630 }
00631 
00632 drizzle_result_st *drizzle_shutdown(drizzle_con_st *con,
00633                                     drizzle_result_st *result, uint32_t, // level is unused
00634                                     drizzle_return_t *ret_ptr)
00635 {
00636   return drizzle_con_shutdown(con, result, ret_ptr);
00637 }
00638 
00639 drizzle_result_st *drizzle_kill(drizzle_con_st *con,
00640                                 drizzle_result_st *result,
00641                                 uint32_t query_id,
00642                                 drizzle_return_t *ret_ptr)
00643 {
00644   drizzle_return_t unused;
00645   if (ret_ptr == NULL)
00646   {
00647     ret_ptr= &unused;
00648   }
00649 
00650   uint32_t sent= htonl(query_id);
00651   return drizzle_con_command_write(con, result, DRIZZLE_COMMAND_PROCESS_KILL,
00652                                    &sent, sizeof(uint32_t), sizeof(uint32_t), ret_ptr);
00653 }
00654 
00655 drizzle_result_st *drizzle_con_ping(drizzle_con_st *con,
00656                                     drizzle_result_st *result,
00657                                     drizzle_return_t *ret_ptr)
00658 {
00659   return drizzle_con_command_write(con, result, DRIZZLE_COMMAND_PING, NULL, 0,
00660                                    0, ret_ptr);
00661 }
00662 
00663 drizzle_result_st *drizzle_ping(drizzle_con_st *con,
00664                                 drizzle_result_st *result,
00665                                 drizzle_return_t *ret_ptr)
00666 {
00667   return drizzle_con_ping(con, result, ret_ptr);
00668 }
00669 
00670 drizzle_result_st *drizzle_con_command_write(drizzle_con_st *con,
00671                                              drizzle_result_st *result,
00672                                              drizzle_command_t command,
00673                                              const void *data, size_t size,
00674                                              size_t total,
00675                                              drizzle_return_t *ret_ptr)
00676 {
00677   drizzle_return_t unused;
00678   if (ret_ptr == NULL)
00679   {
00680     ret_ptr= &unused;
00681   }
00682 
00683   if (con == NULL)
00684   {
00685     *ret_ptr= DRIZZLE_RETURN_INVALID_ARGUMENT;
00686     return NULL;
00687   }
00688 
00689   drizzle_result_st *old_result;
00690 
00691   if (!(con->options & DRIZZLE_CON_READY))
00692   {
00693     if (con->options & DRIZZLE_CON_RAW_PACKET)
00694     {
00695       drizzle_set_error(con->drizzle, "drizzle_command_write",
00696                         "connection not ready");
00697       *ret_ptr= DRIZZLE_RETURN_NOT_READY;
00698       return result;
00699     }
00700 
00701     *ret_ptr= drizzle_con_connect(con);
00702     if (*ret_ptr != DRIZZLE_RETURN_OK)
00703       return result;
00704   }
00705 
00706   if (drizzle_state_none(con))
00707   {
00708     if (con->options & (DRIZZLE_CON_RAW_PACKET | DRIZZLE_CON_NO_RESULT_READ))
00709       con->result= NULL;
00710     else
00711     {
00712       for (old_result= con->result_list; old_result != NULL; old_result= old_result->next)
00713       {
00714         if (result == old_result)
00715         {
00716           drizzle_set_error(con->drizzle, "drizzle_command_write", "result struct already in use");
00717           *ret_ptr= DRIZZLE_RETURN_INTERNAL_ERROR;
00718           return result;
00719         }
00720       }
00721 
00722       con->result= drizzle_result_create(con, result);
00723       if (con->result == NULL)
00724       {
00725         *ret_ptr= DRIZZLE_RETURN_MEMORY;
00726         return NULL;
00727       }
00728     }
00729 
00730     con->command= command;
00731     con->command_data= (uint8_t *)data;
00732     con->command_size= size;
00733     con->command_offset= 0;
00734     con->command_total= total;
00735 
00736     drizzle_state_push(con, drizzle_state_command_write);
00737   }
00738   else if (con->command_data == NULL)
00739   {
00740     con->command_data= (uint8_t *)data;
00741     con->command_size= size;
00742   }
00743 
00744   *ret_ptr= drizzle_state_loop(con);
00745   if (*ret_ptr == DRIZZLE_RETURN_PAUSE)
00746     *ret_ptr= DRIZZLE_RETURN_OK;
00747   else if (*ret_ptr != DRIZZLE_RETURN_OK &&
00748            *ret_ptr != DRIZZLE_RETURN_IO_WAIT &&
00749            *ret_ptr != DRIZZLE_RETURN_ERROR_CODE)
00750   {
00751     drizzle_result_free(con->result);
00752     con->result= result;
00753   }
00754 
00755   return con->result;
00756 }
00757 
00758 /*
00759  * Server Definitions
00760  */
00761 
00762 drizzle_return_t drizzle_con_listen(drizzle_con_st *con)
00763 {
00764   if (con == NULL)
00765   {
00766     return DRIZZLE_RETURN_INVALID_ARGUMENT;
00767   }
00768 
00769   if (con->options & DRIZZLE_CON_READY)
00770   {
00771     return DRIZZLE_RETURN_OK;
00772   }
00773 
00774   if (drizzle_state_none(con))
00775   {
00776     drizzle_state_push(con, drizzle_state_listen);
00777     drizzle_state_push(con, drizzle_state_addrinfo);
00778   }
00779 
00780   return drizzle_state_loop(con);
00781 }
00782 
00783 int drizzle_con_backlog(const drizzle_con_st *con)
00784 {
00785   if (con == NULL)
00786   {
00787     return 0;
00788   }
00789 
00790   return con->backlog;
00791 }
00792 
00793 void drizzle_con_set_backlog(drizzle_con_st *con, int backlog)
00794 {
00795   if (con == NULL)
00796   {
00797     return;
00798   }
00799 
00800   con->backlog= backlog;
00801 }
00802 
00803 void drizzle_con_set_protocol_version(drizzle_con_st *con,
00804                                       uint8_t protocol_version)
00805 {
00806   if (con == NULL)
00807   {
00808     return;
00809   }
00810 
00811   con->protocol_version= protocol_version;
00812 }
00813 
00814 void drizzle_con_set_server_version(drizzle_con_st *con,
00815                                     const char *server_version)
00816 {
00817   if (con == NULL)
00818   {
00819     return;
00820   }
00821 
00822   if (server_version == NULL)
00823   {
00824     con->server_version[0]= 0;
00825   }
00826   else
00827   {
00828     strncpy(con->server_version, server_version,
00829             DRIZZLE_MAX_SERVER_VERSION_SIZE);
00830     con->server_version[DRIZZLE_MAX_SERVER_VERSION_SIZE - 1]= 0;
00831   }
00832 }
00833 
00834 void drizzle_con_set_thread_id(drizzle_con_st *con, uint32_t thread_id)
00835 {
00836   if (con == NULL)
00837   {
00838     return;
00839   }
00840 
00841   con->thread_id= thread_id;
00842 }
00843 
00844 void drizzle_con_set_scramble(drizzle_con_st *con, const uint8_t *scramble)
00845 {
00846   if (con == NULL)
00847   {
00848     return;
00849   }
00850 
00851   if (scramble == NULL)
00852   {
00853     con->scramble= NULL;
00854   }
00855   else
00856   {
00857     con->scramble= con->scramble_buffer;
00858     memcpy(con->scramble, scramble, DRIZZLE_MAX_SCRAMBLE_SIZE);
00859   }
00860 }
00861 
00862 void drizzle_con_set_capabilities(drizzle_con_st *con,
00863                                   drizzle_capabilities_t capabilities)
00864 {
00865   if (con == NULL)
00866   {
00867     return;
00868   }
00869 
00870   con->capabilities= capabilities;
00871 }
00872 
00873 void drizzle_con_set_charset(drizzle_con_st *con, drizzle_charset_t charset)
00874 {
00875   if (con == NULL)
00876   {
00877     return;
00878   }
00879 
00880   con->charset= charset;
00881 }
00882 
00883 void drizzle_con_set_status(drizzle_con_st *con, drizzle_con_status_t status)
00884 {
00885   if (con == NULL)
00886   {
00887     return;
00888   }
00889 
00890   con->status= status;
00891 }
00892 
00893 void drizzle_con_set_max_packet_size(drizzle_con_st *con,
00894                                      uint32_t max_packet_size)
00895 {
00896   if (con == NULL)
00897   {
00898     return;
00899   }
00900 
00901   con->max_packet_size= max_packet_size;
00902 }
00903 
00904 void drizzle_con_copy_handshake(drizzle_con_st *con, drizzle_con_st *from)
00905 {
00906   drizzle_con_set_auth(con, from->user, NULL);
00907   drizzle_con_set_scramble(con, from->scramble);
00908   drizzle_con_set_db(con, from->db);
00909   drizzle_con_set_protocol_version(con, from->protocol_version);
00910   drizzle_con_set_server_version(con, from->server_version);
00911   drizzle_con_set_thread_id(con, from->thread_id);
00912   drizzle_con_set_scramble(con, from->scramble);
00913   drizzle_con_set_capabilities(con, drizzle_capabilities_t(from->capabilities));
00914   drizzle_con_set_charset(con, from->charset);
00915   drizzle_con_set_status(con, from->status);
00916   drizzle_con_set_max_packet_size(con, from->max_packet_size);
00917 }
00918 
00919 void *drizzle_con_command_read(drizzle_con_st *con,
00920                                drizzle_command_t *command, size_t *offset,
00921                                size_t *size, size_t *total,
00922                                drizzle_return_t *ret_ptr)
00923 {
00924   drizzle_return_t unused_ret;
00925   if (ret_ptr == NULL)
00926   {
00927     ret_ptr= &unused_ret;
00928   }
00929 
00930   if (con == NULL)
00931   {
00932     *ret_ptr= DRIZZLE_RETURN_INVALID_ARGUMENT;
00933     return NULL;
00934   }
00935 
00936   if (drizzle_state_none(con))
00937   {
00938     con->packet_number= 0;
00939     con->command_offset= 0;
00940     con->command_total= 0;
00941 
00942     drizzle_state_push(con, drizzle_state_command_read);
00943     drizzle_state_push(con, drizzle_state_packet_read);
00944   }
00945 
00946   if (offset)
00947   {
00948     *offset= con->command_offset;
00949   }
00950 
00951   *ret_ptr= drizzle_state_loop(con);
00952   if (*ret_ptr == DRIZZLE_RETURN_PAUSE)
00953   {
00954     *ret_ptr= DRIZZLE_RETURN_OK;
00955   }
00956 
00957   if (command)
00958   {
00959     *command= con->command;
00960   }
00961 
00962   if (size)
00963   {
00964     *size= con->command_size;
00965   }
00966 
00967   if (total)
00968   {
00969     *total= con->command_total;
00970   }
00971 
00972   return con->command_data;
00973 }
00974 
00975 void *drizzle_con_command_buffer(drizzle_con_st *con,
00976                                  drizzle_command_t *command, size_t *total,
00977                                  drizzle_return_t *ret_ptr)
00978 {
00979   size_t offset= 0;
00980   size_t size= 0;
00981 
00982   drizzle_return_t unused_ret;
00983   if (ret_ptr == NULL)
00984   {
00985     ret_ptr= &unused_ret;
00986   }
00987 
00988   size_t unused_total;
00989   if (total == NULL)
00990   {
00991     total= &unused_total;
00992   }
00993 
00994   if (con == NULL)
00995   {
00996     *ret_ptr= DRIZZLE_RETURN_INVALID_ARGUMENT;
00997     return NULL;
00998   }
00999 
01000   char *command_data= (char *)drizzle_con_command_read(con, command, &offset, &size, total, ret_ptr);
01001   if (*ret_ptr != DRIZZLE_RETURN_OK)
01002   {
01003     return NULL;
01004   }
01005 
01006   if (command_data == NULL)
01007   {
01008     *total= 0;
01009     return NULL;
01010   }
01011 
01012   if (con->command_buffer == NULL)
01013   {
01014     con->command_buffer= (uint8_t*)realloc(NULL, (*total) +1);
01015     if (con->command_buffer == NULL)
01016     {
01017       drizzle_set_error(con->drizzle, __func__, "Failed to allocate.");
01018       *ret_ptr= DRIZZLE_RETURN_MEMORY;
01019       return NULL;
01020     }
01021   }
01022 
01023   memcpy(con->command_buffer + offset, command_data, size);
01024 
01025   while ((offset + size) != (*total))
01026   {
01027     command_data= (char *)drizzle_con_command_read(con, command, &offset, &size, total, ret_ptr);
01028     if (*ret_ptr != DRIZZLE_RETURN_OK)
01029     {
01030       return NULL;
01031     }
01032 
01033     memcpy(con->command_buffer + offset, command_data, size);
01034   }
01035 
01036   command_data= (char *)con->command_buffer;
01037   con->command_buffer= NULL;
01038   command_data[*total]= 0;
01039 
01040   return command_data;
01041 }
01042 
01043 /*
01044  * Local Definitions
01045  */
01046 
01047 void drizzle_con_reset_addrinfo(drizzle_con_st *con)
01048 {
01049   if (con == NULL)
01050   {
01051     return;
01052   }
01053 
01054   switch (con->socket_type)
01055   {
01056   case DRIZZLE_CON_SOCKET_TCP:
01057     if (con->socket.tcp.addrinfo != NULL)
01058     {
01059       freeaddrinfo(con->socket.tcp.addrinfo);
01060       con->socket.tcp.addrinfo= NULL;
01061     }
01062     break;
01063 
01064   case DRIZZLE_CON_SOCKET_UDS:
01065     con->socket.uds.addrinfo.ai_addr= NULL;
01066     break;
01067 
01068   default:
01069     break;
01070   }
01071 
01072   con->addrinfo_next= NULL;
01073 }
01074 
01075 /*
01076  * State Definitions
01077  */
01078 
01079 drizzle_return_t drizzle_state_addrinfo(drizzle_con_st *con)
01080 {
01081   drizzle_con_tcp_st *tcp;
01082   const char *host;
01083   char port[NI_MAXSERV];
01084   struct addrinfo ai;
01085   int ret;
01086 
01087   if (con == NULL)
01088   {
01089     return DRIZZLE_RETURN_INVALID_ARGUMENT;
01090   }
01091 
01092   drizzle_log_debug(con->drizzle, __func__);
01093 
01094   switch (con->socket_type)
01095   {
01096   case DRIZZLE_CON_SOCKET_TCP:
01097     tcp= &(con->socket.tcp);
01098 
01099     if (tcp->addrinfo != NULL)
01100     {
01101       freeaddrinfo(tcp->addrinfo);
01102       tcp->addrinfo= NULL;
01103     }
01104 
01105     if (tcp->port != 0)
01106     {
01107       snprintf(port, NI_MAXSERV, "%u", tcp->port);
01108     }
01109     else if (con->options & DRIZZLE_CON_MYSQL)
01110     {
01111       snprintf(port, NI_MAXSERV, "%u", DRIZZLE_DEFAULT_TCP_PORT_MYSQL);
01112     }
01113     else
01114     {
01115       snprintf(port, NI_MAXSERV, "%u", DRIZZLE_DEFAULT_TCP_PORT);
01116     }
01117     port[NI_MAXSERV-1]= 0;
01118 
01119     memset(&ai, 0, sizeof(struct addrinfo));
01120     ai.ai_socktype= SOCK_STREAM;
01121     ai.ai_protocol= IPPROTO_TCP;
01122     ai.ai_flags = AI_PASSIVE;
01123     ai.ai_family = AF_UNSPEC;
01124 
01125     if (con->options & DRIZZLE_CON_LISTEN)
01126     {
01127       host= tcp->host;
01128     }
01129     else
01130     {
01131       if (tcp->host == NULL)
01132       {
01133         host= DRIZZLE_DEFAULT_TCP_HOST;
01134       }
01135       else
01136       {
01137         host= tcp->host;
01138       }
01139     }
01140 
01141     ret= getaddrinfo(host, port, &ai, &(tcp->addrinfo));
01142     if (ret != 0)
01143     {
01144       drizzle_set_error(con->drizzle, "drizzle_state_addrinfo", "getaddrinfo:%s", gai_strerror(ret));
01145       return DRIZZLE_RETURN_GETADDRINFO;
01146     }
01147 
01148     con->addrinfo_next= tcp->addrinfo;
01149 
01150     break;
01151 
01152   case DRIZZLE_CON_SOCKET_UDS:
01153     con->addrinfo_next= &(con->socket.uds.addrinfo);
01154     break;
01155 
01156   default:
01157     break;
01158   }
01159 
01160   drizzle_state_pop(con);
01161   return DRIZZLE_RETURN_OK;
01162 }
01163 
01164 drizzle_return_t drizzle_state_connect(drizzle_con_st *con)
01165 {
01166   int ret;
01167   drizzle_return_t dret;
01168 
01169   if (con == NULL)
01170   {
01171     return DRIZZLE_RETURN_INVALID_ARGUMENT;
01172   }
01173 
01174   drizzle_log_debug(con->drizzle, "drizzle_state_connect");
01175 
01176   if (con->fd != -1)
01177   {
01178     (void)closesocket(con->fd);
01179     con->fd= -1;
01180   }
01181 
01182   if (con->addrinfo_next == NULL)
01183   {
01184     drizzle_set_error(con->drizzle, __func__, "could not connect");
01185     drizzle_state_reset(con);
01186     return DRIZZLE_RETURN_COULD_NOT_CONNECT;
01187   }
01188 
01189   con->fd= socket(con->addrinfo_next->ai_family,
01190                   con->addrinfo_next->ai_socktype,
01191                   con->addrinfo_next->ai_protocol);
01192   if (con->fd == -1)
01193   {
01194     drizzle_set_error(con->drizzle, __func__, "socket:%s", strerror(errno));
01195     con->drizzle->last_errno= errno;
01196     return DRIZZLE_RETURN_COULD_NOT_CONNECT;
01197   }
01198 
01199   dret= _con_setsockopt(con);
01200   if (dret != DRIZZLE_RETURN_OK)
01201   {
01202     con->drizzle->last_errno= errno;
01203     return DRIZZLE_RETURN_COULD_NOT_CONNECT;
01204   }
01205 
01206   while (1)
01207   {
01208     ret= connect(con->fd, con->addrinfo_next->ai_addr,
01209                  con->addrinfo_next->ai_addrlen);
01210 
01211 #ifdef _WIN32
01212     errno = WSAGetLastError();
01213     switch(errno) {
01214     case WSAEINVAL:
01215     case WSAEALREADY:
01216     case WSAEWOULDBLOCK:
01217       errno= EINPROGRESS;
01218       break;
01219     case WSAECONNREFUSED:
01220       errno= ECONNREFUSED;
01221       break;
01222     case WSAENETUNREACH:
01223       errno= ENETUNREACH;
01224       break;
01225     case WSAETIMEDOUT:
01226       errno= ETIMEDOUT;
01227       break;
01228     case WSAECONNRESET:
01229       errno= ECONNRESET;
01230       break;
01231     case WSAEADDRINUSE:
01232       errno= EADDRINUSE;
01233       break;
01234     case WSAEOPNOTSUPP:
01235       errno= EOPNOTSUPP;
01236       break;
01237     case WSAENOPROTOOPT:
01238       errno= ENOPROTOOPT;
01239       break;
01240     default:
01241       break;
01242     }
01243 #endif /* _WIN32 */
01244   
01245     drizzle_log_crazy(con->drizzle, "connect return=%d errno=%s", ret, strerror(errno));
01246 
01247     if (ret == 0)
01248     {
01249       con->addrinfo_next= NULL;
01250       break;
01251     }
01252 
01253     if (errno == EAGAIN || errno == EINTR)
01254     {
01255       continue;
01256     }
01257 
01258     if (errno == EINPROGRESS)
01259     {
01260       drizzle_state_pop(con);
01261       drizzle_state_push(con, drizzle_state_connecting);
01262       return DRIZZLE_RETURN_OK;
01263     }
01264 
01265     if (errno == ECONNREFUSED || errno == ENETUNREACH || errno == ETIMEDOUT)
01266     {
01267       con->addrinfo_next= con->addrinfo_next->ai_next;
01268       return DRIZZLE_RETURN_OK;
01269     }
01270 
01271     drizzle_set_error(con->drizzle, __func__, "connect:%s", strerror(errno));
01272     con->drizzle->last_errno= errno;
01273     return DRIZZLE_RETURN_COULD_NOT_CONNECT;
01274   }
01275 
01276   drizzle_state_pop(con);
01277 
01278   return DRIZZLE_RETURN_OK;
01279 }
01280 
01281 drizzle_return_t drizzle_state_connecting(drizzle_con_st *con)
01282 {
01283   drizzle_return_t ret;
01284 
01285   if (con == NULL)
01286   {
01287     return DRIZZLE_RETURN_INVALID_ARGUMENT;
01288   }
01289 
01290   drizzle_log_debug(con->drizzle, "drizzle_state_connecting");
01291 
01292   while (1)
01293   {
01294     int error;
01295     if (con->revents & POLLOUT)
01296     {
01297       drizzle_state_pop(con);
01298       return DRIZZLE_RETURN_OK;
01299       socklen_t error_length= sizeof(error);
01300       int getsockopt_error;
01301       if ((getsockopt_error= getsockopt(con->fd, SOL_SOCKET, SO_ERROR, (void*)&error, &error_length)) < 1)
01302       {
01303         drizzle_set_error(con->drizzle, __func__, strerror(getsockopt_error));
01304         return DRIZZLE_RETURN_COULD_NOT_CONNECT;
01305       }
01306 
01307       if (error == 0)
01308       {
01309         drizzle_state_pop(con);
01310         return DRIZZLE_RETURN_OK;
01311       }
01312     }
01313     else if (con->revents & (POLLERR | POLLHUP | POLLNVAL))
01314     {
01315       error= 1;
01316     }
01317 
01318     if (error)
01319     {
01320       con->revents= 0;
01321       drizzle_state_pop(con);
01322       drizzle_state_push(con, drizzle_state_connect);
01323       con->addrinfo_next= con->addrinfo_next->ai_next;
01324       return DRIZZLE_RETURN_OK;
01325     }
01326 
01327     ret= drizzle_con_set_events(con, POLLOUT);
01328     if (ret != DRIZZLE_RETURN_OK)
01329     {
01330       return ret;
01331     }
01332 
01333     if (con->drizzle->options & DRIZZLE_NON_BLOCKING)
01334     {
01335       return DRIZZLE_RETURN_IO_WAIT;
01336     }
01337 
01338     ret= drizzle_con_wait(con->drizzle);
01339     if (ret != DRIZZLE_RETURN_OK)
01340     {
01341       return ret;
01342     }
01343   }
01344 }
01345 
01346 drizzle_return_t drizzle_state_read(drizzle_con_st *con)
01347 {
01348   drizzle_return_t ret;
01349   ssize_t read_size;
01350 
01351   if (con == NULL)
01352   {
01353     return DRIZZLE_RETURN_INVALID_ARGUMENT;
01354   }
01355 
01356   drizzle_log_debug(con->drizzle, "drizzle_state_read");
01357 
01358   if (con->buffer_size == 0)
01359     con->buffer_ptr= con->buffer;
01360   else if ((con->buffer_ptr - con->buffer) > (DRIZZLE_MAX_BUFFER_SIZE / 2))
01361   {
01362     memmove(con->buffer, con->buffer_ptr, con->buffer_size);
01363     con->buffer_ptr= con->buffer;
01364   }
01365 
01366   if ((con->revents & POLLIN) == 0 &&
01367       (con->drizzle->options & DRIZZLE_NON_BLOCKING))
01368   {
01369     /* non-blocking mode: return IO_WAIT instead of attempting to read. This
01370      * avoids reading immediately after writing a command, which typically
01371      * returns EAGAIN. This improves performance. */
01372     ret= drizzle_con_set_events(con, POLLIN);
01373     if (ret != DRIZZLE_RETURN_OK)
01374       return ret;
01375     return DRIZZLE_RETURN_IO_WAIT;
01376   }
01377 
01378   while (1)
01379   {
01380     size_t available_buffer= (size_t)DRIZZLE_MAX_BUFFER_SIZE -
01381         ((size_t)(con->buffer_ptr - con->buffer) + con->buffer_size);
01382     read_size = recv(con->fd, (char *)con->buffer_ptr + con->buffer_size,
01383                      available_buffer, 0);
01384 #ifdef _WIN32
01385     errno = WSAGetLastError();
01386     switch(errno) {
01387     case WSAENOTCONN:
01388     case WSAEWOULDBLOCK:
01389       errno= EAGAIN;
01390       break;
01391     case WSAEINVAL:
01392     case WSAEALREADY:
01393       errno= EINPROGRESS;
01394       break;
01395     case WSAECONNREFUSED:
01396       errno= ECONNREFUSED;
01397       break;
01398     case WSAENETUNREACH:
01399       errno= ENETUNREACH;
01400       break;
01401     case WSAETIMEDOUT:
01402       errno= ETIMEDOUT;
01403       break;
01404     case WSAECONNRESET:
01405       errno= ECONNRESET;
01406       break;
01407     case WSAEADDRINUSE:
01408       errno= EADDRINUSE;
01409       break;
01410     case WSAEOPNOTSUPP:
01411       errno= EOPNOTSUPP;
01412       break;
01413     case WSAENOPROTOOPT:
01414       errno= ENOPROTOOPT;
01415       break;
01416     default:
01417       break;
01418     }
01419 #endif /* _WIN32 */ 
01420     drizzle_log_crazy(con->drizzle, "read fd=%d return=%zd errno=%s", con->fd,
01421                       read_size, strerror(errno));
01422 
01423     if (read_size == 0)
01424     {
01425       drizzle_set_error(con->drizzle, "drizzle_state_read",
01426                         "lost connection to server (EOF)");
01427       return DRIZZLE_RETURN_LOST_CONNECTION;
01428     }
01429     else if (read_size == -1)
01430     {
01431       if (errno == EAGAIN)
01432       {
01433         /* clear the read ready flag */
01434         con->revents&= ~POLLIN;
01435         ret= drizzle_con_set_events(con, POLLIN);
01436         if (ret != DRIZZLE_RETURN_OK)
01437           return ret;
01438 
01439         if (con->drizzle->options & DRIZZLE_NON_BLOCKING)
01440           return DRIZZLE_RETURN_IO_WAIT;
01441 
01442         ret= drizzle_con_wait(con->drizzle);
01443         if (ret != DRIZZLE_RETURN_OK)
01444           return ret;
01445 
01446         continue;
01447       }
01448       else if (errno == ECONNREFUSED)
01449       {
01450         con->revents= 0;
01451         drizzle_state_pop(con);
01452         drizzle_state_push(con, drizzle_state_connect);
01453         con->addrinfo_next= con->addrinfo_next->ai_next;
01454         return DRIZZLE_RETURN_OK;
01455       }
01456       else if (errno == EINTR)
01457       {
01458         continue;
01459       }
01460       else if (errno == EPIPE || errno == ECONNRESET)
01461       {
01462         drizzle_set_error(con->drizzle, __func__,
01463                           "lost connection to server (%s)", strerror(errno));
01464         return DRIZZLE_RETURN_LOST_CONNECTION;
01465       }
01466 
01467       drizzle_set_error(con->drizzle, __func__, "read:%s", strerror(errno));
01468       con->drizzle->last_errno= errno;
01469       return DRIZZLE_RETURN_ERRNO;
01470     }
01471 
01472     /* clear the "read ready" flag if we read all available data. */
01473     if ((size_t) read_size < available_buffer)
01474     {
01475       con->revents&= ~POLLIN;
01476     }
01477     con->buffer_size+= (size_t)read_size;
01478     break;
01479   }
01480 
01481   drizzle_state_pop(con);
01482 
01483   return DRIZZLE_RETURN_OK;
01484 }
01485 
01486 drizzle_return_t drizzle_state_write(drizzle_con_st *con)
01487 {
01488   drizzle_return_t ret;
01489   ssize_t write_size;
01490 
01491   if (con == NULL)
01492   {
01493     return DRIZZLE_RETURN_INVALID_ARGUMENT;
01494   }
01495 
01496   drizzle_log_debug(con->drizzle, "drizzle_state_write");
01497 
01498   while (con->buffer_size != 0)
01499   {
01500   
01501     write_size = send(con->fd,(char *) con->buffer_ptr, con->buffer_size, 0);
01502 
01503 #ifdef _WIN32
01504     errno = WSAGetLastError();
01505     switch(errno) {
01506     case WSAENOTCONN:
01507     case WSAEWOULDBLOCK:
01508       errno= EAGAIN;
01509       break;
01510     case WSAEINVAL:
01511     case WSAEALREADY:
01512       errno= EINPROGRESS;
01513       break;
01514     case WSAECONNREFUSED:
01515       errno= ECONNREFUSED;
01516       break;
01517     case WSAENETUNREACH:
01518       errno= ENETUNREACH;
01519       break;
01520     case WSAETIMEDOUT:
01521       errno= ETIMEDOUT;
01522       break;
01523     case WSAECONNRESET:
01524       errno= ECONNRESET;
01525       break;
01526     case WSAEADDRINUSE:
01527       errno= EADDRINUSE;
01528       break;
01529     case WSAEOPNOTSUPP:
01530       errno= EOPNOTSUPP;
01531       break;
01532     case WSAENOPROTOOPT:
01533       errno= ENOPROTOOPT;
01534       break;
01535     default:
01536       break;
01537     }
01538 #endif /* _WIN32 */ 
01539 
01540     drizzle_log_crazy(con->drizzle, "write fd=%d return=%zd errno=%s", con->fd,
01541                       write_size, strerror(errno));
01542 
01543     if (write_size == 0)
01544     {
01545       drizzle_set_error(con->drizzle, __func__, "lost connection to server (EOF)");
01546       return DRIZZLE_RETURN_LOST_CONNECTION;
01547     }
01548     else if (write_size == -1)
01549     {
01550       if (errno == EAGAIN)
01551       {
01552         ret= drizzle_con_set_events(con, POLLOUT);
01553         if (ret != DRIZZLE_RETURN_OK)
01554           return ret;
01555 
01556         if (con->drizzle->options & DRIZZLE_NON_BLOCKING)
01557           return DRIZZLE_RETURN_IO_WAIT;
01558 
01559         ret= drizzle_con_wait(con->drizzle);
01560         if (ret != DRIZZLE_RETURN_OK)
01561           return ret;
01562 
01563         continue;
01564       }
01565       else if (errno == EINTR)
01566       {
01567         continue;
01568       }
01569       else if (errno == EPIPE || errno == ECONNRESET)
01570       {
01571         drizzle_set_error(con->drizzle, __func__, "lost connection to server (%s)", strerror(errno));
01572         return DRIZZLE_RETURN_LOST_CONNECTION;
01573       }
01574 
01575       drizzle_set_error(con->drizzle, "drizzle_state_write", "write:%s", strerror(errno));
01576       con->drizzle->last_errno= errno;
01577       return DRIZZLE_RETURN_ERRNO;
01578     }
01579 
01580     con->buffer_ptr+= write_size;
01581     con->buffer_size-= (size_t)write_size;
01582     if (con->buffer_size == 0)
01583       break;
01584   }
01585 
01586   con->buffer_ptr= con->buffer;
01587 
01588   drizzle_state_pop(con);
01589 
01590   return DRIZZLE_RETURN_OK;
01591 }
01592 
01593 drizzle_return_t drizzle_state_listen(drizzle_con_st *con)
01594 {
01595   char host[NI_MAXHOST];
01596   char port[NI_MAXSERV];
01597   int fd;
01598   int opt;
01599   drizzle_con_st *new_con;
01600 
01601   if (con == NULL)
01602   {
01603     return DRIZZLE_RETURN_INVALID_ARGUMENT;
01604   }
01605 
01606   for (; con->addrinfo_next != NULL;
01607        con->addrinfo_next= con->addrinfo_next->ai_next)
01608   {
01609     int ret= getnameinfo(con->addrinfo_next->ai_addr,
01610                          con->addrinfo_next->ai_addrlen, host, NI_MAXHOST, port,
01611                          NI_MAXSERV, NI_NUMERICHOST | NI_NUMERICSERV);
01612     if (ret != 0)
01613     {
01614       drizzle_set_error(con->drizzle, __func__, "getnameinfo:%s", gai_strerror(ret));
01615       return DRIZZLE_RETURN_GETADDRINFO;
01616     }
01617 
01618     /* Call to socket() can fail for some getaddrinfo results, try another. */
01619     fd= socket(con->addrinfo_next->ai_family, con->addrinfo_next->ai_socktype,
01620                con->addrinfo_next->ai_protocol);
01621     if (fd == -1)
01622     {
01623       drizzle_log_info(con->drizzle, "could not listen on %s:%s", host, port);
01624       drizzle_set_error(con->drizzle, __func__, "socket:%s", strerror(errno));
01625       continue;
01626     }
01627   
01628   opt= 1;
01629 #ifdef _WIN32
01630         ret= setsockopt(fd, SOL_SOCKET, SO_REUSEADDR,(const char*) &opt, sizeof(opt));
01631 #else
01632         ret= setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt));
01633 #endif /* _WIN32 */
01634     if (ret == -1)
01635     {
01636       closesocket(fd);
01637       drizzle_set_error(con->drizzle, __func__, "setsockopt:%s", strerror(errno));
01638       return DRIZZLE_RETURN_COULD_NOT_CONNECT;
01639     }
01640 
01641     ret= bind(fd, con->addrinfo_next->ai_addr, con->addrinfo_next->ai_addrlen);
01642     if (ret == -1)
01643     {
01644       closesocket(fd);
01645       drizzle_set_error(con->drizzle, __func__, "bind:%s", strerror(errno));
01646       if (errno == EADDRINUSE)
01647       {
01648         if (con->fd == -1)
01649         {
01650           drizzle_log_info(con->drizzle, "could not listen on %s:%s", host,
01651                            port);
01652         }
01653 
01654         continue;
01655       }
01656 
01657       return DRIZZLE_RETURN_ERRNO;
01658     }
01659 
01660     if (listen(fd, con->backlog) == -1)
01661     {
01662       closesocket(fd);
01663       drizzle_set_error(con->drizzle, __func__, "listen:%s", strerror(errno));
01664       return DRIZZLE_RETURN_COULD_NOT_CONNECT;
01665     }
01666 
01667     if (con->fd == -1)
01668     {
01669       con->fd= fd;
01670       new_con= con;
01671     }
01672     else
01673     {
01674       new_con= drizzle_con_clone(con->drizzle, NULL, con);
01675       if (new_con == NULL)
01676       {
01677         closesocket(fd);
01678         return DRIZZLE_RETURN_MEMORY;
01679       }
01680 
01681       new_con->fd= fd;
01682     }
01683 
01684     /* Wait for read events on the listening socket. */
01685     drizzle_return_t local_ret= drizzle_con_set_events(new_con, POLLIN);
01686     if (local_ret != DRIZZLE_RETURN_OK)
01687     {
01688       drizzle_con_free(new_con);
01689       return local_ret;
01690     }
01691 
01692     drizzle_log_info(con->drizzle, "listening on %s:%s", host, port);
01693   }
01694 
01695   /* Report last socket() error if we couldn't find an address to bind. */
01696   if (con->fd == -1)
01697   {
01698     return DRIZZLE_RETURN_COULD_NOT_CONNECT;
01699   }
01700 
01701   drizzle_state_pop(con);
01702 
01703   return DRIZZLE_RETURN_OK;
01704 }
01705 
01706 /*
01707  * Static Definitions
01708  */
01709 
01710 static drizzle_return_t _con_setsockopt(drizzle_con_st *con)
01711 {
01712   struct linger linger;
01713   struct timeval waittime;
01714 
01715   assert(con);
01716 
01717   int ret= 1;
01718 
01719 #ifdef _WIN32
01720   ret= setsockopt(con->fd, IPPROTO_TCP, TCP_NODELAY, (const char*)&ret, (socklen_t)sizeof(int));
01721 #else
01722   ret= setsockopt(con->fd, IPPROTO_TCP, TCP_NODELAY, &ret, (socklen_t)sizeof(int));
01723 #endif /* _WIN32 */
01724 
01725   if (ret == -1 && errno != EOPNOTSUPP)
01726   {
01727     drizzle_set_error(con->drizzle, __func__, "setsockopt:TCP_NODELAY:%s", strerror(errno));
01728     return DRIZZLE_RETURN_ERRNO;
01729   }
01730 
01731   linger.l_onoff= 1;
01732   linger.l_linger= DRIZZLE_DEFAULT_SOCKET_TIMEOUT;
01733 
01734 #ifdef _WIN32
01735   ret= setsockopt(con->fd, SOL_SOCKET, SO_LINGER, (const char*)&linger,
01736                   (socklen_t)sizeof(struct linger));
01737 #else
01738   ret= setsockopt(con->fd, SOL_SOCKET, SO_LINGER, &linger,
01739                   (socklen_t)sizeof(struct linger));
01740 #endif /* _WIN32 */
01741 
01742   if (ret == -1)
01743   {
01744     drizzle_set_error(con->drizzle, __func__, "setsockopt:SO_LINGER:%s", strerror(errno));
01745     return DRIZZLE_RETURN_ERRNO;
01746   }
01747 
01748   waittime.tv_sec= DRIZZLE_DEFAULT_SOCKET_TIMEOUT;
01749   waittime.tv_usec= 0;
01750 
01751 #ifdef _WIN32
01752   ret= setsockopt(con->fd, SOL_SOCKET, SO_SNDTIMEO, (const char*)&waittime,
01753                   (socklen_t)sizeof(struct timeval));
01754 #else
01755   ret= setsockopt(con->fd, SOL_SOCKET, SO_SNDTIMEO, &waittime,
01756                   (socklen_t)sizeof(struct timeval));
01757 #endif /* _WIN32 */
01758 
01759   if (ret == -1 && errno != ENOPROTOOPT)
01760   {
01761     drizzle_set_error(con->drizzle, __func__, "setsockopt:SO_SNDTIMEO:%s", strerror(errno));
01762     return DRIZZLE_RETURN_ERRNO;
01763   }
01764 
01765 #ifdef _WIN32
01766   ret= setsockopt(con->fd, SOL_SOCKET, SO_RCVTIMEO, (const char*)&waittime,
01767                   (socklen_t)sizeof(struct timeval));
01768 #else
01769   ret= setsockopt(con->fd, SOL_SOCKET, SO_RCVTIMEO, &waittime,
01770                   (socklen_t)sizeof(struct timeval));
01771 #endif /* _WIN32 */
01772 
01773   if (ret == -1 && errno != ENOPROTOOPT)
01774   {
01775     drizzle_set_error(con->drizzle, __func__,
01776                       "setsockopt:SO_RCVTIMEO:%s", strerror(errno));
01777     return DRIZZLE_RETURN_ERRNO;
01778   }
01779 
01780   ret= DRIZZLE_DEFAULT_SOCKET_SEND_SIZE;
01781 #ifdef _WIN32
01782   ret= setsockopt(con->fd, SOL_SOCKET, SO_SNDBUF, (const char*)&ret, (socklen_t)sizeof(int));
01783 #else
01784   ret= setsockopt(con->fd, SOL_SOCKET, SO_SNDBUF, &ret, (socklen_t)sizeof(int));
01785 #endif /* _WIN32 */
01786   if (ret == -1)
01787   {
01788     drizzle_set_error(con->drizzle, __func__, "setsockopt:SO_SNDBUF:%s", strerror(errno));
01789     return DRIZZLE_RETURN_ERRNO;
01790   }
01791 
01792   ret= DRIZZLE_DEFAULT_SOCKET_RECV_SIZE;
01793 #ifdef _WIN32
01794   ret= setsockopt(con->fd, SOL_SOCKET, SO_RCVBUF, (const char*)&ret, (socklen_t)sizeof(int));
01795 #else
01796   ret= setsockopt(con->fd, SOL_SOCKET, SO_RCVBUF, &ret, (socklen_t)sizeof(int));
01797 #endif /* _WIN32 */
01798   if (ret == -1)
01799   {
01800     drizzle_set_error(con->drizzle, __func__, "setsockopt:SO_RCVBUF:%s", strerror(errno));
01801     return DRIZZLE_RETURN_ERRNO;
01802   }
01803 
01804 #if defined (_WIN32)
01805   {
01806     unsigned long asyncmode;
01807     asyncmode= 1;
01808     ioctlsocket(con->fd, FIONBIO, &asyncmode);
01809   }
01810 #else
01811   ret= fcntl(con->fd, F_GETFL, 0);
01812   if (ret == -1)
01813   {
01814     drizzle_set_error(con->drizzle, __func__, "fcntl:F_GETFL:%s", strerror(errno));
01815     return DRIZZLE_RETURN_ERRNO;
01816   }
01817 
01818   ret= fcntl(con->fd, F_SETFL, ret | O_NONBLOCK);
01819   if (ret == -1)
01820   {
01821     drizzle_set_error(con->drizzle, __func__, "fcntl:F_SETFL:%s", strerror(errno));
01822     return DRIZZLE_RETURN_ERRNO;
01823   }
01824 #endif
01825 
01826   return DRIZZLE_RETURN_OK;
01827 }