[asterisk-commits] branch group/new_loader_completion r36581 - in /team/group/new_loader_complet...

asterisk-commits at lists.digium.com asterisk-commits at lists.digium.com
Sat Jul 1 15:20:14 MST 2006


Author: kpfleming
Date: Sat Jul  1 17:20:13 2006
New Revision: 36581

URL: http://svn.digium.com/view/asterisk?rev=36581&view=rev
Log:
update to trunk

Added:
    team/group/new_loader_completion/doc/osp.txt
      - copied unchanged from r36562, trunk/doc/osp.txt
Removed:
    team/group/new_loader_completion/res/res_osp.c
Modified:
    team/group/new_loader_completion/   (props changed)
    team/group/new_loader_completion/Makefile
    team/group/new_loader_completion/apps/app_directory.c
    team/group/new_loader_completion/apps/app_meetme.c
    team/group/new_loader_completion/apps/app_osplookup.c
    team/group/new_loader_completion/build_tools/prep_moduledeps
    team/group/new_loader_completion/cdr/Makefile
    team/group/new_loader_completion/channels/Makefile
    team/group/new_loader_completion/channels/chan_agent.c
    team/group/new_loader_completion/channels/chan_misdn.c
    team/group/new_loader_completion/channels/chan_nbs.c
    team/group/new_loader_completion/channels/chan_sip.c
    team/group/new_loader_completion/channels/chan_skinny.c
    team/group/new_loader_completion/channels/misdn/chan_misdn_config.h
    team/group/new_loader_completion/channels/misdn/ie.c
    team/group/new_loader_completion/channels/misdn/isdn_lib.c
    team/group/new_loader_completion/channels/misdn/isdn_lib.h
    team/group/new_loader_completion/channels/misdn/isdn_lib_intern.h
    team/group/new_loader_completion/channels/misdn_config.c
    team/group/new_loader_completion/codecs/Makefile
    team/group/new_loader_completion/configs/extensions.conf.sample
    team/group/new_loader_completion/configs/misdn.conf.sample
    team/group/new_loader_completion/configs/queues.conf.sample
    team/group/new_loader_completion/configs/sip.conf.sample
    team/group/new_loader_completion/configure
    team/group/new_loader_completion/configure.ac
    team/group/new_loader_completion/devicestate.c
    team/group/new_loader_completion/doc/extconfig.txt
    team/group/new_loader_completion/doc/realtime.txt
    team/group/new_loader_completion/funcs/func_strings.c
    team/group/new_loader_completion/include/asterisk/astosp.h
    team/group/new_loader_completion/include/asterisk/autoconfig.h.in
    team/group/new_loader_completion/include/asterisk/devicestate.h
    team/group/new_loader_completion/include/asterisk/lock.h
    team/group/new_loader_completion/pbx.c
    team/group/new_loader_completion/res/Makefile
    team/group/new_loader_completion/res/res_features.c
    team/group/new_loader_completion/res/res_jabber.c
    team/group/new_loader_completion/sounds/Makefile

Propchange: team/group/new_loader_completion/
------------------------------------------------------------------------------
    automerge = hopefully

Propchange: team/group/new_loader_completion/
------------------------------------------------------------------------------
Binary property 'branch-1.2-blocked' - no diff available.

Propchange: team/group/new_loader_completion/
------------------------------------------------------------------------------
Binary property 'branch-1.2-merged' - no diff available.

Propchange: team/group/new_loader_completion/
------------------------------------------------------------------------------
--- svnmerge-integrated (original)
+++ svnmerge-integrated Sat Jul  1 17:20:13 2006
@@ -1,1 +1,1 @@
-/trunk:1-36021
+/trunk:1-36580

Modified: team/group/new_loader_completion/Makefile
URL: http://svn.digium.com/view/asterisk/team/group/new_loader_completion/Makefile?rev=36581&r1=36580&r2=36581&view=diff
==============================================================================
--- team/group/new_loader_completion/Makefile (original)
+++ team/group/new_loader_completion/Makefile Sat Jul  1 17:20:13 2006
@@ -66,16 +66,16 @@
 # Define standard directories for various platforms
 # These apply if they are not redefined in asterisk.conf 
 ifeq ($(OSARCH),SunOS)
-  ASTETCDIR=/etc/opt/asterisk
+  ASTETCDIR=/var/etc/asterisk
   ASTLIBDIR=/opt/asterisk/lib
-  ASTVARLIBDIR=/var/opt/asterisk/lib
-  ASTSPOOLDIR=/var/opt/asterisk/spool
-  ASTLOGDIR=/var/opt/asterisk/log
-  ASTHEADERDIR=/opt/asterisk/usr/include/asterisk
-  ASTBINDIR=/opt/asterisk/usr/bin
-  ASTSBINDIR=/opt/asterisk/usr/sbin
-  ASTVARRUNDIR=/var/opt/asterisk/run
-  ASTMANDIR=/opt/asterisk/usr/share/man
+  ASTVARLIBDIR=/var/opt/asterisk
+  ASTSPOOLDIR=/var/spool/asterisk
+  ASTLOGDIR=/var/log/asterisk
+  ASTHEADERDIR=/opt/asterisk/include
+  ASTBINDIR=/opt/asterisk/bin
+  ASTSBINDIR=/opt/asterisk/sbin
+  ASTVARRUNDIR=/var/run/asterisk
+  ASTMANDIR=/opt/asterisk/man
 else
   ASTETCDIR=$(sysconfdir)/asterisk
   ASTLIBDIR=$(libdir)/asterisk
@@ -132,7 +132,17 @@
 MOD_SUBDIR_CFLAGS=-I../include -I..
 OTHER_SUBDIR_CFLAGS=-I../include -I..
 
-ifeq ($(or $(findstring dont-optimize,$(MAKECMDGOALS)),$(findstring DONT_OPTIMIZE,$(MENUSELECT_CFLAGS))),)
+ifeq ($(origin MENUSELECT_CFLAGS),undefined)
+  MENUSELECT_CFLAGS:=$(shell grep MENUSELECT_CFLAGS $(USER_MAKEOPTS) .)
+  ifeq ($(MENUSELECT_CFLAGS),)
+    MENUSELECT_CFLAGS:=$(shell grep MENUSELECT_CFLAGS $(GLOBAL_MAKEOPTS) .)
+  endif
+  ifneq ($(MENUSELECT_CFLAGS),)
+    MENUSELECT_CFLAGS:=$(shell echo $(MENUSELECT_CFLAGS) | cut -f2 -d'=')
+  endif
+endif
+
+ifeq ($(findstring dont-optimize,$(MAKECMDGOALS)),$(findstring DONT_OPTIMIZE,$(MENUSELECT_CFLAGS)))
 # More GSM codec optimization
 # Uncomment to enable MMXTM optimizations for x86 architecture CPU's
 # which support MMX instructions.  This should be newer pentiums,
