1*aa693e99SJason King /*
2*aa693e99SJason King * Copyright 2016 Jakub Klama <jceel@FreeBSD.org>
3*aa693e99SJason King * All rights reserved
4*aa693e99SJason King *
5*aa693e99SJason King * Redistribution and use in source and binary forms, with or without
6*aa693e99SJason King * modification, are permitted providing that the following conditions
7*aa693e99SJason King * are met:
8*aa693e99SJason King * 1. Redistributions of source code must retain the above copyright
9*aa693e99SJason King * notice, this list of conditions and the following disclaimer.
10*aa693e99SJason King * 2. Redistributions in binary form must reproduce the above copyright
11*aa693e99SJason King * notice, this list of conditions and the following disclaimer in the
12*aa693e99SJason King * documentation and/or other materials provided with the distribution.
13*aa693e99SJason King *
14*aa693e99SJason King * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
15*aa693e99SJason King * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
16*aa693e99SJason King * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17*aa693e99SJason King * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
18*aa693e99SJason King * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19*aa693e99SJason King * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20*aa693e99SJason King * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21*aa693e99SJason King * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
22*aa693e99SJason King * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
23*aa693e99SJason King * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
24*aa693e99SJason King * POSSIBILITY OF SUCH DAMAGE.
25*aa693e99SJason King *
26*aa693e99SJason King * Copyright 2021 Joyent, Inc.
27*aa693e99SJason King */
28*aa693e99SJason King
29*aa693e99SJason King #include <stdlib.h>
30*aa693e99SJason King #include <errno.h>
31*aa693e99SJason King #include <string.h>
32*aa693e99SJason King #include <unistd.h>
33*aa693e99SJason King #include <pthread.h>
34*aa693e99SJason King #include <assert.h>
35*aa693e99SJason King #include <sys/types.h>
36*aa693e99SJason King #ifdef __APPLE__
37*aa693e99SJason King # include "../apple_endian.h"
38*aa693e99SJason King #elif __illumos__
39*aa693e99SJason King # include <sys/param.h>
40*aa693e99SJason King # include <port.h>
41*aa693e99SJason King # include "../illumos_endian.h"
42*aa693e99SJason King #else
43*aa693e99SJason King # include <sys/endian.h>
44*aa693e99SJason King #endif
45*aa693e99SJason King #include <sys/socket.h>
46*aa693e99SJason King #ifndef __illumos__
47*aa693e99SJason King # include <sys/event.h>
48*aa693e99SJason King #endif
49*aa693e99SJason King #include <sys/uio.h>
50*aa693e99SJason King #include <netdb.h>
51*aa693e99SJason King #include "../lib9p.h"
52*aa693e99SJason King #include "../lib9p_impl.h"
53*aa693e99SJason King #include "../log.h"
54*aa693e99SJason King #include "socket.h"
55*aa693e99SJason King
56*aa693e99SJason King struct l9p_socket_softc
57*aa693e99SJason King {
58*aa693e99SJason King struct l9p_connection *ls_conn;
59*aa693e99SJason King struct sockaddr ls_sockaddr;
60*aa693e99SJason King socklen_t ls_socklen;
61*aa693e99SJason King pthread_t ls_thread;
62*aa693e99SJason King int ls_fd;
63*aa693e99SJason King };
64*aa693e99SJason King
65*aa693e99SJason King #ifdef __FreeBSD__
66*aa693e99SJason King struct event_svr {
67*aa693e99SJason King struct kevent *ev_kev;
68*aa693e99SJason King struct kevent *ev_event;
69*aa693e99SJason King int ev_kq;
70*aa693e99SJason King };
71*aa693e99SJason King #elif __illumos__
72*aa693e99SJason King struct event_svr {
73*aa693e99SJason King port_event_t *ev_pe;
74*aa693e99SJason King int ev_port;
75*aa693e99SJason King };
76*aa693e99SJason King #else
77*aa693e99SJason King #error "No event server defined"
78*aa693e99SJason King #endif
79*aa693e99SJason King
80*aa693e99SJason King static int l9p_init_event_svr(struct event_svr *, uint_t);
81*aa693e99SJason King static uint_t l9p_get_server_addrs(const char *, const char *,
82*aa693e99SJason King struct addrinfo **);
83*aa693e99SJason King static uint_t l9p_bind_addrs(struct event_svr *, struct addrinfo *, uint_t,
84*aa693e99SJason King int **);
85*aa693e99SJason King static int l9p_event_get(struct l9p_server *, struct event_svr *, uint_t,
86*aa693e99SJason King void (*cb)(struct l9p_server *, int));
87*aa693e99SJason King static int l9p_socket_readmsg(struct l9p_socket_softc *, void **, size_t *);
88*aa693e99SJason King static int l9p_socket_get_response_buffer(struct l9p_request *,
89*aa693e99SJason King struct iovec *, size_t *, void *);
90*aa693e99SJason King static int l9p_socket_send_response(struct l9p_request *, const struct iovec *,
91*aa693e99SJason King const size_t, const size_t, void *);
92*aa693e99SJason King static void l9p_socket_drop_response(struct l9p_request *, const struct iovec *,
93*aa693e99SJason King size_t, void *);
94*aa693e99SJason King static void *l9p_socket_thread(void *);
95*aa693e99SJason King static ssize_t xread(int, void *, size_t);
96*aa693e99SJason King static ssize_t xwrite(int, void *, size_t);
97*aa693e99SJason King
98*aa693e99SJason King int
l9p_start_server(struct l9p_server * server,const char * host,const char * port)99*aa693e99SJason King l9p_start_server(struct l9p_server *server, const char *host, const char *port)
100*aa693e99SJason King {
101*aa693e99SJason King struct addrinfo *res = NULL;
102*aa693e99SJason King int *sockets = NULL;
103*aa693e99SJason King uint_t naddrs = 0;
104*aa693e99SJason King uint_t nsockets = 0;
105*aa693e99SJason King uint_t i;
106*aa693e99SJason King struct event_svr esvr;
107*aa693e99SJason King
108*aa693e99SJason King naddrs = l9p_get_server_addrs(host, port, &res);
109*aa693e99SJason King if (naddrs == 0)
110*aa693e99SJason King return (-1);
111*aa693e99SJason King
112*aa693e99SJason King if (l9p_init_event_svr(&esvr, naddrs) != 0) {
113*aa693e99SJason King freeaddrinfo(res);
114*aa693e99SJason King return (-1);
115*aa693e99SJason King }
116*aa693e99SJason King
117*aa693e99SJason King nsockets = l9p_bind_addrs(&esvr, res, naddrs, &sockets);
118*aa693e99SJason King
119*aa693e99SJason King /*
120*aa693e99SJason King * We don't need res, after this, so free it and NULL it to prevent
121*aa693e99SJason King * any possible use after free.
122*aa693e99SJason King */
123*aa693e99SJason King freeaddrinfo(res);
124*aa693e99SJason King res = NULL;
125*aa693e99SJason King
126*aa693e99SJason King if (nsockets == 0)
127*aa693e99SJason King goto fail;
128*aa693e99SJason King
129*aa693e99SJason King for (;;) {
130*aa693e99SJason King if (l9p_event_get(server, &esvr, nsockets,
131*aa693e99SJason King l9p_socket_accept) < 0)
132*aa693e99SJason King break;
133*aa693e99SJason King }
134*aa693e99SJason King
135*aa693e99SJason King /* We get here if something failed */
136*aa693e99SJason King for (i = 0; i < nsockets; i++)
137*aa693e99SJason King close(sockets[i]);
138*aa693e99SJason King
139*aa693e99SJason King fail:
140*aa693e99SJason King free(sockets);
141*aa693e99SJason King
142*aa693e99SJason King #ifdef __FreeBSD__
143*aa693e99SJason King close(esvr.ev_kq);
144*aa693e99SJason King free(esvr.ev_kev);
145*aa693e99SJason King free(esvr.ev_event);
146*aa693e99SJason King #elif __illumos__
147*aa693e99SJason King close(esvr.ev_port);
148*aa693e99SJason King free(esvr.ev_pe);
149*aa693e99SJason King #else
150*aa693e99SJason King #error "Port me"
151*aa693e99SJason King #endif
152*aa693e99SJason King
153*aa693e99SJason King return (-1);
154*aa693e99SJason King }
155*aa693e99SJason King
156*aa693e99SJason King static uint_t
l9p_get_server_addrs(const char * host,const char * port,struct addrinfo ** resp)157*aa693e99SJason King l9p_get_server_addrs(const char *host, const char *port, struct addrinfo **resp)
158*aa693e99SJason King {
159*aa693e99SJason King struct addrinfo *res, hints;
160*aa693e99SJason King uint_t naddrs;
161*aa693e99SJason King int rc;
162*aa693e99SJason King
163*aa693e99SJason King memset(&hints, 0, sizeof(hints));
164*aa693e99SJason King hints.ai_family = PF_UNSPEC;
165*aa693e99SJason King hints.ai_socktype = SOCK_STREAM;
166*aa693e99SJason King rc = getaddrinfo(host, port, &hints, resp);
167*aa693e99SJason King if (rc > 0) {
168*aa693e99SJason King L9P_LOG(L9P_ERROR, "getaddrinfo(): %s", gai_strerror(rc));
169*aa693e99SJason King return (0);
170*aa693e99SJason King }
171*aa693e99SJason King
172*aa693e99SJason King naddrs = 0;
173*aa693e99SJason King for (res = *resp; res != NULL; res = res->ai_next)
174*aa693e99SJason King naddrs++;
175*aa693e99SJason King
176*aa693e99SJason King if (naddrs == 0) {
177*aa693e99SJason King L9P_LOG(L9P_ERROR, "no addresses found for %s:%s", host, port);
178*aa693e99SJason King }
179*aa693e99SJason King
180*aa693e99SJason King return (naddrs);
181*aa693e99SJason King }
182*aa693e99SJason King
183*aa693e99SJason King #ifdef __FreeBSD__
184*aa693e99SJason King static int
l9p_init_event_svr(struct event_svr * svr,uint_t nsockets)185*aa693e99SJason King l9p_init_event_svr(struct event_svr *svr, uint_t nsockets)
186*aa693e99SJason King {
187*aa693e99SJason King svr->ev_kev = calloc(nsockets, sizeof(struct kevent));
188*aa693e99SJason King if (svr->ev_kev == NULL) {
189*aa693e99SJason King L9P_LOG(L9P_ERROR, "calloc(): %s", strerror(errno));
190*aa693e99SJason King return (-1);
191*aa693e99SJason King }
192*aa693e99SJason King
193*aa693e99SJason King svr->ev_event = calloc(nsockets, sizeof(struct kevent));
194*aa693e99SJason King if (svr->ev_event == NULL) {
195*aa693e99SJason King L9P_LOG(L9P_ERROR, "calloc(): %s", strerror(errno));
196*aa693e99SJason King free(svr->ev_key);
197*aa693e99SJason King svr->ev_key = NULL;
198*aa693e99SJason King return (-1);
199*aa693e99SJason King }
200*aa693e99SJason King
201*aa693e99SJason King svr->ev_kq = kqueue();
202*aa693e99SJason King if (svr->ev_kq == -1) {
203*aa693e99SJason King L9P_LOG(L9P_ERROR, "kqueue(): %s", strerror(errno));
204*aa693e99SJason King free(svr->ev_kev);
205*aa693e99SJason King free(svr->ev_event);
206*aa693e99SJason King svr->ev_kev = NULL;
207*aa693e99SJason King svr->ev_event = NULL;
208*aa693e99SJason King return (-1);
209*aa693e99SJason King }
210*aa693e99SJason King
211*aa693e99SJason King return (0);
212*aa693e99SJason King }
213*aa693e99SJason King #elif __illumos__
214*aa693e99SJason King static int
l9p_init_event_svr(struct event_svr * svr,uint_t nsockets)215*aa693e99SJason King l9p_init_event_svr(struct event_svr *svr, uint_t nsockets)
216*aa693e99SJason King {
217*aa693e99SJason King svr->ev_pe = calloc(nsockets, sizeof(port_event_t));
218*aa693e99SJason King if (svr->ev_pe == NULL) {
219*aa693e99SJason King L9P_LOG(L9P_ERROR, "calloc(): %s", strerror(errno));
220*aa693e99SJason King return (-1);
221*aa693e99SJason King }
222*aa693e99SJason King
223*aa693e99SJason King svr->ev_port = port_create();
224*aa693e99SJason King if (svr->ev_port == -1) {
225*aa693e99SJason King L9P_LOG(L9P_ERROR, "port_create(): %s", strerror(errno));
226*aa693e99SJason King return (-1);
227*aa693e99SJason King }
228*aa693e99SJason King
229*aa693e99SJason King return (0);
230*aa693e99SJason King }
231*aa693e99SJason King #else
232*aa693e99SJason King #error "No event server defined"
233*aa693e99SJason King #endif
234*aa693e99SJason King
235*aa693e99SJason King static uint_t
l9p_bind_addrs(struct event_svr * svr,struct addrinfo * addrs,uint_t naddrs,int ** socketsp)236*aa693e99SJason King l9p_bind_addrs(struct event_svr *svr, struct addrinfo *addrs, uint_t naddrs,
237*aa693e99SJason King int **socketsp)
238*aa693e99SJason King {
239*aa693e99SJason King struct addrinfo *addr;
240*aa693e99SJason King uint_t i, j;
241*aa693e99SJason King
242*aa693e99SJason King *socketsp = calloc(naddrs, sizeof(int));
243*aa693e99SJason King if (*socketsp == NULL) {
244*aa693e99SJason King L9P_LOG(L9P_ERROR, "calloc(): %s", strerror(errno));
245*aa693e99SJason King return (0);
246*aa693e99SJason King }
247*aa693e99SJason King
248*aa693e99SJason King for (i = 0, addr = addrs; addr != NULL; addr = addr->ai_next) {
249*aa693e99SJason King int s;
250*aa693e99SJason King int val = 1;
251*aa693e99SJason King
252*aa693e99SJason King s = socket(addr->ai_family, addr->ai_socktype,
253*aa693e99SJason King addr->ai_protocol);
254*aa693e99SJason King if (s == -1) {
255*aa693e99SJason King L9P_LOG(L9P_ERROR, "socket(): %s", strerror(errno));
256*aa693e99SJason King continue;
257*aa693e99SJason King }
258*aa693e99SJason King
259*aa693e99SJason King if (setsockopt(s, SOL_SOCKET, SO_REUSEADDR, &val,
260*aa693e99SJason King sizeof(val)) < 0) {
261*aa693e99SJason King L9P_LOG(L9P_ERROR, "setsockopt(): %s", strerror(errno));
262*aa693e99SJason King close(s);
263*aa693e99SJason King continue;
264*aa693e99SJason King }
265*aa693e99SJason King
266*aa693e99SJason King if (bind(s, addr->ai_addr, addr->ai_addrlen) < 0) {
267*aa693e99SJason King L9P_LOG(L9P_ERROR, "bind(): %s", strerror(errno));
268*aa693e99SJason King close(s);
269*aa693e99SJason King continue;
270*aa693e99SJason King }
271*aa693e99SJason King
272*aa693e99SJason King if (listen(s, 10) < 0) {
273*aa693e99SJason King L9P_LOG(L9P_ERROR, "listen(): %s", strerror(errno));
274*aa693e99SJason King close(s);
275*aa693e99SJason King continue;
276*aa693e99SJason King }
277*aa693e99SJason King
278*aa693e99SJason King #ifdef __FreeBSD__
279*aa693e99SJason King EV_SET(&svr->ev_kev[i], s, EVFILT_READ, EV_ADD | EV_ENABLE, 0,
280*aa693e99SJason King 0, 0);
281*aa693e99SJason King #elif __illumos__
282*aa693e99SJason King if (port_associate(svr->ev_port, PORT_SOURCE_FD, s,
283*aa693e99SJason King POLLIN|POLLHUP, NULL) < 0) {
284*aa693e99SJason King L9P_LOG(L9P_ERROR, "port_associate(%d): %s", s,
285*aa693e99SJason King strerror(errno));
286*aa693e99SJason King close(s);
287*aa693e99SJason King continue;
288*aa693e99SJason King }
289*aa693e99SJason King #else
290*aa693e99SJason King #error "Port me"
291*aa693e99SJason King #endif
292*aa693e99SJason King
293*aa693e99SJason King *socketsp[i++] = s;
294*aa693e99SJason King }
295*aa693e99SJason King
296*aa693e99SJason King if (i < 1) {
297*aa693e99SJason King free(*socketsp);
298*aa693e99SJason King *socketsp = NULL;
299*aa693e99SJason King return (0);
300*aa693e99SJason King }
301*aa693e99SJason King
302*aa693e99SJason King for (j = i; j < naddrs; j++)
303*aa693e99SJason King *socketsp[j++] = -1;
304*aa693e99SJason King
305*aa693e99SJason King #ifdef __FreeBSD__
306*aa693e99SJason King if (kevent(svr->ev_kq, svr->ev_kev, i, NULL, 0, NULL) < 0) {
307*aa693e99SJason King L9P_LOG(L9P_ERROR, "kevent(): %s", strerror(errno));
308*aa693e99SJason King
309*aa693e99SJason King for (j = 0; j < i; j++)
310*aa693e99SJason King close(j);
311*aa693e99SJason King
312*aa693e99SJason King free(*socketsp);
313*aa693e99SJason King *socketsp = NULL;
314*aa693e99SJason King
315*aa693e99SJason King return (0);
316*aa693e99SJason King }
317*aa693e99SJason King #endif
318*aa693e99SJason King
319*aa693e99SJason King return (i);
320*aa693e99SJason King }
321*aa693e99SJason King
322*aa693e99SJason King #ifdef __FreeBSD__
323*aa693e99SJason King static int
l9p_event_get(struct l9p_server * l9svr,struct event_svr * esvr,uint_t nsockets,void (* cb)(struct l9p_server *,int))324*aa693e99SJason King l9p_event_get(struct l9p_server *l9svr, struct event_svr *esvr, uint_t nsockets,
325*aa693e99SJason King void (*cb)(struct l9p_server *, int))
326*aa693e99SJason King {
327*aa693e99SJason King int i, evs;
328*aa693e99SJason King
329*aa693e99SJason King evs = kevent(esvr->ev_kq, NULL, 0, esvr->ev_event, nsockets, NULL);
330*aa693e99SJason King if (evs < 0) {
331*aa693e99SJason King if (errno == EINTR)
332*aa693e99SJason King return (0);
333*aa693e99SJason King L9P_LOG(L9P_ERROR, "kevent(): %s", strerror(errno));
334*aa693e99SJason King return (-1);
335*aa693e99SJason King }
336*aa693e99SJason King
337*aa693e99SJason King for (i = 0; i < evs; i++)
338*aa693e99SJason King cb(l9svr, (int)sevr->ev_event[i].ident);
339*aa693e99SJason King
340*aa693e99SJason King return (0);
341*aa693e99SJason King }
342*aa693e99SJason King #elif __illumos__
343*aa693e99SJason King static int
l9p_event_get(struct l9p_server * l9svr,struct event_svr * esvr,uint_t nsockets,void (* cb)(struct l9p_server *,int))344*aa693e99SJason King l9p_event_get(struct l9p_server *l9svr, struct event_svr *esvr, uint_t nsockets,
345*aa693e99SJason King void (*cb)(struct l9p_server *, int))
346*aa693e99SJason King {
347*aa693e99SJason King uint_t evs = 1;
348*aa693e99SJason King int i;
349*aa693e99SJason King
350*aa693e99SJason King if (port_getn(esvr->ev_port, esvr->ev_pe, nsockets, &evs, NULL) < 0) {
351*aa693e99SJason King if (errno == EINTR)
352*aa693e99SJason King return (0);
353*aa693e99SJason King L9P_LOG(L9P_ERROR, "port_getn(): %s", strerror(errno));
354*aa693e99SJason King return (-1);
355*aa693e99SJason King }
356*aa693e99SJason King
357*aa693e99SJason King for (i = 0; i < evs; i++) {
358*aa693e99SJason King if (esvr->ev_pe[i].portev_source != PORT_SOURCE_FD)
359*aa693e99SJason King continue;
360*aa693e99SJason King
361*aa693e99SJason King cb(l9svr, (int)esvr->ev_pe[i].portev_object);
362*aa693e99SJason King }
363*aa693e99SJason King
364*aa693e99SJason King return (0);
365*aa693e99SJason King }
366*aa693e99SJason King #else
367*aa693e99SJason King #error "Port me"
368*aa693e99SJason King #endif
369*aa693e99SJason King
370*aa693e99SJason King void
l9p_socket_accept(struct l9p_server * server,int svr_fd)371*aa693e99SJason King l9p_socket_accept(struct l9p_server *server, int svr_fd)
372*aa693e99SJason King {
373*aa693e99SJason King struct l9p_socket_softc *sc;
374*aa693e99SJason King struct l9p_connection *conn;
375*aa693e99SJason King char host[NI_MAXHOST + 1];
376*aa693e99SJason King char serv[NI_MAXSERV + 1];
377*aa693e99SJason King struct sockaddr client_addr;
378*aa693e99SJason King socklen_t client_addr_len = sizeof(client_addr);
379*aa693e99SJason King int conn_fd, err;
380*aa693e99SJason King
381*aa693e99SJason King conn_fd = accept(svr_fd, &client_addr, &client_addr_len);
382*aa693e99SJason King if (conn_fd < 0) {
383*aa693e99SJason King L9P_LOG(L9P_WARNING, "accept(): %s", strerror(errno));
384*aa693e99SJason King return;
385*aa693e99SJason King }
386*aa693e99SJason King
387*aa693e99SJason King err = getnameinfo(&client_addr, client_addr_len, host, NI_MAXHOST,
388*aa693e99SJason King serv, NI_MAXSERV, NI_NUMERICHOST | NI_NUMERICSERV);
389*aa693e99SJason King
390*aa693e99SJason King if (err != 0) {
391*aa693e99SJason King L9P_LOG(L9P_WARNING, "cannot look up client name: %s",
392*aa693e99SJason King gai_strerror(err));
393*aa693e99SJason King } else {
394*aa693e99SJason King L9P_LOG(L9P_INFO, "new connection from %s:%s", host, serv);
395*aa693e99SJason King }
396*aa693e99SJason King
397*aa693e99SJason King if (l9p_connection_init(server, &conn) != 0) {
398*aa693e99SJason King L9P_LOG(L9P_ERROR, "cannot create new connection");
399*aa693e99SJason King return;
400*aa693e99SJason King }
401*aa693e99SJason King
402*aa693e99SJason King sc = l9p_calloc(1, sizeof(*sc));
403*aa693e99SJason King sc->ls_conn = conn;
404*aa693e99SJason King sc->ls_fd = conn_fd;
405*aa693e99SJason King
406*aa693e99SJason King /*
407*aa693e99SJason King * Fill in transport handler functions and aux argument.
408*aa693e99SJason King */
409*aa693e99SJason King conn->lc_lt.lt_aux = sc;
410*aa693e99SJason King conn->lc_lt.lt_get_response_buffer = l9p_socket_get_response_buffer;
411*aa693e99SJason King conn->lc_lt.lt_send_response = l9p_socket_send_response;
412*aa693e99SJason King conn->lc_lt.lt_drop_response = l9p_socket_drop_response;
413*aa693e99SJason King
414*aa693e99SJason King err = pthread_create(&sc->ls_thread, NULL, l9p_socket_thread, sc);
415*aa693e99SJason King if (err) {
416*aa693e99SJason King L9P_LOG(L9P_ERROR,
417*aa693e99SJason King "pthread_create (for connection from %s:%s): error %s",
418*aa693e99SJason King host, serv, strerror(err));
419*aa693e99SJason King l9p_connection_close(sc->ls_conn);
420*aa693e99SJason King free(sc);
421*aa693e99SJason King }
422*aa693e99SJason King }
423*aa693e99SJason King
424*aa693e99SJason King static void *
l9p_socket_thread(void * arg)425*aa693e99SJason King l9p_socket_thread(void *arg)
426*aa693e99SJason King {
427*aa693e99SJason King struct l9p_socket_softc *sc = (struct l9p_socket_softc *)arg;
428*aa693e99SJason King struct iovec iov;
429*aa693e99SJason King void *buf;
430*aa693e99SJason King size_t length;
431*aa693e99SJason King
432*aa693e99SJason King for (;;) {
433*aa693e99SJason King if (l9p_socket_readmsg(sc, &buf, &length) != 0)
434*aa693e99SJason King break;
435*aa693e99SJason King
436*aa693e99SJason King iov.iov_base = buf;
437*aa693e99SJason King iov.iov_len = length;
438*aa693e99SJason King l9p_connection_recv(sc->ls_conn, &iov, 1, NULL);
439*aa693e99SJason King free(buf);
440*aa693e99SJason King }
441*aa693e99SJason King
442*aa693e99SJason King L9P_LOG(L9P_INFO, "connection closed");
443*aa693e99SJason King l9p_connection_close(sc->ls_conn);
444*aa693e99SJason King free(sc);
445*aa693e99SJason King return (NULL);
446*aa693e99SJason King }
447*aa693e99SJason King
448*aa693e99SJason King static int
l9p_socket_readmsg(struct l9p_socket_softc * sc,void ** buf,size_t * size)449*aa693e99SJason King l9p_socket_readmsg(struct l9p_socket_softc *sc, void **buf, size_t *size)
450*aa693e99SJason King {
451*aa693e99SJason King uint32_t msize;
452*aa693e99SJason King size_t toread;
453*aa693e99SJason King ssize_t ret;
454*aa693e99SJason King void *buffer;
455*aa693e99SJason King int fd = sc->ls_fd;
456*aa693e99SJason King
457*aa693e99SJason King assert(fd > 0);
458*aa693e99SJason King
459*aa693e99SJason King buffer = l9p_malloc(sizeof(uint32_t));
460*aa693e99SJason King
461*aa693e99SJason King ret = xread(fd, buffer, sizeof(uint32_t));
462*aa693e99SJason King if (ret < 0) {
463*aa693e99SJason King L9P_LOG(L9P_ERROR, "read(): %s", strerror(errno));
464*aa693e99SJason King return (-1);
465*aa693e99SJason King }
466*aa693e99SJason King
467*aa693e99SJason King if (ret != sizeof(uint32_t)) {
468*aa693e99SJason King if (ret == 0) {
469*aa693e99SJason King L9P_LOG(L9P_DEBUG, "%p: EOF", (void *)sc->ls_conn);
470*aa693e99SJason King } else {
471*aa693e99SJason King L9P_LOG(L9P_ERROR,
472*aa693e99SJason King "short read: %zd bytes of %zd expected",
473*aa693e99SJason King ret, sizeof(uint32_t));
474*aa693e99SJason King }
475*aa693e99SJason King return (-1);
476*aa693e99SJason King }
477*aa693e99SJason King
478*aa693e99SJason King msize = le32toh(*(uint32_t *)buffer);
479*aa693e99SJason King toread = msize - sizeof(uint32_t);
480*aa693e99SJason King buffer = l9p_realloc(buffer, msize);
481*aa693e99SJason King
482*aa693e99SJason King ret = xread(fd, (char *)buffer + sizeof(uint32_t), toread);
483*aa693e99SJason King if (ret < 0) {
484*aa693e99SJason King L9P_LOG(L9P_ERROR, "read(): %s", strerror(errno));
485*aa693e99SJason King return (-1);
486*aa693e99SJason King }
487*aa693e99SJason King
488*aa693e99SJason King if (ret != (ssize_t)toread) {
489*aa693e99SJason King L9P_LOG(L9P_ERROR, "short read: %zd bytes of %zd expected",
490*aa693e99SJason King ret, toread);
491*aa693e99SJason King return (-1);
492*aa693e99SJason King }
493*aa693e99SJason King
494*aa693e99SJason King *size = msize;
495*aa693e99SJason King *buf = buffer;
496*aa693e99SJason King L9P_LOG(L9P_INFO, "%p: read complete message, buf=%p size=%d",
497*aa693e99SJason King (void *)sc->ls_conn, buffer, msize);
498*aa693e99SJason King
499*aa693e99SJason King return (0);
500*aa693e99SJason King }
501*aa693e99SJason King
502*aa693e99SJason King static int
l9p_socket_get_response_buffer(struct l9p_request * req,struct iovec * iov,size_t * niovp,void * arg __unused)503*aa693e99SJason King l9p_socket_get_response_buffer(struct l9p_request *req, struct iovec *iov,
504*aa693e99SJason King size_t *niovp, void *arg __unused)
505*aa693e99SJason King {
506*aa693e99SJason King size_t size = req->lr_conn->lc_msize;
507*aa693e99SJason King void *buf;
508*aa693e99SJason King
509*aa693e99SJason King buf = l9p_malloc(size);
510*aa693e99SJason King iov[0].iov_base = buf;
511*aa693e99SJason King iov[0].iov_len = size;
512*aa693e99SJason King
513*aa693e99SJason King *niovp = 1;
514*aa693e99SJason King return (0);
515*aa693e99SJason King }
516*aa693e99SJason King
517*aa693e99SJason King static int
l9p_socket_send_response(struct l9p_request * req __unused,const struct iovec * iov,const size_t niov __unused,const size_t iolen,void * arg)518*aa693e99SJason King l9p_socket_send_response(struct l9p_request *req __unused,
519*aa693e99SJason King const struct iovec *iov, const size_t niov __unused, const size_t iolen,
520*aa693e99SJason King void *arg)
521*aa693e99SJason King {
522*aa693e99SJason King struct l9p_socket_softc *sc = (struct l9p_socket_softc *)arg;
523*aa693e99SJason King
524*aa693e99SJason King assert(sc->ls_fd >= 0);
525*aa693e99SJason King
526*aa693e99SJason King L9P_LOG(L9P_DEBUG, "%p: sending reply, buf=%p, size=%d", arg,
527*aa693e99SJason King iov[0].iov_base, iolen);
528*aa693e99SJason King
529*aa693e99SJason King if (xwrite(sc->ls_fd, iov[0].iov_base, iolen) != (int)iolen) {
530*aa693e99SJason King L9P_LOG(L9P_ERROR, "short write: %s", strerror(errno));
531*aa693e99SJason King return (-1);
532*aa693e99SJason King }
533*aa693e99SJason King
534*aa693e99SJason King free(iov[0].iov_base);
535*aa693e99SJason King return (0);
536*aa693e99SJason King }
537*aa693e99SJason King
538*aa693e99SJason King static void
l9p_socket_drop_response(struct l9p_request * req __unused,const struct iovec * iov,size_t niov __unused,void * arg)539*aa693e99SJason King l9p_socket_drop_response(struct l9p_request *req __unused,
540*aa693e99SJason King const struct iovec *iov, size_t niov __unused, void *arg)
541*aa693e99SJason King {
542*aa693e99SJason King
543*aa693e99SJason King L9P_LOG(L9P_DEBUG, "%p: drop buf=%p", arg, iov[0].iov_base);
544*aa693e99SJason King free(iov[0].iov_base);
545*aa693e99SJason King }
546*aa693e99SJason King
547*aa693e99SJason King static ssize_t
xread(int fd,void * buf,size_t count)548*aa693e99SJason King xread(int fd, void *buf, size_t count)
549*aa693e99SJason King {
550*aa693e99SJason King size_t done = 0;
551*aa693e99SJason King ssize_t ret;
552*aa693e99SJason King
553*aa693e99SJason King while (done < count) {
554*aa693e99SJason King ret = read(fd, (char *)buf + done, count - done);
555*aa693e99SJason King if (ret < 0) {
556*aa693e99SJason King if (errno == EINTR)
557*aa693e99SJason King continue;
558*aa693e99SJason King
559*aa693e99SJason King return (-1);
560*aa693e99SJason King }
561*aa693e99SJason King
562*aa693e99SJason King if (ret == 0)
563*aa693e99SJason King return ((ssize_t)done);
564*aa693e99SJason King
565*aa693e99SJason King done += (size_t)ret;
566*aa693e99SJason King }
567*aa693e99SJason King
568*aa693e99SJason King return ((ssize_t)done);
569*aa693e99SJason King }
570*aa693e99SJason King
571*aa693e99SJason King static ssize_t
xwrite(int fd,void * buf,size_t count)572*aa693e99SJason King xwrite(int fd, void *buf, size_t count)
573*aa693e99SJason King {
574*aa693e99SJason King size_t done = 0;
575*aa693e99SJason King ssize_t ret;
576*aa693e99SJason King
577*aa693e99SJason King while (done < count) {
578*aa693e99SJason King ret = write(fd, (char *)buf + done, count - done);
579*aa693e99SJason King if (ret < 0) {
580*aa693e99SJason King if (errno == EINTR)
581*aa693e99SJason King continue;
582*aa693e99SJason King
583*aa693e99SJason King return (-1);
584*aa693e99SJason King }
585*aa693e99SJason King
586*aa693e99SJason King if (ret == 0)
587*aa693e99SJason King return ((ssize_t)done);
588*aa693e99SJason King
589*aa693e99SJason King done += (size_t)ret;
590*aa693e99SJason King }
591*aa693e99SJason King
592*aa693e99SJason King return ((ssize_t)done);
593*aa693e99SJason King }
594