]> git.ipfire.org Git - thirdparty/freeswitch.git/commitdiff
ftmod_libpri: Initial support for BRI and various cleanups + double locking fix
authorStefan Knoblich <s.knoblich@axsentis.de>
Sat, 6 Nov 2010 15:08:07 +0000 (16:08 +0100)
committerStefan Knoblich <s.knoblich@axsentis.de>
Sat, 6 Nov 2010 15:08:07 +0000 (16:08 +0100)
Fixes:
- Fix double locking in check_state(): remove ftdm_mutex_(un)lock calls.

New:
- Add lpwrap_init_bri() to initialize libpri in BRI mode
- Use trunk type to determine PRI/BRI and PTP/PTMP mode (no additional configuration required).
- Improve libpri detection code in configure.ac, check whether libpri is usable
  and if BRI support is available (needs more work)

Cleanups:
- Whitespace and indentation cleanups
- Rename str2* functions to parse_*
- Simplify libpri_configure_span() option parsing and bail out on error
- Add "ftdm libpri help" command that displays usage information
- Coding style cleanups and other (minor) changes

Known issues:
- BRI PTMP TE Q.921 link does not go beyond TEI ASSIGNED state,
  SABME requests are ignored by NT (EuroISDN DTAG, DAHDI-2.3.0.1, vzaphfc)

Signed-off-by: Stefan Knoblich <s.knoblich@axsentis.de>
libs/freetdm/configure.ac
libs/freetdm/src/ftmod/ftmod_libpri/ftmod_libpri.c
libs/freetdm/src/ftmod/ftmod_libpri/lpwrap_pri.c
libs/freetdm/src/ftmod/ftmod_libpri/lpwrap_pri.h

index 9f74d9465d05a5b15a2585a13bf1d4038193d861..c27d1160dc4764dac30f19791ddf27e1d5852b31 100644 (file)
@@ -144,21 +144,6 @@ fi
 ##
 AC_MSG_RESULT([${as_nl}<<>> Modules and optional features])
 
-##
-# libpri (TODO: add checks)
-#
-HAVE_LIBPRI="no"
-AC_ARG_WITH([libpri],
-       [AS_HELP_STRING([--with-libpri], [Install ftmod_libpri])],
-       [case "${withval}" in
-        no)    enable_libpri="no" ;;
-        *)     enable_libpri="yes" ;;
-        esac],
-       [enable_libpri="no"]
-)
-HAVE_LIBPRI="${enable_libpri}"
-AM_CONDITIONAL([HAVE_LIBPRI],[test "${enable_libpri}" = "yes"])
-
 ##
 # pritap (TODO: add checks)
 #
@@ -193,6 +178,50 @@ AC_CHECK_LIB([openr2], [openr2_context_set_io_type], [HAVE_OPENR2="yes"])
 AC_MSG_RESULT([checking whether to build ftmod_r2... ${HAVE_OPENR2}])
 AM_CONDITIONAL([HAVE_OPENR2], [test "${HAVE_OPENR2}" = "yes"])
 
