date and time created 82/05/26 15:16:03 by sam
[unix-history] / usr / src / sys / kern / uipc_socket2.c
CommitLineData
4b11abe3 1/* uipc_socket2.c 4.22 82/03/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{
e495e1cc 263 register struct mbuf *n;
681ebb17 264
e495e1cc
BJ
265 n = sb->sb_mb;
266 if (n)
267 while (n->m_next)
268 n = n->m_next;
681ebb17 269 while (m) {
a73ab5ae 270 if (m->m_len == 0 && (int)m->m_act == 0) {
c64d826c 271 m = m_free(m);
a73ab5ae
BJ
272 continue;
273 }
681ebb17
BJ
274 if (n && n->m_off <= MMAXOFF && m->m_off <= MMAXOFF &&
275 (int)n->m_act == 0 && (int)m->m_act == 0 &&
76a6e254
BJ
276 (n->m_off + n->m_len + m->m_len) <= MMAXOFF) {
277 bcopy(mtod(m, caddr_t), mtod(n, caddr_t) + n->m_len,
ae921915 278 (unsigned)m->m_len);
681ebb17
BJ
279 n->m_len += m->m_len;
280 sb->sb_cc += m->m_len;
281 m = m_free(m);
282 continue;
283 }
284 sballoc(sb, m);
e495e1cc
BJ
285 if (n == 0)
286 sb->sb_mb = m;
287 else
288 n->m_next = m;
681ebb17 289 n = m;
681ebb17 290 m = m->m_next;
e495e1cc 291 n->m_next = 0;
681ebb17
BJ
292 }
293}
294
4c078bb2
BJ
295/*
296 * Append data and address.
297 * Return 0 if no space in sockbuf or if
298 * can't get mbuf to stuff address in.
299 */
2b4b57cd
BJ
300sbappendaddr(sb, asa, m0)
301 struct sockbuf *sb;
302 struct sockaddr *asa;
303 struct mbuf *m0;
304{
305 struct sockaddr *msa;
306 register struct mbuf *m;
307 register int len = sizeof (struct sockaddr);
308
76a6e254
BJ
309 m = m0;
310 if (m == 0)
311 panic("sbappendaddr");
312 for (;;) {
2b4b57cd 313 len += m->m_len;
76a6e254
BJ
314 if (m->m_next == 0) {
315 m->m_act = (struct mbuf *)1;
316 break;
317 }
318 m = m->m_next;
319 }
509e40dd 320 if (len > sbspace(sb))
2b4b57cd 321 return (0);
99308d84 322 m = m_get(M_DONTWAIT);
509e40dd 323 if (m == 0)
2b4b57cd
BJ
324 return (0);
325 m->m_off = MMINOFF;
326 m->m_len = sizeof (struct sockaddr);
327 msa = mtod(m, struct sockaddr *);
328 *msa = *asa;
329 m->m_act = (struct mbuf *)1;
330 sbappend(sb, m);
2b4b57cd
BJ
331 sbappend(sb, m0);
332 return (1);
333}
334
681ebb17
BJ
335/*
336 * Free all mbufs on a sockbuf mbuf chain.
337 * Check that resource allocations return to 0.
338 */
339sbflush(sb)
340 struct sockbuf *sb;
341{
342
343 if (sb->sb_flags & SB_LOCK)
344 panic("sbflush");
a73ab5ae
BJ
345 if (sb->sb_cc)
346 sbdrop(sb, sb->sb_cc);
681ebb17
BJ
347 if (sb->sb_cc || sb->sb_mbcnt || sb->sb_mb)
348 panic("sbflush 2");
349}
350
351/*
352 * Drop data from (the front of) a sockbuf chain.
353 */
354sbdrop(sb, len)
355 register struct sockbuf *sb;
356 register int len;
357{
358 register struct mbuf *m = sb->sb_mb, *mn;
359
360 while (len > 0) {
361 if (m == 0)
362 panic("sbdrop");
b9f0d37f 363 if (m->m_len > len) {
681ebb17
BJ
364 m->m_len -= len;
365 m->m_off += len;
366 sb->sb_cc -= len;
367 break;
368 }
b9f0d37f
BJ
369 len -= m->m_len;
370 sbfree(sb, m);
371 MFREE(m, mn);
372 m = mn;
681ebb17
BJ
373 }
374 sb->sb_mb = m;
375}