Add support for the --once option

This commit is contained in:
Shuanglei Tao
2016-10-10 21:39:43 +08:00
parent f3d06b2857
commit 3c9884a87b
5 changed files with 48 additions and 13 deletions

View File

@@ -65,6 +65,7 @@ OPTIONS:
--gid, -g Group id to run with --gid, -g Group id to run with
--signal, -s Signal to send to the command when exit it (default: SIGHUP) --signal, -s Signal to send to the command when exit it (default: SIGHUP)
--reconnect, -r Time to reconnect for the client in seconds (default: 10) --reconnect, -r Time to reconnect for the client in seconds (default: 10)
--once, -o Accept only one client and exit on disconnection
--ssl, -S Enable ssl --ssl, -S Enable ssl
--ssl-cert, -C Ssl certificate file path --ssl-cert, -C Ssl certificate file path
--ssl-key, -K Ssl key file path --ssl-key, -K Ssl key file path

30
src/index.html vendored
View File

@@ -600,20 +600,17 @@
var io = term.io.push(); var io = term.io.push();
io.onVTKeystroke = function(str) { io.onVTKeystroke = function(str) {
if (ws.readyState === WebSocket.OPEN) {
ws.send("0" + str); ws.send("0" + str);
}
}; };
io.sendString = io.onVTKeystroke; io.sendString = io.onVTKeystroke;
io.onTerminalResize = function(columns, rows) { io.onTerminalResize = function(columns, rows) {
ws.send( if (ws.readyState === WebSocket.OPEN) {
"2" + JSON.stringify( ws.send("2" + JSON.stringify({columns: columns, rows: rows}));
{
columns: columns,
rows: rows,
} }
)
)
}; };
term.installKeyboard(); term.installKeyboard();
@@ -635,7 +632,7 @@
term.setWindowTitle(data); term.setWindowTitle(data);
break; break;
case '3': case '3':
preferences = JSON.parse(data); var preferences = JSON.parse(data);
Object.keys(preferences).forEach(function(key) { Object.keys(preferences).forEach(function(key) {
console.log("Setting " + key + ": " + preferences[key]); console.log("Setting " + key + ": " + preferences[key]);
term.getPrefs().set(key, preferences[key]); term.getPrefs().set(key, preferences[key]);
@@ -651,13 +648,30 @@
ws.onclose = function(event) { ws.onclose = function(event) {
if (term) { if (term) {
term.uninstallKeyboard(); term.uninstallKeyboard();
setTimeout(function(){
term.io.showOverlay("Connection Closed", null); term.io.showOverlay("Connection Closed", null);
}, 300);
} }
clearInterval(pingTimer); clearInterval(pingTimer);
if (autoReconnect > 0) { if (autoReconnect > 0) {
setTimeout(openWs, autoReconnect * 1000); setTimeout(openWs, autoReconnect * 1000);
} }
}; };
ws.onerror = function(event) {
var errorNode = document.createElement('div');
errorNode.style.cssText = [
"color: red",
"font-size: x-large",
"opacity: 0.75",
"text-align: center",
"margin: 1em",
"padding: 0.2em",
"border: 0.1em dotted #ccc"
].join(";");
errorNode.textContent = "Websocket handshake failed!";
document.getElementById("terminal").appendChild(errorNode);
};
}; };

View File

@@ -65,7 +65,7 @@ parse_window_size(const char *json) {
void void
tty_client_destroy(struct tty_client *client) { tty_client_destroy(struct tty_client *client) {
if (client->exit) if (client->exit || client->pid <= 0)
return; return;
// stop event loop // stop event loop
@@ -159,6 +159,12 @@ callback_tty(struct lws *wsi, enum lws_callback_reasons reason,
struct winsize *size; struct winsize *size;
switch (reason) { switch (reason) {
case LWS_CALLBACK_FILTER_PROTOCOL_CONNECTION:
if (server->once && server->client_count > 0) {
lwsl_notice("refuse to serve new client due to the --once option.\n");
return -1;
}
break;
case LWS_CALLBACK_ESTABLISHED: case LWS_CALLBACK_ESTABLISHED:
client->exit = false; client->exit = false;
client->initialized = false; client->initialized = false;
@@ -305,6 +311,12 @@ callback_tty(struct lws *wsi, enum lws_callback_reasons reason,
case LWS_CALLBACK_CLOSED: case LWS_CALLBACK_CLOSED:
tty_client_destroy(client); tty_client_destroy(client);
lwsl_notice("client disconnected from %s (%s), total: %d\n", client->hostname, client->address, server->client_count); lwsl_notice("client disconnected from %s (%s), total: %d\n", client->hostname, client->address, server->client_count);
if (server->once && server->client_count == 0) {
lwsl_notice("exiting due to the --once option.\n");
force_exit = true;
lws_cancel_service(context);
exit(0);
}
break; break;
default: default:

View File

@@ -33,12 +33,13 @@ static const struct option options[] = {
{"ssl-cert", required_argument, NULL, 'C'}, {"ssl-cert", required_argument, NULL, 'C'},
{"ssl-key", required_argument, NULL, 'K'}, {"ssl-key", required_argument, NULL, 'K'},
{"ssl-ca", required_argument, NULL, 'A'}, {"ssl-ca", required_argument, NULL, 'A'},
{"once", no_argument, NULL, 'o'},
{"debug", required_argument, NULL, 'd'}, {"debug", required_argument, NULL, 'd'},
{"version", no_argument, NULL, 'v'}, {"version", no_argument, NULL, 'v'},
{"help", no_argument, NULL, 'h'}, {"help", no_argument, NULL, 'h'},
{NULL, 0, 0, 0} {NULL, 0, 0, 0}
}; };
static const char *opt_string = "p:i:c:u:g:s:r:aSC:K:A:d:vh"; static const char *opt_string = "p:i:c:u:g:s:r:aSC:K:A:od:vh";
void print_help() { void print_help() {
fprintf(stderr, "ttyd is a tool for sharing terminal over the web\n\n" fprintf(stderr, "ttyd is a tool for sharing terminal over the web\n\n"
@@ -54,6 +55,7 @@ void print_help() {
" --gid, -g Group id to run with\n" " --gid, -g Group id to run with\n"
" --signal, -s Signal to send to the command when exit it (default: SIGHUP)\n" " --signal, -s Signal to send to the command when exit it (default: SIGHUP)\n"
" --reconnect, -r Time to reconnect for the client in seconds (default: 10)\n" " --reconnect, -r Time to reconnect for the client in seconds (default: 10)\n"
" --once, -o Accept only one client and exit on disconnection\n"
" --ssl, -S Enable ssl\n" " --ssl, -S Enable ssl\n"
" --ssl-cert, -C Ssl certificate file path\n" " --ssl-cert, -C Ssl certificate file path\n"
" --ssl-key, -K Ssl key file path\n" " --ssl-key, -K Ssl key file path\n"
@@ -200,6 +202,9 @@ main(int argc, char **argv) {
case 'd': case 'd':
debug_level = atoi(optarg); debug_level = atoi(optarg);
break; break;
case 'o':
server->once = true;
break;
case 'p': case 'p':
info.port = atoi(optarg); info.port = atoi(optarg);
if (info.port < 0) { if (info.port < 0) {
@@ -317,6 +322,8 @@ main(int argc, char **argv) {
lwsl_notice(" start command: %s\n", server->command); lwsl_notice(" start command: %s\n", server->command);
lwsl_notice(" reconnect timeout: %ds\n", server->reconnect); lwsl_notice(" reconnect timeout: %ds\n", server->reconnect);
lwsl_notice(" close signal: %s (%d)\n", server->sig_name, server->sig_code); lwsl_notice(" close signal: %s (%d)\n", server->sig_name, server->sig_code);
if (server->once)
lwsl_notice(" once: true\n");
// libwebsockets main loop // libwebsockets main loop
while (!force_exit) { while (!force_exit) {

View File

@@ -71,6 +71,7 @@ struct tty_server {
char **argv; // command with arguments char **argv; // command with arguments
int sig_code; // close signal int sig_code; // close signal
char *sig_name; // human readable signal string char *sig_name; // human readable signal string
bool once; // whether accept only one client and exit on disconnection
pthread_mutex_t lock; pthread_mutex_t lock;
}; };