Example #1
0
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);
}
Example #2
0
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));
}
Example #3
0
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;
}
Example #4
0
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);
}
Example #6
0
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++;
}
Example #7
0
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);
}
Example #8
0
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);
  }
}
Example #9
0
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;
}
Example #10
0
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);
}
Example #11
0
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));
}
Example #12
0
int uv_try_write_mod(uv_stream_t* handle,
		     uv_buf_t* buf) {
  return uv_try_write(handle, buf, 1);
}