Esempio n. 1
0
File: socket.c Progetto: djs55/qemu
/*
 * 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(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);
	DEBUG_MISC((dfd, " ... read nn = %d bytes\n", nn));
#else
	nn = qemu_recv(so->s, iov[0].iov_base, iov[0].iov_len,0);
#endif
	if (nn <= 0) {
		if (nn < 0 && (errno == EINTR || errno == EAGAIN))
			return 0;
		else {
			DEBUG_MISC((dfd, " --- soread() disconnected, nn = %d, errno = %d-%s\n", nn, errno,strerror(errno)));
			sofcantrcvmore(so);
			tcp_sockclosed(sototcpcb(so));
			return -1;
		}
	}

#ifndef HAVE_READV
	/*
	 * If there was no error, try and read the second time round
	 * We read again if n = 2 (ie, there's another part of the buffer)
	 * and we read as much as we could in the first read
	 * We don't test for <= 0 this time, because there legitimately
	 * might not be any more data (since the socket is non-blocking),
	 * a close will be detected on next iteration.
	 * A return of -1 wont (shouldn't) happen, since it didn't happen above
	 */
	if (n == 2 && nn == iov[0].iov_len) {
            int ret;
            ret = qemu_recv(so->s, iov[1].iov_base, iov[1].iov_len,0);
            if (ret > 0)
                nn += ret;
        }

	DEBUG_MISC((dfd, " ... read nn = %d bytes\n", nn));
#endif

	/* Update fields */
	sb->sb_cc += nn;
	sb->sb_wptr += nn;
	if (sb->sb_wptr >= (sb->sb_data + sb->sb_datalen))
		sb->sb_wptr -= sb->sb_datalen;
	return nn;
}
Esempio n. 2
0
File: socket.c Progetto: djs55/qemu
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;
}
Esempio n. 3
0
int
sounlisten(u_int  port)
{
    struct socket *so;

    for (so = tcb.so_next; so != &tcb; so = so->so_next) {
        if (so->so_haddr_port == port) {
            break;
        }
    }

    if (so == &tcb) {
        return -1;
    }

    sofcantrcvmore( so );
    sofcantsendmore( so );
    close( so->s );
    so->s = -1;
    sofree( so );
    return 0;
}
/*
 * 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(PNATState pData, struct socket *so)
{
    int n, nn, lss, total;
    struct sbuf *sb = &so->so_snd;
    u_int len = sb->sb_datalen - sb->sb_cc;
    struct iovec iov[2];
    int mss = so->so_tcpcb->t_maxseg;
    int sockerr;

    STAM_PROFILE_START(&pData->StatIOread, a);
    STAM_COUNTER_RESET(&pData->StatIORead_in_1);
    STAM_COUNTER_RESET(&pData->StatIORead_in_2);

    QSOCKET_LOCK(tcb);
    SOCKET_LOCK(so);
    QSOCKET_UNLOCK(tcb);

    LogFlow(("soread: so = %R[natsock]\n", so));
    Log2(("%s: so = %R[natsock] so->so_snd = %R[sbuf]\n", RT_GCC_EXTENSION __PRETTY_FUNCTION__, so, sb));

    /*
     * 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;

    iov[0].iov_base = sb->sb_wptr;
    iov[1].iov_base = 0;
    iov[1].iov_len  = 0;
    if (sb->sb_wptr < sb->sb_rptr)
    {
        iov[0].iov_len = sb->sb_rptr - sb->sb_wptr;
        /* Should never succeed, but... */
        if (iov[0].iov_len > len)
            iov[0].iov_len = len;
        if (iov[0].iov_len > mss)
            iov[0].iov_len -= iov[0].iov_len%mss;
        n = 1;
    }
    else
    {
        iov[0].iov_len = (sb->sb_data + sb->sb_datalen) - sb->sb_wptr;
        /* Should never succeed, but... */
        if (iov[0].iov_len > len)
            iov[0].iov_len = len;
        len -= iov[0].iov_len;
        if (len)
        {
            iov[1].iov_base = sb->sb_data;
            iov[1].iov_len = sb->sb_rptr - sb->sb_data;
            if (iov[1].iov_len > len)
                iov[1].iov_len = len;
            total = iov[0].iov_len + iov[1].iov_len;
            if (total > mss)
            {
                lss = total % mss;
                if (iov[1].iov_len > lss)
                {
                    iov[1].iov_len -= lss;
                    n = 2;
                }
                else
                {
                    lss -= iov[1].iov_len;
                    iov[0].iov_len -= lss;
                    n = 1;
                }
            }
            else
                n = 2;
        }
        else
        {
            if (iov[0].iov_len > mss)
                iov[0].iov_len -= iov[0].iov_len%mss;
            n = 1;
        }
    }

