uipc_sock2.c
上传用户:nvosite88
上传日期:2007-01-17
资源大小:4983k
文件大小:26k
源码类别:

VxWorks

开发平台:

C/C++

  1. /* uipc_sock2.c - uipc primitive socket routines */
  2. /* Copyright 1984 - 2001 Wind River Systems, Inc. */
  3. #include "copyright_wrs.h"
  4. /*
  5.  * Copyright (c) 1982, 1986, 1988, 1990, 1993
  6.  * The Regents of the University of California.  All rights reserved.
  7.  *
  8.  * Redistribution and use in source and binary forms, with or without
  9.  * modification, are permitted provided that the following conditions
  10.  * are met:
  11.  * 1. Redistributions of source code must retain the above copyright
  12.  *    notice, this list of conditions and the following disclaimer.
  13.  * 2. Redistributions in binary form must reproduce the above copyright
  14.  *    notice, this list of conditions and the following disclaimer in the
  15.  *    documentation and/or other materials provided with the distribution.
  16.  * 3. All advertising materials mentioning features or use of this software
  17.  *    must display the following acknowledgement:
  18.  * This product includes software developed by the University of
  19.  * California, Berkeley and its contributors.
  20.  * 4. Neither the name of the University nor the names of its contributors
  21.  *    may be used to endorse or promote products derived from this software
  22.  *    without specific prior written permission.
  23.  *
  24.  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
  25.  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  26.  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  27.  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
  28.  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  29.  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  30.  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  31.  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  32.  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  33.  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  34.  * SUCH DAMAGE.
  35.  *
  36.  * @(#)uipc_socket2.c 8.2 (Berkeley) 2/14/95
  37.  */
  38. /*
  39. modification history
  40. --------------------
  41. 01g,15oct01,rae  merge from truestack ver 01m, base 01e (SPR #34005 etc.)
  42. 01f,12nov98,n_s  fixed sbcompress to work with netBufLib buffers. spr # 22966
  43. 01e,19sep97,vin  changed m_ext.ext_size to m_extSize
  44. 01d,11aug97,vin  adjusted sb_max to 5 *cc and low water mark to CL_SIZE_64
  45. 01c,03dec96,vin  changed calloc(..) to MALLOC(..) and free(..) to FREE(..)
  46.  to use network buffers.
  47. 01b,22nov96,vin  added cluster support, replace m_get(..) with mBufClGet(..). 
  48. 01a,03mar96,vin  created from BSD4.4lite2. Integrated with 02t of uipc_sock2.c
  49. */
  50. /*
  51. DESCRIPTION
  52. */
  53. #ifdef BSDUNIX44 
  54. #include <sys/param.h>
  55. #include <sys/systm.h>
  56. #include <sys/proc.h>
  57. #include <sys/file.h>
  58. #include <sys/buf.h>
  59. #include <sys/malloc.h>
  60. #include <sys/mbuf.h>
  61. #include <sys/protosw.h>
  62. #include <sys/socket.h>
  63. #include <sys/socketvar.h>
  64. #else
  65. #include "vxWorks.h"
  66. #include "semLib.h"
  67. #include "memLib.h"
  68. #include "errno.h"
  69. #include "net/mbuf.h"
  70. #include "net/protosw.h"
  71. #include "sys/socket.h"
  72. #include "net/socketvar.h"
  73. #include "net/systm.h"
  74. #include "net/unixLib.h"
  75. #include "stdio.h"
  76. #endif /* BSDUNIX44 */
  77. #ifdef VIRTUAL_STACK
  78. #include "netinet/vsLib.h"
  79. #endif    /* VIRTUAL_STACK */
  80. #ifdef WV_INSTRUMENTATION
  81. #ifdef INCLUDE_WVNET
  82. #include "wvNetLib.h"
  83. #endif
  84. #endif
  85. #ifdef WV_INSTRUMENTATION
  86. #ifdef INCLUDE_WVNET
  87.     /* Set common fields of event identifiers for this module. */
  88. LOCAL UCHAR wvNetModuleId = WV_NET_UISOCK2_MODULE; /* Value for uipc_sock2.c */
  89. LOCAL UCHAR wvNetLocalFilter = WV_NET_NONE;     /* Available event filter */
  90. LOCAL ULONG wvNetEventId;       /* Event identifier: see wvNetLib.h */
  91. #endif    /* INCLUDE_WVNET */
  92. #endif
  93. /* globals */
  94. VOIDFUNCPTR sowakeupHook = NULL; /* user callback in sowakeup() */
  95. #ifndef VIRTUAL_STACK
  96. u_long sb_max = SB_MAX; /* patchable max socket buffer size*/
  97. #endif    /* VIRTUAL_STACK */
  98. /*
  99.  * Primitive routines for operating on sockets and socket buffers
  100.  */
  101. /*
  102.  * Procedures to manipulate state flags of socket
  103.  * and do appropriate wakeups.  Normal sequence from the
  104.  * active (originating) side is that soisconnecting() is
  105.  * called during processing of connect() call,
  106.  * resulting in an eventual call to soisconnected() if/when the
  107.  * connection is established.  When the connection is torn down
  108.  * soisdisconnecting() is called during processing of disconnect() call,
  109.  * and soisdisconnected() is called when the connection to the peer
  110.  * is totally severed.  The semantics of these routines are such that
  111.  * connectionless protocols can call soisconnected() and soisdisconnected()
  112.  * only, bypassing the in-progress calls when setting up a ``connection''
  113.  * takes no time.
  114.  *
  115.  * From the passive side, a socket is created with
  116.  * two queues of sockets: so_q0 for connections in progress
  117.  * and so_q for connections already made and awaiting user acceptance.
  118.  * As a protocol is preparing incoming connections, it creates a socket
  119.  * structure queued on so_q0 by calling sonewconn().  When the connection
  120.  * is established, soisconnected() is called, and transfers the
  121.  * socket structure to so_q, making it available to accept().
  122.  * 
  123.  * If a socket is closed with sockets on either
  124.  * so_q0 or so_q, these sockets are dropped.
  125.  *
  126.  * If higher level protocols are implemented in
  127.  * the kernel, the wakeups done here will sometimes
  128.  * cause software-interrupt process scheduling.
  129.  */
  130. void
  131. soisconnecting(so)
  132. register struct socket *so;
  133. {
  134. so->so_state &= ~(SS_ISCONNECTED|SS_ISDISCONNECTING);
  135. so->so_state |= SS_ISCONNECTING;
  136. }
  137. void
  138. soisconnected(so)
  139. register struct socket *so;
  140. {
  141. register struct socket *head = so->so_head;
  142. so->so_state &= ~(SS_ISCONNECTING|SS_ISDISCONNECTING|SS_ISCONFIRMING);
  143. so->so_state |= SS_ISCONNECTED;
  144. if (head && soqremque(so, 0)) {
  145. soqinsque(head, so, 1);
  146. sorwakeup(head);
  147. wakeup(head->so_timeoSem);
  148. } else {
  149.         wakeup(so->so_timeoSem);
  150. sorwakeup(so);
  151. sowwakeup(so);
  152. }
  153. }
  154. void
  155. soisdisconnecting(so)
  156. register struct socket *so;
  157. {
  158. so->so_state &= ~SS_ISCONNECTING;
  159. so->so_state |= (SS_ISDISCONNECTING|SS_CANTRCVMORE|SS_CANTSENDMORE);
  160. wakeup(so->so_timeoSem);
  161. sowwakeup(so);
  162. sorwakeup(so);
  163. }
  164. void
  165. soisdisconnected(so)
  166. register struct socket *so;
  167. {
  168. so->so_state &= ~(SS_ISCONNECTING|SS_ISCONNECTED|SS_ISDISCONNECTING);
  169. so->so_state |= (SS_CANTRCVMORE|SS_CANTSENDMORE);
  170.         if (so->so_timeoSem)
  171.     wakeup(so->so_timeoSem);
  172. sowwakeup(so);
  173. sorwakeup(so);
  174. }
  175. /*
  176.  * When an attempt at a new connection is noted on a socket
  177.  * which accepts connections, sonewconn is called.  If the
  178.  * connection is possible (subject to space constraints, etc.)
  179.  * then we allocate a new structure, propoerly linked into the
  180.  * data structure of the original socket, and return this.
  181.  * Connstatus may be 0, or SO_ISCONFIRMING, or SO_ISCONNECTED.
  182.  *
  183.  * Currently, sonewconn() is defined as sonewconn1() in socketvar.h
  184.  * to catch calls that are missing the (new) second parameter.
  185.  */
  186. struct socket *
  187. sonewconn1(head, connstatus)
  188. register struct socket *head;
  189. int connstatus;
  190. {
  191. register struct socket *so;
  192. int soqueue = connstatus ? 1 : 0;
  193. if (head->so_qlen + head->so_q0len > 3 * head->so_qlimit / 2)
  194. return ((struct socket *)0);
  195.         MALLOC(so, struct socket *, sizeof(*so), MT_SOCKET, M_DONTWAIT);
  196.         if (so == NULL)
  197.                 return ((struct socket *)0);
  198.         bzero((caddr_t)so, sizeof(*so));
  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_pgrp = head->so_pgrp;
  206. /* initialize the socket's semaphores */
  207. so->so_timeoSem = semBCreate (SEM_Q_PRIORITY, SEM_EMPTY);
  208.         if (so->so_timeoSem == NULL)
  209.             {
  210.             FREE(so, MT_SOCKET);
  211.             return ((struct socket *)0);
  212.             }
  213. so->so_rcv.sb_Sem = semBCreate (SEM_Q_PRIORITY, SEM_EMPTY);
  214.         if (so->so_rcv.sb_Sem == NULL)
  215.             {
  216.             semDelete (so->so_timeoSem);
  217.             FREE(so, MT_SOCKET);
  218.             return ((struct socket *)0);
  219.             }
  220. so->so_snd.sb_Sem = semBCreate (SEM_Q_PRIORITY, SEM_EMPTY);
  221.         if (so->so_snd.sb_Sem == NULL)
  222.             {
  223.             semDelete (so->so_timeoSem);
  224.             semDelete (so->so_rcv.sb_Sem);
  225.             FREE(so, MT_SOCKET);
  226.             return ((struct socket *)0);
  227.             }
  228.         /* initialize the select stuff */
  229. selWakeupListInit (&so->so_selWakeupList);
  230.  
  231.         so->selectFlag = TRUE;
  232. (void) soreserve(so, head->so_snd.sb_hiwat, head->so_rcv.sb_hiwat);
  233. soqinsque(head, so, soqueue);
  234. if ((*so->so_proto->pr_usrreq)(so, PRU_ATTACH,
  235.     (struct mbuf *)0, (struct mbuf *)0, (struct mbuf *)0)) {
  236. (void) soqremque(so, soqueue);
  237. semDelete (so->so_timeoSem);
  238. semDelete (so->so_rcv.sb_Sem);
  239. semDelete (so->so_snd.sb_Sem);
  240. selWakeupListTerm (&so->so_selWakeupList);
  241. FREE(so, MT_SOCKET);
  242. return ((struct socket *)0);
  243. }
  244. if (connstatus) {
  245. sorwakeup(head);
  246. wakeup(head->so_timeoSem);
  247. so->so_state |= connstatus;
  248. }
  249. return (so);
  250. }
  251. void
  252. soqinsque(head, so, q)
  253. register struct socket *head, *so;
  254. int q;
  255. {
  256. register struct socket **prev;
  257. so->so_head = head;
  258. if (q == 0) {
  259. head->so_q0len++;
  260. so->so_q0 = 0;
  261. for (prev = &(head->so_q0); *prev; )
  262. prev = &((*prev)->so_q0);
  263. } else {
  264. head->so_qlen++;
  265. so->so_q = 0;
  266. for (prev = &(head->so_q); *prev; )
  267. prev = &((*prev)->so_q);
  268. }
  269. *prev = so;
  270. }
  271. int
  272. soqremque(so, q)
  273. register struct socket *so;
  274. int q;
  275. {
  276. register struct socket *head, *prev, *next;
  277. head = so->so_head;
  278. prev = head;
  279. for (;;) {
  280. next = q ? prev->so_q : prev->so_q0;
  281. if (next == so)
  282. break;
  283. if (next == 0)
  284. return (0);
  285. prev = next;
  286. }
  287. if (q == 0) {
  288. prev->so_q0 = next->so_q0;
  289. head->so_q0len--;
  290. } else {
  291. prev->so_q = next->so_q;
  292. head->so_qlen--;
  293. }
  294. next->so_q0 = next->so_q = 0;
  295. next->so_head = 0;
  296. return (1);
  297. }
  298. /*
  299.  * Socantsendmore indicates that no more data will be sent on the
  300.  * socket; it would normally be applied to a socket when the user
  301.  * informs the system that no more data is to be sent, by the protocol
  302.  * code (in case PRU_SHUTDOWN).  Socantrcvmore indicates that no more data
  303.  * will be received, and will normally be applied to the socket by a
  304.  * protocol when it detects that the peer will send no more data.
  305.  * Data queued for reading in the socket may yet be read.
  306.  */
  307. void
  308. socantsendmore(so)
  309. struct socket *so;
  310. {
  311. so->so_state |= SS_CANTSENDMORE;
  312. sowwakeup(so);
  313. }
  314. void
  315. socantrcvmore(so)
  316. struct socket *so;
  317. {
  318. so->so_state |= SS_CANTRCVMORE;
  319. sorwakeup(so);
  320. }
  321. /*
  322.  * Queue a process for a select on a socket buffer.
  323.  */
  324. void
  325. sbselqueue(so, sb, wakeupNode)
  326. struct socket *so;
  327.         struct sockbuf *sb;
  328. SEL_WAKEUP_NODE *wakeupNode;
  329. {
  330. if (selNodeAdd (&so->so_selWakeupList, wakeupNode) == ERROR)
  331.     return;
  332. /* this is race free ONLY if we assume we're at splnet - rdc */
  333. sb->sb_sel = (struct proc *) 1;
  334. }
  335. void
  336. sbseldequeue(so, sb, wakeupNode)
  337.     struct socket *so;
  338.     struct sockbuf *sb;
  339.     SEL_WAKEUP_NODE *wakeupNode;
  340.     {
  341.     selNodeDelete (&so->so_selWakeupList, wakeupNode);
  342.     /* this is race free ONLY if we assume we're at splnet - rdc */
  343.     if (selWakeupListLen (&so->so_selWakeupList) == 0)
  344. sb->sb_sel = (struct proc *) 0;
  345.     }
  346. /*
  347.  * Wait for data to arrive at/drain from a socket buffer.
  348.  */
  349. void sbwait
  350.     (
  351.     struct sockbuf *sb
  352.     )
  353.     {
  354.     sb->sb_want++;
  355.     sb->sb_flags |= SB_WAIT;
  356. #ifdef WV_INSTRUMENTATION
  357. #ifdef INCLUDE_WVNET    /* WV_NET_INFO event */
  358.     WV_NET_MARKER_0 (NET_CORE_EVENT, WV_NET_INFO, 53, 5,
  359.                      WV_NETEVENT_SBWAIT_SLEEP)
  360. #endif  /* INCLUDE_WVNET */
  361. #endif
  362.     ksleep (sb->sb_Sem);
  363.     }
  364. /* 
  365.  * Lock a sockbuf already known to be locked;
  366.  * return any error returned from sleep (EINTR).
  367.  */
  368. int
  369. sb_lock(sb)
  370. register struct sockbuf *sb;
  371. {
  372. while (sb->sb_flags & SB_LOCK) {
  373. sb->sb_flags |= SB_WANT;
  374. ksleep(sb->sb_Sem);
  375. }
  376. sb->sb_flags |= SB_LOCK;
  377. return (0);
  378. }
  379. /*
  380.  * Wakeup processes waiting on a socket buffer.
  381.  */
  382. void sbwakeup
  383.     (
  384.     struct socket *so,
  385.     register struct sockbuf *sb,
  386.     SELECT_TYPE wakeupType
  387.     )
  388.     {
  389. #ifdef WV_INSTRUMENTATION
  390. #ifdef INCLUDE_WVNET    /* WV_NET_INFO event */
  391.     WV_NET_MARKER_2 (NET_CORE_EVENT, WV_NET_INFO, 54, 6, 
  392.                      WV_NETEVENT_SBWAKEUP_START, so->so_fd, wakeupType)
  393. #endif  /* INCLUDE_WVNET */
  394. #endif
  395.     if (sb->sb_want > 0)
  396.         {
  397.         sb->sb_want--;
  398.         if (sb->sb_Sem)
  399.             wakeup (sb->sb_Sem);
  400.         }
  401.     else
  402.         sb->sb_want = 0;
  403.     if (sb->sb_sel)
  404.         {
  405.         /* 
  406.          * Wake up everybody on selectTask list.
  407.          * (Assume this is running in netTask context).
  408.          */
  409.         if (so->selectFlag)
  410.             selWakeupAll (&so->so_selWakeupList, wakeupType);
  411.         }
  412.     }
  413. /*
  414.  * Wakeup socket readers and writers.
  415.  */
  416. /* ARGSUSED */
  417. void sowakeup(so, sb, wakeupType)
  418. struct socket *so;
  419. struct sockbuf *sb;
  420. SELECT_TYPE wakeupType;
  421. {
  422.         sbwakeup(so, sb, wakeupType);
  423. /* user callback, instead of full signals implementation */
  424. if (sowakeupHook != NULL)
  425.      (*sowakeupHook) (so, wakeupType);
  426. #ifdef BERKELEY
  427. /* XXX one day asynchronous IO will work... -gae */
  428.         register struct proc *p;
  429.         if (so->so_state & SS_ASYNC) {
  430.                 if (so->so_pgrp < 0)
  431.                         gsignal(-so->so_pgrp, SIGIO);
  432.                 else if (so->so_pgrp > 0 && (p = pfind(so->so_pgrp)) != 0)
  433.                         psignal(p, SIGIO);
  434.         }
  435. #endif /* BERKELEY */
  436. }
  437. /*
  438.  * Socket buffer (struct sockbuf) utility routines.
  439.  *
  440.  * Each socket contains two socket buffers: one for sending data and
  441.  * one for receiving data.  Each buffer contains a queue of mbufs,
  442.  * information about the number of mbufs and amount of data in the
  443.  * queue, and other fields allowing select() statements and notification
  444.  * on data availability to be implemented.
  445.  *
  446.  * Data stored in a socket buffer is maintained as a list of records.
  447.  * Each record is a list of mbufs chained together with the m_next
  448.  * field.  Records are chained together with the m_nextpkt field. The upper
  449.  * level routine soreceive() expects the following conventions to be
  450.  * observed when placing information in the receive buffer:
  451.  *
  452.  * 1. If the protocol requires each message be preceded by the sender's
  453.  *    name, then a record containing that name must be present before
  454.  *    any associated data (mbuf's must be of type MT_SONAME).
  455.  * 2. If the protocol supports the exchange of ``access rights'' (really
  456.  *    just additional data associated with the message), and there are
  457.  *    ``rights'' to be received, then a record containing this data
  458.  *    should be present (mbuf's must be of type MT_RIGHTS).
  459.  * 3. If a name or rights record exists, then it must be followed by
  460.  *    a data record, perhaps of zero length.
  461.  *
  462.  * Before using a new socket structure it is first necessary to reserve
  463.  * buffer space to the socket, by calling sbreserve().  This should commit
  464.  * some of the available buffer space in the system buffer pool for the
  465.  * socket (currently, it does nothing but enforce limits).  The space
  466.  * should be released by calling sbrelease() when the socket is destroyed.
  467.  */
  468. int
  469. soreserve(so, sndcc, rcvcc)
  470. register struct socket *so;
  471. u_long sndcc, rcvcc;
  472. {
  473. if (sbreserve(&so->so_snd, sndcc) == 0)
  474. goto bad;
  475. if (sbreserve(&so->so_rcv, rcvcc) == 0)
  476. goto bad2;
  477. if (so->so_rcv.sb_lowat == 0)
  478. so->so_rcv.sb_lowat = 1;
  479. if (so->so_snd.sb_lowat == 0)
  480. so->so_snd.sb_lowat = CL_SIZE_64;
  481. if (so->so_snd.sb_lowat > so->so_snd.sb_hiwat)
  482. so->so_snd.sb_lowat = so->so_snd.sb_hiwat;
  483. return (0);
  484. bad2:
  485. sbrelease(&so->so_snd);
  486. bad:
  487. return (ENOBUFS);
  488. }
  489. /*
  490.  * Allot mbufs to a sockbuf.
  491.  * Attempt to scale mbmax so that mbcnt doesn't become limiting
  492.  * if buffering efficiency is near the normal case.
  493.  */
  494. int
  495. sbreserve(sb, cc)
  496. struct sockbuf *sb;
  497. u_long cc;
  498. {
  499. if (cc > sb_max * MCLBYTES / (MSIZE + MCLBYTES))
  500. return (0);
  501. sb->sb_hiwat = cc;
  502. sb->sb_mbmax = min(cc * 5, sb_max);
  503. if (sb->sb_lowat > sb->sb_hiwat)
  504. sb->sb_lowat = sb->sb_hiwat;
  505. return (1);
  506. }
  507. /*
  508.  * Free mbufs held by a socket, and reserved mbuf space.
  509.  */
  510. void
  511. sbrelease(sb)
  512. struct sockbuf *sb;
  513. {
  514. sbflush(sb);
  515. sb->sb_hiwat = sb->sb_mbmax = 0;
  516. }
  517. /*
  518.  * Routines to add and remove
  519.  * data from an mbuf queue.
  520.  *
  521.  * The routines sbappend() or sbappendrecord() are normally called to
  522.  * append new mbufs to a socket buffer, after checking that adequate
  523.  * space is available, comparing the function sbspace() with the amount
  524.  * of data to be added.  sbappendrecord() differs from sbappend() in
  525.  * that data supplied is treated as the beginning of a new record.
  526.  * To place a sender's address, optional access rights, and data in a
  527.  * socket receive buffer, sbappendaddr() should be used.  To place
  528.  * access rights and data in a socket receive buffer, sbappendrights()
  529.  * should be used.  In either case, the new data begins a new record.
  530.  * Note that unlike sbappend() and sbappendrecord(), these routines check
  531.  * for the caller that there will be enough space to store the data.
  532.  * Each fails if there is not enough space, or if it cannot find mbufs
  533.  * to store additional information in.
  534.  *
  535.  * Reliable protocols may use the socket send buffer to hold data
  536.  * awaiting acknowledgement.  Data is normally copied from a socket
  537.  * send buffer in a protocol with m_copy for output to a peer,
  538.  * and then removing the data from the socket buffer with sbdrop()
  539.  * or sbdroprecord() when the data is acknowledged by the peer.
  540.  */
  541. /*
  542.  * Append mbuf chain m to the last record in the
  543.  * socket buffer sb.  The additional space associated
  544.  * the mbuf chain is recorded in sb.  Empty mbufs are
  545.  * discarded and mbufs are compacted where possible.
  546.  */
  547. void
  548. sbappend(sb, m)
  549. struct sockbuf *sb;
  550. struct mbuf *m;
  551. {
  552. register struct mbuf *n;
  553. if (m == 0)
  554. return;
  555. if ((n = sb->sb_mb)) {
  556. while (n->m_nextpkt)
  557. n = n->m_nextpkt;
  558. do {
  559. if (n->m_flags & M_EOR) {
  560. sbappendrecord(sb, m); /* XXXXXX!!!! */
  561. return;
  562. }
  563. } while (n->m_next && (n = n->m_next));
  564. }
  565. sbcompress(sb, m, n);
  566. }
  567. #ifdef SOCKBUF_DEBUG
  568. void
  569. sbcheck(sb)
  570. register struct sockbuf *sb;
  571. {
  572. register struct mbuf *m;
  573. register int len = 0, mbcnt = 0;
  574. for (m = sb->sb_mb; m; m = m->m_next) {
  575. len += m->m_len;
  576. mbcnt += MSIZE;
  577. if (m->m_flags & M_EXT)
  578. mbcnt += m->m_extSize;
  579. if (m->m_nextpkt)
  580. panic("sbcheck nextpkt");
  581. }
  582. if (len != sb->sb_cc || mbcnt != sb->sb_mbcnt) {
  583. printf("cc %d != %d || mbcnt %d != %dn", len, sb->sb_cc,
  584.     mbcnt, sb->sb_mbcnt);
  585. panic("sbcheck");
  586. }
  587. }
  588. #endif
  589. /*
  590.  * As above, except the mbuf chain
  591.  * begins a new record.
  592.  */
  593. void
  594. sbappendrecord(sb, m0)
  595. register struct sockbuf *sb;
  596. register struct mbuf *m0;
  597. {
  598. register struct mbuf *m;
  599. if (m0 == 0)
  600. return;
  601. if ((m = sb->sb_mb) != NULL)
  602. while (m->m_nextpkt)
  603. m = m->m_nextpkt;
  604. /*
  605.  * Put the first mbuf on the queue.
  606.  * Note this permits zero length records.
  607.  */
  608. sballoc(sb, m0);
  609. if (m)
  610. m->m_nextpkt = m0;
  611. else
  612. sb->sb_mb = m0;
  613. m = m0->m_next;
  614. m0->m_next = 0;
  615. if (m && (m0->m_flags & M_EOR)) {
  616. m0->m_flags &= ~M_EOR;
  617. m->m_flags |= M_EOR;
  618. }
  619. sbcompress(sb, m, m0);
  620. }
  621. /*
  622.  * As above except that OOB data
  623.  * is inserted at the beginning of the sockbuf,
  624.  * but after any other OOB data.
  625.  */
  626. void
  627. sbinsertoob(sb, m0)
  628. register struct sockbuf *sb;
  629. register struct mbuf *m0;
  630. {
  631. register struct mbuf *m;
  632. register struct mbuf **mp;
  633. if (m0 == 0)
  634. return;
  635. for (mp = &sb->sb_mb; (m = *mp) != NULL; mp = &((*mp)->m_nextpkt)) {
  636.     again:
  637. switch (m->m_type) {
  638. case MT_OOBDATA:
  639. continue; /* WANT next train */
  640. case MT_CONTROL:
  641. if ((m = m->m_next) != NULL)
  642. goto again; /* inspect THIS train further */
  643. }
  644. break;
  645. }
  646. /*
  647.  * Put the first mbuf on the queue.
  648.  * Note this permits zero length records.
  649.  */
  650. sballoc(sb, m0);
  651. m0->m_nextpkt = *mp;
  652. *mp = m0;
  653. m = m0->m_next;
  654. m0->m_next = 0;
  655. if (m && (m0->m_flags & M_EOR)) {
  656. m0->m_flags &= ~M_EOR;
  657. m->m_flags |= M_EOR;
  658. }
  659. sbcompress(sb, m, m0);
  660. }
  661. /*
  662.  * Append address and data, and optionally, control (ancillary) data
  663.  * to the receive queue of a socket.  If present,
  664.  * m0 must include a packet header with total length.
  665.  * Returns 0 if no space in sockbuf or insufficient mbufs.
  666.  */
  667. int
  668. sbappendaddr(sb, asa, m0, control)
  669. register struct sockbuf *sb;
  670. struct sockaddr *asa;
  671. struct mbuf *m0, *control;
  672. {
  673. register struct mbuf *m, *n;
  674. int space = asa->sa_len;
  675.     if (m0 && (m0->m_flags & M_PKTHDR) == 0)
  676.         {
  677. #ifdef WV_INSTRUMENTATION
  678. #ifdef INCLUDE_WVNET    /* WV_NET_EMERGENCY event */
  679.         WV_NET_EVENT_0 (NET_CORE_EVENT, WV_NET_EMERGENCY, 41, 1, 
  680.                         WV_NETEVENT_SBAPPENDADDR_PANIC, WV_NET_RECV)
  681. #endif  /* INCLUDE_WVNET */
  682. #endif
  683.         panic("sbappendaddr");
  684.         }
  685. if (m0)
  686. space += m0->m_pkthdr.len;
  687. for (n = control; n; n = n->m_next) {
  688. space += n->m_len;
  689. if (n->m_next == 0) /* keep pointer to last control buf */
  690. break;
  691. }
  692. if (space > sbspace(sb))
  693. return (0);
  694. if (asa->sa_len > CL_SIZE_128)
  695. return (0);
  696. m = mBufClGet(M_DONTWAIT, MT_SONAME, CL_SIZE_128, TRUE);
  697. if (m == 0)
  698. return (0);
  699. m->m_len = asa->sa_len;
  700. bcopy((caddr_t)asa, mtod(m, caddr_t), asa->sa_len);
  701. if (n)
  702. n->m_next = m0; /* concatenate data to control */
  703. else
  704. control = m0;
  705. m->m_next = control;
  706. for (n = m; n; n = n->m_next)
  707. sballoc(sb, n);
  708. if ((n = sb->sb_mb) != NULL) {
  709. while (n->m_nextpkt)
  710. n = n->m_nextpkt;
  711. n->m_nextpkt = m;
  712. } else
  713. sb->sb_mb = m;
  714. return (1);
  715. }
  716. int
  717. sbappendcontrol(sb, m0, control)
  718. struct sockbuf *sb;
  719. struct mbuf *m0, *control;
  720. {
  721. register struct mbuf *m, *n;
  722. int space = 0;
  723.     if (control == 0)
  724.         {
  725. #ifdef WV_INSTRUMENTATION
  726. #ifdef INCLUDE_WVNET    /* WV_NET_EMERGENCY event */
  727.         WV_NET_MARKER_0 (NET_AUX_EVENT, WV_NET_EMERGENCY, 42, 2, 
  728.                          WV_NETEVENT_SBAPPENDCTRL_PANIC)
  729. #endif  /* INCLUDE_WVNET */
  730. #endif
  731.         panic ("sbappendcontrol");
  732.         }
  733. for (m = control; ; m = m->m_next) {
  734. space += m->m_len;
  735. if (m->m_next == 0)
  736. break;
  737. }
  738. n = m; /* save pointer to last control buffer */
  739. for (m = m0; m; m = m->m_next)
  740. space += m->m_len;
  741. if (space > sbspace(sb))
  742. return (0);
  743. n->m_next = m0; /* concatenate data to control */
  744. for (m = control; m; m = m->m_next)
  745. sballoc(sb, m);
  746. if ((n = sb->sb_mb) != NULL) {
  747. while (n->m_nextpkt)
  748. n = n->m_nextpkt;
  749. n->m_nextpkt = control;
  750. } else
  751. sb->sb_mb = control;
  752. return (1);
  753. }
  754. /*
  755.  * Compress mbuf chain m into the socket
  756.  * buffer sb following mbuf n.  If n
  757.  * is null, the buffer is presumed empty.
  758.  */
  759. void
  760. sbcompress(sb, m, n)
  761. register struct sockbuf *sb;
  762. register struct mbuf *m, *n;
  763. {
  764. register int eor = 0;
  765. register struct mbuf *o;
  766. while (m) {
  767. eor |= m->m_flags & M_EOR;
  768. if (m->m_len == 0 &&
  769.     (eor == 0 ||
  770.      (((o = m->m_next) || (o = n)) &&
  771.       o->m_type == m->m_type))) {
  772. m = m_free(m);
  773. continue;
  774. }
  775. /*
  776.  * This test determines whether or not the data in <m> will
  777.  * be copied to the cluster referenced by <n>.  The conditions
  778.  * which are required for compression are:
  779.  *     1) <n> is non-NULL
  780.  *     2) <n> is not the end of a record.  M_EOR is set for
  781.  *        datagram protocols (UDP, raw IP) but not stream
  782.  *        protocols (TCP)
  783.  *     3) length of data in <m> is less than CL_SIZE_MIN.  This
  784.  *        condition optimizes buffer usage for small clusters
  785.  *        and optimizes speed for large clusters, by not 
  786.  *        copying data in those cases.
  787.  *     4) The data in <m> must fit in the remaining space in 
  788.  *        the cluster referenced by <n>
  789.  *     5) <m> and <n> must contain the same type of data
  790.  */
  791. if (n && 
  792.     (n->m_flags & M_EOR) == 0 && 
  793.     m->m_len < CL_SIZE_MIN &&
  794.     (n->m_data + n->m_len + m->m_len) < 
  795.     (n->m_extBuf + n->m_extSize) &&
  796.     n->m_type == m->m_type) 
  797.     {
  798.     bcopy(mtod(m, caddr_t), mtod(n, caddr_t) + n->m_len,
  799.   (unsigned)m->m_len);
  800.     n->m_len += m->m_len;
  801.     sb->sb_cc += m->m_len;
  802.     m = m_free(m);
  803.     continue;
  804.     }
  805. if (n)
  806. n->m_next = m;
  807. else
  808. sb->sb_mb = m;
  809. sballoc(sb, m);
  810. n = m;
  811. m->m_flags &= ~M_EOR;
  812. m = m->m_next;
  813. n->m_next = 0;
  814. }
  815. if (eor) {
  816. if (n)
  817. n->m_flags |= eor;
  818. else
  819. printf("semi-panic: sbcompressn");
  820. }
  821. }
  822. /*
  823.  * Free all mbufs in a sockbuf.
  824.  * Check that all resources are reclaimed.
  825.  */
  826. void sbflush
  827.     (
  828.     register struct sockbuf *sb
  829.     )
  830.     {
  831.     if (sb->sb_flags & SB_LOCK)
  832.         {
  833. #ifdef WV_INSTRUMENTATION
  834. #ifdef INCLUDE_WVNET    /* WV_NET_EMERGENCY event */
  835.         WV_NET_MARKER_1 (NET_AUX_EVENT, WV_NET_EMERGENCY, 43, 3, 
  836.                          WV_NETEVENT_SBFLUSH_PANIC, 1)
  837. #endif  /* INCLUDE_WVNET */
  838. #endif
  839.         panic("sbflush");
  840.         }
  841.     while (sb->sb_mbcnt)
  842.         sbdrop (sb, (int)sb->sb_cc);
  843.     if (sb->sb_cc || sb->sb_mb)
  844.         {
  845. #ifdef WV_INSTRUMENTATION
  846. #ifdef INCLUDE_WVNET    /* WV_NET_EMERGENCY event */
  847.         WV_NET_MARKER_1 (NET_AUX_EVENT, WV_NET_EMERGENCY, 43, 3, 
  848.                          WV_NETEVENT_SBFLUSH_PANIC, 0)
  849. #endif  /* INCLUDE_WVNET */
  850. #endif
  851.         panic ("sbflush 2");
  852.         }
  853.     }
  854. /*
  855.  * Drop data from (the front of) a sockbuf.
  856.  */
  857. void sbdrop
  858.     (
  859.     register struct sockbuf *sb,
  860.     register int len
  861.     )
  862.     {
  863.     register struct mbuf *m, *mn;
  864.     struct mbuf *next;
  865.     next = (m = sb->sb_mb) ? m->m_nextpkt : 0;
  866.     while (len > 0) 
  867.         {
  868.         if (m == 0) 
  869.             {
  870.             if (next == 0)
  871.                 {
  872. #ifdef WV_INSTRUMENTATION
  873. #ifdef INCLUDE_WVNET    /* WV_NET_EMERGENCY event */
  874.                 WV_NET_MARKER_0 (NET_AUX_EVENT, WV_NET_EMERGENCY, 44, 4, 
  875.                                  WV_NETEVENT_SBDROP_PANIC)
  876. #endif  /* INCLUDE_WVNET */
  877. #endif
  878.                 panic ("sbdrop");
  879.                 }
  880.             m = next;
  881.             next = m->m_nextpkt;
  882.             continue;
  883.             }
  884.         if (m->m_len > len)
  885.             {
  886.             m->m_len -= len;
  887.             m->m_data += len;
  888.             sb->sb_cc -= len;
  889.             break;
  890.             }
  891.         len -= m->m_len;
  892.         sbfree (sb, m);
  893.         mn = m_free (m);
  894.         m = mn;
  895.         }
  896.     while (m && m->m_len == 0)
  897.         {
  898.         sbfree (sb, m);
  899.         mn = m_free (m);
  900.         m = mn;
  901.         }
  902.     if (m)
  903.         {
  904.         sb->sb_mb = m;
  905.         m->m_nextpkt = next;
  906.         }
  907.     else
  908.         sb->sb_mb = next;
  909.     }
  910. /*
  911.  * Drop a record off the front of a sockbuf
  912.  * and move the next record to the front.
  913.  */
  914. void
  915. sbdroprecord(sb)
  916. register struct sockbuf *sb;
  917. {
  918. register struct mbuf *m, *mn;
  919. m = sb->sb_mb;
  920. if (m) {
  921. sb->sb_mb = m->m_nextpkt;
  922. do {
  923. sbfree(sb, m);
  924. mn = m_free(m);
  925. } while ((m = mn));
  926. }
  927. }