@@ -240,7 +250,7 @@
 endif
 
 ifeq ($(OSARCH),SunOS)
-  ASTCFLAGS+=-Wcast-align -DSOLARIS -Iinclude/solaris-compat -I$(CROSS_COMPILE_TARGET)/usr/local/ssl/include
+  ASTCFLAGS+=-Wcast-align -DSOLARIS -Iinclude/solaris-compat -I$(CROSS_COMPILE_TARGET)/opt/ssl/include -I$(CROSS_COMPILE_TARGET)/usr/local/ssl/include
 endif
 
 LIBEDIT=editline/libedit.a
@@ -339,9 +349,8 @@
 endif
 
 ifeq ($(OSARCH),SunOS)
-  LIBS+=-lpthread -ldl -lnsl -lsocket -lresolv -L$(CROSS_COMPILE_TARGET)/usr/local/ssl/lib
+  LIBS+=-lpthread -ldl -lnsl -lsocket -lresolv -L$(CROSS_COMPILE_TARGET)/opt/ssl/lib -L$(CROSS_COMPILE_TARGET)/usr/local/ssl/lib
   OBJS+=strcompat.o
-  MENUSELECT_OBJS+=strcompat.o
   ASTLINK=
   SOLINK=-shared -fpic -L$(CROSS_COMPILE_TARGET)/usr/local/ssl/lib
 endif
@@ -390,11 +399,8 @@
 	@echo "****"
 	@exit 1
 
-menuselect.makeopts: menuselect/menuselect makeopts.xml
-	@menuselect/menuselect --check-deps ${GLOBAL_MAKEOPTS} ${USER_MAKEOPTS} $@
-
-menuselect.makedeps: menuselect/menuselect makeopts.xml
-	@menuselect/menuselect --check-deps ${GLOBAL_MAKEOPTS} ${USER_MAKEOPTS} $@
+menuselect.makeopts menuselect.makedeps: menuselect/menuselect makeopts.xml
+	menuselect/menuselect --check-deps $(GLOBAL_MAKEOPTS) $(USER_MAKEOPTS) menuselect.makeopts
 
 #ifneq ($(wildcard tags),)
 ctags: tags
@@ -509,18 +515,19 @@
 	@$(MAKE) -C stdtime clean
 	@$(MAKE) -C menuselect clean
 
-distclean: dist-clean
-
-dist-clean: clean
+dist-clean: distclean
+
+distclean: clean
 	@$(MAKE) -C mxml clean
 	@$(MAKE) -C menuselect dist-clean
 	@$(MAKE) -C sounds dist-clean
 	rm -f menuselect.makeopts makeopts makeopts.xml menuselect.makedeps
 	rm -f config.log config.status
 	rm -rf autom4te.cache
-	rm -f include/autoconfig.h
+	rm -f include/asterisk/autoconfig.h
 	rm -f include/asterisk/buildopts.h
 	rm -rf doc/api
+	rm -f build_tools/menuselect-deps
 
 datafiles: all
 	if [ x`$(ID) -un` = xroot ]; then sh build_tools/mkpkgconfig $(DESTDIR)/usr/lib/pkgconfig; fi
@@ -876,10 +883,10 @@
 	rm -rf $(DESTDIR)$(ASTLOGDIR)
 
 menuselect: menuselect/menuselect makeopts.xml
-	- at menuselect/menuselect ${GLOBAL_MAKEOPTS} ${USER_MAKEOPTS} menuselect.makeopts && echo "menuselect changes saved!" || echo "menuselect changes NOT saved!"
-
-menuselect/menuselect: menuselect/menuselect.c menuselect/menuselect_curses.c menuselect/menuselect.h menuselect/linkedlists.h config.status mxml/libmxml.a $(MENUSELECT_OBJS)
-	@CFLAGS="-include ../include/asterisk/autoconfig.h" $(MAKE) -C menuselect menuselect
+	- at menuselect/menuselect $(GLOBAL_MAKEOPTS) $(USER_MAKEOPTS) menuselect.makeopts && echo "menuselect changes saved!" || echo "menuselect changes NOT saved!"
+
+menuselect/menuselect: menuselect/menuselect.c menuselect/menuselect_curses.c menuselect/menuselect.h menuselect/linkedlists.h config.status mxml/libmxml.a
+	@CFLAGS="-include $(PWD)/include/asterisk/autoconfig.h -I$(PWD)/include" PARENTSRC="$(PWD)" $(MAKE) -C menuselect menuselect
 
 mxml/libmxml.a:
 	@cd mxml && unset CFLAGS LIBS && test -f config.h || ./configure

Modified: team/group/new_loader_completion/apps/app_directory.c
URL: http://svn.digium.com/view/asterisk/team/group/new_loader_completion/apps/app_directory.c?rev=36581&r1=36580&r2=36581&view=diff
==============================================================================
--- team/group/new_loader_completion/apps/app_directory.c (original)
+++ team/group/new_loader_completion/apps/app_directory.c Sat Jul  1 17:20:13 2006
@@ -44,6 +44,16 @@
 #include "asterisk/say.h"
 #include "asterisk/utils.h"
 #include "asterisk/app.h"
+
+#ifdef USE_ODBC_STORAGE
+#include <errno.h>
+#include <sys/mman.h>
+#include "asterisk/res_odbc.h"
+
+static char odbc_database[80] = "asterisk";
+static char odbc_table[80] = "voicemessages";
+static char vmfmts[80] = "wav";
+#endif
 
 static char *app = "Directory";
 
@@ -78,6 +88,101 @@
 #define NUMDIGITS 3
 
 
