1 /* uipc_socket2.c 4.6 81/11/21 */ 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)/MSIZE; 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); 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_off) <= MMAXOFF) { 194 bcopy(mtod(m, caddr_t), mtod(n, caddr_t), 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 for (m = m0; m; m = m->m_next) 219 len += m->m_len; 220 if (len > sbspace(sb)) 221 return (0); 222 m = m_get(0); 223 if (m == 0) 224 return (0); 225 m->m_off = MMINOFF; 226 m->m_len = sizeof (struct sockaddr); 227 msa = mtod(m, struct sockaddr *); 228 *msa = *asa; 229 m->m_act = (struct mbuf *)1; 230 sbappend(sb, m); 231 m0->m_act = (struct mbuf *)1; 232 sbappend(sb, m0); 233 return (1); 234 } 235 236 /* 237 * Free all mbufs on a sockbuf mbuf chain. 238 * Check that resource allocations return to 0. 239 */ 240 sbflush(sb) 241 struct sockbuf *sb; 242 { 243 244 if (sb->sb_flags & SB_LOCK) 245 panic("sbflush"); 246 sbdrop(sb, sb->sb_cc); 247 if (sb->sb_cc || sb->sb_mbcnt || sb->sb_mb) 248 panic("sbflush 2"); 249 } 250 251 /* 252 * Drop data from (the front of) a sockbuf chain. 253 */ 254 sbdrop(sb, len) 255 register struct sockbuf *sb; 256 register int len; 257 { 258 register struct mbuf *m = sb->sb_mb, *mn; 259 260 while (len > 0) { 261 if (m == 0) 262 panic("sbdrop"); 263 if (m->m_len <= len) { 264 len -= m->m_len; 265 sbfree(sb, m); 266 MFREE(m, mn); 267 m = mn; 268 } else { 269 m->m_len -= len; 270 m->m_off += len; 271 sb->sb_cc -= len; 272 break; 273 } 274 } 275 sb->sb_mb = m; 276 } 277