int
callback_http(struct lws *wsi, enum lws_callback_reasons reason, void *user, void *in, size_t len) {
+ struct pss_http *pss = (struct pss_http *) user;
unsigned char buffer[4096 + LWS_PRE], *p, *end;
char buf[256], name[100], rip[50];
// only GET method is allowed
if (!lws_hdr_total_length(wsi, WSI_TOKEN_GET_URI) || len < 1) {
lws_return_http_status(wsi, HTTP_STATUS_BAD_REQUEST, NULL);
- goto try_to_reuse;
+ return 0;
}
+ lws_snprintf(pss->path, sizeof(pss->path), "%s", (const char *)in);
lws_get_peer_addresses(wsi, lws_get_socket_fd(wsi), name, sizeof(name), rip, sizeof(rip));
lwsl_notice("HTTP %s - %s (%s)\n", (char *) in, rip, name);
case 0:
break;
case -1:
- goto try_to_reuse;
+ return 0;
case 1:
default:
return 1;
p = buffer + LWS_PRE;
end = p + sizeof(buffer) - LWS_PRE;
- if (!strncmp((const char *) in, "/auth_token.js", 14)) {
+ if (strncmp(pss->path, "/auth_token.js", 14) == 0) {
size_t n = server->credential != NULL ? sprintf(buf, "var tty_auth_token = '%s';", server->credential) : 0;
if (lws_add_http_header_status(wsi, HTTP_STATUS_OK, &p, end))
return 1;
if (lws_write(wsi, buffer + LWS_PRE, p - (buffer + LWS_PRE), LWS_WRITE_HTTP_HEADERS) < 0)
return 1;
- if (n > 0 && lws_write_http(wsi, buf, n) < 0) {
- return 1;
+ if (n > 0) {
+ pss->buffer = strdup(buf);
+ pss->len = n;
+ lws_callback_on_writable(wsi);
}
- goto try_to_reuse;
+ return 0;
}
- if (strncmp((const char *) in, "/", 1) != 0) {
+ if (strcmp(pss->path, "/") != 0) {
lws_return_http_status(wsi, HTTP_STATUS_NOT_FOUND, NULL);
- goto try_to_reuse;
+ return 0;
}
const char* content_type = "text/html";
if (lws_write(wsi, buffer + LWS_PRE, p - (buffer + LWS_PRE), LWS_WRITE_HTTP_HEADERS) < 0)
return 1;
- if (lws_write_http(wsi, index_html, index_html_len) < 0)
+ pss->buffer = (char *) index_html;
+ pss->len = index_html_len;
+ lws_callback_on_writable(wsi);
+ return 0;
+ }
+ break;
+ case LWS_CALLBACK_HTTP_WRITEABLE:
+ if (pss->len > 0) {
+ int n = lws_write_http(wsi, pss->buffer, pss->len);
+ if (strncmp(pss->path, "/", 1) != 0)
+ free(pss->buffer);
+ if (n < pss->len)
return 1;
- goto try_to_reuse;
}
+ if (lws_http_transaction_completed(wsi))
+ return -1;
break;
case LWS_CALLBACK_OPENSSL_PERFORM_CLIENT_CERT_VERIFICATION:
if (!len || (SSL_get_verify_result((SSL *) in) != X509_V_OK)) {
}
return 0;
-
- /* if we're on HTTP1.1 or 2.0, will keep the idle connection alive */
- try_to_reuse:
- if (lws_http_transaction_completed(wsi))
- return -1;
-
- return 0;
}
#include "server.h"
#include "utils.h"
+// initial message list
+char initial_cmds[] = {
+ SET_WINDOW_TITLE,
+ SET_RECONNECT,
+ SET_PREFERENCES
+};
+
int
-send_initial_message(struct lws *wsi) {
- unsigned char message[LWS_PRE + 256];
+send_initial_message(struct lws *wsi, int index) {
+ unsigned char message[LWS_PRE + 1 + 4096];
unsigned char *p = &message[LWS_PRE];
- int n;
-
- char hostname[128];
- gethostname(hostname, sizeof(hostname) - 1);
-
- // window title
- n = sprintf((char *) p, "%c%s (%s)", SET_WINDOW_TITLE, server->command, hostname);
- if (lws_write(wsi, p, (size_t) n, LWS_WRITE_BINARY) < n) {
- return -1;
- }
- // reconnect time
- n = sprintf((char *) p, "%c%d", SET_RECONNECT, server->reconnect);
- if (lws_write(wsi, p, (size_t) n, LWS_WRITE_BINARY) < n) {
- return -1;
- }
- // client preferences
- n = sprintf((char *) p, "%c%s", SET_PREFERENCES, server->prefs_json);
- if (lws_write(wsi, p, (size_t) n, LWS_WRITE_BINARY) < n) {
- return -1;
+ char buffer[128];
+ int n = 0;
+
+ char cmd = initial_cmds[index];
+ switch(cmd) {
+ case SET_WINDOW_TITLE:
+ gethostname(buffer, sizeof(buffer) - 1);
+ n = sprintf((char *) p, "%c%s (%s)", cmd, server->command, buffer);
+ break;
+ case SET_RECONNECT:
+ n = sprintf((char *) p, "%c%d", cmd, server->reconnect);
+ break;
+ case SET_PREFERENCES:
+ n = sprintf((char *) p, "%c%s", cmd, server->prefs_json);
+ break;
+ default:
+ break;
}
- return 0;
+
+ return lws_write(wsi, p, (size_t) n, LWS_WRITE_BINARY);
}
bool
lwsl_warn("refuse to serve WS client due to the --max-clients option.\n");
return 1;
}
- if (lws_hdr_copy(wsi, buf, sizeof(buf), WSI_TOKEN_GET_URI) <= 0 || strcmp(buf, WS_PATH)) {
+ if (lws_hdr_copy(wsi, buf, sizeof(buf), WSI_TOKEN_GET_URI) <= 0 || strcmp(buf, WS_PATH) != 0) {
lwsl_warn("refuse to serve WS client for illegal ws path: %s\n", buf);
return 1;
}
case LWS_CALLBACK_ESTABLISHED:
client->running = false;
client->initialized = false;
+ client->initial_cmd_index = 0;
client->authenticated = false;
client->wsi = wsi;
client->buffer = NULL;
case LWS_CALLBACK_SERVER_WRITEABLE:
if (!client->initialized) {
- if (send_initial_message(wsi) < 0) {
+ if (client->initial_cmd_index == sizeof(initial_cmds)) {
+ client->initialized = true;
+ break;
+ }
+ if (send_initial_message(wsi, client->initial_cmd_index) < 0) {
tty_client_remove(client);
lws_close_reason(wsi, LWS_CLOSE_STATUS_UNEXPECTED_CONDITION, NULL, 0);
return -1;
}
- client->initialized = true;
- break;
+ client->initial_cmd_index++;
+ lws_callback_on_writable(wsi);
+ return 0;
}
if (client->state != STATE_READY)
break;
// websocket protocols
static const struct lws_protocols protocols[] = {
- {"http-only", callback_http, 0, 0},
+ {"http-only", callback_http, sizeof(struct pss_http), 0},
{"tty", callback_tty, sizeof(struct tty_client), 0},
{NULL, NULL, 0, 0}
};
struct tty_client {
bool running;
bool initialized;
+ int initial_cmd_index;
bool authenticated;
char hostname[100];
char address[50];
LIST_ENTRY(tty_client) list;
};
+struct pss_http {
+ char path[128];
+ char *buffer;
+ size_t len;
+};
+
struct tty_server {
LIST_HEAD(client, tty_client) clients; // client list
int client_count; // client count