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