Beispiel #1
0
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);
}
Beispiel #2
0
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;
}
Beispiel #3
0
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;
}
Beispiel #4
0
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);
}
Beispiel #5
0
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);
}
Beispiel #6
0
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);
}
Beispiel #7
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);
}
Beispiel #9
0
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);
}
Beispiel #10
0
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;
}
Beispiel #11
0
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));
}