// on data received err_t client_recv(void *arg, struct tcp_pcb *pcb, struct pbuf *p, err_t err) { struct client *c = arg; if (err!=ERR_OK) { pbuf_free(p); return client_kill(c); } // no buffer if (!p) { c->st = TERMINATED; // and no queued data -> close if (!c->p) return client_kill(c); return flushq(c); } switch (c->st) { case ACCEPTED: { c->st++; } case RECEIVED: { // this is a hack - we assume each line fits into a single packet // this could be done properly using pbuf header magic and keeping line state u8_t *dst = p->payload; u8_t *res = memchr(dst, '\n', p->len); // invalid data or exit requested if (!res || !memcmp(dst,"exit",4)) { pbuf_free(p); return client_kill(c); } // reverse the line if (res[-1] == '\r') res--; u32_t len = res-dst; for (int i = 0; i < (len)/2;i++) { u8_t t = dst[i]; dst[i] = dst[len-i-1]; dst[len-i-1] = t; } dst[len] = '\n'; pbuf_realloc(p, len+1); // and enqueue it if (c->p) { pbuf_chain(c->p, p); return ERR_OK; } c->p = p; return flushq(c); } // unknown state default: { tcp_recved(pcb, p->tot_len); c->p = NULL; // XXX leaky? pbuf_free(p); } } return ERR_OK; }
static void handle_client(struct sstate *ss, struct client *c) { unsigned char buf[2048]; int len = sizeof(buf); int cmd; cmd = net_get(c->c_s, buf, &len); if (cmd == -1) { debug(ss, c, 2, "handle_client: net_get()\n"); client_kill(c); return; } /* figure out command */ switch (cmd) { case NET_SET_CHAN: handle_set_chan(ss, c, buf, len); break; case NET_SET_RATE: handle_set_rate(ss, c, buf, len); break; case NET_GET_MAC: handle_get_mac(ss, c); break; case NET_GET_CHAN: handle_get_chan(ss, c); break; case NET_GET_RATE: handle_get_rate(ss, c); break; case NET_GET_MONITOR: handle_get_monitor(ss, c); break; case NET_WRITE: handle_write(ss, c, buf, len); break; default: printf("Unknown request %d\n", cmd); client_kill(c); break; } }
static gboolean run_func(struct wm_actions_data *data, gpointer options) { (void)options; if(data->client) client_kill(data->client); return FALSE; }
void key_handler_kill(struct key *key) { (void)key; if (selmon->sel) client_kill(selmon->sel); }
// flush queues err_t flushq(struct client *c) { struct tcp_pcb *pcb = c->pcb; while (c->p != NULL && c->p->len < tcp_sndbuf(pcb)) { if (tcp_write(pcb, c->p->payload, c->p->len, 1) != ERR_OK) break; // defer to poll u32_t oldlen = c->p->len; struct pbuf *next = c->p->next; pbuf_free(c->p); if ((c->p = next)) pbuf_ref(c->p); tcp_recved(pcb, oldlen); } if (c->st == TERMINATED) client_kill(c); return ERR_OK; }
void client_registry_unpublish(struct client *c, s32 name) { s32 o_idx=0; while(1){ if(o_idx==CLIENT_OBJS_MAX) break; struct client_obj *o=&c->objs[o_idx]; if(!(o->state&CLIENT_OBJ_INVALID)&&o->state&CLIENT_OBJ_REGISTRY_MAP) if(o->map.name==REGISTRY_NAME){ s8 r=wl_registry_ev_global_remove(c,o->id,name); if(r==LWL_ERR){ client_kill(c);//naughty client, kill it return; } } ++o_idx; } }
static void handle_set_rate(struct sstate *ss, struct client *c, unsigned char *buf, int len) { uint32_t rate; uint32_t rc; if (len != sizeof(rate)) { client_kill(c); return; } rate = *((uint32_t*)buf); rate = ntohl(rate); debug(ss, c, 2, "Got setrate %d\n", rate); rc = card_set_rate(ss, rate); rc = htonl(rc); net_send_kill(c, NET_RC, &rc, sizeof(rc)); }
static void handle_set_chan(struct sstate *ss, struct client *c, unsigned char *buf, int len) { uint32_t chan; uint32_t rc; if (len != sizeof(chan)) { client_kill(c); return; } chan = *((uint32_t*)buf); chan = ntohl(chan); debug(ss, c, 2, "Got setchan %d\n", chan); rc = card_set_chan(ss, chan); rc = htonl(rc); net_send_kill(c, NET_RC, &rc, sizeof(rc)); }
static void seat_caps_broadcast(s32 seat_name) { s32 client=0; while(1){ if(client==CLIENTS_MAX) break; struct client *c=&clients[client]; s32 obj=CLIENT_FIRST_VALID_ID; while(1){ if(obj==CLIENT_OBJS_MAX) break; struct client_obj *o=&c->objs[obj]; if(!(o->state&CLIENT_OBJ_INVALID)&&(o->state&CLIENT_OBJ_REGISTRY_MAP)){ struct gbl *g=®istry[o->map.name]; if(g->itf==WL_SEAT&&o->map.name==seat_name){ s8 r=wl_seat_ev_capabilities(c,o->id,g->seat.caps); if(r==LWL_ERR) client_kill(c);//punish misbehaving client } } ++obj; } ++client; } }
static void net_send_kill(struct client *c, int cmd, void *data, int len) { if (net_send(c->c_s, cmd, data, len) == -1) client_kill(c); }
/* ClientMessage handle event *\param ev XClientMessageEvent pointer */ static void clientmessageevent(XClientMessageEvent *ev) { Client *c; Systray *sy; int s, i, mess_t = 0; Atom rt; int rf; ulong ir, il; uchar *ret = NULL; uchar *ret_cmd = NULL; void (*func)(uicb_t); if(ev->format != 32) return; s = screen_count(); for(i = 0; i < net_last + s; ++i) if(net_atom[i] == ev->message_type) mess_t = i; if(ev->window == ROOT) { /* Manage _NET_CURRENT_DESKTOP */ if(mess_t == net_current_desktop && ev->data.l[0] >= 0 && ev->data.l[0] < conf.ntag[selscreen]) tag_set((int)(ev->data.l[0] + 1)); /* Manage _WMFS_SET_SCREEN */ if(mess_t == wmfs_set_screen && ev->data.l[0] >= 0 && ev->data.l[0] <= s) screen_set_sel((int)(ev->data.l[0])); /* Manage _NET_ACTIVE_WINDOW */ else if(mess_t == net_active_window) { if((c = client_gb_win(ev->window))) client_focus(c); else if((sy = systray_find(ev->data.l[0]))) XSetInputFocus(dpy, sy->win, RevertToNone, CurrentTime); } } else if(ev->window == traywin) { /* Manage _NET_WM_SYSTEM_TRAY_OPCODE */ if(mess_t == net_wm_system_tray_opcode) { if(ev->data.l[1] == XEMBED_EMBEDDED_NOTIFY) { systray_add(ev->data.l[2]); systray_update(); } else if(ev->data.l[1] == XEMBED_REQUEST_FOCUS) if((sy = systray_find(ev->data.l[2]))) ewmh_send_message(sy->win, sy->win, "_XEMBED", XEMBED_FOCUS_IN, XEMBED_FOCUS_CURRENT, 0, 0, 0); } } /* Manage _NET_WM_STATE */ if(mess_t == net_wm_state) if((c = client_gb_win(ev->window))) ewmh_manage_net_wm_state(ev->data.l, c); /* Manage _NET_CLOSE_WINDOW */ if(mess_t == net_close_window) if((c = client_gb_win(ev->window))) client_kill(c); /* Manage _NET_WM_DESKTOP */ if(mess_t == net_wm_desktop) if((c = client_gb_win(ev->window)) && ev->data.l[0] != (long)0xFFFFFFFF) tag_transfert(c, ev->data.l[0]); /* Manage _WMFS_STATUSTEXT_x */ if(mess_t >= wmfs_statustext && ev->data.l[4] == True) { if(XGetWindowProperty(dpy, ROOT, net_atom[mess_t], 0, 4096, False, net_atom[utf8_string], &rt, &rf, &ir, &il, &ret) == Success) { statustext_handle(mess_t - wmfs_statustext, (char*)ret); XFree(ret); } } /* Manage _WMFS_FUNCTION && _WMFS_CMD */ if((mess_t == wmfs_function && ev->data.l[4] == True) || (mess_t == wmfs_cmd && ev->data.l[4] == True)) { XGetWindowProperty(dpy, ROOT, net_atom[wmfs_function], 0, 4096, False, net_atom[utf8_string], &rt, &rf, &ir, &il, &ret); XGetWindowProperty(dpy, ROOT, net_atom[wmfs_cmd], 0, 4096, False, net_atom[utf8_string], &rt, &rf, &ir, &il, &ret_cmd); if((func = name_to_func((char*)ret, func_list))) func((uicb_t)ret_cmd); XFree(ret_cmd); XFree(ret); } /* Manage _WMFS_UPDATE_HINTS */ if(mess_t == wmfs_update_hints) { ewmh_get_number_of_desktop(); ewmh_update_current_tag_prop(); ewmh_get_client_list(); ewmh_get_desktop_names(); ewmh_set_desktop_geometry(); screen_count(); screen_get_sel(); } if(mess_t == wmfs_update_status && estatus) spawn(conf.status_path); return; }