Пример #1
0
Файл: conn.c Проект: 0xffea/shim
static void
write_socks_request(struct conninfo *info)
{
	if (info->socks == SOCKS_4) {
		struct sockaddr_in *sin = (struct sockaddr_in*)&info->addr;

		if (info->addr.ss_family != AF_INET) {
			finish_connection(info, 0,
				"SOCKS 4 can't handle ipv6!");
		}

		/* connection request */
		bufferevent_write(info->bev, "\x04\x01", 2);
		bufferevent_write(info->bev, &sin->sin_port,
				  sizeof(sin->sin_port));
		bufferevent_write(info->bev, &sin->sin_addr.s_addr,
				  sizeof(sin->sin_addr.s_addr));
		bufferevent_write(info->bev, "xx", 3);
	} else {
		ev_uint16_t port = htons(info->port);

		assert(info->host != NULL);
		bufferevent_write(info->bev, "\x04\x01", 2);
		bufferevent_write(info->bev, &port, sizeof(port));
		bufferevent_write(info->bev, "\x00\x00\x00\xff", 4);
		bufferevent_write(info->bev, "xx", 3);
		bufferevent_write(info->bev, info->host, strlen(info->host)+1);
	}

	bufferevent_enable(info->bev, EV_READ);
}
Пример #2
0
static void
idle( ClientData client_data, struct timeval* nowP )
    {
    int cnum;
    connecttab* c;

    for ( cnum = 0; cnum < max_connects; ++cnum )
	{
	c = &connects[cnum];
	switch ( c->conn_state )
	    {
	    case CNST_READING:
	    if ( nowP->tv_sec - c->active_at >= IDLE_READ_TIMELIMIT )
		{
		httpd_send_err(
		    c->hc, 408, httpd_err408title, "", httpd_err408form, "" );
		finish_connection( c, nowP );
		}
	    break;
	    case CNST_SENDING:
	    case CNST_PAUSING:
	    if ( nowP->tv_sec - c->active_at >= IDLE_SEND_TIMELIMIT )
		{
		clear_connection( c, nowP );
		}
	    break;
	    case CNST_SLEEPING:;
	    }
	}
    }
