mirror of
https://github.com/tsl0922/ttyd.git
synced 2025-12-23 04:14:18 +01:00
all: remove pthread
This commit is contained in:
@@ -67,7 +67,7 @@ add_custom_command(OUTPUT html.h
|
|||||||
list(APPEND SOURCE_FILES html.h)
|
list(APPEND SOURCE_FILES html.h)
|
||||||
|
|
||||||
set(INCLUDE_DIRS ${OPENSSL_INCLUDE_DIR} ${LIBWEBSOCKETS_INCLUDE_DIR} ${JSON-C_INCLUDE_DIR})
|
set(INCLUDE_DIRS ${OPENSSL_INCLUDE_DIR} ${LIBWEBSOCKETS_INCLUDE_DIR} ${JSON-C_INCLUDE_DIR})
|
||||||
set(LINK_LIBS pthread ${OPENSSL_LIBRARIES} ${LIBWEBSOCKETS_LIBRARIES} ${JSON-C_LIBRARY})
|
set(LINK_LIBS ${OPENSSL_LIBRARIES} ${LIBWEBSOCKETS_LIBRARIES} ${JSON-C_LIBRARY})
|
||||||
|
|
||||||
if(APPLE)
|
if(APPLE)
|
||||||
# required for the new homebrew version of libwebsockets
|
# required for the new homebrew version of libwebsockets
|
||||||
|
|||||||
@@ -61,10 +61,11 @@ check_auth(struct lws *wsi, struct pss_http *pss) {
|
|||||||
return AUTH_FAIL;
|
return AUTH_FAIL;
|
||||||
}
|
}
|
||||||
|
|
||||||
void access_log(struct lws *wsi, const char *path) {
|
void
|
||||||
|
access_log(struct lws *wsi, const char *path) {
|
||||||
char rip[50];
|
char rip[50];
|
||||||
|
|
||||||
#if LWS_LIBRARY_VERSION_MAJOR > 2 || (LWS_LIBRARY_VERSION_MAJOR ==2 && LWS_LIBRARY_VERSION_MINOR >=4)
|
#if LWS_LIBRARY_VERSION_NUMBER >= 2004000
|
||||||
lws_get_peer_simple(lws_get_network_wsi(wsi), rip, sizeof(rip));
|
lws_get_peer_simple(lws_get_network_wsi(wsi), rip, sizeof(rip));
|
||||||
#else
|
#else
|
||||||
char name[100];
|
char name[100];
|
||||||
|
|||||||
@@ -7,9 +7,6 @@
|
|||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <sys/ioctl.h>
|
#include <sys/ioctl.h>
|
||||||
#include <sys/queue.h>
|
#include <sys/queue.h>
|
||||||
#include <sys/select.h>
|
|
||||||
#include <sys/types.h>
|
|
||||||
#include <pthread.h>
|
|
||||||
|
|
||||||
#if defined(__OpenBSD__) || defined(__APPLE__)
|
#if defined(__OpenBSD__) || defined(__APPLE__)
|
||||||
#include <util.h>
|
#include <util.h>
|
||||||
@@ -111,7 +108,6 @@ check_host_origin(struct lws *wsi) {
|
|||||||
|
|
||||||
void
|
void
|
||||||
tty_client_remove(struct tty_client *client) {
|
tty_client_remove(struct tty_client *client) {
|
||||||
pthread_mutex_lock(&server->mutex);
|
|
||||||
struct tty_client *iterator;
|
struct tty_client *iterator;
|
||||||
LIST_FOREACH(iterator, &server->clients, list) {
|
LIST_FOREACH(iterator, &server->clients, list) {
|
||||||
if (iterator == client) {
|
if (iterator == client) {
|
||||||
@@ -120,7 +116,6 @@ tty_client_remove(struct tty_client *client) {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
pthread_mutex_unlock(&server->mutex);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
@@ -130,12 +125,6 @@ tty_client_destroy(struct tty_client *client) {
|
|||||||
|
|
||||||
client->running = false;
|
client->running = false;
|
||||||
|
|
||||||
if (pthread_mutex_trylock(&client->mutex) == 0) {
|
|
||||||
client->state = STATE_DONE;
|
|
||||||
pthread_cond_signal(&client->cond);
|
|
||||||
pthread_mutex_unlock(&client->mutex);
|
|
||||||
}
|
|
||||||
|
|
||||||
// kill process (group) and free resource
|
// kill process (group) and free resource
|
||||||
int pgid = getpgid(client->pid);
|
int pgid = getpgid(client->pid);
|
||||||
int pid = pgid > 0 ? -pgid : client->pid;
|
int pid = pgid > 0 ? -pgid : client->pid;
|
||||||
@@ -159,8 +148,6 @@ cleanup:
|
|||||||
free(client->args[i]);
|
free(client->args[i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
pthread_mutex_destroy(&client->mutex);
|
|
||||||
|
|
||||||
#if LWS_LIBRARY_VERSION_NUMBER >= 3002000
|
#if LWS_LIBRARY_VERSION_NUMBER >= 3002000
|
||||||
lws_sul_schedule(context, 0, &client->sul_stagger, NULL, LWS_SET_TIMER_USEC_CANCEL);
|
lws_sul_schedule(context, 0, &client->sul_stagger, NULL, LWS_SET_TIMER_USEC_CANCEL);
|
||||||
#endif
|
#endif
|
||||||
@@ -169,20 +156,8 @@ cleanup:
|
|||||||
tty_client_remove(client);
|
tty_client_remove(client);
|
||||||
}
|
}
|
||||||
|
|
||||||
#if LWS_LIBRARY_VERSION_NUMBER >= 3002000
|
int
|
||||||
void
|
spawn_process(struct tty_client *client) {
|
||||||
stagger_callback(lws_sorted_usec_list_t *sul) {
|
|
||||||
struct tty_client *client = lws_container_of(sul, struct tty_client, sul_stagger);
|
|
||||||
|
|
||||||
lws_callback_on_writable(client->wsi);
|
|
||||||
lws_sul_schedule(context, 0, sul, stagger_callback, 10 * LWS_US_PER_MS);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
void *
|
|
||||||
thread_run_command(void *args) {
|
|
||||||
struct tty_client *client = (struct tty_client *) args;
|
|
||||||
|
|
||||||
// append url args to arguments
|
// append url args to arguments
|
||||||
char *argv[server->argc + client->argc + 1];
|
char *argv[server->argc + client->argc + 1];
|
||||||
int i, n = 0;
|
int i, n = 0;
|
||||||
@@ -195,11 +170,10 @@ thread_run_command(void *args) {
|
|||||||
argv[n] = NULL;
|
argv[n] = NULL;
|
||||||
|
|
||||||
int pty;
|
int pty;
|
||||||
fd_set des_set;
|
|
||||||
pid_t pid = forkpty(&pty, NULL, NULL, NULL);
|
pid_t pid = forkpty(&pty, NULL, NULL, NULL);
|
||||||
if (pid < 0) { /* error */
|
if (pid < 0) { /* error */
|
||||||
lwsl_err("forkpty failed: %d (%s)\n", errno, strerror(errno));
|
lwsl_err("forkpty failed: %d (%s)\n", errno, strerror(errno));
|
||||||
pthread_exit((void *) 1);
|
return 1;
|
||||||
} else if (pid == 0) { /* child */
|
} else if (pid == 0) { /* child */
|
||||||
setenv("TERM", server->terminal_type, true);
|
setenv("TERM", server->terminal_type, true);
|
||||||
// Don't pass the web socket onto child processes
|
// Don't pass the web socket onto child processes
|
||||||
@@ -217,32 +191,24 @@ thread_run_command(void *args) {
|
|||||||
if (client->size.ws_row > 0 && client->size.ws_col > 0)
|
if (client->size.ws_row > 0 && client->size.ws_col > 0)
|
||||||
ioctl(client->pty, TIOCSWINSZ, &client->size);
|
ioctl(client->pty, TIOCSWINSZ, &client->size);
|
||||||
|
|
||||||
while (client->running) {
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
tty_client_poll(struct tty_client *client) {
|
||||||
|
if (!client->running || client->state == STATE_READY) return;
|
||||||
|
|
||||||
|
fd_set des_set;
|
||||||
FD_ZERO (&des_set);
|
FD_ZERO (&des_set);
|
||||||
FD_SET (pty, &des_set);
|
FD_SET (client->pty, &des_set);
|
||||||
struct timeval tv = { 1, 0 };
|
struct timeval tv = { 0, 0 };
|
||||||
int ret = select(pty + 1, &des_set, NULL, NULL, &tv);
|
if (select(client->pty + 1, &des_set, NULL, NULL, &tv) <= 0) return;
|
||||||
if (ret == 0) continue;
|
|
||||||
if (ret < 0) break;
|
|
||||||
|
|
||||||
if (FD_ISSET (pty, &des_set)) {
|
if (FD_ISSET (client->pty, &des_set)) {
|
||||||
while (client->running) {
|
|
||||||
pthread_mutex_lock(&client->mutex);
|
|
||||||
while (client->state == STATE_READY) {
|
|
||||||
pthread_cond_wait(&client->cond, &client->mutex);
|
|
||||||
}
|
|
||||||
memset(client->pty_buffer, 0, sizeof(client->pty_buffer));
|
memset(client->pty_buffer, 0, sizeof(client->pty_buffer));
|
||||||
client->pty_len = read(pty, client->pty_buffer + LWS_PRE + 1, BUF_SIZE);
|
client->pty_len = read(client->pty, client->pty_buffer + LWS_PRE + 1, BUF_SIZE);
|
||||||
client->state = STATE_READY;
|
client->state = STATE_READY;
|
||||||
pthread_mutex_unlock(&client->mutex);
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
if (client->pty_len <= 0) break;
|
|
||||||
}
|
|
||||||
|
|
||||||
pthread_exit((void *) 0);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
@@ -294,17 +260,12 @@ callback_tty(struct lws *wsi, enum lws_callback_reasons reason,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pthread_mutex_init(&client->mutex, NULL);
|
|
||||||
pthread_cond_init(&client->cond, NULL);
|
|
||||||
|
|
||||||
pthread_mutex_lock(&server->mutex);
|
|
||||||
LIST_INSERT_HEAD(&server->clients, client, list);
|
LIST_INSERT_HEAD(&server->clients, client, list);
|
||||||
server->client_count++;
|
server->client_count++;
|
||||||
pthread_mutex_unlock(&server->mutex);
|
|
||||||
|
|
||||||
lws_hdr_copy(wsi, buf, sizeof(buf), WSI_TOKEN_GET_URI);
|
lws_hdr_copy(wsi, buf, sizeof(buf), WSI_TOKEN_GET_URI);
|
||||||
|
|
||||||
#if LWS_LIBRARY_VERSION_MAJOR > 2 || (LWS_LIBRARY_VERSION_MAJOR ==2 && LWS_LIBRARY_VERSION_MINOR >=4)
|
#if LWS_LIBRARY_VERSION_NUMBER >= 2004000
|
||||||
lws_get_peer_simple(lws_get_network_wsi(wsi), client->address, sizeof(client->address));
|
lws_get_peer_simple(lws_get_network_wsi(wsi), client->address, sizeof(client->address));
|
||||||
#else
|
#else
|
||||||
char name[100];
|
char name[100];
|
||||||
@@ -328,8 +289,9 @@ callback_tty(struct lws *wsi, enum lws_callback_reasons reason,
|
|||||||
lws_callback_on_writable(wsi);
|
lws_callback_on_writable(wsi);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (client->state != STATE_READY)
|
if (client->state != STATE_READY) {
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
// read error or client exited, close connection
|
// read error or client exited, close connection
|
||||||
if (client->pty_len == 0) {
|
if (client->pty_len == 0) {
|
||||||
@@ -371,10 +333,6 @@ callback_tty(struct lws *wsi, enum lws_callback_reasons reason,
|
|||||||
// check if there are more fragmented messages
|
// check if there are more fragmented messages
|
||||||
if (lws_remaining_packet_payload(wsi) > 0 || !lws_is_final_fragment(wsi)) {
|
if (lws_remaining_packet_payload(wsi) > 0 || !lws_is_final_fragment(wsi)) {
|
||||||
return 0;
|
return 0;
|
||||||
} else {
|
|
||||||
#if LWS_LIBRARY_VERSION_NUMBER >= 3002000
|
|
||||||
lws_sul_schedule(context, 0, &client->sul_stagger, stagger_callback, 10);
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (command) {
|
switch (command) {
|
||||||
@@ -414,9 +372,7 @@ callback_tty(struct lws *wsi, enum lws_callback_reasons reason,
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
int err = pthread_create(&client->thread, NULL, thread_run_command, client);
|
if (spawn_process(client) != 0) {
|
||||||
if (err != 0) {
|
|
||||||
lwsl_err("pthread_create return: %d\n", err);
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|||||||
34
src/server.c
34
src/server.c
@@ -4,7 +4,6 @@
|
|||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <getopt.h>
|
#include <getopt.h>
|
||||||
#include <pthread.h>
|
|
||||||
#include <signal.h>
|
#include <signal.h>
|
||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
|
|
||||||
@@ -165,7 +164,6 @@ tty_server_free(struct tty_server *ts) {
|
|||||||
unlink(ts->socket_path);
|
unlink(ts->socket_path);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
pthread_mutex_destroy(&ts->mutex);
|
|
||||||
free(ts);
|
free(ts);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -229,6 +227,15 @@ calc_command_start(int argc, char **argv) {
|
|||||||
return start;
|
return start;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if LWS_LIBRARY_VERSION_NUMBER >= 3002000
|
||||||
|
void
|
||||||
|
stagger_callback(lws_sorted_usec_list_t *sul) {
|
||||||
|
struct tty_client *client = lws_container_of(sul, struct tty_client, sul_stagger);
|
||||||
|
|
||||||
|
lws_callback_on_writable(client->wsi);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
int
|
int
|
||||||
main(int argc, char **argv) {
|
main(int argc, char **argv) {
|
||||||
if (argc == 1) {
|
if (argc == 1) {
|
||||||
@@ -238,7 +245,6 @@ main(int argc, char **argv) {
|
|||||||
|
|
||||||
int start = calc_command_start(argc, argv);
|
int start = calc_command_start(argc, argv);
|
||||||
server = tty_server_new(argc, argv, start);
|
server = tty_server_new(argc, argv, start);
|
||||||
pthread_mutex_init(&server->mutex, NULL);
|
|
||||||
|
|
||||||
struct lws_context_creation_info info;
|
struct lws_context_creation_info info;
|
||||||
memset(&info, 0, sizeof(info));
|
memset(&info, 0, sizeof(info));
|
||||||
@@ -476,27 +482,21 @@ main(int argc, char **argv) {
|
|||||||
open_uri(url);
|
open_uri(url);
|
||||||
}
|
}
|
||||||
|
|
||||||
// libwebsockets main loop
|
|
||||||
while (!force_exit) {
|
while (!force_exit) {
|
||||||
pthread_mutex_lock(&server->mutex);
|
|
||||||
if (!LIST_EMPTY(&server->clients)) {
|
if (!LIST_EMPTY(&server->clients)) {
|
||||||
struct tty_client *client;
|
struct tty_client *client;
|
||||||
LIST_FOREACH(client, &server->clients, list) {
|
LIST_FOREACH(client, &server->clients, list) {
|
||||||
if (client->running && pthread_mutex_trylock(&client->mutex) == 0) {
|
tty_client_poll(client);
|
||||||
if (client->state != STATE_DONE)
|
|
||||||
lws_callback_on_writable(client->wsi);
|
|
||||||
else
|
|
||||||
pthread_cond_signal(&client->cond);
|
|
||||||
pthread_mutex_unlock(&client->mutex);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
pthread_mutex_unlock(&server->mutex);
|
|
||||||
lws_service(context, 10);
|
|
||||||
#if LWS_LIBRARY_VERSION_NUMBER >= 3002000
|
#if LWS_LIBRARY_VERSION_NUMBER >= 3002000
|
||||||
usleep(10 * LWS_US_PER_MS);
|
lws_sul_schedule(context, 0, &client->sul_stagger, stagger_callback, 0);
|
||||||
|
#else
|
||||||
|
lws_callback_on_writable(client->wsi);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
lws_service(context, 0);
|
||||||
|
usleep(10 * 1000); // 10ms
|
||||||
|
}
|
||||||
|
|
||||||
lws_context_destroy(context);
|
lws_context_destroy(context);
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,3 @@
|
|||||||
#include <pthread.h>
|
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
#include <sys/ioctl.h>
|
#include <sys/ioctl.h>
|
||||||
#include <sys/queue.h>
|
#include <sys/queue.h>
|
||||||
@@ -48,9 +47,6 @@ struct tty_client {
|
|||||||
enum pty_state state;
|
enum pty_state state;
|
||||||
char pty_buffer[LWS_PRE + 1 + BUF_SIZE];
|
char pty_buffer[LWS_PRE + 1 + BUF_SIZE];
|
||||||
ssize_t pty_len;
|
ssize_t pty_len;
|
||||||
pthread_t thread;
|
|
||||||
pthread_mutex_t mutex;
|
|
||||||
pthread_cond_t cond;
|
|
||||||
|
|
||||||
LIST_ENTRY(tty_client) list;
|
LIST_ENTRY(tty_client) list;
|
||||||
};
|
};
|
||||||
@@ -80,7 +76,6 @@ struct tty_server {
|
|||||||
bool once; // whether accept only one client and exit on disconnection
|
bool once; // whether accept only one client and exit on disconnection
|
||||||
char socket_path[255]; // UNIX domain socket path
|
char socket_path[255]; // UNIX domain socket path
|
||||||
char terminal_type[30]; // terminal type to report
|
char terminal_type[30]; // terminal type to report
|
||||||
pthread_mutex_t mutex;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
extern int
|
extern int
|
||||||
@@ -89,3 +84,5 @@ callback_http(struct lws *wsi, enum lws_callback_reasons reason, void *user, voi
|
|||||||
extern int
|
extern int
|
||||||
callback_tty(struct lws *wsi, enum lws_callback_reasons reason, void *user, void *in, size_t len);
|
callback_tty(struct lws *wsi, enum lws_callback_reasons reason, void *user, void *in, size_t len);
|
||||||
|
|
||||||
|
extern void
|
||||||
|
tty_client_poll(struct tty_client *client);
|
||||||
|
|||||||
Reference in New Issue
Block a user