Exemple #1
0
static void _pkr_close(struct incoming_conn_state* ics,
                       int log_level,
                       const char* reason)
{
  char rbuf[128];
  char lbuf[128];

  /* FIXME: Log more useful things about the connection. */
  pk_log(PK_LOG_TUNNEL_CONNS | log_level,
        "%s; remote=%s; local=%s; hostname=%s; proto=%s; fd=%d",
        reason,
        in_addr_to_str((struct sockaddr*) &(ics->remote_addr), rbuf, 128),
        in_addr_to_str((struct sockaddr*) &(ics->local_addr), lbuf, 128),
        ics->hostname,
        known_protos[ics->parsed_as],
        ics->pkb->conn.sockfd);

  if (ics->pkb) {
    pkc_reset_conn(&(ics->pkb->conn), 0);
    pkm_free_be_conn(ics->pkb);
  }
  ics->parse_state = PARSE_FAILED; /* A horrible hack */

  if (ics->unparsed_data != NULL) free(ics->unparsed_data);
  free(ics);
}
Exemple #2
0
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;
}
Exemple #3
0
void pkb_log_fe_status(struct pk_manager* pkm)
{
  int j, ddnsup_ago;
  struct pk_tunnel* fe;
  char printip[128];
  char ddnsinfo[128];

  PK_TRACE_FUNCTION;

  for (j = 0, fe = pkm->tunnels; j < pkm->tunnel_max; j++, fe++) {
    if (fe->ai.ai_addr && fe->fe_hostname) {
      if (NULL != in_addr_to_str(fe->ai.ai_addr, printip, 128)) {
        ddnsinfo[0] = '\0';
        if (fe->last_ddnsup) {
          ddnsup_ago = time(0) - fe->last_ddnsup;
          sprintf(ddnsinfo, " (in DNS %us ago)", ddnsup_ago);
        }
        pk_log(PK_LOG_MANAGER_DEBUG,
               "Relay; status=0x%8.8x; errors=%d; info=%s%s%s%s%s%s%s%s",
               fe->conn.status,
               fe->error_count,
               printip,
               (fe->conn.status & FE_STATUS_REJECTED) ? " rejected": "",
               (fe->conn.status & FE_STATUS_WANTED) ? " wanted": "",
               (fe->conn.status & FE_STATUS_LAME) ? " lame": "",
               (fe->conn.status & FE_STATUS_IN_DNS) ? " in-DNS": "",
               (fe->conn.status & FE_STATUS_IS_FAST) ? " fast": "",
               (fe->conn.sockfd > 0) ? " live" : "",
               ddnsinfo);
      }
    }
  }
}
Exemple #4
0
void* pkb_tunnel_ping(void* void_fe) {
  struct pk_tunnel* fe = (struct pk_tunnel*) void_fe;
  struct timeval tv1, tv2, to;
  char buffer[1024], printip[1024];
  int sockfd, bytes, want;

  PK_TRACE_FUNCTION;

  fe->priority = 0;
  in_addr_to_str(fe->ai.ai_addr, printip, 1024);

  if (pk_state.fake_ping) {
    fe->priority = rand() % 500;
  }
  else {
    gettimeofday(&tv1, NULL);
    to.tv_sec = pk_state.socket_timeout_s;
    to.tv_usec = 0;
    if ((0 > (sockfd = PKS_socket(fe->ai.ai_family, fe->ai.ai_socktype,
                                  fe->ai.ai_protocol))) ||
        PKS_fail(PKS_setsockopt(sockfd, SOL_SOCKET, SO_RCVTIMEO, (char *) &to, sizeof(to))) ||
        PKS_fail(PKS_setsockopt(sockfd, SOL_SOCKET, SO_SNDTIMEO, (char *) &to, sizeof(to))) ||
        PKS_fail(PKS_connect(sockfd, fe->ai.ai_addr, fe->ai.ai_addrlen)) ||
        PKS_fail(PKS_write(sockfd, PK_FRONTEND_PING, strlen(PK_FRONTEND_PING))))
    {
      if (sockfd >= 0){
        PKS_close(sockfd);
      }
      if (fe->error_count < 999)
        fe->error_count += 1;
      pk_log(PK_LOG_MANAGER_DEBUG, "Ping %s failed! (connect)", printip);
      sleep(2); /* We don't want to return first! */
      return NULL;
    }

    /* Magic number: 116 bytes is the shortest response we expect. It is
     * still long enough to contain the X-PageKite-Overloaded marker, if
     * present at all. */
    bytes = timed_read(sockfd, buffer, 116, 1000);
    buffer[116] = '\0';

    want = strlen(PK_FRONTEND_PONG);
    if ((bytes < want) ||
        (0 != strncmp(buffer, PK_FRONTEND_PONG, want))) {
      if (fe->error_count < 999)
        fe->error_count += 1;
      pk_log(PK_LOG_MANAGER_DEBUG, "Ping %s failed! (read=%d)", printip, bytes);
      sleep(2); /* We don't want to return first! */
      return NULL;
    }
    PKS_close(sockfd);
    gettimeofday(&tv2, NULL);

    fe->priority = (tv2.tv_sec - tv1.tv_sec) * 1000
                 + (tv2.tv_usec - tv1.tv_usec) / 1000;

    if (strcasestr(buffer, PK_FRONTEND_OVERLOADED) != NULL) {
      fe->priority += 1;
      sleep(2); /* We don't want to return first! */
    }
  }

  if (fe->conn.status & (FE_STATUS_WANTED|FE_STATUS_IS_FAST))
  {
    /* Bias ping time to make old decisions a bit more sticky. We ignore
     * DNS though, to allow a bit of churn to spread the load around and
     * make sure new tunnels don't stay ignored forever. */
    fe->priority /= 10;
    fe->priority *= 9;
    pk_log(PK_LOG_MANAGER_DEBUG,
           "Ping %s: %dms (biased)", printip, fe->priority);
  }
  else {
    /* Add artificial +/-5% jitter to ping results */
    fe->priority *= ((rand() % 11) + 95);
    fe->priority /= 100;
    pk_log(PK_LOG_MANAGER_DEBUG, "Ping %s: %dms", printip, fe->priority);
  }

  PK_CHECK_MEMORY_CANARIES;
  return NULL;
}