Ticket #22872: ayiya-reconnect.diff

File ayiya-reconnect.diff, 2.4 KB (added by danchr (Dan Villiom Podlaski Christiansen), 8 years ago)

AICCU patch that implements socket recreation

  • common/ayiya.c

    # HG changeset patch
    # User Dan Villiom Podlaski Christiansen <danchr@gmail.com>
    # Date 1454621270 -3600
    #      Thu Feb 04 22:27:50 2016 +0100
    # Node ID 1ea14c7448d2e9367c021c44222e02b253190f96
    # Parent  45ed0847573d0b30ef796c6f58078b3baa76ab91
    ayiya: handle EADDRNOTAVAIL when reading from UDP socket
    
    AICCU uses a UDP socket for communicating with AYIYA servers. The
    general idea is that this connection should be kept alive as long as
    AICCU is running, and generally speaking this is true: As long as the
    computer retains the IPv4 address used that socket bound to,
    everything will work.
    
    However, that assumption is no longer safe on modern laptops. They
    tend to connect and disconnect from networks, and frequently have many
    different IPv4 addresses as time passes.
    
    On OS X, losing the socket IPv4 address results in reads failing
    with errno set to EADDRNOTAVAIL. We handle this by simply recreating
    the socket.
    
    diff --git a/common/ayiya.c b/common/ayiya.c
    a b void ayiya_log(int level, const char *wh 
    7777        dolog(level, buf);
    7878}
    7979
     80static bool ayiya_reconnect(void);
     81static bool ayiya_reconnect(void)
     82{
     83        char *addr = inet_ntoa(ayiya_ipv4_pop);
     84        TLSSOCKET new_socket = connect_client(addr, AYIYA_PORT, AF_INET, SOCK_DGRAM);
     85
     86        if (!new_socket)
     87        {
     88                ayiya_log(LOG_WARNING, reader_name, NULL, 0, "Error while reconnecting to AYIYA server %s: %s (%d)\n", addr, strerror(errno), errno);
     89
     90                return false;
     91        }
     92
     93        ayiya_log(LOG_DEBUG, reader_name, NULL, 0, "Reconnected to server %s...\n", addr);
     94
     95                sock_free(ayiya_socket);
     96        ayiya_socket = new_socket;
     97
     98        return true;
     99}
     100
    80101/* Tun -> Socket */
    81102void ayiya_reader(char *buf, unsigned int length);
    82103void ayiya_reader(char *buf, unsigned int length)
    void ayiya_reader(char *buf, unsigned in 
    137158        if (lenout < 0)
    138159        {
    139160                ayiya_log(LOG_ERR, reader_name, NULL, 0, "Error (%d) while sending %u bytes to network: %s (%d)\n", lenout, length, strerror(errno), errno);
     161
     162#ifdef EADDRNOTAVAIL
     163                if (errno == EADDRNOTAVAIL)
     164                {
     165                        ayiya_reconnect();
     166                }
     167#endif
    140168        }
    141169        else if (length != (unsigned int)lenout)
    142170        {
    void ayiya_beat(void) 
    335363        if (lenout < 0)
    336364        {
    337365                ayiya_log(LOG_ERR, beat_name, NULL, 0, "Error (%d) while sending %u bytes sent to network: %s (%d)\n", lenout, n, strerror(errno), errno);
     366
     367#ifdef EADDRNOTAVAIL
     368                if (errno == EADDRNOTAVAIL)
     369                {
     370                        ayiya_reconnect();
     371                }
     372#endif
    338373        }
    339374        else if (n != lenout)
    340375        {