Main Page | Modules | Class Hierarchy | Class List | File List | Class Members | Related Pages

create a snmp service

Table Of Contents

Introduction

to create an new service like snmp a couple of steps are always mandatory:

Find the right dynamic library to use

Setup your build environment for the service

Create the files needed

to create a service from a dynamic library a couple of files are always needed:
Makefile build the service using a compiler
main.c main entry point, create parent object and start event-loop
main.h include mandatory library and libFreiburg 2.0 header files
context.c place event handles and context management procedures

Makefile

the Makefile is separated into three independent parts
  1. Makefile.local, different for every build (shared, static, debugging, profile)
  2. Makefile.arch, different for every host system (darwin7.0-powerpc, Interix-x86, linux-i386, CYGWIN_NT-5.1-i686)
  3. Makefile, one generic file per project, including Makefile.local and Makefile.arch
#
# Parameters
PROGRAM   = tclsnmp_server.debug
OBJECTS   = main.lo context.lo api.lo misc.lo
FREIBLIB  = $(FREIBDIR)/lib/libfreiburg.la
SNMPLIB   = $(SNMPDIR)/lib/libnetsnmp.la
#
# Compiler flags
CFLAGS    = -g -Wall -D$(ARCH)
CPPFLAGS  = -I$(FREIBDIR)/include -I$(SNMPDIR)/include
LDLIBS    = -lm $(FREIBLIB) $(SNMPLIB)
#
# Rules
%.lo: %.c
    $(LIBTOOL) --mode=compile $(CC) $(CFLAGS) $(CPPFLAGS) -c $<
#
# service
$(PROGRAM): $(OBJECTS) $(FREIBLIB)
    $(LIBTOOL) --mode=link $(CC) -o $@ $(OBJECTS) $(LDLIBS)

main.c

main.c is the easiest part of the development. The file is always the same doesn't matter what service you offer.
#include "main.h"
#include "context.h"
#include "msgque/bufferL.h"

int main(int argc, char **argv)
{
   ContextS *context;                                             // the parent-context
   MqBufferLS *largv = MqBufferLCreateArgv(NULL, --argc, ++argv); // parse command-line
   MqBufferLAppendH2(largv, "-type", MQ_SERVER);                  // I'm a server
   MqErrorCheck(ContextCreate(largv, &context));                  // create the ContextS
   MqErrorCheck(
    // start event-loop and wait forever
    MqProcessEvent(context->msgque,MQ_TIMEOUT,MQ_WAIT|MQ_FOREVER)
   );
   ContextDelete(&context);                                       // this should never be reached
   exit(EXIT_SUCCESS);
error:                                                            // something is wrong
   MqErrorSSend(context->msgque->error, __func__);                // send error-msg to 'client'
   ContextDelete(&context);                                       // cleanup
   exit(EXIT_FAILURE);
}

main.h

main.h supplies mandatory #include directives need by all files.
// net-snmp include files
...
// the main libFreiburg include-file
#include "msgque/types.h"
// some common usable const
...

context.c

context.c is always available for a service. the propose is to provide code for creating (ContextCreate) and deleting (ContextDelete) of a parent or child ContextS object and to add code for the service handles.

struct ContextS

ContextS is the main object used as parent or child context. Every ContextS has at leased one entry for the MqS (e.g. libFreiburg 2.0) object.
typedef struct ContextS {
   struct MqS          *msgque     ;   // the libFreiburg object belonging to the ContectS
   netsnmp_session     *session    ;   // the current net_snmp session
   struct MqBufferS    *misc       ;   // internal temporary data 
} ContextS;

procedure ContextCreate

ContextCreate create a new parent or child ContextS. Creating a context mean:
  1. create the ContextS object
  2. create the MqS (e.g libFreiburg 2.0) object
  3. add initial service handles
  4. initialize ContextS own data
MqErrorE
ContextCreate(MqBufferLS * const argv, ContextS **out) {
   ContextS *context = MqSysCalloc(NULL,1,sizeof(ContextS));
   if (out) *out = context;
 // MqS, the main libFreiburg object, does not know anything about the current
 // ContextS but need the information to build and delete a 'child' context
   MqBufferLAppendHP(argv, "-fCreate", ContextCreate);      // function to create a 'child'
   MqBufferLAppendHP(argv, "-fDelete", ContextDelete);      // function to delete a 'child'
   MqErrorCheck(MqCreate(context, argv, &context->msgque)); // create libFreiburg object
 // add the login (e.g. INIT) service as !only! initial service
   MqErrorCheck(MqTokenAddHdl(context->msgque->srvT, "INIT", Ot_INIT, NULL));
   context->misc = MqBufferCreate(context->msgque->error, 100); // temporary internal buffer
 error:
 // something is wrong, add current function to the error stack
   return MqErrorSAppendV(context->msgque->error, MQ_ERROR_PROC_FMT, __func__);
}

procedure ContextDelete

ContextDelete is used to cleanup the ContextS object
void ContextDelete(ContextS ** contextP) {
   struct ContextS * context = *contextP;
   if (!context) return;                      // if nothing to do just return
   MqBufferDelete(&context->misc);            // delete ContextS own data
   MqDelete(&context->msgque);                // delete libFreiburg data
   MqSysFree(NULL,(MQ_PTR*)contextP);         // delete ContestS object
}

procedure and service-handle Ot_INIT

Ot_INIT is a service handle to do the user verification. One feature of libFreiburg 2.0 is the ability to dynamically add and remove service handles. In this case after a successful login no additional login for the same ContextS is allowed -> just delete the INIT service but add additional services local to the current verified context.
static MqErrorE Ot_INIT(MqS *msgque, void* data) {
   struct ContextS *context = msgque->myCtx;
   struct MqTokenS *token = msgque->srvT;
   netsnmp_session session;
   int arg, largc;
   char **largv;

   MqErrorReset(MQ_ERROR_S);                                  // reset 'error' buffer
   MqErrorCheck(MqReadArgv(msgque->read, &largc, &largv));    // split package into 'argv'
   switch (arg = snmp_parse_args(largc, largv, &session, "", NULL)) { // parse command-line
   }
   context->session = snmp_open(&session);                    // open an SNMP session
   if (!context->session) {                                   // diagnose snmp_open errors
       MqErrorC(MQ_ERROR_S, __func__, -1, "can not open session");
       goto error;
   }
   MqErrorCheck(MqTokenDelHdl(token, "INIT"));                // 'INIT' not need anymore
   MqErrorCheck(MqTokenAddHdl(token, "BGET", Ot_BGET, NULL)); // add new service handle
   ...
 error:                                                       // always be reached
   return MqSendRETURN(msgque->send, MQ_ERROR_PROC_FMT, __func__); // status back
}

prev: client/server versa parent/child - top: libFreiburg 2.0 - next: using a superserver

Generated on Tue Nov 23 16:13:06 2004 for libFreiburg by  doxygen 1.3.8-20040928