s3:smbd: make mdns registration event driven.
authorStefan Metzmacher <metze@samba.org>
Mon, 26 Jan 2009 13:55:54 +0000 (14:55 +0100)
committerStefan Metzmacher <metze@samba.org>
Tue, 27 Jan 2009 14:28:11 +0000 (15:28 +0100)
metze

source3/include/includes.h
source3/include/proto.h
source3/smbd/dnsregister.c
source3/smbd/server.c

index 50140c17f72238f6edcf94703faad71fdf167f66..ea856f1c1645f66a8f65c9d1f9c5f451f8259369 100644 (file)
@@ -678,20 +678,6 @@ struct printjob;
 
 #include "smb_ldap.h"
 
-struct dns_reg_state;
-
-void dns_register_smbd(struct dns_reg_state ** dns_state_ptr,
-               unsigned port,
-               int *maxfd,
-               fd_set *listen_set,
-               struct timeval *timeout);
-
-void dns_register_close(struct dns_reg_state ** dns_state_ptr);
-
-
-bool dns_register_smbd_reply(struct dns_reg_state *dns_state,
-               fd_set *lfds, struct timeval *timeout);
-
 /*
  * Reasons for cache flush.
  */
index ae4929053985a0865c20382583935d92e0817eb9..f8a9dbce66f2af119ee395311c4bbbe955d829b5 100644 (file)
@@ -6651,14 +6651,9 @@ uint32 dmapi_file_flags(const char * const path);
 
 /* The following definitions come from smbd/dnsregister.c  */
 
-void dns_register_close(struct dns_reg_state **dns_state_ptr);
-void dns_register_smbd(struct dns_reg_state ** dns_state_ptr,
-               unsigned port,
-               int *maxfd,
-               fd_set *listen_set,
-               struct timeval *timeout);
-bool dns_register_smbd_reply(struct dns_reg_state *dns_state,
-               fd_set *lfds, struct timeval *timeout);
+bool smbd_setup_mdns_registration(struct tevent_context *ev,
+                                 TALLOC_CTX *mem_ctx,
+                                 uint16_t port);
 
 /* The following definitions come from smbd/dosmode.c  */
 
index c092251feec63169a86d09a8143ab7fd0d292d32..2fd95f9fb7abbb6f12cd1cbdbe796d4b42c72f56 100644 (file)
 #include <dns_sd.h>
 
 struct dns_reg_state {
+       struct tevent_context *event_ctx;
+       uint16_t port;
        DNSServiceRef srv_ref;
-       struct timed_event *retry_handler;
+       struct tevent_timer *te;
+       int fd;
+       struct tevent_fd *fde;
 };
 
-void dns_register_close(struct dns_reg_state **dns_state_ptr)
+static int dns_reg_state_destructor(struct dns_reg_state *dns_state)
 {
-       struct dns_reg_state *dns_state = *dns_state_ptr;
-
-       if (dns_state == NULL) {
-               return;
-       }
-
        if (dns_state->srv_ref != NULL) {
                /* Close connection to the mDNS daemon */
                DNSServiceRefDeallocate(dns_state->srv_ref);
@@ -54,81 +52,52 @@ void dns_register_close(struct dns_reg_state **dns_state_ptr)
        }
 
        /* Clear event handler */
-       if (dns_state->retry_handler != NULL) {
-               TALLOC_FREE(dns_state->retry_handler);
-               dns_state->retry_handler = NULL;
-       }
+       TALLOC_FREE(dns_state->te);
+       TALLOC_FREE(dns_state->fde);
+       dns_state->fd = -1;
 
-       talloc_free(dns_state);
-       *dns_state_ptr = NULL;
+       return 0;
 }
 
-static void dns_register_smbd_retry(struct event_context *ctx,
-                                   struct timed_event *te,
-                                   const struct timeval *now,
-                                   void *private_data)
+static void dns_register_smbd_retry(struct tevent_context *ctx,
+                                   struct tevent_timer *te,
+                                   struct timeval now,
+                                   void *private_data);
+static void dns_register_smbd_fde_handler(struct tevent_context *ev,
+                                         struct tevent_fd *fde,
+                                         uint16_t flags,
+                                         void *private_data);
+
+static bool dns_register_smbd_schedule(struct dns_reg_state *dns_state,
+                                      struct timeval tval)
 {
-       struct dns_reg_state *dns_state = (struct dns_reg_state *)private_data;
-
-       /* Clear previous registration state to force new
-        * registration attempt. Clears event handler.
-        */
-       dns_register_close(&dns_state);
-}
-
-static void schedule_dns_register_smbd_retry(struct dns_reg_state *dns_state,
-               struct timeval *timeout)
-{
-       struct timed_event * event;
-
-       dns_state->srv_ref = NULL;
-       event= event_add_timed(smbd_event_context(),
-                       NULL,
-                       timeval_current_ofs(DNS_REG_RETRY_INTERVAL, 0),
-                       dns_register_smbd_retry,
-                       dns_state);
+       dns_reg_state_destructor(dns_state);
+
+       dns_state->te = tevent_add_timer(dns_state->event_ctx,
+                                        dns_state,
+                                        tval,
+                                        dns_register_smbd_retry,
+                                        dns_state);
+       if (!dns_state->te) {
+               return false;
+       }
 
-       dns_state->retry_handler = event;
-       get_timed_events_timeout(smbd_event_context(), timeout);
+       return true;
 }
 
