mirror of
https://github.com/clearlinux/uwsgi.git
synced 2026-10-04 16:08:31 +00:00
implemented uwsgi protocol for forkptyrouter
This commit is contained in:
@@ -2,6 +2,13 @@
|
||||
|
||||
uWSGI forkpty-router
|
||||
|
||||
can use the uwsgi protocol, modifier2 means:
|
||||
|
||||
0 -> stdin
|
||||
1-99 -> UNIX signal
|
||||
100 -> window rows (pktsize is the window size)
|
||||
101 -> window cols (pktsize is the window size)
|
||||
|
||||
*/
|
||||
|
||||
#include <uwsgi.h>
|
||||
@@ -24,12 +31,16 @@ extern struct uwsgi_server uwsgi;
|
||||
static struct uwsgi_forkptyrouter {
|
||||
struct uwsgi_corerouter cr;
|
||||
char *cmd;
|
||||
// use the uwsgi protocol ?
|
||||
int uwsgi;
|
||||
} ufpty;
|
||||
|
||||
extern struct uwsgi_server uwsgi;
|
||||
|
||||
struct forkptyrouter_session {
|
||||
struct corerouter_session session;
|
||||
size_t restore_size;
|
||||
struct winsize w;
|
||||
pid_t pid;
|
||||
};
|
||||
|
||||
@@ -61,6 +72,7 @@ static struct uwsgi_option forkptyrouter_options[] = {
|
||||
|
||||
// write to backend
|
||||
static ssize_t fpty_instance_write(struct corerouter_peer *peer) {
|
||||
struct forkptyrouter_session *fpty_session = (struct forkptyrouter_session *) peer->session;
|
||||
ssize_t len = cr_write(peer, "fpty_instance_write()");
|
||||
// end on empty write
|
||||
if (!len) return 0;
|
||||
@@ -68,7 +80,8 @@ static ssize_t fpty_instance_write(struct corerouter_peer *peer) {
|
||||
// the chunk has been sent, start (again) reading from client and instances
|
||||
if (cr_write_complete(peer)) {
|
||||
// reset the buffer
|
||||
peer->out->pos = 0;
|
||||
if (uwsgi_buffer_decapitate(peer->out, peer->out->pos)) return -1;
|
||||
peer->out->pos = fpty_session->restore_size;
|
||||
cr_reset_hooks(peer);
|
||||
}
|
||||
|
||||
@@ -91,6 +104,42 @@ static ssize_t fpty_write(struct corerouter_peer *main_peer) {
|
||||
return len;
|
||||
}
|
||||
|
||||
static ssize_t fpty_parse_uwsgi(struct corerouter_peer *peer) {
|
||||
|
||||
struct forkptyrouter_session *fpty_session = (struct forkptyrouter_session *) peer->session;
|
||||
for(;;) {
|
||||
if (peer->in->pos < 4) return 0;
|
||||
struct uwsgi_header *uh = (struct uwsgi_header *) peer->in->buf;
|
||||
uint16_t pktsize = uh->pktsize;
|
||||
switch(uh->modifier2) {
|
||||
case 0:
|
||||
// stdin
|
||||
if ((size_t) (pktsize+4) > peer->in->pos) return 0;
|
||||
if (uwsgi_buffer_decapitate(peer->in, 4)) return -1;
|
||||
return pktsize;
|
||||
case 100:
|
||||
if (uwsgi_buffer_decapitate(peer->in, 4)) return -1;
|
||||
fpty_session->w.ws_row = pktsize;
|
||||
ioctl(peer->session->peers->fd, TIOCSWINSZ, &fpty_session->w);
|
||||
// rows
|
||||
break;
|
||||
case 101:
|
||||
if (uwsgi_buffer_decapitate(peer->in, 4)) return -1;
|
||||
fpty_session->w.ws_col = pktsize;
|
||||
ioctl(peer->session->peers->fd, TIOCSWINSZ, &fpty_session->w);
|
||||
// cols
|
||||
break;
|
||||
default:
|
||||
if (uwsgi_buffer_decapitate(peer->in, 4)) return -1;
|
||||
// send signal
|
||||
kill(fpty_session->pid, uh->modifier2);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
// read from backend
|
||||
static ssize_t fpty_instance_read(struct corerouter_peer *peer) {
|
||||
ssize_t len = cr_read(peer, "fpty_instance_read()");
|
||||
@@ -106,10 +155,18 @@ static ssize_t fpty_instance_read(struct corerouter_peer *peer) {
|
||||
|
||||
// read from client
|
||||
static ssize_t fpty_read(struct corerouter_peer *main_peer) {
|
||||
struct forkptyrouter_session *fpty_session = (struct forkptyrouter_session *) main_peer->session;
|
||||
ssize_t len = cr_read(main_peer, "fpty_read()");
|
||||
if (!len) return 0;
|
||||
|
||||
ssize_t rlen = fpty_parse_uwsgi(main_peer);
|
||||
if (rlen < 0) return -1;
|
||||
if (rlen == 0) return 1;
|
||||
|
||||
fpty_session->restore_size = main_peer->in->pos - rlen;
|
||||
|
||||
main_peer->session->peers->out = main_peer->in;
|
||||
main_peer->session->peers->out->pos = rlen;
|
||||
main_peer->session->peers->out_pos = 0;
|
||||
|
||||
cr_write_to_backend(main_peer->session->peers, fpty_instance_write);
|
||||
@@ -137,12 +194,15 @@ static int forkptyrouter_alloc_session(struct uwsgi_corerouter *ucr, struct uwsg
|
||||
cs->close = fpty_session_close;
|
||||
|
||||
struct forkptyrouter_session *fpty_session = (struct forkptyrouter_session *) cs;
|
||||
// default terminal size
|
||||
fpty_session->w.ws_row = 24;
|
||||
fpty_session->w.ws_col = 80;
|
||||
|
||||
// add a new peer
|
||||
struct corerouter_peer *peer = uwsgi_cr_peer_add(cs);
|
||||
|
||||
// on new connection generate a new pty
|
||||
fpty_session->pid = forkpty(&peer->fd, NULL, NULL, NULL);
|
||||
fpty_session->pid = forkpty(&peer->fd, NULL, NULL, &fpty_session->w);
|
||||
if (fpty_session->pid < 0) {
|
||||
uwsgi_error("forkpty()");
|
||||
return -1;
|
||||
|
||||
+39
-1
@@ -21,6 +21,7 @@ struct uwsgi_pty_client {
|
||||
static struct uwsgi_pty {
|
||||
char *addr;
|
||||
char *remote;
|
||||
char *uremote;
|
||||
int queue;
|
||||
int server_fd;
|
||||
int master_fd;
|
||||
@@ -77,6 +78,7 @@ static struct uwsgi_option uwsgi_pty_options[] = {
|
||||
{"pty-log", no_argument, 0, "send stdout/stderr to the log engine too", uwsgi_opt_true, &upty.log, 0},
|
||||
{"pty-input", no_argument, 0, "read from original stdin in addition to pty", uwsgi_opt_true, &upty.input, 0},
|
||||
{"pty-connect", required_argument, 0, "connect the current terminal to a pty server", uwsgi_opt_set_str, &upty.remote, 0},
|
||||
{"pty-uconnect", required_argument, 0, "connect the current terminal to a pty server (using uwsgi protocol)", uwsgi_opt_set_str, &upty.uremote, 0},
|
||||
{"pty-no-isig", no_argument, 0, "disable ISIG terminal attribute in client mode", uwsgi_opt_true, &upty.no_isig, 0},
|
||||
{"pty-exec", required_argument, 0, "run the specified command soon after the pty thread is spawned", uwsgi_opt_set_str, &upty.command, 0},
|
||||
{0, 0, 0, 0, 0, 0, 0},
|
||||
@@ -256,6 +258,27 @@ static void uwsgi_pty_init() {
|
||||
|
||||
}
|
||||
|
||||
static void uwsgi_pty_winch() {
|
||||
// 2 uwsgi packets
|
||||
char uwsgi_pkt[8];
|
||||
#ifdef TIOCGWINSZ
|
||||
struct winsize w;
|
||||
ioctl(0, TIOCGWINSZ, &w);
|
||||
uwsgi_pkt[0] = 0;
|
||||
uwsgi_pkt[1] = (uint8_t) (w.ws_row & 0xff);
|
||||
uwsgi_pkt[2] = (uint8_t) ((w.ws_row >> 8) & 0xff);
|
||||
uwsgi_pkt[3] = 100;
|
||||
uwsgi_pkt[4] = 0;
|
||||
uwsgi_pkt[5] = (uint8_t) (w.ws_col & 0xff);
|
||||
uwsgi_pkt[6] = (uint8_t) ((w.ws_col >> 8) & 0xff);
|
||||
uwsgi_pkt[7] = 101;
|
||||
#endif
|
||||
if (write(upty.server_fd, uwsgi_pkt, 8) != 8) {
|
||||
uwsgi_error("uwsgi_pty_winch()/write()");
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
static int uwsgi_pty_client() {
|
||||
if (!upty.remote) return 0;
|
||||
|
||||
@@ -277,8 +300,14 @@ static int uwsgi_pty_client() {
|
||||
|
||||
uwsgi_log("[pty] connected.\n");
|
||||
|
||||
|
||||
uwsgi_pty_setterm(0);
|
||||
|
||||
signal(SIGWINCH, uwsgi_pty_winch);
|
||||
|
||||
// send current terminal size
|
||||
uwsgi_pty_winch();
|
||||
|
||||
upty.queue = event_queue_init();
|
||||
event_queue_add_fd_read(upty.queue, upty.server_fd);
|
||||
event_queue_add_fd_read(upty.queue, 0);
|
||||
@@ -287,10 +316,19 @@ static int uwsgi_pty_client() {
|
||||
char buf[8192];
|
||||
int interesting_fd = -1;
|
||||
int ret = event_queue_wait(upty.queue, -1, &interesting_fd);
|
||||
if (ret <= 0) break;
|
||||
if (ret == 0) break;
|
||||
if (ret < 0) {
|
||||
if (errno == EINTR) continue;
|
||||
break;
|
||||
}
|
||||
if (interesting_fd == 0) {
|
||||
ssize_t rlen = read(0, buf, 8192);
|
||||
if (rlen <= 0) break;
|
||||
struct uwsgi_header uh;
|
||||
uh.modifier1 = 0;
|
||||
uh.pktsize = rlen;
|
||||
uh.modifier2 = 0;
|
||||
if (write(upty.server_fd, &uh, 4) != 4) break;
|
||||
if (write(upty.server_fd, buf, rlen) != rlen) break;
|
||||
continue;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user