#ifdef HAVE_READV
    nn = readv(so->s, (struct iovec *)iov, n);
#else
    nn = recv(so->s, iov[0].iov_base, iov[0].iov_len, (so->so_tcpcb->t_force? MSG_OOB:0));
#endif
    if (nn < 0)
        sockerr = errno; /* save it, as it may be clobbered by logging */
    else
        sockerr = 0;

    Log2(("%s: read(1) nn = %d bytes\n", RT_GCC_EXTENSION __PRETTY_FUNCTION__, nn));
    Log2(("%s: so = %R[natsock] so->so_snd = %R[sbuf]\n", RT_GCC_EXTENSION __PRETTY_FUNCTION__, so, sb));
    if (nn <= 0)
    {
#ifdef RT_OS_WINDOWS
        /*
         * Windows reports ESHUTDOWN after SHUT_RD (SD_RECEIVE)
         * instead of just returning EOF indication.
         */
        if (nn < 0 && sockerr == ESHUTDOWN)
        {
            nn = 0;
            sockerr = 0;
        }
#endif

        if (nn == 0) /* XXX: should this be inside #if defined(RT_OS_WINDOWS)? */
        {
            /*
             * Special case for WSAEnumNetworkEvents: If we receive 0 bytes that
             * _could_ mean that the connection is closed. But we will receive an
             * FD_CLOSE event later if the connection was _really_ closed. With
             * www.youtube.com I see this very often. Closing the socket too early
             * would be dangerous.
             */
            int status;
            unsigned long pending = 0;
            status = ioctlsocket(so->s, FIONREAD, &pending);
            if (status < 0)
                Log(("NAT:%s: error in WSAIoctl: %d\n", RT_GCC_EXTENSION __PRETTY_FUNCTION__, errno));
            if (pending != 0)
            {
                SOCKET_UNLOCK(so);
                STAM_PROFILE_STOP(&pData->StatIOread, a);
                return 0;
            }
        }

        if (   nn < 0
            && soIgnorableErrorCode(sockerr))
        {
            SOCKET_UNLOCK(so);
            STAM_PROFILE_STOP(&pData->StatIOread, a);
            return 0;
        }
        else
        {
            int fUninitializedTemplate = 0;
            int shuterr;

            fUninitializedTemplate = RT_BOOL((   sototcpcb(so)
                                              && (  sototcpcb(so)->t_template.ti_src.s_addr == INADDR_ANY
                                                 || sototcpcb(so)->t_template.ti_dst.s_addr == INADDR_ANY)));
            /* nn == 0 means peer has performed an orderly shutdown */
            Log2(("%s: disconnected, nn = %d, errno = %d (%s)\n",
                  RT_GCC_EXTENSION __PRETTY_FUNCTION__, nn, sockerr, strerror(sockerr)));

            shuterr = sofcantrcvmore(so);
            if (!sockerr && !shuterr && !fUninitializedTemplate)
                tcp_sockclosed(pData, sototcpcb(so));
            else
            {
                LogRel2(("NAT: sockerr %d, shuterr %d - %R[natsock]\n", sockerr, shuterr, so));
                tcp_drop(pData, sototcpcb(so), sockerr);
            }
            SOCKET_UNLOCK(so);
            STAM_PROFILE_STOP(&pData->StatIOread, a);
            return -1;
        }
    }
    STAM_STATS(
        if (n == 1)
        {
            STAM_COUNTER_INC(&pData->StatIORead_in_1);
            STAM_COUNTER_ADD(&pData->StatIORead_in_1_bytes, nn);
        }
        else
        {
            STAM_COUNTER_INC(&pData->StatIORead_in_2);
            STAM_COUNTER_ADD(&pData->StatIORead_in_2_1st_bytes, nn);
        }
    );
