Subversion Repositories planix.SVN

Rev

Details | Last modification | View Log | RSS feed

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