1 /* $OpenBSD$ */
2 
3 /*
4  * Copyright (c) 2012 Nicholas Marriott <nicholas.marriott@gmail.com>
5  * Copyright (c) 2012 George Nachman <tmux@georgester.com>
6  *
7  * Permission to use, copy, modify, and distribute this software for any
8  * purpose with or without fee is hereby granted, provided that the above
9  * copyright notice and this permission notice appear in all copies.
10  *
11  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
12  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
13  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
14  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
15  * WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER
16  * IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
17  * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
18  */
19 
20 #include <sys/types.h>
21 
22 #include <stdlib.h>
23 #include <string.h>
24 #include <time.h>
25 #include <unistd.h>
26 
27 #include "tmux.h"
28 
29 /*
30  * Block of data to output. Each client has one "all" queue of blocks and
31  * another queue for each pane (in struct client_offset). %output blocks are
32  * added to both queues and other output lines (notifications) added only to
33  * the client queue.
34  *
35  * When a client becomes writeable, data from blocks on the pane queue are sent
36  * up to the maximum size (CLIENT_BUFFER_HIGH). If a block is entirely written,
37  * it is removed from both pane and client queues and if this means non-%output
38  * blocks are now at the head of the client queue, they are written.
39  *
40  * This means a %output block holds up any subsequent non-%output blocks until
41  * it is written which enforces ordering even if the client cannot accept the
42  * entire block in one go.
43  */
44 struct control_block {
45 	size_t				 size;
46 	char				*line;
47 	uint64_t			 t;
48 
49 	TAILQ_ENTRY(control_block)	 entry;
50 	TAILQ_ENTRY(control_block)	 all_entry;
51 };
52 
53 /* Control client pane. */
54 struct control_pane {
55 	u_int				 pane;
56 
57 	/*
58 	 * Offsets into the pane data. The first (offset) is the data we have
59 	 * written; the second (queued) the data we have queued (pointed to by
60 	 * a block).
61 	 */
62 	struct window_pane_offset	 offset;
63 	struct window_pane_offset	 queued;
64 
65 	int				 flags;
66 #define CONTROL_PANE_OFF 0x1
67 #define CONTROL_PANE_PAUSED 0x2
68 
69 	int				 pending_flag;
70 	TAILQ_ENTRY(control_pane)	 pending_entry;
71 
72 	TAILQ_HEAD(, control_block)	 blocks;
73 
74 	RB_ENTRY(control_pane)		 entry;
75 };
76 RB_HEAD(control_panes, control_pane);
77 
78 /* Subscription pane. */
79 struct control_sub_pane {
80 	u_int				 pane;
81 	u_int				 idx;
82 	char				*last;
83 
84 	RB_ENTRY(control_sub_pane)	 entry;
85 };
86 RB_HEAD(control_sub_panes, control_sub_pane);
87 
88 /* Subscription window. */
89 struct control_sub_window {
90 	u_int				 window;
91 	u_int				 idx;
92 	char				*last;
93 
94 	RB_ENTRY(control_sub_window)	 entry;
95 };
96 RB_HEAD(control_sub_windows, control_sub_window);
97 
98 /* Control client subscription. */
99 struct control_sub {
100 	char				*name;
101 	char				*format;
102 
103 	enum control_sub_type		 type;
104 	u_int				 id;
105 
106 	char				*last;
107 	struct control_sub_panes	 panes;
108 	struct control_sub_windows	 windows;
109 
110 	RB_ENTRY(control_sub)		 entry;
111 };
112 RB_HEAD(control_subs, control_sub);
113 
114 /* Control client state. */
115 struct control_state {
116 	struct control_panes		 panes;
117 
118 	TAILQ_HEAD(, control_pane)	 pending_list;
119 	u_int				 pending_count;
120 
121 	TAILQ_HEAD(, control_block)	 all_blocks;
122 
123 	struct bufferevent		*read_event;
124 	struct bufferevent		*write_event;
125 
126 	struct control_subs		 subs;
127 	struct event			 subs_timer;
128 };
129 
130 /* Low and high watermarks. */
131 #define CONTROL_BUFFER_LOW 512
132 #define CONTROL_BUFFER_HIGH 8192
133 
134 /* Minimum to write to each client. */
135 #define CONTROL_WRITE_MINIMUM 32
136 
137 /* Maximum age for clients that are not using pause mode. */
138 #define CONTROL_MAXIMUM_AGE 300000
139 
140 /* Flags to ignore client. */
141 #define CONTROL_IGNORE_FLAGS \
142 	(CLIENT_CONTROL_NOOUTPUT| \
143 	 CLIENT_UNATTACHEDFLAGS)
144 
145 /* Compare client panes. */
146 static int
control_pane_cmp(struct control_pane * cp1,struct control_pane * cp2)147 control_pane_cmp(struct control_pane *cp1, struct control_pane *cp2)
148 {
149 	if (cp1->pane < cp2->pane)
150 		return (-1);
151 	if (cp1->pane > cp2->pane)
152 		return (1);
153 	return (0);
154 }
155 RB_GENERATE_STATIC(control_panes, control_pane, entry, control_pane_cmp);
156 
157 /* Compare client subs. */
158 static int
control_sub_cmp(struct control_sub * csub1,struct control_sub * csub2)159 control_sub_cmp(struct control_sub *csub1, struct control_sub *csub2)
160 {
161 	return (strcmp(csub1->name, csub2->name));
162 }
163 RB_GENERATE_STATIC(control_subs, control_sub, entry, control_sub_cmp);
164 
165 /* Compare client subscription panes. */
166 static int
control_sub_pane_cmp(struct control_sub_pane * csp1,struct control_sub_pane * csp2)167 control_sub_pane_cmp(struct control_sub_pane *csp1,
168     struct control_sub_pane *csp2)
169 {
170 	if (csp1->pane < csp2->pane)
171 		return (-1);
172 	if (csp1->pane > csp2->pane)
173 		return (1);
174 	if (csp1->idx < csp2->idx)
175 		return (-1);
176 	if (csp1->idx > csp2->idx)
177 		return (1);
178 	return (0);
179 }
180 RB_GENERATE_STATIC(control_sub_panes, control_sub_pane, entry,
181     control_sub_pane_cmp);
182 
183 /* Compare client subscription windows. */
184 static int
control_sub_window_cmp(struct control_sub_window * csw1,struct control_sub_window * csw2)185 control_sub_window_cmp(struct control_sub_window *csw1,
186     struct control_sub_window *csw2)
187 {
188 	if (csw1->window < csw2->window)
189 		return (-1);
190 	if (csw1->window > csw2->window)
191 		return (1);
192 	if (csw1->idx < csw2->idx)
193 		return (-1);
194 	if (csw1->idx > csw2->idx)
195 		return (1);
196 	return (0);
197 }
198 RB_GENERATE_STATIC(control_sub_windows, control_sub_window, entry,
199     control_sub_window_cmp);
200 
201 /* Free a subscription. */
202 static void
control_free_sub(struct control_state * cs,struct control_sub * csub)203 control_free_sub(struct control_state *cs, struct control_sub *csub)
204 {
205 	struct control_sub_pane		*csp, *csp1;
206 	struct control_sub_window	*csw, *csw1;
207 
208 	RB_FOREACH_SAFE(csp, control_sub_panes, &csub->panes, csp1) {
209 		RB_REMOVE(control_sub_panes, &csub->panes, csp);
210 		free(csp);
211 	}
212 	RB_FOREACH_SAFE(csw, control_sub_windows, &csub->windows, csw1) {
213 		RB_REMOVE(control_sub_windows, &csub->windows, csw);
214 		free(csw);
215 	}
216 	free(csub->last);
217 
218 	RB_REMOVE(control_subs, &cs->subs, csub);
219 	free(csub->name);
220 	free(csub->format);
221 	free(csub);
222 }
223 
224 /* Free a block. */
225 static void
control_free_block(struct control_state * cs,struct control_block * cb)226 control_free_block(struct control_state *cs, struct control_block *cb)
227 {
228 	free(cb->line);
229 	TAILQ_REMOVE(&cs->all_blocks, cb, all_entry);
230 	free(cb);
231 }
232 
233 /* Get pane offsets for this client. */
234 static struct control_pane *
control_get_pane(struct client * c,struct window_pane * wp)235 control_get_pane(struct client *c, struct window_pane *wp)
236 {
237 	struct control_state	*cs = c->control_state;
238 	struct control_pane	 cp = { .pane = wp->id };
239 
240 	return (RB_FIND(control_panes, &cs->panes, &cp));
241 }
242 
243 /* Add pane offsets for this client. */
244 static struct control_pane *
control_add_pane(struct client * c,struct window_pane * wp)245 control_add_pane(struct client *c, struct window_pane *wp)
246 {
247 	struct control_state	*cs = c->control_state;
248 	struct control_pane	*cp;
249 
250 	cp = control_get_pane(c, wp);
251 	if (cp != NULL)
252 		return (cp);
253 
254 	cp = xcalloc(1, sizeof *cp);
255 	cp->pane = wp->id;
256 	RB_INSERT(control_panes, &cs->panes, cp);
257 
258 	memcpy(&cp->offset, &wp->offset, sizeof cp->offset);
259 	memcpy(&cp->queued, &wp->offset, sizeof cp->queued);
260 	TAILQ_INIT(&cp->blocks);
261 
262 	return (cp);
263 }
264 
265 /* Discard output for a pane. */
266 static void
control_discard_pane(struct client * c,struct control_pane * cp)267 control_discard_pane(struct client *c, struct control_pane *cp)
268 {
269 	struct control_state	*cs = c->control_state;
270 	struct control_block	*cb, *cb1;
271 
272 	TAILQ_FOREACH_SAFE(cb, &cp->blocks, entry, cb1) {
273 		TAILQ_REMOVE(&cp->blocks, cb, entry);
274 		control_free_block(cs, cb);
275 	}
276 }
277 
278 /* Get actual pane for this client. */
279 static struct window_pane *
control_window_pane(struct client * c,u_int pane)280 control_window_pane(struct client *c, u_int pane)
281 {
282 	struct window_pane	*wp;
283 
284 	if (c->session == NULL)
285 		return (NULL);
286 	if ((wp = window_pane_find_by_id(pane)) == NULL)
287 		return (NULL);
288 	if (winlink_find_by_window(&c->session->windows, wp->window) == NULL)
289 		return (NULL);
290 	return (wp);
291 }
292 
293 /* Reset control offsets. */
294 void
control_reset_offsets(struct client * c)295 control_reset_offsets(struct client *c)
296 {
297 	struct control_state	*cs = c->control_state;
298 	struct control_pane	*cp, *cp1;
299 
300 	RB_FOREACH_SAFE(cp, control_panes, &cs->panes, cp1) {
301 		RB_REMOVE(control_panes, &cs->panes, cp);
302 		free(cp);
303 	}
304 
305 	TAILQ_INIT(&cs->pending_list);
306 	cs->pending_count = 0;
307 }
308 
309 /* Get offsets for client. */
310 struct window_pane_offset *
control_pane_offset(struct client * c,struct window_pane * wp,int * off)311 control_pane_offset(struct client *c, struct window_pane *wp, int *off)
312 {
313 	struct control_state	*cs = c->control_state;
314 	struct control_pane	*cp;
315 
316 	if (c->flags & CLIENT_CONTROL_NOOUTPUT) {
317 		*off = 0;
318 		return (NULL);
319 	}
320 
321 	cp = control_get_pane(c, wp);
322 	if (cp == NULL || (cp->flags & CONTROL_PANE_PAUSED)) {
323 		*off = 0;
324 		return (NULL);
325 	}
326 	if (cp->flags & CONTROL_PANE_OFF) {
327 		*off = 1;
328 		return (NULL);
329 	}
330 	*off = (EVBUFFER_LENGTH(cs->write_event->output) >= CONTROL_BUFFER_LOW);
331 	return (&cp->offset);
332 }
333 
334 /* Set pane as on. */
335 void
control_set_pane_on(struct client * c,struct window_pane * wp)336 control_set_pane_on(struct client *c, struct window_pane *wp)
337 {
338 	struct control_pane	*cp;
339 
340 	cp = control_get_pane(c, wp);
341 	if (cp != NULL && (cp->flags & CONTROL_PANE_OFF)) {
342 		cp->flags &= ~CONTROL_PANE_OFF;
343 		memcpy(&cp->offset, &wp->offset, sizeof cp->offset);
344 		memcpy(&cp->queued, &wp->offset, sizeof cp->queued);
345 	}
346 }
347 
348 /* Set pane as off. */
349 void
control_set_pane_off(struct client * c,struct window_pane * wp)350 control_set_pane_off(struct client *c, struct window_pane *wp)
351 {
352 	struct control_pane	*cp;
353 
354 	cp = control_add_pane(c, wp);
355 	cp->flags |= CONTROL_PANE_OFF;
356 }
357 
358 /* Continue a paused pane. */
359 void
control_continue_pane(struct client * c,struct window_pane * wp)360 control_continue_pane(struct client *c, struct window_pane *wp)
361 {
362 	struct control_pane	*cp;
363 
364 	cp = control_get_pane(c, wp);
365 	if (cp != NULL && (cp->flags & CONTROL_PANE_PAUSED)) {
366 		cp->flags &= ~CONTROL_PANE_PAUSED;
367 		memcpy(&cp->offset, &wp->offset, sizeof cp->offset);
368 		memcpy(&cp->queued, &wp->offset, sizeof cp->queued);
369 		control_write(c, "%%continue %%%u", wp->id);
370 	}
371 }
372 
373 /* Pause a pane. */
374 void
control_pause_pane(struct client * c,struct window_pane * wp)375 control_pause_pane(struct client *c, struct window_pane *wp)
376 {
377 	struct control_pane	*cp;
378 
379 	cp = control_add_pane(c, wp);
380 	if (~cp->flags & CONTROL_PANE_PAUSED) {
381 		cp->flags |= CONTROL_PANE_PAUSED;
382 		control_discard_pane(c, cp);
383 		control_write(c, "%%pause %%%u", wp->id);
384 	}
385 }
386 
387 /* Write a line. */
388 static void
control_vwrite(struct client * c,const char * fmt,va_list ap)389 control_vwrite(struct client *c, const char *fmt, va_list ap)
390 {
391 	struct control_state	*cs = c->control_state;
392 	char			*s;
393 
394 	xvasprintf(&s, fmt, ap);
395 	log_debug("%s: %s: writing line: %s", __func__, c->name, s);
396 
397 	bufferevent_write(cs->write_event, s, strlen(s));
398 	bufferevent_write(cs->write_event, "\n", 1);
399 
400 	bufferevent_enable(cs->write_event, EV_WRITE);
401 	free(s);
402 }
403 
404 /* Write a line. */
405 void
control_write(struct client * c,const char * fmt,...)406 control_write(struct client *c, const char *fmt, ...)
407 {
408 	struct control_state	*cs = c->control_state;
409 	struct control_block	*cb;
410 	va_list			 ap;
411 
412 	va_start(ap, fmt);
413 
414 	if (TAILQ_EMPTY(&cs->all_blocks)) {
415 		control_vwrite(c, fmt, ap);
416 		va_end(ap);
417 		return;
418 	}
419 
420 	cb = xcalloc(1, sizeof *cb);
421 	xvasprintf(&cb->line, fmt, ap);
422 	TAILQ_INSERT_TAIL(&cs->all_blocks, cb, all_entry);
423 	cb->t = get_timer();
424 
425 	log_debug("%s: %s: storing line: %s", __func__, c->name, cb->line);
426 	bufferevent_enable(cs->write_event, EV_WRITE);
427 
428 	va_end(ap);
429 }
430 
431 /* Check age for this pane. */
432 static int
control_check_age(struct client * c,struct window_pane * wp,struct control_pane * cp)433 control_check_age(struct client *c, struct window_pane *wp,
434     struct control_pane *cp)
435 {
436 	struct control_block	*cb;
437 	uint64_t		 t, age;
438 
439 	cb = TAILQ_FIRST(&cp->blocks);
440 	if (cb == NULL)
441 		return (0);
442 	t = get_timer();
443 	if (cb->t >= t)
444 		return (0);
445 
446 	age = t - cb->t;
447 	log_debug("%s: %s: %%%u is %llu behind", __func__, c->name, wp->id,
448 	    (unsigned long long)age);
449 
450 	if (c->flags & CLIENT_CONTROL_PAUSEAFTER) {
451 		if (age < c->pause_age)
452 			return (0);
453 		cp->flags |= CONTROL_PANE_PAUSED;
454 		control_discard_pane(c, cp);
455 		control_write(c, "%%pause %%%u", wp->id);
456 	} else {
457 		if (age < CONTROL_MAXIMUM_AGE)
458 			return (0);
459 		c->exit_message = xstrdup("too far behind");
460 		c->flags |= CLIENT_EXIT;
461 		control_discard(c);
462 	}
463 	return (1);
464 }
465 
466 /* Write output from a pane. */
467 void
control_write_output(struct client * c,struct window_pane * wp)468 control_write_output(struct client *c, struct window_pane *wp)
469 {
470 	struct control_state	*cs = c->control_state;
471 	struct control_pane	*cp;
472 	struct control_block	*cb;
473 	size_t			 new_size;
474 
475 	if (winlink_find_by_window(&c->session->windows, wp->window) == NULL)
476 		return;
477 
478 	if (c->flags & CONTROL_IGNORE_FLAGS) {
479 		cp = control_get_pane(c, wp);
480 		if (cp != NULL)
481 			goto ignore;
482 		return;
483 	}
484 	cp = control_add_pane(c, wp);
485 	if (cp->flags & (CONTROL_PANE_OFF|CONTROL_PANE_PAUSED))
486 		goto ignore;
487 	if (control_check_age(c, wp, cp))
488 		return;
489 
490 	window_pane_get_new_data(wp, &cp->queued, &new_size);
491 	if (new_size == 0)
492 		return;
493 	window_pane_update_used_data(wp, &cp->queued, new_size);
494 
495 	cb = xcalloc(1, sizeof *cb);
496 	cb->size = new_size;
497 	TAILQ_INSERT_TAIL(&cs->all_blocks, cb, all_entry);
498 	cb->t = get_timer();
499 
500 	TAILQ_INSERT_TAIL(&cp->blocks, cb, entry);
501 	log_debug("%s: %s: new output block of %zu for %%%u", __func__, c->name,
502 	    cb->size, wp->id);
503 
504 	if (!cp->pending_flag) {
505 		log_debug("%s: %s: %%%u now pending", __func__, c->name,
506 		    wp->id);
507 		TAILQ_INSERT_TAIL(&cs->pending_list, cp, pending_entry);
508 		cp->pending_flag = 1;
509 		cs->pending_count++;
510 	}
511 	bufferevent_enable(cs->write_event, EV_WRITE);
512 	return;
513 
514 ignore:
515 	log_debug("%s: %s: ignoring pane %%%u", __func__, c->name, wp->id);
516 	window_pane_update_used_data(wp, &cp->offset, SIZE_MAX);
517 	window_pane_update_used_data(wp, &cp->queued, SIZE_MAX);
518 }
519 
520 /* Control client error callback. */
521 static enum cmd_retval
control_error(struct cmdq_item * item,void * data)522 control_error(struct cmdq_item *item, void *data)
523 {
524 	struct client	*c = cmdq_get_client(item);
525 	char		*error = data;
526 
527 	cmdq_guard(item, "begin", 1);
528 	control_write(c, "parse error: %s", error);
529 	cmdq_guard(item, "error", 1);
530 
531 	free(error);
532 	return (CMD_RETURN_NORMAL);
533 }
534 
535 /* Control client error callback. */
536 static void
control_error_callback(__unused struct bufferevent * bufev,__unused short what,void * data)537 control_error_callback(__unused struct bufferevent *bufev,
538     __unused short what, void *data)
539 {
540 	struct client	*c = data;
541 
542 	c->flags |= CLIENT_EXIT;
543 }
544 
545 /* Control client input callback. Read lines and fire commands. */
546 static void
control_read_callback(__unused struct bufferevent * bufev,void * data)547 control_read_callback(__unused struct bufferevent *bufev, void *data)
548 {
549 	struct client		*c = data;
550 	struct control_state	*cs = c->control_state;
551 	struct evbuffer		*buffer = cs->read_event->input;
552 	char			*line, *error;
553 	struct cmdq_state	*state;
554 	enum cmd_parse_status	 status;
555 
556 	for (;;) {
557 		line = evbuffer_readln(buffer, NULL, EVBUFFER_EOL_LF);
558 		if (line == NULL)
559 			break;
560 		log_debug("%s: %s: %s", __func__, c->name, line);
561 		if (*line == '\0') { /* empty line detach */
562 			free(line);
563 			c->flags |= CLIENT_EXIT;
564 			break;
565 		}
566 
567 		state = cmdq_new_state(NULL, NULL, CMDQ_STATE_CONTROL);
568 		status = cmd_parse_and_append(line, NULL, c, state, &error);
569 		if (status == CMD_PARSE_ERROR)
570 			cmdq_append(c, cmdq_get_callback(control_error, error));
571 		cmdq_free_state(state);
572 
573 		free(line);
574 	}
575 }
576 
577 /* Does this control client have outstanding data to write? */
578 int
control_all_done(struct client * c)579 control_all_done(struct client *c)
580 {
581 	struct control_state	*cs = c->control_state;
582 
583 	if (!TAILQ_EMPTY(&cs->all_blocks))
584 		return (0);
585 	return (EVBUFFER_LENGTH(cs->write_event->output) == 0);
586 }
587 
588 /* Flush all blocks until output. */
589 static void
control_flush_all_blocks(struct client * c)590 control_flush_all_blocks(struct client *c)
591 {
592 	struct control_state	*cs = c->control_state;
593 	struct control_block	*cb, *cb1;
594 
595 	TAILQ_FOREACH_SAFE(cb, &cs->all_blocks, all_entry, cb1) {
596 		if (cb->size != 0)
597 			break;
598 		log_debug("%s: %s: flushing line: %s", __func__, c->name,
599 		    cb->line);
600 
601 		bufferevent_write(cs->write_event, cb->line, strlen(cb->line));
602 		bufferevent_write(cs->write_event, "\n", 1);
603 		control_free_block(cs, cb);
604 	}
605 }
606 
607 /* Append data to buffer. */
608 static struct evbuffer *
control_append_data(struct client * c,struct control_pane * cp,uint64_t age,struct evbuffer * message,struct window_pane * wp,size_t size)609 control_append_data(struct client *c, struct control_pane *cp, uint64_t age,
610     struct evbuffer *message, struct window_pane *wp, size_t size)
611 {
612 	u_char	*new_data;
613 	size_t	 new_size;
614 	u_int	 i;
615 
616 	if (message == NULL) {
617 		message = evbuffer_new();
618 		if (message == NULL)
619 			fatalx("out of memory");
620 		if (c->flags & CLIENT_CONTROL_PAUSEAFTER) {
621 			evbuffer_add_printf(message,
622 			    "%%extended-output %%%u %llu : ", wp->id,
623 			    (unsigned long long)age);
624 		} else
625 			evbuffer_add_printf(message, "%%output %%%u ", wp->id);
626 	}
627 
628 	new_data = window_pane_get_new_data(wp, &cp->offset, &new_size);
629 	if (new_size < size)
630 		fatalx("not enough data: %zu < %zu", new_size, size);
631 	for (i = 0; i < size; i++) {
632 		if (new_data[i] < ' ' || new_data[i] == '\\')
633 			evbuffer_add_printf(message, "\\%03o", new_data[i]);
634 		else
635 			evbuffer_add_printf(message, "%c", new_data[i]);
636 	}
637 	window_pane_update_used_data(wp, &cp->offset, size);
638 	return (message);
639 }
640 
641 /* Write buffer. */
642 static void
control_write_data(struct client * c,struct evbuffer * message)643 control_write_data(struct client *c, struct evbuffer *message)
644 {
645 	struct control_state	*cs = c->control_state;
646 
647 	log_debug("%s: %s: %.*s", __func__, c->name,
648 	    (int)EVBUFFER_LENGTH(message), EVBUFFER_DATA(message));
649 
650 	evbuffer_add(message, "\n", 1);
651 	bufferevent_write_buffer(cs->write_event, message);
652 	evbuffer_free(message);
653 }
654 
655 /* Write output to client. */
656 static int
control_write_pending(struct client * c,struct control_pane * cp,size_t limit)657 control_write_pending(struct client *c, struct control_pane *cp, size_t limit)
658 {
659 	struct control_state	*cs = c->control_state;
660 	struct window_pane	*wp = NULL;
661 	struct evbuffer		*message = NULL;
662 	size_t			 used = 0, size;
663 	struct control_block	*cb, *cb1;
664 	uint64_t		 age, t = get_timer();
665 
666 	wp = control_window_pane(c, cp->pane);
667 	if (wp == NULL) {
668 		TAILQ_FOREACH_SAFE(cb, &cp->blocks, entry, cb1) {
669 			TAILQ_REMOVE(&cp->blocks, cb, entry);
670 			control_free_block(cs, cb);
671 		}
672 		control_flush_all_blocks(c);
673 		return (0);
674 	}
675 
676 	while (used != limit && !TAILQ_EMPTY(&cp->blocks)) {
677 		if (control_check_age(c, wp, cp)) {
678 			if (message != NULL)
679 				evbuffer_free(message);
680 			message = NULL;
681 			break;
682 		}
683 
684 		cb = TAILQ_FIRST(&cp->blocks);
685 		if (cb->t < t)
686 			age = t - cb->t;
687 		else
688 			age = 0;
689 		log_debug("%s: %s: output block %zu (age %llu) for %%%u "
690 		    "(used %zu/%zu)", __func__, c->name, cb->size,
691 		    (unsigned long long)age, cp->pane, used, limit);
692 
693 		size = cb->size;
694 		if (size > limit - used)
695 			size = limit - used;
696 		used += size;
697 
698 		message = control_append_data(c, cp, age, message, wp, size);
699 
700 		cb->size -= size;
701 		if (cb->size == 0) {
702 			TAILQ_REMOVE(&cp->blocks, cb, entry);
703 			control_free_block(cs, cb);
704 
705 			cb = TAILQ_FIRST(&cs->all_blocks);
706 			if (cb != NULL && cb->size == 0) {
707 				if (wp != NULL && message != NULL) {
708 					control_write_data(c, message);
709 					message = NULL;
710 				}
711 				control_flush_all_blocks(c);
712 			}
713 		}
714 	}
715 	if (message != NULL)
716 		control_write_data(c, message);
717 	return (!TAILQ_EMPTY(&cp->blocks));
718 }
719 
720 /* Control client write callback. */
721 static void
control_write_callback(__unused struct bufferevent * bufev,void * data)722 control_write_callback(__unused struct bufferevent *bufev, void *data)
723 {
724 	struct client		*c = data;
725 	struct control_state	*cs = c->control_state;
726 	struct control_pane	*cp, *cp1;
727 	struct evbuffer		*evb = cs->write_event->output;
728 	size_t			 space, limit;
729 
730 	control_flush_all_blocks(c);
731 
732 	while (EVBUFFER_LENGTH(evb) < CONTROL_BUFFER_HIGH) {
733 		if (cs->pending_count == 0)
734 			break;
735 		space = CONTROL_BUFFER_HIGH - EVBUFFER_LENGTH(evb);
736 		log_debug("%s: %s: %zu bytes available, %u panes", __func__,
737 		    c->name, space, cs->pending_count);
738 
739 		limit = (space / cs->pending_count / 3); /* 3 bytes for \xxx */
740 		if (limit < CONTROL_WRITE_MINIMUM)
741 			limit = CONTROL_WRITE_MINIMUM;
742 
743 		TAILQ_FOREACH_SAFE(cp, &cs->pending_list, pending_entry, cp1) {
744 			if (EVBUFFER_LENGTH(evb) >= CONTROL_BUFFER_HIGH)
745 				break;
746 			if (control_write_pending(c, cp, limit))
747 				continue;
748 			TAILQ_REMOVE(&cs->pending_list, cp, pending_entry);
749 			cp->pending_flag = 0;
750 			cs->pending_count--;
751 		}
752 	}
753 	if (EVBUFFER_LENGTH(evb) == 0)
754 		bufferevent_disable(cs->write_event, EV_WRITE);
755 }
756 
757 /* Initialize for control mode. */
758 void
control_start(struct client * c)759 control_start(struct client *c)
760 {
761 	struct control_state	*cs;
762 
763 	if (c->flags & CLIENT_CONTROLCONTROL) {
764 		close(c->out_fd);
765 		c->out_fd = -1;
766 	} else
767 		setblocking(c->out_fd, 0);
768 	setblocking(c->fd, 0);
769 
770 	cs = c->control_state = xcalloc(1, sizeof *cs);
771 	RB_INIT(&cs->panes);
772 	TAILQ_INIT(&cs->pending_list);
773 	TAILQ_INIT(&cs->all_blocks);
774 	RB_INIT(&cs->subs);
775 
776 	cs->read_event = bufferevent_new(c->fd, control_read_callback,
777 	    control_write_callback, control_error_callback, c);
778 	bufferevent_enable(cs->read_event, EV_READ);
779 
780 	if (c->flags & CLIENT_CONTROLCONTROL)
781 		cs->write_event = cs->read_event;
782 	else {
783 		cs->write_event = bufferevent_new(c->out_fd, NULL,
784 		    control_write_callback, control_error_callback, c);
785 	}
786 	bufferevent_setwatermark(cs->write_event, EV_WRITE, CONTROL_BUFFER_LOW,
787 	    0);
788 
789 	if (c->flags & CLIENT_CONTROLCONTROL) {
790 		bufferevent_write(cs->write_event, "\033P1000p", 7);
791 		bufferevent_enable(cs->write_event, EV_WRITE);
792 	}
793 }
794 
795 /* Discard all output for a client. */
796 void
control_discard(struct client * c)797 control_discard(struct client *c)
798 {
799 	struct control_state	*cs = c->control_state;
800 	struct control_pane	*cp;
801 
802 	RB_FOREACH(cp, control_panes, &cs->panes)
803 		control_discard_pane(c, cp);
804 	bufferevent_disable(cs->read_event, EV_READ);
805 }
806 
807 /* Stop control mode. */
808 void
control_stop(struct client * c)809 control_stop(struct client *c)
810 {
811 	struct control_state	*cs = c->control_state;
812 	struct control_block	*cb, *cb1;
813 	struct control_sub	*csub, *csub1;
814 
815 	if (~c->flags & CLIENT_CONTROLCONTROL)
816 		bufferevent_free(cs->write_event);
817 	bufferevent_free(cs->read_event);
818 
819 	RB_FOREACH_SAFE(csub, control_subs, &cs->subs, csub1)
820 		control_free_sub(cs, csub);
821 	if (evtimer_initialized(&cs->subs_timer))
822 		evtimer_del(&cs->subs_timer);
823 
824 	TAILQ_FOREACH_SAFE(cb, &cs->all_blocks, all_entry, cb1)
825 		control_free_block(cs, cb);
826 	control_reset_offsets(c);
827 
828 	free(cs);
829 }
830 
831 /* Check session subscription. */
832 static void
control_check_subs_session(struct client * c,struct control_sub * csub)833 control_check_subs_session(struct client *c, struct control_sub *csub)
834 {
835 	struct session		*s = c->session;
836 	struct format_tree	*ft;
837 	char			*value;
838 
839 	ft = format_create_defaults(NULL, c, s, NULL, NULL);
840 	value = format_expand(ft, csub->format);
841 	format_free(ft);
842 
843 	if (csub->last != NULL && strcmp(value, csub->last) == 0) {
844 		free(value);
845 		return;
846 	}
847 	control_write(c,
848 	    "%%subscription-changed %s $%u - - - : %s",
849 	    csub->name, s->id, value);
850 	free(csub->last);
851 	csub->last = value;
852 }
853 
854 /* Check pane subscription. */
855 static void
control_check_subs_pane(struct client * c,struct control_sub * csub)856 control_check_subs_pane(struct client *c, struct control_sub *csub)
857 {
858 	struct session		*s = c->session;
859 	struct window_pane	*wp;
860 	struct window		*w;
861 	struct winlink		*wl;
862 	struct format_tree	*ft;
863 	char			*value;
864 	struct control_sub_pane	*csp, find;
865 
866 	wp = window_pane_find_by_id(csub->id);
867 	if (wp == NULL)
868 		return;
869 	w = wp->window;
870 
871 	TAILQ_FOREACH(wl, &w->winlinks, wentry) {
872 		if (wl->session != s)
873 			continue;
874 
875 		ft = format_create_defaults(NULL, c, s, wl, wp);
876 		value = format_expand(ft, csub->format);
877 		format_free(ft);
878 
879 		find.pane = wp->id;
880 		find.idx = wl->idx;
881 
882 		csp = RB_FIND(control_sub_panes, &csub->panes, &find);
883 		if (csp == NULL) {
884 			csp = xcalloc(1, sizeof *csp);
885 			csp->pane = wp->id;
886 			csp->idx = wl->idx;
887 			RB_INSERT(control_sub_panes, &csub->panes, csp);
888 		}
889 
890 		if (csp->last != NULL && strcmp(value, csp->last) == 0) {
891 			free(value);
892 			continue;
893 		}
894 		control_write(c,
895 		    "%%subscription-changed %s $%u @%u %u %%%u : %s",
896 		    csub->name, s->id, w->id, wl->idx, wp->id, value);
897 		free(csp->last);
898 		csp->last = value;
899 	}
900 }
901 
902 /* Check all panes subscription. */
903 static void
control_check_subs_all_panes(struct client * c,struct control_sub * csub)904 control_check_subs_all_panes(struct client *c, struct control_sub *csub)
905 {
906 	struct session		*s = c->session;
907 	struct window_pane	*wp;
908 	struct window		*w;
909 	struct winlink		*wl;
910 	struct format_tree	*ft;
911 	char			*value;
912 	struct control_sub_pane	*csp, find;
913 
914 	RB_FOREACH(wl, winlinks, &s->windows) {
915 		w = wl->window;
916 		TAILQ_FOREACH(wp, &w->panes, entry) {
917 			ft = format_create_defaults(NULL, c, s, wl, wp);
918 			value = format_expand(ft, csub->format);
919 			format_free(ft);
920 
921 			find.pane = wp->id;
922 			find.idx = wl->idx;
923 
924 			csp = RB_FIND(control_sub_panes, &csub->panes, &find);
925 			if (csp == NULL) {
926 				csp = xcalloc(1, sizeof *csp);
927 				csp->pane = wp->id;
928 				csp->idx = wl->idx;
929 				RB_INSERT(control_sub_panes, &csub->panes, csp);
930 			}
931 
932 			if (csp->last != NULL &&
933 			    strcmp(value, csp->last) == 0) {
934 				free(value);
935 				continue;
936 			}
937 			control_write(c,
938 			    "%%subscription-changed %s $%u @%u %u %%%u : %s",
939 			    csub->name, s->id, w->id, wl->idx, wp->id, value);
940 			free(csp->last);
941 			csp->last = value;
942 		}
943 	}
944 }
945 
946 /* Check window subscription. */
947 static void
control_check_subs_window(struct client * c,struct control_sub * csub)948 control_check_subs_window(struct client *c, struct control_sub *csub)
949 {
950 	struct session			*s = c->session;
951 	struct window			*w;
952 	struct winlink			*wl;
953 	struct format_tree		*ft;
954 	char				*value;
955 	struct control_sub_window	*csw, find;
956 
957 	w = window_find_by_id(csub->id);
958 	if (w == NULL)
959 		return;
960 
961 	TAILQ_FOREACH(wl, &w->winlinks, wentry) {
962 		if (wl->session != s)
963 			continue;
964 
965 		ft = format_create_defaults(NULL, c, s, wl, NULL);
966 		value = format_expand(ft, csub->format);
967 		format_free(ft);
968 
969 		find.window = w->id;
970 		find.idx = wl->idx;
971 
972 		csw = RB_FIND(control_sub_windows, &csub->windows, &find);
973 		if (csw == NULL) {
974 			csw = xcalloc(1, sizeof *csw);
975 			csw->window = w->id;
976 			csw->idx = wl->idx;
977 			RB_INSERT(control_sub_windows, &csub->windows, csw);
978 		}
979 
980 		if (csw->last != NULL && strcmp(value, csw->last) == 0) {
981 			free(value);
982 			continue;
983 		}
984 		control_write(c,
985 		    "%%subscription-changed %s $%u @%u %u - : %s",
986 		    csub->name, s->id, w->id, wl->idx, value);
987 		free(csw->last);
988 		csw->last = value;
989 	}
990 }
991 
992 /* Check all windows subscription. */
993 static void
control_check_subs_all_windows(struct client * c,struct control_sub * csub)994 control_check_subs_all_windows(struct client *c, struct control_sub *csub)
995 {
996 	struct session			*s = c->session;
997 	struct window			*w;
998 	struct winlink			*wl;
999 	struct format_tree		*ft;
1000 	char				*value;
1001 	struct control_sub_window	*csw, find;
1002 
1003 	RB_FOREACH(wl, winlinks, &s->windows) {
1004 		w = wl->window;
1005 
1006 		ft = format_create_defaults(NULL, c, s, wl, NULL);
1007 		value = format_expand(ft, csub->format);
1008 		format_free(ft);
1009 
1010 		find.window = w->id;
1011 		find.idx = wl->idx;
1012 
1013 		csw = RB_FIND(control_sub_windows, &csub->windows, &find);
1014 		if (csw == NULL) {
1015 			csw = xcalloc(1, sizeof *csw);
1016 			csw->window = w->id;
1017 			csw->idx = wl->idx;
1018 			RB_INSERT(control_sub_windows, &csub->windows, csw);
1019 		}
1020 
1021 		if (csw->last != NULL && strcmp(value, csw->last) == 0) {
1022 			free(value);
1023 			continue;
1024 		}
1025 		control_write(c,
1026 		    "%%subscription-changed %s $%u @%u %u - : %s",
1027 		    csub->name, s->id, w->id, wl->idx, value);
1028 		free(csw->last);
1029 		csw->last = value;
1030 	}
1031 }
1032 
1033 /* Check subscriptions timer. */
1034 static void
control_check_subs_timer(__unused int fd,__unused short events,void * data)1035 control_check_subs_timer(__unused int fd, __unused short events, void *data)
1036 {
1037 	struct client		*c = data;
1038 	struct control_state	*cs = c->control_state;
1039 	struct control_sub	*csub, *csub1;
1040 	struct timeval		 tv = { .tv_sec = 1 };
1041 
1042 	log_debug("%s: timer fired", __func__);
1043 	evtimer_add(&cs->subs_timer, &tv);
1044 
1045 	RB_FOREACH_SAFE(csub, control_subs, &cs->subs, csub1) {
1046 		switch (csub->type) {
1047 		case CONTROL_SUB_SESSION:
1048 			control_check_subs_session(c, csub);
1049 			break;
1050 		case CONTROL_SUB_PANE:
1051 			control_check_subs_pane(c, csub);
1052 			break;
1053 		case CONTROL_SUB_ALL_PANES:
1054 			control_check_subs_all_panes(c, csub);
1055 			break;
1056 		case CONTROL_SUB_WINDOW:
1057 			control_check_subs_window(c, csub);
1058 			break;
1059 		case CONTROL_SUB_ALL_WINDOWS:
1060 			control_check_subs_all_windows(c, csub);
1061 			break;
1062 		}
1063 	}
1064 }
1065 
1066 /* Add a subscription. */
1067 void
control_add_sub(struct client * c,const char * name,enum control_sub_type type,int id,const char * format)1068 control_add_sub(struct client *c, const char *name, enum control_sub_type type,
1069     int id, const char *format)
1070 {
1071 	struct control_state	*cs = c->control_state;
1072 	struct control_sub	*csub, find;
1073 	struct timeval		 tv = { .tv_sec = 1 };
1074 
1075 	find.name = (char *)name;
1076 	if ((csub = RB_FIND(control_subs, &cs->subs, &find)) != NULL)
1077 		control_free_sub(cs, csub);
1078 
1079 	csub = xcalloc(1, sizeof *csub);
1080 	csub->name = xstrdup(name);
1081 	csub->type = type;
1082 	csub->id = id;
1083 	csub->format = xstrdup(format);
1084 	RB_INSERT(control_subs, &cs->subs, csub);
1085 
1086 	RB_INIT(&csub->panes);
1087 	RB_INIT(&csub->windows);
1088 
1089 	if (!evtimer_initialized(&cs->subs_timer))
1090 		evtimer_set(&cs->subs_timer, control_check_subs_timer, c);
1091 	if (!evtimer_pending(&cs->subs_timer, NULL))
1092 		evtimer_add(&cs->subs_timer, &tv);
1093 }
1094 
1095 /* Remove a subscription. */
1096 void
control_remove_sub(struct client * c,const char * name)1097 control_remove_sub(struct client *c, const char *name)
1098 {
1099 	struct control_state	*cs = c->control_state;
1100 	struct control_sub	*csub, find;
1101 
1102 	find.name = (char *)name;
1103 	if ((csub = RB_FIND(control_subs, &cs->subs, &find)) != NULL)
1104 		control_free_sub(cs, csub);
1105 	if (RB_EMPTY(&cs->subs))
1106 		evtimer_del(&cs->subs_timer);
1107 }
1108