diff --git a/reactos/drivers/lib/oskittcp/oskittcp/interface.c b/reactos/drivers/lib/oskittcp/oskittcp/interface.c index dd0a9404c29..bfd12b0190d 100644 --- a/reactos/drivers/lib/oskittcp/oskittcp/interface.c +++ b/reactos/drivers/lib/oskittcp/oskittcp/interface.c @@ -108,35 +108,37 @@ int OskitTCPRecv( void *connection, OSK_UINT Len, OSK_UINT *OutLen, OSK_UINT Flags ) { - struct mbuf *paddr = 0; - struct mbuf m, *mp; + char *output_ptr = Data; struct uio uio = { 0 }; + struct iovec iov = { 0 }; int error = 0; int tcp_flags = 0; + int tocopy = 0; + + *OutLen = 0; if( Flags & OSK_MSG_OOB ) tcp_flags |= MSG_OOB; if( Flags & OSK_MSG_DONTWAIT ) tcp_flags |= MSG_DONTWAIT; if( Flags & OSK_MSG_PEEK ) tcp_flags |= MSG_PEEK; uio.uio_resid = Len; - m.m_len = Len; - m.m_data = Data; - m.m_type = MT_DATA; - m.m_flags = M_PKTHDR | M_EOR; - - mp = &m; + uio.uio_iov = &iov; + uio.uio_rw = UIO_READ; + uio.uio_iovcnt = 1; + iov.iov_len = Len; + iov.iov_base = Data; OS_DbgPrint(OSK_MID_TRACE,("Reading %d bytes from TCP:\n", Len)); - error = soreceive( connection, &paddr, &uio, &mp, NULL /* SCM_RIGHTS */, + error = soreceive( connection, NULL, &uio, NULL, NULL /* SCM_RIGHTS */, &tcp_flags ); if( error == 0 ) { OS_DbgPrint(OSK_MID_TRACE,("Successful read from TCP:\n")); - OskitDumpBuffer( m.m_data, uio.uio_resid ); + *OutLen = Len - uio.uio_resid; + OskitDumpBuffer( Data, *OutLen ); } - *OutLen = uio.uio_resid; return error; } diff --git a/reactos/drivers/lib/oskittcp/oskittcp/uipc_socket.c b/reactos/drivers/lib/oskittcp/oskittcp/uipc_socket.c index 6c301c992f1..0891134d64c 100644 --- a/reactos/drivers/lib/oskittcp/oskittcp/uipc_socket.c +++ b/reactos/drivers/lib/oskittcp/oskittcp/uipc_socket.c @@ -76,8 +76,6 @@ socreate(dom, aso, type, proto) register struct socket *so; register int error; - printf("socreate(%d,%x,%d,%d)\n", dom, aso, type, proto); - if (proto) prp = pffindproto(dom, proto, type); else @@ -89,6 +87,10 @@ socreate(dom, aso, type, proto) MALLOC(so, struct socket *, sizeof(*so), M_SOCKET, M_WAIT); bzero((caddr_t)so, sizeof(*so)); so->so_type = type; +#ifndef __REACTOS__ + if (p->p_ucred->cr_uid == 0) + so->so_state = SS_PRIV; +#endif so->so_proto = prp; error = (*prp->pr_usrreq)(so, PRU_ATTACH, @@ -356,7 +358,9 @@ sosend(so, addr, uio, top, control, flags) dontroute = (flags & MSG_DONTROUTE) && (so->so_options & SO_DONTROUTE) == 0 && (so->so_proto->pr_flags & PR_ATOMIC); - /* p->p_stats->p_ru.ru_msgsnd++; */ +#ifndef __REACTOS__ + p->p_stats->p_ru.ru_msgsnd++; +#endif if (control) clen = control->m_len; #define snderr(errno) { error = errno; splx(s); goto release; } @@ -486,13 +490,10 @@ nopages: release: sbunlock(so, &so->so_snd); out: -#ifndef __REACTOS__ if (top) - m_freem(top); + m_freem(top); if (control) - m_freem(control); -#endif /* The caller owns top and control */ - OS_DbgPrint(OSK_MID_TRACE,("Leaving\n")); + m_freem(control); return (error); } @@ -513,91 +514,306 @@ out: * only for the count in uio_resid. */ int -soreceive(so, paddr, uio, _mp0, controlp, flagsp) +soreceive(so, paddr, uio, mp0, controlp, flagsp) register struct socket *so; struct mbuf **paddr; struct uio *uio; - struct mbuf **_mp0; + struct mbuf **mp0; struct mbuf **controlp; int *flagsp; { - struct mbuf dummy = { 0 }; - struct mbuf *mb = &dummy, *mn, *mp0 = *_mp0; - int total = 0, copyamt; + register struct mbuf *m, **mp; + register int flags, len, error, s, offset; + struct protosw *pr = so->so_proto; + struct mbuf *nextrecord; + int moff, type = 0; + int orig_resid = uio->uio_resid; - dummy.m_nextpkt = so->so_rcv.sb_mb; - uio->uio_resid = 0; + mp = mp0; + if (paddr) + *paddr = 0; + if (controlp) + *controlp = 0; + if (flagsp) + flags = *flagsp &~ MSG_EOR; + else + flags = 0; + if (flags & MSG_OOB) { + m = m_get(M_WAIT, MT_DATA); + error = (*pr->pr_usrreq)(so, PRU_RCVOOB, + m, (struct mbuf *)(flags & MSG_PEEK), (struct mbuf *)0); + if (error) + goto bad; + do { + error = uiomove(mtod(m, caddr_t), + (int) min(uio->uio_resid, m->m_len), uio); + m = m_free(m); + } while (uio->uio_resid && error == 0 && m); +bad: + if (m) + m_freem(m); + return (error); + } + if (mp) + *mp = (struct mbuf *)0; + if (so->so_state & SS_ISCONFIRMING && uio->uio_resid) + (*pr->pr_usrreq)(so, PRU_RCVD, (struct mbuf *)0, + (struct mbuf *)0, (struct mbuf *)0); - if( mp0->m_len == 0 ) - return 0; +restart: + error = sblock(&so->so_rcv, SBLOCKWAIT(flags)); + if (error) + return (error); + s = splnet(); - if( so->so_rcv.sb_cc == 0 && - /*so->so_rcv.sb_sel.si_flags & SEL_FIN*/ - (so->so_state & SS_CANTRCVMORE) ) { - OS_DbgPrint(OSK_MID_TRACE, ("Receive: SEL_FIN\n")); - return OSK_ESHUTDOWN; - } - - while( mb->m_nextpkt && total < mp0->m_len ) { - OS_DbgPrint(OSK_MID_TRACE, ("Looking at packet %x\n", mb)); - - if( *flagsp & MSG_OOB ) { - OS_DbgPrint(OSK_MID_TRACE, ("Searching for oob: %x\n", mb)); - while( mb->m_nextpkt && mb->m_nextpkt->m_type != MT_OOBDATA ) - mb = mb->m_nextpkt; - } else { - while( mb->m_nextpkt && mb->m_nextpkt->m_type != MT_DATA ) { - OS_DbgPrint - (OSK_MID_TRACE, - ("Searching for data: %x (%x@%x)\n", - mb->m_nextpkt->m_type, - mb->m_nextpkt->m_len, - mb->m_nextpkt->m_data)); - mb = mb->m_nextpkt; - } + m = so->so_rcv.sb_mb; + /* + * If we have less data than requested, block awaiting more + * (subject to any timeout) if: + * 1. the current count is less than the low water mark, or + * 2. MSG_WAITALL is set, and it is possible to do the entire + * receive operation at once if we block (resid <= hiwat). + * 3. MSG_DONTWAIT is not set + * If MSG_WAITALL is set but resid is larger than the receive buffer, + * we have to do the receive in sections, and thus risk returning + * a short count if a timeout or signal occurs after we start. + */ + if (m == 0 || (((flags & MSG_DONTWAIT) == 0 && + so->so_rcv.sb_cc < uio->uio_resid) && + (so->so_rcv.sb_cc < so->so_rcv.sb_lowat || + ((flags & MSG_WAITALL) && uio->uio_resid <= so->so_rcv.sb_hiwat)) && + m->m_nextpkt == 0 && (pr->pr_flags & PR_ATOMIC) == 0)) { +#ifdef DIAGNOSTIC + if (m == 0 && so->so_rcv.sb_cc) + panic("receive 1"); +#endif + if (so->so_error) { + if (m) + goto dontblock; + error = so->so_error; + if ((flags & MSG_PEEK) == 0) + so->so_error = 0; + goto release; + } + if (so->so_state & SS_CANTRCVMORE) { + if (m) + goto dontblock; + else + goto release; + } + for (; m; m = m->m_next) + if (m->m_type == MT_OOBDATA || (m->m_flags & M_EOR)) { + m = so->so_rcv.sb_mb; + goto dontblock; + } + if ((so->so_state & (SS_ISCONNECTED|SS_ISCONNECTING)) == 0 && + (so->so_proto->pr_flags & PR_CONNREQUIRED)) { + error = ENOTCONN; + goto release; + } + if (uio->uio_resid == 0) + goto release; + if ((so->so_state & SS_NBIO) || (flags & MSG_DONTWAIT)) { + error = EWOULDBLOCK; + goto release; + } + sbunlock(so, &so->so_rcv); + error = sbwait(&so->so_rcv); + splx(s); + if (error) + return (error); + goto restart; + } +dontblock: + if (uio->uio_procp) + uio->uio_procp->p_stats->p_ru.ru_msgrcv++; + nextrecord = m->m_nextpkt; + if (pr->pr_flags & PR_ADDR) { +#ifdef DIAGNOSTIC + if (m->m_type != MT_SONAME) + panic("receive 1a"); +#endif + orig_resid = 0; + if (flags & MSG_PEEK) { + if (paddr) + *paddr = m_copy(m, 0, m->m_len); + m = m->m_next; + } else { + sbfree(&so->so_rcv, m); + if (paddr) { + *paddr = m; + so->so_rcv.sb_mb = m->m_next; + m->m_next = 0; + m = so->so_rcv.sb_mb; + } else { + MFREE(m, so->so_rcv.sb_mb); + m = so->so_rcv.sb_mb; + } + } + } + while (m && m->m_type == MT_CONTROL && error == 0) { + if (flags & MSG_PEEK) { + if (controlp) + *controlp = m_copy(m, 0, m->m_len); + m = m->m_next; + } else { + sbfree(&so->so_rcv, m); +#ifndef __REACTOS__ + if (controlp) { + if (pr->pr_domain->dom_externalize && + mtod(m, struct cmsghdr *)->cmsg_type == + SCM_RIGHTS) + error = (*pr->pr_domain->dom_externalize)(m); + *controlp = m; + so->so_rcv.sb_mb = m->m_next; + m->m_next = 0; + m = so->so_rcv.sb_mb; + } else +#endif + { + MFREE(m, so->so_rcv.sb_mb); + m = so->so_rcv.sb_mb; + } + } + if (controlp) { + orig_resid = 0; + controlp = &(*controlp)->m_next; + } + } + if (m) { + if ((flags & MSG_PEEK) == 0) + m->m_nextpkt = nextrecord; + type = m->m_type; + if (type == MT_OOBDATA) + flags |= MSG_OOB; + } + moff = 0; + offset = 0; + while (m && uio->uio_resid > 0 && error == 0) { + if (m->m_type == MT_OOBDATA) { + if (type != MT_OOBDATA) + break; + } else if (type == MT_OOBDATA) + break; +#ifdef DIAGNOSTIC + else if (m->m_type != MT_DATA && m->m_type != MT_HEADER) + panic("receive 3"); +#endif + so->so_state &= ~SS_RCVATMARK; + len = uio->uio_resid; + if (so->so_oobmark && len > so->so_oobmark - offset) + len = so->so_oobmark - offset; + if (len > m->m_len - moff) + len = m->m_len - moff; + /* + * If mp is set, just pass back the mbufs. + * Otherwise copy them out via the uio, then free. + * Sockbuf must be consistent here (points to current mbuf, + * it points to next record) when we drop priority; + * we must note any additions to the sockbuf when we + * block interrupts again. + */ + if (mp == 0) { + splx(s); + error = uiomove(mtod(m, caddr_t) + moff, (int)len, uio); + s = splnet(); + } else + uio->uio_resid -= len; + if (len == m->m_len - moff) { + if (m->m_flags & M_EOR) + flags |= MSG_EOR; + if (flags & MSG_PEEK) { + m = m->m_next; + moff = 0; + } else { + nextrecord = m->m_nextpkt; + sbfree(&so->so_rcv, m); + if (mp) { + *mp = m; + mp = &m->m_next; + so->so_rcv.sb_mb = m = m->m_next; + *mp = (struct mbuf *)0; + } else { + MFREE(m, so->so_rcv.sb_mb); + m = so->so_rcv.sb_mb; + } + if (m) + m->m_nextpkt = nextrecord; + } + } else { + if (flags & MSG_PEEK) + moff += len; + else { + if (mp) + *mp = m_copym(m, 0, len, M_WAIT); + m->m_data += len; + m->m_len -= len; + so->so_rcv.sb_cc -= len; + } + } + if (so->so_oobmark) { + if ((flags & MSG_PEEK) == 0) { + so->so_oobmark -= len; + if (so->so_oobmark == 0) { + so->so_state |= SS_RCVATMARK; + break; + } + } else { + offset += len; + if (offset == so->so_oobmark) + break; + } + } + if (flags & MSG_EOR) + break; + /* + * If the MSG_WAITALL flag is set (for non-atomic socket), + * we must not quit until "uio->uio_resid == 0" or an error + * termination. If a signal/timeout occurs, return + * with a short count but without error. + * Keep sockbuf locked against other readers. + */ + while (flags & MSG_WAITALL && m == 0 && uio->uio_resid > 0 && + !sosendallatonce(so) && !nextrecord) { + if (so->so_error || so->so_state & SS_CANTRCVMORE) + break; + error = sbwait(&so->so_rcv); + if (error) { + sbunlock(so, &so->so_rcv); + splx(s); + return (0); + } + m = so->so_rcv.sb_mb; + if (m) + nextrecord = m->m_nextpkt; + } } - if( !mb->m_nextpkt ) break; - - mn = mb->m_nextpkt; - - if( !mn->m_next ) mn->m_next = mn->m_data; - copyamt = min(mn->m_len, mp0->m_len); - OS_DbgPrint(OSK_MID_TRACE, - ("Copying %d bytes (%d,%d) (total is %d so far)\n", - copyamt, mn->m_len, mp0->m_len, total + copyamt)); - memcpy( mp0->m_data + total, mn->m_next, copyamt ); - total += copyamt; - mp0->m_len -= copyamt; - - if( copyamt < mn->m_len ) { - if( !(*flagsp & MSG_PEEK) ) - ((caddr_t)mn->m_next) += copyamt; - break; - } - - mb->m_nextpkt = mn->m_nextpkt; - } - - /* Free previous buffers if not peek */ - if( !(*flagsp & MSG_PEEK) ) { - while( dummy.m_nextpkt && dummy.m_nextpkt != mn ) { - mb = dummy.m_nextpkt; - dummy.m_nextpkt = mb->m_nextpkt; - OS_DbgPrint - (OSK_MID_TRACE, - ("Deleting buf %x", mb)); - m_free(mb); + if (m && pr->pr_flags & PR_ATOMIC) { + flags |= MSG_TRUNC; + if ((flags & MSG_PEEK) == 0) + (void) sbdroprecord(&so->so_rcv); + } + if ((flags & MSG_PEEK) == 0) { + if (m == 0) + so->so_rcv.sb_mb = nextrecord; + if (pr->pr_flags & PR_WANTRCVD && so->so_pcb) + (*pr->pr_usrreq)(so, PRU_RCVD, (struct mbuf *)0, + (struct mbuf *)flags, (struct mbuf *)0); + } + if (orig_resid == uio->uio_resid && orig_resid && + (flags & MSG_EOR) == 0 && (so->so_state & SS_CANTRCVMORE) == 0) { + sbunlock(so, &so->so_rcv); + splx(s); + goto restart; } - so->so_rcv.sb_cc -= total; - so->so_rcv.sb_mb = dummy.m_nextpkt; - } - uio->uio_resid = total; - - OS_DbgPrint(OSK_MID_TRACE,("Leaving (success: %d bytes)\n", total)); - - return 0; + if (flagsp) + *flagsp |= flags; +release: + sbunlock(so, &so->so_rcv); + splx(s); + return (error); } int @@ -669,7 +885,7 @@ sosetopt(so, level, optname, m0) case SO_USELOOPBACK: case SO_BROADCAST: case SO_REUSEADDR: - /*case SO_REUSEPORT:*/ + case SO_REUSEPORT: case SO_OOBINLINE: if (m == NULL || m->m_len < sizeof (int)) { error = EINVAL; @@ -751,7 +967,7 @@ sosetopt(so, level, optname, m0) } bad: if (m) - (void) m_free(m); + (void) m_free(m); return (error); } @@ -787,7 +1003,7 @@ sogetopt(so, level, optname, mp) case SO_DEBUG: case SO_KEEPALIVE: case SO_REUSEADDR: - /*case SO_REUSEPORT: */ + case SO_REUSEPORT: case SO_BROADCAST: case SO_OOBINLINE: *mtod(m, int *) = so->so_options & optname; @@ -832,8 +1048,8 @@ sogetopt(so, level, optname, mp) } default: - (void)m_free(m); - return (ENOPROTOOPT); + (void)m_free(m); + return (ENOPROTOOPT); } *mp = m; return (0); @@ -850,5 +1066,9 @@ sohasoutofband(so) gsignal(-so->so_pgid, SIGURG); else if (so->so_pgid > 0 && (p = pfind(so->so_pgid)) != 0) psignal(p, SIGURG); - wakeup(so, 0); +#ifndef __REACTOS__ + selwakeup(so, &so->so_rcv.sb_sel); +#else + sorwakeup(so); +#endif }