-/* Kick off a mDNS request to register the "_smb._tcp" on the specified port.
- * We really ought to register on all the ports we are listening on. This will
- * have to be an exercise for some-one who knows the DNS registration API a bit
- * better.
- */
-void dns_register_smbd(struct dns_reg_state ** dns_state_ptr,
-               unsigned port,
-               int *maxfd,
-               fd_set *listen_set,
-               struct timeval *timeout)
+static void dns_register_smbd_retry(struct tevent_context *ctx,
+                                   struct tevent_timer *te,
+                                   struct timeval now,
+                                   void *private_data)
 {
-       int mdnsd_conn_fd;
+       struct dns_reg_state *dns_state = talloc_get_type_abort(private_data,
+                                         struct dns_reg_state);
        DNSServiceErrorType err;
-       struct dns_reg_state *dns_state = *dns_state_ptr;
-
-       if (dns_state == NULL) {
-               *dns_state_ptr = dns_state = talloc(NULL, struct dns_reg_state);
-               if (dns_state == NULL) {
-                       return;
-               }
-       }
-
-       /* Quit if a re-try attempt has been scheduled.  */
-       if (dns_state->retry_handler != NULL) {
-               return;
-       }
 
-       /* If a registration is active add conn
-        * fd to select listen_set and return
-        */
-       if (dns_state->srv_ref != NULL) {
-               mdnsd_conn_fd = DNSServiceRefSockFD(dns_state->srv_ref);
-               FD_SET(mdnsd_conn_fd, listen_set);
-               return;
-       }
+       dns_reg_state_destructor(dns_state);
 
-       DEBUG(6, ("registering _smb._tcp service on port %d\n", port));
+       DEBUG(6, ("registering _smb._tcp service on port %d\n",
+                 dns_state->port));
 
        /* Register service with DNS. Connects with the mDNS
         * daemon running on the local system to perform DNS
@@ -140,7 +109,7 @@ void dns_register_smbd(struct dns_reg_state ** dns_state_ptr,
                        "_smb._tcp" /* service type */,
                        NULL /* domain */,
                        "" /* SRV target host name */,
-                       htons(port),
+                       htons(dns_state->port),
                        0 /* TXT record len */,
                        NULL /* TXT record data */,
                        NULL /* callback func */,
@@ -150,62 +119,81 @@ void dns_register_smbd(struct dns_reg_state ** dns_state_ptr,
                /* Failed to register service. Schedule a re-try attempt.
                 */
                DEBUG(3, ("unable to register with mDNS (err %d)\n", err));
-               schedule_dns_register_smbd_retry(dns_state, timeout);
-               return;
+               goto retry;
+       }
+
+       dns_state->fd = DNSServiceRefSockFD(dns_state->srv_ref);
+       if (dns_state->fd == -1) {
+               goto retry;
        }
 
-       mdnsd_conn_fd = DNSServiceRefSockFD(dns_state->srv_ref);
-       FD_SET(mdnsd_conn_fd, listen_set);
-       *maxfd = MAX(*maxfd, mdnsd_conn_fd);
-       *timeout = timeval_zero();
+       dns_state->fde = tevent_add_fd(dns_state->event_ctx,
+                                      dns_state,
+                                      dns_state->fd,
+                                      TEVENT_FD_READ,
+                                      dns_register_smbd_fde_handler,
+                                      dns_state);
+       if (!dns_state->fde) {
+               goto retry;
+       }
 
+       return;
+ retry:
+       dns_register_smbd_schedule(dns_state,
+               timeval_current_ofs(DNS_REG_RETRY_INTERVAL, 0));
 }
 
 /* Processes reply from mDNS daemon. Returns true if a reply was received */
