Exemple #1
0
int pklua_lua_socket_send(lua_State* L)
{
  pk_log(PK_LOG_LUA_DEBUG, "pklua_lua_socket_send(%p)", L);
  int sockfd = _pklua_lua_socket_get_sockfd(L);
  if (lua_gettop(L) > 1 && lua_isstring(L, 2)) {
    ssize_t dl;
    size_t data_len;
    const char *data = lua_tolstring(L, 2, &data_len);
    if ((dl = data_len) != PKS_write(sockfd, data, data_len)) {
      pk_log(PK_LOG_LUA_DEBUG, "write failed to %d", sockfd);
      return 0;
    }
    lua_pushinteger(L, data_len);
    return 1;
  }
  lua_pushstring(L, "Incorrect arguments");
  lua_error(L);
  return -1;
}
Exemple #2
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;
}
Exemple #3
0
int dbg_write(int sockfd, char *buffer, int bytes)
{
  printf(">> %s", buffer);
  return PKS_write(sockfd, buffer, bytes);
}
Exemple #4
0
int http_get(const char* url, char* result_buffer, size_t maxlen)
{
  char *urlparse, *hostname, *port, *path;
  struct addrinfo hints, *result, *rp;
  char request[10240], *bp;
  int sockfd, rlen, bytes, total_bytes;

  /* http://hostname:port/foo */
  urlparse = strdup(url);
  hostname = urlparse+7;
  while (*hostname && *hostname == '/') hostname++;
  port = hostname;
  while (*port && *port != '/' && *port != ':') port++;
  if (*port == '/') {
    path = port;
    *path++ = '\0';
    port = (url[5] == 's') ? "443" : "80";
  }
  else {
    *port++ = '\0';
    path = port;
    while (*path && *path != '/') path++;
    *path++ = '\0';
  }

  rlen = snprintf(request, 10240,
                  "GET /%s HTTP/1.1\r\nHost: %s\r\n\r\n", path, hostname);
  if (10240 == rlen)
  {
    free(urlparse);
    return -1;
  }

  total_bytes = 0;
  memset(&hints, 0, sizeof(struct addrinfo));
  hints.ai_family = AF_UNSPEC;
  hints.ai_socktype = SOCK_STREAM;
  if (0 == getaddrinfo(hostname, port, &hints, &result)) {
    for (rp = result; rp != NULL; rp = rp->ai_next) {
      if ((0 > (sockfd = PKS_socket(rp->ai_family, rp->ai_socktype,
                                    rp->ai_protocol))) ||
          PKS_fail(PKS_connect(sockfd, rp->ai_addr, rp->ai_addrlen)) ||
          PKS_fail(PKS_write(sockfd, request, rlen))) {
        if (sockfd >= 0) PKS_close(sockfd);
      }
      else {
        total_bytes = 0;
        bp = result_buffer;
        do {
          bytes = timed_read(sockfd, bp, maxlen-(1+total_bytes), 1000);
          if (bytes > 0) {
            bp += bytes;
            total_bytes += bytes;
          }
        } while (bytes > 0);
        *bp = '\0';
        PKS_close(sockfd);
        break;
      }
    }
    freeaddrinfo(result);
  }
  free(urlparse);
  return total_bytes;
}