mirror of
https://github.com/tsl0922/ttyd.git
synced 2025-12-23 04:14:18 +01:00
libwebsockets: hande fragmented messages, fixes #9
This commit is contained in:
@@ -82,6 +82,10 @@ tty_client_destroy(struct tty_client *client) {
|
|||||||
lwsl_notice("process exited with code %d, pid: %d\n", status, client->pid);
|
lwsl_notice("process exited with code %d, pid: %d\n", status, client->pid);
|
||||||
close(client->pty);
|
close(client->pty);
|
||||||
|
|
||||||
|
// free the buffer
|
||||||
|
if (client->buffer != NULL)
|
||||||
|
t_free(client->buffer);
|
||||||
|
|
||||||
// remove from clients list
|
// remove from clients list
|
||||||
pthread_mutex_lock(&server->lock);
|
pthread_mutex_lock(&server->lock);
|
||||||
LIST_REMOVE(client, list);
|
LIST_REMOVE(client, list);
|
||||||
@@ -152,7 +156,6 @@ int
|
|||||||
callback_tty(struct lws *wsi, enum lws_callback_reasons reason,
|
callback_tty(struct lws *wsi, enum lws_callback_reasons reason,
|
||||||
void *user, void *in, size_t len) {
|
void *user, void *in, size_t len) {
|
||||||
struct tty_client *client = (struct tty_client *) user;
|
struct tty_client *client = (struct tty_client *) user;
|
||||||
char *data;
|
|
||||||
struct winsize *size;
|
struct winsize *size;
|
||||||
|
|
||||||
switch (reason) {
|
switch (reason) {
|
||||||
@@ -161,6 +164,7 @@ callback_tty(struct lws *wsi, enum lws_callback_reasons reason,
|
|||||||
client->initialized = false;
|
client->initialized = false;
|
||||||
client->authenticated = false;
|
client->authenticated = false;
|
||||||
client->wsi = wsi;
|
client->wsi = wsi;
|
||||||
|
client->buffer = NULL;
|
||||||
lws_get_peer_addresses(wsi, lws_get_socket_fd(wsi),
|
lws_get_peer_addresses(wsi, lws_get_socket_fd(wsi),
|
||||||
client->hostname, sizeof(client->hostname),
|
client->hostname, sizeof(client->hostname),
|
||||||
client->address, sizeof(client->address));
|
client->address, sizeof(client->address));
|
||||||
@@ -222,8 +226,18 @@ callback_tty(struct lws *wsi, enum lws_callback_reasons reason,
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case LWS_CALLBACK_RECEIVE:
|
case LWS_CALLBACK_RECEIVE:
|
||||||
data = (char *) in;
|
if (client->buffer == NULL) {
|
||||||
char command = data[0];
|
client->buffer = t_malloc(len + 1);
|
||||||
|
client->len = len;
|
||||||
|
memcpy(client->buffer, in, len);
|
||||||
|
} else {
|
||||||
|
client->buffer = t_realloc(client->buffer, client->len + len + 1);
|
||||||
|
memcpy(client->buffer + client->len, in, len);
|
||||||
|
client->len += len;
|
||||||
|
}
|
||||||
|
client->buffer[client->len] = '\0';
|
||||||
|
|
||||||
|
const char command = client->buffer[0];
|
||||||
|
|
||||||
// check auth
|
// check auth
|
||||||
if (server->credential != NULL && !client->authenticated && command != JSON_DATA) {
|
if (server->credential != NULL && !client->authenticated && command != JSON_DATA) {
|
||||||
@@ -231,9 +245,14 @@ callback_tty(struct lws *wsi, enum lws_callback_reasons reason,
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// check if there are more fragmented messages
|
||||||
|
if (lws_remaining_packet_payload(wsi) > 0 || !lws_is_final_fragment(wsi)) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
switch (command) {
|
switch (command) {
|
||||||
case INPUT:
|
case INPUT:
|
||||||
if (write(client->pty, data + 1, len - 1) < len - 1) {
|
if (write(client->pty, client->buffer + 1, client->len - 1) < client->len - 1) {
|
||||||
lwsl_err("write INPUT to pty\n");
|
lwsl_err("write INPUT to pty\n");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
@@ -248,7 +267,7 @@ callback_tty(struct lws *wsi, enum lws_callback_reasons reason,
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case RESIZE_TERMINAL:
|
case RESIZE_TERMINAL:
|
||||||
size = parse_window_size(data + 1);
|
size = parse_window_size(client->buffer + 1);
|
||||||
if (size != NULL) {
|
if (size != NULL) {
|
||||||
if (ioctl(client->pty, TIOCSWINSZ, size) == -1) {
|
if (ioctl(client->pty, TIOCSWINSZ, size) == -1) {
|
||||||
lwsl_err("ioctl TIOCSWINSZ: %d (%s)\n", errno, strerror(errno));
|
lwsl_err("ioctl TIOCSWINSZ: %d (%s)\n", errno, strerror(errno));
|
||||||
@@ -260,7 +279,7 @@ callback_tty(struct lws *wsi, enum lws_callback_reasons reason,
|
|||||||
if (server->credential == NULL)
|
if (server->credential == NULL)
|
||||||
break;
|
break;
|
||||||
{
|
{
|
||||||
json_object *obj = json_tokener_parse(data);
|
json_object *obj = json_tokener_parse(client->buffer);
|
||||||
struct json_object *o = NULL;
|
struct json_object *o = NULL;
|
||||||
if (json_object_object_get_ex(obj, "AuthToken", &o)) {
|
if (json_object_object_get_ex(obj, "AuthToken", &o)) {
|
||||||
const char *token = json_object_get_string(o);
|
const char *token = json_object_get_string(o);
|
||||||
@@ -276,6 +295,11 @@ callback_tty(struct lws *wsi, enum lws_callback_reasons reason,
|
|||||||
lwsl_notice("unknown message type: %c\n", command);
|
lwsl_notice("unknown message type: %c\n", command);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (client->buffer != NULL) {
|
||||||
|
t_free(client->buffer);
|
||||||
|
client->buffer = NULL;
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case LWS_CALLBACK_CLOSED:
|
case LWS_CALLBACK_CLOSED:
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ struct tty_server *server;
|
|||||||
// websocket protocols
|
// websocket protocols
|
||||||
static const struct lws_protocols protocols[] = {
|
static const struct lws_protocols protocols[] = {
|
||||||
{"http-only", callback_http, 0, 0},
|
{"http-only", callback_http, 0, 0},
|
||||||
{"tty", callback_tty, sizeof(struct tty_client), 128},
|
{"tty", callback_tty, sizeof(struct tty_client), 0},
|
||||||
{NULL, NULL, 0, 0}
|
{NULL, NULL, 0, 0}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -50,6 +50,8 @@ struct tty_client {
|
|||||||
char address[50];
|
char address[50];
|
||||||
|
|
||||||
struct lws *wsi;
|
struct lws *wsi;
|
||||||
|
char *buffer;
|
||||||
|
size_t len;
|
||||||
int pid;
|
int pid;
|
||||||
int pty;
|
int pty;
|
||||||
pthread_t thread;
|
pthread_t thread;
|
||||||
|
|||||||
Reference in New Issue
Block a user