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