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