]> git.lizzy.rs Git - plan9front.git/blob - sys/src/cmd/cwfs/srv.c
audiohda: fix syntax error
[plan9front.git] / sys / src / cmd / cwfs / srv.c
1 #include "all.h"
2 #include "io.h"
3 #include <fcall.h>              /* 9p2000 */
4 #include <thread.h>
5
6 enum {
7         Nqueue          = 100,          /* reply queue size per connection (tunable) */
8         Nchans          = 30,           /* maximum number of connections */
9 };
10
11 typedef struct Srv Srv;
12 struct Srv
13 {
14         Ref;
15         Chan    *chan;
16         int     fd;
17 };
18
19 static struct {
20         Lock;
21         Chan    *hd;
22 } freechans;
23
24 void
25 chanhangup(Chan *chan, char *msg)
26 {
27         char buf[128], *p;
28         Srv *srv;
29         int cfd;
30
31         fileinit(chan);
32         srv = chan->pdata;
33         if(chan == cons.chan || srv == nil || srv->chan != chan)
34                 return;
35         if(msg[0] && chatty)
36                 fprint(2, "hangup %s: %s\n", chan->whochan, msg);
37         if(fd2path(srv->fd, buf, sizeof(buf)) == 0){
38                 if(p = strrchr(buf, '/')){
39                         strecpy(p, buf+sizeof(buf), "/ctl");
40                         if((cfd = open(buf, OWRITE)) >= 0){
41                                 write(cfd, "hangup", 6);
42                                 close(cfd);
43                         }
44                 }
45         }
46 }
47
48 static void
49 srvput(Srv *srv)
50 {
51         Chan *chan;
52
53         if(decref(srv))
54                 return;
55
56         close(srv->fd);
57         srv->fd = -1;
58         chan = srv->chan;
59         fileinit(chan);
60         if(chatty)
61                 fprint(2, "%s closed\n", chan->whochan);
62         lock(&freechans);
63         srv->chan = freechans.hd;
64         freechans.hd = chan;
65         unlock(&freechans);
66 }
67
68 static void
69 srvo(void *aux)
70 {
71         Chan *chan;
72         Srv *srv;
73         Msgbuf *mb;
74         char buf[ERRMAX];
75
76         chan = aux;
77         for(;;){
78                 mb = fs_recv(chan->reply, 0);
79                 if(mb == nil)
80                         continue;
81                 if(mb->data == nil){
82                         if(!(mb->flags & FREE))
83                                 mbfree(mb);
84                         continue;
85                 }
86                 srv = chan->pdata;
87                 while(write(srv->fd, mb->data, mb->count) != mb->count){
88                         rerrstr(buf, sizeof(buf));
89                         if(strstr(buf, "interrupt"))
90                                 continue;
91                         chanhangup(chan, buf);
92                         break;
93                 }
94                 mbfree(mb);
95                 srvput(srv);
96         }
97 }
98
99 static void
100 srvi(void *aux)
101 {
102         Chan *chan;
103         Srv *srv;
104         Msgbuf *mb, *ms;
105         uchar *b, *p, *e;
106         int n, m;
107         char err[ERRMAX];
108
109         err[0] = 0;
110         chan = aux;
111         srv = chan->pdata;
112
113         if((mb = mballoc(IOHDRSZ+MAXDAT, chan, Mbeth1)) == nil)
114                 panic("srvi: mballoc failed");
115         b = mb->data;
116         p = b;
117         e = b + mb->count;
118
119 Read:
120         while((n = read(srv->fd, p, e - p)) > 0){
121                 p += n;
122                 while((p - b) >= BIT32SZ){
123                         m = GBIT32(b);
124                         if((m < BIT32SZ) || (m > mb->count)){
125                                 strcpy(err, "bad length in 9P2000 message header");
126                                 goto Hangup;
127                         }
128                         if((n = (p - b) - m) < 0){
129                                 e = b + m;
130                                 goto Read;
131                         }
132                         if(m <= SMALLBUF){
133                                 if((ms = mballoc(m, chan, Mbeth1)) == nil)
134                                         panic("srvi: mballoc failed");
135                                 memmove(ms->data, b, m);
136                         } else {
137                                 ms = mb;
138                                 if((mb = mballoc(mb->count, chan, Mbeth1)) == nil)
139                                         panic("srvi: mballoc failed");
140                                 ms->count = m;
141                         }
142                         if(n > 0)
143                                 memmove(mb->data, b + m, n);
144                         b = mb->data;
145                         p = b + n;
146
147                         incref(srv);
148                         fs_send(chan->send, ms);
149                 }
150                 e = b + mb->count;
151         }
152
153         if(n < 0)
154                 errstr(err, sizeof(err));
155
156 Hangup:
157         chanhangup(chan, err);
158         srvput(srv);
159
160         mbfree(mb);
161 }
162
163 Chan*
164 srvchan(int fd, char *name)
165 {
166         char buf[64];
167         Chan *chan;
168         Srv *srv;
169
170         lock(&freechans);
171         chan = freechans.hd;
172         if(chan == nil){
173                 unlock(&freechans);
174                 return nil;
175         }
176         srv = chan->pdata;
177         freechans.hd = srv->chan;
178         unlock(&freechans);
179
180         chan->protocol = nil;
181         chan->msize = 0;
182         chan->whotime = 0;
183         snprint(chan->whochan, sizeof(chan->whochan), "%s", name);
184         chan->authok = 0;
185
186         incref(srv);
187         srv->chan = chan;
188         srv->fd = fd;
189
190         if(chan->reply == nil){
191                 chan->reply = newqueue(Nqueue, "srvoq");
192                 newproc(srvo, chan, "srvo");
193         }
194
195         if(chan->send == nil)
196                 chan->send = serveq;
197         snprint(buf, sizeof(buf), "srvi %s", name);
198         newproc(srvi, chan, buf);
199
200         return chan;
201 }
202
203 void
204 srvinit(void)
205 {
206         Chan *chan;
207         Srv *srv;
208         int i;
209
210         if(freechans.hd != nil)
211                 return;
212         for(i=0; i<Nchans; i++){
213                 chan = fs_chaninit(1, sizeof(Srv));
214                 srv = chan->pdata;
215                 srv->fd = -1;
216                 srv->chan = freechans.hd;
217                 freechans.hd = chan;
218         }
219 }