1 /* uipc_socket2.c 4.9 81/11/23 */ 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 selwakeup(sb->sb_sel, sb->sb_flags & SB_COLL); 135 sb->sb_sel = 0; 136 sb->sb_flags &= ~SB_COLL; 137 } 138 if (sb->sb_flags & SB_WAIT) { 139 sb->sb_flags &= ~SB_WAIT; 140 wakeup((caddr_t)&sb->sb_cc); 141 } 142 } 143 144 /* 145 * Allot mbufs to a sockbuf. 146 */ 147 sbreserve(sb, cc) 148 struct sockbuf *sb; 149 { 150 151 if (m_reserve((cc*2)/MSIZE) == 0) 152 return (0); 153 sb->sb_hiwat = cc; 154 sb->sb_mbmax = cc*2; 155 return (1); 156 } 157 158 /* 159 * Free mbufs held by a socket, and reserved mbuf space. 160 */ 161 sbrelease(sb) 162 struct sockbuf *sb; 163 { 164 165 sbflush(sb); 166 m_release(sb->sb_mbmax/MSIZE); 167 sb->sb_hiwat = sb->sb_mbmax = 0; 168 } 169 170 /* 171 * Routines to add (at the end) and remove (from the beginning) 172 * data from a mbuf queue. 173 */ 174 175 /* 176 * Append mbuf queue m to sockbuf sb. 177 */ 178 sbappend(sb, m) 179 register struct mbuf *m; 180 register struct sockbuf *sb; 181 { 182 register struct mbuf **np, *n; 183 184 np = &sb->sb_mb; 185 n = 0; 186 while (*np) { 187 n = *np; 188 np = &n->m_next; 189 } 190 while (m) { 191 if (n && n->m_off <= MMAXOFF && m->m_off <= MMAXOFF && 192 (int)n->m_act == 0 && (int)m->m_act == 0 && 193 (n->m_off + n->m_len + m->m_len) <= MMAXOFF) { 194 bcopy(mtod(m, caddr_t), mtod(n, caddr_t) + n->m_len, 195 (unsigned)m->m_len); 196 n->m_len += m->m_len; 197 sb->sb_cc += m->m_len; 198 m = m_free(m); 199 continue; 200 } 201 sballoc(sb, m); 202 *np = m; 203 n = m; 204 np = &n->m_next; 205 m = m->m_next; 206 } 207 } 208 209 sbappendaddr(sb, asa, m0) 210 struct sockbuf *sb; 211 struct sockaddr *asa; 212 struct mbuf *m0; 213 { 214 struct sockaddr *msa; 215 register struct mbuf *m; 216 register int len = sizeof (struct sockaddr); 217 218 m = m0; 219 if (m == 0) 220 panic("sbappendaddr"); 221 for (;;) { 222 len += m->m_len; 223 if (m->m_next == 0) { 224 m->m_act = (struct mbuf *)1; 225 break; 226 } 227 m = m->m_next; 228 } 229 if (len > sbspace(sb)) 230 return (0); 231 m = m_get(0); 232 if (m == 0) 233 return (0); 234 m->m_off = MMINOFF; 235 m->m_len = sizeof (struct sockaddr); 236 msa = mtod(m, struct sockaddr *); 237 *msa = *asa; 238 m->m_act = (struct mbuf *)1; 239 sbappend(sb, m); 240 sbappend(sb, m0); 241 return (1); 242 } 243 244 /* 245 * Free all mbufs on a sockbuf mbuf chain. 246 * Check that resource allocations return to 0. 247 */ 248 sbflush(sb) 249 struct sockbuf *sb; 250 { 251 252 if (sb->sb_flags & SB_LOCK) 253 panic("sbflush"); 254 sbdrop(sb, sb->sb_cc); 255 if (sb->sb_cc || sb->sb_mbcnt || sb->sb_mb) 256 panic("sbflush 2"); 257 } 258 259 /* 260 * Drop data from (the front of) a sockbuf chain. 261 */ 262 sbdrop(sb, len) 263 register struct sockbuf *sb; 264 register int len; 265 { 266 register struct mbuf *m = sb->sb_mb, *mn; 267 268 while (len > 0) { 269 if (m == 0) 270 panic("sbdrop"); 271 if (m->m_len <= len) { 272 len -= m->m_len; 273 sbfree(sb, m); 274 MFREE(m, mn); 275 m = mn; 276 } else { 277 m->m_len -= len; 278 m->m_off += len; 279 sb->sb_cc -= len; 280 break; 281 } 282 } 283 sb->sb_mb = m; 284 } 285