コード例 #1
0
void pkr_relay_incoming(pk_lua_t* LUA, int result, void* void_data) {
  struct incoming_conn_state* ics = (struct incoming_conn_state*) void_data;

  PK_TRACE_FUNCTION;

  if (ics->parse_state == PARSE_FAILED) {
    pk_log(PK_LOG_TUNNEL_DATA|PK_LOG_ERROR,
           "pkr_relay_incoming() invoked for dead ics");
    return; /* Should never happen */
  }

  if (result == PARSE_WANT_MORE_DATA) {
    if (time(NULL) - ics->created > 5) {
      /* We don't wait forever for more data; that would make resource
       * exhaustion DOS attacks against the server trivially easy. */
      _pkr_close(ics, 0, "Timed out");
    }
    else {
      /* Slow down a tiny bit, unless there are jobs in the queue waiting
       * for us to finish. */
      if (ics->pkm->blocking_jobs.count < 1) sleep_ms(100);
      _pkr_process_readable(ics);
    }
  }
  else {
    /* If we get this far, then the request has been parsed and we have
     * in ics details about what needs to be done. So we do it! :)
     */
    _pkr_close(ics, 0, "FIXME");
  }
}
コード例 #2
0
ファイル: pkrelay.c プロジェクト: pagekite/libpagekite
int pkr_conn_accepted_cb(int sockfd, void* void_pkm)
{
  struct incoming_conn_state* ics;
  struct pk_manager* pkm = (struct pk_manager*) void_pkm;
  struct pk_backend_conn* pkb;
  socklen_t slen;
  char rbuf[128];
  char lbuf[128];

  PK_TRACE_FUNCTION;

  ics = malloc(sizeof(struct incoming_conn_state));
  ics->pkm = pkm;
  ics->pkb = NULL;
  ics->tunnel = NULL;
  ics->hostname = NULL;
  ics->parsed_as = PROTO_UNKNOWN;
  ics->parse_state = PARSE_UNDECIDED;
  ics->created = pk_time();
  ics->unparsed_data = NULL;

  slen = sizeof(ics->local_addr);
  getsockname(sockfd, (struct sockaddr*) &(ics->local_addr), &slen);

  slen = sizeof(ics->remote_addr);
  getpeername(sockfd, (struct sockaddr*) &(ics->remote_addr), &slen);

  pk_log(PK_LOG_TUNNEL_DATA,
         "Accepted; remote=%s; local=%s; fd=%d",
         in_addr_to_str((struct sockaddr*) &(ics->remote_addr), rbuf, 128),
         in_addr_to_str((struct sockaddr*) &(ics->local_addr), lbuf, 128),
         sockfd);

  /* Allocate a connection for this request or die... */
  sprintf(lbuf, "!NEW:%d", ics->remote_addr.sin_port);
  if (NULL == (pkb = pkm_alloc_be_conn(pkm, NULL, lbuf))) {
    _pkr_close(ics, PK_LOG_ERROR, "BE alloc failed");
    PKS_close(sockfd);
    return -1;
  }

  pkb->kite = NULL;
  pkb->conn.sockfd = sockfd;
  ics->pkb = pkb;

  set_non_blocking(sockfd);

  ev_io_init(&(pkb->conn.watch_r),
             pkr_new_conn_readable_cb,
             PKS_EV_FD(sockfd),
             EV_READ);
  pkb->conn.watch_r.data = (void *) ics;
  ev_io_start(pkm->loop, &(pkb->conn.watch_r));
  return 0;
}
コード例 #3
0
ファイル: pkrelay.c プロジェクト: pagekite/libpagekite
void pkr_relay_incoming(int result, void* void_data) {
  struct incoming_conn_state* ics = (struct incoming_conn_state*) void_data;

  PK_TRACE_FUNCTION;

  if (ics->parse_state == PARSE_FAILED) {
    pk_log(PK_LOG_TUNNEL_DATA|PK_LOG_ERROR,
           "pkr_relay_incoming() invoked for dead ics");
    return; /* Should never happen */
  }

  if (result == PARSE_WANT_MORE_DATA) {
    if (pk_time() - ics->created > 5) {
      /* We don't wait forever for more data; that would make resource
       * exhaustion DOS attacks against the server trivially easy. */
      _pkr_close(ics, 0, "Timed out");
    }
    else {
      /* Slow down a tiny bit, unless there are jobs in the queue waiting
       * for us to finish. */
      if (ics->pkm->blocking_jobs.count < 1) sleep_ms(100);
      _pkr_process_readable(ics);
    }
  }
  else {
    /* If we get this far, then the request has been parsed and we have
     * in ics details about what needs to be done. So we do it! :)
     */

    if (ics->parsed_as == PROTO_PAGEKITE) {
      char* response = NULL;
      struct pke_event* ev = pke_post_blocking_event(NULL,
        PK_EV_TUNNEL_REQUEST, 0, ics->unparsed_data, NULL, &response);

      int rlen = 0;
      if (response && *response) {
        rlen = strlen(response);
        pkc_write(&(ics->pkb->conn), response, rlen);
      }

      int result_ok = rlen && ev && (ev->response_code & PK_EV_RESPOND_TRUE);
      if (result_ok) {
        /* FIXME: Upgrade this connection to a tunnel */

        int flying = 0;
        struct pk_kite_request* pkr = pk_parse_pagekite_response(
          response, rlen + 1, NULL, NULL);
        if (pkr != NULL) {
          struct pk_kite_request* p;
          for (p = pkr; p->status != PK_KITE_UNKNOWN; p++) {
            if (p->status == PK_KITE_FLYING) {
              /* FIXME: Record kite->tunnel mapping */
              pk_log(PK_LOG_MANAGER_DEBUG, "Accepted kite: %s://%s:%d",
                                           p->kite->protocol,
                                           p->kite->public_domain,
                                           p->kite->public_port);
              flying++;
            }
            else {
              pk_log(PK_LOG_MANAGER_DEBUG, "Rejected kite: %s://%s:%d (%d)",
                                           p->kite->protocol,
                                           p->kite->public_domain,
                                           p->kite->public_port,
                                           p->status);
            }
          }
          free(pkr);

          /* FIXME: Add to event loop */
        }

        if (!flying) result_ok = 0;
      }

      if (ev) pke_free_event(NULL, ev->event_code);
      if (response) free(response);
      if (!result_ok) _pkr_close(ics, 0, "Rejected");
    }
    else {
      _pkr_close(ics, 0, "FIXME");
    }
  }
}
コード例 #4
0
ファイル: pkrelay.c プロジェクト: pagekite/libpagekite
static int _pkr_process_readable(struct incoming_conn_state* ics)
{
  char peeked[PEEK_BYTES+1];
  int bytes;
  int result = PARSE_UNDECIDED;

  PK_TRACE_FUNCTION;

  /* We have data! Peek at it to find out what it is... */
  bytes = PKS_peek(ics->pkb->conn.sockfd, peeked, PEEK_BYTES);
  if (bytes == 0) {
    /* Connection closed already */
    result = PARSE_FAILED;
  }
  else if (bytes < 0) {
    pk_log(PK_LOG_MANAGER_DEBUG,
           "_pkr_process_readable(%d): peek failed %d=%s!",
           ics->pkb->conn.sockfd, errno, strerror(errno));
    if (errno == EAGAIN || errno == EINTR || errno == EWOULDBLOCK) {
      result = PARSE_WANT_MORE_DATA;
    }
    else {
      result = PARSE_FAILED;
    }
  }
  else {
    peeked[bytes] = '\0';
  }

  if (!result) result = _pkr_parse_ssltls(peeked, bytes, ics);
  if (!result) result = _pkr_parse_http(peeked, bytes, ics);

  /* No result yet? Do we have enough data? */
  if (!result) {
    if (bytes > 4) {
      result = PARSE_FAILED;
    }
    else {
      result = PARSE_WANT_MORE_DATA;
    }
  }

  ics->parse_state = result;
  pk_log(PK_LOG_MANAGER_DEBUG,
         "_pkr_process_readable(%d): result=%d, bytes=%d",
         ics->pkb->conn.sockfd, result, bytes);

  if ((result == PARSE_WANT_MORE_DATA) || (result == PARSE_MATCH_SLOW)) {
    /* Parsers found something or we still need more data.
     * Punt to another thread for further processing. */
    pkb_add_job(&(ics->pkm->blocking_jobs), PK_RELAY_INCOMING, result, ics);
  }
  else if (result == PARSE_MATCH_FAST) {
    /* Parsers found something. Process now. */
    pkr_relay_incoming(result, ics);
  }
  else {
    /* result == PARSE_FAILED */
    _pkr_close(ics, 0, "No tunnel found");
  }

  PK_CHECK_MEMORY_CANARIES;

  return result;
}