]> git.karo-electronics.de Git - mdnsd.git/blobdiff - mhttp.c
Cosmetic
[mdnsd.git] / mhttp.c
diff --git a/mhttp.c b/mhttp.c
index 31e16386fd991c7eb88520d8b09ca3e8e3601d28..6333163c1df7d86f9d127b0ee1598d38ffa0baf8 100644 (file)
--- a/mhttp.c
+++ b/mhttp.c
@@ -1,5 +1,3 @@
-#define _GNU_SOURCE
-
 #include <sys/types.h>
 #include <sys/socket.h>
 #include <netinet/in.h>
 #include <signal.h>
 #include <poll.h>
 #include <sys/time.h>
+#include <sys/stat.h>
 
 #include "mdnsd.h"
-#include "sdtxt.h"
-#include "netwatch.h"
+#include "dns_sd_txt.h"
+
+#ifdef UNUSED
+#elif defined(__GNUC__)
+# define UNUSED(x) UNUSED_ ## x __attribute__((unused))
+#elif defined(__LCLINT__)
+# define UNUSED(x) /*@unused@*/ x
+#else
+# define UNUSED(x) x
+#endif
 
 #define HOSTNAMESIZE 64
-#define FIFO_PATH "/tmp/mdns-fifo"
 
-enum {
-   MDNSD_STARTUP,
-   MDNSD_PROBE,
-   MDNSD_ANNOUNCE,
-   MDNSD_RUN,
-   MDNSD_SHUTDOWN
-};
+typedef enum {
+    MDNSD_PROBE,
+    MDNSD_ANNOUNCE,
+    MDNSD_RUN,
+    MDNSD_SHUTDOWN
+} TMdnsdState;
 
-typedef struct _ipcam_service_info
+typedef struct _service_info
 {
-  mdnsd          dnsd;
-  char           hostname[HOSTNAMESIZE];
-  char          *servicename;
+    TMdnsd        *mdnsd;
+    char           hostname[HOSTNAMESIZE];
+    char          *servicename;
 
-  int            port;
-  char          *label;
-  char          *ip;
-  int            link;
+    char          *ip;
+    int            port;
 
-  xht            metadata;
+    /* service-discovery records */
+    TMdnsdRecord  *host_to_ip;
+    TMdnsdRecord  *ip_to_host;
+    struct in_addr announce_ip;
 
-  /* service-discovery records */
-  mdnsdr         host_to_ip;
-  mdnsdr         ip_to_host;
+    SHASH          metadata;
 
-  mdnsdr         srv_to_host;
-  mdnsdr         txt_for_srv;
+    /* service-discovery records */
+    TMdnsdRecord  *srv_to_host;
+    TMdnsdRecord  *txt_for_srv;
 
-  mdnsdr         ptr_to_srv;
+    TMdnsdRecord  *ptr_to_srv;
 
-  int            state;
-} IpcamServiceInfo;
+    TMdnsdState    state;
+} ServiceInfo;
 
-static IpcamServiceInfo ipcam_info;
-static int signal_pipe[2];
-static int fifo_fd;
+static ServiceInfo service_info;
 
-void     request_service (IpcamServiceInfo *info, int stage);
+void     request_service      (ServiceInfo *info, int stage);
+void     request_ip_addresses (ServiceInfo *info);
 
