vm: util.S not used currently; leave it out.
[minix.git] / servers / inet / qp.c
blobc6bc310ca701fa8f0762bd639e3dc2073b0ded7a
1 /*
2 inet/qp.c
4 Query parameters
6 Created: June 1995 by Philip Homburg <philip@f-mnx.phicoh.com>
7 */
9 #include "inet.h"
10 #include "generic/assert.h"
12 #include <sys/svrctl.h>
13 #include "queryparam.h"
15 #include "generic/buf.h"
16 #include "generic/clock.h"
17 #include "generic/event.h"
18 #include "generic/type.h"
19 #include "generic/sr.h"
21 #include "generic/tcp_int.h"
22 #include "generic/udp_int.h"
23 #include "mq.h"
24 #include "qp.h"
25 #include "sr_int.h"
27 THIS_FILE
29 #define MAX_REQ 1024 /* Maximum size of a request */
31 #define QP_FD_NR 4
33 typedef struct qp_fd
35 int qf_flags;
36 int qf_srfd;
37 get_userdata_t qf_get_userdata;
38 put_userdata_t qf_put_userdata;
39 acc_t *qf_req_pkt;
40 } qp_fd_t;
42 #define QFF_EMPTY 0
43 #define QFF_INUSE 1
45 PRIVATE qp_fd_t qp_fd_table[QP_FD_NR];
47 PRIVATE struct export_param_list inet_ex_list[]=
49 QP_VARIABLE(sr_fd_table),
50 QP_VARIABLE(ip_dev),
51 QP_VARIABLE(tcp_fd_table),
52 QP_VARIABLE(tcp_conn_table),
53 QP_VARIABLE(tcp_cancel_f),
54 QP_VECTOR(udp_port_table, udp_port_table, ip_conf_nr),
55 QP_VARIABLE(udp_fd_table),
56 QP_END()
59 PRIVATE struct export_params inet_ex_params= { inet_ex_list, NULL };
61 PRIVATE struct queryvars {
62 /* Input */
63 acc_t *param;
65 /* Output */
66 qp_fd_t *qp_fd;
67 off_t fd_offset;
68 size_t rd_bytes_left;
69 off_t outbuf_off;
70 char outbuf[256];
72 int r; /* result */
73 } *qvars;
76 FORWARD int qp_open ARGS(( int port, int srfd,
77 get_userdata_t get_userdata, put_userdata_t put_userdata,
78 put_pkt_t put_pkt, select_res_t select_res ));
79 FORWARD void qp_close ARGS(( int fd ));
80 FORWARD int qp_read ARGS(( int fd, size_t count ));
81 FORWARD int qp_write ARGS(( int fd, size_t count ));
82 FORWARD int qp_ioctl ARGS(( int fd, ioreq_t req ));
83 FORWARD int qp_cancel ARGS(( int fd, int which_operation ));
84 FORWARD int qp_select ARGS(( int fd, unsigned operations ));
85 FORWARD qp_fd_t *get_qp_fd ARGS(( int fd ));
86 FORWARD int do_query ARGS(( qp_fd_t *qp_fd, acc_t *pkt, int count ));
87 FORWARD int qp_getc ARGS(( void ));
88 FORWARD void qp_putc ARGS(( struct queryvars *qv, int c ));
89 FORWARD void qp_buffree ARGS(( int priority ));
90 #ifdef BUF_CONSISTENCY_CHECK
91 FORWARD void qp_bufcheck ARGS(( void ));
92 #endif
94 PUBLIC void qp_init()
96 int i;
98 qp_export(&inet_ex_params);
100 for (i= 0; i<QP_FD_NR; i++)
101 qp_fd_table[i].qf_flags= QFF_EMPTY;
103 #ifndef BUF_CONSISTENCY_CHECK
104 bf_logon(qp_buffree);
105 #else
106 bf_logon(qp_buffree, qp_bufcheck);
107 #endif
109 sr_add_minor(IPSTAT_MINOR, 0, qp_open, qp_close, qp_read, qp_write,
110 qp_ioctl, qp_cancel, qp_select);
113 PRIVATE int qp_open(port, srfd, get_userdata, put_userdata, put_pkt,
114 select_res)
115 int port;
116 int srfd;
117 get_userdata_t get_userdata;
118 put_userdata_t put_userdata;
119 put_pkt_t put_pkt;
120 select_res_t select_res;
122 int i;
123 qp_fd_t *qp_fd;
125 for (i= 0; i< QP_FD_NR; i++)
127 if (!(qp_fd_table[i].qf_flags & QFF_INUSE))
128 break;
130 if (i >= QP_FD_NR)
131 return EAGAIN;
132 qp_fd= &qp_fd_table[i];
133 qp_fd->qf_flags= QFF_INUSE;
134 qp_fd->qf_srfd= srfd;
135 qp_fd->qf_get_userdata= get_userdata;
136 qp_fd->qf_put_userdata= put_userdata;
137 qp_fd->qf_req_pkt= NULL;
139 return i;
142 PRIVATE void qp_close(fd)
143 int fd;
145 qp_fd_t *qp_fd;
147 qp_fd= get_qp_fd(fd);
148 qp_fd->qf_flags= QFF_EMPTY;
149 if (qp_fd->qf_req_pkt)
151 bf_afree(qp_fd->qf_req_pkt);
152 qp_fd->qf_req_pkt= NULL;
156 PRIVATE int qp_read(fd, count)
157 int fd;
158 size_t count;
160 int r;
161 acc_t *pkt;
162 qp_fd_t *qp_fd;
164 qp_fd= get_qp_fd(fd);
165 pkt= qp_fd->qf_req_pkt;
166 qp_fd->qf_req_pkt= NULL;
167 if (!pkt)
169 /* Nothing to do */
170 qp_fd->qf_put_userdata(qp_fd->qf_srfd, EIO, 0,
171 FALSE /* !for_ioctl*/);
172 return OK;
174 r= do_query(qp_fd, pkt, count);
175 qp_fd->qf_put_userdata(qp_fd->qf_srfd, r, 0,
176 FALSE /* !for_ioctl*/);
177 return OK;
180 PRIVATE int qp_write(fd, count)
181 int fd;
182 size_t count;
184 acc_t *pkt;
185 qp_fd_t *qp_fd;
187 qp_fd= get_qp_fd(fd);
188 if (count > MAX_REQ)
190 qp_fd->qf_get_userdata(qp_fd->qf_srfd, ENOMEM, 0,
191 FALSE /* !for_ioctl*/);
192 return OK;
194 pkt= qp_fd->qf_get_userdata(qp_fd->qf_srfd, 0, count,
195 FALSE /* !for_ioctl*/);
196 if (!pkt)
198 qp_fd->qf_get_userdata(qp_fd->qf_srfd, EFAULT, 0,
199 FALSE /* !for_ioctl*/);
200 return OK;
202 if (qp_fd->qf_req_pkt)
204 bf_afree(qp_fd->qf_req_pkt);
205 qp_fd->qf_req_pkt= NULL;
207 qp_fd->qf_req_pkt= pkt;
208 qp_fd->qf_get_userdata(qp_fd->qf_srfd, count, 0,
209 FALSE /* !for_ioctl*/);
210 return OK;
213 PRIVATE int qp_ioctl(fd, req)
214 int fd;
215 ioreq_t req;
217 qp_fd_t *qp_fd;
219 qp_fd= get_qp_fd(fd);
220 qp_fd->qf_get_userdata(qp_fd->qf_srfd, ENOTTY, 0,
221 TRUE /* for_ioctl*/);
222 return OK;
225 PRIVATE int qp_cancel(fd, which_operation)
226 int fd;
227 int which_operation;
229 ip_panic(( "qp_cancel: should not be here, no blocking calls" ));
232 PRIVATE int qp_select(fd, operations)
233 int fd;
234 unsigned operations;
236 unsigned resops;
238 resops= 0;
239 if (operations & SR_SELECT_READ)
240 resops |= SR_SELECT_READ;
241 if (operations & SR_SELECT_WRITE)
242 resops |= SR_SELECT_WRITE;
243 return resops;
246 PRIVATE qp_fd_t *get_qp_fd(fd)
247 int fd;
249 qp_fd_t *qp_fd;
251 assert(fd >= 0 && fd < QP_FD_NR);
252 qp_fd= &qp_fd_table[fd];
253 assert(qp_fd->qf_flags & QFF_INUSE);
254 return qp_fd;
257 PRIVATE int do_query(qp_fd, pkt, count)
258 qp_fd_t *qp_fd;
259 acc_t *pkt;
260 int count;
262 struct queryvars qv;
263 void *addr;
264 size_t n, size;
265 int byte;
266 int more;
267 static char hex[]= "0123456789ABCDEF";
269 qvars= &qv;
270 qv.param= pkt; pkt= NULL;
271 qv.qp_fd= qp_fd;
272 qv.fd_offset= 0;
273 qv.outbuf_off= 0;
274 qv.rd_bytes_left= count;
275 qv.r= 0;
277 do {
278 more= queryparam(qp_getc, &addr, &size);
279 for (n= 0; n < size; n++) {
280 byte= ((u8_t *) addr)[n];
281 qp_putc(&qv, hex[byte >> 4]);
282 qp_putc(&qv, hex[byte & 0x0F]);
284 qp_putc(&qv, more ? ',' : 0);
285 if (qv.r)
286 break;
287 } while (more);
288 if (qv.param)
290 assert(0);
291 bf_afree(qv.param);
292 qv.param= NULL;
294 if (qv.r)
295 return qv.r;
296 return qv.fd_offset;
299 PRIVATE int qp_getc()
301 /* Return one character of the names to search for. */
302 acc_t *pkt;
303 struct queryvars *qv= qvars;
304 u8_t c;
306 pkt= qv->param;
307 qv->param= NULL;
308 if (pkt == NULL)
309 return 0;
311 assert(bf_bufsize(pkt) > 0);
312 c= ptr2acc_data(pkt)[0];
313 if (bf_bufsize(pkt) > 1)
314 qv->param= bf_delhead(pkt, 1);
315 else
317 bf_afree(pkt);
318 qv->param= NULL;
321 return c;
324 PRIVATE void qp_putc(qv, c)
325 struct queryvars *qv;
326 int c;
328 /* Send one character back to the user. */
329 acc_t *pkt;
330 qp_fd_t *qp_fd;
331 size_t bytes_left;
332 off_t off;
334 bytes_left= qv->rd_bytes_left;
335 if (qv->r || bytes_left == 0)
336 return;
338 off= qv->outbuf_off;
339 assert(off < sizeof(qv->outbuf));
340 qv->outbuf[off]= c;
341 off++;
342 bytes_left--;
343 qv->rd_bytes_left= bytes_left;
344 if (c != '\0' && off < sizeof(qv->outbuf) && bytes_left != 0)
346 qv->outbuf_off= off;
347 return;
350 pkt= bf_memreq(off);
351 assert(pkt->acc_next == NULL);
352 memcpy(ptr2acc_data(pkt), qv->outbuf, off);
353 qp_fd= qv->qp_fd;
354 qv->r= qp_fd->qf_put_userdata(qp_fd->qf_srfd, qv->fd_offset,
355 pkt, FALSE /* !for_ioctl*/ );
356 qv->fd_offset += off;
357 qv->outbuf_off= 0;
360 PRIVATE void qp_buffree (priority)
361 int priority;
363 /* For the moment, we are not going to free anything */
366 #ifdef BUF_CONSISTENCY_CHECK
367 PRIVATE void qp_bufcheck()
369 int i;
370 qp_fd_t *qp_fd;
372 for (i= 0, qp_fd= qp_fd_table; i<QP_FD_NR; i++, qp_fd++)
374 if (!(qp_fd->qf_flags & QFF_INUSE))
375 continue;
376 if (qp_fd->qf_req_pkt)
377 bf_check_acc(qp_fd->qf_req_pkt);
380 #endif
383 * $PchId: qp.c,v 1.7 2005/06/28 14:25:25 philip Exp $