int soreserve(struct socket *so, u_long sndcc, u_long rcvcc) { KASSERT(so->so_pcb == NULL || solocked(so)); /* * there's at least one application (a configure script of screen) * which expects a fifo is writable even if it has "some" bytes * in its buffer. * so we want to make sure (hiwat - lowat) >= (some bytes). * * PIPE_BUF here is an arbitrary value chosen as (some bytes) above. * we expect it's large enough for such applications. */ u_long lowat = MAX(sock_loan_thresh, MCLBYTES); u_long hiwat = lowat + PIPE_BUF; if (sndcc < hiwat) sndcc = hiwat; if (sbreserve(&so->so_snd, sndcc, so) == 0) goto bad; if (sbreserve(&so->so_rcv, rcvcc, so) == 0) goto bad2; if (so->so_rcv.sb_lowat == 0) so->so_rcv.sb_lowat = 1; if (so->so_snd.sb_lowat == 0) so->so_snd.sb_lowat = lowat; if (so->so_snd.sb_lowat > so->so_snd.sb_hiwat) so->so_snd.sb_lowat = so->so_snd.sb_hiwat; return (0); bad2: sbrelease(&so->so_snd, so); bad: return (ENOBUFS); }
/* FUNCTION: sorflush() * * PARAM1: struct socket * socket structure * * RETURNS: none * * Closes the "read" half of the socket connection. No more data * can be received on the socket, and any data currently in the * socket receive buffer is discarded. Wakeup any processes waiting * on the socket. */ void sorflush(struct socket * so) { struct sockbuf *sb = &so->so_rcv; int s; sblock(sb); socantrcvmore(so); sbunlock(sb); sbrelease(sb); MEMSET((char *)sb, 0, sizeof (*sb)); s = so->so_error; so->so_error = ESHUTDOWN; sorwakeup(so); so->so_error = s; }
/* * Socket buffer (struct sockbuf) utility routines. * * Each socket contains two socket buffers: one for sending data and * one for receiving data. Each buffer contains a queue of mbufs, * information about the number of mbufs and amount of data in the * queue, and other fields allowing select() statements and notification * on data availability to be implemented. * * Data stored in a socket buffer is maintained as a list of records. * Each record is a list of mbufs chained together with the m_next * field. Records are chained together with the m_nextpkt field. The upper * level routine soreceive() expects the following conventions to be * observed when placing information in the receive buffer: * * 1. If the protocol requires each message be preceded by the sender's * name, then a record containing that name must be present before * any associated data (mbuf's must be of type MT_SONAME). * 2. If the protocol supports the exchange of ``access rights'' (really * just additional data associated with the message), and there are * ``rights'' to be received, then a record containing this data * should be present (mbuf's must be of type MT_RIGHTS). * 3. If a name or rights record exists, then it must be followed by * a data record, perhaps of zero length. * * Before using a new socket structure it is first necessary to reserve * buffer space to the socket, by calling sbreserve(). This should commit * some of the available buffer space in the system buffer pool for the * socket (currently, it does nothing but enforce limits). The space * should be released by calling sbrelease() when the socket is destroyed. */ int soreserve(struct usn_socket *so, u_long sndcc, u_long rcvcc) { if (sbreserve(&so->so_snd, sndcc) == 0) goto bad; if (sbreserve(&so->so_rcv, rcvcc) == 0) goto bad2; if (so->so_rcv.sb_lowat == 0) so->so_rcv.sb_lowat = 1; if (so->so_snd.sb_lowat == 0) so->so_snd.sb_lowat = MCLBYTES; if (so->so_snd.sb_lowat > so->so_snd.sb_hiwat) so->so_snd.sb_lowat = so->so_snd.sb_hiwat; return (0); bad2: sbrelease(&so->so_snd); bad: return -1;// no buffer available: (ENOBUFS); }
void sofree(struct socket * so) { INET_TRACE (INETM_SOCKET|INETM_CLOSE, ("INET: sofree, so %lx so_pcb %lx so_state %x so_head %lx\n", so, so->so_pcb, so->so_state, so->so_head)); if (so->so_pcb || (so->so_state & SS_NOFDREF) == 0) return; if (so->so_head) { if (!soqremque(so, 0) && !soqremque(so, 1)) panic("sofree"); so->so_head = 0; } sbrelease(&so->so_snd); sorflush(so); #ifdef SAVE_SOCK_ENDPOINTS if (so->so_endpoint) _socket_free_entry (so); #endif /* SAVE_SOCK_ENDPOINTS */ #ifdef IP_MULTICAST /* multicast opts? */ if (so->inp_moptions) ip_freemoptions(so->inp_moptions); #endif /* IP_MULTICAST */ /* IP_TOS opts? */ if (so->so_optsPack) SOCOPT_FREE(so->so_optsPack); qdel(&soq, so); /* Delete the socket entry from the queue */ if (so_evtmap) (*so_evtmap_delete) (so); SOC_FREE(so); }
int soreserve(struct socket *so, u_long sndcc, u_long rcvcc) { if (sbreserve(&so->so_snd, sndcc)) goto bad; if (sbreserve(&so->so_rcv, rcvcc)) goto bad2; so->so_snd.sb_wat = sndcc; so->so_rcv.sb_wat = rcvcc; if (so->so_rcv.sb_lowat == 0) so->so_rcv.sb_lowat = 1; if (so->so_snd.sb_lowat == 0) so->so_snd.sb_lowat = MCLBYTES; if (so->so_snd.sb_lowat > so->so_snd.sb_hiwat) so->so_snd.sb_lowat = so->so_snd.sb_hiwat; return (0); bad2: sbrelease(&so->so_snd); bad: return (ENOBUFS); }