mirror of
https://github.com/reactos/reactos.git
synced 2024-12-28 10:04:49 +00:00
Main changes: reimported uipc_socket.c which had lots of differences with
freebsd. Fixed: OskitTCPReceive. Now rely exclusively on uio as suggested. svn path=/trunk/; revision=10992
This commit is contained in:
parent
bb9e009623
commit
36cc9bb181
2 changed files with 319 additions and 97 deletions
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue