From: Shuanglei Tao Date: Thu, 19 Jan 2017 15:33:35 +0000 (+0800) Subject: Add support for the --index option X-Git-Url: http://git.prime8.dev/?a=commitdiff_plain;h=c9ffa8a8d7d21ca3114b3bcd49fd8d4624723185;p=ttyd.git Add support for the --index option --- diff --git a/README.md b/README.md index 3f673b9..01e15f9 100644 --- a/README.md +++ b/README.md @@ -77,6 +77,7 @@ OPTIONS: --client-option, -t Send option to client (format: key=value), repeat to add more options --check-origin, -O Do not allow websocket connection from different origin --once, -o Accept only one client and exit on disconnection + --index, -I Custom index.html path --ssl, -S Enable SSL --ssl-cert, -C SSL certificate file path --ssl-key, -K SSL key file path diff --git a/src/http.c b/src/http.c index 4b92bb8..8b63e85 100644 --- a/src/http.c +++ b/src/http.c @@ -109,24 +109,28 @@ callback_http(struct lws *wsi, enum lws_callback_reasons reason, void *user, voi goto try_to_reuse; } - if (lws_add_http_header_status(wsi, HTTP_STATUS_OK, &p, end)) - return 1; - if (lws_add_http_header_by_token(wsi, - WSI_TOKEN_HTTP_CONTENT_TYPE, - (unsigned char *) "text/html", - 9, &p, end)) - return 1; - if (lws_add_http_header_content_length(wsi, (unsigned long) index_html_len, &p, end)) - return 1; - if (lws_finalize_http_header(wsi, &p, end)) - return 1; - if (lws_write(wsi, buffer + LWS_PRE, p - (buffer + LWS_PRE), LWS_WRITE_HTTP_HEADERS) < 0) { - return 1; - } + const char* content_type = "text/html"; + if (server->index != NULL) { + int n = lws_serve_http_file(wsi, server->index, content_type, NULL, 0); + if (n < 0 || (n > 0 && lws_http_transaction_completed(wsi))) + return 1; + } else { + if (lws_add_http_header_status(wsi, HTTP_STATUS_OK, &p, end)) + return 1; + if (lws_add_http_header_by_token(wsi, WSI_TOKEN_HTTP_CONTENT_TYPE, (const unsigned char *) content_type, 9, &p, end)) + return 1; + if (lws_add_http_header_content_length(wsi, (unsigned long) index_html_len, &p, end)) + return 1; + if (lws_finalize_http_header(wsi, &p, end)) + return 1; + 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) - return 1; + if (lws_write_http(wsi, index_html, index_html_len) < 0) + return 1; + } goto try_to_reuse; + case LWS_CALLBACK_OPENSSL_PERFORM_CLIENT_CERT_VERIFICATION: if (!len || (SSL_get_verify_result((SSL *) in) != X509_V_OK)) { int err = X509_STORE_CTX_get_error((X509_STORE_CTX *) user); @@ -136,6 +140,7 @@ callback_http(struct lws *wsi, enum lws_callback_reasons reason, void *user, voi return 1; } break; + default: break; } diff --git a/src/protocol.c b/src/protocol.c index 6317e31..278240a 100644 --- a/src/protocol.c +++ b/src/protocol.c @@ -197,6 +197,7 @@ callback_tty(struct lws *wsi, enum lws_callback_reasons reason, return -1; } break; + case LWS_CALLBACK_ESTABLISHED: client->exit = false; client->initialized = false; diff --git a/src/server.c b/src/server.c index 68f9eac..cfe3923 100644 --- a/src/server.c +++ b/src/server.c @@ -29,6 +29,7 @@ static const struct option options[] = { {"gid", required_argument, NULL, 'g'}, {"signal", required_argument, NULL, 's'}, {"reconnect", required_argument, NULL, 'r'}, + {"index", required_argument, NULL, 'I'}, {"ssl", no_argument, NULL, 'S'}, {"ssl-cert", required_argument, NULL, 'C'}, {"ssl-key", required_argument, NULL, 'K'}, @@ -41,7 +42,7 @@ static const struct option options[] = { {"help", no_argument, NULL, 'h'}, {NULL, 0, 0, 0} }; -static const char *opt_string = "p:i:c:u:g:s:r:aSC:K:A:Rt:Ood:vh"; +static const char *opt_string = "p:i:c:u:g:s:r:I:aSC:K:A:Rt:Ood:vh"; void print_help() { fprintf(stderr, "ttyd is a tool for sharing terminal over the web\n\n" @@ -61,6 +62,7 @@ void print_help() { " --client-option, -t Send option to client (format: key=value), repeat to add more options\n" " --check-origin, -O Do not allow websocket connection from different origin\n" " --once, -o Accept only one client and exit on disconnection\n" + " --index, -I Custom index.html path\n" " --ssl, -S Enable SSL\n" " --ssl-cert, -C SSL certificate file path\n" " --ssl-key, -K SSL key file path\n" @@ -112,6 +114,25 @@ tty_server_new(int argc, char **argv, int start) { return ts; } +void +tty_server_free(struct tty_server *ts) { + if (ts == NULL) + return; + if (ts->credential != NULL) + free(ts->credential); + if (ts->index != NULL) + free(ts->index); + free(ts->command); + free(ts->prefs_json); + int i = 0; + do { + free(ts->argv[i++]); + } while (ts->argv[i] != NULL); + free(ts->argv); + free(ts->sig_name); + free(ts); +} + void sig_handler(int sig) { if (force_exit) @@ -260,6 +281,24 @@ main(int argc, char **argv) { return -1; } break; + case 'I': + if (!strncmp(optarg, "~/", 2)) { + const char* home = getenv("HOME"); + server->index = malloc(strlen(home) + strlen(optarg) - 1); + sprintf(server->index, "%s%s", home, optarg + 1); + } else { + server->index = strdup(optarg); + } + struct stat st; + if (stat(server->index, &st) == -1) { + fprintf(stderr, "Can not stat index.html: %s, error: %s\n", server->index, strerror(errno)); + return -1; + } + if (S_ISDIR(st.st_mode)) { + fprintf(stderr, "Invalid index.html path: %s, is it a dir?\n", server->index); + return -1; + } + break; case 'S': ssl = true; break; @@ -360,6 +399,9 @@ main(int argc, char **argv) { lwsl_notice(" readonly: true\n"); if (server->once) lwsl_notice(" once: true\n"); + if (server->index != NULL) { + lwsl_notice(" custom index.html: %s\n", server->index); + } // libwebsockets main loop while (!force_exit) { @@ -379,17 +421,7 @@ main(int argc, char **argv) { lws_context_destroy(context); // cleanup - if (server->credential != NULL) - free(server->credential); - free(server->command); - free(server->prefs_json); - int i = 0; - do { - free(server->argv[i++]); - } while (server->argv[i] != NULL); - free(server->argv); - free(server->sig_name); - free(server); + tty_server_free(server); return 0; } diff --git a/src/server.h b/src/server.h index eb1235a..2c971d9 100644 --- a/src/server.h +++ b/src/server.h @@ -70,6 +70,7 @@ struct tty_server { char *prefs_json; // client preferences char *credential; // encoded basic auth credential int reconnect; // reconnect timeout + char *index; // custom index.html char *command; // full command line char **argv; // command with arguments int sig_code; // close signal