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 #ifdef _WIN32
00829
00830 errno = WSAGetLastError();
00831 switch(errno) {
00832 case WSAEINVAL:
00833 case WSAEALREADY:
00834 case WSAEWOULDBLOCK:
00835 errno = EINPROGRESS;
00836 break;
00837 default:
00838 break;
00839 }
00840 #endif
00841
00842 drizzle_log_crazy(con->drizzle, "connect return=%d errno=%d", ret, errno);
00843
00844 if (ret == 0)
00845 {
00846 con->addrinfo_next= NULL;
00847 break;
00848 }
00849
00850 if (errno == EAGAIN || errno == EINTR)
00851 continue;
00852
00853 if (errno == EINPROGRESS)
00854 {
00855 drizzle_state_pop(con);
00856 drizzle_state_push(con, drizzle_state_connecting);
00857 return DRIZZLE_RETURN_OK;
00858 }
00859
00860 if (errno == ECONNREFUSED || errno == ENETUNREACH || errno == ETIMEDOUT)
00861 {
00862 con->addrinfo_next= con->addrinfo_next->ai_next;
00863 return DRIZZLE_RETURN_OK;
00864 }
00865
00866 drizzle_set_error(con->drizzle, "drizzle_state_connect", "connect:%d",
00867 errno);
00868 con->drizzle->last_errno= errno;
00869 return DRIZZLE_RETURN_ERRNO;
00870 }
00871
00872 drizzle_state_pop(con);
00873 return DRIZZLE_RETURN_OK;
00874 }
00875
00876 drizzle_return_t drizzle_state_connecting(drizzle_con_st *con)
00877 {
00878 drizzle_return_t ret;
00879
00880 drizzle_log_debug(con->drizzle, "drizzle_state_connecting");
00881
00882 while (1)
00883 {
00884 if (con->revents & POLLOUT)
00885 {
00886 drizzle_state_pop(con);
00887 return DRIZZLE_RETURN_OK;
00888 }
00889 else if (con->revents & (POLLERR | POLLHUP | POLLNVAL))
00890 {
00891 con->revents= 0;
00892 drizzle_state_pop(con);
00893 drizzle_state_push(con, drizzle_state_connect);
00894 con->addrinfo_next= con->addrinfo_next->ai_next;
00895 return DRIZZLE_RETURN_OK;
00896 }
00897
00898 ret= drizzle_con_set_events(con, POLLOUT);
00899 if (ret != DRIZZLE_RETURN_OK)
00900 return ret;
00901
00902 if (con->drizzle->options & DRIZZLE_NON_BLOCKING)
00903 return DRIZZLE_RETURN_IO_WAIT;
00904
00905 ret= drizzle_con_wait(con->drizzle);
00906 if (ret != DRIZZLE_RETURN_OK)
00907 return ret;
00908 }
00909 }
00910
00911 drizzle_return_t drizzle_state_read(drizzle_con_st *con)
00912 {
00913 drizzle_return_t ret;
00914 ssize_t read_size;
00915
00916 drizzle_log_debug(con->drizzle, "drizzle_state_read");
00917
00918 if (con->buffer_size == 0)
00919 con->buffer_ptr= con->buffer;
00920 else if ((con->buffer_ptr - con->buffer) > (DRIZZLE_MAX_BUFFER_SIZE / 2))
00921 {
00922 memmove(con->buffer, con->buffer_ptr, con->buffer_size);
00923 con->buffer_ptr= con->buffer;
00924 }
00925
00926 while (1)
00927 {
00928 read_size = recv(con->fd, (char *)con->buffer_ptr + con->buffer_size,
00929 (size_t)DRIZZLE_MAX_BUFFER_SIZE -
00930 ((size_t)(con->buffer_ptr - con->buffer) +
00931 con->buffer_size),0);
00932 #ifdef _WIN32
00933
00934 errno = WSAGetLastError();
00935 switch(errno) {
00936 case WSAEWOULDBLOCK:
00937 case 10057:
00938 errno = EAGAIN;
00939 break;
00940 default:
00941 break;
00942 }
00943 #endif
00944 drizzle_log_crazy(con->drizzle, "read fd=%d return=%zd errno=%d", con->fd,
00945 read_size, errno);
00946
00947 if (read_size == 0)
00948 {
00949 drizzle_set_error(con->drizzle, "drizzle_state_read",
00950 "lost connection to server (EOF)");
00951 return DRIZZLE_RETURN_LOST_CONNECTION;
00952 }
00953 else if (read_size == -1)
00954 {
00955 if (errno == EAGAIN)
00956 {
00957 ret= drizzle_con_set_events(con, POLLIN);
00958 if (ret != DRIZZLE_RETURN_OK)
00959 return 0;
00960
00961 if (con->drizzle->options & DRIZZLE_NON_BLOCKING)
00962 return DRIZZLE_RETURN_IO_WAIT;
00963
00964 ret= drizzle_con_wait(con->drizzle);
00965 if (ret != DRIZZLE_RETURN_OK)
00966 return ret;
00967
00968 continue;
00969 }
00970 else if (errno == ECONNREFUSED)
00971 {
00972 con->revents= 0;
00973 drizzle_state_pop(con);
00974 drizzle_state_push(con, drizzle_state_connect);
00975 con->addrinfo_next= con->addrinfo_next->ai_next;
00976 return DRIZZLE_RETURN_OK;
00977 }
00978 else if (errno == EINTR)
00979 continue;
00980 else if (errno == EPIPE || errno == ECONNRESET)
00981 {
00982 drizzle_set_error(con->drizzle, "drizzle_state_read",
00983 "lost connection to server (%d)", errno);
00984 return DRIZZLE_RETURN_LOST_CONNECTION;
00985 }
00986
00987 drizzle_set_error(con->drizzle, "drizzle_state_read", "read:%d", errno);
00988 con->drizzle->last_errno= errno;
00989 return DRIZZLE_RETURN_ERRNO;
00990 }
00991
00992 con->buffer_size+= (size_t)read_size;
00993 break;
00994 }
00995
00996 drizzle_state_pop(con);;
00997 return DRIZZLE_RETURN_OK;
00998 }
00999
01000 drizzle_return_t drizzle_state_write(drizzle_con_st *con)
01001 {
01002 drizzle_return_t ret;
01003 ssize_t write_size;
01004
01005 drizzle_log_debug(con->drizzle, "drizzle_state_write");
01006
01007 while (con->buffer_size != 0)
01008 {
01009
01010 write_size = send(con->fd,(char *) con->buffer_ptr, con->buffer_size,0);
01011
01012 drizzle_log_crazy(con->drizzle, "write fd=%d return=%zd errno=%d", con->fd,
01013 write_size, errno);
01014
01015 if (write_size == 0)
01016 {
01017 drizzle_set_error(con->drizzle, "drizzle_state_write",
01018 "lost connection to server (EOF)");
01019 return DRIZZLE_RETURN_LOST_CONNECTION;
01020 }
01021 else if (write_size == -1)
01022 {
01023 if (errno == EAGAIN)
01024 {
01025 ret= drizzle_con_set_events(con, POLLOUT);
01026 if (ret != DRIZZLE_RETURN_OK)
01027 return ret;
01028
01029 if (con->drizzle->options & DRIZZLE_NON_BLOCKING)
01030 return DRIZZLE_RETURN_IO_WAIT;
01031
01032 ret= drizzle_con_wait(con->drizzle);
01033 if (ret != DRIZZLE_RETURN_OK)
01034 return ret;
01035
01036 continue;
01037 }
01038 else if (errno == EINTR)
01039 continue;
01040 else if (errno == EPIPE || errno == ECONNRESET)
01041 {
01042 drizzle_set_error(con->drizzle, "drizzle_state_write",
01043 "lost connection to server (%d)", errno);
01044 return DRIZZLE_RETURN_LOST_CONNECTION;
01045 }
01046
01047 drizzle_set_error(con->drizzle, "drizzle_state_write", "write:%d", errno);
01048 con->drizzle->last_errno= errno;
01049 return DRIZZLE_RETURN_ERRNO;
01050 }
01051
01052 con->buffer_ptr+= write_size;
01053 con->buffer_size-= (size_t)write_size;
01054 if (con->buffer_size == 0)
01055 break;
01056 }
01057
01058 con->buffer_ptr= con->buffer;
01059
01060 drizzle_state_pop(con);
01061 return DRIZZLE_RETURN_OK;
01062 }
01063
01064 drizzle_return_t drizzle_state_listen(drizzle_con_st *con)
01065 {
01066 char host[NI_MAXHOST];
01067 char port[NI_MAXSERV];
01068 int ret;
01069 int fd;
01070 int opt;
01071 drizzle_con_st *new_con;
01072
01073 for (; con->addrinfo_next != NULL;
01074 con->addrinfo_next= con->addrinfo_next->ai_next)
01075 {
01076 ret= getnameinfo(con->addrinfo_next->ai_addr,
01077 con->addrinfo_next->ai_addrlen, host, NI_MAXHOST, port,
01078 NI_MAXSERV, NI_NUMERICHOST | NI_NUMERICSERV);
01079 if (ret != 0)
01080 {
01081 drizzle_set_error(con->drizzle, "drizzle_state_listen", "getnameinfo:%s",
01082 gai_strerror(ret));
01083 return DRIZZLE_RETURN_GETADDRINFO;
01084 }
01085
01086
01087 fd= socket(con->addrinfo_next->ai_family, con->addrinfo_next->ai_socktype,
01088 con->addrinfo_next->ai_protocol);
01089 if (fd == -1)
01090 {
01091 drizzle_log_info(con->drizzle, "could not listen on %s:%s", host, port);
01092 drizzle_set_error(con->drizzle, "drizzle_state_listen", "socket:%d",
01093 errno);
01094 continue;
01095 }
01096
01097 opt= 1;
01098 #ifdef _WIN32
01099 ret= setsockopt(fd, SOL_SOCKET, SO_REUSEADDR,(const char*) &opt, sizeof(opt));
01100 #else
01101 ret= setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt));
01102 #endif
01103 if (ret == -1)
01104 {
01105 close(fd);
01106 drizzle_set_error(con->drizzle, "drizzle_state_listen", "setsockopt:%d",
01107 errno);
01108 return DRIZZLE_RETURN_ERRNO;
01109 }
01110
01111 ret= bind(fd, con->addrinfo_next->ai_addr, con->addrinfo_next->ai_addrlen);
01112 if (ret == -1)
01113 {
01114 close(fd);
01115 drizzle_set_error(con->drizzle, "drizzle_state_listen", "bind:%d", errno);
01116 if (errno == EADDRINUSE)
01117 {
01118 if (con->fd == -1)
01119 {
01120 drizzle_log_info(con->drizzle, "could not listen on %s:%s", host,
01121 port);
01122 }
01123
01124 continue;
01125 }
01126
01127 return DRIZZLE_RETURN_ERRNO;
01128 }
01129
01130 if (listen(fd, con->backlog) == -1)
01131 {
01132 close(fd);
01133 drizzle_set_error(con->drizzle, "drizzle_state_listen", "listen:%d",
01134 errno);
01135 return DRIZZLE_RETURN_ERRNO;
01136 }
01137
01138 if (con->fd == -1)
01139 {
01140 con->fd= fd;
01141 new_con= con;
01142 }
01143 else
01144 {
01145 new_con= drizzle_con_clone(con->drizzle, NULL, con);
01146 if (new_con == NULL)
01147 {
01148 close(fd);
01149 return DRIZZLE_RETURN_MEMORY;
01150 }
01151
01152 new_con->fd= fd;
01153 }
01154
01155
01156 ret= drizzle_con_set_events(new_con, POLLIN);
01157 if (ret != DRIZZLE_RETURN_OK)
01158 {
01159 drizzle_con_free(new_con);
01160 return ret;
01161 }
01162
01163 drizzle_log_info(con->drizzle, "listening on %s:%s", host, port);
01164 }
01165
01166
01167 if (con->fd == -1)
01168 return DRIZZLE_RETURN_ERRNO;
01169
01170 drizzle_state_pop(con);
01171 return DRIZZLE_RETURN_OK;
01172 }
01173
01174
01175
01176
01177
01178 static drizzle_return_t _con_setsockopt(drizzle_con_st *con)
01179 {
01180 int ret;
01181 struct linger linger;
01182 struct timeval waittime;
01183
01184 ret= 1;
01185
01186 #ifdef _WIN32
01187 ret= setsockopt(con->fd, IPPROTO_TCP, TCP_NODELAY, (const char*)&ret,
01188 (socklen_t)sizeof(int));
01189 #else
01190 ret= setsockopt(con->fd, IPPROTO_TCP, TCP_NODELAY, &ret,
01191 (socklen_t)sizeof(int));
01192 #endif
01193
01194 if (ret == -1 && errno != EOPNOTSUPP)
01195 {
01196 drizzle_set_error(con->drizzle, "_con_setsockopt",
01197 "setsockopt:TCP_NODELAY:%d", errno);
01198 return DRIZZLE_RETURN_ERRNO;
01199 }
01200
01201 linger.l_onoff= 1;
01202 linger.l_linger= DRIZZLE_DEFAULT_SOCKET_TIMEOUT;
01203
01204 #ifdef _WIN32
01205 ret= setsockopt(con->fd, SOL_SOCKET, SO_LINGER, (const char*)&linger,
01206 (socklen_t)sizeof(struct linger));
01207 #else
01208 ret= setsockopt(con->fd, SOL_SOCKET, SO_LINGER, &linger,
01209 (socklen_t)sizeof(struct linger));
01210 #endif
01211
01212 if (ret == -1)
01213 {
01214 drizzle_set_error(con->drizzle, "_con_setsockopt",
01215 "setsockopt:SO_LINGER:%d", errno);
01216 return DRIZZLE_RETURN_ERRNO;
01217 }
01218
01219 waittime.tv_sec= DRIZZLE_DEFAULT_SOCKET_TIMEOUT;
01220 waittime.tv_usec= 0;
01221
01222 #ifdef _WIN32
01223 ret= setsockopt(con->fd, SOL_SOCKET, SO_SNDTIMEO, (const char*)&waittime,
01224 (socklen_t)sizeof(struct timeval));
01225 #else
01226 ret= setsockopt(con->fd, SOL_SOCKET, SO_SNDTIMEO, &waittime,
01227 (socklen_t)sizeof(struct timeval));
01228 #endif
01229
01230 if (ret == -1 && errno != ENOPROTOOPT)
01231 {
01232 drizzle_set_error(con->drizzle, "_con_setsockopt",
01233 "setsockopt:SO_SNDTIMEO:%d", errno);
01234 return DRIZZLE_RETURN_ERRNO;
01235 }
01236
01237 #ifdef _WIN32
01238 ret= setsockopt(con->fd, SOL_SOCKET, SO_RCVTIMEO, (const char*)&waittime,
01239 (socklen_t)sizeof(struct timeval));
01240 #else
01241 ret= setsockopt(con->fd, SOL_SOCKET, SO_RCVTIMEO, &waittime,
01242 (socklen_t)sizeof(struct timeval));
01243 #endif
01244
01245 if (ret == -1 && errno != ENOPROTOOPT)
01246 {
01247 drizzle_set_error(con->drizzle, "_con_setsockopt",
01248 "setsockopt:SO_RCVTIMEO:%d", errno);
01249 return DRIZZLE_RETURN_ERRNO;
01250 }
01251
01252 ret= DRIZZLE_DEFAULT_SOCKET_SEND_SIZE;
01253 #ifdef _WIN32
01254 ret= setsockopt(con->fd, SOL_SOCKET, SO_SNDBUF, (const char*)&ret, (socklen_t)sizeof(int));
01255 #else
01256 ret= setsockopt(con->fd, SOL_SOCKET, SO_SNDBUF, &ret, (socklen_t)sizeof(int));
01257 #endif
01258 if (ret == -1)
01259 {
01260 drizzle_set_error(con->drizzle, "_con_setsockopt",
01261 "setsockopt:SO_SNDBUF:%d", errno);
01262 return DRIZZLE_RETURN_ERRNO;
01263 }
01264
01265 ret= DRIZZLE_DEFAULT_SOCKET_RECV_SIZE;
01266 #ifdef _WIN32
01267 ret= setsockopt(con->fd, SOL_SOCKET, SO_RCVBUF, (const char*)&ret, (socklen_t)sizeof(int));
01268 #else
01269 ret= setsockopt(con->fd, SOL_SOCKET, SO_RCVBUF, &ret, (socklen_t)sizeof(int));
01270 #endif
01271 if (ret == -1)
01272 {
01273 drizzle_set_error(con->drizzle, "_con_setsockopt",
01274 "setsockopt:SO_RCVBUF:%d", errno);
01275 return DRIZZLE_RETURN_ERRNO;
01276 }
01277
01278 #if defined (_WIN32)
01279 unsigned long asyncmode = 1;
01280 ioctlsocket(con->fd, FIONBIO, &asyncmode);
01281 #else
01282 ret= fcntl(con->fd, F_GETFL, 0);
01283 if (ret == -1)
01284 {
01285 drizzle_set_error(con->drizzle, "_con_setsockopt", "fcntl:F_GETFL:%d",
01286 errno);
01287 return DRIZZLE_RETURN_ERRNO;
01288 }
01289
01290 ret= fcntl(con->fd, F_SETFL, ret | O_NONBLOCK);
01291 if (ret == -1)
01292 {
01293 drizzle_set_error(con->drizzle, "_con_setsockopt", "fcntl:F_SETFL:%d",
01294 errno);
01295 return DRIZZLE_RETURN_ERRNO;
01296 }
01297 #endif
01298
01299 return DRIZZLE_RETURN_OK;
01300 }