Drizzled Public API Documentation

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