Exemplo n.º 1
0
static int
tipc_setopt(nbio_sock_t socket, tipc_option opt, ...)
{ plsocket_ptr s;
  va_list args;
  int rc;

  if ( !(s = nbio_to_plsocket(socket)) )
    return -1;

  va_start(args, opt);

  switch(opt)
  { case NB_TIPC_IMPORTANCE:
    { int val = va_arg(args, int);

      if ( setsockopt(plsocket_handle(s), SOL_TIPC, TIPC_IMPORTANCE,
		      (const void *)&val, sizeof(val)) == -1 )
      { nbio_error(h_errno, TCP_HERRNO);
	rc = -1;
      } else
	rc = 0;

      break;
    }
    case NB_TIPC_SRC_DROPPABLE:
    case NB_TIPC_DEST_DROPPABLE:
    { int val = va_arg(args, int);
      int level = (opt == NB_TIPC_SRC_DROPPABLE) ? TIPC_SRC_DROPPABLE
						 : TIPC_DEST_DROPPABLE;

      if ( setsockopt(plsocket_handle(s), SOL_TIPC, level,
		      (const void *) &val, sizeof(val)) == -1 )
      { nbio_error(h_errno, TCP_HERRNO);
	rc = -1;
      } else
	rc = 0;

      break;
    }
    case NB_TIPC_CONN_TIMEOUT:
    { int val = va_arg(args, int);

      if ( setsockopt(plsocket_handle(s), SOL_TIPC, TIPC_CONN_TIMEOUT,
		      (const void *) &val, sizeof(val)) == -1 )
      { nbio_error(h_errno, TCP_HERRNO);
	rc = -1;
      } else
	rc = 0;

      break;
    }
    default:
      rc = -1;
      assert(0);
  }

  va_end(args);

  return rc;
}
Exemplo n.º 2
0
static foreign_t
pl_host_to_address(term_t Host, term_t Ip)
{   struct in_addr ip;
    char *host_name;

    if ( PL_get_atom_chars(Host, &host_name) )
    {   struct addrinfo hints;
        struct addrinfo *res;

        memset(&hints, 0, sizeof(hints));
        hints.ai_family = AF_INET;

        if ( getaddrinfo(host_name, NULL, &hints, &res) == 0 )
        {   int rc;

            switch( res->ai_family )
            {
            case AF_INET:
            {   struct sockaddr_in *addr = (struct sockaddr_in*)res->ai_addr;

                rc = nbio_unify_ip4(Ip, ntohl(addr->sin_addr.s_addr));
                break;
            }
            case AF_INET6:
            {   rc = PL_warning("tcp_host_to_address/2: IPv6 address not supported");
                break;
            }
            default:
                assert(0);
                rc = FALSE;
            }

            freeaddrinfo(res);

            return rc;
        } else
        {   return nbio_error(h_errno, TCP_HERRNO);
        }
    } else if ( nbio_get_ip(Ip, &ip) )
    {   struct hostent *host;

        if ( (host = gethostbyaddr((char *)&ip, sizeof(ip), AF_INET)) )
            return PL_unify_atom_chars(Host, host->h_name);
        else
            return nbio_error(h_errno, TCP_HERRNO);
    }

    return FALSE;
}
Exemplo n.º 3
0
static foreign_t
pl_bind(term_t Socket, term_t Address)
{ struct sockaddr_in sockaddr;
  int socket;

  memset(&sockaddr, 0, sizeof(sockaddr));

  if ( !tcp_get_socket(Socket, &socket) ||
       !nbio_get_sockaddr(Address, &sockaddr) )
    return FALSE;

  if ( nbio_bind(socket, (struct sockaddr*)&sockaddr, sizeof(sockaddr)) < 0 )
    return FALSE;

  if ( PL_is_variable(Address) )
  { SOCKET fd = nbio_fd(socket);
    struct sockaddr_in addr;
#ifdef __WINDOWS__
    int len = sizeof(addr);
#else
    socklen_t len = sizeof(addr);
#endif

    if ( getsockname(fd, (struct sockaddr *) &addr, &len) )
      return nbio_error(errno, TCP_ERRNO);
    return PL_unify_integer(Address, ntohs(addr.sin_port));
  }

  return TRUE;
}
Exemplo n.º 4
0
static foreign_t
udp_send(term_t Socket, term_t Data, term_t To, term_t Options)
{ struct sockaddr_in sockaddr;
#ifdef __WINDOWS__
  int alen = sizeof(sockaddr);
#else
  int alen = sizeof(sockaddr);
#endif
  int socket;
  int flags = 0L;
  char *data;
  size_t dlen;
  ssize_t n;

  if ( !PL_get_nchars(Data, &dlen, &data, CVT_ALL|CVT_EXCEPTION) )
    return FALSE;

  if ( !tcp_get_socket(Socket, &socket) ||
       !nbio_get_sockaddr(To, &sockaddr) )
    return FALSE;

  if ( (n=nbio_sendto(socket, data,
		      (int)dlen,
		      flags,
		      (struct sockaddr*)&sockaddr, alen)) == -1 )
    return nbio_error(errno, TCP_ERRNO);

  return TRUE;
}
Exemplo n.º 5
0
static foreign_t
pl_gethostname(term_t name)
{   static atom_t hname;

    if ( !hname )
    {   char buf[256];

        if ( gethostname(buf, sizeof(buf)) == 0 )
        {   struct addrinfo *res;
            struct addrinfo hints;

            memset(&hints, 0, sizeof(hints));
            hints.ai_flags = AI_CANONNAME;

            if ( getaddrinfo(buf, NULL, &hints, &res) == 0 )
            {   hname = PL_new_atom(res->ai_canonname);
                freeaddrinfo(res);
            }
            else
                hname = PL_new_atom(buf);

        } else
        {   return nbio_error(h_errno, TCP_HERRNO);
        }
    }

    return PL_unify_atom(name, hname);
}
Exemplo n.º 6
0
static foreign_t
pl_tipc_subscribe(term_t Socket, term_t Address,
		  term_t timeout, term_t filter, term_t usr_handle)
{ struct sockaddr_tipc sockaddr;
  struct tipc_subscr subscr;
  int socket;
  unsigned time, filt;
  char *handle;
  size_t handle_len;
  SOCKET fd;

  memset(&subscr, 0, sizeof(subscr));
  memset(&sockaddr, 0, sizeof(sockaddr));

  if ( !tipc_get_socket(Socket, &socket) ||
       !nbio_get_tipc_sockaddr(Address, &sockaddr))
    return FALSE;

  if(sockaddr.addrtype != TIPC_ADDR_NAMESEQ)
    return pl_error(NULL, 0, NULL, ERR_DOMAIN, Address, "name_seq/3");

  if( !get_uint(timeout, &time))
    return pl_error(NULL, 0, NULL, ERR_DOMAIN, timeout, "integer");

  if( !get_uint(filter, &filt))
    return pl_error(NULL, 0, NULL, ERR_DOMAIN, filter, "integer");

  if ( !PL_get_nchars(usr_handle, &handle_len, &handle, CVT_ALL|CVT_EXCEPTION) )
    return FALSE;

  if(tipc_version > 1)
  { struct tipc_name_seq *p = &subscr.seq,
                         *p1 = &sockaddr.addr.nameseq;

    p->type = htonl(p1->type);
    p->lower = htonl(p1->lower);
    p->upper = htonl(p1->upper);

    subscr.timeout = htonl(time);
    subscr.filter = htonl((filt == V1_TIPC_SUB_SERVICE) 
                          ? TIPC_SUB_SERVICE 
                          : filt);
  } else {
    memcpy(&subscr.seq, &sockaddr.addr.nameseq, sizeof(subscr.seq));
    subscr.timeout = time;
    subscr.filter = filt;
  }
  memcpy(&subscr.usr_handle, handle, 
         (handle_len < sizeof(subscr.usr_handle)) 
          ? handle_len
          : sizeof(subscr.usr_handle));

  fd = nbio_fd(socket);

  if ( (send(fd, &subscr, sizeof(subscr), 0)) != sizeof(subscr) )
    return nbio_error(errno, TCP_ERRNO);
  else
    return TRUE;
}
Exemplo n.º 7
0
static foreign_t
pl_close_socket(term_t socket)
{ int sock;

  if ( !tcp_get_socket(socket, &sock) )
    return FALSE;

  if ( nbio_closesocket(sock) < 0 )
    return nbio_error(errno, TCP_ERRNO);;

  return TRUE;
}
Exemplo n.º 8
0
static foreign_t
pl_host_to_address(term_t Host, term_t Ip)
{ struct in_addr ip;
  struct hostent *host;
  char *host_name;

  if ( PL_get_atom_chars(Host, &host_name) )
  { if ( (host = gethostbyname(host_name)) )
    { if ( sizeof(ip) == host->h_length )
      { memcpy(&ip, host->h_addr, host->h_length);
	return nbio_unify_ip4(Ip, ntohl(ip.s_addr));
      } else
	return PL_warning("tcp_host_to_address/2: length mismatch in address");
    } else
      return nbio_error(h_errno, TCP_HERRNO);
  } else if ( nbio_get_ip(Ip, &ip) )
  { if ( (host = gethostbyaddr((char *)&ip, sizeof(ip), AF_INET)) )
      return PL_unify_atom_chars(Host, host->h_name);
    else
      return nbio_error(h_errno, TCP_HERRNO);
  }

  return FALSE;
}
Exemplo n.º 9
0
static foreign_t
pl_gethostname(term_t name)
{ static atom_t hname;

  if ( !hname )
  { char buf[256];

    if ( gethostname(buf, sizeof(buf)) == 0 )
    { struct hostent *he;

      if ( (he = gethostbyname(buf)) )
	hname = PL_new_atom(he->h_name);
      else
	hname = PL_new_atom(buf);
    } else
    { return nbio_error(h_errno, TCP_HERRNO);
    }
  }

  return PL_unify_atom(name, hname);
}
Exemplo n.º 10
0
static foreign_t
pl_tipc_basic_get_name(term_t Socket, term_t t, int peer)
{ struct sockaddr_tipc addr;
  int socket;
  SOCKET fd;
#ifdef __WINDOWS__
  int alen = sizeof(addr);
#else
  socklen_t alen = sizeof(addr);
#endif

  memset(&addr, 0, sizeof(addr));

  if ( !tipc_get_socket(Socket, &socket))
    return FALSE;

  fd = nbio_fd(socket);

  if ( (peer) ? getpeername(fd, (struct sockaddr *) &addr, &alen)
			  : getsockname(fd, (struct sockaddr *) &addr, &alen) )
    return nbio_error(errno, TCP_ERRNO);
  else
    return unify_tipc_address(t, &addr);
}
Exemplo n.º 11
0
static foreign_t
udp_receive(term_t Socket, term_t Data, term_t From, term_t options)
{ struct sockaddr_in sockaddr;
#ifdef __WINDOWS__
  int alen = sizeof(sockaddr);
#else
  socklen_t alen = sizeof(sockaddr);
#endif
  int socket;
  int flags = 0;
  char buf[UDP_MAXDATA];
  ssize_t n;
  int as = PL_STRING;

  if ( !PL_get_nil(options) )
  { term_t tail = PL_copy_term_ref(options);
    term_t head = PL_new_term_ref();
    term_t arg  = PL_new_term_ref();

    while(PL_get_list(tail, head, tail))
    { atom_t name;
      int arity;

      if ( PL_get_name_arity(head, &name, &arity) && arity == 1 )
      { _PL_get_arg(1, head, arg);

	if ( name == ATOM_as )
	{ atom_t a;

	  if ( !PL_get_atom(arg, &a) )
	    return pl_error(NULL, 0, NULL, ERR_TYPE, head, "atom");
	  if ( a == ATOM_atom )
	    as = PL_ATOM;
	  else if ( a == ATOM_codes )
	    as = PL_CODE_LIST;
	  else if ( a == ATOM_string )
	    as = PL_STRING;
	  else
	    return pl_error(NULL, 0, NULL, ERR_DOMAIN, arg, "as_option");
	}

      } else
	return pl_error(NULL, 0, NULL, ERR_TYPE, head, "option");
    }
    if ( !PL_get_nil(tail) )
      return pl_error(NULL, 0, NULL, ERR_TYPE, tail, "list");
  }


  if ( !tcp_get_socket(Socket, &socket) ||
       !nbio_get_sockaddr(From, &sockaddr) )
    return FALSE;

  if ( (n=nbio_recvfrom(socket, buf, sizeof(buf), flags,
			(struct sockaddr*)&sockaddr, &alen)) == -1 )
    return nbio_error(errno, TCP_ERRNO);
  if ( !PL_unify_chars(Data, as, n, buf) )
    return FALSE;

  return unify_address(From, &sockaddr);
}
Exemplo n.º 12
0
static foreign_t
pl_tipc_receive_subscr_event(term_t Socket, term_t Data)
{ struct sockaddr_tipc sockaddr;
#ifdef __WINDOWS__
  int alen = sizeof(sockaddr);
#else
  socklen_t alen = sizeof(sockaddr);
#endif
  int socket;
  int flags = 0;
  union {
     char asCodes[sizeof(struct tipc_event)];
     struct tipc_event asEvent;
  } buf;

  ssize_t n;
  struct tipc_event *event = &buf.asEvent;

  memset(&sockaddr, 0, sizeof(sockaddr));

  if ( !tipc_get_socket(Socket, &socket))
    return FALSE;

  if ( (n=nbio_recvfrom(socket, buf.asCodes, sizeof(buf.asCodes), flags,
			(struct sockaddr*)&sockaddr, &alen)) == -1 )
    return nbio_error(errno, TCP_ERRNO);

  if(n != sizeof(*event))
     return FALSE;

  if(tipc_version > 1)
  { struct tipc_name_seq *p = &event->s.seq;

    event->event = ntohl(event->event);
    event->found_lower = ntohl(event->found_lower);
    event->found_upper = ntohl(event->found_upper);

    event->port.ref = ntohl(event->port.ref);
    event->port.node = ntohl(event->port.node);

    p->type = ntohl(p->type);
    p->lower = ntohl(p->lower);
    p->upper = ntohl(p->upper);

    event->s.timeout = ntohl(event->s.timeout);
    event->s.filter = ntohl(event->s.filter);

    if(event->s.filter == TIPC_SUB_SERVICE) 
        event->s.filter = V1_TIPC_SUB_SERVICE;
  }

  switch(event->event) 
  {
      case TIPC_PUBLISHED:
      case TIPC_WITHDRAWN:
        { term_t Found = PL_new_term_ref(),
                 Port_id = PL_new_term_ref(),
                 Subscr = PL_new_term_ref();
          const char *event_chars = (event->event == TIPC_PUBLISHED)
                                    ? "published"
                                    : "withdrawn";

          if(!PL_unify_term(Subscr, PL_FUNCTOR_CHARS, "name_seq", 3,
			   IntArg(event->s.seq.type),
			   IntArg(event->s.seq.lower),
			   IntArg(event->s.seq.upper)))
             return FALSE;

          if(!PL_unify_term(Found, PL_FUNCTOR_CHARS, "name_seq", 3,
			   IntArg(event->s.seq.type),
			   IntArg(event->found_lower),
			   IntArg(event->found_upper)))
             return FALSE;

          if(!PL_unify_term(Port_id, PL_FUNCTOR_CHARS, "port_id", 2,
			   IntArg(event->port.ref),
			   IntArg(event->port.node)))
             return FALSE;

          if(!PL_unify_term(Data, PL_FUNCTOR_CHARS, "tipc_event", 4,
               AtomArg(event_chars),
			   PL_TERM, Subscr,
			   PL_TERM, Found,
			   PL_TERM, Port_id))
             return FALSE;
          
          return TRUE;
        }

      case TIPC_SUBSCR_TIMEOUT:
        {
          return PL_unify_term(Data, PL_FUNCTOR_CHARS, "subscr_timeout", 0);
        }
      default:
          return FALSE;
   };
  return FALSE;
}
Exemplo n.º 13
0
static foreign_t
udp_receive(term_t Socket, term_t Data, term_t From, term_t options)
{   struct sockaddr_in sockaddr;
#ifdef __WINDOWS__
    int alen = sizeof(sockaddr);
#else
    socklen_t alen = sizeof(sockaddr);
#endif
    int socket;
    int flags = 0;
    char smallbuf[UDP_DEFAULT_BUFSIZE];
    char *buf = smallbuf;
    int bufsize = UDP_DEFAULT_BUFSIZE;
    term_t varport = 0;
    ssize_t n;
    int as = PL_STRING;
    int rc;

    if ( !PL_get_nil(options) )
    {   term_t tail = PL_copy_term_ref(options);
        term_t head = PL_new_term_ref();
        term_t arg  = PL_new_term_ref();

        while(PL_get_list(tail, head, tail))
        {   atom_t name;
            size_t arity;

            if ( PL_get_name_arity(head, &name, &arity) && arity == 1 )
            {   _PL_get_arg(1, head, arg);

                if ( name == ATOM_as )
                {   atom_t a;

                    if ( !PL_get_atom(arg, &a) )
                        return pl_error(NULL, 0, NULL, ERR_TYPE, head, "atom");
                    if ( a == ATOM_atom )
                        as = PL_ATOM;
                    else if ( a == ATOM_codes )
                        as = PL_CODE_LIST;
                    else if ( a == ATOM_string )
                        as = PL_STRING;
                    else
                        return pl_error(NULL, 0, NULL, ERR_DOMAIN, arg, "as_option");

                } else if ( name == ATOM_max_message_size )
                {   if ( !PL_get_integer(arg, &bufsize) )
                        return pl_error(NULL, 0, NULL, ERR_TYPE, arg, "integer");
                    if ( bufsize < 0 || bufsize > UDP_MAXDATA )
                        return pl_error(NULL, 0, NULL, ERR_DOMAIN, arg, "0 - 65535");
                }
            } else
                return pl_error(NULL, 0, NULL, ERR_TYPE, head, "option");
        }
        if ( !PL_get_nil(tail) )
            return pl_error(NULL, 0, NULL, ERR_TYPE, tail, "list");
    }

    if ( !tcp_get_socket(Socket, &socket) ||
            !nbio_get_sockaddr(From, &sockaddr, &varport) )
        return FALSE;

    if ( bufsize > UDP_DEFAULT_BUFSIZE )
    {   if ( !(buf = malloc(bufsize)) )
            return pl_error(NULL, 0, NULL, ERR_RESOURCE, "memory");
    }

    if ( (n=nbio_recvfrom(socket, buf, bufsize, flags,
                          (struct sockaddr*)&sockaddr, &alen)) == -1 )
    {   rc = nbio_error(errno, TCP_ERRNO);
        goto out;
    }

    rc = ( PL_unify_chars(Data, as, n, buf) &&
           unify_address(From, &sockaddr)
         );

out:
    if ( buf != smallbuf )
        free(buf);

    return rc;
}