xref: /csrg-svn/sys/kern/uipc_pipe.c (revision 5021)
1*5021Sroot /*	uipc_pipe.c	4.8	81/11/22	*/
24904Swnj 
34904Swnj #include "../h/param.h"
44904Swnj #include "../h/dir.h"
54904Swnj #include "../h/user.h"
64904Swnj #include "../h/mbuf.h"
74904Swnj #include "../h/protosw.h"
84904Swnj #include "../h/socket.h"
94904Swnj #include "../h/socketvar.h"
104927Swnj #include "../net/inet_systm.h"		/* XXX */
114904Swnj 
124927Swnj int	piusrreq();
134904Swnj #define	PIPSIZ	4096
144904Swnj 
154904Swnj /*
164904Swnj  * Code for pipes and other loopback protocols (single machine, that is.)
174904Swnj  */
184904Swnj struct	protosw pipeproto = {
195010Swnj 	SOCK_STREAM,	PF_LOCAL,	0,		PR_CONNREQUIRED|PR_WANTRCVD,
204904Swnj 	0,		0,		0,		0,
214927Swnj 	piusrreq,	0,		0,
224904Swnj 	0,		0,		0,		0
234904Swnj };
244904Swnj 
254904Swnj /*
264904Swnj  * Connect a pipe from wso to rso.  The protocol control block
274904Swnj  * for a pipe is used to store a pointer to the matching socket.
284904Swnj  */
294927Swnj piconnect(wso, rso)
304904Swnj 	struct socket *wso, *rso;
314904Swnj {
324904Swnj 
334927Swnj COUNT(PICONNECT);
345017Swnj 	if (m_reserve(PIPSIZ*2/MSIZE) == 0) {
354904Swnj 		u.u_error = ENOBUFS;
364904Swnj 		return (0);
374904Swnj 	}
384904Swnj 	wso->so_proto = rso->so_proto = &pipeproto;
394904Swnj 	wso->so_pcb = (caddr_t)rso;
404904Swnj 	rso->so_pcb = (caddr_t)wso;
414981Swnj 	wso->so_snd.sb_hiwat = PIPSIZ;
424981Swnj 	wso->so_snd.sb_mbmax = 2*PIPSIZ;
434904Swnj 	wso->so_state |= SS_ISCONNECTED|SS_CANTRCVMORE;
444981Swnj 	rso->so_rcv.sb_hiwat = 0;
454981Swnj 	rso->so_rcv.sb_mbmax = 0;
464904Swnj 	rso->so_state |= SS_ISCONNECTED|SS_CANTSENDMORE;
474904Swnj 	return (1);
484904Swnj }
494904Swnj 
504904Swnj /*
514904Swnj  * User requests on pipes and other internally implemented
524904Swnj  * structures.
534904Swnj  */
544916Swnj /*ARGSUSED*/
554927Swnj piusrreq(so, req, m, addr)
564904Swnj 	struct socket *so;
574904Swnj 	int req;
584904Swnj 	struct mbuf *m;
594904Swnj 	caddr_t addr;
604904Swnj {
614904Swnj 	struct socket *so2 = (struct socket *)so->so_pcb;
624904Swnj 
634927Swnj COUNT(PIUSRREQ);
644904Swnj 	switch (req) {
654904Swnj 
664904Swnj 	case PRU_ATTACH:
675010Swnj 		break;
685010Swnj 
694904Swnj 	case PRU_DETACH:
705010Swnj 		so->so_pcb = 0;
714904Swnj 		break;
724904Swnj 
734904Swnj 	case PRU_CONNECT:
744927Swnj 	case PRU_ACCEPT:
754904Swnj 		return (EOPNOTSUPP);
764904Swnj 
774904Swnj 	case PRU_DISCONNECT:
784904Swnj 		if (so2 == 0)
794904Swnj 			return (ENOTCONN);
804904Swnj 		so->so_pcb = 0;
81*5021Sroot 		so2->so_pcb = 0;
824916Swnj 		soisdisconnected(so);
835010Swnj 		soisdisconnected(so2);
844904Swnj 		break;
854904Swnj 
864904Swnj 	case PRU_SHUTDOWN:
874927Swnj 		socantsendmore(so);
884927Swnj 		if (so2)
894927Swnj 			socantrcvmore(so2);
904904Swnj 		break;
914904Swnj 
924904Swnj 	case PRU_RCVD:
934981Swnj 		if (so2 == 0)
944981Swnj 			break;
954981Swnj #define	rcv (&so->so_rcv)
964981Swnj #define snd (&so2->so_snd)
975010Swnj /*
985010Swnj printf("pru_rcvd in: ");
995010Swnj psndrcv(snd, rcv);
1005010Swnj */
1014981Swnj 		/*
1024981Swnj 		 * Transfer resources back to send port
1034981Swnj 		 * and wakeup any waiting to write.
1044981Swnj 		 */
1054981Swnj 		snd->sb_mbmax += rcv->sb_mbmax - rcv->sb_mbcnt;
1064981Swnj 		rcv->sb_mbmax = rcv->sb_mbcnt;
1074981Swnj 		snd->sb_hiwat += rcv->sb_hiwat - rcv->sb_cc;
1084981Swnj 		rcv->sb_hiwat = rcv->sb_cc;
1095010Swnj /*
1105010Swnj printf("pru_rcvd out: ");
1115010Swnj psndrcv(snd, rcv);
1125010Swnj */
1134981Swnj 		sbwakeup(snd);
1144981Swnj #undef snd
1154981Swnj #undef rcv
1164904Swnj 		break;
1174904Swnj 
1184904Swnj 	case PRU_SEND:
1194981Swnj #define	rcv (&so2->so_rcv)
1204981Swnj #define	snd (&so->so_snd)
121*5021Sroot 		if (so2 == 0)
122*5021Sroot 			panic("pipe send");
1234981Swnj 		/*
1244981Swnj 		 * Send to paired receive port, and then
1254981Swnj 		 * give it enough resources to hold what it already has.
1264981Swnj 		 * Wake up readers.
1274981Swnj 		 */
1285010Swnj /*
1295010Swnj printf("pru_send in: ");
1305010Swnj psndrcv(snd, rcv);
1315010Swnj */
1324981Swnj 		sbappend(rcv, m);
1334981Swnj 		snd->sb_mbmax -= rcv->sb_mbcnt - rcv->sb_mbmax;
1344981Swnj 		rcv->sb_mbmax = rcv->sb_mbcnt;
1354981Swnj 		snd->sb_hiwat -= rcv->sb_cc - rcv->sb_hiwat;
1364981Swnj 		rcv->sb_hiwat = rcv->sb_cc;
1374981Swnj 		sbwakeup(rcv);
1385010Swnj /*
1395010Swnj printf("pru_send out: ");
1405010Swnj psndrcv(snd, rcv);
1415010Swnj */
1424981Swnj #undef snd
1434981Swnj #undef rcv
1444904Swnj 		break;
1454904Swnj 
1464904Swnj 	case PRU_ABORT:
1474904Swnj 		return (EOPNOTSUPP);
1484904Swnj 
1494904Swnj 	case PRU_CONTROL:
1504904Swnj 		return (EOPNOTSUPP);
1514904Swnj 
1524904Swnj 	default:
1534927Swnj 		panic("piusrreq");
1544904Swnj 	}
1554904Swnj 	return (0);
1564904Swnj }
1575010Swnj 
1585010Swnj psndrcv(snd, rcv)
1595010Swnj 	struct sockbuf *snd, *rcv;
1605010Swnj {
1615010Swnj 
1625010Swnj 	printf("snd: (cc,hiwat,mbcnt,mbmax) (%d,%d,%d,%d) ",
1635010Swnj 	    snd->sb_cc, snd->sb_hiwat, snd->sb_mbcnt, snd->sb_mbmax);
1645010Swnj 	printf("m %x, m->m_len %d\n", snd->sb_mb, snd->sb_mb ? snd->sb_mb->m_len : 0);
1655010Swnj 	printf("rcv: (cc,hiwat,mbcnt,mbmax) (%d,%d,%d,%d) ",
1665010Swnj 	    rcv->sb_cc, rcv->sb_hiwat, rcv->sb_mbcnt, rcv->sb_mbmax);
1675010Swnj 	printf("m %x, m->m_len %d\n", rcv->sb_mb, rcv->sb_mb ? rcv->sb_mb->m_len : 0);
1685010Swnj }
169