CAMLprim value bigstring_recvfrom_assume_fd_is_nonblocking_stub( value v_sock, value v_pos, value v_len, value v_bstr) { CAMLparam1(v_bstr); CAMLlocal1(v_addr); struct caml_ba_array *ba = Caml_ba_array_val(v_bstr); char *bstr = (char *) ba->data + Long_val(v_pos); size_t len = Long_val(v_len); ssize_t n_read; union sock_addr_union addr; socklen_param_type addr_len = sizeof(addr); value v_res; if (len > THREAD_IO_CUTOFF) { caml_enter_blocking_section(); n_read = recvfrom(Int_val(v_sock), bstr, len, 0, &addr.s_gen, &addr_len); caml_leave_blocking_section(); } else n_read = recvfrom(Int_val(v_sock), bstr, len, 0, &addr.s_gen, &addr_len); if (n_read == -1) uerror("bigstring_recvfrom_assume_fd_is_nonblocking", Nothing); v_addr = alloc_sockaddr(&addr, addr_len, -1); v_res = caml_alloc_small(2, 0); Field(v_res, 0) = Val_long(n_read); Field(v_res, 1) = v_addr; CAMLreturn(v_res); }
CAMLprim value unix_recvfrom(value sock, value buff, value ofs, value len, value flags) { SOCKET s = Socket_val(sock); int flg = convert_flag_list(flags, msg_flag_table); int ret; intnat numbytes; char iobuf[UNIX_BUFFER_SIZE]; value res; value adr = Val_unit; union sock_addr_union addr; socklen_param_type addr_len; DWORD err = 0; Begin_roots2 (buff, adr); numbytes = Long_val(len); if (numbytes > UNIX_BUFFER_SIZE) numbytes = UNIX_BUFFER_SIZE; addr_len = sizeof(sock_addr); enter_blocking_section(); ret = recvfrom(s, iobuf, (int) numbytes, flg, &addr.s_gen, &addr_len); if (ret == -1) err = WSAGetLastError(); leave_blocking_section(); if (ret == -1) { win32_maperr(err); uerror("recvfrom", Nothing); } memmove (&Byte(buff, Long_val(ofs)), iobuf, ret); adr = alloc_sockaddr(&addr, addr_len, -1); res = alloc_small(2, 0); Field(res, 0) = Val_int(ret); Field(res, 1) = adr; End_roots(); return res; }
CAMLprim value unix_recvfrom(value sock, value buff, value ofs, value len, value flags) { int ret, cv_flags; long numbytes; char iobuf[UNIX_BUFFER_SIZE]; value res; value adr = Val_unit; union sock_addr_union addr; socklen_param_type addr_len; cv_flags = convert_flag_list(flags, msg_flag_table); Begin_roots2 (buff, adr); numbytes = Long_val(len); if (numbytes > UNIX_BUFFER_SIZE) numbytes = UNIX_BUFFER_SIZE; addr_len = sizeof(addr); enter_blocking_section(); ret = recvfrom(Int_val(sock), iobuf, (int) numbytes, cv_flags, &addr.s_gen, &addr_len); leave_blocking_section(); if (ret == -1) uerror("recvfrom", Nothing); memmove (&Byte(buff, Long_val(ofs)), iobuf, ret); adr = alloc_sockaddr(&addr, addr_len, -1); res = alloc_small(2, 0); Field(res, 0) = Val_int(ret); Field(res, 1) = adr; End_roots(); return res; }
ssize_t recvmmsg_assume_fd_is_nonblocking( value v_fd, struct iovec *iovecs, value v_count, value v_srcs, struct mmsghdr *hdrs) { CAMLparam3(v_fd, v_count, v_srcs); CAMLlocal1(v_sockaddrs); size_t total_len = 0; union sock_addr_union addrs[Int_val(v_count)]; int i; for (i = 0; i < Int_val(v_count); i++) { hdrs[i].msg_hdr.msg_name = (Is_block(v_srcs) ? &addrs[i].s_gen : 0); hdrs[i].msg_hdr.msg_namelen = (Is_block(v_srcs) ? sizeof(addrs[i]) : 0); #if DEBUG fprintf(stderr, "i=%d, count=%d, is_some srcs=%d\n", i, Int_val(v_count), Is_block(v_srcs)); #endif total_len += iovecs[i].iov_len; hdrs[i].msg_hdr.msg_iov = &iovecs[i]; hdrs[i].msg_hdr.msg_iovlen = 1; hdrs[i].msg_hdr.msg_control = 0; hdrs[i].msg_hdr.msg_controllen = 0; hdrs[i].msg_hdr.msg_flags = 0; /* We completely ignore msg_flags and ancillary data (msg_control) for now. In the future, users may be interested in this. */ } ssize_t n_read; /* pszilagyi: This is only 64k in unix_utils.h, which we will very quickly overrun with recvmmsg and then maybe Jumbo frames. bnigito has already observed the Pico feed filling over 32 recvmmsg buffers in a single call, in a test scenario. */ if (total_len > THREAD_IO_CUTOFF) { caml_enter_blocking_section(); n_read = recvmmsg(Int_val(v_fd), hdrs, Int_val(v_count), 0, 0); caml_leave_blocking_section(); } else n_read = recvmmsg(Int_val(v_fd), hdrs, Int_val(v_count), 0, 0); if (n_read == -1) { /* bnigito via pszilagyi: This prototype performance tweak saves the allocation of an exception in common cases, at the cost of conflating reception of an empty message with nothing to do. */ if (errno == EWOULDBLOCK || errno == EAGAIN) n_read = -errno; else uerror("recvmmsg_assume_fd_is_nonblocking", Nothing); } else { if (Is_block(v_srcs)) { /* Some */ v_sockaddrs = Field(v_srcs, 0); for (i = 0; (unsigned)i < n_read && (unsigned)i < Wosize_val(v_sockaddrs); i++) Store_field(v_sockaddrs, i, alloc_sockaddr(&addrs[i], hdrs[i].msg_hdr.msg_namelen, -1)); } } CAMLreturnT(ssize_t, n_read); }
CAMLprim value unix_getpeername(value sock) { int retcode; union sock_addr_union addr; socklen_param_type addr_len; addr_len = sizeof(addr); retcode = getpeername(Int_val(sock), &addr.s_gen, &addr_len); if (retcode == -1) uerror("getpeername", Nothing); return alloc_sockaddr(&addr, addr_len, -1); }
static uint64 on_accept (utp_callback_arguments *a) { CAMLparam0 (); CAMLlocal2 (addr, val); union sock_addr_union sock_addr; socklen_param_type sock_addr_len; static value *on_accept_fun = NULL; if (on_accept_fun == NULL) on_accept_fun = caml_named_value ("utp_on_accept"); sock_addr_len = sizeof (struct sockaddr_in); memcpy (&sock_addr.s_inet, (struct sockaddr_in *) a->address, sock_addr_len); addr = alloc_sockaddr (&sock_addr, sock_addr_len, 0); caml_callback3 (*on_accept_fun, Val_utp_context (a->context), Val_utp_socket (a->socket), addr); CAMLreturn (0); }
static uint64 on_sendto (utp_callback_arguments *a) { CAMLparam0 (); CAMLlocal2 (addr, buf); union sock_addr_union sock_addr; socklen_param_type sock_addr_len; static value *on_sendto_fun = NULL; if (on_sendto_fun == NULL) on_sendto_fun = caml_named_value ("utp_on_sendto"); sock_addr_len = sizeof (struct sockaddr_in); memcpy (&sock_addr.s_inet, (struct sockaddr_in *) a->address, sock_addr_len); addr = alloc_sockaddr (&sock_addr, sock_addr_len, 0); buf = caml_ba_alloc_dims (CAML_BA_UINT8 | CAML_BA_C_LAYOUT, 1, (void *) a->buf, a->len); caml_callback3 (*on_sendto_fun, Val_utp_context (a->context), addr, buf); CAMLreturn (0); }
static value convert_addrinfo(struct addrinfo * a) { CAMLparam0(); CAMLlocal3(vres,vaddr,vcanonname); union sock_addr_union sa; socklen_param_type len; len = a->ai_addrlen; if (len > sizeof(sa)) len = sizeof(sa); memcpy(&sa.s_gen, a->ai_addr, len); vaddr = alloc_sockaddr(&sa, len, -1); vcanonname = copy_string(a->ai_canonname == NULL ? "" : a->ai_canonname); vres = alloc_small(5, 0); Field(vres, 0) = cst_to_constr(a->ai_family, socket_domain_table, 3, 0); Field(vres, 1) = cst_to_constr(a->ai_socktype, socket_type_table, 4, 0); Field(vres, 2) = Val_int(a->ai_protocol); Field(vres, 3) = vaddr; Field(vres, 4) = vcanonname; CAMLreturn(vres); }
value skt_accept(value sock_v){ SOCKET news; union sock_addr_union addr; socklen_param_type addr_len; CAMLparam1(sock_v); CAMLlocal3(pair_v, addr_v, news_v); SKTTRACE(("skt_accept(\n")); news = accept(Socket_val(sock_v), (struct sockaddr*)&addr.s_inet, &addr_len); SKTTRACE2((")\n")); if (news == INVALID_SOCKET) serror("accept"); addr_v = alloc_sockaddr(&addr, addr_len); news_v = Val_socket(news); pair_v = alloc_small(2,0); Field(pair_v,0) = news_v; Field(pair_v,1) = addr_v; CAMLreturn(pair_v); }
CAMLprim value unix_accept(value sock) { int retcode; value res; value a; union sock_addr_union addr; socklen_param_type addr_len; addr_len = sizeof(addr); enter_blocking_section(); retcode = accept(Int_val(sock), &addr.s_gen, &addr_len); leave_blocking_section(); if (retcode == -1) uerror("accept", Nothing); a = alloc_sockaddr(&addr, addr_len, retcode); Begin_root (a); res = alloc_small(2, 0); Field(res, 0) = Val_int(retcode); Field(res, 1) = a; End_roots(); return res; }
CAMLprim value bigstring_recvmmsg_assume_fd_is_nonblocking_stub( value v_fd, value v_iovecs, value v_count, value v_srcs, value v_lens) { CAMLparam5(v_fd, v_iovecs, v_count, v_srcs, v_lens); CAMLlocal5(v_iovec, v_buf, v_pos, v_len, v_sockaddrs); size_t total_len = 0; struct mmsghdr hdrs[Long_val(v_count)]; union sock_addr_union addrs[Long_val(v_count)]; struct iovec iovecs[Long_val(v_count)]; unsigned i; ssize_t n_read; int save_source_addresses; int fd; unsigned int count; save_source_addresses = Is_block(v_srcs); fd = Int_val(v_fd); count = (unsigned int) Long_val(v_count); if (count != Long_val(v_count)) { caml_invalid_argument("bigstring_recvmmsg_assume_fd_is_nonblocking_stub: " "v_count exceeds unsigned int"); } if (!Is_block(v_lens)) { caml_invalid_argument("bigstring_recvmmsg_assume_fd_is_nonblocking_stub: " "v_lens is not an array"); } if (Wosize_val(v_lens) < count) { caml_invalid_argument("bigstring_recvmmsg_assume_fd_is_nonblocking_stub: " "length v_lens < count"); } for (i = 0; i < count; i++) { hdrs[i].msg_hdr.msg_name = (save_source_addresses ? &addrs[i].s_gen : 0); hdrs[i].msg_hdr.msg_namelen = sizeof(addrs[i]); v_iovec = Field(v_iovecs, i); v_buf = Field(v_iovec, 0); v_pos = Field(v_iovec, 1); v_len = Field(v_iovec, 2); iovecs[i].iov_base = get_bstr(v_buf, v_pos); iovecs[i].iov_len = Long_val(v_len); total_len += iovecs[i].iov_len; hdrs[i].msg_hdr.msg_iov = &iovecs[i]; hdrs[i].msg_hdr.msg_iovlen = 1; hdrs[i].msg_hdr.msg_control = 0; hdrs[i].msg_hdr.msg_flags = 0; } if (total_len > THREAD_IO_CUTOFF) { caml_enter_blocking_section(); n_read = recvmmsg(fd, hdrs, count, 0, 0); caml_leave_blocking_section(); } else { n_read = recvmmsg(fd, hdrs, count, 0, 0); } if (n_read > count) { caml_failwith("bigstring_recvmmsg_assume_fd_is_nonblocking_stub: " "recvmmsg unexpectedly returned n_read > count"); } if (n_read == -1) { uerror("recvmmsg_assume_fd_is_nonblocking", Nothing); } else { if (save_source_addresses) { v_sockaddrs = Field(v_srcs, 0); if (!Is_block(v_sockaddrs)) { caml_invalid_argument("bigstring_recvmmsg_assume_fd_is_nonblocking_stub: " "v_sockaddrs is not an array"); } if (Wosize_val(v_sockaddrs) < count) { caml_invalid_argument("bigstring_recvmmsg_assume_fd_is_nonblocking_stub: " "length v_sockaddrs < count"); } for (i = 0; i < n_read; i++) { value addr = alloc_sockaddr(&addrs[i], hdrs[i].msg_hdr.msg_namelen, -1); Store_field(v_sockaddrs, i, addr); } } for (i = 0; i < n_read; i++) { Field(v_lens, i) = Val_long(hdrs[i].msg_len); } } CAMLreturn(Val_long(n_read)); }