Table of Contents

My interest is mostly in writing new Modules for OpenSER at this time. I could not find a lot of information about it, so I started this page set. Please if you find I am going down the wrong path, correct me and these pages. I will try to only include correct information, but I am learning as I go.

Introduction

The code and APIs are based off the current 1.1.x source base.

When starting a new module, there are a few things you must do. Listed below will get you started with the template module structured code example:

Template Module

#include "../../sr_module.h"
 
MODULE_VERSION
 
static int modInit(void);
static void modDestroy();
 
/*
 * Script commands we export.
 */
static cmd_export_t cmds[]={
  {0,0,0,0,0}
};
 
/*
 * Script parameters
 */
static param_export_t mod_params[]={
  { 0,0,0 }
};
 
/*
 * Export the statistics we have
 */
static stat_export_t mod_stats[] = {
  {0,0,0}
};
 
struct module_exports exports= {
  "MyMod",	/* module's name */
  cmds,         /* exported functions */
  mod_params,   /* param exports */
  mod_stats,    /* exported statistics */
  modInit,      /* module initialization function */
  0,            /* reply processing function FIXME Not sure when this is used */
  modDestroy,   /* Destroy function */
  childInit     /* per-child init function */
};
 
/**
 * @return 0 to continue to load the OpenSER, -1 to stop the loading
 * and abort OpenSER.
 */
static int modInit(void) {
  return(0);
}
 
/**
 * Called only once when OpenSER is shuting down to clean up module
 * resources.
 */
static void modDestroy() {
  return;
}
 
/**
 * The rank will be o for the main process calling this function,
 * or 1 through n for each listener process. The rank can have a negative
 * value if it is a special process calling the child init function.
 * Other then the listeners, the rank will equal one of these values:
 * PROC_MAIN      0  Main ser process
 * PROC_TIMER    -1  Timer attendant process 
 * PROC_FIFO     -2  FIFO attendant process
 * PROC_TCP_MAIN -4  TCP main process
 * PROC_UNIXSOCK -5  Unix domain socket server processes
 *
 * If this function returns a nonzero value the loading of OpenSER will
 * stop.
 */
static int childInit(int rank) {
  int rtn = 0;
 
  return(rtn);
}

You should be able to cut and paste the code above into your first module “C” file. To build the module, read the Module Makefile section.

Module export structure

cmd_export_t

struct cmd_export_t {
	char* name;             /* null terminated command name */
	cmd_function function;  /* pointer to the corresponding function */
	int param_no;           /* number of parameters used by the function */
	fixup_function fixup;   /* pointer to the function called to "fix" the
				   parameters */
	int flags;              /* Function flags */
};

Hints & Tips

Because the module is written in “C” you must be carefull about naming your functions. The function field in the cmd_export_t structure can be file scope (static) if you want to define the real handler in the same file as you define the cmd_export_t structure. In most cases you will want to define all your handlers in a separate file like MyMod_handlers.c. In this case, make sure you add your module name to the begining of the function named to ensure there is no namespace collisions. i.e. MyMod_func1().

Licensing of Modules

The relevant part of the GPL concerning distribution of proprietary modules is the bottom of section 2, here quoted:

These requirements apply to the modified work as a whole. If identifiable sections of that work are not derived from the Program, and can be reasonably considered independent and separate works in themselves, then this License, and its terms, do not apply to those sections when you distribute them as separate works. But when you distribute the same sections as part of a whole which is a work based on the Program, the distribution of the whole must be on the terms of this License, whose permissions for other licensees extend to the entire whole, and thus to each and every part regardless of who wrote it. Thus, it is not the intent of this section to claim rights or contest your rights to work written entirely by you; rather, the intent is to exercise the right to control the distribution of derivative or collective works based on the Program. In addition, mere aggregation of another work not based on the Program with the Program (or with a work based on the Program) on a volume of a storage or distribution medium does not bring the other work under the scope of this License.

So, if you are writing a closed module that washes the dog, walks the dishes, and controls the light in your aquarium within the larger context of the openSER framework, without modifying the framework, directing people who wish source code to the openSER web site to obtain the GPL'd portions of a proprietary and commercial VOIP-controlled dog-washing, dish-walking, aquarium-light-controlling appliance is sufficent, although RMS will probably not share his ravs with you should the opportunity arise. Your module's main focus – home automation with regard to dogs, dishes, and pet fish – is not the main focus of openSER, and although your module plugs into the openSER framework, it could just as well plug into some other framework instead of openSER.

The GPL would not force distribution of your trade secrets involved in your dog/dish/fish component.

Addition of a module does not constitute a modification of openSER, nor does selection of openSER as a product's framework for interfacing with VOIP necessarily make the resulting composite work a derivative work of openSER.

Said home automation system would not be “based on” openSER. Said home automation system would include openSER for VOIP functionality.

Adherence to the provided and documented module API fulfills the “arm's length” requirement discussed at http://www.gnu.org/licenses/gpl-faq.html#TOCGPLInProprietarySystem even though the module and the framework will be linked into a single binary executable file, which is a technical detail.