pass rw flags to d_stop indicating which queues were flushed
[unix-history] / usr / src / sys / kern / uipc_socket2.c
CommitLineData
c64d826c 1/* uipc_socket2.c 4.17 81/12/22 */
681ebb17
BJ
2
3#include "../h/param.h"
4#include "../h/systm.h"
5#include "../h/dir.h"
6#include "../h/user.h"
7#include "../h/proc.h"
8#include "../h/file.h"
9#include "../h/inode.h"
10#include "../h/buf.h"
11#include "../h/mbuf.h"
681ebb17
BJ
12#include "../h/protosw.h"
13#include "../h/socket.h"
14#include "../h/socketvar.h"
c5ff2e32
BJ
15#include "../net/in.h"
16#include "../net/in_systm.h"
681ebb17
BJ
17
18/*
19 * Primitive routines for operating on sockets and socket buffers
20 */
21
22/*
23 * Procedures to manipulate state flags of socket
4c078bb2
BJ
24 * and do appropriate wakeups. Normal sequence is that
25 * soisconnecting() is called during processing of connect() call,
26 * resulting in an eventual call to soisconnected() if/when the
27 * connection is established. When the connection is torn down
28 * soisdisconnecting() is called during processing of disconnect() call,
29 * and soisdisconnected() is called when the connection to the peer
30 * is totally severed. The semantics of these routines are such that
31 * connectionless protocols can call soisconnected() and soisdisconnected()
32 * only, bypassing the in-progress calls when setting up a ``connection''
33 * takes no time.
34 *
35 * When higher level protocols are implemented in
36 * the kernel, the wakeups done here will sometimes
37 * be implemented as software-interrupt process scheduling.
681ebb17 38 */
4c078bb2 39
681ebb17
BJ
40soisconnecting(so)
41 struct socket *so;
42{
43
44 so->so_state &= ~(SS_ISCONNECTED|SS_ISDISCONNECTING);
45 so->so_state |= SS_ISCONNECTING;
46 wakeup((caddr_t)&so->so_timeo);
47}
48
49soisconnected(so)
50 struct socket *so;
51{
52
53 so->so_state &= ~(SS_ISCONNECTING|SS_ISDISCONNECTING);
54 so->so_state |= SS_ISCONNECTED;
55 wakeup((caddr_t)&so->so_timeo);
56}
57
58soisdisconnecting(so)
59 struct socket *so;
60{
61
72857acf 62 so->so_state &= ~SS_ISCONNECTING;
681ebb17
BJ
63 so->so_state |= (SS_ISDISCONNECTING|SS_CANTRCVMORE|SS_CANTSENDMORE);
64 wakeup((caddr_t)&so->so_timeo);
4c078bb2 65 sowwakeup(so);
b454c3ea 66 sorwakeup(so);
681ebb17
BJ
67}
68
69soisdisconnected(so)
70 struct socket *so;
71{
72
73 so->so_state &= ~(SS_ISCONNECTING|SS_ISCONNECTED|SS_ISDISCONNECTING);
74 so->so_state |= (SS_CANTRCVMORE|SS_CANTSENDMORE);
75 wakeup((caddr_t)&so->so_timeo);
76 sowwakeup(so);
77 sorwakeup(so);
78}
79
4c078bb2
BJ
80/*
81 * Socantsendmore indicates that no more data will be sent on the
82 * socket; it would normally be applied to a socket when the user
83 * informs the system that no more data is to be sent, by the protocol
84 * code (in case PRU_SHUTDOWN). Socantrcvmore indicates that no more data
85 * will be received, and will normally be applied to the socket by a
86 * protocol when it detects that the peer will send no more data.
87 * Data queued for reading in the socket may yet be read.
88 */
89
ae921915
BJ
90socantsendmore(so)
91 struct socket *so;
92{
93
94 so->so_state |= SS_CANTSENDMORE;
95 sowwakeup(so);
96}
97
98socantrcvmore(so)
99 struct socket *so;
100{
101
102 so->so_state |= SS_CANTRCVMORE;
103 sorwakeup(so);
104}
105
681ebb17 106/*
4c078bb2
BJ
107 * Socket select/wakeup routines.
108 */
109
110/*
111 * Interface routine to select() system
112 * call for sockets.
681ebb17
BJ
113 */
114soselect(so, flag)
115 register struct socket *so;
116 int flag;
117{
118
119 if (flag & FREAD) {
120 if (soreadable(so))
121 return (1);
122 sbselqueue(&so->so_rcv);
123 }
124 if (flag & FWRITE) {
125 if (sowriteable(so))
126 return (1);
127 sbselqueue(&so->so_snd);
128 }
129 return (0);
130}
131
132/*
133 * Queue a process for a select on a socket buffer.
134 */
135sbselqueue(sb)
136 struct sockbuf *sb;
137{
138 register struct proc *p;
139
ae921915 140 if ((p = sb->sb_sel) && p->p_wchan == (caddr_t)&selwait)
681ebb17
BJ
141 sb->sb_flags |= SB_COLL;
142 else
143 sb->sb_sel = u.u_procp;
144}
145
ae921915
BJ
146/*
147 * Wait for data to arrive at/drain from a socket buffer.
148 */
149sbwait(sb)
150 struct sockbuf *sb;
151{
152
153 sb->sb_flags |= SB_WAIT;
154 sleep((caddr_t)&sb->sb_cc, PZERO+1);
155}
156
681ebb17
BJ
157/*
158 * Wakeup processes waiting on a socket buffer.
159 */
160sbwakeup(sb)
161 struct sockbuf *sb;
162{
163
164 if (sb->sb_sel) {
165 selwakeup(sb->sb_sel, sb->sb_flags & SB_COLL);
166 sb->sb_sel = 0;
167 sb->sb_flags &= ~SB_COLL;
168 }
169 if (sb->sb_flags & SB_WAIT) {
170 sb->sb_flags &= ~SB_WAIT;
388ca8bd 171 wakeup((caddr_t)&sb->sb_cc);
681ebb17
BJ
172 }
173}
174
4c078bb2
BJ
175/*
176 * Socket buffer (struct sockbuf) utility routines.
177 *
178 * Each socket contains two socket buffers: one for sending data and
179 * one for receiving data. Each buffer contains a queue of mbufs,
180 * information about the number of mbufs and amount of data in the
181 * queue, and other fields allowing select() statements and notification
182 * on data availability to be implemented.
183 *
184 * Before using a new socket structure it is first necessary to reserve
185 * buffer space to the socket, by calling sbreserve. This commits
186 * some of the available buffer space in the system buffer pool for the
187 * socket. The space should be released by calling sbrelease when the
188 * socket is destroyed.
189 *
190 * The routine sbappend() is normally called to append new mbufs
191 * to a socket buffer, after checking that adequate space is available
192 * comparing the function spspace() with the amount of data to be added.
193 * Data is normally removed from a socket buffer in a protocol by
194 * first calling m_copy on the socket buffer mbuf chain and sending this
195 * to a peer, and then removing the data from the socket buffer with
196 * sbdrop when the data is acknowledged by the peer (or immediately
b454c3ea 197 * in the case of unreliable protocols.)
4c078bb2
BJ
198 *
199 * Protocols which do not require connections place both source address
200 * and data information in socket buffer queues. The source addresses
201 * are stored in single mbufs after each data item, and are easily found
202 * as the data items are all marked with end of record markers. The
203 * sbappendaddr() routine stores a datum and associated address in
204 * a socket buffer. Note that, unlike sbappend(), this routine checks
205 * for the caller that there will be enough space to store the data.
206 * It fails if there is not enough space, or if it cannot find
207 * a mbuf to store the address in.
208 *
209 * The higher-level routines sosend and soreceive (in socket.c)
b454c3ea 210 * also add data to, and remove data from socket buffers repectively.
4c078bb2
BJ
211 */
212
681ebb17
BJ
213/*
214 * Allot mbufs to a sockbuf.
215 */
216sbreserve(sb, cc)
217 struct sockbuf *sb;
218{
219
196d84fd 220 if (m_reserve((cc*2)/MSIZE) == 0)
681ebb17 221 return (0);
d028a086 222 sb->sb_hiwat = cc;
76a6e254 223 sb->sb_mbmax = cc*2;
ae921915 224 return (1);
681ebb17
BJ
225}
226
227/*
228 * Free mbufs held by a socket, and reserved mbuf space.
229 */
230sbrelease(sb)
231 struct sockbuf *sb;
232{
233
234 sbflush(sb);
d5a69809 235 m_release(sb->sb_mbmax/MSIZE);
d028a086 236 sb->sb_hiwat = sb->sb_mbmax = 0;
681ebb17
BJ
237}
238
239/*
240 * Routines to add (at the end) and remove (from the beginning)
241 * data from a mbuf queue.
242 */
243
244/*
245 * Append mbuf queue m to sockbuf sb.
246 */
247sbappend(sb, m)
248 register struct mbuf *m;
249 register struct sockbuf *sb;
250{
251 register struct mbuf **np, *n;
252
253 np = &sb->sb_mb;
388ca8bd
BJ
254 n = 0;
255 while (*np) {
256 n = *np;
681ebb17 257 np = &n->m_next;
388ca8bd 258 }
681ebb17 259 while (m) {
a73ab5ae 260 if (m->m_len == 0 && (int)m->m_act == 0) {
c64d826c 261 m = m_free(m);
a73ab5ae
BJ
262 continue;
263 }
681ebb17
BJ
264 if (n && n->m_off <= MMAXOFF && m->m_off <= MMAXOFF &&
265 (int)n->m_act == 0 && (int)m->m_act == 0 &&
76a6e254
BJ
266 (n->m_off + n->m_len + m->m_len) <= MMAXOFF) {
267 bcopy(mtod(m, caddr_t), mtod(n, caddr_t) + n->m_len,
ae921915 268 (unsigned)m->m_len);
681ebb17
BJ
269 n->m_len += m->m_len;
270 sb->sb_cc += m->m_len;
271 m = m_free(m);
272 continue;
273 }
274 sballoc(sb, m);
275 *np = m;
276 n = m;
277 np = &n->m_next;
278 m = m->m_next;
279 }
280}
281
4c078bb2
BJ
282/*
283 * Append data and address.
284 * Return 0 if no space in sockbuf or if
285 * can't get mbuf to stuff address in.
286 */
2b4b57cd
BJ
287sbappendaddr(sb, asa, m0)
288 struct sockbuf *sb;
289 struct sockaddr *asa;
290 struct mbuf *m0;
291{
292 struct sockaddr *msa;
293 register struct mbuf *m;
294 register int len = sizeof (struct sockaddr);
295
76a6e254
BJ
296 m = m0;
297 if (m == 0)
298 panic("sbappendaddr");
299 for (;;) {
2b4b57cd 300 len += m->m_len;
76a6e254
BJ
301 if (m->m_next == 0) {
302 m->m_act = (struct mbuf *)1;
303 break;
304 }
305 m = m->m_next;
306 }
509e40dd 307 if (len > sbspace(sb))
2b4b57cd
BJ
308 return (0);
309 m = m_get(0);
509e40dd 310 if (m == 0)
2b4b57cd
BJ
311 return (0);
312 m->m_off = MMINOFF;
313 m->m_len = sizeof (struct sockaddr);
314 msa = mtod(m, struct sockaddr *);
315 *msa = *asa;
316 m->m_act = (struct mbuf *)1;
317 sbappend(sb, m);
2b4b57cd
BJ
318 sbappend(sb, m0);
319 return (1);
320}
321
681ebb17
BJ
322/*
323 * Free all mbufs on a sockbuf mbuf chain.
324 * Check that resource allocations return to 0.
325 */
326sbflush(sb)
327 struct sockbuf *sb;
328{
329
330 if (sb->sb_flags & SB_LOCK)
331 panic("sbflush");
a73ab5ae
BJ
332 if (sb->sb_cc)
333 sbdrop(sb, sb->sb_cc);
681ebb17
BJ
334 if (sb->sb_cc || sb->sb_mbcnt || sb->sb_mb)
335 panic("sbflush 2");
336}
337
338/*
339 * Drop data from (the front of) a sockbuf chain.
340 */
341sbdrop(sb, len)
342 register struct sockbuf *sb;
343 register int len;
344{
345 register struct mbuf *m = sb->sb_mb, *mn;
346
347 while (len > 0) {
348 if (m == 0)
349 panic("sbdrop");
b9f0d37f 350 if (m->m_len > len) {
681ebb17
BJ
351 m->m_len -= len;
352 m->m_off += len;
353 sb->sb_cc -= len;
354 break;
355 }
b9f0d37f
BJ
356 len -= m->m_len;
357 sbfree(sb, m);
358 MFREE(m, mn);
359 m = mn;
681ebb17
BJ
360 }
361 sb->sb_mb = m;
362}
a73ab5ae
BJ
363
364/*
365printm(m)
366 struct mbuf *m;
367{
368
369 printf("<");
370 while (m) {
371 printf("%d,", m->m_len);
372 m = m->m_next;
373 }
374 printf(">");
375 printf("\n");
376}
377*/