Esempio n. 5
0
/*
 * 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(struct socket *so)
{
	int n, nn, 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_ARG("so = %p", 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;
	
	iov[0].iov_base = sb->sb_wptr;
	if (sb->sb_wptr < sb->sb_rptr) {
		iov[0].iov_len = sb->sb_rptr - sb->sb_wptr;
		/* Should never succeed, but... */
		if (iov[0].iov_len > len)
		   iov[0].iov_len = len;
		if (iov[0].iov_len > mss)
		   iov[0].iov_len -= iov[0].iov_len%mss;
		n = 1;
	} else {
		iov[0].iov_len = (sb->sb_data + sb->sb_datalen) - sb->sb_wptr;
		/* Should never succeed, but... */
		if (iov[0].iov_len > len) iov[0].iov_len = len;
		len -= iov[0].iov_len;
		if (len) {
			iov[1].iov_base = sb->sb_data;
			iov[1].iov_len = sb->sb_rptr - sb->sb_data;
			if(iov[1].iov_len > len)
			   iov[1].iov_len = len;
			total = iov[0].iov_len + iov[1].iov_len;
			if (total > mss) {
				lss = total%mss;
				if (iov[1].iov_len > lss) {
					iov[1].iov_len -= lss;
					n = 2;
				} else {
					lss -= iov[1].iov_len;
					iov[0].iov_len -= lss;
					n = 1;
				}
			} else
				n = 2;
		} else {
			if (iov[0].iov_len > mss)
			   iov[0].iov_len -= iov[0].iov_len%mss;
			n = 1;
		}
	}
	
#ifdef HAVE_READV
	nn = readv(so->s, (struct iovec *)iov, n);
	DEBUG_MISC((" ... read nn = %d bytes\n", nn));
#else
	nn = recv(so->s, iov[0].iov_base, iov[0].iov_len,0);
#endif	
	if (nn <= 0) {
		if (nn < 0 && (errno == EINTR || errno == EAGAIN))
			return 0;
		else {
			DEBUG_MISC((" --- soread() disconnected, nn = %d, errno = %d-%s\n", nn, errno,strerror(errno)));
			sofcantrcvmore(so);
			tcp_sockclosed(sototcpcb(so));
			return -1;
		}
	}
	
#ifndef HAVE_READV
	/*
	 * If there was no error, try and read the second time round
	 * We read again if n = 2 (ie, there's another part of the buffer)
	 * and we read as much as we could in the first read
	 * We don't test for <= 0 this time, because there legitimately
	 * might not be any more data (since the socket is non-blocking),
	 * a close will be detected on next iteration.
	 * A return of -1 wont (shouldn't) happen, since it didn't happen above
	 */
	if (n == 2 && nn == iov[0].iov_len) {
            int ret;
            ret = recv(so->s, iov[1].iov_base, iov[1].iov_len,0);
            if (ret > 0)
                nn += ret;
        }
	
	DEBUG_MISC((" ... read nn = %d bytes\n", nn));
#endif
	
	/* Update fields */
	sb->sb_cc += nn;
	sb->sb_wptr += nn;
	if (sb->sb_wptr >= (sb->sb_data + sb->sb_datalen))
		sb->sb_wptr -= sb->sb_datalen;
	return nn;
}