Skip site navigation (1)Skip section navigation (2)
Date:      Wed, 3 Oct 2007 21:40:51 GMT
From:      Fredrik Lindberg <fli@FreeBSD.org>
To:        Perforce Change Reviews <perforce@FreeBSD.org>
Subject:   PERFORCE change 127156 for review
Message-ID:  <200710032140.l93Lep1J097975@repoman.freebsd.org>

next in thread | raw e-mail | index | archive | help
http://perforce.freebsd.org/chv.cgi?CH=127156

Change 127156 by fli@fli_nexus on 2007/10/03 21:40:27

	- Timers and _wcsdup have been moved to util.c, remove.
	- Input processing have its own file now, remove. 
	- Cache structures and prototypes live in cache.h, remove.
	- Check for subsystem failures during interface initialization.

Affected files ...

.. //depot/projects/soc2007/fli-mdns_sd/mdnsd/mdnsd.c#7 edit
.. //depot/projects/soc2007/fli-mdns_sd/mdnsd/mdnsd.h#7 edit

Differences ...

==== //depot/projects/soc2007/fli-mdns_sd/mdnsd/mdnsd.c#7 (text+ko) ====

@@ -47,6 +47,7 @@
 #include <unistd.h>
 
 #include "mdnsd.h"
+#include "util.h"
 #include "log.h"
 #include "objalloc.h"
 
@@ -73,64 +74,61 @@
 
 static void usage(char *);
 
-/*
- * Generic timer intialization
- */
-static int
-tmr_init(int what, struct event_tmr *ev, ev_arg arg)
+static inline void
+record2rrset(struct record *r, uint16_t class, uint16_t  type,
+    struct record_res *rr, struct mdns_rrset *rs, int cflush)
 {
 
-	switch (what) {
-	case EVENT_INIT_OPEN:
-		ev->evtmr_timeout = arg.int32;
-		break;
-	case EVENT_INIT_CLOSE:
-		break;
-	}
-	return (0);
-}
+	MDNS_INIT_ASSERT(r, r_magic);
+	MDNS_INIT_ASSERT(rr, rr_magic);
 
-static int
-tmr_init_oneshot(int what, struct event_tmr *ev, ev_arg arg)
-{
-
-	switch (what) {
-	case EVENT_INIT_OPEN:
-		ev->evtmr_timeout = arg.int32;
-		ev->evtmr_oneshot = 1;
-		break;
-	case EVENT_INIT_CLOSE:
-		break;
-	}
-	return (0);
+	mdns_rrset_name(rs, r->r_name);
+	rs->r_type = type;
+	rs->r_class = class;
+	rs->r_cflush = cflush;
+	rs->r_datalen = rr->rr_len;
+	rs->r_data = rr->rr_data;
 }
 
 /*
- * Start a timer, returns a unique timer identifier
+ * Callback routine from aggregation queue, called when a data
+ * object is supposed to be added to the packet.
  */
-int
-tmr_start(struct md_glob *g, uint32_t timeout, ev_handler_tmr handler,
-    void *arg, int oneshot)
+static void
+aggr_resp_engine(struct mdns_pkgchain *pc, void *data)
 {
-	int id;
-	ev_arg eva, evai;
+	struct record *r;
+	struct record_class *rc;
+	struct record_type *rt;
+	struct record_res *rr;
+	struct dbr_res *ds;
+	struct mdns_rrset *mrs;
+
+	rr = data;
+	MDNS_INIT_ASSERT(rr, rr_magic);
+	ds = record_res_getparent(rr);
+	MDNS_INIT_ASSERT(ds, ds_magic);
+
+	rt = record_get_type(rr);
+	rc = record_get_class(rt);
+	r = record_get_record(rc);
 
-	evai.int32 = timeout;
-	eva.ptr = arg;
-	if (oneshot)
-		id = event_add(g->g_evl, EVENT_TYPE_TMR, handler, &eva,
-		    tmr_init_oneshot, &evai);
-	else
-		id = event_add(g->g_evl, EVENT_TYPE_TMR, handler, &eva,
-		    tmr_init, &evai);
-	return (id);
+	mrs = mdns_pkg_getrrset();
+	record2rrset(r, rc->rc_class, rt->rt_type, rr, mrs, 0);
+	mrs->r_ttl = ds->ds_dir->dir_ttl;
+	clock_gettime(CLOCK_REALTIME, &ds->ds_time);
+	mdns_pkg_addanswer(pc, mrs, 0);
 }
 
