version 1.345, 2020/05/21 07:24:13 |
version 1.346, 2020/05/22 11:07:04 |
|
|
} |
} |
RB_GENERATE(client_windows, client_window, entry, server_client_window_cmp); |
RB_GENERATE(client_windows, client_window, entry, server_client_window_cmp); |
|
|
/* Compare client offsets. */ |
|
static int |
|
server_client_offset_cmp(struct client_offset *co1, struct client_offset *co2) |
|
{ |
|
if (co1->pane < co2->pane) |
|
return (-1); |
|
if (co1->pane > co2->pane) |
|
return (1); |
|
return (0); |
|
} |
|
RB_GENERATE(client_offsets, client_offset, entry, server_client_offset_cmp); |
|
|
|
/* Get pane offsets for this client. */ |
|
struct client_offset * |
|
server_client_get_pane_offset(struct client *c, struct window_pane *wp) |
|
{ |
|
struct client_offset co = { .pane = wp->id }; |
|
|
|
return (RB_FIND(client_offsets, &c->offsets, &co)); |
|
} |
|
|
|
/* Add pane offsets for this client. */ |
|
struct client_offset * |
|
server_client_add_pane_offset(struct client *c, struct window_pane *wp) |
|
{ |
|
struct client_offset *co; |
|
|
|
co = server_client_get_pane_offset(c, wp); |
|
if (co != NULL) |
|
return (co); |
|
co = xcalloc(1, sizeof *co); |
|
co->pane = wp->id; |
|
RB_INSERT(client_offsets, &c->offsets, co); |
|
memcpy(&co->offset, &wp->offset, sizeof co->offset); |
|
return (co); |
|
} |
|
|
|
/* Number of attached clients. */ |
/* Number of attached clients. */ |
u_int |
u_int |
server_client_how_many(void) |
server_client_how_many(void) |
|
|
|
|
c->queue = cmdq_new(); |
c->queue = cmdq_new(); |
RB_INIT(&c->windows); |
RB_INIT(&c->windows); |
RB_INIT(&c->offsets); |
|
RB_INIT(&c->files); |
RB_INIT(&c->files); |
|
|
c->tty.fd = -1; |
c->tty.fd = -1; |
|
|
{ |
{ |
struct client_file *cf, *cf1; |
struct client_file *cf, *cf1; |
struct client_window *cw, *cw1; |
struct client_window *cw, *cw1; |
struct client_offset *co, *co1; |
|
|
|
c->flags |= CLIENT_DEAD; |
c->flags |= CLIENT_DEAD; |
|
|
|
|
RB_REMOVE(client_windows, &c->windows, cw); |
RB_REMOVE(client_windows, &c->windows, cw); |
free(cw); |
free(cw); |
} |
} |
RB_FOREACH_SAFE(co, client_offsets, &c->offsets, co1) { |
control_free_offsets(c); |
RB_REMOVE(client_offsets, &c->offsets, co); |
|
free(co); |
|
} |
|
|
|
TAILQ_REMOVE(&clients, c, entry); |
TAILQ_REMOVE(&clients, c, entry); |
log_debug("lost client %p", c); |
log_debug("lost client %p", c); |
|
|
struct evbuffer *evb = wp->event->input; |
struct evbuffer *evb = wp->event->input; |
size_t minimum; |
size_t minimum; |
struct client *c; |
struct client *c; |
struct client_offset *co; |
struct window_pane_offset *wpo; |
int off = !TAILQ_EMPTY(&clients); |
int off = 1, flag; |
|
u_int attached_clients = 0; |
|
|
/* |
/* |
* Work out the minimum acknowledged size. This is the most that can be |
* Work out the minimum acknowledged size. This is the most that can be |
|
|
TAILQ_FOREACH(c, &clients, entry) { |
TAILQ_FOREACH(c, &clients, entry) { |
if (c->session == NULL) |
if (c->session == NULL) |
continue; |
continue; |
if ((~c->flags & CLIENT_CONTROL) || |
attached_clients++; |
(c->flags & CLIENT_CONTROL_NOOUTPUT) || |
|
(co = server_client_get_pane_offset(c, wp)) == NULL) { |
if (~c->flags & CLIENT_CONTROL) { |
off = 0; |
off = 0; |
continue; |
continue; |
} |
} |
if (~co->flags & CLIENT_OFFSET_OFF) |
wpo = control_pane_offset(c, wp, &flag); |
|
if (wpo == NULL) { |
off = 0; |
off = 0; |
|
continue; |
|
} |
|
if (!flag) |
|
off = 0; |
|
|
log_debug("%s: %s has %zu bytes used, %zu bytes acknowledged " |
log_debug("%s: %s has %zu bytes used, %zu bytes acknowledged " |
"for %%%u", __func__, c->name, co->offset.used, |
"for %%%u", __func__, c->name, wpo->used, wpo->acknowledged, |
co->offset.acknowledged, wp->id); |
wp->id); |
if (co->offset.acknowledged < minimum) |
if (wpo->acknowledged < minimum) |
minimum = co->offset.acknowledged; |
minimum = wpo->acknowledged; |
} |
} |
|
if (attached_clients == 0) |
|
off = 0; |
minimum -= wp->base_offset; |
minimum -= wp->base_offset; |
if (minimum == 0) |
if (minimum == 0) |
goto out; |
goto out; |
|
|
TAILQ_FOREACH(c, &clients, entry) { |
TAILQ_FOREACH(c, &clients, entry) { |
if (c->session == NULL || (~c->flags & CLIENT_CONTROL)) |
if (c->session == NULL || (~c->flags & CLIENT_CONTROL)) |
continue; |
continue; |
co = server_client_get_pane_offset(c, wp); |
wpo = control_pane_offset(c, wp, &flag); |
if (co != NULL) { |
if (wpo != NULL && !flag) { |
co->offset.acknowledged -= wp->base_offset; |
wpo->acknowledged -= wp->base_offset; |
co->offset.used -= wp->base_offset; |
wpo->used -= wp->base_offset; |
} |
} |
} |
} |
wp->base_offset = minimum; |
wp->base_offset = minimum; |
|
|
c->flags &= ~flag; |
c->flags &= ~flag; |
else |
else |
c->flags |= flag; |
c->flags |= flag; |
|
if (flag == CLIENT_CONTROL_NOOUTPUT) |
|
control_free_offsets(c); |
} |
} |
free(copy); |
free(copy); |
|
|
} |
} |
|
|
/* Get client flags. This is only flags useful to show to users. */ |
/* Get client flags. This is only flags useful to show to users. */ |