+##
+# Digium libpri (TODO: add checks)
+#
+HAVE_LIBPRI="no"
+AC_ARG_WITH([libpri],
+       [AS_HELP_STRING([--with-libpri], [Install ftmod_libpri])],
+       [case "${withval}" in
+        no)    enable_libpri="no" ;;
+        *)     enable_libpri="yes" ;;
+        esac],
+       [enable_libpri="no"]
+)
+if test "${enable_libpri}" != "no"
+then
+       AC_MSG_RESULT([${as_nl}<<>> Digium libpri])
+
+       save_LIBS="${LIBS}"
+       LIBS="${LIBS} -lpri"
+       AC_MSG_CHECKING([whether libpri is usable])
+       AC_LINK_IFELSE(
+               [AC_LANG_PROGRAM(
+                       [#include <libpri.h>],
+                       [const char *version = pri_get_version();]
+               )],
+               [AC_MSG_RESULT([yes])],
+               [AC_MSG_RESULT([no])
+                AC_MSG_ERROR([libpri is not installed or unusable (see config.log for details)])]
+       )
+
+       AC_MSG_CHECKING([whether libpri has BRI support])
+       AC_LINK_IFELSE(
+               [AC_LANG_PROGRAM(
+                       [extern void pri_new_bri_cb(void);],
+                       [pri_new_bri_cb();]
+               )],
+               [AC_DEFINE([HAVE_LIBPRI_BRI], [1], [libpri has bri support])
+                AC_MSG_RESULT([yes])],
+               [AC_MSG_RESULT([no])]
+       )
+       LIBS="${save_LIBS}"
+fi
+HAVE_LIBPRI="${enable_libpri}"
+AM_CONDITIONAL([HAVE_LIBPRI],[test "${enable_libpri}" = "yes"])
+
 ##
 # Sangoma Wanpipe
 #
index 444b907911afcd4c826b6d30fb81a6f5be341890..6e09562a7e1ad62437b367332243171e39c51d60 100644 (file)
@@ -1,23 +1,23 @@
 /*
  * Copyright (c) 2007, Anthony Minessale II
  * All rights reserved.
- * 
+ *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
  * are met:
- * 
+ *
  * * Redistributions of source code must retain the above copyright
  * notice, this list of conditions and the following disclaimer.
- * 
+ *
  * * Redistributions in binary form must reproduce the above copyright
  * notice, this list of conditions and the following disclaimer in the
  * documentation and/or other materials provided with the distribution.
- * 
+ *
  * * Neither the name of the original author; nor the names of any contributors
  * may be used to endorse or promote products derived from this software
  * without specific prior written permission.
- * 
- * 
+ *
+ *
  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
@@ -140,35 +140,7 @@ static void s_pri_message(char *s)
 static void s_pri_message(struct pri *pri, char *s)
 #endif
 {
-               ftdm_log(FTDM_LOG_DEBUG, "%s", s);
-}
-
-/**
- * \brief Parses an option string to flags
- * \param in String to parse for configuration options
- * \return Flags
- */
-static uint32_t parse_opts(const char *in)
-{
-       uint32_t flags = 0;
-       
-       if (!in) {
-               return 0;
-       }
-       
-       if (strstr(in, "suggest_channel")) {
-               flags |= FTMOD_LIBPRI_OPT_SUGGEST_CHANNEL;
-       }
-       
-       if (strstr(in, "omit_display")) {
-               flags |= FTMOD_LIBPRI_OPT_OMIT_DISPLAY_IE;
-       }
-       
-       if (strstr(in, "omit_redirecting_number")) {
-               flags |= FTMOD_LIBPRI_OPT_OMIT_REDIRECTING_NUMBER_IE;
-       }
-
-       return flags;
+       ftdm_log(FTDM_LOG_DEBUG, "%s", s);
 }
 
 /**
@@ -187,43 +159,33 @@ static int parse_debug(const char *in)
        if (strstr(in, "q921_raw")) {
                flags |= PRI_DEBUG_Q921_RAW;
        }
-
        if (strstr(in, "q921_dump")) {
                flags |= PRI_DEBUG_Q921_DUMP;
        }
-
        if (strstr(in, "q921_state")) {
                flags |= PRI_DEBUG_Q921_STATE;
        }
-
        if (strstr(in, "config")) {
                flags |= PRI_DEBUG_CONFIG;
        }
-
        if (strstr(in, "q931_dump")) {
                flags |= PRI_DEBUG_Q931_DUMP;
        }
-
        if (strstr(in, "q931_state")) {
                flags |= PRI_DEBUG_Q931_STATE;
        }
-
        if (strstr(in, "q931_anomaly")) {
                flags |= PRI_DEBUG_Q931_ANOMALY;
        }
-
        if (strstr(in, "apdu")) {
                flags |= PRI_DEBUG_APDU;
        }
-
        if (strstr(in, "aoc")) {
                flags |= PRI_DEBUG_AOC;
        }
-
        if (strstr(in, "all")) {
                flags |= PRI_DEBUG_ALL;
        }
-
        if (strstr(in, "none")) {
                flags = 0;
        }
@@ -231,9 +193,13 @@ static int parse_debug(const char *in)
        return flags;
 }
 
+static ftdm_status_t ftdm_libpri_start(ftdm_span_t *span);
 static ftdm_io_interface_t ftdm_libpri_interface;
 
-static ftdm_status_t ftdm_libpri_start(ftdm_span_t *span);
+static const char *ftdm_libpri_usage =
+       "Usage:\n"
+       "libpri kill <span>\n"
+       "libpri debug <span> <level>\n";
 
 /**
  * \brief API function to kill or debug a libpri span
@@ -244,13 +210,20 @@ static ftdm_status_t ftdm_libpri_start(ftdm_span_t *span);
 static FIO_API_FUNCTION(ftdm_libpri_api)
 {
        char *mycmd = NULL, *argv[10] = { 0 };
-    int argc = 0;
-       
+       int argc = 0;
+
        if (data) {
                mycmd = ftdm_strdup(data);
                argc = ftdm_separate_string(mycmd, ' ', argv, (sizeof(argv) / sizeof(argv[0])));
        }
 
+       if (argc == 1) {
+               if (!strcasecmp(argv[0], "help") || !strcasecmp(argv[0], "usage")) {
+                       stream->write_function(stream, ftdm_libpri_usage);
+                       goto done;
+               }
+       }
+
        if (argc == 2) {
                if (!strcasecmp(argv[0], "kill")) {
                        int span_id = atoi(argv[1]);
@@ -285,7 +258,7 @@ static FIO_API_FUNCTION(ftdm_libpri_api)
                                        goto done;
                                }
 
-                               pri_set_debug(isdn_data->spri.pri, parse_debug(argv[2]));                               
+                               pri_set_debug(isdn_data->spri.pri, parse_debug(argv[2]));
                                stream->write_function(stream, "%s: +OK debug set.\n", __FILE__);
                                goto done;
                        } else {
@@ -295,16 +268,15 @@ static FIO_API_FUNCTION(ftdm_libpri_api)
                }
 
        }
-
        stream->write_function(stream, "%s: -ERR invalid command.\n", __FILE__);
-       
- done:
 
+done:
        ftdm_safe_free(mycmd);
 
        return FTDM_SUCCESS;
 }
 
+
 /**
  * \brief Loads libpri IO module
  * \param fio FreeTDM IO interface
@@ -313,10 +285,10 @@ static FIO_API_FUNCTION(ftdm_libpri_api)
 static FIO_IO_LOAD_FUNCTION(ftdm_libpri_io_init)
 {
        assert(fio != NULL);
-       memset(&ftdm_libpri_interface, 0, sizeof(ftdm_libpri_interface));
 
+       memset(&ftdm_libpri_interface, 0, sizeof(ftdm_libpri_interface));
        ftdm_libpri_interface.name = "libpri";
-       ftdm_libpri_interface.api ftdm_libpri_api;
+       ftdm_libpri_interface.api  = &ftdm_libpri_api;
 
        *fio = &ftdm_libpri_interface;
 
@@ -445,8 +417,6 @@ static ftdm_state_map_t isdn_state_map = {
                        {FTDM_CHANNEL_STATE_UP, FTDM_END},
                        {FTDM_CHANNEL_STATE_HANGUP, FTDM_CHANNEL_STATE_TERMINATING, FTDM_END},
                },
-               
-
        }
 };
 
@@ -461,11 +431,9 @@ static __inline__ void state_advance(ftdm_channel_t *ftdmchan)
        ftdm_status_t status;
        ftdm_sigmsg_t sig;
        q931_call *call = (q931_call *) ftdmchan->call_data;
-       
-       
-       ftdm_log(FTDM_LOG_DEBUG, "%d:%d STATE [%s]\n", 
-                       ftdmchan->span_id, ftdmchan->chan_id, ftdm_channel_state2str(ftdmchan->state));
 
+       ftdm_log(FTDM_LOG_DEBUG, "%d:%d STATE [%s]\n",
+                       ftdmchan->span_id, ftdmchan->chan_id, ftdm_channel_state2str(ftdmchan->state));
 
 #if 0
        if (!ftdm_test_flag(ftdmchan, FTDM_CHANNEL_OUTBOUND) && !call) {
@@ -473,7 +441,7 @@ static __inline__ void state_advance(ftdm_channel_t *ftdmchan)
        }
 #endif
 
-       
+
        memset(&sig, 0, sizeof(sig));
        sig.chan_id = ftdmchan->chan_id;
        sig.span_id = ftdmchan->span_id;
@@ -484,7 +452,7 @@ static __inline__ void state_advance(ftdm_channel_t *ftdmchan)
        case FTDM_CHANNEL_STATE_DOWN:
                {
                        ftdmchan->call_data = NULL;
-                       ftdm_channel_done(ftdmchan);                    
+                       ftdm_channel_done(ftdmchan);
                }
                break;
        case FTDM_CHANNEL_STATE_PROGRESS:
@@ -562,7 +530,6 @@ static __inline__ void state_advance(ftdm_channel_t *ftdmchan)
                                return;
                        }
 
-                       
                        dp = ftdmchan->caller_data.dnis.type;
                        switch(dp) {
                        case FTDM_TON_NATIONAL:
@@ -584,15 +551,18 @@ static __inline__ void state_advance(ftdm_channel_t *ftdmchan)
                        pri_sr_set_channel(sr, ftdmchan->chan_id, 0, 0);
                        pri_sr_set_bearer(sr, 0, isdn_data->l1);
                        pri_sr_set_called(sr, ftdmchan->caller_data.dnis.digits, dp, 1);
-                       pri_sr_set_caller(sr, ftdmchan->caller_data.cid_num.digits, (isdn_data->opts & FTMOD_LIBPRI_OPT_OMIT_DISPLAY_IE ? NULL : ftdmchan->caller_data.cid_name),
-                                               dp, (ftdmchan->caller_data.pres != 1 ? PRES_ALLOWED_USER_NUMBER_PASSED_SCREEN : PRES_PROHIB_USER_NUMBER_NOT_SCREENED));
+                       pri_sr_set_caller(sr, ftdmchan->caller_data.cid_num.digits,
+                                       (isdn_data->opts & FTMOD_LIBPRI_OPT_OMIT_DISPLAY_IE ? NULL : ftdmchan->caller_data.cid_name),
+                                       dp,
+                                       (ftdmchan->caller_data.pres != 1 ? PRES_ALLOWED_USER_NUMBER_PASSED_SCREEN : PRES_PROHIB_USER_NUMBER_NOT_SCREENED));
 
                        if (!(isdn_data->opts & FTMOD_LIBPRI_OPT_OMIT_REDIRECTING_NUMBER_IE)) {
-                               pri_sr_set_redirecting(sr, ftdmchan->caller_data.cid_num.digits, dp, PRES_ALLOWED_USER_NUMBER_PASSED_SCREEN, PRI_REDIR_UNCONDITIONAL);
+                               pri_sr_set_redirecting(sr, ftdmchan->caller_data.cid_num.digits, dp,
+                                       PRES_ALLOWED_USER_NUMBER_PASSED_SCREEN, PRI_REDIR_UNCONDITIONAL);
                        }
 
                        if (pri_setup(isdn_data->spri.pri, call, sr)) {
-                               ftdmchan->caller_data.hangup_cause = FTDM_CAUSE_DESTINATION_OUT_OF_ORDER;                               
+                               ftdmchan->caller_data.hangup_cause = FTDM_CAUSE_DESTINATION_OUT_OF_ORDER;
                                ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_HANGUP);
                        }
 
@@ -606,7 +576,7 @@ static __inline__ void state_advance(ftdm_channel_t *ftdmchan)
                                pri_hangup(isdn_data->spri.pri, call, ftdmchan->caller_data.hangup_cause);
                                pri_destroycall(isdn_data->spri.pri, call);
                                ftdmchan->call_data = NULL;
-                       } 
+                       }
                        ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_DOWN);
                }
                break;
@@ -633,21 +603,23 @@ static __inline__ void state_advance(ftdm_channel_t *ftdmchan)
  */
 static __inline__ void check_state(ftdm_span_t *span)
 {
-    if (ftdm_test_flag(span, FTDM_SPAN_STATE_CHANGE)) {
-        uint32_t j;
-        ftdm_clear_flag_locked(span, FTDM_SPAN_STATE_CHANGE);
-        for(j = 1; j <= span->chan_count; j++) {
-            if (ftdm_test_flag((span->channels[j]), FTDM_CHANNEL_STATE_CHANGE)) {
-                               ftdm_mutex_lock(span->channels[j]->mutex);
-               ftdm_channel_lock(span->channels[j]);
-                ftdm_clear_flag((span->channels[j]), FTDM_CHANNEL_STATE_CHANGE);
-                state_advance(span->channels[j]);
-                ftdm_channel_complete_state(span->channels[j]);
-                               ftdm_mutex_unlock(span->channels[j]->mutex);
-               ftdm_channel_unlock(span->channels[j]);
-            }
-        }
-    }
+       if (ftdm_test_flag(span, FTDM_SPAN_STATE_CHANGE)) {
+               uint32_t j;
+
+               ftdm_clear_flag_locked(span, FTDM_SPAN_STATE_CHANGE);
+
+               for (j = 1; j <= span->chan_count; j++) {
+                       if (ftdm_test_flag((span->channels[j]), FTDM_CHANNEL_STATE_CHANGE)) {
+                               ftdm_channel_lock(span->channels[j]);
+
+                               ftdm_clear_flag((span->channels[j]), FTDM_CHANNEL_STATE_CHANGE);
+                               state_advance(span->channels[j]);
+                               ftdm_channel_complete_state(span->channels[j]);
+
+                               ftdm_channel_unlock(span->channels[j]);
+                       }
+               }
+       }
 }
 
 /**
@@ -659,7 +631,6 @@ static __inline__ void check_state(ftdm_span_t *span)
  */
 static int on_info(lpwrap_pri_t *spri, lpwrap_pri_event_t event_type, pri_event *pevent)
 {
-
        ftdm_log(FTDM_LOG_DEBUG, "number is: %s\n", pevent->ring.callednum);
        if (strlen(pevent->ring.callednum) > 3) {
                ftdm_log(FTDM_LOG_DEBUG, "final number is: %s\n", pevent->ring.callednum);
@@ -681,7 +652,7 @@ static int on_hangup(lpwrap_pri_t *spri, lpwrap_pri_event_t event_type, pri_even
        ftdm_channel_t *ftdmchan = NULL;
        q931_call *call = NULL;
        ftdmchan = span->channels[pevent->hangup.channel];
-       
+
        if (!ftdmchan) {
                ftdm_log(FTDM_LOG_CRIT, "-- Hangup on channel %d:%d %s but it's not in use?\n", spri->span->span_id, pevent->hangup.channel);
                return 0;
@@ -698,7 +669,7 @@ static int on_hangup(lpwrap_pri_t *spri, lpwrap_pri_event_t event_type, pri_even
                ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "Ignoring remote hangup in state %s with no call data\n", ftdm_channel_state2str(ftdmchan->state));
                goto done;
        }
-       
+
        call = (q931_call *) ftdmchan->call_data;
        ftdm_log(FTDM_LOG_DEBUG, "-- Hangup on channel %d:%d\n", spri->span->span_id, pevent->hangup.channel);
        ftdmchan->caller_data.hangup_cause = pevent->hangup.cause;
@@ -727,13 +698,12 @@ static int on_answer(lpwrap_pri_t *spri, lpwrap_pri_event_t event_type, pri_even
        ftdm_channel_t *ftdmchan = NULL;
 
        ftdmchan = span->channels[pevent->answer.channel];
-       
+
        if (ftdmchan) {
                ftdm_log(FTDM_LOG_DEBUG, "-- Answer on channel %d:%d\n", spri->span->span_id, pevent->answer.channel);
                ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_UP);
        } else {
                ftdm_log(FTDM_LOG_DEBUG, "-- Answer on channel %d:%d %s but it's not in use?\n", spri->span->span_id, pevent->answer.channel, ftdmchan->chan_id);
-                               
        }
 
        return 0;
@@ -750,9 +720,9 @@ static int on_proceed(lpwrap_pri_t *spri, lpwrap_pri_event_t event_type, pri_eve
 {
        ftdm_span_t *span = spri->private_info;
        ftdm_channel_t *ftdmchan = NULL;
-       
+
        ftdmchan = span->channels[pevent->proceeding.channel];
-       
+
        if (ftdmchan) {
                ftdm_log(FTDM_LOG_DEBUG, "-- Proceeding on channel %d:%d\n", spri->span->span_id, pevent->proceeding.channel);
                ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_PROGRESS_MEDIA);
@@ -777,7 +747,7 @@ static int on_ringing(lpwrap_pri_t *spri, lpwrap_pri_event_t event_type, pri_eve
        ftdm_channel_t *ftdmchan = NULL;
 
        ftdmchan = span->channels[pevent->ringing.channel];
-       
+
        if (ftdmchan) {
                ftdm_log(FTDM_LOG_DEBUG, "-- Ringing on channel %d:%d\n", spri->span->span_id, pevent->ringing.channel);
                /* we may get on_ringing even when we're already in FTDM_CHANNEL_STATE_PROGRESS_MEDIA */
@@ -808,7 +778,7 @@ static int on_ring(lpwrap_pri_t *spri, lpwrap_pri_event_t event_type, pri_event
        int ret = 0;
 
        //switch_mutex_lock(globals.channel_mutex);
-       
+
        ftdmchan = span->channels[pevent->ring.channel];
        if (!ftdmchan || ftdmchan->state != FTDM_CHANNEL_STATE_DOWN || ftdm_test_flag(ftdmchan, FTDM_CHANNEL_INUSE)) {
                ftdm_log(FTDM_LOG_WARNING, "--Duplicate Ring on channel %d:%d (ignored)\n", spri->span->span_id, pevent->ring.channel);
@@ -821,13 +791,12 @@ static int on_ring(lpwrap_pri_t *spri, lpwrap_pri_event_t event_type, pri_event
                ret = 0;
                goto done;
        }
-       
 
        ftdm_log(FTDM_LOG_NOTICE, "-- Ring on channel %d:%d (from %s to %s)\n", spri->span->span_id, pevent->ring.channel,
                                          pevent->ring.callingnum, pevent->ring.callednum);
-       
+
        memset(&ftdmchan->caller_data, 0, sizeof(ftdmchan->caller_data));
-       
+
        ftdm_set_string(ftdmchan->caller_data.cid_num.digits, (char *)pevent->ring.callingnum);
        if (!ftdm_strlen_zero((char *)pevent->ring.callingname)) {
                ftdm_set_string(ftdmchan->caller_data.cid_name, (char *)pevent->ring.callingname);
@@ -836,19 +805,18 @@ static int on_ring(lpwrap_pri_t *spri, lpwrap_pri_event_t event_type, pri_event
        }
        ftdm_set_string(ftdmchan->caller_data.ani.digits, (char *)pevent->ring.callingani);
        ftdm_set_string(ftdmchan->caller_data.dnis.digits, (char *)pevent->ring.callednum);
-       
+
        if (pevent->ring.ani2 >= 0) {
                snprintf(ftdmchan->caller_data.aniII, 5, "%.2d", pevent->ring.ani2);
        }
-       
+
        // scary to trust this pointer, you'd think they would give you a copy of the call data so you own it......
        ftdmchan->call_data = pevent->ring.call;
-       
+
        ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_RING);
-       
- done:
-       //switch_mutex_unlock(globals.channel_mutex);
 
+done:
+       //switch_mutex_unlock(globals.channel_mutex);
        return ret;
 }
 
@@ -861,8 +829,13 @@ static int on_ring(lpwrap_pri_t *spri, lpwrap_pri_event_t event_type, pri_event
 static __inline__ ftdm_status_t process_event(ftdm_span_t *span, ftdm_event_t *event)
 {
        ftdm_alarm_flag_t alarmbits;
-       ftdm_log(FTDM_LOG_DEBUG, "EVENT [%s][%d][%d:%d] STATE [%s]\n", 
-                       ftdm_oob_event2str(event->enum_id), event->enum_id, event->channel->span_id, event->channel->chan_id, ftdm_channel_state2str(event->channel->state));
+
+       ftdm_log(FTDM_LOG_DEBUG, "EVENT [%s][%d][%d:%d] STATE [%s]\n",
+                       ftdm_oob_event2str(event->enum_id),
+                       event->enum_id,
+                       event->channel->span_id,
+                       event->channel->chan_id,
+                       ftdm_channel_state2str(event->channel->state));
 
        switch(event->enum_id) {
        case FTDM_OOB_ALARM_TRAP:
@@ -872,11 +845,9 @@ static __inline__ ftdm_status_t process_event(ftdm_span_t *span, ftdm_event_t *e
                                        ftdm_set_state_locked(event->channel, FTDM_CHANNEL_STATE_RESTART);
                                }
                        }
-                       
 
                        ftdm_set_flag(event->channel, FTDM_CHANNEL_SUSPENDED);
 
-                       
                        ftdm_channel_get_alarms(event->channel, &alarmbits);
                        ftdm_log(FTDM_LOG_WARNING, "channel %d:%d (%d:%d) has alarms! [%s]\n", 
                                        event->channel->span_id, event->channel->chan_id, 
@@ -886,7 +857,6 @@ static __inline__ ftdm_status_t process_event(ftdm_span_t *span, ftdm_event_t *e
                break;
        case FTDM_OOB_ALARM_CLEAR:
                {
-                       
                        ftdm_log(FTDM_LOG_WARNING, "channel %d:%d (%d:%d) alarms Cleared!\n", event->channel->span_id, event->channel->chan_id,
                                        event->channel->physical_span_id, event->channel->physical_chan_id);
 
@@ -905,14 +875,11 @@ static __inline__ ftdm_status_t process_event(ftdm_span_t *span, ftdm_event_t *e
  */
 static __inline__ void check_events(ftdm_span_t *span)
 {
-       ftdm_status_t status;
-
-       status = ftdm_span_poll_event(span, 5);
-
-       switch(status) {
+       switch (ftdm_span_poll_event(span, 5)) {
        case FTDM_SUCCESS:
                {
                        ftdm_event_t *event;
+
                        while (ftdm_span_next_event(span, &event) == FTDM_SUCCESS) {
                                if (event->enum_id == FTDM_OOB_NOOP) {
                                        continue;
@@ -923,12 +890,12 @@ static __inline__ void check_events(ftdm_span_t *span)
                        }
                }
                break;
+
        case FTDM_FAIL:
-               {
-                       ftdm_log(FTDM_LOG_DEBUG, "Event Failure! %d\n", ftdm_running());
-                       ftdm_sleep(2000);
-               }
+               ftdm_log(FTDM_LOG_DEBUG, "Event Failure! %d\n", ftdm_running());
+               ftdm_sleep(2000);
                break;
+
        default:
                break;
        }
@@ -949,8 +916,6 @@ static int check_flags(lpwrap_pri_t *spri)
 
        check_state(span);
        check_events(span);
-
-
        return 0;
 }
 
@@ -967,7 +932,7 @@ static int on_restart(lpwrap_pri_t *spri, lpwrap_pri_event_t event_type, pri_eve
        ftdm_channel_t *ftdmchan;
 
        ftdm_log(FTDM_LOG_NOTICE, "-- Restarting %d:%d\n", spri->span->span_id, pevent->restart.channel);
-       
+
        spri->dchan->state = FTDM_CHANNEL_STATE_UP;
        ftdmchan = span->channels[pevent->restart.channel];
 
@@ -998,19 +963,23 @@ static int on_dchan_up(lpwrap_pri_t *spri, lpwrap_pri_event_t event_type, pri_ev
                ftdm_channel_t *ftdmchan = NULL;
                ftdm_sigmsg_t sig;
                int i;
+
                ftdm_log(FTDM_LOG_INFO, "Span %d D-Chan UP!\n", spri->span->span_id);
                ftdm_set_flag(spri, LPWRAP_PRI_READY);
                ftdm_set_state_all(spri->span, FTDM_CHANNEL_STATE_RESTART);
 
                ftdm_log(FTDM_LOG_NOTICE, "%d:Signaling link status changed to %s\n", spri->span->span_id, ftdm_signaling_status2str(status));
-               for(i=1; i <= spri->span->chan_count; i++) {
+
+               for (i = 1; i <= spri->span->chan_count; i++) {
                        ftdmchan = spri->span->channels[i];
+
                        memset(&sig, 0, sizeof(sig));
                        sig.chan_id = ftdmchan->chan_id;
                        sig.span_id = ftdmchan->span_id;
                        sig.channel = ftdmchan;
                        sig.event_id = FTDM_SIGEVENT_SIGSTATUS_CHANGED;
                        sig.raw_data = &status;
+
                        ftdm_span_send_signal(spri->span, &sig);
                }
        }
@@ -1025,26 +994,29 @@ static int on_dchan_up(lpwrap_pri_t *spri, lpwrap_pri_event_t event_type, pri_ev
  * \return 0
  */
 static int on_dchan_down(lpwrap_pri_t *spri, lpwrap_pri_event_t event_type, pri_event *pevent)
-{      
+{
        if (ftdm_test_flag(spri, LPWRAP_PRI_READY)) {
                ftdm_signaling_status_t status = FTDM_SIG_STATE_DOWN;
                ftdm_channel_t *ftdmchan = NULL;
                ftdm_sigmsg_t sig;
                int i;
+
                ftdm_log(FTDM_LOG_INFO, "Span %d D-Chan DOWN!\n", spri->span->span_id);
                ftdm_clear_flag(spri, LPWRAP_PRI_READY);
                ftdm_set_state_all(spri->span, FTDM_CHANNEL_STATE_RESTART);
 
-
                ftdm_log(FTDM_LOG_NOTICE, "%d:Signaling link status changed to %s\n", spri->span->span_id, ftdm_signaling_status2str(status));
-               for(i=1; i <= spri->span->chan_count; i++) {
+
+               for (i = 1; i <= spri->span->chan_count; i++) {
                        ftdmchan = spri->span->channels[i];
+
                        memset(&sig, 0, sizeof(sig));
                        sig.chan_id = ftdmchan->chan_id;
                        sig.span_id = ftdmchan->span_id;
                        sig.channel = ftdmchan;
                        sig.event_id = FTDM_SIGEVENT_SIGSTATUS_CHANGED;
                        sig.raw_data = &status;
+
                        ftdm_span_send_signal(spri->span, &sig);
                }
        }
@@ -1061,7 +1033,6 @@ static int on_dchan_down(lpwrap_pri_t *spri, lpwrap_pri_event_t event_type, pri_
  */
 static int on_anything(lpwrap_pri_t *spri, lpwrap_pri_event_t event_type, pri_event *pevent)
 {
-
        ftdm_log(FTDM_LOG_DEBUG, "Caught Event span %d %u (%s)\n", spri->span->span_id, event_type, lpwrap_pri_event_str(event_type));
        return 0;
 }
@@ -1075,7 +1046,6 @@ static int on_anything(lpwrap_pri_t *spri, lpwrap_pri_event_t event_type, pri_ev
  */
 static int on_io_fail(lpwrap_pri_t *spri, lpwrap_pri_event_t event_type, pri_event *pevent)
 {
-
        ftdm_log(FTDM_LOG_DEBUG, "Caught Event span %d %u (%s)\n", spri->span->span_id, event_type, lpwrap_pri_event_str(event_type));
        return 0;
 }
@@ -1084,20 +1054,24 @@ static int on_io_fail(lpwrap_pri_t *spri, lpwrap_pri_event_t event_type, pri_eve
  * \brief Main thread function for libpri span (monitor)
  * \param me Current thread
  * \param obj Span to run in this thread
+ *
+ * \todo  Move all init stuff outside of loop or into ftdm_libpri_configure_span()
  */
 static void *ftdm_libpri_run(ftdm_thread_t *me, void *obj)
 {
        ftdm_span_t *span = (ftdm_span_t *) obj;
        ftdm_libpri_data_t *isdn_data = span->signal_data;
-       int i, x = 0;
        int down = 0;
        int got_d = 0;
-       
+       int res = 0;
+
        ftdm_set_flag(span, FTDM_SPAN_IN_THREAD);
-       
-       while(ftdm_running() && !ftdm_test_flag(span, FTDM_SPAN_STOP_THREAD)) {
+
+       while (ftdm_running() && !ftdm_test_flag(span, FTDM_SPAN_STOP_THREAD)) {
                if (!got_d) {
-                       for(i = 1; i <= span->chan_count; i++) {
+                       int i, x;
+
+                       for (i = 1, x = 0; i <= span->chan_count; i++) {
                                if (span->channels[i]->type == FTDM_CHAN_TYPE_DQ921) {
                                        if (ftdm_channel_open(span->span_id, i, &isdn_data->dchan) == FTDM_SUCCESS) {
                                                ftdm_log(FTDM_LOG_DEBUG, "opening d-channel #%d %d:%d\n", x, isdn_data->dchan->span_id, isdn_data->dchan->chan_id);
@@ -1110,22 +1084,33 @@ static void *ftdm_libpri_run(ftdm_thread_t *me, void *obj)
                                }
                        }
                }
-
                if (!got_d) {
                        ftdm_log(FTDM_LOG_ERROR, "Failed to get a D-channel in span %d\n", span->span_id);
                        break;
                }
-               
-               
-               if (lpwrap_init_pri(&isdn_data->spri,
-                                                                 span,  // span
-                                                                 isdn_data->dchan, // dchan
-                                                                 isdn_data->pswitch,
-                                                                 isdn_data->node,
-                                                                 isdn_data->debug) < 0) {
-                       snprintf(span->last_error, sizeof(span->last_error), "PRI init FAIL!");
-               } else {
 
+               /* Initialize libpri trunk */
+               switch (span->trunk_type) {
+               case FTDM_TRUNK_E1:
+               case FTDM_TRUNK_T1:
+               case FTDM_TRUNK_J1:
+                       res = lpwrap_init_pri(&isdn_data->spri, span, isdn_data->dchan,
+                                       isdn_data->pswitch, isdn_data->node, isdn_data->debug);
+                       break;
+               case FTDM_TRUNK_BRI:
+                       res = lpwrap_init_bri(&isdn_data->spri, span, isdn_data->dchan,
+                                       isdn_data->pswitch, isdn_data->node, 0, isdn_data->debug);
+                       break;
+               case FTDM_TRUNK_BRI_PTMP:
+                       res = lpwrap_init_bri(&isdn_data->spri, span, isdn_data->dchan,
+                                       isdn_data->pswitch, isdn_data->node, 1, isdn_data->debug);
+                       break;
+               default:
+                       snprintf(span->last_error, sizeof(span->last_error), "Invalid trunk type");
+                       goto out;
+               }
+
+               if (res == 0) {
                        LPWRAP_MAP_PRI_EVENT(isdn_data->spri, LPWRAP_PRI_EVENT_ANY, on_anything);
                        LPWRAP_MAP_PRI_EVENT(isdn_data->spri, LPWRAP_PRI_EVENT_RING, on_ring);
                        LPWRAP_MAP_PRI_EVENT(isdn_data->spri, LPWRAP_PRI_EVENT_RINGING, on_ringing);
@@ -1148,8 +1133,10 @@ static void *ftdm_libpri_run(ftdm_thread_t *me, void *obj)
 
                        isdn_data->spri.on_loop = check_flags;
                        isdn_data->spri.private_info = span;
-                       lpwrap_run_pri(&isdn_data->spri);
 
+                       lpwrap_run_pri(&isdn_data->spri);
+               } else {
+                       snprintf(span->last_error, sizeof(span->last_error), "PRI init FAIL!");
                }
 
                if (!ftdm_running() || ftdm_test_flag(span, FTDM_SPAN_STOP_THREAD)) {
@@ -1172,7 +1159,7 @@ static void *ftdm_libpri_run(ftdm_thread_t *me, void *obj)
                down++;
                ftdm_sleep(5000);
        }
-
+out:
        ftdm_log(FTDM_LOG_DEBUG, "PRI thread ended on span %d\n", span->span_id);
 
        ftdm_clear_flag(span, FTDM_SPAN_IN_THREAD);
@@ -1197,11 +1184,15 @@ static ftdm_status_t ftdm_libpri_stop(ftdm_span_t *span)
        }
 
        ftdm_set_state_all(span, FTDM_CHANNEL_STATE_RESTART);
+
        check_state(span);
+
        ftdm_set_flag(span, FTDM_SPAN_STOP_THREAD);
-       while(ftdm_test_flag(span, FTDM_SPAN_IN_THREAD)) {
+
+       while (ftdm_test_flag(span, FTDM_SPAN_IN_THREAD)) {
                ftdm_sleep(100);
        }
+
        check_state(span);
 
        return FTDM_SUCCESS;
@@ -1241,7 +1232,7 @@ static ftdm_status_t ftdm_libpri_start(ftdm_span_t *span)
  * \param node Node string to convert
  * \return -1 on failure, node value on success
  */
-static int str2node(char *node)
+static int parse_node(const char *node)
 {
        if (!strcasecmp(node, "cpe") || !strcasecmp(node, "user"))
                return PRI_CPE;
@@ -1255,7 +1246,7 @@ static int str2node(char *node)
  * \param swtype Swtype string to convert
  * \return Switch value
  */
-static int str2switch(char *swtype)
+static int parse_switch(const char *swtype)
 {
        if (!strcasecmp(swtype, "ni1"))
                return PRI_SWITCH_NI1;
@@ -1273,6 +1264,7 @@ static int str2switch(char *swtype)
                return PRI_SWITCH_GR303_EOC;
        if (!strcasecmp(swtype, "gr303tmc"))
                return PRI_SWITCH_GR303_TMC;
+
        return PRI_SWITCH_DMS100;
 }
 
@@ -1281,11 +1273,11 @@ static int str2switch(char *swtype)
  * \param l1 L1 string to convert
  * \return L1 value
  */
-static int str2l1(char *l1)
+static int parse_l1(const char *l1)
 {
        if (!strcasecmp(l1, "alaw"))
                return PRI_LAYER_1_ALAW;
-       
+
        return PRI_LAYER_1_ULAW;
 }
 
@@ -1294,7 +1286,7 @@ static int str2l1(char *l1)
  * \param dp DP string to convert
  * \return DP value
  */
-static int str2dp(char *dp)
+static int parse_numplan(const char *dp)
 {
        if (!strcasecmp(dp, "international"))
                return PRI_INTERNATIONAL_ISDN;
@@ -1310,6 +1302,32 @@ static int str2dp(char *dp)
        return PRI_UNKNOWN;
 }
 
+/**
+ * \brief Parses an option string to flags
+ * \param in String to parse for configuration options
+ * \return Flags
+ */
+static uint32_t parse_opts(const char *in)
+{
+       uint32_t flags = 0;
+
+       if (!in) {
+               return 0;
+       }
+
+       if (strstr(in, "suggest_channel")) {
+               flags |= FTMOD_LIBPRI_OPT_SUGGEST_CHANNEL;
+       }
+       if (strstr(in, "omit_display")) {
+               flags |= FTMOD_LIBPRI_OPT_OMIT_DISPLAY_IE;
+       }
+       if (strstr(in, "omit_redirecting_number")) {
+               flags |= FTMOD_LIBPRI_OPT_OMIT_REDIRECTING_NUMBER_IE;
+       }
+
+       return flags;
+}
+
 /**
  * \brief Initialises a libpri span from configuration variables
  * \param span Span to configure
@@ -1323,13 +1341,12 @@ static FIO_SIG_CONFIGURE_FUNCTION(ftdm_libpri_configure_span)
        //ftdm_channel_t *dchans[2] = {0};
        ftdm_libpri_data_t *isdn_data;
        char *var, *val;
-       char *debug = NULL;
 
        if (span->trunk_type >= FTDM_TRUNK_NONE) {
                ftdm_log(FTDM_LOG_WARNING, "Invalid trunk type '%s' defaulting to T1.\n", ftdm_trunk_type2str(span->trunk_type));
                span->trunk_type = FTDM_TRUNK_T1;
        }
-       
+
        for(i = 1; i <= span->chan_count; i++) {
                if (span->channels[i]->type == FTDM_CHAN_TYPE_DQ921) {
                        if (x > 1) {
@@ -1346,7 +1363,7 @@ static FIO_SIG_CONFIGURE_FUNCTION(ftdm_libpri_configure_span)
                        }
                }
        }
-       
+
 #if 0
        if (!x) {
                snprintf(span->last_error, sizeof(span->last_error), "Span has no D-Channels!");
@@ -1358,88 +1375,77 @@ static FIO_SIG_CONFIGURE_FUNCTION(ftdm_libpri_configure_span)
        assert(isdn_data != NULL);
        memset(isdn_data, 0, sizeof(*isdn_data));
 
-    if (span->trunk_type == FTDM_TRUNK_E1) {
-        ftdm_log(FTDM_LOG_NOTICE, "Setting default Layer 1 to ALAW since this is an E1 trunk\n");
-        isdn_data->l1 = PRI_LAYER_1_ALAW;
-    } else if (span->trunk_type == FTDM_TRUNK_T1) {
-        ftdm_log(FTDM_LOG_NOTICE, "Setting default Layer 1 to ULAW since this is a T1 trunk\n");
-        isdn_data->l1 = PRI_LAYER_1_ULAW;
-    }
-       
-       while((var = va_arg(ap, char *))) {
+       if (span->trunk_type == FTDM_TRUNK_E1) {
+               ftdm_log(FTDM_LOG_NOTICE, "Setting default Layer 1 to ALAW since this is an E1 trunk\n");
+               isdn_data->l1 = PRI_LAYER_1_ALAW;
+       } else if (span->trunk_type == FTDM_TRUNK_T1) {
+               ftdm_log(FTDM_LOG_NOTICE, "Setting default Layer 1 to ULAW since this is a T1 trunk\n");
+               isdn_data->l1 = PRI_LAYER_1_ULAW;
+       }
+
+       while ((var = va_arg(ap, char *))) {
+               val = va_arg(ap, char *);
+
+               if (!val) {
+                       ftdm_log(FTDM_LOG_ERROR, "Parameter '%s' has no value\n", var);
+                       return FTDM_FAIL;
+               }
+
                if (!strcasecmp(var, "node")) {
-                       int node;
-                       if (!(val = va_arg(ap, char *))) {
-                               break;
-                       }
-                       node = str2node(val);
-                       if (-1 == node) {
-                               ftdm_log(FTDM_LOG_ERROR, "Unknown node type %s, defaulting to CPE mode\n", val);
-                               node = PRI_CPE;
-                       }
-                       isdn_data->node = node;
-               } else if (!strcasecmp(var, "switch")) {
-                       if (!(val = va_arg(ap, char *))) {
-                               break;
-                       }
-                       isdn_data->pswitch = str2switch(val);
-               } else if (!strcasecmp(var, "opts")) {
-                       if (!(val = va_arg(ap, char *))) {
-                               break;
+                       if ((isdn_data->node = parse_node(val)) == -1) {
+                               ftdm_log(FTDM_LOG_ERROR, "Unknown node type '%s', defaulting to CPE mode\n", val);
+                               isdn_data->node = PRI_CPE;
                        }
+               }
+               else if (!strcasecmp(var, "switch")) {
+                       isdn_data->pswitch = parse_switch(val);
+               }
+               else if (!strcasecmp(var, "opts")) {
                        isdn_data->opts = parse_opts(val);
-               } else if (!strcasecmp(var, "dp")) {
-                       if (!(val = va_arg(ap, char *))) {
-                               break;
-                       }
-                       isdn_data->dp = str2dp(val);
-               } else if (!strcasecmp(var, "l1")) {
-                       if (!(val = va_arg(ap, char *))) {
-                               break;
-                       }
-                       isdn_data->l1 = str2l1(val);
-               } else if (!strcasecmp(var, "debug")) {
-                       if (!(val = va_arg(ap, char *))) {
-                               break;
-                       }
-                       debug = val;
-               } else {
+               }
+               else if (!strcasecmp(var, "dp")) {
+                       isdn_data->dp = parse_numplan(val);
+               }
+               else if (!strcasecmp(var, "l1")) {
+                       isdn_data->l1 = parse_l1(val);
+               }
+               else if (!strcasecmp(var, "debug")) {
+                       isdn_data->debug = parse_debug(val);
+               }
+               else {
                        snprintf(span->last_error, sizeof(span->last_error), "Unknown parameter [%s]", var);
                        return FTDM_FAIL;
                }
        }
-    
+
        span->start = ftdm_libpri_start;
-       span->stop = ftdm_libpri_stop;
+       span->stop  = ftdm_libpri_stop;
        span->signal_cb = sig_cb;
        //isdn_data->dchans[0] = dchans[0];
        //isdn_data->dchans[1] = dchans[1];
        //isdn_data->dchan = isdn_data->dchans[0];
-       
-       isdn_data->debug = parse_debug(debug);
-               
 
        span->signal_data = isdn_data;
        span->signal_type = FTDM_SIGTYPE_ISDN;
        span->outgoing_call = isdn_outgoing_call;
 
+       span->state_map = &isdn_state_map;
+
        span->get_channel_sig_status = isdn_get_channel_sig_status;
        span->get_span_sig_status = isdn_get_span_sig_status;
-       
+
        if ((isdn_data->opts & FTMOD_LIBPRI_OPT_SUGGEST_CHANNEL)) {
                span->channel_request = isdn_channel_request;
                ftdm_set_flag(span, FTDM_SPAN_SUGGEST_CHAN_ID);
        }
 
-       span->state_map = &isdn_state_map;
-
        return FTDM_SUCCESS;
 }
 
 /**
  * \brief FreeTDM libpri signaling and IO module definition
  */
-ftdm_module_t ftdm_module = { 
+ftdm_module_t ftdm_module = {
        "libpri",
        ftdm_libpri_io_init,
        ftdm_libpri_unload,
@@ -1448,7 +1454,6 @@ ftdm_module_t ftdm_module = {
        NULL
 };
 
-
 /* For Emacs:
  * Local Variables:
  * mode:c
index 8dfba34ec30ef3c3a22a810a0c57f186519474d1..2cfdd822286160cd7b463db6346fecd83dc0f485 100644 (file)
@@ -1,23 +1,23 @@
 /*
  * Copyright (c) 2009, Anthony Minessale II
  * All rights reserved.
- * 
+ *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
  * are met:
- * 
+ *
  * * Redistributions of source code must retain the above copyright
  * notice, this list of conditions and the following disclaimer.
- * 
+ *
  * * Redistributions in binary form must reproduce the above copyright
  * notice, this list of conditions and the following disclaimer in the
  * documentation and/or other materials provided with the distribution.
- * 
+ *
  * * Neither the name of the original author; nor the names of any contributors
  * may be used to endorse or promote products derived from this software
  * without specific prior written permission.
- * 
- * 
+ *
+ *
  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
@@ -106,7 +106,7 @@ static struct lpwrap_pri_event_list LPWRAP_PRI_EVENT_LIST[] = {
 #define LINE "--------------------------------------------------------------------------------"
 
 const char *lpwrap_pri_event_str(lpwrap_pri_event_t event_id)
-{ 
+{
        return LPWRAP_PRI_EVENT_LIST[event_id].name;
 }
 
@@ -124,7 +124,7 @@ static int __pri_lpwrap_read(struct pri *pri, void *buf, int buflen)
                } else {
                        ftdm_log(FTDM_LOG_CRIT, "span %d D-READ TIMEOUT\n", spri->span->span_id);
                }
-               
+
                ftdm_clear_flag(spri, LPWRAP_PRI_READY);
                return -1;
        }
@@ -173,21 +173,56 @@ int lpwrap_init_pri(struct lpwrap_pri *spri, ftdm_span_t *span, ftdm_channel_t *
        int ret = -1;
 
        memset(spri, 0, sizeof(struct lpwrap_pri));
-       
        spri->dchan = dchan;
-       spri->span = span;
+       spri->span  = span;
+
+       if (!spri->dchan) {
+               ftdm_log(FTDM_LOG_ERROR, "No D-Channel available, unable to create PRI\n");
+               return ret;
+       }
 
-       if (spri->dchan && (spri->pri = pri_new_cb(spri->dchan->sockfd, node, swtype, __pri_lpwrap_read, __pri_lpwrap_write, spri))){
+       if ((spri->pri = pri_new_cb(spri->dchan->sockfd, node, swtype, __pri_lpwrap_read, __pri_lpwrap_write, spri))) {
                unsigned char buf[4] = { 0 };
                size_t buflen = sizeof(buf), len = 0;
+
                pri_set_debug(spri->pri, debug);
-               ret = 0;
-               
                ftdm_channel_write(spri->dchan, buf, buflen, &len);
+
+               ret = 0;
        } else {
-               fprintf(stderr, "Unable to create PRI\n");
+               ftdm_log(FTDM_LOG_ERROR, "Unable to create PRI\n");
+       }
+       return ret;
+}
+
+int lpwrap_init_bri(struct lpwrap_pri *spri, ftdm_span_t *span, ftdm_channel_t *dchan, int swtype, int node, int ptmp, int debug)
+{
+       int ret = -1;
+#ifdef HAVE_LIBPRI_BRI
+       memset(spri, 0, sizeof(struct lpwrap_pri));
+       spri->dchan = dchan;
+       spri->span  = span;
+
+       if (!spri->dchan) {
+               ftdm_log(FTDM_LOG_ERROR, "No D-Channel available, unable to create BRI\n");
+               return ret;
        }
 
+       if ((spri->pri = pri_new_bri_cb(spri->dchan->sockfd, ptmp, node, swtype, __pri_lpwrap_read, __pri_lpwrap_write, spri))) {
+               unsigned char buf[4] = { 0 };
+               size_t buflen = sizeof(buf), len = 0;
+
+               pri_set_debug(spri->pri, debug);
+               ftdm_channel_write(spri->dchan, buf, buflen, &len);
+
+               ret = 0;
+       } else {
+               ftdm_log(FTDM_LOG_ERROR, "Unable to create BRI\n");
+       }
+#else
+       ftdm_log(FTDM_LOG_ERROR, "Installed libpri version (%s) has no BRI support\n",
+                       pri_get_version());
+#endif
        return ret;
 }
 
@@ -198,8 +233,8 @@ int lpwrap_one_loop(struct lpwrap_pri *spri)
        struct timeval now = {0,0}, *next;
        pri_event *event;
        event_handler handler;
-    int sel;
-       
+       int sel;
+
        if (spri->on_loop) {
                if ((sel = spri->on_loop(spri)) < 0) {
                        return sel;
@@ -269,7 +304,7 @@ int lpwrap_one_loop(struct lpwrap_pri *spri)
 int lpwrap_run_pri(struct lpwrap_pri *spri)
 {
        int ret = 0;
-       
+
        for (;;){
                ret = lpwrap_one_loop(spri);
 
@@ -280,7 +315,7 @@ int lpwrap_run_pri(struct lpwrap_pri *spri)
                                /* Igonore an interrupted system call */
                                continue;
                        }
-#endif 
+#endif
                        ftdm_log(FTDM_LOG_CRIT, "Error = %i [%s]\n", ret, strerror(errno));
                        break;
                }
@@ -300,4 +335,3 @@ int lpwrap_run_pri(struct lpwrap_pri *spri)
  * For VIM:
  * vim:set softtabstop=4 shiftwidth=4 tabstop=4:
  */
-
index f92c5bbafac618ea4361d2598ce6bdbe57e49fec..d3d1c437688a8f7b04112a07bd0a02388b60eeea 100644 (file)
@@ -121,6 +121,8 @@ struct lpwrap_pri_event_list {
 const char *lpwrap_pri_event_str(lpwrap_pri_event_t event_id);
 int lpwrap_one_loop(struct lpwrap_pri *spri);
 int lpwrap_init_pri(struct lpwrap_pri *spri, ftdm_span_t *span, ftdm_channel_t *dchan, int swtype, int node, int debug);
+int lpwrap_init_bri(struct lpwrap_pri *spri, ftdm_span_t *span, ftdm_channel_t *dchan, int swtype, int node, int ptmp, int debug);
 int lpwrap_run_pri(struct lpwrap_pri *spri);
+#define lpwrap_run_bri(x)      lpwrap_run_pri(x)
 
 #endif