00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00016 #include "common.h"
00017
00018
00019
00020
00021
00031 static drizzle_return_t _con_setsockopt(drizzle_con_st *con);
00032
00035
00036
00037
00038
00039 drizzle_con_st *drizzle_con_create(drizzle_st *drizzle, drizzle_con_st *con)
00040 {
00041 if (con == NULL)
00042 {
00043 con= malloc(sizeof(drizzle_con_st));
00044 if (con == NULL)
00045 {
00046 if (drizzle != NULL)
00047 DRIZZLE_ERROR_SET(drizzle, "drizzle_con_create", "malloc")
00048 return NULL;
00049 }
00050
00051 con->options= DRIZZLE_CON_ALLOCATED;
00052 }
00053 else
00054 con->options= 0;
00055
00056 if (drizzle == NULL)
00057 {
00058 drizzle= drizzle_create(NULL);
00059 if (drizzle == NULL)
00060 {
00061 if (con->options & DRIZZLE_CON_ALLOCATED)
00062 free(con);
00063 return NULL;
00064 }
00065
00066 drizzle->options|= DRIZZLE_AUTO_ALLOCATED;
00067 }
00068
00069 con->drizzle= drizzle;
00070
00071 if (drizzle->con_list)
00072 drizzle->con_list->prev= con;
00073 con->next= drizzle->con_list;
00074 con->prev= NULL;
00075 drizzle->con_list= con;
00076 drizzle->con_count++;
00077
00078 con->result_list= NULL;
00079 con->result_count= 0;
00080 con->data= NULL;
00081 con->data_free_fn= NULL;
00082 con->query= NULL;
00083 strncpy(con->user, DRIZZLE_DEFAULT_USER, DRIZZLE_MAX_USER_SIZE);
00084 con->user[DRIZZLE_MAX_USER_SIZE - 1]= 0;
00085 con->password[0]= 0;
00086 con->db[0]= 0;
00087 con->host[0]= 0;
00088 con->port= 0;
00089 con->tcp_addrinfo= NULL;
00090 con->uds_addrinfo.ai_addr= NULL;
00091 con->addrinfo_next= NULL;
00092 drizzle_con_set_tcp(con, NULL, 0);
00093 DRIZZLE_STATE_RESET(con)
00094 con->fd= -1;
00095 con->events= 0;
00096 con->revents= 0;
00097 con->buffer_ptr= con->buffer;
00098 con->buffer_size= 0;
00099 con->packet_size= 0;
00100 con->packet_number= 0;
00101 con->protocol_version= 0;
00102 con->server_version[0]= 0;
00103 con->thread_id= 0;
00104 con->scramble= NULL;
00105 con->capabilities= DRIZZLE_CAPABILITIES_NONE;
00106 con->charset= 0;
00107 con->status= DRIZZLE_CON_STATUS_NONE;
00108 con->max_packet_size= DRIZZLE_MAX_PACKET_SIZE;
00109 con->command= 0;
00110 con->command_data= NULL;
00111 con->command_buffer= NULL;
00112 con->command_size= 0;
00113 con->command_offset= 0;
00114 con->command_total= 0;
00115
00116 return con;
00117 }
00118
00119 drizzle_con_st *drizzle_con_clone(drizzle_st *drizzle, drizzle_con_st *con,
00120 drizzle_con_st *from)
00121 {
00122 if (drizzle == NULL)
00123 drizzle= from->drizzle;
00124
00125 con= drizzle_con_create(drizzle, con);
00126 if (con == NULL)
00127 return NULL;
00128
00129 con->options|= (from->options &
00130 (drizzle_con_options_t)~DRIZZLE_CON_ALLOCATED);
00131 strcpy(con->user, from->user);
00132 strcpy(con->password, from->password);
00133 strcpy(con->db, from->db);
00134
00135 if (drizzle_con_uses_uds(con))
00136 drizzle_con_clone_uds(con, from);
00137 else
00138 {
00139 strcpy(con->host, from->host);
00140 con->port= from->port;
00141 }
00142
00143 return con;
00144 }
00145
00146 void drizzle_con_free(drizzle_con_st *con)
00147 {
00148 drizzle_result_st *result;
00149
00150 if (con->data != NULL && con->data_free_fn != NULL)
00151 (*(con->data_free_fn))(con, (void *)(con->data));
00152
00153 for (result= con->result_list; result != NULL; result= con->result_list)
00154 drizzle_result_free(result);
00155
00156 if (con->fd != -1)
00157 drizzle_con_close(con);
00158
00159 drizzle_con_reset_addrinfo(con);
00160
00161 if (con->drizzle->con_list == con)
00162 con->drizzle->con_list= con->next;
00163 if (con->prev)
00164 con->prev->next= con->next;
00165 if (con->next)
00166 con->next->prev= con->prev;
00167 con->drizzle->con_count--;
00168
00169 if (con->drizzle->con_count == 0 &&
00170 con->drizzle->options & DRIZZLE_AUTO_ALLOCATED)
00171 {
00172 drizzle_free(con->drizzle);
00173 }
00174
00175 if (con->options & DRIZZLE_CON_ALLOCATED)
00176 free(con);
00177 }
00178
00179 int drizzle_con_fd(drizzle_con_st *con)
00180 {
00181 return con->fd;
00182 }
00183
00184 drizzle_return_t drizzle_con_set_fd(drizzle_con_st *con, int fd)
00185 {
00186 drizzle_return_t ret;
00187
00188 con->fd= fd;
00189
00190 ret= _con_setsockopt(con);
00191 if (ret != DRIZZLE_RETURN_OK)
00192 con->drizzle->last_errno= errno;
00193
00194 return ret;
00195 }
00196
00197 void drizzle_con_close(drizzle_con_st *con)
00198 {
00199 if (con->fd == -1)
00200 return;
00201
00202 (void)close(con->fd);
00203 con->fd= -1;
00204
00205 con->options&= (drizzle_con_options_t)~DRIZZLE_CON_READY;
00206 con->packet_number= 0;
00207 con->buffer_ptr= con->buffer;
00208 con->buffer_size= 0;
00209 con->events= 0;
00210 con->revents= 0;
00211
00212 DRIZZLE_STATE_RESET(con)
00213 }
00214
00215 drizzle_return_t drizzle_con_wait(drizzle_st *drizzle)
00216 {
00217 drizzle_con_st *con;
00218 struct pollfd *pfds;
00219 uint32_t x;
00220 int ret;
00221
00222 if (drizzle->pfds_size < drizzle->con_count)
00223 {
00224 pfds= realloc(drizzle->pfds, drizzle->con_count * sizeof(struct pollfd));
00225 if (pfds == NULL)
00226 {
00227 DRIZZLE_ERROR_SET(drizzle, "drizzle_con_wait", "realloc")
00228 return DRIZZLE_RETURN_MEMORY;
00229 }
00230
00231 drizzle->pfds= pfds;
00232 drizzle->pfds_size= drizzle->con_count;
00233 }
00234 else
00235 pfds= drizzle->pfds;
00236
00237 x= 0;
00238 for (con= drizzle->con_list; con != NULL; con= con->next)
00239 {
00240 if (con->events == 0)
00241 continue;
00242
00243 pfds[x].fd= con->fd;
00244 pfds[x].events= con->events;
00245 pfds[x].revents= 0;
00246 x++;
00247 }
00248
00249 if (x == 0)
00250 {
00251 DRIZZLE_ERROR_SET(drizzle, "drizzle_con_wait", "no active file descriptors")
00252 return DRIZZLE_RETURN_NO_ACTIVE_CONNECTIONS;
00253 }
00254
00255 while (1)
00256 {
00257 PDEBUG("drizzle_con_wait", "%5d", x)
00258 ret= poll(pfds, x, -1);
00259 PDEBUG("drizzle_con_wait", "%5d %5d", ret, errno)
00260 if (ret == -1)
00261 {
00262 if (errno == EINTR)
00263 continue;
00264
00265 DRIZZLE_ERROR_SET(drizzle, "drizzle_con_wait", "poll:%d", errno)
00266 drizzle->last_errno= errno;
00267 return DRIZZLE_RETURN_ERRNO;
00268 }
00269
00270 break;
00271 }
00272
00273 x= 0;
00274 for (con= drizzle->con_list; con != NULL; con= con->next)
00275 {
00276 if (con->events == 0)
00277 continue;
00278
00279 drizzle_con_set_revents(con, pfds[x].revents);
00280 x++;
00281 }
00282
00283 return DRIZZLE_RETURN_OK;
00284 }
00285
00286 drizzle_return_t drizzle_con_set_events(drizzle_con_st *con, short events)
00287 {
00288 drizzle_return_t ret;
00289
00290 if ((con->events | events) == con->events)
00291 return DRIZZLE_RETURN_OK;
00292
00293 con->events|= events;
00294
00295 if (con->drizzle->event_watch != NULL)
00296 {
00297 ret= (con->drizzle->event_watch)(con, con->events,
00298 con->drizzle->event_watch_arg);
00299 if (ret != DRIZZLE_RETURN_OK)
00300 {
00301 drizzle_con_close(con);
00302 return ret;
00303 }
00304 }
00305
00306 return DRIZZLE_RETURN_OK;
00307 }
00308
00309 void drizzle_con_set_revents(drizzle_con_st *con, short revents)
00310 {
00311 if (revents != 0)
00312 con->options|= DRIZZLE_CON_IO_READY;
00313
00314 con->revents= revents;
00315 con->events&= (short)~revents;
00316 }
00317
00318 drizzle_con_st *drizzle_con_ready(drizzle_st *drizzle)
00319 {
00320 drizzle_con_st *con;
00321
00322
00323
00324
00325 for (con= drizzle->con_list; con != NULL; con= con->next)
00326 {
00327 if (con->options & DRIZZLE_CON_IO_READY)
00328 {
00329 con->options&= (drizzle_con_options_t)~DRIZZLE_CON_IO_READY;
00330 return con;
00331 }
00332 }
00333
00334 return NULL;
00335 }
00336
00337 drizzle_st *drizzle_con_drizzle(drizzle_con_st *con)
00338 {
00339 return con->drizzle;
00340 }
00341
00342 const char *drizzle_con_error(drizzle_con_st *con)
00343 {
00344 return drizzle_error(con->drizzle);
00345 }
00346
00347 int drizzle_con_errno(drizzle_con_st *con)
00348 {
00349 return drizzle_errno(con->drizzle);
00350 }
00351
00352 uint16_t drizzle_con_error_code(drizzle_con_st *con)
00353 {
00354 return drizzle_error_code(con->drizzle);
00355 }
00356
00357 const char *drizzle_con_sqlstate(drizzle_con_st *con)
00358 {
00359 return drizzle_sqlstate(con->drizzle);
00360 }
00361
00362 drizzle_con_options_t drizzle_con_options(drizzle_con_st *con)
00363 {
00364 return con->options;
00365 }
00366
00367 void drizzle_con_set_options(drizzle_con_st *con,
00368 drizzle_con_options_t options)
00369 {
00370 con->options= options;
00371 }
00372
00373 void drizzle_con_add_options(drizzle_con_st *con,
00374 drizzle_con_options_t options)
00375 {
00376 con->options|= options;
00377 }
00378
00379 void drizzle_con_remove_options(drizzle_con_st *con,
00380 drizzle_con_options_t options)
00381 {
00382 con->options&= ~options;
00383 }
00384
00385 const char *drizzle_con_host(drizzle_con_st *con)
00386 {
00387 return con->host;
00388 }
00389
00390 in_port_t drizzle_con_port(drizzle_con_st *con)
00391 {
00392 if (con->port != 0)
00393 return con->port;
00394
00395 if (con->options & DRIZZLE_CON_MYSQL)
00396 return DRIZZLE_DEFAULT_TCP_PORT_MYSQL;
00397
00398 return DRIZZLE_DEFAULT_TCP_PORT;
00399 }
00400
00401 void drizzle_con_set_tcp(drizzle_con_st *con, const char *host, in_port_t port)
00402 {
00403 drizzle_con_reset_addrinfo(con);
00404
00405 if (host == NULL || host[0] == 0)
00406 host= DRIZZLE_DEFAULT_TCP_HOST;
00407
00408 strncpy(con->host, host, NI_MAXHOST);
00409 con->host[NI_MAXHOST - 1]= 0;
00410
00411 con->port= port;
00412 }
00413
00414
00415 const char *drizzle_con_user(drizzle_con_st *con)
00416 {
00417 return con->user;
00418 }
00419
00420 const char *drizzle_con_password(drizzle_con_st *con)
00421 {
00422 return con->password;
00423 }
00424
00425 void drizzle_con_set_auth(drizzle_con_st *con, const char *user,
00426 const char *password)
00427 {
00428 if (user == NULL)
00429 strncpy(con->user, DRIZZLE_DEFAULT_USER, DRIZZLE_MAX_USER_SIZE);
00430 else
00431 strncpy(con->user, user, DRIZZLE_MAX_USER_SIZE);
00432 con->user[DRIZZLE_MAX_USER_SIZE - 1]= 0;
00433
00434 if (password == NULL)
00435 con->password[0]= 0;
00436 else
00437 {
00438 strncpy(con->password, password, DRIZZLE_MAX_PASSWORD_SIZE);
00439 con->password[DRIZZLE_MAX_PASSWORD_SIZE - 1]= 0;
00440 }
00441 }
00442
00443 const char *drizzle_con_db(drizzle_con_st *con)
00444 {
00445 return con->db;
00446 }
00447
00448 void drizzle_con_set_db(drizzle_con_st *con, const char *db)
00449 {
00450 if (db == NULL)
00451 con->db[0]= 0;
00452 else
00453 {
00454 strncpy(con->db, db, DRIZZLE_MAX_DB_SIZE);
00455 con->db[DRIZZLE_MAX_DB_SIZE - 1]= 0;
00456 }
00457 }
00458
00459 #if 0
00460 const char *drizzle_con_ssl_cipher(drizzle_con_st *con)
00461 {
00462 return "";
00463 }
00464
00465 drizzle_return_t drizzle_con_ssl(drizzle_con_st *con, char *key, char *cert,
00466 char *ca_file, char *ca_path, char *cipher)
00467 {
00468 return DRIZZLE_RETURN_OK;
00469 }
00470 #endif
00471
00472 void *drizzle_con_data(drizzle_con_st *con)
00473 {
00474 return (void *)(con->data);
00475 }
00476
00477 void drizzle_con_set_data(drizzle_con_st *con, const void *data)
00478 {
00479 con->data= data;
00480 }
00481
00482 void drizzle_con_set_data_free(drizzle_con_st *con,
00483 drizzle_con_data_free_fn *free_fn)
00484 {
00485 con->data_free_fn= free_fn;
00486 }
00487
00488 uint8_t drizzle_con_protocol_version(drizzle_con_st *con)
00489 {
00490 return con->protocol_version;
00491 }
00492
00493 const char *drizzle_con_server_version(drizzle_con_st *con)
00494 {
00495 return con->server_version;
00496 }
00497
00498 uint32_t drizzle_con_server_version_number(drizzle_con_st *con)
00499 {
00500 uint32_t major;
00501 uint32_t minor;
00502 uint32_t version;
00503 char *current;
00504 char *end;
00505
00506 current= con->server_version;
00507
00508 major= (uint32_t)strtoul(current, &end, 10);
00509 current= end + 1;
00510 minor= (uint32_t)strtoul(current, &end, 10);
00511 current= end + 1;
00512 version= (uint32_t)strtoul(current, &end, 10);
00513
00514 return (major * 10000) + (minor * 100) + version;
00515 }
00516
00517 uint32_t drizzle_con_thread_id(drizzle_con_st *con)
00518 {
00519 return con->thread_id;
00520 }
00521
00522 const uint8_t *drizzle_con_scramble(drizzle_con_st *con)
00523 {
00524 return con->scramble;
00525 }
00526
00527 drizzle_capabilities_t drizzle_con_capabilities(drizzle_con_st *con)
00528 {
00529 return con->capabilities;
00530 }
00531
00532 uint8_t drizzle_con_charset(drizzle_con_st *con)
00533 {
00534 return con->charset;
00535 }
00536
00537 drizzle_con_status_t drizzle_con_status(drizzle_con_st *con)
00538 {
00539 return con->status;
00540 }
00541
00542 uint32_t drizzle_con_max_packet_size(drizzle_con_st *con)
00543 {
00544 return con->max_packet_size;
00545 }
00546
00547
00548
00549
00550
00551 drizzle_con_st *drizzle_con_add_tcp(drizzle_st *drizzle, drizzle_con_st *con,
00552 const char *host, in_port_t port,
00553 const char *user, const char *password,
00554 const char *db,
00555 drizzle_con_options_t options)
00556 {
00557 con= drizzle_con_create(drizzle, con);
00558 if (con == NULL)
00559 return NULL;
00560
00561 drizzle_con_set_tcp(con, host, port);
00562 drizzle_con_set_auth(con, user, password);
00563 drizzle_con_set_db(con, db);
00564 drizzle_con_add_options(con, options);
00565
00566 return con;
00567 }
00568
00569 drizzle_con_st *drizzle_con_add_uds(drizzle_st *drizzle, drizzle_con_st *con,
00570 const char *uds, const char *user,
00571 const char *password, const char *db,
00572 drizzle_con_options_t options)
00573 {
00574 con= drizzle_con_create(drizzle, con);
00575 if (con == NULL)
00576 return NULL;
00577
00578 drizzle_con_set_uds(con, uds);
00579 drizzle_con_set_auth(con, user, password);
00580 drizzle_con_set_db(con, db);
00581 drizzle_con_add_options(con, options);
00582
00583 return con;
00584 }
00585
00586 drizzle_return_t drizzle_con_connect(drizzle_con_st *con)
00587 {
00588 if (con->options & DRIZZLE_CON_READY)
00589 return DRIZZLE_RETURN_OK;
00590
00591 if (DRIZZLE_STATE_NONE(con))
00592 {
00593 if (!(con->options & DRIZZLE_CON_RAW_PACKET))
00594 {
00595 DRIZZLE_STATE_PUSH(con, drizzle_state_server_handshake_read)
00596 DRIZZLE_STATE_PUSH(con, drizzle_state_packet_read)
00597 }
00598
00599 DRIZZLE_STATE_PUSH(con, drizzle_state_connect)
00600 DRIZZLE_STATE_PUSH(con, drizzle_state_addrinfo)
00601 }
00602
00603 return drizzle_state_loop(con);
00604 }
00605
00606
00607
00608
00609
00610 void drizzle_con_set_protocol_version(drizzle_con_st *con,
00611 uint8_t protocol_version)
00612 {
00613 con->protocol_version= protocol_version;
00614 }
00615
00616 void drizzle_con_set_server_version(drizzle_con_st *con,
00617 const char *server_version)
00618 {
00619 if (server_version == NULL)
00620 con->server_version[0]= 0;
00621 else
00622 {
00623 strncpy(con->server_version, server_version,
00624 DRIZZLE_MAX_SERVER_VERSION_SIZE);
00625 con->server_version[DRIZZLE_MAX_SERVER_VERSION_SIZE - 1]= 0;
00626 }
00627 }
00628
00629 void drizzle_con_set_thread_id(drizzle_con_st *con, uint32_t thread_id)
00630 {
00631 con->thread_id= thread_id;
00632 }
00633
00634 void drizzle_con_set_scramble(drizzle_con_st *con, const uint8_t *scramble)
00635 {
00636 if (scramble == NULL)
00637 con->scramble= NULL;
00638 else
00639 {
00640 con->scramble= con->scramble_buffer;
00641 memcpy(con->scramble, scramble, DRIZZLE_MAX_SCRAMBLE_SIZE);
00642 }
00643 }
00644
00645 void drizzle_con_set_capabilities(drizzle_con_st *con,
00646 drizzle_capabilities_t capabilities)
00647 {
00648 con->capabilities= capabilities;
00649 }
00650
00651 void drizzle_con_set_charset(drizzle_con_st *con, drizzle_charset_t charset)
00652 {
00653 con->charset= charset;
00654 }
00655
00656 void drizzle_con_set_status(drizzle_con_st *con, drizzle_con_status_t status)
00657 {
00658 con->status= status;
00659 }
00660
00661 void drizzle_con_set_max_packet_size(drizzle_con_st *con,
00662 uint32_t max_packet_size)
00663 {
00664 con->max_packet_size= max_packet_size;
00665 }
00666
00667 void drizzle_con_copy_handshake(drizzle_con_st *con, drizzle_con_st *from)
00668 {
00669 drizzle_con_set_auth(con, from->user, NULL);
00670 drizzle_con_set_scramble(con, from->scramble);
00671 drizzle_con_set_db(con, from->db);
00672 drizzle_con_set_protocol_version(con, from->protocol_version);
00673 drizzle_con_set_server_version(con, from->server_version);
00674 drizzle_con_set_thread_id(con, from->thread_id);
00675 drizzle_con_set_scramble(con, from->scramble);
00676 drizzle_con_set_capabilities(con, from->capabilities);
00677 drizzle_con_set_charset(con, from->charset);
00678 drizzle_con_set_status(con, from->status);
00679 drizzle_con_set_max_packet_size(con, from->max_packet_size);
00680 }
00681
00682
00683
00684
00685
00686 drizzle_return_t drizzle_state_addrinfo(drizzle_con_st *con)
00687 {
00688 char port_str[NI_MAXSERV];
00689 struct addrinfo ai;
00690 int ret;
00691
00692 if (drizzle_con_uses_uds(con))
00693 con->addrinfo_next= &(con->uds_addrinfo);
00694 else
00695 {
00696 if (con->tcp_addrinfo != NULL)
00697 {
00698 freeaddrinfo(con->tcp_addrinfo);
00699 con->tcp_addrinfo= NULL;
00700 }
00701
00702 if (con->port != 0)
00703 snprintf(port_str, NI_MAXSERV, "%u", con->port);
00704 else if (con->options & DRIZZLE_CON_MYSQL)
00705 snprintf(port_str, NI_MAXSERV, "%u", DRIZZLE_DEFAULT_TCP_PORT_MYSQL);
00706 else
00707 snprintf(port_str, NI_MAXSERV, "%u", DRIZZLE_DEFAULT_TCP_PORT);
00708
00709 memset(&ai, 0, sizeof(struct addrinfo));
00710 ai.ai_flags= (AI_V4MAPPED | AI_ADDRCONFIG);
00711 ai.ai_family= AF_UNSPEC;
00712 ai.ai_socktype= SOCK_STREAM;
00713 ai.ai_protocol= IPPROTO_TCP;
00714
00715 ret= getaddrinfo(con->host, port_str, &ai, &(con->tcp_addrinfo));
00716 if (ret != 0)
00717 {
00718 DRIZZLE_ERROR_SET(con->drizzle, "drizzle_state_addrinfo",
00719 "getaddrinfo:%s", gai_strerror(ret))
00720 return DRIZZLE_RETURN_GETADDRINFO;
00721 }
00722
00723 con->addrinfo_next= con->tcp_addrinfo;
00724 }
00725
00726 DRIZZLE_STATE_POP(con)
00727 return DRIZZLE_RETURN_OK;
00728 }
00729
00730 drizzle_return_t drizzle_state_connect(drizzle_con_st *con)
00731 {
00732 int ret;
00733 drizzle_return_t dret;
00734
00735 PDEBUG("drizzle_state_connect", "%5d", con->fd)
00736
00737 if (con->fd != -1)
00738 {
00739 (void)close(con->fd);
00740 con->fd= -1;
00741 }
00742
00743 if (con->addrinfo_next == NULL)
00744 {
00745 DRIZZLE_ERROR_SET(con->drizzle, "drizzle_state_connect",
00746 "could not connect")
00747 DRIZZLE_STATE_RESET(con)
00748 return DRIZZLE_RETURN_COULD_NOT_CONNECT;
00749 }
00750
00751 con->fd= socket(con->addrinfo_next->ai_family,
00752 con->addrinfo_next->ai_socktype,
00753 con->addrinfo_next->ai_protocol);
00754 if (con->fd == -1)
00755 {
00756 DRIZZLE_ERROR_SET(con->drizzle, "drizzle_state_connect", "socket:%d", errno)
00757 con->drizzle->last_errno= errno;
00758 return DRIZZLE_RETURN_ERRNO;
00759 }
00760
00761 dret= _con_setsockopt(con);
00762 if (dret != DRIZZLE_RETURN_OK)
00763 {
00764 con->drizzle->last_errno= errno;
00765 return dret;
00766 }
00767
00768 while (1)
00769 {
00770 ret= connect(con->fd, con->addrinfo_next->ai_addr,
00771 con->addrinfo_next->ai_addrlen);
00772 PDEBUG("drizzle_state_connect", "%5d %5d", ret, errno)
00773 if (ret == 0)
00774 {
00775 con->addrinfo_next= NULL;
00776 break;
00777 }
00778
00779 if (errno == EAGAIN || errno == EINTR)
00780 continue;
00781
00782 if (errno == EINPROGRESS)
00783 {
00784 DRIZZLE_STATE_POP(con)
00785 DRIZZLE_STATE_PUSH(con, drizzle_state_connecting)
00786 return DRIZZLE_RETURN_OK;
00787 }
00788
00789 if (errno == ECONNREFUSED || errno == ENETUNREACH || errno == ETIMEDOUT)
00790 {
00791 con->addrinfo_next= con->addrinfo_next->ai_next;
00792 return DRIZZLE_RETURN_OK;
00793 }
00794
00795 DRIZZLE_ERROR_SET(con->drizzle, "drizzle_state_connect", "connect:%d",
00796 errno)
00797 con->drizzle->last_errno= errno;
00798 return DRIZZLE_RETURN_ERRNO;
00799 }
00800
00801 DRIZZLE_STATE_POP(con)
00802 return DRIZZLE_RETURN_OK;
00803 }
00804
00805 drizzle_return_t drizzle_state_connecting(drizzle_con_st *con)
00806 {
00807 drizzle_return_t ret;
00808
00809 PDEBUG("drizzle_state_connecting", "%5d", con->fd)
00810
00811 while (1)
00812 {
00813 if (con->revents & POLLOUT)
00814 {
00815 DRIZZLE_STATE_POP(con)
00816 return DRIZZLE_RETURN_OK;
00817 }
00818 else if (con->revents & (POLLERR | POLLHUP | POLLNVAL))
00819 {
00820 con->revents= 0;
00821 DRIZZLE_STATE_POP(con)
00822 DRIZZLE_STATE_PUSH(con, drizzle_state_connect)
00823 con->addrinfo_next= con->addrinfo_next->ai_next;
00824 return DRIZZLE_RETURN_OK;
00825 }
00826
00827 ret= drizzle_con_set_events(con, POLLOUT);
00828 if (ret != DRIZZLE_RETURN_OK)
00829 return ret;
00830
00831 if (con->drizzle->options & DRIZZLE_NON_BLOCKING)
00832 return DRIZZLE_RETURN_IO_WAIT;
00833
00834 ret= drizzle_con_wait(con->drizzle);
00835 if (ret != DRIZZLE_RETURN_OK)
00836 return ret;
00837 }
00838 }
00839
00840 drizzle_return_t drizzle_state_read(drizzle_con_st *con)
00841 {
00842 drizzle_return_t ret;
00843 ssize_t read_size;
00844
00845 if (con->buffer_size == 0)
00846 con->buffer_ptr= con->buffer;
00847 else if ((con->buffer_ptr - con->buffer) > (DRIZZLE_MAX_BUFFER_SIZE / 2))
00848 {
00849 memmove(con->buffer, con->buffer_ptr, con->buffer_size);
00850 con->buffer_ptr= con->buffer;
00851 }
00852
00853 while (1)
00854 {
00855 read_size= read(con->fd, con->buffer_ptr + con->buffer_size,
00856 (size_t)DRIZZLE_MAX_BUFFER_SIZE -
00857 ((size_t)(con->buffer_ptr - con->buffer) +
00858 con->buffer_size));
00859 PDEBUG("drizzle_state_read", "%5d %5zd %5d", con->fd, read_size, errno)
00860 if (read_size == 0)
00861 {
00862 DRIZZLE_ERROR_SET(con->drizzle, "drizzle_state_read",
00863 "lost connection to server (EOF)")
00864 return DRIZZLE_RETURN_LOST_CONNECTION;
00865 }
00866 else if (read_size == -1)
00867 {
00868 if (errno == EAGAIN)
00869 {
00870 ret= drizzle_con_set_events(con, POLLIN);
00871 if (ret != DRIZZLE_RETURN_OK)
00872 return 0;
00873
00874 if (con->drizzle->options & DRIZZLE_NON_BLOCKING)
00875 return DRIZZLE_RETURN_IO_WAIT;
00876
00877 ret= drizzle_con_wait(con->drizzle);
00878 if (ret != DRIZZLE_RETURN_OK)
00879 return ret;
00880
00881 continue;
00882 }
00883 else if (errno == ECONNREFUSED)
00884 {
00885 con->revents= 0;
00886 DRIZZLE_STATE_POP(con)
00887 DRIZZLE_STATE_PUSH(con, drizzle_state_connect)
00888 con->addrinfo_next= con->addrinfo_next->ai_next;
00889 return DRIZZLE_RETURN_OK;
00890 }
00891 else if (errno == EINTR)
00892 continue;
00893 else if (errno == EPIPE || errno == ECONNRESET)
00894 {
00895 DRIZZLE_ERROR_SET(con->drizzle, "drizzle_state_read",
00896 "lost connection to server (%d)", errno)
00897 return DRIZZLE_RETURN_LOST_CONNECTION;
00898 }
00899
00900 DRIZZLE_ERROR_SET(con->drizzle, "drizzle_state_read", "read:%d", errno)
00901 con->drizzle->last_errno= errno;
00902 return DRIZZLE_RETURN_ERRNO;
00903 }
00904
00905 con->buffer_size+= (size_t)read_size;
00906 break;
00907 }
00908
00909 DRIZZLE_STATE_POP(con);
00910 return DRIZZLE_RETURN_OK;
00911 }
00912
00913 drizzle_return_t drizzle_state_write(drizzle_con_st *con)
00914 {
00915 drizzle_return_t ret;
00916 ssize_t write_size;
00917
00918 while (con->buffer_size != 0)
00919 {
00920 write_size= write(con->fd, con->buffer_ptr, con->buffer_size);
00921 PDEBUG("drizzle_state_write", "%5d %5zd %5d", con->fd, write_size, errno)
00922 if (write_size == 0)
00923 {
00924 DRIZZLE_ERROR_SET(con->drizzle, "drizzle_state_write",
00925 "lost connection to server (EOF)")
00926 return DRIZZLE_RETURN_LOST_CONNECTION;
00927 }
00928 else if (write_size == -1)
00929 {
00930 if (errno == EAGAIN)
00931 {
00932 ret= drizzle_con_set_events(con, POLLOUT);
00933 if (ret != DRIZZLE_RETURN_OK)
00934 return ret;
00935
00936 if (con->drizzle->options & DRIZZLE_NON_BLOCKING)
00937 return DRIZZLE_RETURN_IO_WAIT;
00938
00939 ret= drizzle_con_wait(con->drizzle);
00940 if (ret != DRIZZLE_RETURN_OK)
00941 return ret;
00942
00943 continue;
00944 }
00945 else if (errno == EINTR)
00946 continue;
00947 else if (errno == EPIPE || errno == ECONNRESET)
00948 {
00949 DRIZZLE_ERROR_SET(con->drizzle, "drizzle_state_write",
00950 "lost connection to server (%d)", errno)
00951 return DRIZZLE_RETURN_LOST_CONNECTION;
00952 }
00953
00954 DRIZZLE_ERROR_SET(con->drizzle, "drizzle_state_write", "write:%d", errno)
00955 con->drizzle->last_errno= errno;
00956 return DRIZZLE_RETURN_ERRNO;
00957 }
00958
00959 con->buffer_ptr+= write_size;
00960 con->buffer_size-= (size_t)write_size;
00961 if (con->buffer_size == 0)
00962 break;
00963 }
00964
00965 con->buffer_ptr= con->buffer;
00966
00967 DRIZZLE_STATE_POP(con);
00968 return DRIZZLE_RETURN_OK;
00969 }
00970
00971
00972
00973
00974
00975 void drizzle_con_reset_addrinfo(drizzle_con_st *con)
00976 {
00977 if (con->tcp_addrinfo != NULL)
00978 {
00979 freeaddrinfo(con->tcp_addrinfo);
00980 con->tcp_addrinfo= NULL;
00981 }
00982
00983 con->uds_addrinfo.ai_addr= NULL;
00984 con->addrinfo_next= NULL;
00985 }
00986
00987 static drizzle_return_t _con_setsockopt(drizzle_con_st *con)
00988 {
00989 int ret;
00990 struct linger linger;
00991 struct timeval waittime;
00992
00993 ret= 1;
00994 ret= setsockopt(con->fd, IPPROTO_TCP, TCP_NODELAY, &ret,
00995 (socklen_t)sizeof(int));
00996 if (ret == -1 && errno != EOPNOTSUPP)
00997 {
00998 DRIZZLE_ERROR_SET(con->drizzle, "_con_setsockopt",
00999 "setsockopt:TCP_NODELAY:%d", errno)
01000 return DRIZZLE_RETURN_ERRNO;
01001 }
01002
01003 linger.l_onoff= 1;
01004 linger.l_linger= DRIZZLE_DEFAULT_SOCKET_TIMEOUT;
01005 ret= setsockopt(con->fd, SOL_SOCKET, SO_LINGER, &linger,
01006 (socklen_t)sizeof(struct linger));
01007 if (ret == -1)
01008 {
01009 DRIZZLE_ERROR_SET(con->drizzle, "_con_setsockopt",
01010 "setsockopt:SO_LINGER:%d", errno)
01011 return DRIZZLE_RETURN_ERRNO;
01012 }
01013
01014 waittime.tv_sec= DRIZZLE_DEFAULT_SOCKET_TIMEOUT;
01015 waittime.tv_usec= 0;
01016 ret= setsockopt(con->fd, SOL_SOCKET, SO_SNDTIMEO, &waittime,
01017 (socklen_t)sizeof(struct timeval));
01018 if (ret == -1 && errno != ENOPROTOOPT)
01019 {
01020 DRIZZLE_ERROR_SET(con->drizzle, "_con_setsockopt",
01021 "setsockopt:SO_SNDTIMEO:%d", errno)
01022 return DRIZZLE_RETURN_ERRNO;
01023 }
01024
01025 ret= setsockopt(con->fd, SOL_SOCKET, SO_RCVTIMEO, &waittime,
01026 (socklen_t)sizeof(struct timeval));
01027 if (ret == -1 && errno != ENOPROTOOPT)
01028 {
01029 DRIZZLE_ERROR_SET(con->drizzle, "_con_setsockopt",
01030 "setsockopt:SO_RCVTIMEO:%d", errno)
01031 return DRIZZLE_RETURN_ERRNO;
01032 }
01033
01034 ret= DRIZZLE_DEFAULT_SOCKET_SEND_SIZE;
01035 ret= setsockopt(con->fd, SOL_SOCKET, SO_SNDBUF, &ret, (socklen_t)sizeof(int));
01036 if (ret == -1)
01037 {
01038 DRIZZLE_ERROR_SET(con->drizzle, "_con_setsockopt",
01039 "setsockopt:SO_SNDBUF:%d", errno)
01040 return DRIZZLE_RETURN_ERRNO;
01041 }
01042
01043 ret= DRIZZLE_DEFAULT_SOCKET_RECV_SIZE;
01044 ret= setsockopt(con->fd, SOL_SOCKET, SO_RCVBUF, &ret, (socklen_t)sizeof(int));
01045 if (ret == -1)
01046 {
01047 DRIZZLE_ERROR_SET(con->drizzle, "_con_setsockopt",
01048 "setsockopt:SO_RCVBUF:%d", errno)
01049 return DRIZZLE_RETURN_ERRNO;
01050 }
01051
01052 #ifdef FIONBIO
01053 ret= 1;
01054 ret= ioctl(con->fd, FIONBIO, &ret);
01055 if (ret == -1)
01056 {
01057 DRIZZLE_ERROR_SET(con->drizzle, "_con_setsockopt",
01058 "ioctl:FIONBIO:%d", errno)
01059 return DRIZZLE_RETURN_ERRNO;
01060 }
01061 #else
01062 ret= fcntl(con->fd, F_GETFL, 0);
01063 if (ret == -1)
01064 {
01065 DRIZZLE_ERROR_SET(con->drizzle, "_con_setsockopt",
01066 "fcntl:F_GETFL:%d", errno)
01067 return DRIZZLE_RETURN_ERRNO;
01068 }
01069
01070 ret= fcntl(con->fd, F_SETFL, ret | O_NONBLOCK);
01071 if (ret == -1)
01072 {
01073 DRIZZLE_ERROR_SET(con->drizzle, "_con_setsockopt",
01074 "fcntl:F_SETFL:%d", errno)
01075 return DRIZZLE_RETURN_ERRNO;
01076 }
01077 #endif
01078
01079 return DRIZZLE_RETURN_OK;
01080 }