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