-char *
-increment_name (char *name)
+char *increment_name (char *name)
 {
-  int   id = 1;
-  char *pos, *end = NULL;
-  char *ret = NULL;
-
-  pos = strrchr (name, '-');
-
-  if (pos)
-    {
-      id = strtol (pos + 1, &end, 10);
-      if (*end == '\0')
-        *pos = '\0';
-      else
-        id = 1;
+    int   id = 1;
+    char *pos;
+       char *end = NULL;
+    char *ret = NULL;
+
+    pos = strrchr (name, '-');
+
+    if (pos) {
+        id = strtol (pos + 1, &end, 10);
+        if (*end == '\0') {
+            *pos = '\0';
+               } else {
+            id = 1;
+               }
     }
 
-  id += 1;
+    id += 1;
 
-  asprintf (&ret, "%s-%d", name, id);
+    asprintf (&ret, "%s-%d", name, id);
 
-  return ret;
+    return ret;
 }
 
 
 /* conflict handling */
-void
-handle_conflict (char *name, int type, void *arg)
+void handle_conflict (TMdnsdRecord *record, char *name, int UNUSED(type), void *arg)
 {
-  IpcamServiceInfo *info = (IpcamServiceInfo *) arg;
-  char *newname;
+    ServiceInfo *info = (ServiceInfo *) arg;
+    char *newname;
 
-  if (info->servicename == NULL)
-    {
-      newname = increment_name (info->hostname);
+    if (record == info->ip_to_host) {
+        /* can't do anything about a reverse lookup conflict. Just stop
+         * announcing it. */
+        info->ip_to_host = NULL;
+        fprintf (stderr, "zeroconf reverse lookup conflict for %s!\n", info->ip);
+        return;
     }
-  else
-    {
-      newname = increment_name (info->servicename);
-      free (info->servicename);
+
+    if (record == info->host_to_ip) {
+        info->host_to_ip = NULL;
+        info->announce_ip.s_addr = 0;
     }
 
-  info->servicename = newname;
+    if (info->servicename == NULL) {
+        newname = increment_name (info->hostname);
+    } else {
+        newname = increment_name (info->servicename);
+        free (info->servicename);
+    }
 
-  switch (type)
-    {
-      case QTYPE_A:
-        info->host_to_ip = NULL;
-        break;
-      case QTYPE_PTR:
-        info->ip_to_host = NULL;
-        break;
-      case QTYPE_SRV:
+    info->servicename = newname;
+
+    if (record == info->srv_to_host) {
         info->srv_to_host = NULL;
-        break;
-      case QTYPE_TXT:
+       }
+
+    if (record == info->txt_for_srv) {
         info->txt_for_srv = NULL;
-        break;
-      default:
-        fprintf (stderr, "Huh?\n");
-    }
-  fprintf (stderr, "conflicting name \"%s\". trying %s\n",
-           name, info->servicename);
+       }
+
+    fprintf (stderr, "conflicting name \"%s\". trying %s\n",
+             name, info->servicename);
 
-  info->state = MDNSD_PROBE;
-  write (signal_pipe[1], " ", 1);
+       /* The hostname was changed, so go back to probe state */
+    info->state = MDNSD_PROBE;
 }
 
 
 /* quit and updates */
 void sighandler (int sig)
 {
-  if (sig != SIGHUP)
-    {
-      ipcam_info.state = MDNSD_SHUTDOWN;
+    if (sig != SIGHUP) {
+        service_info.state = MDNSD_SHUTDOWN;
     }
-
-  write (signal_pipe[1], " ", 1);
 }
 
 
 /* create multicast 224.0.0.251:5353 socket */
-int
-msock ()
+int msock ()
 {
-  int s, flag = 1, ittl = 255;
-  struct sockaddr_in in;
-  struct ip_mreq mc;
-  char ttl = 255;
-
-  bzero (&in, sizeof (in));
-  in.sin_family = AF_INET;
-  in.sin_port = htons (5353);
-  in.sin_addr.s_addr = 0;
-
-  if ((s = socket (AF_INET,SOCK_DGRAM,0)) < 0)
-    return 0;
-
-  setsockopt(s, SOL_SOCKET, SO_REUSEADDR, (char*) &flag, sizeof (flag));
-  if (bind (s, (struct sockaddr*) &in, sizeof (in)))
-    {
-      close(s);
-      return 0;
+    int    sock_fd;
+       int    flag = 1;
+       int    ittl = 255;
+    char   ttl = 255;
+    struct sockaddr_in in;
+    struct ip_mreq mc;
+
+    bzero (&in, sizeof (in));
+    in.sin_family = AF_INET;
+    in.sin_port = htons (MDNS_PORT);
+    in.sin_addr.s_addr = 0;
+
+    if ((sock_fd = socket (AF_INET, SOCK_DGRAM, 0)) < 0) {
+        return 0;
+       }
+
+    setsockopt(sock_fd, SOL_SOCKET, SO_REUSEADDR, (char*) &flag, sizeof (flag));
+    if (bind (sock_fd, (struct sockaddr*) &in, sizeof (in))) {
+        close(sock_fd);
+        return 0;
     }
 
-  mc.imr_multiaddr.s_addr = inet_addr ("224.0.0.251");
-  mc.imr_interface.s_addr = htonl (INADDR_ANY);
-  setsockopt (s, IPPROTO_IP, IP_ADD_MEMBERSHIP, &mc,   sizeof (mc));
-  setsockopt (s, IPPROTO_IP, IP_MULTICAST_TTL,  &ttl,  sizeof (ttl));
-  setsockopt (s, IPPROTO_IP, IP_MULTICAST_TTL,  &ittl, sizeof (ittl));
-
-  flag =  fcntl (s, F_GETFL, 0);
-  flag |= O_NONBLOCK;
-  fcntl (s, F_SETFL, flag);
+    mc.imr_multiaddr.s_addr = inet_addr ("224.0.0.251");
+    mc.imr_interface.s_addr = htonl (INADDR_ANY);
+    setsockopt (sock_fd, IPPROTO_IP, IP_ADD_MEMBERSHIP, &mc,   sizeof (mc));
+    setsockopt (sock_fd, IPPROTO_IP, IP_MULTICAST_TTL,  &ttl,  sizeof (ttl));
+    setsockopt (sock_fd, IPPROTO_IP, IP_MULTICAST_TTL,  &ittl, sizeof (ittl));
 
-  return s;
-}
+    flag =  fcntl (sock_fd, F_GETFL, 0);
+    flag |= O_NONBLOCK;
+    fcntl (sock_fd, F_SETFL, flag);
 
-void
-request_service (IpcamServiceInfo *info, int stage)
-{
-  unsigned char *packet, servlocal[256], hostlocal[256], revlookup[256];
-  int len = 0;
-  unsigned long ip;
-
-  if (!info->ip)
-    return;
-
-  ip = inet_addr (info->ip);
-
-  sprintf (servlocal, "%s._http._tcp.local.",
-           info->servicename ? info->servicename : info->hostname);
-  sprintf (hostlocal, "%s.local.",
-           info->servicename ? info->servicename : info->hostname);
-  sprintf (revlookup, "%ld.%ld.%ld.%ld.in-addr.arpa.",
-           (ip >> 24) & 0xff, (ip >> 16) & 0xff, (ip >> 8) & 0xff, (ip >> 0) & 0xff);
-
-  /*
-   * Timeouts according to
-   *   http://files.multicastdns.org/draft-cheshire-dnsext-multicastdns.txt
-   *
-   * As a general rule, the recommended TTL value for Multicast DNS
-   * resource records with a host name as the resource record's name
-   * (e.g. A, AAAA, HINFO, etc.) or contained within the resource record's
-   * rdata (e.g. SRV, reverse mapping PTR record, etc.) is 120 seconds.
-   *
-   * The recommended TTL value for other Multicast DNS resource records
-   * is 75 minutes.
-   */
-
-  switch (stage)
-    {
-      case 0:
-        if (!info->host_to_ip)
-          {
-            info->host_to_ip  = mdnsd_unique (info->dnsd, hostlocal,
-                                              QTYPE_A, 120, handle_conflict, info);
-          }
-        mdnsd_set_raw (info->dnsd, info->host_to_ip, (unsigned char *) &ip, 4);
-
-        if (!info->ip_to_host)
-          {
-            info->ip_to_host  = mdnsd_unique (info->dnsd, revlookup,
-                                              QTYPE_PTR, 120, handle_conflict, info);
-          }
-        mdnsd_set_host (info->dnsd, info->ip_to_host, hostlocal);
-        break;
-
-      case 1:
-        if (!info->srv_to_host)
-          {
-            info->srv_to_host = mdnsd_unique (info->dnsd, servlocal,
-                                              QTYPE_SRV, 120, handle_conflict, info);
-          }
-        mdnsd_set_srv (info->dnsd, info->srv_to_host, 0, 0,
-                       info->port, hostlocal);
-
-        if (!info->txt_for_srv)
-          {
-            info->txt_for_srv = mdnsd_unique (info->dnsd, servlocal,
-                                              QTYPE_TXT, 4500, handle_conflict, info);
-          }
-        packet = sd2txt (info->metadata, &len);
-        mdnsd_set_raw (info->dnsd, info->txt_for_srv, packet, len);
-        free(packet);
-        break;
-
-      case 2:
-        if (!info->ptr_to_srv)
-          {
-            info->ptr_to_srv  = mdnsd_shared (info->dnsd, "_http._tcp.local.",
-                                              QTYPE_PTR, 4500);
-          }
-        mdnsd_set_host (info->dnsd, info->ptr_to_srv, servlocal);
-
-        fprintf (stderr, "Announcing .local site named '%s' to %s:%d (%s)\n", hostlocal,
-                 info->ip, info->port, servlocal);
-        break;
-
-      default:
-        fprintf (stderr, "announce stage %d is invalid\n", stage);
-        break;
-    }
+    return sock_fd;
 }
 
-void
-update_port_info (IpcamServiceInfo *info, int port)
+void request_ip_addresses (ServiceInfo *info)
 {
-  unsigned char hostlocal[256];
-
-  if (port == info->port)
-    return;
+    char revlookup[256];
+       char hostlocal[256];
+    struct in_addr ip;
+    int  num_ips = 0;
 
-  info->port = port;
+    sprintf (hostlocal, "%s.local.", info->servicename ? info->servicename : info->hostname);
 
-  if (!info->srv_to_host)
-    return;
+    if (info->ip) {
+        ip.s_addr = inet_addr (info->ip);
 
-  sprintf (hostlocal, "%s.local.",
-           info->servicename ? info->servicename : info->hostname);
+        if (ip.s_addr != info->announce_ip.s_addr) {
+            snprintf (revlookup, 256, "%d.%d.%d.%d.in-addr.arpa.",
+                      (ip.s_addr >> 24) & 0xff, (ip.s_addr >> 16) & 0xff,
+                      (ip.s_addr >> 8) & 0xff, (ip.s_addr >> 0) & 0xff);
 
-  fprintf (stderr, "mhttp: updating port info to port %d\n", info->port);
-  mdnsd_set_srv (info->dnsd, info->srv_to_host, 0, 0,
-                 info->port, hostlocal);
-}
+            if (!info->host_to_ip) {
+                info->host_to_ip  = MdnsdAllocUnique(info->mdnsd, hostlocal,
+                                                             QTYPE_A, 120, handle_conflict, info);
+            }
+            MdnsdSetRaw (info->mdnsd, info->host_to_ip, (char *) &ip, 4);
 
-void
-iface_change_callback (int   link_index,
-                       char *label,
-                       char *ipaddr,
-                       int   add,
-                       void *user_data)
-{
-  IpcamServiceInfo *info = (IpcamServiceInfo *) user_data;
+            if (!info->ip_to_host) {
+                info->ip_to_host  = MdnsdAllocUnique(info->mdnsd, revlookup,
+                                                             QTYPE_PTR, 120, handle_conflict, info);
+            }
+            MdnsdSetHost (info->mdnsd, info->ip_to_host, hostlocal);
 
-  if (strcmp (info->label, label) != 0)
-    return;
+            info->announce_ip = ip;
+        }
 
-  if (add && (!info->ip ||
-              strcmp (info->ip, ipaddr) != 0 ||
-              info->link != link_index))
-    {
-      if (info->ip)
-        free (info->ip);
-      info->ip = strdup (ipaddr);
-      info->link = link_index;
-    }
+        num_ips++;
+    } else {
+        if (info->host_to_ip) {
+            MdnsdDone (service_info.mdnsd, info->host_to_ip);
+               }
+        if (info->ip_to_host) {
+            MdnsdDone (service_info.mdnsd, info->ip_to_host);
+               }
 
-  if (!add && info->ip)
-    {
-      free (info->ip);
-      info->ip = NULL;
-      info->link = -1;
+        info->host_to_ip = NULL;
+        info->ip_to_host = NULL;
+        info->announce_ip.s_addr = 0;
     }
-
-  info->state = MDNSD_PROBE;
-  write (signal_pipe[1], " ", 1);
 }
 
-
-void
-iface_link_callback (int   link_index,
-                     int   running,
-                     void *user_data)
+void request_service (ServiceInfo *info, int stage)
 {
-  IpcamServiceInfo *info = (IpcamServiceInfo *) user_data;
+    uint8_t *packet;
+       char     servlocal[256];
+       char     hostlocal[256];
+    int      len = 0;
+
+    sprintf (servlocal, "%s._http._tcp.local.",
+             info->servicename ? info->servicename : info->hostname);
+
+    /*
+     * Timeouts according to
+     *   http://files.multicastdns.org/draft-cheshire-dnsext-multicastdns.txt
+     *
+     * As a general rule, the recommended TTL value for Multicast DNS
+     * resource records with a host name as the resource record's name
+     * (e.g. A, AAAA, HINFO, etc.) or contained within the resource record's
+         * rdata (e.g. SRV, reverse mapping PTR record, etc.) is 120 seconds.
+             *
+     * The recommended TTL value for other Multicast DNS resource records
+     * is 75 minutes.
+     */
+
+    switch (stage)
+    {
+        case 0:
+            request_ip_addresses (info);
 
-  if (link_index != info->link)
-    return;
+            break;
 
+        case 1:
+            sprintf (hostlocal, "%s.local.",
+                     info->servicename ? info->servicename : info->hostname);
 
-  info->state = running ? MDNSD_PROBE : MDNSD_STARTUP;
-  write (signal_pipe[1], " ", 1);
-}
+            if (!info->srv_to_host) {
+                info->srv_to_host = MdnsdAllocUnique (info->mdnsd, servlocal,
+                                                      QTYPE_SRV, 120, handle_conflict, info);
+            }
 
+            MdnsdSetSrv (info->mdnsd, info->srv_to_host, 0, 0, info->port, hostlocal);
 
-int main(int argc, char *argv[])
-{
-  struct message msg;
-  unsigned short int port;
-  struct timeval tv;
-  int bsize, ssize = sizeof(struct sockaddr_in);
-  unsigned char buf[MAX_PACKET_LEN];
-  struct sockaddr_in from, to;
-  int i, s;
-  int nlink;
-  unsigned long remote_ip;
-  char *value;
-  int polltime = 0;
-  int announce_stage = 0;
-  struct pollfd fds[4];
-
-  if(argc < 3)
-    {
-      fprintf (stderr, "usage: mhttp <label> <port> <key1>=<value1> <key2>=<value2> ...\n");
-      fprintf (stderr, "   <label> is the label of the network interface to be watched\n");
-      fprintf (stderr, "   <port> is the port number of the service to be advertized\n");
-      fprintf (stderr, "   <key>=<value> are the keys that get embedded into the TXT record.\n");
-      fprintf (stderr, "\n   The port later can be changed by writing \"port:8080\" to " FIFO_PATH ".\n");
-      return -1;
-    }
+            if (!info->txt_for_srv) {
+                info->txt_for_srv = MdnsdAllocUnique (info->mdnsd, servlocal,
+                                                      QTYPE_TXT, 4500, handle_conflict, info);
+            }
 
-  ipcam_info.dnsd = mdnsd_new (1, 1000);
+            packet = DnsSd2Txt (info->metadata, &len);
+            MdnsdSetRaw (info->mdnsd, info->txt_for_srv, packet, len);
+            free(packet);
+            break;
 
-  ipcam_info.state = MDNSD_STARTUP;
+        case 2:
+            if (!info->ptr_to_srv) {
+                info->ptr_to_srv  = MdnsdAllocShared (info->mdnsd, "_http._tcp.local.",
+                                                  QTYPE_PTR, 4500);
+            }
+            MdnsdSetHost (info->mdnsd, info->ptr_to_srv, servlocal);
 
-  gethostname (ipcam_info.hostname, HOSTNAMESIZE);
-  ipcam_info.hostname[HOSTNAMESIZE-1] = '\0';
-  if (strchr (ipcam_info.hostname, '.'))
-    strchr (ipcam_info.hostname, '.')[0] = '\0';
+            if (info->ip) {
+                fprintf (stderr, "Announcing \"%s.local\" to %s:%d\n",
+                         info->servicename ? info->servicename : info->hostname,
+                         info->ip, info->port);
+                       }
+            break;
 
-  ipcam_info.servicename = NULL;
-  ipcam_info.label = argv[1];
-  ipcam_info.ip = NULL;
-  ipcam_info.link = -1;
-  ipcam_info.port = atoi(argv[2]);
+        default:
+            fprintf (stderr, "announce stage %d is invalid\n", stage);
+            break;
+    }
+}
 
-  ipcam_info.metadata = xht_new (11);
-  for (i = 3; i < argc; i++)
+int main(int argc, char *argv[])
+{
+    DNSMESSAGE msg;
+    uint16_t   port;
+    struct timeval tv;
+    int        bsize;
+       int        ssize = sizeof(struct sockaddr_in);
+    uint8_t    buf[MAX_PACKET_LEN];
+    struct sockaddr_in from;
+       struct sockaddr_in to;
+    int        idx;
+       int        s;
+    struct in_addr remote_ip;
+    char      *value;
+    int        polltime = 0;
+    int        announce_stage = 0;
+    struct pollfd fds[1];
+
+    if(argc < 4)
     {
-      value = index (argv[i], '=');
-      if (value)
-        {
-          value[0] = '\0';
-          value++;
-          xht_set (ipcam_info.metadata, argv[i], value);
-        }
+        fprintf (stderr, "usage: mhttp <ip> <port> <key1>=<value1> <key2>=<value2> ...\n");
+        fprintf (stderr, "   <ip>  The IP address to promote\n");
+        fprintf (stderr, "   <port> is the port number of the service to be advertized\n");
+        fprintf (stderr, "   <key>=<value> are the keys that get embedded into the TXT record.\n");
+        return -1;
     }
 
-  ipcam_info.ptr_to_srv  = NULL;
-  ipcam_info.srv_to_host = NULL;
-  ipcam_info.txt_for_srv = NULL;
-  ipcam_info.host_to_ip  = NULL;
-  ipcam_info.ip_to_host  = NULL;
+    service_info.mdnsd = MdnsdNew (1, 1000);
 
-  pipe (signal_pipe);
-  signal(SIGHUP,  sighandler);
-  signal(SIGINT,  sighandler);
-  signal(SIGQUIT, sighandler);
-  signal(SIGTERM, sighandler);
+       //gethostname (service_info.hostname, HOSTNAMESIZE);
+       sprintf(service_info.hostname, "reinhardt");
+    service_info.hostname[HOSTNAMESIZE-1] = '\0';
+    if (strchr (service_info.hostname, '.'))
+        strchr (service_info.hostname, '.')[0] = '\0';
 
-  if ((s = msock()) == 0)
-    {
-      fprintf (stderr, "can't create socket: %s\n", strerror(errno));
-      return -1;
-    }
+    service_info.servicename = NULL;
 
-  if ((nlink = netwatch_open ()) < 0)
-    {
-      fprintf (stderr, "can't connect to netlink: %s\n", strerror(errno));
-      return -1;
-    }
-
-  netwatch_register_callbacks (iface_change_callback,
-                               iface_link_callback,
-                              &ipcam_info);
-  netwatch_queue_inforequest (nlink);
+    service_info.ip          = strdup(argv[1]);
+    service_info.announce_ip.s_addr = inet_addr(service_info.ip);
+    service_info.host_to_ip  = NULL;
+    service_info.ip_to_host  = NULL;
 
+    service_info.port = atoi(argv[2]);
 
-  if (mkfifo (FIFO_PATH, S_IRWXU) < 0)
-    {
-      if (errno != EEXIST)
-        {
-          fprintf (stderr, "can't create named pipe: %s\n", strerror(errno));
-          return -1;
+    service_info.metadata = SHashInit (11);
+    for (idx = 2; idx < argc; idx++) {
+        value = index (argv[idx], '=');
+        if (value) {
+            value[0] = '\0';
+            value++;
+            SHashSet (service_info.metadata, argv[idx], value);
         }
     }
 
-  if ((fifo_fd = open (FIFO_PATH, O_RDONLY | O_NONBLOCK)) < 0)
-    {
-      fprintf (stderr, "can't open named pipe: %s\n", strerror(errno));
-      return -1;
-    }
+    service_info.ptr_to_srv     = NULL;
+    service_info.srv_to_host    = NULL;
+    service_info.txt_for_srv    = NULL;
 
-  /* we need to open the fifo for writing as well (although we'll never
-   * use it for this) to avoid POLLHUP to happen when no client wants
-   * something from us. Ugh. */
+    signal(SIGHUP,  sighandler);
+    signal(SIGINT,  sighandler);
+    signal(SIGQUIT, sighandler);
+    signal(SIGTERM, sighandler);
 
-  if ((i = open (FIFO_PATH, O_WRONLY)) < 0)
+    if ((s = msock()) == 0)
     {
-      fprintf (stderr, "can't dummy-open write end of pipe: %s\n",
-               strerror(errno));
-      return -1;
+        fprintf (stderr, "can't create socket: %s\n", strerror(errno));
+        return -1;
     }
 
-  while(1)
-    {
-      fds[0].fd      = signal_pipe[0];
-      fds[0].events  = POLLIN;
-      fds[0].revents = 0;
-      fds[1].fd      = s;
-      fds[1].events  = POLLIN;
-      fds[1].revents = 0;
-      fds[2].fd      = nlink;
-      fds[2].events  = POLLIN;
-      fds[2].revents = 0;
-      fds[3].fd      = fifo_fd;
-      fds[3].events  = POLLIN;
-      fds[3].revents = 0;
-
-      poll (fds, 4, polltime);
-
-      /* only used when we wake-up from a signal */
-      if (fds[0].revents)
-        {
-          char hostname[HOSTNAMESIZE];
+    request_ip_addresses (&service_info);
 
-          read (signal_pipe[0], buf, MAX_PACKET_LEN);
+    service_info.state = MDNSD_PROBE;
 
-          gethostname (hostname, HOSTNAMESIZE);
-          hostname[HOSTNAMESIZE-1] = '\0';
-          if (strchr (hostname, '.'))
-            strchr (hostname, '.')[0] = '\0';
-          if (strcmp (hostname, ipcam_info.hostname))
-            {
-              /* hostname changed */
-              strcpy (ipcam_info.hostname, hostname);
-              free (ipcam_info.servicename);
-              ipcam_info.servicename = NULL;
+    while(1) {
+        fds[0].fd      = s;
+        fds[0].events  = POLLIN;
+        fds[0].revents = 0;
 
-              ipcam_info.state = MDNSD_PROBE;
-            }
-        }
-
-      if (fds[2].revents)
-        {
-          netwatch_dispatch (nlink);
-        }
+        poll (fds, 1, polltime);
 
-      if (fds[3].revents)
+        switch (service_info.state)
         {
-          char message[1024];
-          int ret;
-
-          ret = read (fifo_fd, message, 1023);
-
-          if (ret > 0)
-            {
-              message[ret] = '\0';
-
-              if (!strncmp ("port:", message, 5))
-                {
-                  int port = atoi (message + 5);
-                  if (port > 0 && port < 65536)
-                    update_port_info (&ipcam_info, port);
+            case MDNSD_PROBE:
+
+                               if (service_info.ptr_to_srv) {
+                    MdnsdDone (service_info.mdnsd, service_info.ptr_to_srv);
+                               }
+
+                               if (service_info.srv_to_host) {
+                    MdnsdDone (service_info.mdnsd, service_info.srv_to_host);
+                               }
+
+                if (service_info.txt_for_srv) {
+                    MdnsdDone (service_info.mdnsd, service_info.txt_for_srv);
+                               }
+
+                service_info.ptr_to_srv     = NULL;
+                service_info.srv_to_host    = NULL;
+                service_info.txt_for_srv    = NULL;
+
+                if (service_info.host_to_ip) {
+                    MdnsdDone (service_info.mdnsd, service_info.host_to_ip);
+                               }
+
+                if (service_info.ip_to_host) {
+                    MdnsdDone (service_info.mdnsd, service_info.ip_to_host);
+                               }
+
+                service_info.host_to_ip  = NULL;
+                service_info.ip_to_host  = NULL;
+                service_info.announce_ip.s_addr = 0;
+
+                service_info.state = MDNSD_ANNOUNCE;
+                announce_stage = 0;
+                tv.tv_sec = 0;
+                tv.tv_usec = 0;
+                break;
+
+            case MDNSD_ANNOUNCE:
+                if (announce_stage < 3) {
+                    struct timeval cur_tv;
+                    long msecs;
+
+                    gettimeofday (&cur_tv, NULL);
+                    msecs = (cur_tv.tv_sec - tv.tv_sec) * 1000 + cur_tv.tv_usec / 1000 - tv.tv_usec / 1000;
+
+                    if ((tv.tv_sec == 0) || (msecs > 755)) {
+                        request_service (&service_info, announce_stage);
+                        announce_stage ++;
+                        tv = cur_tv;
+                        cur_tv = *MdnsdGetMaxSleepTime (service_info.mdnsd);
+                        polltime = cur_tv.tv_sec * 1000 + cur_tv.tv_usec / 1000;
+                        if (polltime >= 756) {
+                            polltime = 756;
+                                               }
+                    } else {
+                        cur_tv = *MdnsdGetMaxSleepTime (service_info.mdnsd);
+                        polltime = cur_tv.tv_sec * 1000 + cur_tv.tv_usec / 1000;
+                        if (polltime >= 756 - msecs) {
+                            polltime = 756 - msecs;
+                                               }
+                    }
+                } else {
+                    tv = *MdnsdGetMaxSleepTime (service_info.mdnsd);
+                    polltime = tv.tv_sec * 1000 + tv.tv_usec / 1000;
+
+                    service_info.state = MDNSD_RUN;
                 }
-              else
-                {
-                  fprintf (stderr, "mdnsd: got unknown fifo message: %s", message);
-                }
-            }
-          else if (ret < 0)
-            {
-              fprintf (stderr, "mdnsd: can't read from pipe: %s\n", strerror (errno));
-            }
-        }
+                break;
 
-      switch (ipcam_info.state)
-        {
-          case MDNSD_STARTUP:
-            /* we're waiting for a netwatch based statechange */
-            /* fprintf (stderr, "in STARTUP\n"); */
-            polltime = 5000;
-            break;
-
-          case MDNSD_PROBE:
-            /* fprintf (stderr, "in PROBE\n"); */
-            if (ipcam_info.ptr_to_srv)
-              mdnsd_done (ipcam_info.dnsd, ipcam_info.ptr_to_srv);
-            if (ipcam_info.srv_to_host)
-              mdnsd_done (ipcam_info.dnsd, ipcam_info.srv_to_host);
-            if (ipcam_info.txt_for_srv)
-              mdnsd_done (ipcam_info.dnsd, ipcam_info.txt_for_srv);
-            if (ipcam_info.host_to_ip)
-              mdnsd_done (ipcam_info.dnsd, ipcam_info.host_to_ip);
-            if (ipcam_info.ip_to_host)
-              mdnsd_done (ipcam_info.dnsd, ipcam_info.ip_to_host);
-
-            ipcam_info.ptr_to_srv  = NULL;
-            ipcam_info.srv_to_host = NULL;
-            ipcam_info.txt_for_srv = NULL;
-            ipcam_info.host_to_ip  = NULL;
-            ipcam_info.ip_to_host  = NULL;
-
-            ipcam_info.state = MDNSD_ANNOUNCE;
-            announce_stage = 0;
-            tv.tv_sec = 0;
-            tv.tv_usec = 0;
-            break;
-
-          case MDNSD_ANNOUNCE:
-            /* fprintf (stderr, "in ANNOUNCE\n"); */
-            if (announce_stage < 3)
-              {
-                struct timeval cur_tv;
-                long msecs;
-                gettimeofday (&cur_tv, NULL);
-                msecs = (cur_tv.tv_sec - tv.tv_sec) * 1000 + cur_tv.tv_usec / 1000 - tv.tv_usec / 1000;
-
-                if (tv.tv_sec == 0 || msecs > 755)
-                  {
-                    request_service (&ipcam_info, announce_stage);
-                    announce_stage ++;
-                    tv = cur_tv;
-                    cur_tv = *mdnsd_sleep (ipcam_info.dnsd);
-                    polltime = cur_tv.tv_sec * 1000 + cur_tv.tv_usec / 1000;
-                    if (polltime >= 756)
-                      polltime = 756;
-                  }
-                else
-                  {
-                    cur_tv = *mdnsd_sleep (ipcam_info.dnsd);
-                    polltime = cur_tv.tv_sec * 1000 + cur_tv.tv_usec / 1000;
-                    if (polltime >= 756 - msecs)
-                      polltime = 756 - msecs;
-                  }
-              }
-            else
-              {
-                tv = *mdnsd_sleep (ipcam_info.dnsd);
+            case MDNSD_RUN:
+                tv = *MdnsdGetMaxSleepTime (service_info.mdnsd);
                 polltime = tv.tv_sec * 1000 + tv.tv_usec / 1000;
+                break;
 
-                ipcam_info.state = MDNSD_RUN;
-              }
-            break;
-
-          case MDNSD_RUN:
-            tv = *mdnsd_sleep (ipcam_info.dnsd);
-            polltime = tv.tv_sec * 1000 + tv.tv_usec / 1000;
-            break;
-
-          case MDNSD_SHUTDOWN:
-            mdnsd_shutdown (ipcam_info.dnsd);
-            break;
+            case MDNSD_SHUTDOWN:
+                MdnsdShutdown (service_info.mdnsd);
+                break;
 
-          default:
-            fprintf (stderr, "in default???\n");
-            break;
+            default:
+                fprintf (stderr, "in default???\n");
+                break;
         }
 
-      if (fds[1].revents)
-        {
-          while ((bsize = recvfrom (s, buf, MAX_PACKET_LEN, 0,
-                                    (struct sockaddr*) &from, &ssize)) > 0)
+        if (fds[0].revents) {
+            while ((bsize = recvfrom (s, buf, MAX_PACKET_LEN, 0, (struct sockaddr*) &from, &ssize)) > 0)
             {
-              bzero (&msg, sizeof (struct message));
-              message_parse (&msg, buf);
-              mdnsd_in (ipcam_info.dnsd, &msg,
-                        (unsigned long int) from.sin_addr.s_addr,
-                        from.sin_port);
+                bzero (&msg, sizeof (DNSMESSAGE));
+                DnsParseMsg (&msg, buf);
+                MdnsdInput(service_info.mdnsd, &msg,
+                           from.sin_addr,
+                           from.sin_port);
             }
-          if (bsize < 0 && errno != EAGAIN)
-            {
-              fprintf (stderr, "can't read from socket: %s\n", strerror (errno));
+
+            if (bsize < 0 && errno != EAGAIN) {
+                fprintf (stderr, "can't read from socket: %s\n", strerror (errno));
             }
         }
 
-      while (mdnsd_out (ipcam_info.dnsd, &msg, &remote_ip, &port))
-        {
-          bzero (&to, sizeof (to));
-          to.sin_family = AF_INET;
-          to.sin_port = port;
-          to.sin_addr.s_addr = remote_ip;
-          if (sendto (s, message_packet (&msg), message_packet_len (&msg),
-                      0, (struct sockaddr *) &to,
-                      sizeof (struct sockaddr_in)) != message_packet_len (&msg))
-            {
-              fprintf (stderr, "can't write to socket: %s\n", strerror(errno));
+        while (MdnsdOutput (service_info.mdnsd, &msg, &remote_ip, &port)) {
+            bzero (&to, sizeof (to));
+            to.sin_family = AF_INET;
+            to.sin_port = port;
+            to.sin_addr.s_addr = remote_ip.s_addr;
+
+            if (sendto (s, DnsMsg2Pkt (&msg), DnsMsgLen(&msg), 0, (struct sockaddr *) &to, sizeof (struct sockaddr_in)) != DnsMsgLen(&msg)) {
+                fprintf (stderr, "can't write to socket: %s\n", strerror(errno));
             }
         }
 
-      if (ipcam_info.state == MDNSD_SHUTDOWN)
-        break;
+        if (service_info.state == MDNSD_SHUTDOWN) {
+            break;
+               }
     }
 
-  mdnsd_shutdown (ipcam_info.dnsd);
-  mdnsd_free (ipcam_info.dnsd);
-  return 0;
+    MdnsdShutdown (service_info.mdnsd);
+    MdnsdFree (service_info.mdnsd);
+    return 0;
 }