|
|
1.1 root 1: /*
2: * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
3: *
4: * @APPLE_LICENSE_HEADER_START@
5: *
6: * Portions Copyright (c) 1999 Apple Computer, Inc. All Rights
7: * Reserved. This file contains Original Code and/or Modifications of
8: * Original Code as defined in and that are subject to the Apple Public
9: * Source License Version 1.1 (the "License"). You may not use this file
10: * except in compliance with the License. Please obtain a copy of the
11: * License at http://www.apple.com/publicsource and read it before using
12: * this file.
13: *
14: * The Original Code and all software distributed under the License are
15: * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
16: * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
17: * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
18: * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the
19: * License for the specific language governing rights and limitations
20: * under the License.
21: *
22: * @APPLE_LICENSE_HEADER_END@
23: */
24:
25: /* Copyright (c) 1995 NeXT Computer, Inc. All Rights Reserved */
26: /*
27: * Copyright (c) 1982, 1986, 1988, 1990, 1993
28: * The Regents of the University of California. All rights reserved.
29: *
30: * Redistribution and use in source and binary forms, with or without
31: * modification, are permitted provided that the following conditions
32: * are met:
33: * 1. Redistributions of source code must retain the above copyright
34: * notice, this list of conditions and the following disclaimer.
35: * 2. Redistributions in binary form must reproduce the above copyright
36: * notice, this list of conditions and the following disclaimer in the
37: * documentation and/or other materials provided with the distribution.
38: * 3. All advertising materials mentioning features or use of this software
39: * must display the following acknowledgement:
40: * This product includes software developed by the University of
41: * California, Berkeley and its contributors.
42: * 4. Neither the name of the University nor the names of its contributors
43: * may be used to endorse or promote products derived from this software
44: * without specific prior written permission.
45: *
46: * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
47: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
48: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
49: * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
50: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
51: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
52: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
53: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
54: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
55: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
56: * SUCH DAMAGE.
57: *
58: * @(#)uipc_socket2.c 8.2 (Berkeley) 2/14/95
59: */
60:
61: #include <sys/param.h>
62: #include <sys/systm.h>
63: #include <sys/proc.h>
64: #include <sys/file.h>
65: #include <sys/buf.h>
66: #include <sys/malloc.h>
67: #include <sys/mbuf.h>
68: #include <sys/protosw.h>
69: #include <sys/socket.h>
70: #include <sys/socketvar.h>
71: #include <sys/ev.h>
72:
73: /*
74: * Primitive routines for operating on sockets and socket buffers
75: */
76:
77: /* strings for sleep message: */
78: char netio[] = "netio";
79: char netcon[] = "netcon";
80: char netcls[] = "netcls";
81:
82: u_long sb_max = SB_MAX; /* patchable */
83:
84: /*
85: * Procedures to manipulate state flags of socket
86: * and do appropriate wakeups. Normal sequence from the
87: * active (originating) side is that soisconnecting() is
88: * called during processing of connect() call,
89: * resulting in an eventual call to soisconnected() if/when the
90: * connection is established. When the connection is torn down
91: * soisdisconnecting() is called during processing of disconnect() call,
92: * and soisdisconnected() is called when the connection to the peer
93: * is totally severed. The semantics of these routines are such that
94: * connectionless protocols can call soisconnected() and soisdisconnected()
95: * only, bypassing the in-progress calls when setting up a ``connection''
96: * takes no time.
97: *
98: * From the passive side, a socket is created with
99: * two queues of sockets: so_q0 for connections in progress
100: * and so_q for connections already made and awaiting user acceptance.
101: * As a protocol is preparing incoming connections, it creates a socket
102: * structure queued on so_q0 by calling sonewconn(). When the connection
103: * is established, soisconnected() is called, and transfers the
104: * socket structure to so_q, making it available to accept().
105: *
106: * If a socket is closed with sockets on either
107: * so_q0 or so_q, these sockets are dropped.
108: *
109: * If higher level protocols are implemented in
110: * the kernel, the wakeups done here will sometimes
111: * cause software-interrupt process scheduling.
112: */
113:
114: void
115: soisconnecting(so)
116: register struct socket *so;
117: {
118:
119: so->so_state &= ~(SS_ISCONNECTED|SS_ISDISCONNECTING);
120: so->so_state |= SS_ISCONNECTING;
121: }
122:
123: void
124: soisconnected(so)
125: register struct socket *so;
126: {
127: register struct socket *head = so->so_head;
128:
129: so->so_state &= ~(SS_ISCONNECTING|SS_ISDISCONNECTING|SS_ISCONFIRMING);
130: so->so_state |= SS_ISCONNECTED;
131: if (head && soqremque(so, 0)) {
132: postevent(head,0,EV_RCONN);
133: soqinsque(head, so, 1);
134: sorwakeup(head);
135: wakeup((caddr_t)&head->so_timeo);
136: } else {
137: postevent(so,0,EV_WCONN);
138: wakeup((caddr_t)&so->so_timeo);
139: sorwakeup(so);
140: sowwakeup(so);
141: }
142: }
143:
144: void
145: soisdisconnecting(so)
146: register struct socket *so;
147: {
148:
149: so->so_state &= ~SS_ISCONNECTING;
150: so->so_state |= (SS_ISDISCONNECTING|SS_CANTRCVMORE|SS_CANTSENDMORE);
151: wakeup((caddr_t)&so->so_timeo);
152: sowwakeup(so);
153: sorwakeup(so);
154: }
155:
156: void
157: soisdisconnected(so)
158: register struct socket *so;
159: {
160:
161: so->so_state &= ~(SS_ISCONNECTING|SS_ISCONNECTED|SS_ISDISCONNECTING);
162: so->so_state |= (SS_CANTRCVMORE|SS_CANTSENDMORE);
163: wakeup((caddr_t)&so->so_timeo);
164: sowwakeup(so);
165: sorwakeup(so);
166: }
167:
168: /*
169: * When an attempt at a new connection is noted on a socket
170: * which accepts connections, sonewconn is called. If the
171: * connection is possible (subject to space constraints, etc.)
172: * then we allocate a new structure, propoerly linked into the
173: * data structure of the original socket, and return this.
174: * Connstatus may be 0, or SO_ISCONFIRMING, or SO_ISCONNECTED.
175: *
176: * Currently, sonewconn() is defined as sonewconn1() in socketvar.h
177: * to catch calls that are missing the (new) second parameter.
178: */
179: struct socket *
180: sonewconn1(head, connstatus)
181: register struct socket *head;
182: int connstatus;
183: {
184: register struct socket *so;
185: int soqueue = connstatus ? 1 : 0;
186:
187: if (head->so_qlen + head->so_q0len > 3 * head->so_qlimit / 2)
188: return ((struct socket *)0);
189:
190: #ifdef SOCKET_CACHE_ON
191: cached_sock_alloc(&so);
192: #else
193: MALLOC_ZONE(so, struct socket *, sizeof(*so), M_SOCKET, M_WAITOK);
194: bzero((caddr_t)so, sizeof(*so));
195: #endif
196:
197: if (so == NULL)
198: return ((struct socket *)0);
199: so->so_type = head->so_type;
200: so->so_options = head->so_options &~ SO_ACCEPTCONN;
201: so->so_linger = head->so_linger;
202: so->so_state = head->so_state | SS_NOFDREF;
203: so->so_proto = head->so_proto;
204: so->so_timeo = head->so_timeo;
205: so->so_pgid = head->so_pgid;
206: (void) soreserve(so, head->so_snd.sb_hiwat, head->so_rcv.sb_hiwat);
207: soqinsque(head, so, soqueue);
208: if ((*so->so_proto->pr_usrreq)(so, PRU_ATTACH,
209: (struct mbuf *)0, (struct mbuf *)0, (struct mbuf *)0)) {
210: (void) soqremque(so, soqueue);
211:
212: #ifdef SOCKET_CACHE_ON
213: cached_sock_free(so);
214: #else
215: (void) _FREE_ZONE((caddr_t)so, sizeof *so, M_SOCKET);
216: #endif
217: return ((struct socket *)0);
218: }
219: if (connstatus) {
220: sorwakeup(head);
221: wakeup((caddr_t)&head->so_timeo);
222: so->so_state |= connstatus;
223: }
224: so->so_rcv.sb_flags |= SB_RECV;
225: so->so_rcv.sb_so = so->so_snd.sb_so = so;
226: TAILQ_INIT(&so->so_evlist);
227: return (so);
228: }
229:
230: void
231: soqinsque(head, so, q)
232: register struct socket *head, *so;
233: int q;
234: {
235:
236: register struct socket **prev;
237: so->so_head = head;
238: if (q == 0) {
239: head->so_q0len++;
240: so->so_q0 = 0;
241: for (prev = &(head->so_q0); *prev; )
242: prev = &((*prev)->so_q0);
243: } else {
244: head->so_qlen++;
245: so->so_q = 0;
246: for (prev = &(head->so_q); *prev; )
247: prev = &((*prev)->so_q);
248: }
249: *prev = so;
250: }
251:
252: int
253: soqremque(so, q)
254: register struct socket *so;
255: int q;
256: {
257: register struct socket *head, *prev, *next;
258:
259: head = so->so_head;
260: prev = head;
261: for (;;) {
262: next = q ? prev->so_q : prev->so_q0;
263: if (next == so)
264: break;
265: if (next == 0)
266: return (0);
267: prev = next;
268: }
269: if (q == 0) {
270: prev->so_q0 = next->so_q0;
271: head->so_q0len--;
272: } else {
273: prev->so_q = next->so_q;
274: head->so_qlen--;
275: }
276: next->so_q0 = next->so_q = 0;
277: next->so_head = 0;
278: return (1);
279: }
280:
281: /*
282: * Socantsendmore indicates that no more data will be sent on the
283: * socket; it would normally be applied to a socket when the user
284: * informs the system that no more data is to be sent, by the protocol
285: * code (in case PRU_SHUTDOWN). Socantrcvmore indicates that no more data
286: * will be received, and will normally be applied to the socket by a
287: * protocol when it detects that the peer will send no more data.
288: * Data queued for reading in the socket may yet be read.
289: */
290:
291: void
292: socantsendmore(so)
293: struct socket *so;
294: {
295:
296: so->so_state |= SS_CANTSENDMORE;
297: sowwakeup(so);
298: }
299:
300: void
301: socantrcvmore(so)
302: struct socket *so;
303: {
304:
305: so->so_state |= SS_CANTRCVMORE;
306: sorwakeup(so);
307: }
308:
309: /*
310: * Wait for data to arrive at/drain from a socket buffer.
311: */
312: int
313: sbwait(sb)
314: struct sockbuf *sb;
315: {
316:
317: sb->sb_flags |= SB_WAIT;
318: return (tsleep((caddr_t)&sb->sb_cc,
319: (sb->sb_flags & SB_NOINTR) ? PSOCK : PSOCK | PCATCH, netio,
320: sb->sb_timeo));
321: }
322:
323: /*
324: * Lock a sockbuf already known to be locked;
325: * return any error returned from sleep (EINTR).
326: */
327: int
328: sb_lock(sb)
329: register struct sockbuf *sb;
330: {
331: int error;
332:
333: while (sb->sb_flags & SB_LOCK) {
334: sb->sb_flags |= SB_WANT;
335: if (error = tsleep((caddr_t)&sb->sb_flags,
336: (sb->sb_flags & SB_NOINTR) ? PSOCK : PSOCK|PCATCH,
337: netio, 0))
338: return (error);
339: }
340: sb->sb_flags |= SB_LOCK;
341: return (0);
342: }
343:
344: /*
345: * Wakeup processes waiting on a socket buffer.
346: * Do asynchronous notification via SIGIO
347: * if the socket has the SS_ASYNC flag set.
348: */
349: void
350: sowakeup(so, sb)
351: register struct socket *so;
352: register struct sockbuf *sb;
353: {
354: struct proc *p;
355:
356: selwakeup(&sb->sb_sel);
357: sb->sb_flags &= ~SB_SEL;
358: if (sb->sb_flags & SB_WAIT) {
359: sb->sb_flags &= ~SB_WAIT;
360: wakeup((caddr_t)&sb->sb_cc);
361: }
362: if (so->so_state & SS_ASYNC) {
363: if (so->so_pgid < 0)
364: gsignal(-so->so_pgid, SIGIO);
365: else if (so->so_pgid > 0 && (p = pfind(so->so_pgid)) != 0)
366: psignal(p, SIGIO);
367: }
368: }
369:
370: /*
371: * Socket buffer (struct sockbuf) utility routines.
372: *
373: * Each socket contains two socket buffers: one for sending data and
374: * one for receiving data. Each buffer contains a queue of mbufs,
375: * information about the number of mbufs and amount of data in the
376: * queue, and other fields allowing select() statements and notification
377: * on data availability to be implemented.
378: *
379: * Data stored in a socket buffer is maintained as a list of records.
380: * Each record is a list of mbufs chained together with the m_next
381: * field. Records are chained together with the m_nextpkt field. The upper
382: * level routine soreceive() expects the following conventions to be
383: * observed when placing information in the receive buffer:
384: *
385: * 1. If the protocol requires each message be preceded by the sender's
386: * name, then a record containing that name must be present before
387: * any associated data (mbuf's must be of type MT_SONAME).
388: * 2. If the protocol supports the exchange of ``access rights'' (really
389: * just additional data associated with the message), and there are
390: * ``rights'' to be received, then a record containing this data
391: * should be present (mbuf's must be of type MT_RIGHTS).
392: * 3. If a name or rights record exists, then it must be followed by
393: * a data record, perhaps of zero length.
394: *
395: * Before using a new socket structure it is first necessary to reserve
396: * buffer space to the socket, by calling sbreserve(). This should commit
397: * some of the available buffer space in the system buffer pool for the
398: * socket (currently, it does nothing but enforce limits). The space
399: * should be released by calling sbrelease() when the socket is destroyed.
400: */
401:
402: int
403: soreserve(so, sndcc, rcvcc)
404: register struct socket *so;
405: u_long sndcc, rcvcc;
406: {
407:
408: if (sbreserve(&so->so_snd, sndcc) == 0)
409: goto bad;
410: if (sbreserve(&so->so_rcv, rcvcc) == 0)
411: goto bad2;
412: if (so->so_rcv.sb_lowat == 0)
413: so->so_rcv.sb_lowat = 1;
414: if (so->so_snd.sb_lowat == 0)
415: so->so_snd.sb_lowat = MCLBYTES;
416: if (so->so_snd.sb_lowat > so->so_snd.sb_hiwat)
417: so->so_snd.sb_lowat = so->so_snd.sb_hiwat;
418: return (0);
419: bad2:
420: sbrelease(&so->so_snd);
421: bad:
422: return (ENOBUFS);
423: }
424:
425: /*
426: * Allot mbufs to a sockbuf.
427: * Attempt to scale mbmax so that mbcnt doesn't become limiting
428: * if buffering efficiency is near the normal case.
429: */
430: int
431: sbreserve(sb, cc)
432: struct sockbuf *sb;
433: u_long cc;
434: {
435:
436: if (cc > sb_max * MCLBYTES / (MSIZE + MCLBYTES))
437: return (0);
438: sb->sb_hiwat = cc;
439: sb->sb_mbmax = min(cc * 2, sb_max);
440: if (sb->sb_lowat > sb->sb_hiwat)
441: sb->sb_lowat = sb->sb_hiwat;
442: return (1);
443: }
444:
445: /*
446: * Free mbufs held by a socket, and reserved mbuf space.
447: */
448: void
449: sbrelease(sb)
450: struct sockbuf *sb;
451: {
452:
453: sbflush(sb);
454: sb->sb_hiwat = sb->sb_mbmax = 0;
455:
456: {
457: int oldpri = splimp();
458: selthreadclear(&sb->sb_sel);
459: splx(oldpri);
460: }
461: }
462:
463: /*
464: * Routines to add and remove
465: * data from an mbuf queue.
466: *
467: * The routines sbappend() or sbappendrecord() are normally called to
468: * append new mbufs to a socket buffer, after checking that adequate
469: * space is available, comparing the function sbspace() with the amount
470: * of data to be added. sbappendrecord() differs from sbappend() in
471: * that data supplied is treated as the beginning of a new record.
472: * To place a sender's address, optional access rights, and data in a
473: * socket receive buffer, sbappendaddr() should be used. To place
474: * access rights and data in a socket receive buffer, sbappendrights()
475: * should be used. In either case, the new data begins a new record.
476: * Note that unlike sbappend() and sbappendrecord(), these routines check
477: * for the caller that there will be enough space to store the data.
478: * Each fails if there is not enough space, or if it cannot find mbufs
479: * to store additional information in.
480: *
481: * Reliable protocols may use the socket send buffer to hold data
482: * awaiting acknowledgement. Data is normally copied from a socket
483: * send buffer in a protocol with m_copy for output to a peer,
484: * and then removing the data from the socket buffer with sbdrop()
485: * or sbdroprecord() when the data is acknowledged by the peer.
486: */
487:
488: /*
489: * Append mbuf chain m to the last record in the
490: * socket buffer sb. The additional space associated
491: * the mbuf chain is recorded in sb. Empty mbufs are
492: * discarded and mbufs are compacted where possible.
493: */
494: void
495: sbappend(sb, m)
496: struct sockbuf *sb;
497: struct mbuf *m;
498: {
499: register struct mbuf *n;
500:
501: if (m == 0)
502: return;
503: if (n = sb->sb_mb) {
504: while (n->m_nextpkt)
505: n = n->m_nextpkt;
506: do {
507: if (n->m_flags & M_EOR) {
508: sbappendrecord(sb, m); /* XXXXXX!!!! */
509: return;
510: }
511: } while (n->m_next && (n = n->m_next));
512: }
513: sbcompress(sb, m, n);
514: }
515:
516: #ifdef SOCKBUF_DEBUG
517: void
518: sbcheck(sb)
519: register struct sockbuf *sb;
520: {
521: register struct mbuf *m;
522: register int len = 0, mbcnt = 0;
523:
524: for (m = sb->sb_mb; m; m = m->m_next) {
525: len += m->m_len;
526: mbcnt += MSIZE;
527: if (m->m_flags & M_EXT)
528: mbcnt += m->m_ext.ext_size;
529: if (m->m_nextpkt)
530: panic("sbcheck nextpkt");
531: }
532: if (len != sb->sb_cc || mbcnt != sb->sb_mbcnt) {
533: printf("cc %d != %d || mbcnt %d != %d\n", len, sb->sb_cc,
534: mbcnt, sb->sb_mbcnt);
535: panic("sbcheck");
536: }
537: }
538: #endif
539:
540: /*
541: * As above, except the mbuf chain
542: * begins a new record.
543: */
544: void
545: sbappendrecord(sb, m0)
546: register struct sockbuf *sb;
547: register struct mbuf *m0;
548: {
549: register struct mbuf *m;
550:
551: if (m0 == 0)
552: return;
553: if (m = sb->sb_mb)
554: while (m->m_nextpkt)
555: m = m->m_nextpkt;
556: /*
557: * Put the first mbuf on the queue.
558: * Note this permits zero length records.
559: */
560: sballoc(sb, m0);
561: if (m)
562: m->m_nextpkt = m0;
563: else
564: sb->sb_mb = m0;
565: m = m0->m_next;
566: m0->m_next = 0;
567: if (m && (m0->m_flags & M_EOR)) {
568: m0->m_flags &= ~M_EOR;
569: m->m_flags |= M_EOR;
570: }
571: sbcompress(sb, m, m0);
572: }
573:
574: /*
575: * As above except that OOB data
576: * is inserted at the beginning of the sockbuf,
577: * but after any other OOB data.
578: */
579: void
580: sbinsertoob(sb, m0)
581: register struct sockbuf *sb;
582: register struct mbuf *m0;
583: {
584: register struct mbuf *m;
585: register struct mbuf **mp;
586:
587: if (m0 == 0)
588: return;
589: for (mp = &sb->sb_mb; m = *mp; mp = &((*mp)->m_nextpkt)) {
590: again:
591: switch (m->m_type) {
592:
593: case MT_OOBDATA:
594: continue; /* WANT next train */
595:
596: case MT_CONTROL:
597: if (m = m->m_next)
598: goto again; /* inspect THIS train further */
599: }
600: break;
601: }
602: /*
603: * Put the first mbuf on the queue.
604: * Note this permits zero length records.
605: */
606: sballoc(sb, m0);
607: m0->m_nextpkt = *mp;
608: *mp = m0;
609: m = m0->m_next;
610: m0->m_next = 0;
611: if (m && (m0->m_flags & M_EOR)) {
612: m0->m_flags &= ~M_EOR;
613: m->m_flags |= M_EOR;
614: }
615: sbcompress(sb, m, m0);
616: }
617:
618: /*
619: * Append address and data, and optionally, control (ancillary) data
620: * to the receive queue of a socket. If present,
621: * m0 must include a packet header with total length.
622: * Returns 0 if no space in sockbuf or insufficient mbufs.
623: */
624: int
625: sbappendaddr(sb, asa, m0, control)
626: register struct sockbuf *sb;
627: struct sockaddr *asa;
628: struct mbuf *m0, *control;
629: {
630: register struct mbuf *m, *n;
631: int space = asa->sa_len;
632:
633: if (m0 && (m0->m_flags & M_PKTHDR) == 0)
634: panic("sbappendaddr");
635: if (m0)
636: space += m0->m_pkthdr.len;
637: for (n = control; n; n = n->m_next) {
638: space += n->m_len;
639: if (n->m_next == 0) /* keep pointer to last control buf */
640: break;
641: }
642: if (space > sbspace(sb))
643: return (0);
644: if (asa->sa_len > MLEN)
645: return (0);
646: MGET(m, M_DONTWAIT, MT_SONAME);
647: if (m == 0)
648: return (0);
649: m->m_len = asa->sa_len;
650: bcopy((caddr_t)asa, mtod(m, caddr_t), asa->sa_len);
651: if (n)
652: n->m_next = m0; /* concatenate data to control */
653: else
654: control = m0;
655: m->m_next = control;
656: for (n = m; n; n = n->m_next)
657: sballoc(sb, n);
658: if (n = sb->sb_mb) {
659: while (n->m_nextpkt)
660: n = n->m_nextpkt;
661: n->m_nextpkt = m;
662: } else
663: sb->sb_mb = m;
664: postevent(0,sb,EV_RWBYTES);
665: return (1);
666: }
667:
668: int
669: sbappendcontrol(sb, m0, control)
670: struct sockbuf *sb;
671: struct mbuf *m0, *control;
672: {
673: register struct mbuf *m, *n;
674: int space = 0;
675:
676: if (control == 0)
677: panic("sbappendcontrol");
678: for (m = control; ; m = m->m_next) {
679: space += m->m_len;
680: if (m->m_next == 0)
681: break;
682: }
683: n = m; /* save pointer to last control buffer */
684: for (m = m0; m; m = m->m_next)
685: space += m->m_len;
686: if (space > sbspace(sb))
687: return (0);
688: n->m_next = m0; /* concatenate data to control */
689: for (m = control; m; m = m->m_next)
690: sballoc(sb, m);
691: if (n = sb->sb_mb) {
692: while (n->m_nextpkt)
693: n = n->m_nextpkt;
694: n->m_nextpkt = control;
695: } else
696: sb->sb_mb = control;
697: postevent(0,sb,EV_RWBYTES);
698: return (1);
699: }
700:
701: /*
702: * Compress mbuf chain m into the socket
703: * buffer sb following mbuf n. If n
704: * is null, the buffer is presumed empty.
705: */
706: void
707: sbcompress(sb, m, n)
708: register struct sockbuf *sb;
709: register struct mbuf *m, *n;
710: {
711: register int eor = 0;
712: register struct mbuf *o;
713:
714: while (m) {
715: eor |= m->m_flags & M_EOR;
716: if (m->m_len == 0 &&
717: (eor == 0 ||
718: (((o = m->m_next) || (o = n)) &&
719: o->m_type == m->m_type))) {
720: m = m_free(m);
721: continue;
722: }
723: if (n && (n->m_flags & (M_EXT | M_EOR)) == 0 &&
724: (n->m_data + n->m_len + m->m_len) < &n->m_dat[MLEN] &&
725: n->m_type == m->m_type) {
726: bcopy(mtod(m, caddr_t), mtod(n, caddr_t) + n->m_len,
727: (unsigned)m->m_len);
728: n->m_len += m->m_len;
729: sb->sb_cc += m->m_len;
730: m = m_free(m);
731: continue;
732: }
733: if (n)
734: n->m_next = m;
735: else
736: sb->sb_mb = m;
737: sballoc(sb, m);
738: n = m;
739: m->m_flags &= ~M_EOR;
740: m = m->m_next;
741: n->m_next = 0;
742: }
743: if (eor) {
744: if (n)
745: n->m_flags |= eor;
746: else
747: printf("semi-panic: sbcompress\n");
748: }
749: postevent(0,sb, EV_RWBYTES);
750: }
751:
752: /*
753: * Free all mbufs in a sockbuf.
754: * Check that all resources are reclaimed.
755: */
756: void
757: sbflush(sb)
758: register struct sockbuf *sb;
759: {
760:
761: if (sb->sb_flags & SB_LOCK)
762: panic("sbflush");
763: while (sb->sb_mbcnt)
764: sbdrop(sb, (int)sb->sb_cc);
765: if (sb->sb_cc || sb->sb_mb)
766: panic("sbflush 2");
767: postevent(0, sb, EV_RWBYTES);
768: }
769:
770: /*
771: * Drop data from (the front of) a sockbuf.
772: */
773: void
774: sbdrop(sb, len)
775: register struct sockbuf *sb;
776: register int len;
777: {
778: register struct mbuf *m, *mn;
779: struct mbuf *next;
780:
781: next = (m = sb->sb_mb) ? m->m_nextpkt : 0;
782: while (len > 0) {
783: if (m == 0) {
784: if (next == 0)
785: panic("sbdrop");
786: m = next;
787: next = m->m_nextpkt;
788: continue;
789: }
790: if (m->m_len > len) {
791: m->m_len -= len;
792: m->m_data += len;
793: sb->sb_cc -= len;
794: break;
795: }
796: len -= m->m_len;
797: sbfree(sb, m);
798: MFREE(m, mn);
799: m = mn;
800: }
801: while (m && m->m_len == 0) {
802: sbfree(sb, m);
803: MFREE(m, mn);
804: m = mn;
805: }
806: if (m) {
807: sb->sb_mb = m;
808: m->m_nextpkt = next;
809: } else
810: sb->sb_mb = next;
811: postevent(0, sb, EV_RWBYTES);
812: }
813:
814: /*
815: * Drop a record off the front of a sockbuf
816: * and move the next record to the front.
817: */
818: void
819: sbdroprecord(sb)
820: register struct sockbuf *sb;
821: {
822: register struct mbuf *m, *mn;
823:
824: m = sb->sb_mb;
825: if (m) {
826: sb->sb_mb = m->m_nextpkt;
827: do {
828: sbfree(sb, m);
829: MFREE(m, mn);
830: } while (m = mn);
831: }
832: postevent(0, sb, EV_RWBYTES);
833: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.