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