// non blocking API void MySQL_Connection::connect_start() { PROXY_TRACE(); mysql=mysql_init(NULL); assert(mysql); mysql_options(mysql, MYSQL_OPT_NONBLOCK, 0); unsigned int timeout= 1; mysql_options(mysql, MYSQL_OPT_CONNECT_TIMEOUT, (void *)&timeout); const CHARSET_INFO * c = proxysql_find_charset_nr(mysql_thread___default_charset); if (!c) { proxy_error("Not existing charset number %u\n", mysql_thread___default_charset); assert(0); } mysql_options(mysql, MYSQL_SET_CHARSET_NAME, c->csname); unsigned long client_flags = 0; if (mysql_thread___client_found_rows) client_flags += CLIENT_FOUND_ROWS; if (parent->compression) client_flags += CLIENT_COMPRESS; if (parent->port) { async_exit_status=mysql_real_connect_start(&ret_mysql, mysql, parent->address, userinfo->username, userinfo->password, userinfo->schemaname, parent->port, NULL, client_flags); } else { async_exit_status=mysql_real_connect_start(&ret_mysql, mysql, "localhost", userinfo->username, userinfo->password, userinfo->schemaname, parent->port, parent->address, client_flags); } fd=mysql_get_socket(mysql); }
static void next_event(int new_st, int status, struct state_data *sd) { short wait_event= 0; struct timeval tv, *ptv; int fd; if (status & MYSQL_WAIT_READ) wait_event|= EV_READ; if (status & MYSQL_WAIT_WRITE) wait_event|= EV_WRITE; if (wait_event) fd= mysql_get_socket(&sd->mysql); else fd= -1; if (status & MYSQL_WAIT_TIMEOUT) { tv.tv_sec= mysql_get_timeout_value(&sd->mysql); tv.tv_usec= 0; ptv= &tv; } else ptv= NULL; event_set(&sd->ev_mysql, fd, wait_event, state_machine_handler, sd); event_add(&sd->ev_mysql, ptv); sd->ST= new_st; }
static int statement_get_socket (lua_State * L) /* {{{ */ { statement_t *statement = (statement_t *) luaL_checkudata (L, 1, DBD_MYSQL_STATEMENT); lua_pushnumber (L, mysql_get_socket (statement->mysql)); return 1; } /* }}} */
void MySQL_Connection::next_event(MDB_ASYNC_ST new_st) { #ifdef DEBUG int fd; #endif /* DEBUG */ wait_events=0; if (async_exit_status & MYSQL_WAIT_READ) wait_events |= POLLIN; if (async_exit_status & MYSQL_WAIT_WRITE) wait_events|= POLLOUT; if (wait_events) #ifdef DEBUG fd= mysql_get_socket(mysql); #else mysql_get_socket(mysql); #endif /* DEBUG */ else
my_bool ma_tls_connect(MARIADB_TLS *ctls) { SSL *ssl = (SSL *)ctls->ssl; my_bool blocking; MYSQL *mysql; MARIADB_PVIO *pvio; int rc; mysql= (MYSQL *)SSL_get_app_data(ssl); pvio= mysql->net.pvio; /* Set socket to blocking if not already set */ if (!(blocking= pvio->methods->is_blocking(pvio))) pvio->methods->blocking(pvio, TRUE, 0); SSL_clear(ssl); SSL_SESSION_set_timeout(SSL_get_session(ssl), mysql->options.connect_timeout); SSL_set_fd(ssl, mysql_get_socket(mysql)); if (SSL_connect(ssl) != 1) { ma_tls_set_error(mysql); /* restore blocking mode */ if (!blocking) pvio->methods->blocking(pvio, FALSE, 0); return 1; } if ((mysql->client_flag & CLIENT_SSL_VERIFY_SERVER_CERT)) { rc= SSL_get_verify_result(ssl); if (rc != X509_V_OK) { my_set_error(mysql, CR_SSL_CONNECTION_ERROR, SQLSTATE_UNKNOWN, ER(CR_SSL_CONNECTION_ERROR), X509_verify_cert_error_string(rc)); /* restore blocking mode */ if (!blocking) pvio->methods->blocking(pvio, FALSE, 0); return 1; } } pvio->ctls->ssl= ctls->ssl= (void *)ssl; return 0; }
static int wait_for_mysql(MYSQL *mysql, int status) { #ifdef _WIN32 fd_set rs, ws, es; int res; struct timeval tv, *timeout; my_socket s= mysql_get_socket(mysql); FD_ZERO(&rs); FD_ZERO(&ws); FD_ZERO(&es); if (status & MYSQL_WAIT_READ) FD_SET(s, &rs); if (status & MYSQL_WAIT_WRITE) FD_SET(s, &ws); if (status & MYSQL_WAIT_EXCEPT) FD_SET(s, &es); if (status & MYSQL_WAIT_TIMEOUT) { tv.tv_sec= mysql_get_timeout_value(mysql); tv.tv_usec= 0; timeout= &tv; } else timeout= NULL; res= select(1, &rs, &ws, &es, timeout); if (res == 0) return MYSQL_WAIT_TIMEOUT; else if (res == SOCKET_ERROR) { /* In a real event framework, we should handle errors and re-try the select. */ return MYSQL_WAIT_TIMEOUT; } else { int status= 0; if (FD_ISSET(s, &rs)) status|= MYSQL_WAIT_READ; if (FD_ISSET(s, &ws)) status|= MYSQL_WAIT_WRITE; if (FD_ISSET(s, &es)) status|= MYSQL_WAIT_EXCEPT; return status; } #else struct pollfd pfd; int timeout; int res= -1; pfd.fd= mysql_get_socket(mysql); pfd.events= (status & MYSQL_WAIT_READ ? POLLIN : 0) | (status & MYSQL_WAIT_WRITE ? POLLOUT : 0) | (status & MYSQL_WAIT_EXCEPT ? POLLPRI : 0); if (status & MYSQL_WAIT_TIMEOUT) timeout= mysql_get_timeout_value_ms(mysql); else timeout= -1; do { res= poll(&pfd, 1, timeout); } while (res == -1 && errno == EINTR); if (res == 0) return MYSQL_WAIT_TIMEOUT; else if (res < 0) { /* In a real event framework, we should handle EINTR and re-try the poll. */ return MYSQL_WAIT_TIMEOUT; } else { int status= 0; if (pfd.revents & POLLIN) status|= MYSQL_WAIT_READ; if (pfd.revents & POLLOUT) status|= MYSQL_WAIT_WRITE; if (pfd.revents & POLLPRI) status|= MYSQL_WAIT_EXCEPT; return status; } #endif }
my_bool ma_tls_connect(MARIADB_TLS *ctls) { SSL *ssl = (SSL *)ctls->ssl; my_bool blocking, try_connect= 1; MYSQL *mysql; MARIADB_PVIO *pvio; int rc; #if OPENSSL_USE_BIOMETHOD BIO_METHOD *bio_method= NULL; BIO *bio; #endif mysql= (MYSQL *)SSL_get_app_data(ssl); pvio= mysql->net.pvio; /* Set socket to non blocking if not already set */ if (!(blocking= pvio->methods->is_blocking(pvio))) pvio->methods->blocking(pvio, FALSE, 0); SSL_clear(ssl); #if OPENSSL_USE_BIOMETHOD bio= BIO_new(&ma_BIO_method); bio->ptr= pvio; SSL_set_bio(ssl, bio, bio); BIO_set_fd(bio, mysql_get_socket(mysql), BIO_NOCLOSE); #else SSL_set_fd(ssl, mysql_get_socket(mysql)); #endif while (try_connect && (rc= SSL_connect(ssl)) == -1) { switch(SSL_get_error(ssl, rc)) { case SSL_ERROR_WANT_READ: if (pvio->methods->wait_io_or_timeout(pvio, TRUE, mysql->options.connect_timeout) < 1) try_connect= 0; break; case SSL_ERROR_WANT_WRITE: if (pvio->methods->wait_io_or_timeout(pvio, TRUE, mysql->options.connect_timeout) < 1) try_connect= 0; break; default: try_connect= 0; } } if (rc != 1) { ma_tls_set_error(mysql); /* restore blocking mode */ if (!blocking) pvio->methods->blocking(pvio, FALSE, 0); return 1; } if ((mysql->client_flag & CLIENT_SSL_VERIFY_SERVER_CERT)) { rc= SSL_get_verify_result(ssl); if (rc != X509_V_OK) { my_set_error(mysql, CR_SSL_CONNECTION_ERROR, SQLSTATE_UNKNOWN, ER(CR_SSL_CONNECTION_ERROR), X509_verify_cert_error_string(rc)); /* restore blocking mode */ if (!blocking) pvio->methods->blocking(pvio, FALSE, 0); return 1; } } pvio->ctls->ssl= ctls->ssl= (void *)ssl; return 0; }