diff options
author | aliguori <aliguori@c046a42c-6fe2-441c-8c8c-71466251a162> | 2009-01-08 19:18:21 +0000 |
---|---|---|
committer | aliguori <aliguori@c046a42c-6fe2-441c-8c8c-71466251a162> | 2009-01-08 19:18:21 +0000 |
commit | e1c5a2b33409b9795fa58bf389eac855981330a5 (patch) | |
tree | c88f13940cab1cc4824cee90109fe93d6ffd3670 /slirp/socket.c | |
parent | 4dda406337050578c252374981733223c9af72f3 (diff) |
Redirect slirp traffic to/from qemu character device (Gleb Natapov)
Signed-off-by: Gleb Natapov <gleb@redhat.com>
Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@6240 c046a42c-6fe2-441c-8c8c-71466251a162
Diffstat (limited to 'slirp/socket.c')
-rw-r--r-- | slirp/socket.c | 101 |
1 files changed, 80 insertions, 21 deletions
diff --git a/slirp/socket.c b/slirp/socket.c index 00694e2c71..9def541dae 100644 --- a/slirp/socket.c +++ b/slirp/socket.c @@ -5,13 +5,13 @@ * terms and conditions of the copyright. */ +#include "qemu-common.h" #define WANT_SYS_IOCTL_H #include <slirp.h> #include "ip_icmp.h" #ifdef __sun__ #include <sys/filio.h> #endif -#include "qemu-common.h" static void sofcantrcvmore(struct socket *so); static void sofcantsendmore(struct socket *so); @@ -91,31 +91,21 @@ sofree(so) free(so); } -/* - * Read from so's socket into sb_snd, updating all relevant sbuf fields - * NOTE: This will only be called if it is select()ed for reading, so - * a read() of 0 (or less) means it's disconnected - */ -int -soread(so) - struct socket *so; +size_t sopreprbuf(struct socket *so, struct iovec *iov, int *np) { - int n, nn, lss, total; + int n, lss, total; struct sbuf *sb = &so->so_snd; int len = sb->sb_datalen - sb->sb_cc; - struct iovec iov[2]; int mss = so->so_tcpcb->t_maxseg; - DEBUG_CALL("soread"); + DEBUG_CALL("sopreprbuf"); DEBUG_ARG("so = %lx", (long )so); - /* - * No need to check if there's enough room to read. - * soread wouldn't have been called if there weren't - */ - len = sb->sb_datalen - sb->sb_cc; + if (len <= 0) + return 0; + iov[0].iov_base = sb->sb_wptr; iov[1].iov_base = NULL; iov[1].iov_len = 0; @@ -156,6 +146,33 @@ soread(so) n = 1; } } + if (np) + *np = n; + + return iov[0].iov_len + (n - 1) * iov[1].iov_len; +} + +/* + * Read from so's socket into sb_snd, updating all relevant sbuf fields + * NOTE: This will only be called if it is select()ed for reading, so + * a read() of 0 (or less) means it's disconnected + */ +int +soread(so) + struct socket *so; +{ + int n, nn; + struct sbuf *sb = &so->so_snd; + struct iovec iov[2]; + + DEBUG_CALL("soread"); + DEBUG_ARG("so = %lx", (long )so); + + /* + * No need to check if there's enough room to read. + * soread wouldn't have been called if there weren't + */ + sopreprbuf(so, iov, &n); #ifdef HAVE_READV nn = readv(so->s, (struct iovec *)iov, n); @@ -202,6 +219,48 @@ soread(so) return nn; } +int soreadbuf(struct socket *so, const char *buf, int size) +{ + int n, nn, copy = size; + struct sbuf *sb = &so->so_snd; + struct iovec iov[2]; + + DEBUG_CALL("soreadbuf"); + DEBUG_ARG("so = %lx", (long )so); + + /* + * No need to check if there's enough room to read. + * soread wouldn't have been called if there weren't + */ + if (sopreprbuf(so, iov, &n) < size) + goto err; + + nn = MIN(iov[0].iov_len, copy); + memcpy(iov[0].iov_base, buf, nn); + + copy -= nn; + buf += nn; + + if (copy == 0) + goto done; + + memcpy(iov[1].iov_base, buf, copy); + +done: + /* Update fields */ + sb->sb_cc += size; + sb->sb_wptr += size; + if (sb->sb_wptr >= (sb->sb_data + sb->sb_datalen)) + sb->sb_wptr -= sb->sb_datalen; + return size; +err: + + sofcantrcvmore(so); + tcp_sockclosed(sototcpcb(so)); + fprintf(stderr, "soreadbuf buffer to small"); + return -1; +} + /* * Get urgent data * @@ -255,7 +314,7 @@ sosendoob(so) if (sb->sb_rptr < sb->sb_wptr) { /* We can send it directly */ - n = send(so->s, sb->sb_rptr, so->so_urgc, (MSG_OOB)); /* |MSG_DONTWAIT)); */ + n = slirp_send(so, sb->sb_rptr, so->so_urgc, (MSG_OOB)); /* |MSG_DONTWAIT)); */ so->so_urgc -= n; DEBUG_MISC((dfd, " --- sent %d bytes urgent data, %d urgent bytes left\n", n, so->so_urgc)); @@ -276,7 +335,7 @@ sosendoob(so) so->so_urgc -= n; len += n; } - n = send(so->s, buff, len, (MSG_OOB)); /* |MSG_DONTWAIT)); */ + n = slirp_send(so, buff, len, (MSG_OOB)); /* |MSG_DONTWAIT)); */ #ifdef DEBUG if (n != len) DEBUG_ERROR((dfd, "Didn't send all data urgently XXXXX\n")); @@ -348,7 +407,7 @@ sowrite(so) DEBUG_MISC((dfd, " ... wrote nn = %d bytes\n", nn)); #else - nn = send(so->s, iov[0].iov_base, iov[0].iov_len,0); + nn = slirp_send(so, iov[0].iov_base, iov[0].iov_len,0); #endif /* This should never happen, but people tell me it does *shrug* */ if (nn < 0 && (errno == EAGAIN || errno == EINTR)) @@ -365,7 +424,7 @@ sowrite(so) #ifndef HAVE_READV if (n == 2 && nn == iov[0].iov_len) { int ret; - ret = send(so->s, iov[1].iov_base, iov[1].iov_len,0); + ret = slirp_send(so, iov[1].iov_base, iov[1].iov_len,0); if (ret > 0) nn += ret; } |