static void idle(ClientData client_data, struct timeval *nowP)
{
  int cnum;
  struct connect_s *conn;

  for (cnum = 0; cnum < AVAILABLE_FDS; ++cnum)
    {
      conn = &connects[cnum];
      switch (conn->conn_state)
        {
        case CNST_READING:
          if (nowP->tv_sec - conn->active_at >= CONFIG_THTTPD_IDLE_READ_LIMIT_SEC)
            {
              ndbg("%s connection timed out reading\n", httpd_ntoa(&conn->hc->client_addr));
              httpd_send_err(conn->hc, 408, httpd_err408title, "",
                             httpd_err408form, "");
              finish_connection(conn, nowP);
            }
          break;

        case CNST_SENDING:
          if (nowP->tv_sec - conn->active_at >= CONFIG_THTTPD_IDLE_SEND_LIMIT_SEC)
            {
              ndbg("%s connection timed out sending\n", httpd_ntoa(&conn->hc->client_addr));
              clear_connection(conn, nowP);
            }
          break;
        }
    }
}
Пример #4
0
static void must_succeed(grpc_exec_ctx *exec_ctx, void *arg, int success) {
  GPR_ASSERT(g_connecting != NULL);
  GPR_ASSERT(success);
  grpc_endpoint_shutdown(exec_ctx, g_connecting);
  grpc_endpoint_destroy(exec_ctx, g_connecting);
  g_connecting = NULL;
  finish_connection();
}
Пример #5
0
Файл: conn.c Проект: 0xffea/shim
int
conn_connect_bufferevent(struct bufferevent *bev, struct evdns_base *dns,
			 int family, const char *name, int port,
			 conn_connectcb conncb, void *arg)
{
	struct conninfo *info;
	int rv = -1;
	

	info = mem_calloc(1, sizeof(*info));
	info->bev = bev;
	info->on_connect = conncb;
	info->cbarg = arg;
	info->connecting = 1;
	info->socks = use_socks;

	bufferevent_setcb(bev, conn_readcb, NULL, conn_errorcb, info);
	if (use_socks != SOCKS_NONE) {
		info->host = mem_strdup(name);
		info->port = port;
		if (use_socks == SOCKS_4a) {
			rv = bufferevent_socket_connect(bev,
					(struct sockaddr*)&socks_addr,
					socks_addr_len);
			return rv;
		}
#ifndef DISABLE_DIRECT_CONNECTIONS
		else {
			struct evutil_addrinfo hint;
			char portstr[NI_MAXSERV];

			evutil_snprintf(portstr, sizeof(portstr), "%d", port);
			memset(&hint, 0, sizeof(hint));
			hint.ai_family = AF_INET;
			hint.ai_protocol = IPPROTO_TCP;
			hint.ai_socktype = SOCK_STREAM;

			evdns_getaddrinfo(dns, name, portstr, &hint,
				          socks_resolvecb, info);
			return 0;
		}
#endif
	}
#ifdef DISABLE_DIRECT_CONNECTIONS
	{
		const char *msg;
		msg = "Direct connections disabled, but I have no SOCKS 4a "
		      "proxy to connect to!";
		log_error("conn: %s", msg);
		finish_connection(info, 0, msg);
	}
#else
	rv =  bufferevent_socket_connect_hostname(bev, dns, family, name, port);
#endif

	return rv;
}
Пример #6
0
static void must_succeed(grpc_exec_ctx *exec_ctx, void *arg,
                         grpc_error *error) {
  GPR_ASSERT(g_connecting != NULL);
  GPR_ASSERT(error == GRPC_ERROR_NONE);
  grpc_endpoint_shutdown(
      exec_ctx, g_connecting,
      GRPC_ERROR_CREATE_FROM_STATIC_STRING("must_succeed called"));
  grpc_endpoint_destroy(exec_ctx, g_connecting);
  g_connecting = NULL;
  finish_connection(exec_ctx);
}
Пример #7
0
static void
handle_read_2( connecttab *c, struct timeval *tvP )
    {
    httpd_conn* hc = c->hc;
    ClientData client_data;

    /* Fill in end_byte_index. */
    if ( hc->got_range )
	{
	c->next_byte_index = hc->first_byte_index;
	c->end_byte_index = hc->last_byte_index + 1;
	}
    else if ( hc->bytes_to_send < 0 )
	c->end_byte_index = 0;
    else
	c->end_byte_index = hc->bytes_to_send;

    /* Check if it's already handled. */
    if ( hc->body_data == (char*) 0 )
	{
	/* No body data means someone else is handling it. */
	c->next_byte_index = hc->bytes_sent;
	finish_connection( c, tvP );
	return;
	}
    if ( c->next_byte_index >= c->end_byte_index )
	{
	/* There's nothing to send. */
	finish_connection( c, tvP );
	return;
	}

    /* Cool, we have a valid connection and a file to send to it. */
    c->conn_state = CNST_SENDING;
    c->started_at = tvP->tv_sec;
    c->wouldblock_delay = 0;
    client_data.p = c;

    fdwatch_del_fd( hc->conn_fd );
    fdwatch_add_fd( hc->conn_fd, c, FDW_WRITE );
    }
Пример #8
0
Файл: conn.c Проект: 0xffea/shim
static void
conn_errorcb(struct bufferevent *bev, short what, void *arg)
{
	struct conninfo *info = arg;

	if (info->connecting) {
		info->connecting = 0;
		if (what & BEV_EVENT_CONNECTED) {
			if (info->socks != SOCKS_NONE)
				write_socks_request(info);
			else
				finish_connection(info, 1, NULL);
		} else {
			// XXX need better err msg
			const char *msg = "Connection failed";
			if (info->socks != SOCKS_NONE)
				msg = "Connection to proxy server failed";
			finish_connection(info, 0, msg);
		}
	} else {
		finish_connection(info, 0, "SOCKS I/O error");
	}
}
Пример #9
0
Файл: conn.c Проект: 0xffea/shim
static void
conn_readcb(struct bufferevent *bev, void *arg)
{
	struct conninfo *info = arg;
	struct evbuffer *inbuf = bufferevent_get_input(bev);
	unsigned char *data;
	unsigned char code;

	/* socks4 and socks4a both have an 8 byte response */
	if (evbuffer_get_length(inbuf) < 8) {
		log_debug("conn: waiting for full socks response");
		return;
	}

	data = evbuffer_pullup(inbuf, 8);
	code = data[1];
	evbuffer_drain(inbuf, 8);

	if (code != 0x5a) {
		finish_connection(info, 0, socks4_error_to_string(code));
	} else {
		finish_connection(info, 1, NULL);
	}
}
Пример #10
0
static void
httpd_conn_wakeup( ClientData client_data, struct timeval* nowP )
    {
    connecttab* c = client_data.p;

    c->conn_state = CNST_READING;
    c->wakeup_timer = (Timer*) 0;
    if( httpd_continue_request( c->hc, nowP ) < 0 )
        {
        finish_connection( c, nowP );
        return;
        }
    if( c->conn_state == CNST_READING )
      handle_read_2( c, nowP );
    }
