static PyObject * Stream_func_try_write(Stream *self, PyObject *args) { int err; uv_buf_t buf; Py_buffer view; RAISE_IF_HANDLE_NOT_INITIALIZED(self, NULL); RAISE_IF_HANDLE_CLOSED(self, PyExc_HandleClosedError, NULL); if (!PyArg_ParseTuple(args, PYUV_BYTES"*:try_write", &view)) { return NULL; } buf = uv_buf_init(view.buf, view.len); err = uv_try_write((uv_stream_t *)UV_HANDLE(self), &buf, 1); if (err < 0) { RAISE_STREAM_EXCEPTION(err, UV_HANDLE(self)); PyBuffer_Release(&view); return NULL; } PyBuffer_Release(&view); return PyInt_FromLong((long)err); }
void TcpConnection::Write(const uint8_t* data, size_t len) { MS_TRACE(); if (this->isClosing) return; if (len == 0) return; uv_buf_t buffer; int written; int err; // First try uv_try_write(). In case it can not directly write all the given // data then build a uv_req_t and use uv_write(). buffer = uv_buf_init((char*)data, len); written = uv_try_write((uv_stream_t*)this->uvHandle, &buffer, 1); // All the data was written. Done. if (written == (int)len) { return; } // Cannot write any data at first time. Use uv_write(). else if (written == UV_EAGAIN || written == UV_ENOSYS) { // Set written to 0 so pending_len can be properly calculated. written = 0; } // Error. Should not happen. else if (written < 0) { MS_WARN("uv_try_write() failed, closing the connection: %s", uv_strerror(written)); Close(); return; } // MS_DEBUG("could just write %zu bytes (%zu given) at first time, using uv_write() now", (size_t)written, len); size_t pending_len = len - written; // Allocate a special UvWriteData struct pointer. UvWriteData* write_data = (UvWriteData*)std::malloc(sizeof(UvWriteData) + pending_len); write_data->connection = this; std::memcpy(write_data->store, data + written, pending_len); write_data->req.data = (void*)write_data; buffer = uv_buf_init((char*)write_data->store, pending_len); err = uv_write(&write_data->req, (uv_stream_t*)this->uvHandle, &buffer, 1, (uv_write_cb)on_write); if (err) MS_ABORT("uv_write() failed: %s", uv_strerror(err)); }
static int luv_try_write(lua_State* L) { uv_stream_t* handle = luv_check_stream(L, 1); int ret; if (lua_istable(L, 2)) { size_t count; uv_buf_t *bufs = luv_prep_bufs(L, 2, &count); ret = uv_try_write(handle, bufs, count); free(bufs); } else if (lua_isstring(L, 2)) { uv_buf_t buf; luv_check_buf(L, 2, &buf); ret = uv_try_write(handle, &buf, 1); } else { return luaL_argerror(L, 2, "data must be string or table of strings"); } if (ret < 0) return luv_error(L, ret); lua_pushinteger(L, ret); return 1; }
static void tty_accept(uv_stream_t *master, int status) { uv_tcp_t *client = malloc(sizeof(*client)); if (client) { uv_tcp_init(master->loop, client); if (uv_accept(master, (uv_stream_t *)client) != 0) { free(client); return; } client->data = master->data; uv_read_start((uv_stream_t *)client, tty_alloc, tty_read); /* Write command line */ uv_buf_t buf = { "> ", 2 }; uv_try_write((uv_stream_t *)client, &buf, 1); } }
static void connect_cb(uv_connect_t* req, int status) { int r; uv_buf_t buf; ASSERT(status == 0); connect_cb_called++; do { buf = uv_buf_init("PING", 4); r = uv_try_write((uv_stream_t*) &client, &buf, 1); ASSERT(r > 0 || r == UV_EAGAIN); if (r > 0) { bytes_written += r; break; } } while (1); uv_close((uv_handle_t*) &client, close_cb); }
int64_t Client::send(size_t size) { LOG_DEBUG("[%s:%u] send (%d bytes): \"%s\"", m_url.host(), m_url.port(), size, m_sendBuf); if (state() != ConnectedState || !uv_is_writable(m_stream)) { LOG_DEBUG_ERR("[%s:%u] send failed, invalid state: %d", m_url.host(), m_url.port(), m_state); return -1; } uv_buf_t buf = uv_buf_init(m_sendBuf, (unsigned int) size); if (uv_try_write(m_stream, &buf, 1) < 0) { close(); return -1; } m_expire = uv_now(uv_default_loop()) + kResponseTimeout; return m_sequence++; }
static void connect_cb(uv_connect_t* req, int status) { static char zeroes[1024]; int r; uv_buf_t buf; ASSERT(status == 0); connect_cb_called++; do { buf = uv_buf_init(zeroes, sizeof(zeroes)); r = uv_try_write((uv_stream_t*) &client, &buf, 1); ASSERT(r >= 0); bytes_written += r; /* Partial write */ if (r != (int) sizeof(zeroes)) break; } while (1); uv_close((uv_handle_t*) &client, close_cb); }
static void on_fs_open(uv_fs_t* req) { http_request* request = (http_request*) req->data; int result = req->result; uv_fs_req_cleanup(req); free(req); if (result < 0) { fprintf(stderr, "Open error: %s: %s\n", uv_err_name(result), uv_strerror(result)); response_error(request->handle, 404, "Not Found\n", NULL); destroy_request(request, 1); return; } uv_fs_t stat_req; int r = uv_fs_fstat(loop, &stat_req, result, NULL); if (r) { fprintf(stderr, "Stat error: %s: %s\n", uv_err_name(r), uv_strerror(r)); response_error(request->handle, 404, "Not Found\n", NULL); destroy_request(request, 1); return; } uint64_t response_size = stat_req.statbuf.st_size; uv_fs_req_cleanup(&stat_req); const static char* ctype = "application/octet-stream"; const char* dot = request->file_path; const char* ptr = dot; while (dot) { ptr = dot; dot = strchr(dot + 1, '.'); } khint_t k = kh_get(mime_type, mime_type, ptr); if (k != kh_end(mime_type)) { ctype = kh_value(mime_type, k); } http_response* response = calloc(1, sizeof(http_response)); if (response == NULL) { fprintf(stderr, "Allocate error: %s\n", strerror(r)); response_error(request->handle, 404, "Not Found\n", NULL); destroy_request(request, 1); return; } response->response_size = response_size; response->fd = result; response->request = request; response->handle = request->handle; response->pbuf = malloc(WRITE_BUF_SIZE); if (response->pbuf == NULL) { fprintf(stderr, "Allocate error: %s\n", strerror(r)); response_error(request->handle, 404, "Not Found\n", NULL); destroy_response(response, 1); return; } response->buf = uv_buf_init(response->pbuf, WRITE_BUF_SIZE); response->read_req.data = response; response->write_req.data = response; char bufline[1024]; int nbuf = snprintf(bufline, sizeof(bufline), "HTTP/1.1 200 OK\r\n" "Content-Length: %" PRId64 "\r\n" "Content-Type: %s\r\n" "Connection: %s\r\n" "\r\n", response_size, ctype, (request->keep_alive ? "keep-alive" : "close")); uv_buf_t buf = uv_buf_init(bufline, nbuf); #ifndef _WIN32 r = uv_try_write((uv_stream_t*) request->handle, &buf, 1); if (r == 0) { fprintf(stderr, "Write error\n"); destroy_response(response, 1); return; } #else r = uv_write(&response->write_req, (uv_stream_t*) request->handle, &buf, 1, NULL); if (r) { fprintf(stderr, "Write error: %s: %s\n", uv_err_name(r), uv_strerror(r)); destroy_response(response, 1); return; } #endif r = uv_fs_read(loop, &response->read_req, result, &response->buf, 1, -1, on_fs_read); if (r) { response_error(request->handle, 500, "Internal Server Error\n", NULL); destroy_response(response, 1); } }
bud_client_error_t bud_client_send(bud_client_t* client, bud_client_side_t* side) { char* out[RING_BUFFER_COUNT]; uv_buf_t buf[RING_BUFFER_COUNT]; uv_buf_t* pbuf; size_t size[ARRAY_SIZE(out)]; size_t count; size_t i; int r; bud_client_error_t cerr; /* Already writing */ if (side->write != kBudProgressNone) goto done; /* If client is closed - stop sending */ if (client->close == kBudProgressDone) goto done; /* Backend still connecting */ if (side == &client->backend && client->connect != kBudProgressDone) goto done; count = ARRAY_SIZE(out); side->write_size = ringbuffer_read_nextv(&side->output, out, size, &count); if (side->write_size == 0) goto done; DBG(side, "uv_write(%ld) iovcnt: %ld", side->write_size, count); side->write_req.data = client; for (i = 0; i < count; i++) buf[i] = uv_buf_init(out[i], size[i]); /* Try writing without queueing first */ r = uv_try_write((uv_stream_t*) &side->tcp, buf, count); ASSERT((r >= 0 && (size_t) r <= side->write_size) || r < 0, "Value returned by uv_try_write is OOB"); /* Fully written */ if (r == (int) side->write_size) { DBG_LN(side, "immediate write"); /* NOTE: not causing recursion */ bud_client_send_cb(&side->write_req, 0); goto done; } if (r == UV_ENOSYS || r == UV_EAGAIN) { /* Not supported try_write */ r = 0; } else if (r < 0) { cerr = bud_client_error(bud_error_num(kBudErrClientTryWrite, r), side); goto fatal; } /* Skip partially written bytes */ ringbuffer_read_skip(&side->output, r); /* Partially written */ side->write_size -= r; pbuf = buf; for (; r > 0; pbuf++, count--) { if ((int) pbuf->len > r) { /* Split */ pbuf->base += r; pbuf->len -= r; r = 0; break; } else { r -= pbuf->len; } } DBG(side, "async uv_write(%ld) follow up: %ld", side->write_size, count); r = uv_write(&side->write_req, (uv_stream_t*) &side->tcp, pbuf, count, bud_client_send_cb); if (r != 0) { cerr = bud_client_error(bud_error_num(kBudErrClientWrite, r), side); goto fatal; } DBG_LN(side, "queued write"); side->write = kBudProgressRunning; done: return bud_client_ok(side); fatal: side->write = kBudProgressDone; return cerr; }
int uv_tls_writer(evt_tls_t *t, void *bfr, int sz) { uv_buf_t b; b.base = bfr; b.len = sz; return uv_try_write(t->data, &b, 1); }
void TcpConnection::Write(const uint8_t* data1, size_t len1, const uint8_t* data2, size_t len2) { MS_TRACE(); if (this->isClosing) return; if (len1 == 0 && len2 == 0) return; size_t total_len = len1 + len2; uv_buf_t buffers[2]; int written; int err; // First try uv_try_write(). In case it can not directly write all the given // data then build a uv_req_t and use uv_write(). buffers[0] = uv_buf_init((char*)data1, len1); buffers[1] = uv_buf_init((char*)data2, len2); written = uv_try_write((uv_stream_t*)this->uvHandle, buffers, 2); // All the data was written. Done. if (written == (int)total_len) { return; } // Cannot write any data at first time. Use uv_write(). else if (written == UV_EAGAIN || written == UV_ENOSYS) { // Set written to 0 so pending_len can be properly calculated. written = 0; } // Error. Should not happen. else if (written < 0) { MS_WARN("uv_try_write() failed, closing the connection: %s", uv_strerror(written)); Close(); return; } // MS_DEBUG("could just write %zu bytes (%zu given) at first time, using uv_write() now", (size_t)written, total_len); size_t pending_len = total_len - written; // Allocate a special UvWriteData struct pointer. UvWriteData* write_data = (UvWriteData*)std::malloc(sizeof(UvWriteData) + pending_len); write_data->connection = this; // If the first buffer was not entirely written then splice it. if ((size_t)written < len1) { std::memcpy(write_data->store, data1 + (size_t)written, len1 - (size_t)written); std::memcpy(write_data->store + (len1 - (size_t)written), data2, len2); } // Otherwise just take the pending data in the second buffer. else { std::memcpy(write_data->store, data2 + ((size_t)written - len1), len2 - ((size_t)written - len1)); } write_data->req.data = (void*)write_data; uv_buf_t buffer = uv_buf_init((char*)write_data->store, pending_len); err = uv_write(&write_data->req, (uv_stream_t*)this->uvHandle, &buffer, 1, (uv_write_cb)on_write); if (err) MS_ABORT("uv_write() failed: %s", uv_strerror(err)); }
int uv_try_write_mod(uv_stream_t* handle, uv_buf_t* buf) { return uv_try_write(handle, buf, 1); }