== General Design ==

NBE will do its current loading of spans and configuration process through Sangoma Board Manager (SBM).
After doing SangomaBoardManager::getInstance().configure -> start. It will proceed to initalize
the openzap stack (just as the TelesoftStack is loaded after starting SMB. The procedure will be:

- create a static or malloced zap_io_interface_t
- call zap_global_set_logger with the logging hooks.
- call zap_global_set_memhandler() with the memory hooks.
- call zap_global_init() to initialize the stack
- call zap_add_io_iface() to add the I/O iface.
- iterate over all SBM spans configured for BRI or any boost-managed signaling and:
    * call zap_span_create(NBE I/O mod, in_ptrSpan, SMB span name)
    * Fill in some members like: 
      span->trunk_type = E1/T1/J1/FXO/FXS etc ...
    * iterate over all channels in SMB span and:
      * zap_span_add_channel(zap_span, sock, type:CAS|BCHAN|DCHAN|ETC)
    * call zap_configure_span("sangoma_boost", span, sigmsg_callback, "param1", value1, "param2", value1 ...)
    * zap_span_start(span);


At this point, NBE would receive signaling msgs via sigmsg_callback registered when configuring
and NBE would request hangup or making calls throug openzap API, like zap_set_state_* and zap_channel_outgoing_call() to place calls.

When NBE wants to check for link status. 

      zap_get_siglink_state() which would return 
      ZAP_SIG_STATE_UP (D-chan UP, R2 bits in IDLE, ss7?)
      ZAP_SIG_STATE_SUSPENDED (D-chan in power saving mode?)
      ZAP_SIG_STATE_DOWN (D-chan down, R2 bits in blocked, ss7?)

      Whenever a state in sig link changes, the sigmsg_callback will be used to notify NBE or any other user.

NOTE: right now hardware alarms notification in openzap is seriously broken,
see ozmod_libpri.c process_event ... reads an event from hardware (zap_event_t *),
then checks the event type, if its ZAP_OOB_ALARM_TRAP prepares a zap_sigmsg_t
(signaling event) setting its event_id to ZAP_OOB_ALARM_TRAP, which is *WRONG*
because event_id is of type zap_signal_event_t and not zap_oob_event_t!
this means on alarm the user will get ZAP_SIGEVENT_PROGRESS_MEDIA!! which is
value 7 that is in conflict with ZAP_OOB_ALARM_TRAP, I think a separate
callback should be used if the outside user wants to be notified about
hardware events like HW DTMF or so. Currently there is alreadya  generic DTMF
listener.

== Tasks Stage 1 / OpenZAP and Boost changes (To be tested with FreeSWITCH) ==

- Change malloc and other mem functions in openzap
  to use internal hooks provided via zap_global_set_memhandler()
  which would be called before zap_global_init(), this is
  already done for the logger via zap_global_set_logger()
  
  question: should the mem routines allow for memory pool ptr?
            this could be useful to provide a memory pool to
            the whole module.

  question: should we allow hooks for threads and locking?
            I think we can skip this one unless needed. They already
            use their own threading abstraction which is working for
            Linux and Windows. If we ever need to profile threading
            we can add profiling hooks.

  question: I had to add openzap calls to the hash table and libteletone implementations, is that acceptable?

- Modify zap_global_init() API
  
  This API must just initialize vars, mutexes etc.
  and NOT DO ANY CONFIGURATION LOADING, PARSING, SPAN CREATION and I/O
  configuration, which is what is currently doing. 
  We don't want zap_global_init() to create the spans based on that configuration
  since NBE will have its own configuration and will take care of creating
  the needed data structures on its own.

- Add new zap_std_io_config() API 

  This API will parse the standard openzap.conf module and create the spans.  
  This will be used by FS but not by NBE, which will create the openzap spans by itself.
  The NBE flow to initialize openzap will be:

- Add new API zap_global_add_io_iface(), 

  This API will add a new I/O interface structure to the internal openzap hash of I/O structs. 
  This is needed because NBE I/O structure will NOT be loaded from an openzap module (.so/.dll)
  but rather just registered on runtime (probably from a static structure in NBE code).
  This openzap hash is used by zap_api_execute() for example, to find the module that can 
  handle a given API, ie (oz libpri status). This is an example of how an openzap I/O interface 
  can decide to implement just the ->api() member to handle commands and NOTHING else,
  so I/O interfaces not necessary are hardware-related.

- Add new zap_channel_get_siglink_state(zap_channel, zap_siglink_status_t &status)

- Modify mod_openzap.c to read proto= setting in boost spans, this will determine wich boost sig
  module will handle the configuration and those channels.

    <boost_spans> <span sigmod="bri|ss7|blah"> <param="proto-specific-setting" value="setting"> </span> </boost_spans>

    Then as first config arg to zap_config_span() the boost proto module name would be included as "sigmod" which will be used
    by ozmod_sangoma_boost to decide which sig module must handle that span configuration

- Create minimal boost mod interface.
 
   ozmod_boost_ss7 should load sig boost mods and get interface via dlsym(boost_get_interface) boost_get_interface(boost_iface);
  The boost interface will have
    * const char *name                  // boost sigmod name (brid,ss7d)
    * set_write_boost_msg_cb(callback)  // tell the stack how to send us boost messages
    * set_sig_status_cb(callback);      // tell the stack how to notify us about link status changes
    * write_boost_msg(struct boost_msg) // send a boost msg to the stack
    * configure_span(zap_span_t span, "configuration", value, "configuration", value) // configure a given span
    * get_sig_status(openzap_sigstatus_t status)
    * start(span) // to start a given openzap span
    * stop(span) // to stop the stack on a given openzap span

- Migrate current sangoma_brid sig module to openzap
  * Make sangoma_brid a library
  * Move from using malloc, threading, locking, logging and I/O to openzap functions. Export the boost sigmod interface and its supporting code.

== State 2 Tasks == 

- Create the I/O NBE interface and supporting functions. It must be possible to poll over the span
  given that ozmod_sangoma_boost BRI module and others may need to *wait* for data. The poll()
  function in I/O NBE interface would wait on a pthread condition or Windows event, which would
  be triggered by some external NBE component registered with Sangoma Board Manager (SMB) for d-chan
  data, whenever d-chan data arrives, saves the data in a buffer and triggers the condition to wakeup
  any waiter, then the waiter (sangoma_brid or any other boost client) calls zap_channel_read which calls
  our own I/O NBE interface read method and retrieves the data from the buffer.

    Dropped alternative design:
    Another option is to add a new API zap_span_push_incoming_data(span/chan, data); However this changes
    the model openzap has followed and I don't think fits that well, since now we have 2 different models
    to support in openzap. 

== TODO ==

- how about logging specific modules, like, just ozmod_boost, or just the BRI stack?
  more work to be done so the BRI module uses zap_log instead of current syslog
  then work to be done to be able to filter logs from specific openzap code? is it worth it?

- remove FORCE_SEGFAULT from sprid


=== Shortcomings ==

- we had to drop smg support in the branch where we work on sangoma prid.
  After all, most people using sangoma_prid is using freeswitch/openzap and not Sangoma Media Gateway
  The problem is in freeswitch/openzap mode, sangoma_boost ozmod takes care of span events (POLLPRI)
  where in SMG and Netborder POLLPRI is done typically by sangoma board manager.

