Zero-Knowledge Command Server library

Freedom Services 2.0 Archive Validated

$Id: zkCmdSrv.html,v 1.7 2001/07/10 20:37:42 sam Exp $
Revision Comments
1.1 Author(s): Francis L'Écuyer (francisl@zks.net); 
Initial draft. 

Contents

  1. Introduction
  2. Configuration
  3. Callback functions
  4. Runtime control (signal handling)
  5. Server Processes
  6. Examples
  7. Test Tools

1 - Introduction

Goto : [top]
The Command Server is a library for implementing servers based on the Zero-Knowledge Command Protocol (ZKCP). Its main purpose is to listen on a port for new commands and to send back response (following the ZKCP commands format). The handling of the commands is not done by the server itself but by callbacks that the library user provides to the server. So the semantic of the commands and protocol  is left out of the server and is defined and handled by the user. The Command Server can be configured through command line options and file configuration as well as process signals.

Notes on Server Processes

When the server is started, a new process is started as the deamon process which then pre-forks one child process for each simultaneous connection that the server can handle (configurable). All child processes will listen to the socket port waiting for a new connection. Note that only 1 process will get the connection and the other will be blocked again, waiting for another connection. For robustness purpose, the Command Server can be configure so that pre-forked processes eventually die and get recreated.
See also:
ZK Command Protocol Specification
ZK Command Server Configuration
ZK Command Server Test Tools
ZK Command Server Test Plan

2 - Configuration

Goto : [top]
The Command Server uses the zkConfig frame-work for configuration. So both command line and config file options are available. Also an access file is used to restrict access to the server. The access file contains IP addresses of all authorized clients.

Please refer to the ZK Command Server Configuration page for a complete description of all Command Server options.

3- Callback functions

Goto : [top]
Because the Command Server is a generic server it has no knowledge of the commands that it can receive neither what to do with them. The handling of the commands is defined by the user of library by providing the server with callback functions

3.1 - Process callbacks

When a new child process is forked, the user may need to do some initialization before receiving and handling sessions (or connections). For that, a callback function can be provided to the server which will call by each new process when created. A pointer is passed to the callback function so the application can return some memory space that will be used during the process lifetime. This pointer is also passed to the session and command callback functions so they can access the process data.

The prototype and binding function are:

typedef int (*ZkCmdSrvInitProcess) (ZK_OUT ZkError err,
                                    ZK_IN  void*   applData,
                                    ZK_OUT void**  processData);
extern int zkCmdSrv_SetInitProcess(ZK_OUT ZkError             err,
                                   ZK_IN  ZkCmdSrv            cmdsrv,
                                   ZK_IN  ZkCmdSrvInitProcess function);
Similarly, a callback function can be provided to the server so that when a process terminates, the user can clean up properly. The prototype and binding function are:
typedef int (*ZkCmdSrvTermProcess) (ZK_OUT ZkError err,
                                    ZK_IN  void*   applData,
                                    ZK_IN  void**  processData);
extern int zkCmdSrv_SetTermProcess(ZK_OUT ZkError             err,
                                   ZK_IN  ZkCmdSrv            cmdsrv,
                                   ZK_IN  ZkCmdSrvTermProcess function);

3.2 - Session callbacks

When a new connection starts, the user may need to do some initialization before receiving and handling commands. For that, a callback function can be provided to the server which it will call at the beginning of each connection. A pointer is passed to the callback function so the application can return some memory space that will be used during the session. This pointer is also passed to the command callback functions so they can access the session data.

The prototype and binding function are:

typedef int (*ZkCmdSrvInitSession) (ZK_OUT ZkError err,
                                    ZK_IN  void*   applData,
                                    ZK_IN  void*   processData,
                                    ZK_OUT void**  sessionData);
extern int zkCmdSrv_SetInitSession(ZK_OUT ZkError err,
                                   ZK_IN  ZkCmdSrv cmdsrv,
                                   ZK_IN  ZkCmdSrvInitSession function);
Similarly, a callback function can be provided to the server so that when a session terminates, the user can clean up properly. The prototype and binding function are:
typedef int (*ZkCmdSrvTermSession) (ZK_OUT ZkError err,
                                    ZK_IN  void*   applData,
                                    ZK_IN  void*   processData,
                                    ZK_IN  void**  sessionData);
extern int zkCmdSrv_SetTermSession(ZK_OUT ZkError             err,
                                   ZK_IN  ZkCmdSrv            cmdsrv,
                                   ZK_IN  ZkCmdSrvTermSession function);

3.3 - Command callbacks

