示例#1
0
文件: stud.c 项目: gyepisam/stud
/* Read some data from the upstream secure socket via OpenSSL,
 * and buffer anything we get for writing to the backend */
static void client_read(struct ev_loop *loop, ev_io *w, int revents) {
    (void) revents;
    int t;    
    proxystate *ps = (proxystate *)w->data;
    if (ps->want_shutdown) {
        ev_io_stop(loop, &ps->ev_r_up);
        return;
    }
    char * buf = ringbuffer_write_ptr(&ps->ring_down);
    t = SSL_read(ps->ssl, buf, RING_DATA_LEN);
    if (t > 0) {
        ringbuffer_write_append(&ps->ring_down, t);
        if (ringbuffer_is_full(&ps->ring_down))
            ev_io_stop(loop, &ps->ev_r_up);
        safe_enable_io(ps, &ps->ev_w_down);
    }
    else {
        int err = SSL_get_error(ps->ssl, t);
        if (err == SSL_ERROR_WANT_WRITE) {
            start_handshake(ps, err);
        }
        else if (err == SSL_ERROR_WANT_READ) { } /* incomplete SSL data */
        else
            handle_fatal_ssl_error(ps, err);
    }
}
示例#2
0
文件: stud.c 项目: gyepisam/stud
/* Read some data from the backend when libev says data is available--
 * write it into the upstream buffer and make sure the write event is
 * enabled for the upstream socket */
static void back_read(struct ev_loop *loop, ev_io *w, int revents) {
    (void) revents;
    int t;
    proxystate *ps = (proxystate *)w->data;
    if (ps->want_shutdown) {
        ev_io_stop(loop, &ps->ev_r_down);
        return;
    }
    int fd = w->fd;
    char * buf = ringbuffer_write_ptr(&ps->ring_up);
    t = recv(fd, buf, RING_DATA_LEN, 0);

    if (t > 0) {
        ringbuffer_write_append(&ps->ring_up, t);
        if (ringbuffer_is_full(&ps->ring_up))
            ev_io_stop(loop, &ps->ev_r_down);
        safe_enable_io(ps, &ps->ev_w_up);
    }
    else if (t == 0) {
        LOG("{backend} Connection closed\n");
        shutdown_proxy(ps, SHUTDOWN_DOWN);
    }
    else {
        assert(t == -1);
        handle_socket_errno(ps);
    }
}
示例#3
0
bud_client_error_t bud_client_backend_out(bud_client_t* client) {
  int read;
  int err;
  size_t avail;
  char* out;
  bud_client_error_t cerr;

  /* If buffer is full - stop reading */
  cerr = bud_client_throttle(client,
                             &client->backend,
                             &client->backend.output);
  if (cerr.err.code == kBudErrClientThrottle)
    return bud_client_ok(&client->frontend);
  else if (!bud_is_ok(cerr.err))
    return cerr;

  do {
    avail = 0;
    out = ringbuffer_write_ptr(&client->backend.output, &avail);
    read = SSL_read(client->ssl, out, avail);
    DBG(&client->frontend, "SSL_read() => %d", read);
    if (read > 0) {
      ringbuffer_write_append(&client->backend.output, read);
      if (client->selected_backend->xforward &&
          !bud_client_xforward_done(client)) {
        cerr = bud_client_prepend_xforward(client);
        if (!bud_is_ok(cerr.err))
          return cerr;
      }

      cerr = bud_client_send(client, &client->backend);
      if (!bud_is_ok(cerr.err))
        return cerr;
    }

    /* info_cb() has closed front-end */
    if (client->close != kBudProgressNone)
      return bud_client_ok(&client->frontend);
  } while (read > 0);

  if (read > 0)
    goto success;

  err = SSL_get_error(client->ssl, read);
  if (err == SSL_ERROR_WANT_READ || err == SSL_ERROR_WANT_WRITE)
    goto success;

  /* Close-notify, most likely */
  if (err == SSL_ERROR_ZERO_RETURN)
    return bud_client_shutdown(client, &client->backend);

  return bud_client_error(bud_error_num(kBudErrClientSSLRead, err),
                          &client->frontend);

success:
  return bud_client_ok(&client->backend);
}
示例#4
0
文件: client.c 项目: noscripter/bud
void bud_client_read_cb(uv_stream_t* stream,
                        ssize_t nread,
                        const uv_buf_t* buf) {
  int r;
  bud_client_t* client;
  bud_client_side_t* side;
  bud_client_side_t* opposite;
  bud_client_error_t cerr;

  client = stream->data;
  side = bud_client_side_by_tcp(client, (uv_tcp_t*) stream);

  /* Commit data if there was no error */
  r = 0;
  if (nread >= 0)
    r = ringbuffer_write_append(&side->input, nread);

  DBG(side, "after read_cb() => %d", nread);

  /* Handle EOF */
  if (nread == UV_EOF) {
    side->reading = kBudProgressDone;

    /* Shutdown opposite side */
    opposite = side == &client->frontend ? &client->backend : &client->frontend;
    cerr = bud_client_shutdown(client, opposite);
    if (!bud_is_ok(cerr.err))
      goto done;
  }

  /* Try writing out data anyway */
  cerr = bud_client_cycle(client);
  if (!bud_is_ok(cerr.err))
    goto done;

  if ((r != 0 || nread < 0) && nread != UV_EOF) {
    if (nread < 0)
      cerr = bud_client_error(bud_error_num(kBudErrClientReadCb, nread), side);
    else
      cerr = bud_client_error(bud_error(kBudErrClientWriteAppend), side);

    /* Unrecoverable socket error, close */
    return bud_client_close(client, cerr);
  }

  /* If buffer is full - stop reading */
  cerr = bud_client_throttle(client, side, &side->input);

done:
  if (!bud_is_ok(cerr.err) && cerr.err.code != kBudErrClientThrottle)
    bud_client_close(client, cerr);
}
示例#5
0
文件: stud.c 项目: djs55/stud
/* Continue/complete the asynchronous connect() before starting data transmission
 * between front/backend */
