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