+#ifdef USE_ODBC_STORAGE
+static void retrieve_file(char *dir)
+{
+	int x = 0;
+	int res;
+	int fd=-1;
+	size_t fdlen = 0;
+	void *fdm=NULL;
+	SQLHSTMT stmt;
+	char sql[256];
+	char fmt[80]="";
+	char *c;
+	SQLLEN colsize;
+	char full_fn[256];
+
+	odbc_obj *obj;
+	obj = fetch_odbc_obj(odbc_database, 0);
+	if (obj) {
+		do {
+			ast_copy_string(fmt, vmfmts, sizeof(fmt));
+			c = strchr(fmt, '|');
+			if (c)
+				*c = '\0';
+			if (!strcasecmp(fmt, "wav49"))
+				strcpy(fmt, "WAV");
+			snprintf(full_fn, sizeof(full_fn), "%s.%s", dir, fmt);
+			res = SQLAllocHandle(SQL_HANDLE_STMT, obj->con, &stmt);
+			if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) {
+				ast_log(LOG_WARNING, "SQL Alloc Handle failed!\n");
+				break;
+			}
+			snprintf(sql, sizeof(sql), "SELECT recording FROM %s WHERE dir=? AND msgnum=-1", odbc_table);
+			res = SQLPrepare(stmt, (unsigned char *)sql, SQL_NTS);
+			if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) {
+				ast_log(LOG_WARNING, "SQL Prepare failed![%s]\n", sql);
+				SQLFreeHandle(SQL_HANDLE_STMT, stmt);
+				break;
+			}
+			SQLBindParameter(stmt, 1, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR, strlen(dir), 0, (void *)dir, 0, NULL);
+			res = odbc_smart_execute(obj, stmt);
+			if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) {
+				ast_log(LOG_WARNING, "SQL Execute error!\n[%s]\n\n", sql);
+				SQLFreeHandle(SQL_HANDLE_STMT, stmt);
+				break;
+			}
+			res = SQLFetch(stmt);
+			if (res == SQL_NO_DATA) {
+				SQLFreeHandle(SQL_HANDLE_STMT, stmt);
+				break;
+			} else if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) {
+				ast_log(LOG_WARNING, "SQL Fetch error!\n[%s]\n\n", sql);
+				SQLFreeHandle(SQL_HANDLE_STMT, stmt);
+				break;
+			}
+			fd = open(full_fn, O_RDWR | O_CREAT | O_TRUNC, 0770);
+			if (fd < 0) {
+				ast_log(LOG_WARNING, "Failed to write '%s': %s\n", full_fn, strerror(errno));
+				SQLFreeHandle(SQL_HANDLE_STMT, stmt);
+				break;
+			}
+
+			res = SQLGetData(stmt, 1, SQL_BINARY, NULL, 0, &colsize);
+			fdlen = colsize;
+			if (fd > -1) {
+				char tmp[1]="";
+				lseek(fd, fdlen - 1, SEEK_SET);
+				if (write(fd, tmp, 1) != 1) {
+					close(fd);
+					fd = -1;
+					break;
+				}
+				if (fd > -1)
+					fdm = mmap(NULL, fdlen, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
+			}
+			if (fdm) {
+				memset(fdm, 0, fdlen);
+				res = SQLGetData(stmt, x + 1, SQL_BINARY, fdm, fdlen, &colsize);
+				if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) {
+					ast_log(LOG_WARNING, "SQL Get Data error!\n[%s]\n\n", sql);
+					SQLFreeHandle(SQL_HANDLE_STMT, stmt);
+					break;
+				}
+			}
+			SQLFreeHandle(SQL_HANDLE_STMT, stmt);
+		} while (0);
+	} else
+		ast_log(LOG_WARNING, "Failed to obtain database object for '%s'!\n", odbc_database);
+	if (fdm)
+		munmap(fdm, fdlen);
+	if (fd > -1)
+		close(fd);
+	return;
+}
+#endif
+
 static char *convert(char *lastname)
 {
 	char *tmp;
@@ -162,12 +267,18 @@
 	/* Check for the VoiceMail2 greeting first */
 	snprintf(fn, sizeof(fn), "%s/voicemail/%s/%s/greet",
 		ast_config_AST_SPOOL_DIR, context, ext);
+#ifdef USE_ODBC_STORAGE
+	retrieve_file(fn);
+#endif
 
 	if (ast_fileexists(fn, NULL, chan->language) <= 0) {
 		/* no file, check for an old-style Voicemail greeting */
 		snprintf(fn, sizeof(fn), "%s/vm/%s/greet",
 			ast_config_AST_SPOOL_DIR, ext);
 	}
+#ifdef USE_ODBC_STORAGE
+	retrieve_file(fn2);
+#endif
 
 	if (ast_fileexists(fn, NULL, chan->language) > 0) {
 		res = ast_stream_and_wait(chan, fn, chan->language, AST_DIGIT_ANY);
@@ -184,6 +295,10 @@
 			res = ast_say_character_str(chan, ext, AST_DIGIT_ANY, chan->language);
 		}
 	}
+#ifdef USE_ODBC_STORAGE
+	ast_filedelete(fn, NULL);	
+	ast_filedelete(fn2, NULL);	
+#endif
 
 	for (loop = 3 ; loop > 0; loop--) {
 		if (!res)
@@ -471,6 +586,25 @@
 
 static int load_module(void)
 {
+#ifdef USE_ODBC_STORAGE
+	struct ast_config *cfg = ast_config_load(VOICEMAIL_CONFIG);
+	char *tmp;
+
+	if (cfg) {
+		if ((tmp = ast_variable_retrieve(cfg, "general", "odbcstorage"))) {
+			ast_copy_string(odbc_database, tmp, sizeof(odbc_database));
+		}
+		if ((tmp = ast_variable_retrieve(cfg, "general", "odbctable"))) {
+			ast_copy_string(odbc_table, tmp, sizeof(odbc_table));
+		}
+		if ((tmp = ast_variable_retrieve(cfg, "general", "format"))) {
+			ast_copy_string(vmfmts, tmp, sizeof(vmfmts));
+		}
+		ast_config_destroy(cfg);
+	} else
+		ast_log(LOG_WARNING, "Unable to load " VOICEMAIL_CONFIG " - ODBC defaults will be used\n");
+#endif
+
 	return ast_register_application(app, directory_exec, synopsis, descrip);
 }
 

Modified: team/group/new_loader_completion/apps/app_meetme.c
URL: http://svn.digium.com/view/asterisk/team/group/new_loader_completion/apps/app_meetme.c?rev=36581&r1=36580&r2=36581&view=diff
==============================================================================
--- team/group/new_loader_completion/apps/app_meetme.c (original)
+++ team/group/new_loader_completion/apps/app_meetme.c Sat Jul  1 17:20:13 2006
@@ -58,6 +58,7 @@
 #include "asterisk/utils.h"
 #include "asterisk/translate.h"
 #include "asterisk/ulaw.h"
+#include "asterisk/devicestate.h"
 
 #include "enter.h"
 #include "leave.h"
@@ -272,7 +273,7 @@
 	int markedusers;                        /*!< Number of marked users */
 	time_t start;                           /*!< Start time (s) */
 	int refcount;                           /*!< reference count of usage */
-	enum recording_state recording:2;               /*!< recording status */
+	enum recording_state recording:2;       /*!< recording status */
 	unsigned int isdynamic:1;               /*!< Created on the fly? */
 	unsigned int locked:1;                  /*!< Is the conference locked? */
 	pthread_t recordthread;                 /*!< thread for recording */
@@ -964,6 +965,10 @@
 	/* Update table */
 	snprintf(members, sizeof(members), "%d", conf->users);
 	ast_update_realtime("meetme", "confno", conf->confno, "members", members , NULL);
+
+	/* This device changed state now - if this is the first user */
+	if (conf->users == 1)
+		ast_device_state_changed("meetme:%s", conf->confno);
 
 	ast_mutex_unlock(&conf->playlock);
 
@@ -1740,6 +1745,10 @@
 		/* Return the number of seconds the user was in the conf */
 		snprintf(meetmesecs, sizeof(meetmesecs), "%d", (int) (time(NULL) - user->jointime));
 		pbx_builtin_setvar_helper(chan, "MEETMESECS", meetmesecs);
+
+		/* This device changed state now */
+		if (!conf->users)	/* If there are no more members */
+			ast_device_state_changed("meetme:%s", conf->confno);
 	}
 	free(user);
 	AST_LIST_UNLOCK(&confs);