-void
-tmr_stop(struct md_glob *g, int timer)
+/*
+ * Initialize a response packet chain
+ */
+static void
+aggr_resp_pkgchain(struct md_if *mif, struct mdns_pkgchain *pc)
 {
 
-	event_del(g->g_evl, timer, NULL);
+	mdns_pkgchain_init(&mif->mif_stack, pc, MDNS_PC_NONE);
+	mdns_pkg_sethdr(pc, 0, MDNS_HEAD_RESP | MDNS_HEAD_AA);
 }
 
 /*
@@ -209,25 +207,6 @@
 }
 
 /*
- * Duplicate an wide character string
- * XXX: Move to a better place
- */
-wchar_t *
-_wcsdup(const wchar_t *s)
-{
-	size_t len;
-	wchar_t *d;
-
-	len = (wcslen(s) + 1) * sizeof(wchar_t);
-	d = malloc(len);
-	if (d == NULL)
-		return (NULL);
-	memcpy(d, s, len);
-	return (d);
-}
-
-
-/*
  * Generic I/O read-ready event initializtion
  */
 int
@@ -246,404 +225,6 @@
 	return (0);
 }
 
-static inline void
-record2rrset(struct record *r, struct record_type *rt, struct record_res *rr,
-    struct mdns_rrset *rs, int cflush)
-{
-
-	MDNS_INIT_ASSERT(r, r_magic);
-	MDNS_INIT_ASSERT(rt, rt_magic);
-	MDNS_INIT_ASSERT(rr, rr_magic);
-
-	mdns_rrset_name(rs, r->r_name);
-	rs->r_type = rt->rt_type;
-	rs->r_class = mdns_c_in;
-	rs->r_cflush = cflush;
-	rs->r_datalen = rr->rr_len;
-	rs->r_data = rr->rr_data;
-}
-
-/*
- * Callback routine from aggregation queue, called when a data
- * object is supposed to be added to the packet.
- */
-static void
-aggr_resp_engine(struct mdns_pkgchain *pc, void *data)
-{
-	struct record *r;
-	struct record_type *rt;
-	struct record_res *rr;
-	struct dbr_res *ds;
-	struct mdns_rrset *mrs;
-
-	rr = data;
-	MDNS_INIT_ASSERT(rr, rr_magic);
-	ds = record_res_getparent(rr);
-	MDNS_INIT_ASSERT(ds, ds_magic);
-	rt = rr->rr_type;
-	MDNS_INIT_ASSERT(rt, rt_magic);
-	r = rt->rt_record;
-	MDNS_INIT_ASSERT(r, r_magic);
-
-	mrs = mdns_pkg_getrrset();
-	record2rrset(r, rt, rr, mrs, 0);
-	mrs->r_ttl = ds->ds_dir->dir_ttl;
-	clock_gettime(CLOCK_REALTIME, &ds->ds_time);
-	mdns_pkg_addanswer(pc, mrs, 0);
-}
-
-/*
- * Initialize a response packet chain
- */
-static void
-aggr_resp_pkgchain(struct md_if *mif, struct mdns_pkgchain *pc)
-{
-
-	mdns_pkgchain_init(&mif->mif_stack, pc, MDNS_PC_NONE);
-	mdns_pkg_sethdr(pc, 0, MDNS_HEAD_RESP | MDNS_HEAD_AA);
-}
-
-/*
- * Process a query packet
- */
-static void
-process_query(struct md_if *mif, struct mdns_packet *pkg,
-    struct mdns_head *hdr, struct sockaddr *from, socklen_t fromlen, int legacy)
-{
-	struct mdns_qset qs;
-	struct mdns_rrset rs, *rsp;
-	struct dbr_rec *dr;
-	struct dbr_res *ds;
-	struct cache_res *cr;
-	struct record_res  *rr;
-	struct record_type *rt;
-	struct record *r;
-	int i, error, send_unicast;
-	time_t min, min2, max;
-	struct aqueue *aq;
-	struct timespec ts;
-	struct cache ac;
-	struct records auth;
-	struct mdns_pkgchain upc;
-
-	clock_gettime(CLOCK_REALTIME, &ts);
-
-	mdns_pkgchain_init(&mif->mif_stack, &upc, MDNS_PC_NONE);
-	mdns_pkg_sethdr(&upc, hdr->h_id, MDNS_HEAD_RESP | MDNS_HEAD_AA);
-	send_unicast = 0;
-	if (from->sa_family == AF_INET)
-		aq = &mif->mif_aq4;
-#ifdef INET6
-	else if (from->sa_family == AF_INET6)
-		aq = &mif->mif_aq6;
-#endif
-
-	/*
-	 * Process the answer section first
-	 */
-	if (hdr->h_canswer > 0)
-		cache_init(&ac, NULL);
-	for (i = 0; i < hdr->h_canswer; i++) {
-		error = mdns_pkg_getanswer(pkg, i, &rs);
-		if (error != 0)
-			break;
-		if (rs.r_class != mdns_c_in) {
-			free(rs.r_data);
-			continue;
-		}
-
-		/*
-		 * Check if this is a resource we might respond to.
-		 * If it is, check if it's on the output queue and
-		 * remove it if TTL rules match, otherwise add it
-		 * to answer suppression lookup cache.
-		 */
-		ds = dbr_find_res(&mif->mif_dbr, rs.r_name, rs.r_type,
-		    rs.r_data, rs.r_datalen);
-		if (ds != NULL && !(ds->ds_flags & DS_INVALID)) {
-			rr = &ds->ds_res;
-			if (aq_inqueue(aq, rr)) {
-				if (rs.r_ttl > ds->ds_dir->dir_ttl / 2)
-					aq_dequeue(aq, rr);
-			}
-			else if (rs.r_ttl > ds->ds_dir->dir_ttl / 2) {
-				error = cache_add(&ac, &rs, NULL);
-				if (error == 1)
-					free(rs.r_data);
-			}
-			else
-				free(rs.r_data);
-		}
-		else {
-			free(rs.r_data);
-		}
-	}
-
-	/*
-	 * Process the authority section, data in here is used
-	 * for probe tie breaking.
-	 */
-	if (hdr->h_cauth > 0)
-		records_init(&auth, mdns_c_in);
-	for (i = 0; i < hdr->h_cauth; i++) {
-		error = mdns_pkg_getauth(pkg, i, &rs);
-		if (error != 0)
-			break;
-		if (rs.r_class != mdns_c_in) {
-			free(rs.r_data);
-			continue;
-		}
-		record_get(&auth, &r, 0, rs.r_name);
-		record_res_add(r, &rr, 0, rs.r_type,
-		    rs.r_data, rs.r_datalen);
-	}
-
-	/*
-	 * TC bit set, min 400-500 ms delay
-	 * Questions > 1, min 20-120 ms delay
-	 * Other, 0 ms
-	 */
-	if (hdr->h_flags & MDNS_HEAD_TC)
-		min2 = (random() % 101) + 400;
-	else if (hdr->h_cquestion > 1)
-		min2 = (random() % 101) + 20;
-	else
-		min = 0;
-
-	/*
-	 * Process the question section
-	 */
-	for (i = 0; i < hdr->h_cquestion; i++) {
-		error = mdns_pkg_getquestion(pkg, i, &qs);
-		if (error != 0)
-			break;
-		if (qs.q_class != mdns_c_in)
-			continue;
-
-		dprintf(DEBUG_RECV,
-		    "question for %s, type=%d, unicast=%d, legacy=%d",
-		    qs.q_name, qs.q_type, qs.q_unicast, legacy);
-
-		dr = dbr_find(&mif->mif_dbr, qs.q_name);
-		if (dr == NULL)
-			continue;
-		MDNS_INIT_ASSERT(dr, dr_magic);
-		/*
-		 * Simultanesous probe tie-breaking
-		 */
-		if (dr->dr_flags & DR_PROBING && hdr->h_cauth > 0) {
-			record_get(&auth, &r, RECORD_NOINIT, qs.q_name);
-			dbr_tiebreak(&mif->mif_dbr, dr, r);
-			continue;	
-		}
-		else if (!(dr->dr_flags & DR_OK)) {
-			dprintf(DEBUG_SEND, "Record %s found in "
-			    "database, but is not marked ok (%x)",
-			    qs.q_name, dr->dr_flags);
-			continue;
-		}
-		/*
-		 * Fix delay time for if this record is
-		 * marked as shared
-		 */
-		else if (dr->dr_flags & DR_SHARED && min2 == 0)
-			min = (random() % 101) + 20;
-		else
-			min = min2;
-
-		/* Allow additional 500ms if aggreation is possible */
-		max = min + 500;
-
-		dprintf(DEBUG_SEND, "Found %s in database, responding",
-		    qs.q_name);
-		if (legacy)
-			mdns_pkg_addquestion(&upc, &qs, MDNS_PKG_DUP);
-
-		r = &dr->dr_rec;
-		record_foreach(rt, r) {
-			if (qs.q_type != rt->rt_type
-			    && qs.q_type != mdns_in_any)
-				continue;
-			record_type_foreach(rr, rt) {
-				ds = record_res_getparent(rr);
-				if (ds->ds_flags & DS_INVALID)
-					continue;
-				if (hdr->h_canswer > 0) {
-					cr = cache_find(&ac, qs.q_name,
-					    qs.q_type);
-					if (cr != NULL)
-						continue;
-				}
-				/*
-				 * This clients needs/wants a unicast response,
-				 * we also schedule a multicast response in we
-				 * this resource hasn't been multicasted
-				 * "recently".
-				 */
-				if (legacy || qs.q_unicast) {
-					rsp = mdns_pkg_getrrset();
-					record2rrset(r, rt, rr, rsp, 0);
-					rsp->r_ttl = legacy ? 10 :
-					    ds->ds_dir->dir_ttl;
-					mdns_pkg_addanswer(&upc, rsp, 0);
-					send_unicast = 1;
-					/*
-					 * Schedule a multicast response if
-					 * the time this resource last was
-					 * sent is greater than a quarter of
-					 * its ttl.
-					 */	
-					if ((ts.tv_sec - ds->ds_time.tv_sec) >
-					    (int32_t)(ds->ds_dir->dir_ttl / 4))
-						aq_enqueue(aq, rr, min, max);
-				}
-				/*
-				 * Multicase response, only if not already in
-				 * aggregation queue and it's at least one
-				 * second since we last sent this resource.
-				 */
-				else if (!aq_inqueue(aq, rr) &&
-				    ts.tv_sec > ds->ds_time.tv_sec)
-					aq_enqueue(aq, rr, min, max);
-			}
-		}
-	}
-
-	if (send_unicast)
-		oq_enqueue(&mif->mif_oq, &upc, from->sa_family,
-		    from, fromlen);
-	if (hdr->h_canswer > 0)
-		cache_destroy(&ac);
-	if (hdr->h_cauth > 0)
-		records_destroy(&auth);
-
-	mdns_pkgchain_free(&upc);
-}
-
-/*
- * Process a response
- */
-static void
-process_resp(struct md_if *mif, struct mdns_packet *pkg, struct mdns_head *hdr,
-    struct sockaddr *from, socklen_t fromlen __unused)
-{
-	struct dbr_rec *dr;
-	int i, error;
-	struct mdns_rrset rs;
-
-	for (i = 0; i < hdr->h_canswer; i++) {
-		error = mdns_pkg_getanswer(pkg, i, &rs);
-		if (error != 0)
-			break;
-		if (rs.r_class != mdns_c_in) {
-			free(rs.r_data);
-			continue;
-		}
-
-		dprintf(DEBUG_RECV, "response to %s, class=%d, type=%d",
-		    rs.r_name, rs.r_class, rs.r_type);
-
-		dr = dbr_find(&mif->mif_dbr, rs.r_name);
-		if (dr != NULL && !(dr->dr_flags & DR_SHARED)) {
-			dprintf(DEBUG_SEND, "Conflicting name %s (dr=%x)",
-			    rs.r_name, dr);
-			dbr_defend(&mif->mif_dbr, dr, &rs, from->sa_family);
-			continue;
-		}
-
-		/* Notify pending consumers */
-		query_notify(&mif->mif_q, &rs, mif->mif_index,
-		    from->sa_family, ((i + 1) < hdr->h_canswer));
-
-		/* TODO: check for pending questions matching this */
-		/* TODO: check for pending answers matching this */
-
-		/*
-		 * Purge records older than 1 second if this is
-		 * supposed to be a unique rrset (cache flush bit set)
-		 */
-		if (rs.r_cflush)
-			cache_purge(&mif->mif_cache, 1, rs.r_name, rs.r_type);
-		error = cache_add(&mif->mif_cache, &rs, NULL);
-		if (error == 1)
-			free(rs.r_data);
-	}
-}
-
-/*
- * Process a mdns packet and generate appropriate responses
- *   mif  - Interface handle
- *   pc   - Packet chain
- *   type - MDNS_{UDP,TCP} transport type used to receive pkg
- *   from - Peer address information
- *   fromlen - Socket address length
- */
-static int
-pkgprocess(struct md_if *mif, struct mdns_pkgchain *pc, int type __unused,
-	struct sockaddr *from, socklen_t fromlen)
-{
-	struct mdns_packet *pkg;
-	struct mdns_head hdr;
-	int sinaddr_len, legacy;
-	in_port_t port;
-	void *sinaddr = NULL;
-	struct sockaddr_in *sin;
-#ifdef INET6
-	struct sockaddr_in6 *sin6;
-#endif
-#ifdef DEBUG
-	char addr[SOCK_MAXADDRLEN+1];
-#endif
-	struct aqueue *aq;
-
-	switch (from->sa_family) {
-	case AF_INET:
-		sin = (struct sockaddr_in *)from;
-		port = sin->sin_port;
-		sinaddr = &((struct sockaddr_in *)from)->sin_addr;
-		sinaddr_len = sizeof(struct in_addr);
-		aq = &mif->mif_aq4;
-		break;
-#ifdef INET6
-	case AF_INET6:
-		sin6 = (struct sockaddr_in6 *)from;
-		port = sin6->sin6_port;
-		sinaddr = &((struct sockaddr_in6 *)from)->sin6_addr;
-		sinaddr_len = sizeof(struct in6_addr);
-		aq = &mif->mif_aq6;
-		break;
-#endif /* INET6 */
-	}
-
-#ifdef DEBUG
-	inet_ntop(from->sa_family, sinaddr, addr, SOCK_MAXADDRLEN);
-	dprintf(DEBUG_RECV, "Packet received peer=%s, port=%d, if=%s",
-	    addr, port, mif->mif_ifnam);
-#endif /* DEBUG */
-
-	pkg = mdns_pkgchain_curpkg(pc);
-	mdns_pkg_gethdr(pkg, &hdr);
-	dprintf(DEBUG_RECV, "type=%s, questions=%d, answers=%d, authority=%d",
-	    hdr.h_flags & MDNS_HEAD_QUERY ? "query" : "resp",
-	    hdr.h_cquestion, hdr.h_canswer, hdr.h_cauth);
-
-	/*
-	 * We are processing a query
-	 */
-	if (hdr.h_flags & MDNS_HEAD_QUERY) {
-		legacy = (port != 5353) ? 1 : 0;
-		process_query(mif, pkg, &hdr, from, fromlen, legacy);
-	}
-
-	/*
-	 * We are processing a response
-	 */
-	else if (hdr.h_flags & MDNS_HEAD_RESP) {
-		process_resp(mif, pkg, &hdr, from, fromlen);
-	}
-	return (0);
-}
-
 /*
  * UDP socket read-ready event handler
  * Allocates a packet chain and reads data from mdns stack and passes
@@ -1013,27 +594,30 @@
 	MDNS_INIT_SET(mif, mif_magic);
 	mif->mif_index = if_nametoindex(ifnam);
 	if (mif->mif_index == 0)
-		goto out;
+		goto if_new_fail;
 	strncpy(mif->mif_ifnam, ifnam, IFNAMSIZ);
 
 	/* Initialize low-level mdns stack on this interface */
 	error = mdns_init(&mif->mif_stack, g->g_bp, ifnam);
 	if (error != 0)