-bool dns_register_smbd_reply(struct dns_reg_state *dns_state,
-               fd_set *lfds, struct timeval *timeout)
+static void dns_register_smbd_fde_handler(struct tevent_context *ev,
+                                         struct tevent_fd *fde,
+                                         uint16_t flags,
+                                         void *private_data)
 {
-       int mdnsd_conn_fd = -1;
+       struct dns_reg_state *dns_state = talloc_get_type_abort(private_data,
+                                         struct dns_reg_state);
+       DNSServiceErrorType err;
 
-       if (dns_state->srv_ref == NULL) {
-               return false;
+       err = DNSServiceProcessResult(dns_state->srv_ref);
+       if (err != kDNSServiceErr_NoError) {
+               DEBUG(3, ("failed to process mDNS result (err %d), re-trying\n",
+                           err));
+               goto retry;
        }
 
-       mdnsd_conn_fd = DNSServiceRefSockFD(dns_state->srv_ref);
+       talloc_free(dns_state);
+       return;
 
-       /* Process reply from daemon. Handles any errors. */
-       if ((mdnsd_conn_fd != -1) && (FD_ISSET(mdnsd_conn_fd,lfds)) ) {
-               DNSServiceErrorType err;
-               
-               err = DNSServiceProcessResult(dns_state->srv_ref);
-               if (err != kDNSServiceErr_NoError) {
-                       DEBUG(3, ("failed to process mDNS result (err %d), re-trying\n",
-                                   err));
-                       schedule_dns_register_smbd_retry(dns_state, timeout);
-               }
+ retry:
+       dns_register_smbd_schedule(dns_state,
+               timeval_current_ofs(DNS_REG_RETRY_INTERVAL, 0));
+}
 
-               return true;
+bool smbd_setup_mdns_registration(struct tevent_context *ev,
+                                 TALLOC_CTX *mem_ctx,
+                                 uint16_t port)
+{
+       struct dns_reg_state *dns_state;
+
+       dns_state = talloc_zero(mem_ctx, struct dns_reg_state);
+       if (dns_state == NULL) {
+               return false;
        }
+       dns_state->event_ctx = ev;
+       dns_state->port = port;
+       dns_state->fd = -1;
+
+       talloc_set_destructor(dns_state, dns_reg_state_destructor);
 
-       return false;
+       return dns_register_smbd_schedule(dns_state, timeval_zero());
 }
 
 #else /* WITH_DNSSD_SUPPORT */
 
- void dns_register_smbd(struct dns_reg_state ** dns_state_ptr,
-               unsigned port,
-               int *maxfd,
-               fd_set *listen_set,
-               struct timeval *timeout)
-{}
-
- void dns_register_close(struct dns_reg_state ** dns_state_ptr)
-{}
-
- bool dns_register_smbd_reply(struct dns_reg_state *dns_state,
-               fd_set *lfds, struct timeval *timeout)
+bool smbd_setup_mdns_registration(struct tevent_context *ev,
+                                 TALLOC_CTX *mem_ctx,
+                                 uint16_t port)
 {
-       return false;
+       return true;
 }
 
 #endif /* WITH_DNSSD_SUPPORT */
index f95fa874ffba29f97cd0ce6a676f2b0f6126cdbc..d71a04ebc17cff7910c904580119d9abade7d522 100644 (file)
@@ -309,13 +309,15 @@ static bool open_sockets_smbd(bool interactive, const char *smb_ports)
        int maxfd = 0;
        int i;
        char *ports;
-       struct dns_reg_state * dns_reg = NULL;
+       TALLOC_CTX *dns_ctx = NULL;
        unsigned dns_port = 0;
 
 #ifdef HAVE_ATEXIT
        atexit(killkids);
 #endif
 
+       dns_ctx = talloc_new(NULL);
+
        /* Stop zombies */
        smbd_setup_sig_chld_handler();
 
@@ -535,6 +537,11 @@ static bool open_sockets_smbd(bool interactive, const char *smb_ports)
                           MSG_SMB_INJECT_FAULT, msg_inject_fault);
 #endif
 
+       if (dns_port != 0) {
+               smbd_setup_mdns_registration(smbd_event_context(),
+                                            dns_ctx, dns_port);
+       }
+
        /* now accept incoming connections - forking a new process
           for each incoming connection */
        DEBUG(2,("waiting for a connection\n"));
@@ -554,12 +561,6 @@ static bool open_sockets_smbd(bool interactive, const char *smb_ports)
                FD_ZERO(&w_fds);
                GetTimeOfDay(&now);
 
-               /* Kick off our mDNS registration. */
-               if (dns_port != 0) {
-                       dns_register_smbd(&dns_reg, dns_port, &maxfd,
-                                       &r_fds, &idle_timeout);
-               }
-
                event_add_to_select_args(smbd_event_context(), &now,
                                         &r_fds, &w_fds, &idle_timeout,
                                         &maxfd);
@@ -580,11 +581,6 @@ static bool open_sockets_smbd(bool interactive, const char *smb_ports)
                        exit_server_cleanly("idle timeout");
                }
 
-               /* process pending nDNS responses */
-               if (dns_register_smbd_reply(dns_reg, &r_fds, &idle_timeout)) {
-                       --num;
-               }
-
                /* check if we need to reload services */
                check_reload(time(NULL));
 
@@ -624,6 +620,8 @@ static bool open_sockets_smbd(bool interactive, const char *smb_ports)
                            ((child = sys_fork())==0)) {
                                /* Child code ... */
 
+                               TALLOC_FREE(dns_ctx);
+
                                /* Stop zombies, the parent explicitly handles
                                 * them, counting worker smbds. */
                                CatchChild();
@@ -632,9 +630,6 @@ static bool open_sockets_smbd(bool interactive, const char *smb_ports)
                                for(i = 0; i < num_sockets; i++)
                                        close(fd_listenset[i]);
 
-                               /* close our mDNS daemon handle */
-                               dns_register_close(&dns_reg);
-
                                /* close our standard file
                                   descriptors */
                                close_low_fds(False);