@@ -2508,6 +2517,29 @@
 	pthread_exit(0);
 }
 
+/*! \brief Callback for devicestate providers */
+static int meetmestate(const char *data)
+{
+	struct ast_conference *conf;
+
+	/* Find conference */
+	AST_LIST_LOCK(&confs);
+	AST_LIST_TRAVERSE(&confs, conf, list) {
+		if (!strcmp(data, conf->confno))
+			break;
+	}
+	AST_LIST_UNLOCK(&confs);
+	if (!conf)
+		return AST_DEVICE_INVALID;
+
+
+	/* SKREP to fill */
+	if (!conf->users)
+		return AST_DEVICE_NOT_INUSE;
+
+	return AST_DEVICE_INUSE;
+}
+
 static void load_config(void)
 {
 	struct ast_config *cfg;
@@ -2546,6 +2578,7 @@
 	res |= ast_unregister_application(app);
 
 	ast_module_user_hangup_all();
+	ast_devstate_prov_del("Meetme");
 
 	return res;
 }
@@ -2563,6 +2596,7 @@
 	res |= ast_register_application(app2, count_exec, synopsis2, descrip2);
 	res |= ast_register_application(app, conf_exec, synopsis, descrip);
 
+	res |= ast_devstate_prov_add("Meetme", meetmestate);
 	return res;
 }
 