-		goto out;
+		goto if_new_fail;
 	MTX_INIT(mif, mif_stack_mtx, NULL);
 
 	RW_INIT(mif, mif_lock, NULL);	
-	RW_WLOCK(mif, mif_lock);
 	mif->mif_glob = g;
 	TAILQ_INIT(&mif->mif_evlist);
 	if (get_linkstatus(ifnam) != LINK_STATE_DOWN)
 		mif->mif_flags |= MIF_LINKUP;
 
 	/* Client queries system */
-	queries_init(&mif->mif_q, mif);
+	error = queries_init(&mif->mif_q, mif);
+	if (error != 0)
+		goto if_new_fail;
 
 	/* Initialize cache */	
-	cache_init(&mif->mif_cache, &mif->mif_q);
+	error = cache_init(&mif->mif_cache, &mif->mif_q);
+	if (error != 0)
+		goto if_new_fail;
 
 	/* Initialize output queue */
 	oq_init(&mif->mif_oq, mif);
@@ -1055,10 +639,10 @@
 
 	/*
 	 * Read configuration file and create self-claimed records.
-	 * This is done after socket setup so probing is safe to start.
 	 */
 	cfg_read(&mif->mif_dbr, ifnam, g->g_cfgfile);
 
+	RW_WLOCK(mif, mif_lock);
 	RW_WLOCK(g, g_lock);
 	TAILQ_INSERT_TAIL(&g->g_ifs_head, mif, mif_next);
 	if (mif->mif_index >= g->g_ifs_max) {
@@ -1070,15 +654,15 @@
 	}
 	g->g_ifs[mif->mif_index] = mif;
 	RW_UNLOCK(g, g_lock);
