diff --git a/src/apps/socket/dev.lua b/src/apps/socket/dev.lua index 9dbb78f2ae..3291cc8644 100644 --- a/src/apps/socket/dev.lua +++ b/src/apps/socket/dev.lua @@ -28,11 +28,17 @@ end function dev:receive() assert(self.fd) + local size = C.msg_size(self.fd) + assert(size ~= -1) local p = packet.allocate() - local b = buffer.allocate() - local s = C.receive_packet(self.fd, b) + local nbuffers = math.ceil(size/buffer.size) + assert(nbuffers <= C.PACKET_IOVEC_MAX) + for i = 1, nbuffers do + local b = buffer.allocate() + packet.add_iovec(p, b, 0) + end + local s = C.receive_packet(self.fd, p) assert(s ~= -1) - packet.add_iovec(p, b, s) return p end diff --git a/src/apps/socket/io.c b/src/apps/socket/io.c index 32fcd4d675..49c1feb3f1 100644 --- a/src/apps/socket/io.c +++ b/src/apps/socket/io.c @@ -1,6 +1,7 @@ #include #include #include +#include #include #include #include @@ -31,23 +32,50 @@ int send_packet(int fd, struct packet *p) { return(0); } -int receive_packet(int fd, struct buffer *b) { +int receive_packet(int fd, struct packet *p) { struct msghdr msg; - struct iovec iovec; - ssize_t s; + struct iovec iovecs[p->niovecs]; + int i; + ssize_t s, len; bzero(&msg, sizeof(msg)); - iovec.iov_base = b->pointer; - iovec.iov_len = b->size; - msg.msg_iov = &iovec; - msg.msg_iovlen = 1; + for (i=0; iniovecs; i++) { + iovecs[i].iov_base = p->iovecs[i].buffer->pointer; + iovecs[i].iov_len = p->iovecs[i].buffer->size; + } + msg.msg_iov = iovecs; + msg.msg_iovlen = p->niovecs; if ((s = recvmsg(fd, &msg, 0)) == -1) { perror("recvmsg"); return(-1); } + if (msg.msg_flags && MSG_TRUNC) { + printf("truncated\n"); + return(-1); + } + len = s; + for (i=0; iniovecs; i++) { + ssize_t iov_len = msg.msg_iov[i].iov_len; + if (len > iov_len) { + p->iovecs[i].length = iov_len; + len -= iov_len; + } else { + p->iovecs[i].length = len; + } + } + p->length = s; return(s); } +int msg_size(int fd) { + int size; + if (ioctl(fd, FIONREAD, &size) == -1) { + perror("get message size"); + return(-1); + } + return(size); +} + int can_receive(int fd) { fd_set fds; struct timeval tv = { .tv_sec = 0, .tv_usec = 0 }; diff --git a/src/apps/socket/io.h b/src/apps/socket/io.h index da2d0817f5..ba602269ef 100644 --- a/src/apps/socket/io.h +++ b/src/apps/socket/io.h @@ -1,4 +1,5 @@ int send_packet(int, struct packet *); -int receive_packet(int, struct buffer *); +int receive_packet(int, struct packet *); int can_transmit(int); int can_receive(int); +int msg_size(int); diff --git a/src/apps/vpn/vpws.lua b/src/apps/vpn/vpws.lua index 969ac209ee..0079a4bdd0 100644 --- a/src/apps/vpn/vpws.lua +++ b/src/apps/vpn/vpws.lua @@ -75,10 +75,10 @@ function vpws:push() else -- Packet doesn't belong to VPN, discard packet.deref(p) - return + p = nil end end - app.transmit(l_out, p) + if p then app.transmit(l_out, p) end end end end