JNIEXPORT jint JNICALL Java_com_etsy_net_UnixDomainSocket_nativeListen(JNIEnv * jEnv, jclass jClass, jstring jSocketFile, jint jSocketType, jint jBacklog) { int s; /* socket file handle */ struct sockaddr_un sa; const char *socketFile = (*jEnv)->GetStringUTFChars(jEnv, jSocketFile, NULL); socklen_t salen = sockaddr_init(socketFile, &sa); /* create the socket */ s = socket(PF_UNIX, SOCK_TYPE(jSocketType), 0); ASSERTNOERR(s == -1, "nativeListen: socket"); /* bind to the socket; here the socket file is created */ ASSERTNOERR(bind(s, (struct sockaddr *)&sa, salen) == -1, "nativeListen: bind"); if (SOCK_TYPE(jSocketType) == SOCK_STREAM) { ASSERTNOERR(listen(s, jBacklog) == -1, "nativeListen: listen"); } (*jEnv)->ReleaseStringUTFChars(jEnv, jSocketFile, socketFile); /* return the listening socket file handle */ return s; }
JNIEXPORT jint JNICALL Java_com_etsy_net_UnixDomainSocket_nativeOpen(JNIEnv * jEnv, jclass jClass, jstring jSocketFile, jint jSocketType) { int s; /* socket file handle */ struct sockaddr_un sa; const char *socketFile = (*jEnv)->GetStringUTFChars(jEnv, jSocketFile, NULL); socklen_t salen = sockaddr_init(socketFile, &sa); s = socket(PF_UNIX, SOCK_TYPE(jSocketType), 0); ASSERTNOERR(s == -1, "nativeOpen: socket"); if (connect(s, (struct sockaddr *)&sa, salen) == -1) { perror("nativeOpen: connect"); int close_ = close(s); ASSERTNOERR(close_ == -1, "nativeOpen: close connect error socket"); return -1; } (*jEnv)->ReleaseStringUTFChars(jEnv, jSocketFile, socketFile); /* return the socket file handle */ return s; }
__private_extern__ uint32_t inpcb_count_opportunistic(unsigned int ifindex, struct inpcbinfo *pcbinfo, u_int32_t flags) { uint32_t opportunistic = 0; struct inpcb *inp; inp_gen_t gencnt; lck_rw_lock_shared(pcbinfo->ipi_lock); gencnt = pcbinfo->ipi_gencnt; for (inp = LIST_FIRST(pcbinfo->ipi_listhead); inp != NULL; inp = LIST_NEXT(inp, inp_list)) { if (inp->inp_gencnt <= gencnt && inp->inp_state != INPCB_STATE_DEAD && inp->inp_socket != NULL && so_get_opportunistic(inp->inp_socket) && inp->inp_last_outifp != NULL && ifindex == inp->inp_last_outifp->if_index) { opportunistic++; struct socket *so = inp->inp_socket; if ((flags & INPCB_OPPORTUNISTIC_SETCMD) && (so->so_state & SS_ISCONNECTED)) { socket_lock(so, 1); if (flags & INPCB_OPPORTUNISTIC_THROTTLEON) { so->so_flags |= SOF_SUSPENDED; soevent(so, (SO_FILT_HINT_LOCKED | SO_FILT_HINT_SUSPEND)); } else { so->so_flags &= ~(SOF_SUSPENDED); soevent(so, (SO_FILT_HINT_LOCKED | SO_FILT_HINT_RESUME)); } SOTHROTTLELOG(("throttle[%d]: so 0x%llx " "[%d,%d] %s\n", so->last_pid, (uint64_t)VM_KERNEL_ADDRPERM(so), SOCK_DOM(so), SOCK_TYPE(so), (so->so_flags & SOF_SUSPENDED) ? "SUSPENDED" : "RESUMED")); socket_unlock(so, 1); } } } lck_rw_done(pcbinfo->ipi_lock); return (opportunistic); }
JNIEXPORT jint JNICALL Java_com_etsy_net_UnixDomainSocket_nativeAccept(JNIEnv * jEnv, jclass jClass, jint jSocketFileHandle, jint jSocketType) { int s = -1; /* socket file handle */ ASSERTNOERR(jSocketFileHandle == -1, "nativeAccept: socket"); if (SOCK_TYPE(jSocketType) == SOCK_STREAM) { s = accept(jSocketFileHandle, NULL, 0); ASSERTNOERR(s == -1, "nativeAccept: accept"); } /* return the socket file handle */ return s; }
JNIEXPORT jint JNICALL Java_com_etsy_net_UnixDomainSocket_nativeOpen(JNIEnv * jEnv, jclass jClass, jstring jSocketFile, jint jSocketType) { int s; /* socket file handle */ struct sockaddr_un sa; struct timeval timeout; const char *socketFile = (*jEnv)->GetStringUTFChars(jEnv, jSocketFile, NULL); socklen_t salen = sockaddr_init(socketFile, &sa); s = socket(PF_UNIX, SOCK_TYPE(jSocketType), 0); ASSERTNOERR(s == -1, "nativeOpen: socket"); if (connect(s, (struct sockaddr *)&sa, salen) == -1) { perror("nativeOpen: connect"); int close_ = close(s); ASSERTNOERR(close_ == -1, "nativeOpen: close connect error socket"); return -1; } timeout.tv_sec = 10; timeout.tv_usec = 0; if (setsockopt(s, SOL_SOCKET, SO_RCVTIMEO, (char *)&timeout, sizeof(timeout)) < 0) { perror("nativeOpen: setsockopt SO_RCVTIMEO failed"); } if (setsockopt(s, SOL_SOCKET, SO_SNDTIMEO, (char *)&timeout, sizeof(timeout)) < 0) { perror("nativeOpen: setsockopt SO_SNDTIMEO failed"); } (*jEnv)->ReleaseStringUTFChars(jEnv, jSocketFile, socketFile); /* return the socket file handle */ return s; }
errno_t fill_socketinfo(struct socket *so, struct socket_info *si) { errno_t error = 0; int domain; short type; short protocol; socket_lock(so, 0); si->soi_kind = SOCKINFO_GENERIC; fill_common_sockinfo(so, si); if (so->so_pcb == NULL || so->so_proto == 0 || so->so_proto->pr_domain == NULL) goto out; /* * The kind of socket is determined by the triplet * {domain, type, protocol} */ domain = SOCK_DOM(so); type = SOCK_TYPE(so); protocol = SOCK_PROTO(so); switch (domain) { case PF_INET: case PF_INET6: { struct in_sockinfo *insi = &si->soi_proto.pri_in; struct inpcb *inp = (struct inpcb *)so->so_pcb; si->soi_kind = SOCKINFO_IN; insi->insi_fport = inp->inp_fport; insi->insi_lport = inp->inp_lport; insi->insi_gencnt = inp->inp_gencnt; insi->insi_flags = inp->inp_flags; insi->insi_vflag = inp->inp_vflag; insi->insi_ip_ttl = inp->inp_ip_ttl; insi->insi_faddr.ina_6 = inp->inp_dependfaddr.inp6_foreign; insi->insi_laddr.ina_6 = inp->inp_dependladdr.inp6_local; insi->insi_v4.in4_tos = inp->inp_depend4.inp4_ip_tos; insi->insi_v6.in6_hlim = 0; insi->insi_v6.in6_cksum = inp->inp_depend6.inp6_cksum; insi->insi_v6.in6_ifindex = 0; insi->insi_v6.in6_hops = inp->inp_depend6.inp6_hops; if (type == SOCK_STREAM && (protocol == 0 || protocol == IPPROTO_TCP) && inp->inp_ppcb != NULL) { struct tcp_sockinfo *tcpsi = &si->soi_proto.pri_tcp; struct tcpcb *tp = (struct tcpcb *)inp->inp_ppcb; si->soi_kind = SOCKINFO_TCP; tcpsi->tcpsi_state = tp->t_state; tcpsi->tcpsi_timer[TCPT_REXMT] = tp->t_timer[TCPT_REXMT]; tcpsi->tcpsi_timer[TCPT_PERSIST] = tp->t_timer[TCPT_PERSIST]; tcpsi->tcpsi_timer[TCPT_KEEP] = tp->t_timer[TCPT_KEEP]; tcpsi->tcpsi_timer[TCPT_2MSL] = tp->t_timer[TCPT_2MSL]; tcpsi->tcpsi_mss = tp->t_maxseg; tcpsi->tcpsi_flags = tp->t_flags; tcpsi->tcpsi_tp = (u_int64_t)VM_KERNEL_ADDRPERM(tp); } break; } case PF_UNIX: { struct unpcb *unp = (struct unpcb *)so->so_pcb; struct un_sockinfo *unsi = &si->soi_proto.pri_un; si->soi_kind = SOCKINFO_UN; unsi->unsi_conn_pcb = (uint64_t)VM_KERNEL_ADDRPERM(unp->unp_conn); if (unp->unp_conn) unsi->unsi_conn_so = (uint64_t) VM_KERNEL_ADDRPERM(unp->unp_conn->unp_socket); if (unp->unp_addr) { size_t addrlen = unp->unp_addr->sun_len; if (addrlen > SOCK_MAXADDRLEN) addrlen = SOCK_MAXADDRLEN; bcopy(unp->unp_addr, &unsi->unsi_addr, addrlen); } if (unp->unp_conn && unp->unp_conn->unp_addr) { size_t addrlen = unp->unp_conn->unp_addr->sun_len; if (addrlen > SOCK_MAXADDRLEN) addrlen = SOCK_MAXADDRLEN; bcopy(unp->unp_conn->unp_addr, &unsi->unsi_caddr, addrlen); } break; } case PF_NDRV: { struct ndrv_cb *ndrv_cb = (struct ndrv_cb *)so->so_pcb; struct ndrv_info *ndrvsi = &si->soi_proto.pri_ndrv; si->soi_kind = SOCKINFO_NDRV; /* TDB lock ifnet ???? */ if (ndrv_cb->nd_if != 0) { struct ifnet *ifp = ndrv_cb->nd_if; ndrvsi->ndrvsi_if_family = ifp->if_family; ndrvsi->ndrvsi_if_unit = ifp->if_unit; strlcpy(ndrvsi->ndrvsi_if_name, ifp->if_name, IFNAMSIZ); } break; } case PF_SYSTEM: if (SOCK_PROTO(so) == SYSPROTO_EVENT) { struct kern_event_pcb *ev_pcb = (struct kern_event_pcb *)so->so_pcb; struct kern_event_info *kesi = &si->soi_proto.pri_kern_event; si->soi_kind = SOCKINFO_KERN_EVENT; kesi->kesi_vendor_code_filter = ev_pcb->evp_vendor_code_filter; kesi->kesi_class_filter = ev_pcb->evp_class_filter; kesi->kesi_subclass_filter = ev_pcb->evp_subclass_filter; } else if (SOCK_PROTO(so) == SYSPROTO_CONTROL) { struct ctl_cb *kcb = (struct ctl_cb *)so->so_pcb; struct kern_ctl_info *kcsi = &si->soi_proto.pri_kern_ctl; struct kctl *kctl = kcb->kctl; si->soi_kind = SOCKINFO_KERN_CTL; if (kctl == 0) break; kcsi->kcsi_id = kctl->id; kcsi->kcsi_reg_unit = kctl->id; kcsi->kcsi_flags = kctl->flags; kcsi->kcsi_recvbufsize = kctl->recvbufsize; kcsi->kcsi_sendbufsize = kctl->sendbufsize; kcsi->kcsi_unit = kcb->unit; strlcpy(kcsi->kcsi_name, kctl->name, MAX_KCTL_NAME); } break; case PF_ROUTE: case PF_PPP: default: break; } out: socket_unlock(so, 0); return (error); }