chiark / gitweb /
*** empty log message ***
[sympathy.git] / apps / clients.c
1 /*
2  * clients.c:
3  *
4  * Copyright (c) 2008 James McKenzie <james@fishsoup.dhs.org>,
5  * All rights reserved.
6  *
7  */
8
9 static char rcsid[] = "$Id$";
10
11 /*
12  * $Log$
13  * Revision 1.15  2008/03/02 10:27:24  james
14  * *** empty log message ***
15  *
16  * Revision 1.14  2008/02/28 16:57:51  james
17  * *** empty log message ***
18  *
19  * Revision 1.13  2008/02/28 16:37:16  james
20  * *** empty log message ***
21  *
22  * Revision 1.12  2008/02/28 12:12:24  james
23  * *** empty log message ***
24  *
25  * Revision 1.11  2008/02/23 11:48:51  james
26  * *** empty log message ***
27  *
28  * Revision 1.10  2008/02/22 17:06:59  james
29  * *** empty log message ***
30  *
31  * Revision 1.9  2008/02/20 18:49:11  staffcvs
32  * *** empty log message ***
33  *
34  * Revision 1.8  2008/02/20 18:31:44  james
35  * *** empty log message ***
36  *
37  * Revision 1.7  2008/02/15 23:52:12  james
38  * *** empty log message ***
39  *
40  * Revision 1.6  2008/02/15 03:32:07  james
41  * *** empty log message ***
42  *
43  * Revision 1.5  2008/02/14 10:34:47  james
44  * *** empty log message ***
45  *
46  * Revision 1.4  2008/02/14 10:34:30  james
47  * *** empty log message ***
48  *
49  * Revision 1.3  2008/02/14 02:46:44  james
50  * *** empty log message ***
51  *
52  * Revision 1.2  2008/02/14 00:57:58  james
53  * *** empty log message ***
54  *
55  * Revision 1.1  2008/02/13 18:05:06  james
56  * *** empty log message ***
57  *
58  */
59
60 #include <sympathy.h>
61 #include <stdio.h>
62 #include <stdlib.h>
63 #include <string.h>
64 #include <strings.h>
65 #include <malloc.h>
66 #include "clients.h"
67
68 void
69 client_msg (IPC_Msg * m, Context * c)
70 {
71   switch (m->hdr.type) {
72
73   case IPC_MSG_TYPE_NOOP:
74     break;
75   case IPC_MSG_TYPE_DEBUG:
76     fprintf (stderr, "%p [%d] %s\n", m, m->hdr.size, m->debug.msg);
77     break;
78   case IPC_MSG_TYPE_KEY:
79     vt102_send (c, m->key.key);
80     break;
81   case IPC_MSG_TYPE_SETBAUD:
82     tty_set_baud (c->t, m->setbaud.baud);
83     tty_parse_reset (c);
84
85     log_f (c->l, "<baud changed to %d>", m->setbaud.baud);
86     break;
87   case IPC_MSG_TYPE_SENDBREAK:
88     tty_send_break (c->t);
89     break;
90   case IPC_MSG_TYPE_SETFLOW:
91     tty_set_flow (c->t, m->setflow.flow);
92     break;
93   case IPC_MSG_TYPE_SETANSI:
94     vt102_set_ansi (c->v, m->setansi.ansi);
95     break;
96   case IPC_MSG_TYPE_HANGUP:
97     tty_hangup (c->t);
98     break;
99   case IPC_MSG_TYPE_SETSIZE:
100     vt102_resize (c, m->setsize.winsize);
101     break;
102   case IPC_MSG_TYPE_RESET:
103     vt102_reset (c);
104     break;
105   default:
106     fprintf (stderr, "Unhandeled message type %d\n", m->hdr.type);
107   }
108 }
109
110 void
111 client_free (Client * c)
112 {
113   if (c->s)
114     socket_free (c->s);
115
116   free (c);
117 #if 0
118   fprintf (stderr, "Client at %p freed\n", c);
119 #endif
120 }
121
122 Client *
123 clients_new_client (Clients * cs, Socket * s, Context * ctx)
124 {
125   Client *c;
126
127   c = (Client *) malloc (sizeof (Client));
128
129   c->dead = 0;
130   c->s = s;
131   c->next = cs->head;
132
133   cs->head = c;
134   cs->n++;
135
136 #if 0
137   fprintf (stderr, "Client at %p created\n", c);
138 #endif
139
140
141   if (ipc_msg_send_debug (s, "new_client"))
142     c->dead++;
143
144   return c;
145 }
146
147 void
148 clients_reap (Clients * cs)
149 {
150   Client **p, *c;
151
152
153   for (p = &cs->head; *p;) {
154     Client *c = *p;
155
156     if (c->dead) {
157       *p = c->next;
158       client_free (c);
159       cs->n--;
160     } else {
161       p = &(c->next);
162     }
163   }
164 }
165
166 Clients *
167 clients_new (void)
168 {
169   Clients *ret = (Clients *) malloc (sizeof (Clients));
170
171   ret->n = 0;
172   ret->head = NULL;
173
174   return ret;
175 }
176
177 void
178 clients_pre_select (Clients * cs, fd_set * rfds, fd_set * wfds)
179 {
180   Client *c;
181
182   for (c = cs->head; c; c = c->next) {
183     socket_pre_select (c->s, rfds, wfds);
184   }
185 }
186
187 void
188 clients_post_select (Clients * cs, Context * ctx, fd_set * rfds,
189                      fd_set * wfds)
190 {
191   Client *c;
192   int deaded = 0;
193
194   for (c = cs->head; c; c = c->next) {
195     if (socket_post_select (c->s, rfds, wfds)) {
196       c->dead++;
197       deaded++;
198     }
199
200     if (c->s->msg) {
201       client_msg (c->s->msg, ctx);
202       socket_consume_msg (c->s);
203     }
204
205   }
206
207   if (deaded)
208     clients_reap (cs);
209 }
210
211
212 void
213 clients_shutdown (Clients * cs)
214 {
215   Client *c;
216
217   for (c = cs->head; c; c = c->next) {
218     c->dead++;
219   }
220
221
222   clients_reap (cs);
223 }
224
225
226
227
228
229
230 int
231 send_status (Clients * cs, char *msg)
232 {
233   char mbuf[IPC_MAX_BUF + sizeof (IPC_Msg_status)];
234   IPC_Msg_status *m = (IPC_Msg_status *) mbuf;
235   int len;
236
237   Client *c;
238
239   if (!msg)
240     return;
241   len = strlen (msg) + 1;
242
243   if (!len)
244     return;
245   if (len > IPC_MAX_BUF)
246     len = IPC_MAX_BUF;
247
248   m->size = len + sizeof (IPC_Msg_status);
249   m->type = IPC_MSG_TYPE_STATUS;
250   strncpy (m->status, msg, IPC_MAX_BUF);
251   m->status[IPC_MAX_BUF - 1] = 0;
252
253   for (c = cs->head; c; c = c->next) {
254     if (!c->dead)
255       if (ipc_msg_send (c->s, (IPC_Msg *) m))
256         c->dead++;
257   }
258
259   return len;
260 }
261
262
263 int
264 send_output (Clients * cs, void *buf, int len)
265 {
266   char mbuf[IPC_MAX_BUF + sizeof (IPC_Msg_term)];
267   IPC_Msg_term *m = (IPC_Msg_term *) mbuf;
268
269   Client *c;
270
271   if (!len)
272     return;
273   if (len > IPC_MAX_BUF)
274     len = IPC_MAX_BUF;
275
276   m->size = len + sizeof (IPC_Msg_term);
277   m->type = IPC_MSG_TYPE_TERM;
278   m->len = len;
279   memcpy (m->term, buf, len);
280
281   for (c = cs->head; c; c = c->next) {
282     if (!c->dead)
283       if (ipc_msg_send (c->s, (IPC_Msg *) m))
284         c->dead++;
285   }
286
287
288   return len;
289 }
290
291 void
292 send_history (History * h, Client * c)
293 {
294   int rptr = h->wptr;
295
296   HISTORY_INC (h, rptr);
297
298   HISTORY_INC (h, rptr);
299   while (rptr != h->wptr) {
300     History_ent *l = &h->lines[rptr];
301     if (l->valid) {
302
303       if (ipc_msg_send_history (c->s, l))
304         c->dead++;
305
306     }
307     HISTORY_INC (h, rptr);
308   }
309 }
310
311 void
312 send_vt102 (VT102 * v, Client * c)
313 {
314   if (ipc_msg_send_vt102 (c->s, v))
315     c->dead++;
316
317 }