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