A callback function should be provided for each commands defined in the user protocol. So, when the server receives a new command all it does is call the associated function. A response can be returned to the command server who will send it back to the client. The prototype of command callback function is defined as:
typedef int (*ZkCmdSrvCallback) (ZK_OUT ZkError      err,
                                 ZK_IN  void*        applData,
                                 ZK_IN  void*        processData,
                                 ZK_IN  void*        applData,
                                 ZK_IN  ZkcpCommand  comm
                                 ZK_OUT ZkcpCommand* response,
                                 ZK_OUT uint16_t*    closeConn);
Callback functions are bound in the server with the following function:
extern int zkCmdSrv_AddCommand(ZK_OUT ZkError          err,
                               ZK_IN  ZkCmdSrv         cmdsrv,
                               ZK_IN  uint16_t         commId,
                               ZK_IN  ZkCmdSrvCallback function);

3.4- Signal callback

To provide runtime control to the zkCmdSrv library user, the Command Server offers a callback for the SIGURG signal. The user can bind its signal call back using:
typedef int (*ZkCmdSrvSignal) (ZK_OUT ZkError err,
                               ZK_IN  void*   applData);
extern int zkCmdSrv_SetSignal(ZK_OUT ZkError        err,
                              ZK_IN  ZkCmdSrv       cmdsrv,
                              ZK_IN  ZkCmdSrvSignal function);
Note that the callback is not called directly from the signal handler but later when the Command Server goes back to it's main loop.

4 - Runtime Control

Goto : [top]
Like many Freedom servers do, the Command Server provides the user with some runtime configuration using signals. When the server is already started the user can still have some control over the server by sending the following signals: Note that because the Command Server is a pre-forking server special care must be taken to be sure that all processes are signaled. For that, when the server starts it creates a process group to which all processes belong. The syntax to signal a group is to use the parent process ID and prefix it with a dash.  For example, the following would be used to rotate the log file:
kill -HUP -51036

6 - Example

Goto : [top]
The following is an example of how to configure and start a Command Server. Note that for simplicity no error checking and handling is performed. The code in red represents the new command server types and code.
 
void main(int argc, const char **argv)
{
  ZkCmdSrv cmdsrv = NULL;
  ZkCmdSrvConfig srvConfig;
  ZkConfig config;
  ZkcpContext zkcpCtx;
  struct applDataStruct data;
  int pid;

  /* Create and load config file and set command line arguments */
  zkConfigNew(err, &config));
  zkConfigSetCmdParms(err, config, argc, argv);
  zkConfigLoad(err, config, "zkcs.conf));'

  /* Create a Command Protocol context. Also define some zkcp types */
  zkcpContext_Create(err, &zkcpCtx);

  /* Server configuration */
  srvConfig.progName   = argv[0];
  srvConfig.logFile    = "zkcs.log";
  srvConfig.pidFile    = "zkcs.pid";
  srvConfig.accessFile = "zkcs.access";
  srvConfig.addressPath = ":51250";
  srvConfig.maxCommands = 4;
  srvConfig.applData   = &data;
  srvConfig.zkcpCtx     = zkcpCtx;

  /* Create a zkCP context */
  zkcpContext_Create(err, &srvConfig.zkcpCtx);

  /* Create a Command Server object using the server config structure */
  zkCmdSrv_Create(err, &srvConfig, &cmdsrv);

  /* Load up command line and config file options */
  zkCmdSrv_LoadConfig(err, config, cmdsrv);

  /* Set the process callback functions */
  zkCmdSrv_SetInitProcess(err, cmdsrv, ProcessInitCallbackFunc);
  zkCmdSrv_SetTermProcess(err, cmdsrv, ProcessTermCallbackFunc);

  /* Set the session callback functions */
  zkCmdSrv_SetInitSession(err, cmdsrv, SessionInitCallbackFunc);
  zkCmdSrv_SetTermSession(err, cmdsrv, SessionTermCallbackFunc);

  /* Set the command callback functions */
  zkCmdSrv_AddCommand(err, cmdsrv, 0, CommandCallbackFunc0);
  zkCmdSrv_AddCommand(err, cmdsrv, 1, CommandCallbackFunc1);
  zkCmdSrv_AddCommand(err, cmdsrv, 2, CommandCallbackFunc2);
  zkCmdSrv_AddCommand(err, cmdsrv, 3, CommandCallbackFunc3);

  /* Let's start the server */
  zkCmdSrv_Start(err, cmdsrv, &pid);

  if (pid) {
    /* Parent process */
  else {
    /* Child process is done. Let's clean up the data. */
    zkCmdSrv_Destroy(err, cmdsrv);
  }
}

7 - Test Tools

Goto : [top]
Some test tools are available with the library. A small server program can be started and a client program can connect to it. Some options are available. Please refer to  zkcs Test Tools  for more details.

Copyright © 2000 Zero-Knowledge Systems Inc.
All rights reserved.