-
 	RW_UNLOCK(mif, mif_lock);
 	logger(LOG_NOTICE, "Added interface %s", mif->mif_ifnam);
 
 	dbr_probe_all(&mif->mif_dbr);
 
 	return (mif);
-out:
+if_new_fail:
 	free(mif);
+	logger(LOG_ERR, "Failed to add interface %s", ifnam);
 	return (NULL);
 }
 

==== //depot/projects/soc2007/fli-mdns_sd/mdnsd/mdnsd.h#7 (text+ko) ====

@@ -33,13 +33,13 @@
 #include "debug.h"
 #include "dbrec.h"
 #include "clisrv.h"
+#include "cache.h"
 #include "event.h"
 #include "hash.h"
 #include "mdns.h"
 #include "output.h"
 #include "output_aggr.h"
 #include "queries.h"
-#include "record.h"
 #include "threads.h"
 #include "var.h"
 #include "wqueue.h"
@@ -64,27 +64,6 @@
 	struct clisrv g_cs;  /* unix client pipe server */
 };
 
-/*
- * Cache resouce record
- */
-struct cache_res {
-	MAGIC(cr_magic);
-	struct record_res cr_res;
-	TAILQ_ENTRY(cache_res) cr_next;
-	uint32_t cr_ttl_rel;
-	uint32_t cr_ttl_abs;
-	time_t cr_ctime;
-};
-
-/*
- * Cache record set
- */
-struct cache {
-	struct records c_recs;
-	struct queries *c_queries;
-	TAILQ_HEAD(, cache_res) c_list; /* time delta list */
-};
-
 /* Event identifier */
 struct md_if_ev {
 	TAILQ_ENTRY(md_if_ev) ifev_next;
@@ -122,22 +101,9 @@
 	char mif_ifnam[IFNAMSIZ];
 };
 
-/* mdsnd.c */
-int tmr_start(struct md_glob *, uint32_t, ev_handler_tmr, void *, int);
-void tmr_stop(struct md_glob *, int);
-wchar_t * _wcsdup(const wchar_t *);
-
-/* cache.c */
-void cache_init(struct cache *, struct queries *);
-void cache_destroy(struct cache *);
-int cache_add(struct cache *, struct mdns_rrset *, struct record_res **);
-int cache_del(struct cache *, struct record_res *);
-struct cache_res * cache_find(struct cache *, char *, uint16_t);
-struct cache_res * cache_find_next(struct cache_res *);
-void cache_purge(struct cache *, time_t, char *, uint16_t);
-void cache_clean(struct cache *);
-void cache_set_ttl(struct cache *, struct record_res *, uint32_t);
-void cache_flush(struct cache *);
+/* input.c */
+int pkgprocess(struct md_if *, struct mdns_pkgchain *, int,
+    struct sockaddr *, socklen_t);
 
 /* parse.y */
 int cfg_read(struct dbr *r, const char *, const char *);



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200710032140.l93Lep1J097975>