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