Modernize 9ns networking function declarations
[akaros.git] / user / iplib / announce.c
1 /* 
2  * This file is part of the UCB release of Plan 9. It is subject to the license
3  * terms in the LICENSE file found in the top-level directory of this
4  * distribution and at http://akaros.cs.berkeley.edu/files/Plan9License. No
5  * part of the UCB release of Plan 9, including this file, may be copied,
6  * modified, propagated, or distributed except according to the terms contained
7  * in the LICENSE file.
8  */
9 #include <stdlib.h>
10
11 #include <stdio.h>
12 #include <fcntl.h>
13 #include <parlib/parlib.h>
14 #include <unistd.h>
15 #include <signal.h>
16 #include <iplib/iplib.h>
17
18 static int      nettrans(char*, char*, int na, char*, int);
19
20 enum
21 {
22         Maxpath=        256,
23 };
24
25 /*
26  *  announce a network service.
27  */
28 int announce9(char *addr, char *dir, int flags)
29 {
30         int ctl, n, m;
31         char buf[Maxpath];
32         char buf2[Maxpath];
33         char netdir[Maxpath];
34         char naddr[Maxpath];
35         char *cp;
36
37         /*
38          *  translate the address
39          */
40         if(nettrans(addr, naddr, sizeof(naddr), netdir, sizeof(netdir)) < 0)
41                 return -1;
42
43         /*
44          * get a control channel
45          */
46         ctl = open(netdir, O_RDWR);
47         if(ctl<0){
48                 fprintf(stderr,"announce opening %s: %r\n", netdir);
49                 return -1;
50         }
51         cp = strrchr(netdir, '/');
52         if(cp == NULL){
53                 fprintf(stderr,"announce arg format %s\n", netdir);
54                 close(ctl);
55                 return -1;
56         }
57         *cp = 0;
58
59         /*
60          *  find out which line we have
61          */
62         n = snprintf(buf, sizeof(buf), "%s/", netdir);
63         m = read(ctl, &buf[n], sizeof(buf)-n-1);
64         if(m <= 0){
65                 fprintf(stderr,"announce reading %s: %r\n", netdir);
66                 close(ctl);
67                 return -1;
68         }
69         buf[n+m] = 0;
70
71         /*
72          *  make the call
73          */
74         n = snprintf(buf2, sizeof(buf2), "announce %s", naddr);
75         if(write(ctl, buf2, n)!=n){
76                 fprintf(stderr,"announce writing %s: %r\n", netdir);
77                 close(ctl);
78                 return -1;
79         }
80
81         /*
82          *  return directory etc.
83          */
84         if(dir){
85                 strncpy(dir, buf, NETPATHLEN);
86                 dir[NETPATHLEN-1] = 0;
87         }
88         return ctl;
89 }
90
91 /*
92  *  listen for an incoming call
93  */
94 int listen9(char *dir, char *newdir, int flags)
95 {
96         int ctl, n, m;
97         char buf[Maxpath];
98         char *cp;
99
100         /*
101          *  open listen, wait for a call
102          */
103         snprintf(buf, sizeof(buf), "%s/listen", dir);
104         ctl = open(buf, O_RDWR);
105         if(ctl < 0){
106                 if ((errno != EAGAIN) && (errno != EWOULDBLOCK))
107                         fprintf(stderr,"listen opening %s: %r\n", buf);
108                 return -1;
109         }
110
111         /*
112          *  find out which line we have
113          */
114         strncpy(buf, dir, sizeof(buf) - 1);
115         buf[sizeof(buf) - 1] = 0;
116         cp = strrchr(buf, '/');
117         if(cp == NULL){
118                 close(ctl);
119                 fprintf(stderr,"listen arg format %s\n", dir);
120                 return -1;
121         }
122         *++cp = 0;
123         n = cp-buf;
124         m = read(ctl, cp, sizeof(buf) - n - 1);
125         if(m <= 0){
126                 close(ctl);
127                 fprintf(stderr,"listen reading %s/listen: %r\n", dir);
128                 return -1;
129         }
130         buf[n+m] = 0;
131
132         /*
133          *  return directory etc.
134          */
135         if(newdir){
136                 strncpy(newdir, buf, NETPATHLEN);
137                 newdir[NETPATHLEN-1] = 0;
138         }
139         return ctl;
140
141 }
142
143 /*
144  *  accept a call, return an fd to the open data file
145  */
146 int accept9(int ctl, char *dir)
147 {
148         char buf[Maxpath];
149         char *num;
150         long n;
151
152         num = strrchr(dir, '/');
153         if(num == NULL)
154                 num = dir;
155         else
156                 num++;
157
158         n = snprintf(buf, sizeof(buf), "accept %s", num);
159         write(ctl, buf, n); /* ignore return value, network might not need accepts */
160
161         snprintf(buf, sizeof(buf), "%s/data", dir);
162         return open(buf, O_RDWR);
163 }
164
165 /*
166  *  reject a call, tell device the reason for the rejection
167  */
168 int reject9(int ctl, char *dir, char *cause)
169 {
170         char buf[Maxpath];
171         char *num;
172         long n;
173
174         num = strrchr(dir, '/');
175         if(num == 0)
176                 num = dir;
177         else
178                 num++;
179         snprintf(buf, sizeof(buf), "reject %s %s", num, cause);
180         n = strlen(buf);
181         if(write(ctl, buf, n) != n)
182                 return -1;
183         return 0;
184 }
185
186 /*
187  *  perform the identity translation (in case we can't reach cs)
188  */
189 static int
190 identtrans(char *netdir, char *addr, char *naddr, int na, char *file, int nf)
191 {
192         char proto[Maxpath];
193         char *p;
194
195         /* parse the protocol */
196         strncpy(proto, addr, sizeof(proto));
197         proto[sizeof(proto)-1] = 0;
198         p = strchr(proto, '!');
199         if(p)
200                 *p++ = 0;
201
202         snprintf(file, nf, "%s/%s/clone", netdir, proto);
203         strncpy(naddr, p, na);
204         naddr[na-1] = 0;
205
206         return 1;
207 }
208
209 /*
210  *  call up the connection server and get a translation
211  */
212 static int
213 nettrans(char *addr, char *naddr, int na, char *file, int nf)
214 {
215         int i, fd;
216         char buf[Maxpath];
217         char netdir[Maxpath];
218         char *p, *p2;
219         long n;
220
221         /*
222          *  parse, get network directory
223          */
224         p = strchr(addr, '!');
225         if(p == 0){
226                 fprintf(stderr,"bad dial string: %s\n", addr);
227                 return -1;
228         }
229         if(*addr != '/'){
230                 strncpy(netdir, "/net", sizeof(netdir));
231                 netdir[sizeof(netdir) - 1] = 0;
232         } else {
233                 for(p2 = p; *p2 != '/'; p2--)
234                         ;
235                 i = p2 - addr;
236                 if(i == 0 || i >= sizeof(netdir)){
237                         fprintf(stderr,"bad dial string: %s\n", addr);
238                         return -1;
239                 }
240                 strncpy(netdir, addr, i);
241                 netdir[i] = 0;
242                 addr = p2 + 1;
243         }
244
245         /*
246          *  ask the connection server
247          */
248         snprintf(buf, sizeof(buf), "%s/cs", netdir);
249         fd = open(buf, O_RDWR);
250         if(fd < 0)
251                 return identtrans(netdir, addr, naddr, na, file, nf);
252         if(write(fd, addr, strlen(addr)) < 0){
253                 close(fd);
254                 return -1;
255         }
256         lseek(fd, 0, 0);
257         n = read(fd, buf, sizeof(buf)-1);
258         close(fd);
259         if(n <= 0)
260                 return -1;
261         buf[n] = 0;
262
263         /*
264          *  parse the reply
265          */
266         p = strchr(buf, ' ');
267         if(p == 0)
268                 return -1;
269         *p++ = 0;
270         strncpy(naddr, p, na);
271         naddr[na-1] = 0;
272
273         if(buf[0] == '/'){
274                 p = strchr(buf+1, '/');
275                 if(p == NULL)
276                         p = buf;
277                 else 
278                         p++;
279         }
280         snprintf(file, nf, "%s/%s", netdir, p);
281         return 0;
282 }