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