Modified: team/group/new_loader_completion/apps/app_osplookup.c
URL: http://svn.digium.com/view/asterisk/team/group/new_loader_completion/apps/app_osplookup.c?rev=36581&r1=36580&r2=36581&view=diff
==============================================================================
--- team/group/new_loader_completion/apps/app_osplookup.c (original)
+++ team/group/new_loader_completion/apps/app_osplookup.c Sat Jul  1 17:20:13 2006
@@ -18,7 +18,7 @@
 
 /*!
  * \file
- * \brief Open Settlement Protocol Applications
+ * \brief Open Settlement Protocol (OSP) Applications
  *
  * \author Mark Spencer <markster at digium.com>
  * 
@@ -34,90 +34,953 @@
 
 ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
 
+#include <sys/types.h>
 #include <stdio.h>
-#include <stdlib.h>
+#include <string.h>
 #include <unistd.h>
-#include <string.h>
-#include <ctype.h>
+#include <errno.h>
+#include <osp/osp.h>
+#include <osp/osputils.h>
 
 #include "asterisk/lock.h"
-#include "asterisk/file.h"
-#include "asterisk/logger.h"
+#include "asterisk/config.h"
+#include "asterisk/utils.h"
+#include "asterisk/causes.h"
 #include "asterisk/channel.h"
+#include "asterisk/app.h"
+#include "asterisk/module.h"
 #include "asterisk/pbx.h"
 #include "asterisk/options.h"
-#include "asterisk/config.h"
-#include "asterisk/module.h"
-#include "asterisk/utils.h"
-#include "asterisk/causes.h"
+#include "asterisk/cli.h"
+#include "asterisk/logger.h"
 #include "asterisk/astosp.h"
-#include "asterisk/app.h"
-#include "asterisk/options.h"
-
-static char *app1= "OSPAuth";
-static char *synopsis1 = "OSP authentication";
-static char *descrip1 = 
-"  OSPAuth([provider[|options]]):  Authenticate a SIP INVITE by OSP and sets\n"
-"the variables:\n"
-" ${OSPINHANDLE}:  The in_bound call transaction handle\n"
-" ${OSPINTIMELIMIT}:  The in_bound call duration limit in seconds\n"
-"\n"
-"The option string may contain the following character:\n"
-"	'j' -- jump to n+101 priority if the authentication was NOT successful\n"
-"This application sets the following channel variable upon completion:\n"
-"	OSPAUTHSTATUS	The status of the OSP Auth attempt as a text string, one of\n"
-"		SUCCESS | FAILED | ERROR\n";
-
-static char *app2= "OSPLookup";
-static char *synopsis2 = "Lookup destination by OSP";
-static char *descrip2 = 
-"  OSPLookup(exten[|provider[|options]]):  Looks up an extension via OSP and sets\n"
-"the variables, where 'n' is the number of the result beginning with 1:\n"
-" ${OSPOUTHANDLE}:  The OSP Handle for anything remaining\n"
-" ${OSPTECH}:  The technology to use for the call\n"
-" ${OSPDEST}:  The destination to use for the call\n"
-" ${OSPCALLING}:  The calling number to use for the call\n"
-" ${OSPOUTTOKEN}:  The actual OSP token as a string\n"
-" ${OSPOUTTIMELIMIT}:  The out_bound call duration limit in seconds\n"
-" ${OSPRESULTS}:  The number of OSP results total remaining\n"
-"\n"
-"The option string may contain the following character:\n"
-"	'j' -- jump to n+101 priority if the lookup was NOT successful\n"
-"This application sets the following channel variable upon completion:\n"
-"	OSPLOOKUPSTATUS	The status of the OSP Lookup attempt as a text string, one of\n"
-"		SUCCESS | FAILED | ERROR\n";
-
-static char *app3 = "OSPNext";
-static char *synopsis3 = "Lookup next destination by OSP";
-static char *descrip3 = 
-"  OSPNext(cause[|options]):  Looks up the next OSP Destination for ${OSPOUTHANDLE}\n"
-"See OSPLookup for more information\n"
-"\n"
-"The option string may contain the following character:\n"
-"	'j' -- jump to n+101 priority if the lookup was NOT successful\n"
-"This application sets the following channel variable upon completion:\n"
-"	OSPNEXTSTATUS	The status of the OSP Next attempt as a text string, one of\n"
-"		SUCCESS | FAILED |ERROR\n";
-
-static char *app4 = "OSPFinish";
-static char *synopsis4 = "Record OSP entry";
-static char *descrip4 = 
-"  OSPFinish([status[|options]]):  Records call state for ${OSPINHANDLE}, according to\n"
-"status, which should be one of BUSY, CONGESTION, ANSWER, NOANSWER, or CHANUNAVAIL\n"
-"or coincidentally, just what the Dial application stores in its ${DIALSTATUS}.\n"
-"\n"
-"The option string may contain the following character:\n"
-"	'j' -- jump to n+101 priority if the finish attempt was NOT successful\n"
-"This application sets the following channel variable upon completion:\n"
-"	OSPFINISHSTATUS	The status of the OSP Finish attempt as a text string, one of\n"
-"		SUCCESS | FAILED |ERROR \n";
-
-
-static int ospauth_exec(struct ast_channel *chan, void *data)
+
+/* OSP Buffer Sizes */
+#define OSP_INTSTR_SIZE			((unsigned int)16)			/* OSP signed/unsigned int string buffer size */
+#define OSP_NORSTR_SIZE			((unsigned int)256)			/* OSP normal string buffer size */
+#define OSP_TOKSTR_SIZE			((unsigned int)4096)		/* OSP token string buffer size */
+
+/* OSP Constants */
+#define OSP_INVALID_HANDLE		((int)-1)					/* Invalid OSP handle, provider, transaction etc. */
+#define OSP_CONFIG_FILE			((const char*)"osp.conf")	/* OSP configuration file name */
+#define OSP_GENERAL_CAT			((const char*)"general")	/* OSP global configuration context name */
+#define OSP_DEF_PROVIDER		((const char*)"default")	/* OSP default provider context name */
+#define OSP_MAX_CERTS			((unsigned int)10)			/* OSP max number of cacerts */
+#define OSP_MAX_SRVS			((unsigned int)10)			/* OSP max number of service points */
+#define OSP_DEF_MAXCONNECTIONS	((unsigned int)20)			/* OSP default max_connections */
+#define OSP_MIN_MAXCONNECTIONS	((unsigned int)1)			/* OSP min max_connections */
+#define OSP_MAX_MAXCONNECTIONS	((unsigned int)1000)		/* OSP max max_connections */
+#define OSP_DEF_RETRYDELAY		((unsigned int)0)			/* OSP default retry delay */
+#define OSP_MIN_RETRYDELAY		((unsigned int)0)			/* OSP min retry delay */
+#define OSP_MAX_RETRYDELAY		((unsigned int)10)			/* OSP max retry delay */
+#define OSP_DEF_RETRYLIMIT		((unsigned int)2)			/* OSP default retry times */
+#define OSP_MIN_RETRYLIMIT		((unsigned int)0)			/* OSP min retry times */
+#define OSP_MAX_RETRYLIMIT		((unsigned int)100)			/* OSP max retry times */
+#define OSP_DEF_TIMEOUT			((unsigned int)500)			/* OSP default timeout in ms */
+#define OSP_MIN_TIMEOUT			((unsigned int)200)			/* OSP min timeout in ms */
+#define OSP_MAX_TIMEOUT			((unsigned int)10000)		/* OSP max timeout in ms */
+#define OSP_DEF_AUTHPOLICY		((enum osp_authpolicy)OSP_AUTH_YES)
+#define OSP_AUDIT_URL			((const char*)"localhost")	/* OSP default Audit URL */
+#define OSP_LOCAL_VALIDATION	((int)1)					/* Validate OSP token locally */
+#define OSP_SSL_LIFETIME		((unsigned int)300)			/* SSL life time, in seconds */
+#define OSP_HTTP_PERSISTENCE	((int)1)					/* In seconds */
+#define OSP_CUSTOMER_ID			((const char*)"")			/* OSP customer ID */
+#define OSP_DEVICE_ID			((const char*)"")			/* OSP device ID */
+#define OSP_DEF_DESTINATIONS	((unsigned int)5)			/* OSP default max number of destinations */
+#define OSP_DEF_TIMELIMIT		((unsigned int)0)			/* OSP default duration limit, no limit */
+
+/* OSP Authentication Policy */
+enum osp_authpolicy {
+	OSP_AUTH_NO,		/* Accept any call */
+	OSP_AUTH_YES,		/* Accept call with valid OSP token or without OSP token */
+	OSP_AUTH_EXCLUSIVE	/* Only accept call with valid OSP token */
+};
+
+/* OSP Provider */
+struct osp_provider {
+	char name[OSP_NORSTR_SIZE];						/* OSP provider context name */
+	char privatekey[OSP_NORSTR_SIZE];				/* OSP private key file name */
+	char localcert[OSP_NORSTR_SIZE];				/* OSP local cert file name */
+	unsigned int cacount;							/* Number of cacerts */
+	char cacerts[OSP_MAX_CERTS][OSP_NORSTR_SIZE]; 	/* Cacert file names */
+	unsigned int spcount;							/* Number of service points */
+	char srvpoints[OSP_MAX_SRVS][OSP_NORSTR_SIZE];	/* Service point URLs */
+	int maxconnections;								/* Max number of connections */
+	int retrydelay;									/* Retry delay */
+	int retrylimit;									/* Retry limit */
+	int timeout;									/* Timeout in ms */
+	char source[OSP_NORSTR_SIZE];					/* IP of self */
+	enum osp_authpolicy authpolicy;					/* OSP authentication policy */
+	OSPTPROVHANDLE handle;							/* OSP provider handle */
+	struct osp_provider* next;						/* Pointer to next OSP provider */
+};
+
+/* OSP Application In/Output Results */
+struct osp_result {
+	int inhandle;					/* Inbound transaction handle */
+	int outhandle;					/* Outbound transaction handle */
+	unsigned int intimelimit;		/* Inbound duration limit */
+	unsigned int outtimelimit;		/* Outbound duration limit */
+	char tech[20];					/* Asterisk TECH string */
+	char dest[OSP_NORSTR_SIZE];		/* Destination in called at IP format */
+	char calling[OSP_NORSTR_SIZE];	/* Calling number, may be translated */
+	char token[OSP_TOKSTR_SIZE];	/* Outbound OSP token */
+	int numresults;					/* Number of remain destinations */
+};
+
+/* OSP Module Global Variables */
+AST_MUTEX_DEFINE_STATIC(osplock);							/* Lock of OSP provider list */
+static int osp_initialized = 0;								/* Init flag */
+static int osp_hardware = 0;								/* Hardware accelleration flag */
+static struct osp_provider* ospproviders = NULL;			/* OSP provider list */
+static unsigned int osp_tokenformat = TOKEN_ALGO_SIGNED;	/* Token format supported */
+
+/* OSP Client Wrapper APIs */
+
+/*!
+ * \brief Create OSP provider handle according to configuration
+ * \param cfg OSP configuration
+ * \param provider OSP provider context name
+ * \return 1 Success, 0 Failed, -1 Error
+ */
+static int osp_create_provider(
+	struct ast_config* cfg,		/* OSP configuration */
+	const char* provider)		/* OSP provider context name */
+{
+	int res;
+	unsigned int t, i, j;
+	struct osp_provider* p;
+	struct ast_variable* v;
+	OSPTPRIVATEKEY privatekey;
+	OSPTCERT localcert;
+	const char* psrvpoints[OSP_MAX_SRVS];
+	OSPTCERT cacerts[OSP_MAX_CERTS];
+	const OSPTCERT* pcacerts[OSP_MAX_CERTS];
+	int error = OSPC_ERR_NO_ERROR;
+
+	if (!(p = ast_calloc(1, sizeof(*p)))) {
+		ast_log(LOG_ERROR, "Out of memory\n");
+		return -1;
+	}
+
+	ast_copy_string(p->name, provider, sizeof(p->name));
+	snprintf(p->privatekey, sizeof(p->privatekey), "%s/%s-privatekey.pem", ast_config_AST_KEY_DIR, provider);
+	snprintf(p->localcert, sizeof(p->localcert), "%s/%s-localcert.pem", ast_config_AST_KEY_DIR, provider);
+	p->maxconnections = OSP_DEF_MAXCONNECTIONS;
+	p->retrydelay = OSP_DEF_RETRYDELAY;
+	p->retrylimit = OSP_DEF_RETRYLIMIT;
+	p->timeout = OSP_DEF_TIMEOUT;
+	p->authpolicy = OSP_DEF_AUTHPOLICY;
+	p->handle = OSP_INVALID_HANDLE;
+
+	v = ast_variable_browse(cfg, provider);
+	while(v) {
+		if (!strcasecmp(v->name, "privatekey")) {
+			if (v->value[0] == '/') {
+				ast_copy_string(p->privatekey, v->value, sizeof(p->privatekey));
+			} else {
+				snprintf(p->privatekey, sizeof(p->privatekey), "%s/%s", ast_config_AST_KEY_DIR, v->value);
+			}
+			ast_log(LOG_DEBUG, "OSP: privatekey '%s'\n", p->privatekey);
+		} else if (!strcasecmp(v->name, "localcert")) {
+			if (v->value[0] == '/') {
+				ast_copy_string(p->localcert, v->value, sizeof(p->localcert));
+			} else {
+				snprintf(p->localcert, sizeof(p->localcert), "%s/%s", ast_config_AST_KEY_DIR, v->value);
+			}
+			ast_log(LOG_DEBUG, "OSP: localcert '%s'\n", p->localcert);
+		} else if (!strcasecmp(v->name, "cacert")) {
+			if (p->cacount < OSP_MAX_CERTS) {
+				if (v->value[0] == '/') {
+					ast_copy_string(p->cacerts[p->cacount], v->value, sizeof(p->cacerts[0]));
+				} else {
+					snprintf(p->cacerts[p->cacount], sizeof(p->cacerts[0]), "%s/%s", ast_config_AST_KEY_DIR, v->value);
+				}
+				ast_log(LOG_DEBUG, "OSP: cacert[%d]: '%s'\n", p->cacount, p->cacerts[p->cacount]);
+				p->cacount++;
+			} else {
+				ast_log(LOG_WARNING, "OSP: Too many CA Certificates at line %d\n", v->lineno);
+			}
+		} else if (!strcasecmp(v->name, "servicepoint")) {
+			if (p->spcount < OSP_MAX_SRVS) {
+				ast_copy_string(p->srvpoints[p->spcount], v->value, sizeof(p->srvpoints[0]));
+				ast_log(LOG_DEBUG, "OSP: servicepoint[%d]: '%s'\n", p->spcount, p->srvpoints[p->spcount]);
+				p->spcount++;
+			} else {
+				ast_log(LOG_WARNING, "OSP: Too many Service Points at line %d\n", v->lineno);
+			}
+		} else if (!strcasecmp(v->name, "maxconnections")) {
+			if ((sscanf(v->value, "%d", &t) == 1) && (t >= OSP_MIN_MAXCONNECTIONS) && (t <= OSP_MAX_MAXCONNECTIONS)) {
+				p->maxconnections = t;
+				ast_log(LOG_DEBUG, "OSP: maxconnections '%d'\n", t);
+			} else {
+				ast_log(LOG_WARNING, "OSP: maxconnections should be an integer from %d to %d, not '%s' at line %d\n", 
+					OSP_MIN_MAXCONNECTIONS, OSP_MAX_MAXCONNECTIONS, v->value, v->lineno);
+			}
+		} else if (!strcasecmp(v->name, "retrydelay")) {
+			if ((sscanf(v->value, "%d", &t) == 1) && (t >= OSP_MIN_RETRYDELAY) && (t <= OSP_MAX_RETRYDELAY)) {
+				p->retrydelay = t;
+				ast_log(LOG_DEBUG, "OSP: retrydelay '%d'\n", t);
+			} else {
+				ast_log(LOG_WARNING, "OSP: retrydelay should be an integer from %d to %d, not '%s' at line %d\n", 
+					OSP_MIN_RETRYDELAY, OSP_MAX_RETRYDELAY, v->value, v->lineno);
+			}
+		} else if (!strcasecmp(v->name, "retrylimit")) {
+			if ((sscanf(v->value, "%d", &t) == 1) && (t >= OSP_MIN_RETRYLIMIT) && (t <= OSP_MAX_RETRYLIMIT)) {
+				p->retrylimit = t;
+				ast_log(LOG_DEBUG, "OSP: retrylimit '%d'\n", t);
+			} else {
+				ast_log(LOG_WARNING, "OSP: retrylimit should be an integer from %d to %d, not '%s' at line %d\n", 
+					OSP_MIN_RETRYLIMIT, OSP_MAX_RETRYLIMIT, v->value, v->lineno);
+			}
+		} else if (!strcasecmp(v->name, "timeout")) {
+			if ((sscanf(v->value, "%d", &t) == 1) && (t >= OSP_MIN_TIMEOUT) && (t <= OSP_MAX_TIMEOUT)) {
+				p->timeout = t;
+				ast_log(LOG_DEBUG, "OSP: timeout '%d'\n", t);
+			} else {
+				ast_log(LOG_WARNING, "OSP: timeout should be an integer from %d to %d, not '%s' at line %d\n", 
+					OSP_MIN_TIMEOUT, OSP_MAX_TIMEOUT, v->value, v->lineno);
+			}
+		} else if (!strcasecmp(v->name, "source")) {
+			ast_copy_string(p->source, v->value, sizeof(p->source));
+			ast_log(LOG_DEBUG, "OSP: source '%s'\n", p->source);
+		} else if (!strcasecmp(v->name, "authpolicy")) {
+			if ((sscanf(v->value, "%d", &t) == 1) && ((t == OSP_AUTH_NO) || (t == OSP_AUTH_YES) || (t == OSP_AUTH_EXCLUSIVE))) {
+				p->authpolicy = t;
+				ast_log(LOG_DEBUG, "OSP: authpolicy '%d'\n", t);
+			} else {
+				ast_log(LOG_WARNING, "OSP: authpolicy should be %d, %d or %d, not '%s' at line %d\n", 
+					OSP_AUTH_NO, OSP_AUTH_YES, OSP_AUTH_EXCLUSIVE, v->value, v->lineno);
+			}
+		}
+		v = v->next;
+	}
+
+	error = OSPPUtilLoadPEMPrivateKey(p->privatekey, &privatekey);
+	if (error != OSPC_ERR_NO_ERROR) {
+		ast_log(LOG_WARNING, "OSP: Unable to load privatekey '%s', error '%d'\n", p->privatekey, error);
+		free(p);
+		return 0;
+	}
+
+	error = OSPPUtilLoadPEMCert(p->localcert, &localcert);
+	if (error != OSPC_ERR_NO_ERROR) {
+		ast_log(LOG_WARNING, "OSP: Unable to load localcert '%s', error '%d'\n", p->localcert, error);
+		if (privatekey.PrivateKeyData) {
+			free(privatekey.PrivateKeyData);
+		}
+		free(p);
+		return 0;
+	}
+
+	if (p->cacount < 1) {
+		snprintf(p->cacerts[p->cacount], sizeof(p->cacerts[0]), "%s/%s-cacert.pem", ast_config_AST_KEY_DIR, provider);
+		ast_log(LOG_DEBUG, "OSP: cacert[%d]: '%s'\n", p->cacount, p->cacerts[p->cacount]);
+		p->cacount++;
+	}
+	for (i = 0; i < p->cacount; i++) {
+		error = OSPPUtilLoadPEMCert(p->cacerts[i], &cacerts[i]);
+		if (error != OSPC_ERR_NO_ERROR) {
+			ast_log(LOG_WARNING, "OSP: Unable to load cacert '%s', error '%d'\n", p->cacerts[i], error);
+			for (j = 0; j < i; j++) {
+				if (cacerts[j].CertData) {
+					free(cacerts[j].CertData);
+				}
+			}
+			if (localcert.CertData) {
+				free(localcert.CertData);
+			}
+			if (privatekey.PrivateKeyData) {
+				free(privatekey.PrivateKeyData);
+			}
+			free(p);
+			return 0;
+		}
+		pcacerts[i] = &cacerts[i];
+	}
+	
+	for (i = 0; i < p->spcount; i++) {
+		psrvpoints[i] = p->srvpoints[i];
+	}
+
+	error = OSPPProviderNew(
+		p->spcount, psrvpoints,
+		NULL,
+		OSP_AUDIT_URL,
+		&privatekey,
+		&localcert,
+		p->cacount, pcacerts,
+		OSP_LOCAL_VALIDATION,
+		OSP_SSL_LIFETIME,
+		p->maxconnections,
+		OSP_HTTP_PERSISTENCE,
+		p->retrydelay,
+		p->retrylimit,
+		p->timeout,
+		OSP_CUSTOMER_ID,
+		OSP_DEVICE_ID,
+		&p->handle);
+	if (error != OSPC_ERR_NO_ERROR) {
+		ast_log(LOG_WARNING, "OSP: Unable to create provider '%s', error '%d'\n", provider, error);
+		free(p);
+		res = -1;
+	} else {
+		ast_log(LOG_DEBUG, "OSP: provider '%s'\n", provider);
+		ast_mutex_lock(&osplock);
+		p->next = ospproviders;
+		ospproviders = p;
+		ast_mutex_unlock(&osplock); 	
+		res = 1;
+	}
+
+	for (i = 0; i < p->cacount; i++) {
+		if (cacerts[i].CertData) {
+			free(cacerts[i].CertData);
+		}
+	}
+	if (localcert.CertData) {
+		free(localcert.CertData);
+	}
+	if (privatekey.PrivateKeyData) {
+		free(privatekey.PrivateKeyData);
+	}
+
+	return res;
+}
+
+/*!
+ * \brief Get OSP authenticiation policy of provider
+ * \param provider OSP provider context name
+ * \param policy OSP authentication policy, output
+ * \return 1 Success, 0 Failed, -1 Error
+ */
+static int osp_get_policy(
+	const char* provider,		/* OSP provider context name */
+	int* policy)				/* OSP authentication policy, output */
 {
 	int res = 0;
+	struct osp_provider* p;
+
+	ast_mutex_lock(&osplock);
+	p = ospproviders;
+	while(p) {
+		if (!strcasecmp(p->name, provider)) {
+			*policy = p->authpolicy;
+			ast_log(LOG_DEBUG, "OSP: authpolicy '%d'\n", *policy);
+			res = 1;
+			break;
+		}
+		p = p->next;
+	}
+	ast_mutex_unlock(&osplock);
+
+	return res;
+}
+
+/*!
+ * \brief Create OSP transaction handle
+ * \param provider OSP provider context name
+ * \param transaction OSP transaction handle, output
+ * \param sourcesize Size of source buffer, in/output
+ * \param source Source of provider, output
+ * \return 1 Success, 0 Failed, -1 Error
+ */
+static int osp_create_transaction(
+	const char* provider,		/* OSP provider context name */
+	int* transaction,			/* OSP transaction handle, output */
+	unsigned int sourcesize,	/* Size of source buffer, in/output */
+	char* source)				/* Source of provider context, output */
+{
+	int res = 0;
+	struct osp_provider* p;
+	int error;
+
+	ast_mutex_lock(&osplock);
+	p = ospproviders;
+	while(p) {
+		if (!strcasecmp(p->name, provider)) {
+			error = OSPPTransactionNew(p->handle, transaction);
+			if (error == OSPC_ERR_NO_ERROR) {
+				ast_log(LOG_DEBUG, "OSP: transaction '%d'\n", *transaction);
+				ast_copy_string(source, p->source, sourcesize);
+				ast_log(LOG_DEBUG, "OSP: source '%s'\n", source);
+				res = 1;
+			} else {
+				*transaction = OSP_INVALID_HANDLE;
+				ast_log(LOG_DEBUG, "OSP: Unable to create transaction handle, error '%d'\n", error);
+				res = -1;
+			}
+			break;
+		}
+		p = p->next;
+	}
+	ast_mutex_unlock(&osplock);
+
+	return res;
+}
+
+/*!
+ * \brief Validate OSP token of inbound call
+ * \param transaction OSP transaction handle
+ * \param source Source of inbound call
+ * \param dest Destination of inbound call
+ * \param calling Calling number
+ * \param called Called number
+ * \param token OSP token, may be empty
+ * \param timelimit Call duration limit, output
+ * \return 1 Success, 0 Failed, -1 Error
+ */
+static int osp_validate_token(
+	int transaction,			/* OSP transaction handle */
+	const char* source,			/* Source of inbound call */
+	const char* dest,			/* Destination of inbound call */
+	const char* calling,		/* Calling number */
+	const char* called,			/* Called number */
+	const char* token,			/* OSP token, may be empty */
+	unsigned int* timelimit)	/* Call duration limit, output */
+{
+	int res;
+	int tokenlen;
+	char tokenstr[OSP_TOKSTR_SIZE];
+	unsigned int authorised;
+	unsigned int dummy = 0;
+	int error;
+
+	tokenlen = ast_base64decode(tokenstr, token, strlen(token));
+	error = OSPPTransactionValidateAuthorisation(
+		transaction, 
+		source, dest, NULL, NULL,
+		calling ? calling : "", OSPC_E164, 
+		called, OSPC_E164, 
+		0, NULL,
+		tokenlen, tokenstr, 
+		&authorised, 
+		timelimit, 
+		&dummy, NULL, 
+		osp_tokenformat); 
+	if (error != OSPC_ERR_NO_ERROR) {
+		ast_log(LOG_DEBUG, "OSP: Unable to validate inbound token\n");
+		res = -1;
+	} else if (authorised) {
+		ast_log(LOG_DEBUG, "OSP: Authorised\n");
+		res = 1;
+	} else {
+		ast_log(LOG_DEBUG, "OSP: Unauthorised\n");
+		res = 0;
+	}
+	
+	return res;
+}
+
+/*!
+ * \brief Choose min duration limit
+ * \param in Inbound duration limit
+ * \param out Outbound duration limit
+ * \return min duration limit
+ */
+static unsigned int osp_choose_timelimit(
+	unsigned int in,			/* Inbound duration timelimit */
+	unsigned int out)			/* Outbound duration timelimit */
+{
+	if (in == OSP_DEF_TIMELIMIT) {
+		return out;
+	} else if (out == OSP_DEF_TIMELIMIT) {
+		return in;
+	} else {
+		return in < out ? in : out;
+	}
+}
+
+/*!
+ * \brief Choose min duration limit
+ * \param called Called number
+ * \param calling Calling number
+ * \param destination Destination IP in '[x.x.x.x]' format
+ * \param tokenlen OSP token length
+ * \param token OSP token
+ * \param reason Failure reason, output
+ * \param result OSP lookup results, in/output
+ * \return 1 Success, 0 Failed, -1 Error
+ */
+static int osp_check_destination(
+	const char* called,				/* Called number */
+	const char* calling,			/* Calling number */
+	char* destination,				/* Destination IP in '[x.x.x.x]' format */
+	unsigned int tokenlen,			/* OSP token length */
+	const char* token,				/* OSP token */
+	enum OSPEFAILREASON* reason,	/* Failure reason, output */
+	struct osp_result* result)		/* OSP lookup results, in/output */
+{
+	int res;
+	OSPE_DEST_OSP_ENABLED enabled;
+	OSPE_DEST_PROT protocol;
+	int error;
+
+	if (strlen(destination) <= 2) {
+		ast_log(LOG_DEBUG, "OSP: Wrong destination format '%s'\n", destination);
+		*reason = OSPC_FAIL_NORMAL_UNSPECIFIED;
+		return -1;
+	} 
+
+	if ((error = OSPPTransactionIsDestOSPEnabled(result->outhandle, &enabled)) != OSPC_ERR_NO_ERROR) {
+		ast_log(LOG_DEBUG, "OSP: Unable to get destination OSP version, error '%d'\n", error);
+		*reason = OSPC_FAIL_NORMAL_UNSPECIFIED;
+		return -1;
+	}
+
+	if (enabled == OSPE_OSP_FALSE) {
+		result->token[0] = '\0';
+	} else {
+		ast_base64encode(result->token, token, tokenlen, sizeof(result->token) - 1);
+	}
+
+	if ((error = OSPPTransactionGetDestProtocol(result->outhandle, &protocol)) != OSPC_ERR_NO_ERROR) {
+		ast_log(LOG_DEBUG, "OSP: Unable to get destination protocol, error '%d'\n", error);
+		*reason = OSPC_FAIL_NORMAL_UNSPECIFIED; 
+		result->token[0] = '\0';
+		return -1;
+	} 
+
+	res = 1;
+	/* Strip leading and trailing brackets */
+	destination[strlen(destination) - 1] = '\0';
+	switch(protocol) {
+		case OSPE_DEST_PROT_H323_SETUP:
+			ast_log(LOG_DEBUG, "OSP: protocol '%d'\n", protocol);
+			ast_copy_string(result->tech, "H323", sizeof(result->tech));
+			snprintf(result->dest, sizeof(result->dest), "%s@%s", called, destination + 1);
+			ast_copy_string(result->calling, calling, sizeof(result->calling));
+			break;
+		case OSPE_DEST_PROT_SIP:
+			ast_log(LOG_DEBUG, "OSP: protocol '%d'\n", protocol);
+			ast_copy_string(result->tech, "SIP", sizeof(result->tech));

[... 5859 lines stripped ...]


More information about the asterisk-commits mailing list