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
- setup your programming environment for the client (tcl)
- primary I use Linux as development host
- as tools I prefer gcc, gmake, libtool and vim
- all tcl related software is in a development-tree under the TCLBASE environment variable
- as repository I use cvs
- I always using a working-tree based on lndir the CVS-tree into my current workspace
- to build the software on other hosts I export the CVS-tree and create a local working-tree
- I always have 4 uptodate build-trees for every project using different build options(shared, static, debugging and profiling)
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 |
the Makefile is separated into three independent parts
- Makefile.local, different for every build (shared, static, debugging, profile)
- Makefile.arch, different for every host system (darwin7.0-powerpc, Interix-x86, linux-i386, CYGWIN_NT-5.1-i686)
- 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 is the easiest part of the development. The file is always the same doesn't matter what service you offer.
main.h supplies mandatory #include directives need by all files.
...
#include "msgque/types.h"
...
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.
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.
ContextCreate create a new parent or child ContextS. Creating a context mean:
- create the
ContextS object - create the
MqS (e.g libFreiburg 2.0) object - add initial service handles
- initialize
ContextS own data
MqErrorE
ContextCreate(MqBufferLS * const argv, ContextS **out) {
ContextS *context = MqSysCalloc(NULL,1,sizeof(ContextS));
if (out) *out = context;
MqBufferLAppendHP(argv, "-fCreate", ContextCreate);
MqBufferLAppendHP(argv, "-fDelete", ContextDelete);
MqErrorCheck(MqCreate(context, argv, &context->msgque));
MqErrorCheck(MqTokenAddHdl(context->msgque->srvT, "INIT", Ot_INIT, NULL));
context->misc = MqBufferCreate(context->msgque->error, 100);
error:
return MqErrorSAppendV(context->msgque->error, MQ_ERROR_PROC_FMT, __func__);
}
ContextDelete is used to cleanup the ContextS object
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);
MqErrorCheck(MqReadArgv(msgque->read, &largc, &largv));
switch (arg = snmp_parse_args(largc, largv, &session, "", NULL)) {
}
context->session = snmp_open(&session);
if (!context->session) {
MqErrorC(MQ_ERROR_S, __func__, -1, "can not open session");
goto error;
}
MqErrorCheck(MqTokenDelHdl(token, "INIT"));
MqErrorCheck(MqTokenAddHdl(token, "BGET", Ot_BGET, NULL));
...
error:
return MqSendRETURN(msgque->send, MQ_ERROR_PROC_FMT, __func__);
}
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
1.3.8-20040928