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