]> prime8.dev >> repos - ttyd.git/commitdiff
Add support for the --index option
authorShuanglei Tao <tsl0922@gmail.com>
Thu, 19 Jan 2017 15:33:35 +0000 (23:33 +0800)
committerShuanglei Tao <tsl0922@gmail.com>
Thu, 19 Jan 2017 15:40:20 +0000 (23:40 +0800)
README.md
src/http.c
src/protocol.c
src/server.c
src/server.h

index 3f673b92a5ba12dc2e4a0b7077e58a4b8095ec2e..01e15f9520b80e816ec401bd235fc62c34e415fd 100644 (file)
--- 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
index 4b92bb875e6421f641fdb6f7088ce31a843eb689..8b63e8505c4760a7c9060751fa2a245f870da612 100644 (file)
@@ -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;
     }
index 6317e314d6850794dc0103a707c61596b6890714..278240a5842b0bc3153474155c323f4a4737dfbb 100644 (file)
@@ -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;
index 68f9eacbcb1f4de43ce6852913f5c7b61297c28a..cfe39231bad93863c18f5f9b42bfae16188f58cd 100644 (file)
@@ -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;
 }
index eb1235ab0cdbde97d0b3a01b6479d2972927b3e4..2c971d992d5cd5cd5bfe4e51b8f35ac16c2513da 100644 (file)
@@ -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