static void handle_connect(struct ev_loop *loop, ev_io *w, int revents) {
    (void) revents;
    int t;
    proxystate *ps = (proxystate *)w->data;
    t = connect(ps->fd_down, backaddr->ai_addr, backaddr->ai_addrlen);
    if (!t || errno == EISCONN || !errno) {
        /* INIT */
        ev_io_stop(loop, &ps->ev_w_down);
        ev_io_init(&ps->ev_r_down, back_read, ps->fd_down, EV_READ);
        ev_io_init(&ps->ev_w_down, back_write, ps->fd_down, EV_WRITE);
        start_handshake(ps, SSL_ERROR_WANT_READ); /* for client-first handshake */
        ev_io_start(loop, &ps->ev_r_down);
        if (OPTIONS.WRITE_IP_OCTET) {
            char *ring_pnt = ringbuffer_write_ptr(&ps->ring_down);
            assert(ps->remote_ip.ss_family == AF_INET ||
                   ps->remote_ip.ss_family == AF_INET6);
            *ring_pnt++ = (unsigned char) ps->remote_ip.ss_family;
            if (ps->remote_ip.ss_family == AF_INET6) {
                memcpy(ring_pnt, &((struct sockaddr_in6 *) &ps->remote_ip)
                       ->sin6_addr.s6_addr, 16U);
                ringbuffer_write_append(&ps->ring_down, 1U + 16U);
            } else {
                memcpy(ring_pnt, &((struct sockaddr_in *) &ps->remote_ip)
                       ->sin_addr.s_addr, 4U);
                ringbuffer_write_append(&ps->ring_down, 1U + 4U);
            }
            ev_io_start(loop, &ps->ev_w_down);
        }
    }
    else if (errno == EINPROGRESS || errno == EINTR || errno == EALREADY) {
        /* do nothing, we'll get phoned home again... */
    }
    else {
        perror("{backend-connect}");
        shutdown_proxy(ps, SHUTDOWN_HARD);
    }
}
示例#6
0
文件: ringbuffer.c 项目: Acconut/bud
int ringbuffer_insert(ringbuffer* rb,
                      size_t off,
                      const char* data,
                      size_t length) {
  bufent* b;
  bufent* next;
  bufent* start;
  size_t left;
  size_t offset;
  int r;

  assert(length < RING_BUFFER_LEN);

  /* Find owner of `off` */
  left = ringbuffer_size(rb);
  start = rb->read_head;
  while (off != 0) {
    if (off < RB_BUF_SIZE(start))
      break;
    off -= RB_BUF_SIZE(start);
    left -= RB_BUF_SIZE(start);
    start = start->next;
  }

  /* Shift everything after `off` forward by `length` */
  b = rb->write_head;

  /* Ensure that we have enough space for shift */
  r = ringbuffer_write_append(rb, length);
  if (r != 0)
    return r;

  next = rb->write_head;
  while (left > 0) {
    /* Copy part of the data from the end of current to the next buffer */
    if (next != b)
      memcpy(next->data, b->data + RING_BUFFER_LEN - length, length);

    /* Move rest inside current buffer */
    offset = b->read_pos;
    if (b == start)
      offset += off;

    if (offset + length < RING_BUFFER_LEN) {
      memmove(b->data + offset + length,
              b->data + offset,
              RING_BUFFER_LEN - offset - length);
    }

    if (b == start)
      break;

    left -= RB_BUF_SIZE(b);

    /* Select previous buffer, O(N) */
    next = b;
    b = start;
    while (b->next != next)
      b = b->next;
  }

  /* Copy input data into the free space */
  if (off + length > RING_BUFFER_LEN) {
    size_t delta;

    delta = off + length - RING_BUFFER_LEN;
    memcpy(start->data + off, data, length - delta);
    memcpy(next->data, data + length - delta, delta);
  } else {
    memcpy(start->data + off, data, length);
  }

  return 0;
}
示例#7
0
文件: client.c 项目: noscripter/bud
bud_client_error_t bud_client_backend_out(bud_client_t* client) {
  int read;
  int err;
  size_t avail;
  char* out;
  bud_client_error_t cerr;

  /* If buffer is full - stop reading */
  cerr = bud_client_throttle(client,
                             &client->backend,
                             &client->backend.output);
  if (cerr.err.code == kBudErrClientThrottle)
    return bud_client_ok(&client->frontend);
  else if (!bud_is_ok(cerr.err))
    return cerr;

  do {
    avail = 0;
    int init_trigger;

    init_trigger = SSL_is_init_finished(client->ssl);
    out = ringbuffer_write_ptr(&client->backend.output, &avail);
    read = SSL_read(client->ssl, out, avail);
    init_trigger ^= SSL_is_init_finished(client->ssl);

    DBG(&client->frontend, "SSL_read() => %d", read);
    if (read > 0)
      ringbuffer_write_append(&client->backend.output, read);

    /* Send proxyline once the handshake will end */
    if (init_trigger != 0) {
      cerr = bud_client_prepend_proxyline(client);
      if (!bud_is_ok(cerr.err))
        return cerr;
    }

    /* If there is any new data - try to append x-forwarded-for */
    if (read > 0 &&
        client->selected_backend->xforward &&
        !bud_client_xforward_done(client)) {
      cerr = bud_client_prepend_xforward(client);
      if (!bud_is_ok(cerr.err))
        return cerr;
    }

    /* Either proxyline or incoming data - need to send stuff to the client */
    if (init_trigger != 0 || read > 0) {
      cerr = bud_client_send(client, &client->backend);
      if (!bud_is_ok(cerr.err))
        return cerr;
    }

    /* info_cb() has closed front-end */
    if (client->close != kBudProgressNone)
      return bud_client_ok(&client->frontend);
  } while (read > 0);

  if (read > 0)
    goto success;

  err = SSL_get_error(client->ssl, read);
  if (err == SSL_ERROR_WANT_READ ||
      err == SSL_ERROR_WANT_WRITE ||
      err == SSL_ERROR_WANT_X509_LOOKUP) {
    goto success;
  }

  /* Close-notify, most likely */
  if (err == SSL_ERROR_ZERO_RETURN)
    return bud_client_shutdown(client, &client->backend);

  return bud_client_error(bud_error_num(kBudErrClientSSLRead, err),
                          &client->frontend);

success:
  return bud_client_ok(&client->backend);
}
示例#8
0
文件: test.c 项目: Acconut/bud
int main() {
  int i;
  int j;
  int r;
  int after;
  ssize_t len;
  char* ptr;

  data = malloc(TEST_DATA_SIZE);
  assert(data != NULL);
  ringbuffer_init(&rb);

  /* Fill test data */
  for (i = 0; i < TEST_DATA_SIZE; i++)
    data[i] = (i * i) % 137;

  /* Fill ringbuffer */
  i = 0;
  after = 0;
  while (i < TEST_DATA_SIZE - TEST_INSERT_LEN) {
    if (after)
      len = TEST_DATA_SIZE - i - TEST_INSERT_LEN;
    else
      len = TEST_INSERT_OFF - i;

    ptr = ringbuffer_write_ptr(&rb, &len);
    ASSERT(ptr != NULL);

    /* Always make progress */
    ASSERT(len > 0);

    if (after)
      memcpy(ptr, data + i + TEST_INSERT_LEN, len);
    else
      memcpy(ptr, data + i, len);

    i += len;
    r = ringbuffer_write_append(&rb, len);
    ASSERT(r == 0);

    if (i == TEST_INSERT_OFF)
      after = 1;
  }
  ASSERT(ringbuffer_size(&rb) == TEST_DATA_SIZE - TEST_INSERT_LEN);

  /* Insert stuff */
  ringbuffer_insert(&rb,
                    TEST_INSERT_OFF,
                    data + TEST_INSERT_OFF,
                    TEST_INSERT_LEN);

  /* Read from it */
  i = 0;
  while (i < TEST_DATA_SIZE) {
    len = TEST_DATA_SIZE - i;
    ptr = ringbuffer_read_next(&rb, &len);
    ASSERT(ptr != NULL);

    /* Always make progress */
    ASSERT(len > 0);

    for (j = 0; j < len; j++)
      ASSERT(ptr[j] == data[i + j]);

    ringbuffer_read_skip(&rb, len);
    i += len;
  }

  /* Destroy it */
  ringbuffer_destroy(&rb);

  return 0;
}
示例#9
0
文件: stud.c 项目: gyepisam/stud
/* Continue/complete the asynchronous connect() before starting data transmission
 * between front/backend */
