static int tcp6_usr_listen(struct socket *so, struct proc *p) { int s = splnet(); int error = 0; struct inpcb *inp = sotoinpcb(so); struct tcpcb *tp; COMMON_START(); if (inp->inp_lport == 0) { inp->inp_vflag &= ~INP_IPV4; if (ip6_mapped_addr_on && (inp->inp_flags & IN6P_IPV6_V6ONLY) == 0) inp->inp_vflag |= INP_IPV4; error = in6_pcbbind(inp, (struct sockaddr *)0, p); } if (error == 0) tp->t_state = TCPS_LISTEN; COMMON_END(PRU_LISTEN); }
static int tcp6_usr_bind(struct socket *so, struct sockaddr *nam, struct proc *p) { int s = splnet(); int error = 0; struct inpcb *inp = sotoinpcb(so); struct tcpcb *tp; struct sockaddr_in6 *sin6p; COMMON_START(); /* * Must check for multicast addresses and disallow binding * to them. */ sin6p = (struct sockaddr_in6 *)nam; if (sin6p->sin6_family == AF_INET6 && IN6_IS_ADDR_MULTICAST(&sin6p->sin6_addr)) { error = EAFNOSUPPORT; goto out; } inp->inp_vflag &= ~INP_IPV4; inp->inp_vflag |= INP_IPV6; if (ip6_mapped_addr_on && (inp->inp_flags & IN6P_IPV6_V6ONLY) == 0) { if (IN6_IS_ADDR_UNSPECIFIED(&sin6p->sin6_addr)) inp->inp_vflag |= INP_IPV4; else if (IN6_IS_ADDR_V4MAPPED(&sin6p->sin6_addr)) { struct sockaddr_in sin; in6_sin6_2_sin(&sin, sin6p); inp->inp_vflag |= INP_IPV4; inp->inp_vflag &= ~INP_IPV6; error = in_pcbbind(inp, (struct sockaddr *)&sin, p); goto out; } } error = in6_pcbbind(inp, nam, p); if (error) goto out; COMMON_END(PRU_BIND); }
static int tcp6_usr_accept(struct socket *so, struct sockaddr **nam) { int s = splnet(); int error = 0; struct inpcb *inp = sotoinpcb(so); struct tcpcb *tp = NULL; TCPDEBUG0; if (so->so_state & SS_ISDISCONNECTED) { error = ECONNABORTED; goto out; } if (inp == 0) { splx(s); return (EINVAL); } tp = intotcpcb(inp); TCPDEBUG1(); in6_mapped_peeraddr(so, nam); COMMON_END(PRU_ACCEPT); }
verts = gr.newInstance<Buffer>(sizeof(pos), BufferUsageBit::VERTEX, BufferMapAccessBit::WRITE); void* mapped = verts->map(0, sizeof(pos), BufferMapAccessBit::WRITE); memcpy(mapped, &pos[0], sizeof(pos)); verts->unmap(); indices = gr.newInstance<Buffer>(sizeof(idx), BufferUsageBit::INDEX, BufferMapAccessBit::WRITE); mapped = indices->map(0, sizeof(idx), BufferMapAccessBit::WRITE); memcpy(mapped, &idx[0], sizeof(idx)); indices->unmap(); } ANKI_TEST(Gr, GrManager) { COMMON_BEGIN() COMMON_END() } ANKI_TEST(Gr, Shader) { COMMON_BEGIN() ShaderPtr shader = gr->newInstance<Shader>(ShaderType::VERTEX, VERT_SRC); COMMON_END() } ANKI_TEST(Gr, Pipeline) { COMMON_BEGIN()
/* * Do a send by putting data in output queue and updating urgent * marker if URG set. Possibly send more data. Unlike the other * pru_*() routines, the mbuf chains are our responsibility. We * must either enqueue them or free them. The other pru_* routines * generally are caller-frees. */ static int tcp_usr_send(struct socket *so, int flags, struct mbuf *m, struct sockaddr *nam, struct mbuf *control, struct proc *p) { int s = splnet(); int error = 0; struct inpcb *inp = sotoinpcb(so); struct tcpcb *tp; #ifdef INET6 int isipv6; #endif TCPDEBUG0; if (inp == NULL) { /* * OOPS! we lost a race, the TCP session got reset after * we checked SS_CANTSENDMORE, eg: while doing uiomove or a * network interrupt in the non-splnet() section of sosend(). */ if (m) m_freem(m); if (control) m_freem(control); error = ECONNRESET; /* XXX EPIPE? */ tp = NULL; TCPDEBUG1(); goto out; } #ifdef INET6 isipv6 = nam && nam->sa_family == AF_INET6; #endif /* INET6 */ tp = intotcpcb(inp); TCPDEBUG1(); if (control) { /* TCP doesn't do control messages (rights, creds, etc) */ if (control->m_len) { m_freem(control); if (m) m_freem(m); error = EINVAL; goto out; } m_freem(control); /* empty control, just free it */ } if(!(flags & PRUS_OOB)) { sbappend(&so->so_snd, m); if (nam && tp->t_state < TCPS_SYN_SENT) { /* * Do implied connect if not yet connected, * initialize window to default value, and * initialize maxseg/maxopd using peer's cached * MSS. */ #ifdef INET6 if (isipv6) error = tcp6_connect(tp, nam, p); else #endif /* INET6 */ error = tcp_connect(tp, nam, p); if (error) goto out; tp->snd_wnd = TTCP_CLIENT_SND_WND; tcp_mss(tp, -1); } if (flags & PRUS_EOF) { /* * Close the send side of the connection after * the data is sent. */ socantsendmore(so); tp = tcp_usrclosed(tp); } if (tp != NULL) { if (flags & PRUS_MORETOCOME) tp->t_flags |= TF_MORETOCOME; error = tcp_output(tp); if (flags & PRUS_MORETOCOME) tp->t_flags &= ~TF_MORETOCOME; } } else { if (sbspace(&so->so_snd) < -512) { m_freem(m); error = ENOBUFS; goto out; } /* * According to RFC961 (Assigned Protocols), * the urgent pointer points to the last octet * of urgent data. We continue, however, * to consider it to indicate the first octet * of data past the urgent section. * Otherwise, snd_up should be one lower. */ sbappend(&so->so_snd, m); if (nam && tp->t_state < TCPS_SYN_SENT) { /* * Do implied connect if not yet connected, * initialize window to default value, and * initialize maxseg/maxopd using peer's cached * MSS. */ #ifdef INET6 if (isipv6) error = tcp6_connect(tp, nam, p); else #endif /* INET6 */ error = tcp_connect(tp, nam, p); if (error) goto out; tp->snd_wnd = TTCP_CLIENT_SND_WND; tcp_mss(tp, -1); } tp->snd_up = tp->snd_una + so->so_snd.sb_cc; tp->t_force = 1; error = tcp_output(tp); tp->t_force = 0; } COMMON_END((flags & PRUS_OOB) ? PRU_SENDOOB : ((flags & PRUS_EOF) ? PRU_SEND_EOF : PRU_SEND)); }
/* * Do a send by putting data in output queue and updating urgent * marker if URG set. Possibly send more data. Unlike the other * pru_*() routines, the mbuf chains are our responsibility. We * must either enqueue them or free them. The other pru_* routines * generally are caller-frees. */ static void tcp_usr_send(netmsg_t msg) { struct socket *so = msg->send.base.nm_so; int flags = msg->send.nm_flags; struct mbuf *m = msg->send.nm_m; struct sockaddr *nam = msg->send.nm_addr; struct mbuf *control = msg->send.nm_control; struct thread *td = msg->send.nm_td; int error = 0; struct inpcb *inp; struct tcpcb *tp; #ifdef INET6 int isipv6; #endif TCPDEBUG0; inp = so->so_pcb; if (inp == NULL) { /* * OOPS! we lost a race, the TCP session got reset after * we checked SS_CANTSENDMORE, eg: while doing uiomove or a * network interrupt in the non-critical section of sosend(). */ m_freem(m); if (control) m_freem(control); error = ECONNRESET; /* XXX EPIPE? */ tp = NULL; TCPDEBUG1(); goto out; } #ifdef INET6 isipv6 = nam && nam->sa_family == AF_INET6; #endif /* INET6 */ tp = intotcpcb(inp); TCPDEBUG1(); if (control) { /* TCP doesn't do control messages (rights, creds, etc) */ if (control->m_len) { m_freem(control); m_freem(m); error = EINVAL; goto out; } m_freem(control); /* empty control, just free it */ } /* * Don't let too much OOB data build up */ if (flags & PRUS_OOB) { if (ssb_space(&so->so_snd) < -512) { m_freem(m); error = ENOBUFS; goto out; } } /* * Do implied connect if not yet connected. Any data sent * with the connect is handled by tcp_connect() and friends. * * NOTE! PROTOCOL THREAD MAY BE CHANGED BY THE CONNECT! */ if (nam && tp->t_state < TCPS_SYN_SENT) { kprintf("implied fallback\n"); msg->connect.nm_nam = nam; msg->connect.nm_td = td; msg->connect.nm_m = m; msg->connect.nm_flags = flags; msg->connect.nm_reconnect = NMSG_RECONNECT_FALLBACK; #ifdef INET6 if (isipv6) tcp6_connect(msg); else #endif /* INET6 */ tcp_connect(msg); /* msg invalid now */ return; } /* * Pump the data into the socket. */ if (m) ssb_appendstream(&so->so_snd, m); if (flags & PRUS_OOB) { /* * According to RFC961 (Assigned Protocols), * the urgent pointer points to the last octet * of urgent data. We continue, however, * to consider it to indicate the first octet * of data past the urgent section. * Otherwise, snd_up should be one lower. */ tp->snd_up = tp->snd_una + so->so_snd.ssb_cc; tp->t_flags |= TF_FORCE; error = tcp_output(tp); tp->t_flags &= ~TF_FORCE; } else { if (flags & PRUS_EOF) { /* * Close the send side of the connection after * the data is sent. */ socantsendmore(so); tp = tcp_usrclosed(tp); } if (tp != NULL) { if (flags & PRUS_MORETOCOME) tp->t_flags |= TF_MORETOCOME; error = tcp_output(tp); if (flags & PRUS_MORETOCOME) tp->t_flags &= ~TF_MORETOCOME; } } COMMON_END((flags & PRUS_OOB) ? PRU_SENDOOB : ((flags & PRUS_EOF) ? PRU_SEND_EOF : PRU_SEND)); }
/* * Prepare to accept connections. */ static void tcp_usr_listen(netmsg_t msg) { struct socket *so = msg->listen.base.nm_so; struct thread *td = msg->listen.nm_td; int error = 0; struct inpcb *inp; struct tcpcb *tp; struct netmsg_inswildcard nm; lwkt_port_t port0 = netisr_cpuport(0); COMMON_START(so, inp, 0); if (&curthread->td_msgport != port0) { lwkt_msg_t lmsg = &msg->listen.base.lmsg; KASSERT((msg->listen.nm_flags & PRUL_RELINK) == 0, ("already asked to relink")); in_pcbunlink(so->so_pcb, &tcbinfo[mycpuid]); msg->listen.nm_flags |= PRUL_RELINK; /* See the related comment in tcp_connect() */ lwkt_setmsg_receipt(lmsg, tcp_sosetport); lwkt_forwardmsg(port0, lmsg); /* msg invalid now */ return; } KASSERT(so->so_port == port0, ("so_port is not netisr0")); if (msg->listen.nm_flags & PRUL_RELINK) { msg->listen.nm_flags &= ~PRUL_RELINK; in_pcblink(so->so_pcb, &tcbinfo[mycpuid]); } KASSERT(inp->inp_pcbinfo == &tcbinfo[0], ("pcbinfo is not tcbinfo0")); if (tp->t_flags & TF_LISTEN) goto out; if (inp->inp_lport == 0) { error = in_pcbbind(inp, NULL, td); if (error) goto out; } tp->t_state = TCPS_LISTEN; tp->t_flags |= TF_LISTEN; tp->tt_msg = NULL; /* Catch any invalid timer usage */ if (ncpus2 > 1) { /* * Put this inpcb into wildcard hash on other cpus. */ ASSERT_INP_NOTINHASH(inp); netmsg_init(&nm.base, NULL, &curthread->td_msgport, MSGF_PRIORITY, in_pcbinswildcardhash_handler); nm.nm_inp = inp; lwkt_domsg(netisr_cpuport(1), &nm.base.lmsg, 0); } in_pcbinswildcardhash(inp); COMMON_END(PRU_LISTEN); }