xref: /plan9-contrib/sys/src/cmd/webfs/io.c (revision 9a747e4fd48b9f4522c70c07e8f882a15030f964)
1 #include <u.h>
2 #include <libc.h>
3 #include <bio.h>
4 #include <ip.h>
5 #include <plumb.h>
6 #include <thread.h>
7 #include <fcall.h>
8 #include <9p.h>
9 #include <mp.h>
10 #include <libsec.h>
11 #include "dat.h"
12 #include "fns.h"
13 
14 static int tlsdial(char*, char*, char*, int*, int);
15 
16 static long
17 t(Ioproc *io, void (*op)(Ioproc*), int n, ...)
18 {
19 	int i, ret;
20 	va_list arg;
21 
22 	assert(!io->inuse);
23 	io->inuse = 1;
24 	io->op = op;
25 	va_start(arg, n);
26 	for(i=0; i<n; i++)
27 		io->arg[i] = va_arg(arg, long);
28 	sendp(io->c, io);
29 	recvp(io->c);
30 	ret = io->ret;
31 	if(ret < 0)
32 		errstr(io->err, sizeof io->err);
33 	io->inuse = 0;
34 	return ret;
35 }
36 
37 static void
38 t2(Ioproc *io, int ret)
39 {
40 	io->ret = ret;
41 	if(ret < 0)
42 		rerrstr(io->err, sizeof io->err);
43 	sendp(io->c, io);
44 }
45 
46 static void ioread2(Ioproc*);
47 static long
48 ioread(Ioproc *io, int fd, void *a, long n)
49 {
50 	return t(io, ioread2, 3, fd, a, n);
51 }
52 static void
53 ioread2(Ioproc *io)
54 {
55 	t2(io, read(io->arg[0], (void*)io->arg[1], io->arg[2]));
56 }
57 
58 static void iowrite2(Ioproc*);
59 static long
60 iowrite(Ioproc *io, int fd, void *a, long n)
61 {
62 	return t(io, iowrite2, 3, fd, a, n);
63 }
64 static void
65 iowrite2(Ioproc *io)
66 {
67 	t2(io, write(io->arg[0], (void*)io->arg[1], io->arg[2]));
68 }
69 
70 static void ioclose2(Ioproc*);
71 static int
72 ioclose(Ioproc *io, int fd)
73 {
74 	return t(io, ioclose2, 1, fd);
75 }
76 static void
77 ioclose2(Ioproc *io)
78 {
79 	t2(io, close(io->arg[0]));
80 }
81 
82 static void iodial2(Ioproc*);
83 static int
84 iodial(Ioproc *io, char *a, char *b, char *c, int *d, int e)
85 {
86 	return t(io, iodial2, 5, a, b, c, d, e);
87 }
88 static void
89 iodial2(Ioproc *io)
90 {
91 	t2(io, tlsdial((char*)io->arg[0], (char*)io->arg[1], (char*)io->arg[2], (int*)io->arg[3], io->arg[4]));
92 }
93 
94 static void ioopen2(Ioproc*);
95 static int
96 ioopen(Ioproc *io, char *path, int mode)
97 {
98 	return t(io, ioopen2, 2, path, mode);
99 }
100 static void
101 ioopen2(Ioproc *io)
102 {
103 	t2(io, open((char*)io->arg[0], io->arg[1]));
104 }
105 
106 static int
107 ioprint(Ioproc *io, int fd, char *fmt, ...)
108 {
109 	char buf[1024];
110 	va_list arg;
111 
112 	va_start(arg, fmt);
113 	vseprint(buf, buf+sizeof buf, fmt, arg);
114 	va_end(arg);
115 	return iowrite(io, fd, buf, strlen(buf));
116 }
117 
118 static void
119 iointerrupt(Ioproc *io)
120 {
121 	if(!io->inuse)
122 		return;
123 	postnote(PNPROC, io->pid, "interrupt");
124 }
125 
126 static void
127 xioproc(void *a)
128 {
129 	Ioproc *io;
130 
131 	io = a;
132 	io->pid = getpid();
133 	sendp(io->c, nil);
134 	while(recvp(io->c) == io)
135 		io->op(io);
136 	chanfree(io->c);
137 	free(io);
138 }
139 
140 static int
141 tlsdial(char *a, char *b, char *c, int *d, int usetls)
142 {
143 	int fd, tfd;
144 	TLSconn conn;
145 
146 	fd = dial(a, b, c, d);
147 	if(fd < 0)
148 		return -1;
149 	if(usetls == 0)
150 		return fd;
151 
152 	memset(&conn, 0, sizeof conn);
153 	tfd = tlsClient(fd, &conn);
154 	if(tfd < 0){
155 		print("tls %r\n");
156 		close(fd);
157 		return -1;
158 	}
159 	/* BUG: check cert here? */
160 	if(conn.cert)
161 		free(conn.cert);
162 	close(fd);
163 	return tfd;
164 }
165 
166 Ioproc iofns =
167 {
168 	ioread,
169 	iowrite,
170 	iodial,
171 	ioclose,
172 	ioopen,
173 	ioprint,
174 	iointerrupt,
175 };
176 
177 Ioproc *iofree;
178 
179 Ioproc*
180 ioproc(void)
181 {
182 	Ioproc *io;
183 
184 	if((io = iofree) != nil){
185 		iofree = io->next;
186 		return io;
187 	}
188 	io = emalloc(sizeof(*io));
189 	*io = iofns;
190 	io->c = chancreate(sizeof(void*), 0);
191 	if(proccreate(xioproc, io, STACK) < 0)
192 		sysfatal("proccreate: %r");
193 	recvp(io->c);
194 	return io;
195 }
196 
197 void
198 closeioproc(Ioproc *io)
199 {
200 	io->next = iofree;
201 	iofree = io;
202 }
203 
204