static void handle_connect(struct ev_loop *loop, ev_io *w, int revents) {
    (void) revents;
    int t;
    proxystate *ps = (proxystate *)w->data;
    char tcp6_address_string[INET6_ADDRSTRLEN];
    size_t written = 0;
    t = connect(ps->fd_down, backaddr->ai_addr, backaddr->ai_addrlen);
    if (!t || errno == EISCONN || !errno) {
        /* INIT */
        ev_io_stop(loop, &ps->ev_w_down);
        ev_io_init(&ps->ev_r_down, back_read, ps->fd_down, EV_READ);
        ev_io_init(&ps->ev_w_down, back_write, ps->fd_down, EV_WRITE);
        start_handshake(ps, SSL_ERROR_WANT_READ); /* for client-first handshake */
        ev_io_start(loop, &ps->ev_r_down);
        if (OPTIONS.WRITE_PROXY_LINE) {
            char *ring_pnt = ringbuffer_write_ptr(&ps->ring_down);
            assert(ps->remote_ip.ss_family == AF_INET ||
		   ps->remote_ip.ss_family == AF_INET6);
	    if(ps->remote_ip.ss_family == AF_INET) {
	      struct sockaddr_in* addr = (struct sockaddr_in*)&ps->remote_ip;
	      written = snprintf(ring_pnt,
				 RING_DATA_LEN,
				 tcp_proxy_line,
				 "TCP4",
				 inet_ntoa(addr->sin_addr),
				 ntohs(addr->sin_port));
	    }
	    else if (ps->remote_ip.ss_family == AF_INET6) {
	      struct sockaddr_in6* addr = (struct sockaddr_in6*)&ps->remote_ip;
	      inet_ntop(AF_INET6,&(addr->sin6_addr),tcp6_address_string,INET6_ADDRSTRLEN);
	      written = snprintf(ring_pnt,
				 RING_DATA_LEN,
				 tcp_proxy_line,
				 "TCP6",
				 tcp6_address_string,
				 ntohs(addr->sin6_port));
	    }   
            ringbuffer_write_append(&ps->ring_down, written);
            ev_io_start(loop, &ps->ev_w_down);
        }
        else if (OPTIONS.WRITE_IP_OCTET) {
            char *ring_pnt = ringbuffer_write_ptr(&ps->ring_down);
            assert(ps->remote_ip.ss_family == AF_INET ||
                   ps->remote_ip.ss_family == AF_INET6);
            *ring_pnt++ = (unsigned char) ps->remote_ip.ss_family;
            if (ps->remote_ip.ss_family == AF_INET6) {
                memcpy(ring_pnt, &((struct sockaddr_in6 *) &ps->remote_ip)
                       ->sin6_addr.s6_addr, 16U);
                ringbuffer_write_append(&ps->ring_down, 1U + 16U);
            } else {
                memcpy(ring_pnt, &((struct sockaddr_in *) &ps->remote_ip)
                       ->sin_addr.s_addr, 4U);
                ringbuffer_write_append(&ps->ring_down, 1U + 4U);
            }
            ev_io_start(loop, &ps->ev_w_down);
        }
    }
    else if (errno == EINPROGRESS || errno == EINTR || errno == EALREADY) {
        /* do nothing, we'll get phoned home again... */
    }
    else {
        perror("{backend-connect}");
        shutdown_proxy(ps, SHUTDOWN_HARD);
    }
}