xref: /csrg-svn/sys/kern/uipc_socket2.c (revision 5042)
1 /*	uipc_socket2.c	4.8	81/11/22	*/
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"
12 #include "../h/protosw.h"
13 #include "../h/socket.h"
14 #include "../h/socketvar.h"
15 #include "../net/inet.h"
16 #include "../net/inet_systm.h"
17 
18 /*
19  * Primitive routines for operating on sockets and socket buffers
20  */
21 
22 /*
23  * Procedures to manipulate state flags of socket
24  * and do appropriate wakeups.
25  */
26 soisconnecting(so)
27 	struct socket *so;
28 {
29 
30 	so->so_state &= ~(SS_ISCONNECTED|SS_ISDISCONNECTING);
31 	so->so_state |= SS_ISCONNECTING;
32 	wakeup((caddr_t)&so->so_timeo);
33 }
34 
35 soisconnected(so)
36 	struct socket *so;
37 {
38 
39 	so->so_state &= ~(SS_ISCONNECTING|SS_ISDISCONNECTING);
40 	so->so_state |= SS_ISCONNECTED;
41 	wakeup((caddr_t)&so->so_timeo);
42 }
43 
44 soisdisconnecting(so)
45 	struct socket *so;
46 {
47 
48 	so->so_state &= ~(SS_ISCONNECTED|SS_ISCONNECTING);
49 	so->so_state |= (SS_ISDISCONNECTING|SS_CANTRCVMORE|SS_CANTSENDMORE);
50 	wakeup((caddr_t)&so->so_timeo);
51 }
52 
53 soisdisconnected(so)
54 	struct socket *so;
55 {
56 
57 	so->so_state &= ~(SS_ISCONNECTING|SS_ISCONNECTED|SS_ISDISCONNECTING);
58 	so->so_state |= (SS_CANTRCVMORE|SS_CANTSENDMORE);
59 	wakeup((caddr_t)&so->so_timeo);
60 	sowwakeup(so);
61 	sorwakeup(so);
62 }
63 
64 socantsendmore(so)
65 	struct socket *so;
66 {
67 
68 	so->so_state |= SS_CANTSENDMORE;
69 	sowwakeup(so);
70 }
71 
72 socantrcvmore(so)
73 	struct socket *so;
74 {
75 
76 	so->so_state |= SS_CANTRCVMORE;
77 	sorwakeup(so);
78 }
79 
80 /*
81  * Select a socket.
82  */
83 soselect(so, flag)
84 	register struct socket *so;
85 	int flag;
86 {
87 
88 	if (flag & FREAD) {
89 		if (soreadable(so))
90 			return (1);
91 		sbselqueue(&so->so_rcv);
92 	}
93 	if (flag & FWRITE) {
94 		if (sowriteable(so))
95 			return (1);
96 		sbselqueue(&so->so_snd);
97 	}
98 	return (0);
99 }
100 
101 /*
102  * Queue a process for a select on a socket buffer.
103  */
104 sbselqueue(sb)
105 	struct sockbuf *sb;
106 {
107 	register struct proc *p;
108 
109 	if ((p = sb->sb_sel) && p->p_wchan == (caddr_t)&selwait)
110 		sb->sb_flags |= SB_COLL;
111 	else
112 		sb->sb_sel = u.u_procp;
113 }
114 
115 /*
116  * Wait for data to arrive at/drain from a socket buffer.
117  */
118 sbwait(sb)
119 	struct sockbuf *sb;
120 {
121 
122 	sb->sb_flags |= SB_WAIT;
123 	sleep((caddr_t)&sb->sb_cc, PZERO+1);
124 }
125 
126 /*
127  * Wakeup processes waiting on a socket buffer.
128  */
129 sbwakeup(sb)
130 	struct sockbuf *sb;
131 {
132 
133 	if (sb->sb_sel) {
134 		printf("sb %x\n", sb);
135 		selwakeup(sb->sb_sel, sb->sb_flags & SB_COLL);
136 		sb->sb_sel = 0;
137 		sb->sb_flags &= ~SB_COLL;
138 	}
139 	if (sb->sb_flags & SB_WAIT) {
140 		sb->sb_flags &= ~SB_WAIT;
141 		wakeup((caddr_t)&sb->sb_cc);
142 	}
143 }
144 
145 /*
146  * Allot mbufs to a sockbuf.
147  */
148 sbreserve(sb, cc)
149 	struct sockbuf *sb;
150 {
151 
152 	if (m_reserve((cc*2)/MSIZE) == 0)
153 		return (0);
154 	sb->sb_hiwat = cc;
155 	sb->sb_mbmax = cc*2;
156 	return (1);
157 }
158 
159 /*
160  * Free mbufs held by a socket, and reserved mbuf space.
161  */
162 sbrelease(sb)
163 	struct sockbuf *sb;
164 {
165 
166 	sbflush(sb);
167 	m_release(sb->sb_mbmax/MSIZE);
168 	sb->sb_hiwat = sb->sb_mbmax = 0;
169 }
170 
171 /*
172  * Routines to add (at the end) and remove (from the beginning)
173  * data from a mbuf queue.
174  */
175 
176 /*
177  * Append mbuf queue m to sockbuf sb.
178  */
179 sbappend(sb, m)
180 	register struct mbuf *m;
181 	register struct sockbuf *sb;
182 {
183 	register struct mbuf **np, *n;
184 
185 	np = &sb->sb_mb;
186 	n = 0;
187 	while (*np) {
188 		n = *np;
189 		np = &n->m_next;
190 	}
191 	while (m) {
192 /*
193 		if (n && n->m_off <= MMAXOFF && m->m_off <= MMAXOFF &&
194 		   (int)n->m_act == 0 && (int)m->m_act == 0 &&
195 		   (n->m_off + n->m_len + m->m_len) <= MMAXOFF) {
196 			bcopy(mtod(m, caddr_t), mtod(n, caddr_t) + n->m_len,
197 			    (unsigned)m->m_len);
198 			n->m_len += m->m_len;
199 			sb->sb_cc += m->m_len;
200 			m = m_free(m);
201 			continue;
202 		}
203 */
204 		sballoc(sb, m);
205 		*np = m;
206 		n = m;
207 		np = &n->m_next;
208 		m = m->m_next;
209 	}
210 	nullchk("sbappend", sb->sb_mb);
211 }
212 
213 sbappendaddr(sb, asa, m0)
214 	struct sockbuf *sb;
215 	struct sockaddr *asa;
216 	struct mbuf *m0;
217 {
218 	struct sockaddr *msa;
219 	register struct mbuf *m;
220 	register int len = sizeof (struct sockaddr);
221 
222 	printf("sbappendaddr %x asa %x ", sb, asa);
223 	m = m0;
224 	if (m == 0)
225 		panic("sbappendaddr");
226 	for (;;) {
227 		len += m->m_len;
228 		if (m->m_next == 0) {
229 			m->m_act = (struct mbuf *)1;
230 			break;
231 		}
232 		m = m->m_next;
233 	}
234 	printf(": sb_cc %d sb_hiwat %d sb_mbcnt %d sb_mbmax %d sbspace %d: ",
235 	    sb->sb_cc, sb->sb_hiwat, sb->sb_mbcnt, sb->sb_mbmax,
236 	    sbspace(sb));
237 	if (len > sbspace(sb)) {
238 		printf("no space\n");
239 		return (0);
240 	}
241 	m = m_get(0);
242 	if (m == 0) {
243 		printf("no mbufs\n");
244 		return (0);
245 	}
246 	m->m_off = MMINOFF;
247 	m->m_len = sizeof (struct sockaddr);
248 	msa = mtod(m, struct sockaddr *);
249 	*msa = *asa;
250 	m->m_act = (struct mbuf *)1;
251 	sbappend(sb, m);
252 	sbappend(sb, m0);
253 	printf("inserted: sb_cc now %d\n", sb->sb_cc);
254 	return (1);
255 }
256 
257 /*
258  * Free all mbufs on a sockbuf mbuf chain.
259  * Check that resource allocations return to 0.
260  */
261 sbflush(sb)
262 	struct sockbuf *sb;
263 {
264 
265 	if (sb->sb_flags & SB_LOCK)
266 		panic("sbflush");
267 	sbdrop(sb, sb->sb_cc);
268 	if (sb->sb_cc || sb->sb_mbcnt || sb->sb_mb)
269 		panic("sbflush 2");
270 }
271 
272 /*
273  * Drop data from (the front of) a sockbuf chain.
274  */
275 sbdrop(sb, len)
276 	register struct sockbuf *sb;
277 	register int len;
278 {
279 	register struct mbuf *m = sb->sb_mb, *mn;
280 
281 	while (len > 0) {
282 		if (m == 0)
283 			panic("sbdrop");
284 		if (m->m_len <= len) {
285 			len -= m->m_len;
286 			sbfree(sb, m);
287 			MFREE(m, mn);
288 			m = mn;
289 		} else {
290 			m->m_len -= len;
291 			m->m_off += len;
292 			sb->sb_cc -= len;
293 			break;
294 		}
295 	}
296 	sb->sb_mb = m;
297 	nullchk("sbdrop", sb->sb_mb);
298 }
299