From 176908397bd8c30999b87fa4b48b51e0b3c9039a Mon Sep 17 00:00:00 2001 From: Anthony Minessale Date: Mon, 13 Feb 2006 23:59:14 +0000 Subject: [PATCH] add zerconf (the howl depend lib needs work sigh) git-svn-id: http://svn.freeswitch.org/svn/freeswitch/trunk@606 d0543943-73ff-0310-b7d9-9358b9ac24b2 --- Makefile.am | 3 +- Makefile.in | 6 +- conf/zeroconf.conf | 6 + modules.conf | 2 + src/include/switch_types.h | 4 + src/mod/endpoints/mod_exosip/mod_exosip.c | 7 + src/mod/event_handlers/mod_zeroconf/Makefile | 19 ++ .../mod_zeroconf/mod_zeroconf.c | 319 ++++++++++++++++++ .../mod_zeroconf/mod_zeroconf.vcproj | 207 ++++++++++++ src/switch_event.c | 5 +- 10 files changed, 571 insertions(+), 7 deletions(-) create mode 100644 conf/zeroconf.conf create mode 100644 src/mod/event_handlers/mod_zeroconf/Makefile create mode 100644 src/mod/event_handlers/mod_zeroconf/mod_zeroconf.c create mode 100644 src/mod/event_handlers/mod_zeroconf/mod_zeroconf.vcproj diff --git a/Makefile.am b/Makefile.am index 86e55bbf91..407983c887 100644 --- a/Makefile.am +++ b/Makefile.am @@ -12,7 +12,7 @@ AM_LDFLAGS = -L$(PREFIX)/lib AM_LDFLAGS += $(shell $(APR_CONFIG) --link-ld --libs ) AM_CFLAGS += $(shell $(APU_CONFIG) --includes) AM_LDFLAGS += $(shell $(APU_CONFIG) --link-ld --libs ) -lsqlite3 -AM_LDFLAGS += -lhowl -lresample -lm -L/usr/local/lib/db42 -L/usr/local/lib +AM_LDFLAGS += -lresample -lm -L/usr/local/lib/db42 -L/usr/local/lib OSARCH=$(shell uname -s) if ISLINUX AM_LDFLAGS += -Wl,-E @@ -131,7 +131,6 @@ depends: ./build/buildlib.sh . install apr-1.2.2.tar.gz --prefix=$(PREFIX) ./build/buildlib.sh . install apr-util-1.2.2.tar.gz --with-apr=../apr-1.2.2 --prefix=$(PREFIX) ./build/buildlib.sh . libresample-0.1.3.tgz --prefix=$(PREFIX) - ./build/buildlib.sh . howl-1.0.0.tar.gz --prefix=$(PREFIX) rm build/freeswitch.env diff --git a/Makefile.in b/Makefile.in index 01b1d90f9d..14e967f162 100644 --- a/Makefile.in +++ b/Makefile.in @@ -245,9 +245,8 @@ AM_CFLAGS = -I$(PREFIX)/include $(shell $(APR_CONFIG) --cflags \ -DSWITCH_CONF_DIR=\"$(PREFIX)/conf\" \ -DSWITCH_DB_DIR=\"$(PREFIX)/db\" AM_LDFLAGS = -L$(PREFIX)/lib $(shell $(APR_CONFIG) --link-ld --libs ) \ - $(shell $(APU_CONFIG) --link-ld --libs ) -lsqlite3 -lhowl \ - -lresample -lm -L/usr/local/lib/db42 -L/usr/local/lib \ - $(am__append_1) + $(shell $(APU_CONFIG) --link-ld --libs ) -lsqlite3 -lresample \ + -lm -L/usr/local/lib/db42 -L/usr/local/lib $(am__append_1) OSARCH = $(shell uname -s) @ISMAC_FALSE@SOLINK = -shared -Xlinker -x @ISMAC_TRUE@SOLINK = -dynamic -bundle -undefined suppress -force_flat_namespace @@ -1008,7 +1007,6 @@ depends: ./build/buildlib.sh . install apr-1.2.2.tar.gz --prefix=$(PREFIX) ./build/buildlib.sh . install apr-util-1.2.2.tar.gz --with-apr=../apr-1.2.2 --prefix=$(PREFIX) ./build/buildlib.sh . libresample-0.1.3.tgz --prefix=$(PREFIX) - ./build/buildlib.sh . howl-1.0.0.tar.gz --prefix=$(PREFIX) rm build/freeswitch.env modules: $(NAME) diff --git a/conf/zeroconf.conf b/conf/zeroconf.conf new file mode 100644 index 0000000000..29970adbc2 --- /dev/null +++ b/conf/zeroconf.conf @@ -0,0 +1,6 @@ +[settings] + +; cant do both at once WTF? +publish => yes +#browse => _sip._udp + diff --git a/modules.conf b/modules.conf index e6d5cb823b..6c94812e2d 100644 --- a/modules.conf +++ b/modules.conf @@ -1,3 +1,4 @@ +event_handlers/mod_zeroconf applications/mod_bridgecall applications/mod_playback applications/mod_ivrtest @@ -20,3 +21,4 @@ timers/mod_softtimer dialplans/mod_pcre directories/mod_ldap dialplans/mod_dialplan_directory + diff --git a/src/include/switch_types.h b/src/include/switch_types.h index 3777248c58..95692db7fc 100644 --- a/src/include/switch_types.h +++ b/src/include/switch_types.h @@ -330,6 +330,8 @@ typedef enum { SWITCH_EVENT_OUTBOUND_CHAN - A new outbound channel has been created SWITCH_EVENT_STARTUP - The system has been started SWITCH_EVENT_SHUTDOWN - The system has been shutdown + SWITCH_EVENT_PUBLISH - Publish + SWITCH_EVENT_UNPUBLISH - UnPublish SWITCH_EVENT_ALL - All events at once @@ -345,6 +347,8 @@ typedef enum { SWITCH_EVENT_OUTBOUND_CHAN, SWITCH_EVENT_STARTUP, SWITCH_EVENT_SHUTDOWN, + SWITCH_EVENT_PUBLISH, + SWITCH_EVENT_UNPUBLISH, SWITCH_EVENT_ALL } switch_event_t; diff --git a/src/mod/endpoints/mod_exosip/mod_exosip.c b/src/mod/endpoints/mod_exosip/mod_exosip.c index 57ac6a9206..03d4d19d90 100644 --- a/src/mod/endpoints/mod_exosip/mod_exosip.c +++ b/src/mod/endpoints/mod_exosip/mod_exosip.c @@ -1326,6 +1326,7 @@ static int config_exosip(int reload) SWITCH_MOD_DECLARE(switch_status) switch_module_runtime(void) { eXosip_event_t *event = NULL; + switch_event *s_event; config_exosip(0); @@ -1339,6 +1340,12 @@ SWITCH_MOD_DECLARE(switch_status) switch_module_runtime(void) return SWITCH_STATUS_TERM; } + if (switch_event_create(&s_event, SWITCH_EVENT_PUBLISH) == SWITCH_STATUS_SUCCESS) { + switch_event_add_header(s_event, SWITCH_STACK_BOTTOM, "service", "_sip._udp"); + switch_event_add_header(s_event, SWITCH_STACK_BOTTOM, "port", "%d", globals.port); + switch_event_fire(&s_event); + } + globals.running = 1; while (globals.running > 0) { if (!(event = eXosip_event_wait(0, 100))) { diff --git a/src/mod/event_handlers/mod_zeroconf/Makefile b/src/mod/event_handlers/mod_zeroconf/Makefile new file mode 100644 index 0000000000..cca46234bc --- /dev/null +++ b/src/mod/event_handlers/mod_zeroconf/Makefile @@ -0,0 +1,19 @@ +LDFLAGS += -lhowl +CFLAGS += -I$(PREFIX)/include/howl +LINKER=$(CC) + + +all: depends $(MODNAME).so + +depends: + $(BASE)/build/buildlib.sh $(BASE) install howl-1.0.0.tar.gz --prefix=$(PREFIX) + +$(MODNAME).so: $(MODNAME).c + $(CC) $(CFLAGS) -fPIC -c $(MODNAME).c -o $(MODNAME).o + $(LINKER) $(SOLINK) -o $(MODNAME).so $(MODNAME).o $(LDFLAGS) + +clean: + rm -fr *.so *.o *~ + +install: + cp -f $(MODNAME).so $(PREFIX)/mod diff --git a/src/mod/event_handlers/mod_zeroconf/mod_zeroconf.c b/src/mod/event_handlers/mod_zeroconf/mod_zeroconf.c new file mode 100644 index 0000000000..1ce39eef95 --- /dev/null +++ b/src/mod/event_handlers/mod_zeroconf/mod_zeroconf.c @@ -0,0 +1,319 @@ +/* + * FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application + * Copyright (C) 2005/2006, Anthony Minessale II + * + * Version: MPL 1.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application + * + * The Initial Developer of the Original Code is + * Anthony Minessale II + * Portions created by the Initial Developer are Copyright (C) + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * + * Anthony Minessale II + * + * + * mod_zeroconf.c -- Framework Demo Module + * + */ +#include +#include + +static const char modname[] = "mod_zeroconf"; + +static switch_memory_pool *module_pool; + +static struct { + sw_discovery discovery; + sw_discovery_publish_id disc_id; + switch_mutex_t *zc_lock; +} globals; + + + +static sw_result HOWL_API my_browser(sw_discovery discovery, + sw_discovery_oid oid, + sw_discovery_browse_status status, + sw_uint32 interface_index, + sw_const_string name, + sw_const_string type, + sw_const_string domain, + sw_opaque_t extra) { + sw_discovery_resolve_id rid; + + switch (status) { + case SW_DISCOVERY_BROWSE_INVALID: + { + switch_console_printf(SWITCH_CHANNEL_CONSOLE, "browse reply: Invalid\n"); + } + break; + + case SW_DISCOVERY_BROWSE_RELEASE: + { + switch_console_printf(SWITCH_CHANNEL_CONSOLE, "browse reply: Release\n"); + } + break; + + case SW_DISCOVERY_BROWSE_ADD_DOMAIN: + { + switch_console_printf(SWITCH_CHANNEL_CONSOLE, "browse reply: Add Domain\n"); + } + break; + + case SW_DISCOVERY_BROWSE_ADD_DEFAULT_DOMAIN: + { + switch_console_printf(SWITCH_CHANNEL_CONSOLE, "browse reply: Add Default Domain\n"); + } + break; + + case SW_DISCOVERY_BROWSE_REMOVE_DOMAIN: + { + switch_console_printf(SWITCH_CHANNEL_CONSOLE, "browse reply: Remove Domain\n"); + } + break; + + case SW_DISCOVERY_BROWSE_REMOVE_SERVICE: + { + switch_console_printf(SWITCH_CHANNEL_CONSOLE, "browse reply: Remove Service\n"); + switch_console_printf(SWITCH_CHANNEL_CONSOLE, "remove service: 0x%x %s %s %s\n", interface_index, name, type, domain); + } + break; + + case SW_DISCOVERY_BROWSE_RESOLVED: + { + switch_console_printf(SWITCH_CHANNEL_CONSOLE, "browse reply: Resolved\n"); + } + break; + case SW_DISCOVERY_BROWSE_ADD_SERVICE: + break; + } + + return SW_OKAY; +} + + +static sw_result HOWL_API my_service_reply(sw_discovery discovery, + sw_discovery_oid oid, + sw_discovery_publish_status status, + sw_opaque extra) { + static sw_string status_text[] = { + "Started", + "Stopped", + "Name Collision", + "Invalid" + }; + + switch_console_printf(SWITCH_CHANNEL_CONSOLE, "publish reply: %s\n", status_text[status]); + return SW_OKAY; +} + + +static void event_handler(switch_event *event) +{ + sw_text_record text_record; + sw_result result; + + switch (event->event_id) { + case SWITCH_EVENT_PUBLISH: + if (sw_text_record_init(&text_record) != SW_OKAY) { + switch_console_printf(SWITCH_CHANNEL_CONSOLE, "sw_text_record_init() failed\n"); + return; + } else { + switch_event_header *hp; + char *service = switch_event_get_header(event, "service"); + char *port = switch_event_get_header(event, "port"); + int porti = 0; + for (hp = event->headers; hp; hp = hp->next) { + int len = strlen(hp->name) + strlen(hp->value) + 2; + char *data = malloc(len); + + if (!data) { + return; + } + + snprintf(data, len, "%s=%s", hp->name, hp->value); + if (sw_text_record_add_string(text_record, data) != SW_OKAY) { + switch_console_printf(SWITCH_CHANNEL_CONSOLE, "unable to add service text: %s\n", data); + free(data); + return; + } + free(data); + } + if (!service) { + service = "_freeswitch._tcp"; + } + if (port) { + porti = atoi(port); + } + + switch_mutex_lock(globals.zc_lock); + if ((result = sw_discovery_publish(globals.discovery, + 0, + "freeswitch", + service, + NULL, + NULL, + porti, + sw_text_record_bytes(text_record), + sw_text_record_len(text_record), + my_service_reply, + NULL, + &globals.disc_id)) != SW_OKAY) { + switch_console_printf(SWITCH_CHANNEL_CONSOLE, "publish failed: %d\n", result); + sw_text_record_fina(text_record); + switch_mutex_unlock(globals.zc_lock); + return; + } + switch_mutex_unlock(globals.zc_lock); + sw_text_record_fina(text_record); + } + + break; + case SWITCH_EVENT_UNPUBLISH: + + break; + default: + break; + } +} + + +static switch_status load_config(void) +{ + switch_config cfg; + switch_status status = SWITCH_STATUS_SUCCESS; + char *var, *val; + char *cf = "zeroconf.conf"; + int count = 0; + sw_discovery_oid *oid; + + if (!switch_config_open_file(&cfg, cf)) { + switch_console_printf(SWITCH_CHANNEL_CONSOLE, "open of %s failed\n", cf); + return SWITCH_STATUS_TERM; + } + + while (switch_config_next_pair(&cfg, &var, &val)) { + if (!strcasecmp(cfg.category, "settings")) { + if (!strcmp(var, "browse")) { + if ((oid = switch_core_alloc(module_pool, sizeof(*oid)))) { + switch_console_printf(SWITCH_CHANNEL_CONSOLE, "Bind browser to to %s\n", val); + switch_mutex_lock(globals.zc_lock); + sw_discovery_browse(globals.discovery, 0, val, NULL, my_browser, NULL, oid); + switch_mutex_unlock(globals.zc_lock); + count++; + } else { + return SWITCH_STATUS_MEMERR; + } + } else if (!strcasecmp(var, "publish") && !strcasecmp(val, "yes")) { + if (switch_event_bind((char *) modname, SWITCH_EVENT_PUBLISH, SWITCH_EVENT_SUBCLASS_ANY, event_handler, NULL) != + SWITCH_STATUS_SUCCESS) { + switch_console_printf(SWITCH_CHANNEL_CONSOLE, "Couldn't bind!\n"); + return SWITCH_STATUS_GENERR; + } + + if (switch_event_bind((char *) modname, SWITCH_EVENT_UNPUBLISH, SWITCH_EVENT_SUBCLASS_ANY, event_handler, NULL) != + SWITCH_STATUS_SUCCESS) { + switch_console_printf(SWITCH_CHANNEL_CONSOLE, "Couldn't bind!\n"); + return SWITCH_STATUS_GENERR; + } + } + } + } + + switch_config_close_file(&cfg); + + return status; + +} + + +static switch_loadable_module_interface zeroconf_module_interface = { + /*.module_name */ modname, + /*.endpoint_interface */ NULL, + /*.timer_interface */ NULL, + /*.dialplan_interface */ NULL, + /*.codec_interface */ NULL, + /*.application_interface */ NULL +}; + +#define MY_EVENT_PUBLISH "zeroconf::broadcast" +#define MY_EVENT_UNPUBLISH "zeroconf::unbroadcast" + +static int RUNNING = 0; + +SWITCH_MOD_DECLARE(switch_status) switch_module_shutdown(void) +{ + if (RUNNING == 1) { + RUNNING = -1; + switch_yield(100000); + } + return SWITCH_STATUS_SUCCESS; +} + + + +SWITCH_MOD_DECLARE(switch_status) switch_module_load(switch_loadable_module_interface **interface, char *filename) +{ + + memset(&globals, 0, sizeof(globals)); + + if (switch_core_new_memory_pool(&module_pool) != SWITCH_STATUS_SUCCESS) { + switch_console_printf(SWITCH_CHANNEL_CONSOLE, "OH OH no pool\n"); + return SWITCH_STATUS_TERM; + } + + switch_mutex_init(&globals.zc_lock, SWITCH_MUTEX_NESTED, module_pool); + + if (sw_discovery_init(&globals.discovery) != SW_OKAY) { + switch_console_printf(SWITCH_CHANNEL_CONSOLE, "sw_discovery_init() failed\n"); + return SWITCH_STATUS_TERM; + } + + if (load_config() != SWITCH_STATUS_SUCCESS) { + return SWITCH_STATUS_TERM; + } + + if (switch_event_reserve_subclass(MY_EVENT_PUBLISH) != SWITCH_STATUS_SUCCESS) { + switch_console_printf(SWITCH_CHANNEL_CONSOLE, "Couldn't register subclass!"); + return SWITCH_STATUS_GENERR; + } + + if (switch_event_reserve_subclass(MY_EVENT_UNPUBLISH) != SWITCH_STATUS_SUCCESS) { + switch_console_printf(SWITCH_CHANNEL_CONSOLE, "Couldn't register subclass!"); + return SWITCH_STATUS_GENERR; + } + + /* connect my internal structure to the blank pointer passed to me */ + *interface = &zeroconf_module_interface; + + /* indicate that the module should continue to be loaded */ + return SWITCH_STATUS_SUCCESS; +} + + +SWITCH_MOD_DECLARE(switch_status) switch_module_runtime(void) +{ + + RUNNING = 1; + while(RUNNING == 1) { + unsigned int ms; + ms = 100; + sw_discovery_step(globals.discovery, &ms); + switch_yield(1000); + } + RUNNING = 0; + return SWITCH_STATUS_TERM; +} diff --git a/src/mod/event_handlers/mod_zeroconf/mod_zeroconf.vcproj b/src/mod/event_handlers/mod_zeroconf/mod_zeroconf.vcproj new file mode 100644 index 0000000000..9b84f39cdb --- /dev/null +++ b/src/mod/event_handlers/mod_zeroconf/mod_zeroconf.vcproj @@ -0,0 +1,207 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/switch_event.c b/src/switch_event.c index 96b538d10b..8d85bc1bb4 100644 --- a/src/switch_event.c +++ b/src/switch_event.c @@ -98,6 +98,8 @@ static char *EVENT_NAMES[] = { "OUTBOUND_CHAN", "STARTUP", "SHUTDOWN", + "PUBLISH", + "UNPUBLISH", "ALL" }; @@ -116,6 +118,7 @@ static int switch_events_match(switch_event *event, switch_event_node *node) } if (match || event->event_id == node->event_id) { + if (event->subclass && node->subclass) { if (!strncasecmp(node->subclass->name, "file:", 5)) { char *file_header; @@ -130,7 +133,7 @@ static int switch_events_match(switch_event *event, switch_event_node *node) } else { match = strstr(event->subclass->name, node->subclass->name) ? 1 : 0; } - } else if (event->subclass && !node->subclass) { + } else if ((event->subclass && !node->subclass) || (!event->subclass && !node->subclass)) { match = 1; } else { match = 0;