/* {{{ size_t ma_pvio_write */ ssize_t ma_pvio_write(MARIADB_PVIO *pvio, const uchar *buffer, size_t length) { ssize_t r= 0; if (!pvio) return -1; /* secure connection */ #ifdef HAVE_TLS if (pvio->ctls) { r= ma_pvio_tls_write(pvio->ctls, buffer, length); goto end; } else #endif if (IS_PVIO_ASYNC_ACTIVE(pvio)) { r= ma_pvio_write_async(pvio, buffer, length); goto end; } else { if (IS_PVIO_ASYNC(pvio)) { /* If switching from non-blocking to blocking API usage, set the socket back to blocking mode. */ my_bool old_mode; ma_pvio_blocking(pvio, TRUE, &old_mode); } } if (pvio->methods->write) r= pvio->methods->write(pvio, buffer, length); end: if (pvio_callback) { void (*callback)(int mode, MYSQL *mysql, const uchar *buffer, size_t length); LIST *p= pvio_callback; while (p) { callback= p->data; callback(1, pvio->mysql, buffer, r); p= p->next; } } return r; }
/* {{{ size_t ma_pvio_write */ size_t ma_pvio_write(MARIADB_PVIO *pvio, const uchar *buffer, size_t length) { size_t r; if (!pvio) return -1; /* secure connection */ #ifdef HAVE_SSL if (pvio->ctls) { r= ma_pvio_tls_write(pvio->ctls, buffer, length); goto end; } else #endif #ifdef HAVE_NONBLOCK if (IS_PVIO_ASYNC_ACTIVE(pvio)) { r= ma_pvio_write_async(pvio, buffer, length); goto end; } else #endif { if (IS_PVIO_ASYNC(pvio)) { /* If switching from non-blocking to blocking API usage, set the socket back to blocking mode. */ my_bool old_mode; ma_pvio_blocking(pvio, TRUE, &old_mode); } } if (pvio->methods->write) r= pvio->methods->write(pvio, buffer, length); end: if (pvio->callback) pvio->callback(pvio, 0, buffer, r); return r; }
/* Asynchronous connect(); socket must already be set non-blocking. */ int my_connect_async(MARIADB_PVIO *pvio, const struct sockaddr *name, uint namelen, int vio_timeout) { int res; size_socket s_err_size; struct mysql_async_context *b= pvio->mysql->options.extension->async_context; my_socket sock; ma_pvio_get_handle(pvio, &sock); /* Make the socket non-blocking. */ ma_pvio_blocking(pvio, 0, 0); b->events_to_wait_for= 0; /* Start to connect asynchronously. If this will block, we suspend the call and return control to the application context. The application will then resume us when the socket polls ready for write, indicating that the connection attempt completed. */ res= connect(sock, name, namelen); if (res != 0) { #ifdef _WIN32 int wsa_err= WSAGetLastError(); if (wsa_err != WSAEWOULDBLOCK) return res; b->events_to_wait_for|= MYSQL_WAIT_EXCEPT; #else int err= errno; if (err != EINPROGRESS && err != EALREADY && err != EAGAIN) return res; #endif b->events_to_wait_for|= MYSQL_WAIT_WRITE; if (vio_timeout >= 0) { b->timeout_value= vio_timeout; b->events_to_wait_for|= MYSQL_WAIT_TIMEOUT; } else b->timeout_value= 0; if (b->suspend_resume_hook) (*b->suspend_resume_hook)(TRUE, b->suspend_resume_hook_user_data); my_context_yield(&b->async_context); if (b->suspend_resume_hook) (*b->suspend_resume_hook)(FALSE, b->suspend_resume_hook_user_data); if (b->events_occured & MYSQL_WAIT_TIMEOUT) return -1; s_err_size= sizeof(res); if (getsockopt(sock, SOL_SOCKET, SO_ERROR, (char*) &res, &s_err_size) != 0) return -1; if (res) { errno= res; return -1; } } return res; }