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