libwebsockets: hande fragmented messages, fixes #9

This commit is contained in:
Shuanglei Tao
2016-10-01 20:32:40 +08:00
parent 60baf391ca
commit c4d16c0283
3 changed files with 33 additions and 7 deletions

View File

@@ -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:

View File

@@ -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}
}; };

View File

@@ -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;