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