static int pklua_socket_server_accepted_cb(int sockfd, void* void_data) { pk_log(PK_LOG_LUA_DEBUG, "pklua_socket_server_accepted_cb(%d, %p)", sockfd, void_data); pklua_socket_server_cb_data* data = (pklua_socket_server_cb_data*) void_data; pkb_add_job(&(data->pkm->blocking_jobs), PK_ACCEPT_LUA, sockfd, void_data); return 0; }
void pkb_stop_blockers(struct pk_manager *pkm) { int i; pkb_add_job(&(pkm->blocking_jobs), PK_QUIT, 0, NULL); for (i = 0; i < MAX_BLOCKING_THREADS; i++) { if (pkm->blocking_threads[i] != NULL) { pthread_join(pkm->blocking_threads[i]->thread, NULL); #if HAVE_LUA pklua_close_lua(pkm->blocking_threads[i]->lua); #endif free(pkm->blocking_threads[i]); pkm->blocking_threads[i] = NULL; } } }
void* pkb_run_blocker(void *void_pkblocker) { time_t last_check_world = 0; time_t last_check_tunnels = 0; struct pk_job job; struct pk_blocker* this = (struct pk_blocker*) void_pkblocker; struct pk_manager* pkm = this->manager; #if HAVE_LUA /* Initialize Lua state for this thread/blocker. */ if (pkm->lua != NULL) { this->lua = pklua_unlock_lua(pklua_get_locked_lua(pkm)); } #endif pk_log(PK_LOG_MANAGER_DEBUG, "Started blocking thread."); PK_HOOK(PK_HOOK_START_BLOCKER, 0, this, pkm); while (1) { pkb_get_job(&(pkm->blocking_jobs), &job); switch (job.job) { case PK_NO_JOB: break; case PK_CHECK_WORLD: if (time(0) >= last_check_world + pkm->housekeeping_interval_min) { pkm_reconfig_start((struct pk_manager*) job.ptr_data); if (PK_HOOK(PK_HOOK_CHECK_WORLD, 0, this, pkm)) { pkb_check_world((struct pk_manager*) job.ptr_data); pkb_check_tunnels((struct pk_manager*) job.ptr_data); last_check_world = last_check_tunnels = time(0); PK_HOOK(PK_HOOK_CHECK_WORLD, 1, this, pkm); } pkm_reconfig_stop((struct pk_manager*) job.ptr_data); } break; case PK_CHECK_FRONTENDS: if (time(0) >= last_check_tunnels + pkm->housekeeping_interval_min) { pkm_reconfig_start((struct pk_manager*) job.ptr_data); if (PK_HOOK(PK_HOOK_CHECK_TUNNELS, 0, this, pkm)) { pkb_check_tunnels((struct pk_manager*) job.ptr_data); last_check_tunnels = time(0); PK_HOOK(PK_HOOK_CHECK_TUNNELS, 1, this, pkm); } pkm_reconfig_stop((struct pk_manager*) job.ptr_data); } break; case PK_ACCEPT_LUA: #if HAVE_LUA pklua_socket_server_accepted(this->lua, job.int_data, job.ptr_data); #endif break; case PK_ACCEPT_FE: /* FIXME: Do something more useful here */ if (PKS_fail(PKS_close(job.int_data))) { }; break; case PK_QUIT: /* Put the job back in the queue, in case there are many workers */ pkb_add_job(&(pkm->blocking_jobs), PK_QUIT, 0, NULL); pk_log(PK_LOG_MANAGER_DEBUG, "Exiting blocking thread."); return NULL; } } }
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; }