Пример #1
0
static udp_t *
udp_new (int port_nbr)
{
    udp_t *self = (udp_t *) zmalloc (sizeof (udp_t));
    self->port_nbr = port_nbr;

    //  Create UDP socket
    self->handle = socket (AF_INET, SOCK_DGRAM, IPPROTO_UDP);
    if (self->handle == -1)
        s_handle_io_error ("socket");

    //  Ask operating system to let us do broadcasts from socket
    int on = 1;
    if (setsockopt (self->handle, SOL_SOCKET,
                    SO_BROADCAST, &on, sizeof (on)) == -1)
        s_handle_io_error ("setsockopt (SO_BROADCAST)");

    //  Allow multiple processes to bind to socket; incoming
    //  messages will come to each process
    if (setsockopt (self->handle, SOL_SOCKET,
                    SO_REUSEADDR, &on, sizeof (on)) == -1)
        s_handle_io_error ("setsockopt (SO_REUSEADDR)");

    struct sockaddr_in sockaddr = { 0 };
    sockaddr.sin_family = AF_INET;
    sockaddr.sin_port = htons (self->port_nbr);
    sockaddr.sin_addr.s_addr = htonl (INADDR_ANY);
    if (bind (self->handle, &sockaddr, sizeof (sockaddr)) == -1)
        s_handle_io_error ("bind");

#   if defined (__UNIX__)
    struct ifaddrs *interfaces;
    if (getifaddrs (&interfaces) == 0) {
        struct ifaddrs *interface = interfaces;
        while (interface) {
            //  Hopefully the last interface will be WiFi
            if (interface->ifa_addr->sa_family == AF_INET) {
                self->address = *(struct sockaddr_in *) interface->ifa_addr;
                self->broadcast = *(struct sockaddr_in *) interface->ifa_broadaddr;
                self->broadcast.sin_port = htons (self->port_nbr);
            }
            interface = interface->ifa_next;
        }
    }
    freeifaddrs (interfaces);
#   else
#       error "Interface detection TBD on this operating system"
#   endif
    return self;
}
Пример #2
0
zre_udp_t *
zre_udp_new (int port_nbr)
{
    zre_udp_t *self = (zre_udp_t *) zmalloc (sizeof (zre_udp_t));
    self->port_nbr = port_nbr;

    //  Create UDP socket
    self->handle = socket (AF_INET, SOCK_DGRAM, IPPROTO_UDP);
    if (self->handle == -1)
        s_handle_io_error ("socket");

    //  Ask operating system to let us do broadcasts from socket
    int on = 1;
    if (setsockopt (self->handle, SOL_SOCKET, SO_BROADCAST,
                   (char *) &on, sizeof (on)) == -1)
        s_handle_io_error ("setsockopt (SO_BROADCAST)");

    //  Allow multiple processes to bind to socket; incoming
    //  messages will come to each process
    if (setsockopt (self->handle, SOL_SOCKET, SO_REUSEADDR,
                   (char *) &on, sizeof (on)) == -1)
        s_handle_io_error ("setsockopt (SO_REUSEADDR)");

#if defined (SO_REUSEPORT)
    if (setsockopt (self->handle, SOL_SOCKET, SO_REUSEPORT,
                    (char *) &on, sizeof (on)) == -1)
        s_handle_io_error ("setsockopt (SO_REUSEPORT)");
#endif
    //  PROBLEM: this design will not survive the network interface being
    //  killed and restarted while the program is running.
    struct sockaddr_in sockaddr = { 0 };
    sockaddr.sin_family = AF_INET;
    sockaddr.sin_port = htons (self->port_nbr);
    sockaddr.sin_addr.s_addr = htonl (INADDR_ANY);
    if (bind (self->handle, (struct sockaddr *) &sockaddr, sizeof (sockaddr)) == -1)
        s_handle_io_error ("bind");

    //  Get the network interface (not portable)
    s_get_interface (self);
    
    //  Now get printable address as host name
    if (self->host)
        free (self->host);
    self->host = zmalloc (INET_ADDRSTRLEN);
    getnameinfo ((struct sockaddr *) &self->address, sizeof (self->address),
                 self->host, INET_ADDRSTRLEN, NULL, 0, NI_NUMERICHOST);
    return self;
}
Пример #3
0
static int
s_binding_input (zloop_t *loop, zmq_pollitem_t *item, void *arg)
{
    vocket_t *vocket = (vocket_t *) arg;
    driver_t *driver = vocket->driver;

    struct sockaddr_in addr;        //  Peer address
    socklen_t addr_len = sizeof (addr);

    int handle = accept (item->fd, (struct sockaddr *) &addr, &addr_len);
    if (handle >= 0) {
        s_set_nonblock (handle);
        if (vocket->peerings < vocket->max_peerings) {
            char *address = s_sin_addr_to_str (&addr);
            peering_t *peering = peering_require (vocket, address, FALSE);
            peering->handle = handle;
            peering_raise (peering);
            peering_poller (peering, ZMQ_POLLIN + ZMQ_POLLOUT);
        }
        else {
            zclock_log ("W: Max peerings reached for socket");
            close (handle);
        }
    }
    else
        s_handle_io_error ("accept");

    return 0;
}
Пример #4
0
static void
s_send_wire (peering_t *self)
{
    vocket_t *vocket = self->vocket;
    driver_t *driver = self->driver;

    while (TRUE) {
        byte *data;
        size_t size = vtx_codec_bin_get (self->output, &data);
        if (size == 0) {
            peering_poller (self, ZMQ_POLLIN);
            break;      //  Buffer is empty, stop polling out
        }
        if (driver->verbose)
            zclock_log ("I: (tcp) send %zd bytes to %s",
                size, self->address);
        int bytes_sent = send (self->handle, data, size, 0);
        if (driver->verbose)
            zclock_log ("I: (tcp) actually sent %d bytes", bytes_sent);

        if (bytes_sent > 0) {
            vtx_codec_bin_tick (self->output, bytes_sent);
            if (bytes_sent < size)
                break;      //  Wait until network can accept more
        }
        else
        if (bytes_sent == 0 || s_handle_io_error ("send") == -1) {
            self->exception = TRUE;
            break;          //  Signal error and give up
        }
    }
}
Пример #5
0
static ssize_t
s_recv_wire (peering_t *self)
{
    vocket_t *vocket = self->vocket;
    driver_t *driver = self->driver;

    //  Read into buffer and dump what we got
    //  TODO: only read as much as we have space in input queue
    //  implement exception strategy here
    //  - drop oldest, drop newest, pushback
    byte buffer [VTX_TCP_BUFSIZE];
    ssize_t size = recv (self->handle, buffer, VTX_TCP_BUFSIZE, MSG_DONTWAIT);
    if (size == 0)
        //  Other side closed TCP socket, so our peering is down
        self->exception = TRUE;
    else
    if (size == -1) {
        if (s_handle_io_error ("recv") == -1)
            //  Hard error on socket, so peering is down
            self->exception = TRUE;
    }
    else {
        if (driver->verbose)
            zclock_log ("I: (tcp) recv %zd bytes from %s",
                size, self->address);
        int rc = vtx_codec_bin_put (self->input, buffer, size);
        assert (rc == 0);

        //  store binary data into codec
        //  if routing = request
        //      retrieve message, if available
        //      this is a reply
        //      check reply is allowed in state
        //      then send message through to msgpipe
        //      else discard message
        //      reset state machine on peering
        //  if routing = reply
        //      this is a request
        //      if state allows incoming request
        //          retrieve message, if available
        //          vocket->reply_to = peering
        //          send message through to msgpipe
        //  if routing = router
        //      retrieve message, if available
        //      send schemed identity to msgpipe
        //      send message through to msgpipe
        //  any other routing, nomnom allowed
        //      retrieve message, if available
        //      send message through to msgpipe
#if 0
        else
            zclock_log ("W: unexpected message from %s - dropping", address);
        char *colon = strchr (address, ':');
        assert (colon);
        *colon = 0;
        strcpy (vocket->sender, address);
#endif
    }
Пример #6
0
static void
udp_send (udp_t *self, byte *buffer, size_t length)
{
    assert (self);
    inet_aton ("255.255.255.255", &self->broadcast.sin_addr);
    if (sendto (self->handle, buffer, length, 0,
                &self->broadcast, sizeof (struct sockaddr_in)) == -1)
        s_handle_io_error ("sendto");
}
Пример #7
0
void
zre_udp_send (zre_udp_t *self, byte *buffer, size_t length)
{
    assert (self);
    self->broadcast.sin_addr.s_addr = INADDR_BROADCAST;
    ssize_t size = sendto (self->handle, (char *) buffer, length, 0,
        (struct sockaddr *) &self->broadcast, sizeof (struct sockaddr_in));
    if (size == -1)
        s_handle_io_error ("sendto");
}
Пример #8
0
static ssize_t
udp_recv (udp_t *self, byte *buffer, size_t length)
{
    assert (self);
    
    struct sockaddr_in sockaddr;
    socklen_t si_len = sizeof (struct sockaddr_in);

    ssize_t size = recvfrom (self->handle, buffer, length, 0, &sockaddr, &si_len);
    if (size == -1)
        s_handle_io_error ("recvfrom");

    return size;
}
Пример #9
0
void
zre_udp_send (zre_udp_t *self, byte *buffer, size_t length)
{
    assert (self);
#if (defined (__WINDOWS__))
    self->broadcast.sin_addr.s_addr = INADDR_BROADCAST;
#else
    inet_aton ("255.255.255.255", &self->broadcast.sin_addr);
#endif
    if (sendto (self->handle, (char *)buffer, length, 0,
                (struct sockaddr *) &self->broadcast, 
                sizeof (struct sockaddr_in)) == -1)
        s_handle_io_error ("sendto");
}
Пример #10
0
ssize_t
zre_udp_recv (zre_udp_t *self, byte *buffer, size_t length)
{
    assert (self);
    
    socklen_t si_len = sizeof (struct sockaddr_in);
    ssize_t size = recvfrom (self->handle, (char *) buffer, length, 0,
        (struct sockaddr *) &self->sender, &si_len);
    if (size == -1)
        s_handle_io_error ("recvfrom");

    //  Store sender address as printable string
    if (self->from)
        free (self->from);
    self->from = zmalloc (INET_ADDRSTRLEN);
#if (defined (__WINDOWS__))
    getnameinfo ((struct sockaddr *) &self->sender, si_len,
                 self->from, INET_ADDRSTRLEN, NULL, 0, NI_NUMERICHOST);
#else
    inet_ntop (AF_INET, &self->sender.sin_addr, self->from, si_len);
#endif
    return size;
}
Пример #11
0
static void
s_get_interface (zre_udp_t *self)
{
#if defined (__UNIX__)
#   if defined (HAVE_GETIFADDRS) && defined (HAVE_FREEIFADDRS)
    struct ifaddrs *interfaces;
    if (getifaddrs (&interfaces) == 0) {
        struct ifaddrs *interface = interfaces;
        while (interface) {
            //  Hopefully the last interface will be WiFi or Ethernet
            if (interface->ifa_addr->sa_family == AF_INET) {
                self->address = *(struct sockaddr_in *) interface->ifa_addr;
                self->broadcast = *(struct sockaddr_in *) interface->ifa_broadaddr;
                self->broadcast.sin_port = htons (self->port_nbr);
                if (s_wireless_nic (interface->ifa_name))
                    break;
            }
            interface = interface->ifa_next;
        }
    }
    freeifaddrs (interfaces);
#   else
    struct ifreq ifr;
    memset (&ifr, 0, sizeof (ifr));

#   if !defined (LIBZRE_HAVE_ANDROID)
    //  TODO: Using hardcoded wlan0 is ugly
    if (!s_wireless_nic ("wlan0"))
        s_handle_io_error ("wlan0_not_exist");
#   endif

    int sock = 0;
    if ((sock = socket(AF_INET, SOCK_DGRAM, 0)) < 0)
        s_handle_io_error ("foo_socket_not_opened");

    //  Get interface address
    ifr.ifr_addr.sa_family = AF_INET;
    strncpy (ifr.ifr_name, "wlan0", sizeof (ifr.ifr_name));
    int rc = ioctl (sock, SIOCGIFADDR, (caddr_t) &ifr, sizeof (struct ifreq));
    if (rc == -1)
        s_handle_io_error ("siocgifaddr");

    //  Get interface broadcast address
    memcpy (&self->address, ((struct sockaddr_in *) &ifr.ifr_addr),
        sizeof (struct sockaddr_in));
    rc = ioctl (sock, SIOCGIFBRDADDR, (caddr_t) &ifr, sizeof (struct ifreq));
    if (rc == -1)
        s_handle_io_error ("siocgifbrdaddr");

    memcpy (&self->broadcast, ((struct sockaddr_in *) &ifr.ifr_broadaddr),
        sizeof (struct sockaddr_in));
    self->broadcast.sin_port = htons (self->port_nbr);
    close (sock);
#   endif

#   elif defined (__WINDOWS__)
    //  Currently does not filter for wireless NIC
    ULONG addr_size = 0;
    DWORD rc = GetAdaptersAddresses (AF_INET,
        GAA_FLAG_INCLUDE_PREFIX, NULL, NULL, &addr_size);
    assert (rc == ERROR_BUFFER_OVERFLOW);

    PIP_ADAPTER_ADDRESSES pip_addresses = malloc (addr_size);
    rc = GetAdaptersAddresses (AF_INET,
        GAA_FLAG_INCLUDE_PREFIX, NULL, pip_addresses, &addr_size);
    assert (rc == NO_ERROR);

    PIP_ADAPTER_ADDRESSES cur_address = pip_addresses;
    while (cur_address) {
        PIP_ADAPTER_UNICAST_ADDRESS pUnicast = cur_address->FirstUnicastAddress;
        PIP_ADAPTER_PREFIX pPrefix = cur_address->FirstPrefix;

        if (pUnicast && pPrefix) {
            //  self->broadcast.sin_addr is replaced with 255.255.255.255 in zre_udp_send()
            self->address = *(struct sockaddr_in *)(pUnicast->Address.lpSockaddr);
            self->broadcast = *(struct sockaddr_in *)(pPrefix->Address.lpSockaddr);
            self->broadcast.sin_addr.s_addr |= htonl ((1 << (32 - pPrefix->PrefixLength)) - 1);
        }
        self->broadcast.sin_port = htons (self->port_nbr);
        cur_address = cur_address->Next;
    }
    free (pip_addresses);
#   else
#       error "Interface detection TBD on this operating system"
#   endif
}
Пример #12
0
zre_udp_t *
zre_udp_new (int port_nbr)
{
    zre_udp_t *self = (zre_udp_t *) zmalloc (sizeof (zre_udp_t));
    self->port_nbr = port_nbr;

    //  Create UDP socket
    self->handle = socket (AF_INET, SOCK_DGRAM, IPPROTO_UDP);
    if (self->handle == -1)
        s_handle_io_error ("socket");

    //  Ask operating system to let us do broadcasts from socket
    int on = 1;
    if (setsockopt (self->handle, SOL_SOCKET,
                    SO_BROADCAST, (char *)&on, sizeof (on)) == -1)
        s_handle_io_error ("setsockopt (SO_BROADCAST)");

    //  Allow multiple processes to bind to socket; incoming
    //  messages will come to each process
    if (setsockopt (self->handle, SOL_SOCKET,
                    SO_REUSEADDR, (char *)&on, sizeof (on)) == -1)
        s_handle_io_error ("setsockopt (SO_REUSEADDR)");

#if defined (SO_REUSEPORT)
    if (setsockopt (self->handle, SOL_SOCKET,
                    SO_REUSEPORT, &on, sizeof (on)) == -1)
        s_handle_io_error ("setsockopt (SO_REUSEPORT)");
#endif
    //  PROBLEM: this design will not survive the network interface being
    //  killed and restarted while the program is running.
    struct sockaddr_in sockaddr = { 0 };
    sockaddr.sin_family = AF_INET;
    sockaddr.sin_port = htons (self->port_nbr);
    sockaddr.sin_addr.s_addr = htonl (INADDR_ANY);
    if (bind (self->handle, (struct sockaddr *) &sockaddr, sizeof (sockaddr)) == -1)
        s_handle_io_error ("bind");

#   if defined (__UNIX__)

#   if defined (HAVE_GETIFADDRS) && defined (HAVE_FREEIFADDRS)
    struct ifaddrs *interfaces;
    if (getifaddrs (&interfaces) == 0) {
        struct ifaddrs *interface = interfaces;
        while (interface) {
            //  Hopefully the last interface will be WiFi
            if (interface->ifa_addr->sa_family == AF_INET) {
                self->address = *(struct sockaddr_in *) interface->ifa_addr;
                self->broadcast = *(struct sockaddr_in *) interface->ifa_broadaddr;
                self->broadcast.sin_port = htons (self->port_nbr);
                if (s_wireless_nic (interface->ifa_name))
                    break;
            }
            interface = interface->ifa_next;
        }
    }
    freeifaddrs (interfaces);
#   else 
    struct ifreq ifr;
    memset (&ifr, 0, sizeof (ifr));
    /*  TODO: Using hardcoded wlan0 is ugly */ 

#   if !defined ( LIBZRE_HAVE_ANDROID )
    if (!s_wireless_nic ("wlan0"))
        s_handle_io_error ("wlan0_not_exist");
#   endif

    int sock = 0;
    if ((sock = socket(AF_INET, SOCK_DGRAM, 0)) < 0)
        s_handle_io_error ("foo_socket_not_opened");
    
    ifr.ifr_addr.sa_family = AF_INET;
    strncpy (ifr.ifr_name, "wlan0", sizeof (ifr.ifr_name));
    int rc = ioctl (sock, SIOCGIFADDR, (caddr_t) &ifr, sizeof (struct ifreq));
    if (rc == -1)
        s_handle_io_error ("siocgifaddr");
    
    memcpy (&self->address, ((struct sockaddr_in*) &ifr.ifr_addr), sizeof (struct sockaddr_in));
    rc = ioctl (sock, SIOCGIFBRDADDR, (caddr_t) &ifr, sizeof (struct ifreq));
    if (rc == -1)
        s_handle_io_error ("siocgifbrdaddr");
    
    memcpy (&self->broadcast, ((struct sockaddr_in*) &ifr.ifr_broadaddr), sizeof (struct sockaddr_in));
    self->broadcast.sin_port = htons (self->port_nbr);
    close (sock);
#   endif
    if (self->host)
        free (self->host);
    
    self->host = zmalloc (INET_ADDRSTRLEN);
    inet_ntop (AF_INET, &self->address.sin_addr, self->host, sizeof (sockaddr));
#   elif defined (__WINDOWS__)
    s_win_get_interface(self);
    if (self->host)
        free (self->host);
    
    self->host = zmalloc (INET_ADDRSTRLEN);
    getnameinfo ((struct sockaddr *)&self->address, sizeof (self->address), self->host, INET_ADDRSTRLEN, NULL, 0, NI_NUMERICHOST);
#   else
#       error "Interface detection TBD on this operating system"
#   endif
    return self;
}
Пример #13
0
static ssize_t
s_recv_wire (peering_t *self)
{
    vocket_t *vocket = self->vocket;
    driver_t *driver = self->driver;

    //  Read into buffer and dump what we got
    //  TODO: only read as much as we have space in input queue
    //  implement exception strategy here
    //  - drop oldest, drop newest, pushback
    byte buffer [VTX_TCP_BUFSIZE];
    ssize_t size = recv (self->handle, buffer, VTX_TCP_BUFSIZE, MSG_DONTWAIT);
    if (size == 0)
        //  Other side closed TCP socket, so our peering is down
        self->exception = TRUE;
    else
    if (size == -1) {
        if (s_handle_io_error ("recv") == -1)
            //  Hard error on socket, so peering is down
            self->exception = TRUE;
    }
    else {
        if (driver->verbose)
            zclock_log ("I: (tcp) recv %zd bytes from %s",
                size, self->address);
        int rc = vtx_codec_bin_put (self->input, buffer, size);
        assert (rc == 0);

        Bool first_part = !self->more;
        Bool more;
        zmq_msg_t msg;
        zmq_msg_init (&msg);
        rc = vtx_codec_msg_get (self->input, &msg, &more);
        while (rc == 0) {
            if (vocket->routing == VTX_ROUTING_REQUEST) {
                //  TODO state check
                //  TODO Is reply expected to come from thes peering?
                int flags = ZMQ_DONTWAIT;
                if (more)
                    flags |= ZMQ_SNDMORE;
                zmq_sendmsg (vocket->msgpipe, &msg, flags);
            }
            else
            if (vocket->routing == VTX_ROUTING_REPLY) {
                //  TODO state check
                vocket->current_peering = self;
                int flags = ZMQ_DONTWAIT;
                if (more)
                    flags |= ZMQ_SNDMORE;
                zmq_sendmsg (vocket->msgpipe, &msg, flags);
            }
            else
            if (vocket->routing == VTX_ROUTING_ROUTER) {
                //  Send peering's ID
                if (first_part) {
                    size_t id_size = strlen(driver->scheme)
                                   + strlen("://")
                                   + strlen(self->address);
                    zmq_msg_t msg;
                    rc = zmq_msg_init_size (&msg, id_size + 1);
                    assert (rc == 0);
                    strcpy (zmq_msg_data (&msg), driver->scheme);
                    strcat (zmq_msg_data (&msg), "://");
                    strcat (zmq_msg_data (&msg), self->address);
                    zmq_sendmsg (vocket->msgpipe, &msg, ZMQ_DONTWAIT|ZMQ_SNDMORE);
                    zmq_msg_close (&msg);
                }
                int flags = ZMQ_DONTWAIT;
                if (more)
                    flags |= ZMQ_SNDMORE;
                zmq_sendmsg (vocket->msgpipe, &msg, flags);
            }
            else
            if (vocket->nomnom) {
                int flags = ZMQ_DONTWAIT;
                if (more)
                    flags |= ZMQ_SNDMORE;
                zmq_sendmsg (vocket->msgpipe, &msg, flags);
            }
            zmq_msg_close (&msg);
            zmq_msg_init (&msg);
            self->more = more;
            first_part = !more;
            rc = vtx_codec_msg_get (self->input, &msg, &more);
        }
#if 0
        else
            zclock_log ("W: unexpected message from %s - dropping", address);
        char *colon = strchr (address, ':');
        assert (colon);
        *colon = 0;
        strcpy (vocket->sender, address);
#endif
    }