Пример #11
0
void socks_resolvecb(int result, struct evutil_addrinfo *ai, void *arg)
{
	struct conninfo *info = arg;

	if (result) {
		char buf[256];
		evutil_snprintf(buf, sizeof(buf), "DNS Failure: %s",
				evutil_gai_strerror(result));
		finish_connection(info, 0, buf);
	} else {
		log_debug("conn: socks resolve %s",
			  format_addr(ai->ai_addr));
		assert(ai->ai_addrlen <= sizeof(info->addr));
		memcpy(&info->addr, ai->ai_addr, ai->ai_addrlen);
		info->addr_len = ai->ai_addrlen;
		bufferevent_socket_connect(info->bev,
					   (struct sockaddr*)&socks_addr,
					   socks_addr_len);
	}

	if (ai)
		evutil_freeaddrinfo(ai);
}
Пример #12
0
static void
deinit_socket_server (assuan_context_t ctx)
{
  finish_connection (ctx);
}
static void handle_read(struct connect_s *conn, struct timeval *tv)
{
  ClientData client_data;
  httpd_conn *hc = conn->hc;
  off_t actual;
  int sz;

  /* Is there room in our buffer to read more bytes? */

  if (hc->read_idx >= hc->read_size)
    {
      if (hc->read_size > CONFIG_THTTPD_MAXREALLOC)
        {
          BADREQUEST("MAXREALLOC");
          goto errout_with_400;
        }
      httpd_realloc_str(&hc->read_buf, &hc->read_size, hc->read_size + CONFIG_THTTPD_REALLOCINCR);
    }

  /* Read some more bytes */

  sz = read(hc->conn_fd, &(hc->read_buf[hc->read_idx]), hc->read_size - hc->read_idx);
  if (sz == 0)
    {
      BADREQUEST("EOF");
      goto errout_with_400;
    }

  if (sz < 0)
    {
      /* Ignore EINTR and EAGAIN.  Also ignore EWOULDBLOCK.  At first glance
       * you would think that connections returned by fdwatch as readable
       * should never give an EWOULDBLOCK; however, this apparently can
       * happen if a packet gets garbled.
       */

      if (errno == EINTR || errno == EAGAIN || errno == EWOULDBLOCK)
        {
          return;
        }

      ndbg("read(fd=%d) failed: %d\n", hc->conn_fd, errno);
      BADREQUEST("read");
      goto errout_with_400;
    }

  hc->read_idx += sz;
  conn->active_at = tv->tv_sec;

  /* Do we have a complete request yet? */

  switch (httpd_got_request(hc))
    {
    case GR_NO_REQUEST:
      return;
    case GR_BAD_REQUEST:
     BADREQUEST("httpd_got_request");
     goto errout_with_400;
    }

  /* Yes.  Try parsing and resolving it */

  if (httpd_parse_request(hc) < 0)
    {
      goto errout_with_connection;
    }

  /* Start the connection going */

  if (httpd_start_request(hc, tv) < 0)
    {
      /* Something went wrong.  Close down the connection */

      goto errout_with_connection;
    }

  /* Set up the file offsets to read */

  conn->eof            = false;
  if (hc->got_range)
    {
      conn->offset     = hc->range_start;
      conn->end_offset = hc->range_end + 1;
    }
  else
    {
      conn->offset     = 0;
      if (hc->bytes_to_send < 0)
        {
          conn->end_offset = 0;
        }
      else
        {
          conn->end_offset = hc->bytes_to_send;
        }
    }

  /* Check if it's already handled */

  if (hc->file_fd < 0)
    {
      /* No file descriptor means someone else is handling it */

      conn->offset = hc->bytes_sent;
      goto errout_with_connection;
    }

  if (conn->offset >= conn->end_offset)
    {
      /* There's nothing to send */

      goto errout_with_connection;
    }

  /* Seek to the offset of the next byte to send */

  actual = lseek(hc->file_fd, conn->offset, SEEK_SET);
  if (actual != conn->offset)
    {
       ndbg("fseek to %d failed: offset=%d errno=%d\n", conn->offset, actual, errno);
       BADREQUEST("lseek");
       goto errout_with_400;
    }

  /* We have a valid connection and a file to send to it */

  conn->conn_state = CNST_SENDING;
  client_data.p    = conn;
  fdwatch_del_fd(fw, hc->conn_fd);
  return;

errout_with_400:
  BADREQUEST("errout");
  httpd_send_err(hc, 400, httpd_err400title, "", httpd_err400form, "");

errout_with_connection:
  finish_connection(conn, tv);
  return;
}
Пример #14
0
static void must_fail(grpc_exec_ctx *exec_ctx, void *arg, int success) {
  GPR_ASSERT(g_connecting == NULL);
  GPR_ASSERT(!success);
  finish_connection();
}
Пример #15
0
static void
handle_send( connecttab* c, struct timeval* tvP )
    {
    size_t max_bytes;
    int sz, coast;
    ClientData client_data;
    time_t elapsed;
    httpd_conn* hc = c->hc;
    int tind;

    max_bytes = 1000000000L;

    /* Do we need to write the headers first? */
    if ( hc->responselen == 0 )
	{
	/* No, just write the file. */
	sz = write(
	    hc->conn_fd, &(hc->body_data[c->next_byte_index]),
	    MIN( c->end_byte_index - c->next_byte_index, max_bytes ) );
	}
    else
	{
	/* Yes.  We'll combine headers and file into a single writev(),
	** hoping that this generates a single packet.
	*/
	struct iovec iv[2];

	iv[0].iov_base = hc->response;
	iv[0].iov_len = hc->responselen;
	iv[1].iov_base = &(hc->body_data[c->next_byte_index]);
	iv[1].iov_len = MIN( c->end_byte_index - c->next_byte_index, max_bytes );
	sz = writev( hc->conn_fd, iv, 2 );
	}

    if ( sz < 0 && errno == EINTR )
	return;

    if ( sz == 0 ||
	 ( sz < 0 && ( errno == EWOULDBLOCK || errno == EAGAIN ) ) )
	{
	/* This shouldn't happen, but some kernels, e.g.
	** SunOS 4.1.x, are broken and select() says that
	** O_NDELAY sockets are always writable even when
	** they're actually not.
	**
	** Current workaround is to block sending on this
	** socket for a brief adaptively-tuned period.
	** Fortunately we already have all the necessary
	** blocking code, for use with throttling.
	*/
	c->wouldblock_delay += MIN_WOULDBLOCK_DELAY;
	c->conn_state = CNST_PAUSING;
	fdwatch_del_fd( hc->conn_fd );
	client_data.p = c;
	c->wakeup_timer = tmr_create(
	    tvP, wakeup_connection, client_data, c->wouldblock_delay, 0 );
	if ( c->wakeup_timer == (Timer*) 0 )
	    {
	    return;
	    }
	return;
	}

    if ( sz < 0 )
	{
	/* Something went wrong, close this connection.
	*/
	clear_connection( c, tvP );
	return;
	}

    /* Ok, we wrote something. */
    c->active_at = tvP->tv_sec;
    /* Was this a headers + file writev()? */
    if ( hc->responselen > 0 )
	{
	/* Yes; did we write only part of the headers? */
	if ( sz < hc->responselen )
	    {
	    /* Yes; move the unwritten part to the front of the buffer. */
	    int newlen = hc->responselen - sz;
	    (void) memmove( hc->response, &(hc->response[sz]), newlen );
	    hc->responselen = newlen;
	    sz = 0;
	    }
	else
	    {
	    /* Nope, we wrote the full headers, so adjust accordingly. */
	    sz -= hc->responselen;
	    hc->responselen = 0;
	    }
	}
    /* And update how much of the file we wrote. */
    c->next_byte_index += sz;
    c->hc->bytes_sent += sz;

    /* Are we done? */
    if ( c->next_byte_index >= c->end_byte_index )
	{
	/* This connection is finished! */
	finish_connection( c, tvP );
	return;
	}

    /* Tune the (blockheaded) wouldblock delay. */
    if ( c->wouldblock_delay > MIN_WOULDBLOCK_DELAY )
	c->wouldblock_delay -= MIN_WOULDBLOCK_DELAY;

    /* (No check on min_limit here, that only controls connection startups.) */
    }
