xref: /plan9/sys/src/ape/lib/net/announce.c (revision 3e12c5d1bb89fc02707907988834ef147769ddaf)
1 #include <stdlib.h>
2 #include <sys/types.h>
3 #include <unistd.h>
4 #include <fcntl.h>
5 #include <stdio.h>
6 #include <string.h>
7 #include <ctype.h>
8 #include <libnet.h>
9 
10 #define NAMELEN 28
11 
12 static int	nettrans(char*, char*, int na, char*, int);
13 
14 /*
15  *  announce a network service.
16  */
17 int
announce(char * addr,char * dir)18 announce(char *addr, char *dir)
19 {
20 	int ctl, n, m;
21 	char buf[3*NAMELEN];
22 	char buf2[3*NAMELEN];
23 	char netdir[2*NAMELEN];
24 	char naddr[3*NAMELEN];
25 	char *cp;
26 
27 	/*
28 	 *  translate the address
29 	 */
30 	if(nettrans(addr, naddr, sizeof(naddr), netdir, sizeof(netdir)) < 0)
31 		return -1;
32 
33 	/*
34 	 * get a control channel
35 	 */
36 	ctl = open(netdir, O_RDWR);
37 	if(ctl<0)
38 		return -1;
39 	cp = strrchr(netdir, '/');
40 	*cp = 0;
41 
42 	/*
43 	 *  find out which line we have
44 	 */
45 	n = sprintf(buf, "%.*s/", 2*NAMELEN+1, netdir);
46 	m = read(ctl, &buf[n], sizeof(buf)-n-1);
47 	if(n<=0){
48 		close(ctl);
49 		return -1;
50 	}
51 	buf[n+m] = 0;
52 
53 	/*
54 	 *  make the call
55 	 */
56 	n = sprintf(buf2, "announce %.*s", 2*NAMELEN, naddr);
57 	if(write(ctl, buf2, n)!=n){
58 		close(ctl);
59 		return -1;
60 	}
61 
62 	/*
63 	 *  return directory etc.
64 	 */
65 	if(dir)
66 		strcpy(dir, buf);
67 	return ctl;
68 }
69 
70 /*
71  *  listen for an incoming call
72  */
73 int
listen(char * dir,char * newdir)74 listen(char *dir, char *newdir)
75 {
76 	int ctl, n, m;
77 	char buf[3*NAMELEN];
78 	char *cp;
79 
80 	/*
81 	 *  open listen, wait for a call
82 	 */
83 	sprintf(buf, "%.*s/listen", 2*NAMELEN+1, dir);
84 	ctl = open(buf, O_RDWR);
85 	if(ctl < 0)
86 		return -1;
87 
88 	/*
89 	 *  find out which line we have
90 	 */
91 	strcpy(buf, dir);
92 	cp = strrchr(buf, '/');
93 	*++cp = 0;
94 	n = cp-buf;
95 	m = read(ctl, cp, sizeof(buf) - n - 1);
96 	if(n<=0){
97 		close(ctl);
98 		return -1;
99 	}
100 	buf[n+m] = 0;
101 
102 	/*
103 	 *  return directory etc.
104 	 */
105 	if(newdir)
106 		strcpy(newdir, buf);
107 	return ctl;
108 
109 }
110 
111 /*
112  *  accept a call, return an fd to the open data file
113  */
114 int
accept(int ctl,char * dir)115 accept(int ctl, char *dir)
116 {
117 	char buf[128];
118 	char *num;
119 	long n;
120 
121 	num = strrchr(dir, '/');
122 	if(num == 0)
123 		num = dir;
124 	else
125 		num++;
126 
127 	sprintf(buf, "accept %s", num);
128 	n = strlen(buf);
129 	write(ctl, buf, n); /* ignore return value, netowrk might not need accepts */
130 
131 	sprintf(buf, "%s/data", dir);
132 	return open(buf, O_RDWR);
133 }
134 
135 /*
136  *  reject a call, tell device the reason for the rejection
137  */
138 int
reject(int ctl,char * dir,char * cause)139 reject(int ctl, char *dir, char *cause)
140 {
141 	char buf[128];
142 	char *num;
143 	long n;
144 
145 	num = strrchr(dir, '/');
146 	if(num == 0)
147 		num = dir;
148 	else
149 		num++;
150 	sprintf(buf, "reject %s %s", num, cause);
151 	n = strlen(buf);
152 	if(write(ctl, buf, n) != n)
153 		return -1;
154 	return 0;
155 }
156 
157 /*
158  *  perform the identity translation (in case we can't reach cs)
159  */
160 static int
identtrans(char * addr,char * naddr,int na,char * file,int nf)161 identtrans(char *addr, char *naddr, int na, char *file, int nf)
162 {
163 	char reply[4*NAMELEN];
164 	char *p;
165 
166 	USED(nf);
167 
168 	/* parse the network */
169 	strncpy(reply, addr, sizeof(reply));
170 	reply[sizeof(reply)-1] = 0;
171 	p = strchr(addr, '!');
172 	if(p)
173 		*p++ = 0;
174 
175 	sprintf(file, "/net/%.*s/clone", na - sizeof("/net//clone"), reply);
176 	strncpy(naddr, p, na);
177 	naddr[na-1] = 0;
178 
179 	return 1;
180 }
181 
182 /*
183  *  call up the connection server and get a translation
184  */
185 static int
nettrans(char * addr,char * naddr,int na,char * file,int nf)186 nettrans(char *addr, char *naddr, int na, char *file, int nf)
187 {
188 	int fd;
189 	char reply[4*NAMELEN];
190 	char *cp;
191 	long n;
192 
193 	/*
194 	 *  ask the connection server
195 	 */
196 	fd = open("/net/cs", O_RDWR);
197 	if(fd < 0)
198 		return identtrans(addr, naddr, na, file, nf);
199 	if(write(fd, addr, strlen(addr)) < 0){
200 		close(fd);
201 		return -1;
202 	}
203 	lseek(fd, 0, 0);
204 	n = read(fd, reply, sizeof(reply)-1);
205 	close(fd);
206 	if(n <= 0)
207 		return -1;
208 	reply[n] = 0;
209 
210 	/*
211 	 *  parse the reply
212 	 */
213 	cp = strchr(reply, ' ');
214 	if(cp == 0)
215 		return -1;
216 	*cp++ = 0;
217 	strncpy(naddr, cp, na);
218 	naddr[na-1] = 0;
219 	strncpy(file, reply, nf);
220 	file[nf-1] = 0;
221 	return 0;
222 }
223