static void handle_send(struct connect_s *conn, struct timeval *tv)
{
  httpd_conn *hc = conn->hc;
  int nwritten;
  int nread;

  /* Read until the entire file is sent -- this could take awhile!! */

  while (conn->offset < conn->end_offset)
    {
      nvdbg("offset: %d end_offset: %d bytes_sent: %d\n",
            conn->offset, conn->end_offset, conn->hc->bytes_sent);

      /* Fill the rest of the response buffer with file data */

      nread = read_buffer(conn);
      if (nread < 0)
        {
          ndbg("File read error: %d\n", errno);
          goto errout_clear_connection;
        }
      nvdbg("Read %d bytes, buflen %d\n", nread, hc->buflen);

      /* Send the buffer */

      if (hc->buflen > 0)
        {
          /* httpd_write does not return until all bytes have been sent
           * (or an error occurs).
           */

          nwritten = httpd_write(hc->conn_fd, hc->buffer, hc->buflen);
          if (nwritten < 0)
            {
              ndbg("Error sending %s: %d\n", hc->encodedurl, errno);
              goto errout_clear_connection;
            }

          /* We wrote one full buffer of data (httpd_write does not
           * return until the full buffer is written (or an error occurs).
           */

          conn->active_at       = tv->tv_sec;
          hc->buflen            = 0;

          /* And update how much of the file we wrote */

          conn->offset         += nwritten;
          conn->hc->bytes_sent += nwritten;
          nvdbg("Wrote %d bytes\n", nwritten);
        }
    }

  /* The file transfer is complete -- finish the connection */

  nvdbg("Finish connection\n");
  finish_connection(conn, tv);
  return;

errout_clear_connection:
  ndbg("Clear connection\n");
  clear_connection(conn, tv);
  return;
}
Пример #17
0
static void must_fail(grpc_exec_ctx *exec_ctx, void *arg, grpc_error *error) {
  GPR_ASSERT(g_connecting == NULL);
  GPR_ASSERT(error != GRPC_ERROR_NONE);
  finish_connection(exec_ctx);
}
Пример #18
0
static void
handle_read( connecttab* c, struct timeval* tvP )
    {
    int sz;
    httpd_conn* hc = c->hc;

    /* Is there room in our buffer to read more bytes? */
    if ( hc->read_idx >= hc->read_size )
	{
	if ( hc->read_size > 5000 )
	    {
	    httpd_send_err( hc, 400, httpd_err400title, "", httpd_err400form, "" );
	    finish_connection( c, tvP );
	    return;
	    }
	httpd_realloc_str(
	    &hc->read_buf, &hc->read_size, hc->read_size + 1000 );
	}

    /* Read some more bytes. */
    sz = read(
	hc->conn_fd, &(hc->read_buf[hc->read_idx]),
	hc->read_size - hc->read_idx );
    if ( sz == 0 )
	{
	httpd_send_err( hc, 400, httpd_err400title, "", httpd_err400form, "" );
	finish_connection( c, tvP );
	return;
	}
    if ( sz < 0 )
	{
	/* Ignore EINTR and EAGAIN.  Also ignore EWOULDBLOCK.  At first glance
	** you would think that connections returned by fdwatch as readable
	** should never give an EWOULDBLOCK; however, this apparently can
	** happen if a packet gets garbled.
	*/
	if ( errno == EINTR || errno == EAGAIN || errno == EWOULDBLOCK )
	    return;
	httpd_send_err(
	    hc, 400, httpd_err400title, "", httpd_err400form, "" );
	finish_connection( c, tvP );
	return;
	}
    hc->read_idx += sz;
    c->active_at = tvP->tv_sec;

    /* Do we have a complete request yet? */
    switch ( httpd_got_request( hc ) )
	{
	case GR_NO_REQUEST:
	return;
	case GR_BAD_REQUEST:
	httpd_send_err( hc, 400, httpd_err400title, "", httpd_err400form, "" );
	finish_connection( c, tvP );
	return;
	}

    /* Yes.  Try parsing and resolving it. */
    if ( httpd_parse_request( hc ) < 0 )
	{
	finish_connection( c, tvP );
	return;
	}

    /* Start the connection going. */
    if ( httpd_start_request( hc, tvP ) < 0 )
	{
	/* Something went wrong.  Close down the connection. */
	finish_connection( c, tvP );
	return;
	}

    if ( c->conn_state == CNST_SLEEPING )
        {
        return;
        }
    handle_read_2( c, tvP );
    }