Adding an Application
Go back to the Pioneer Overview section.
Adding a new application to Pioneer requires 2 simple steps:
- Send your code
and contact information to
sushila@umich.edu. Your code should be written in a C library,
or possibly a C++ library that can interface with C code.
- Make sure
the code has an
interface as specified below.
Your Code/Contact Information
New applications that have a simple client server format (without multiple
levels of intermediaries)
can be added fairly easily to Pioneer. Currently, I must add some of this
information to the Pioneer code, to accept your application as a valid one.
Once an authentication
framework (which is a parallel project) is in place, we hope to automate
this process. In order to incorporate your application into this framework,
the following
requirements must be met:
- Send me a contact person's Full Name, Institution, and email id.
- Make sure there is an interface to the code that conforms to the format
described in the next section.
- Send me a time period (in seconds) after which this program must be
killed (as an anti hanging precaution). Admin programs may run forever. (at
your own peril, any complaints from unhappy campus folks will be redirected
to you).
Expected Code Format
There are 4 pieces necessary to add a new module to pioneer:
- A CGI script that will be the front end through which the application
is accessed.
- A "C" style header file that lists the functions that are necessary
for pioneer to work.
- A library of routines that contain these functions.
- Some documentation on
an explanation of the results.
Two types of applications are allowed. One is for the average user, and the
other is for admins only. The programs that may be run by all MUST run for
a limited, finite amount of time, and must NOT abuse/affect the network significantly.
(e.g. flood the network). The admin programs have no constraints at the moment.
They are restricted to people with passwords, and the assumption is such
people are responsible.
(Alpha version) Code Idiosyncracies
Currently, Pioneer expects that the user programs are of two types. One is
the case where a program only runs at one end - e.g. Traceroute, or ping.
The other is when they run on two machines, a client end and a server end.
In this case, Pioneer expects two SEPERATE libraries to be submitted,
each with its default set of parameters (unless they are identical). So for
example, "iperf -u -s" and "iperf -c <host> -u" are considered
two seperate modules. The assumption is that the average person will use
applications with a fixed set of default parameters, and anyone who wants
more than that
should have admin privileges. This will probably change in the future to
be one lib per program. All of the communication between the various
servers and modules are SSL encrypted, and new applications must follow
that approach in the CGI scripts (clearly seen in the sample code).
Code Format
Header
The header file must contain pointers to functions that
do the following:
*(fn_debug)(); /* Something that sets debugging to on or
off for this module */
*(fn_get_typestr)(); /*
application name e.g. "ping" used
to make choices in code */
*(fn_get_logstr)(); /*
application name used in logs, e.g. "PING", "IPERFS", "IPERFC" */
*(fn_main)(); /* function to call
when a request is made to run this application */
*(fn_parse)(); /*
function that parses the output and returns a result string in HTML format
*/
Library
The calls listed above must be available as a library, and must pass
the following parameters:
fn_debug (int flag);
where: flag = 0 for no debug, 1 for
debug
fn_get_typestr
();
returns: a "char *" with a string that is EXACTLY as it is
entered in LDAP
fn_get_logstr
();
returns: a "char *" with a string that is used in the log
files to identify activity in this module
fn_main (client_t *myclient, char *fullcmd, char *cmd_name, int *flag);
where: myclient is a data structure as defined below
that is used to pass parameters gathered on the web page.
returns: fullcmd (the full path for the command name e.g.
/usr/bin/ping)
returns: cmd_name (the command name used, should be the same as "fn_get_typestr")
returns: flag which is 0 if no output is generated,
and 1 if
a result is generated. E.g. in the case of iperf that we incorporated,
results are gathered from the server output, and the client output
is discarded.
The data structures for client_t, and the associated
web parameters are:
typedef struct web_request {
int type
/*
iperf/litton etc. */
  int err
/*
Error if any, 0 otherwise */
char host[50];
/* Host to
return response */
int port; /*
Port to send resp to */
char src[100]; /*
Source parameter for cmd */
char dst[100]; /*
Dest parameter for cmd */
char req_host[100]; /*
Cakebox that made request */
void *params; /*
program specific params */
char *resp_str; /*
Response data string */
} web_request_t;
typedef struct client {
char name[50]; /*
Name of this client */
int index; /*
This client's index */
int valid; /*
1/0 if its in use/not */
int socket; /*
fd */
int die; /*
0/1 checked to see if
thread
should exit */
int response_ready; /*
0/1 checked if a web
request
completed */
int thr_type; /*
whether this is client
or
server */
pthread_t thread_id; /*
for cancellation */
int type; /*
for iperf/litton etc. */
web_request_t *webreq; /*
Web based req/resp */
void *params; /*
Parameters based on type */
pthread_mutex_t waitlock; /*
for dowait cond */
pthread_cond_t dowait; /*
for starting a new req */
pthread_mutex_t modlock; /*
for modifying struct */
pthread_mutex_t sleeplock; /*
for dowait cond */
pthread_cond_t sleepcond; /*
for sleep */
} client_t;
fn_parse
(char * cmd, char *output, int len);
where: cmd is
the name to be used in output or error strings, to identify where
its coming from output is the raw output generated by the
command as a result value. len is
the number of bytes of output.
returns: a "char *" result string
that is in HTML format, and sent to the web page where the CGI request was submitted.
CGI Script
This is the front end for the application. It should be based on the
scripts presented in the example section. Primarily, the source and dest
menus
will have to come from a central location where all Cakeboxes have registered
as being alive. In the future, we will make an LDAP interface available
for
the program to access directly.
In the short term, send me the script, and I'll make sure the
menus for Src and Dst are appropriately filled (or cut and paste
from the sample code).
Also note that the message format from the CGI script to the Pioneer
central server is:
sprintf "%d %d %d %d %s %s %s %s %s",
app_code, msglen, $baseport, hostnamelen, get_webhost(), $src,
$dst, $h_name, $params;
where: app_code
is the application code number, which I assign. msglen
is ignored for the moment.
baseport is the port to which results should returned (as
a HTML string).
hostnamelen is the length of the web server host.
get_webhost() returns the central pioneer server name.
src is the source endpoint for the application.
dst is the destination endpoint for the application. h_name
is the name of the host from which the web request was
made to run the application. params is a string that contains
any additional parameters specific to the application.
Sample Code
Here are two examples
for code that we have already incorporated. The first
is "ping" (which
runs on only one machine), and the other is "Iperf" (which
runs on two machines). The version presented for Iperf
is the admin version, which allows all parameters to be
set.
You will notice that ping
runs in a default setting (incorporated in the code) and
runs for a max of 20 seconds. Also notice that the CGI
script for
Iiperf sends two seperate
requests (i.e. messages) to the central Pioneer server:
one to spawn the Iperf server, and one to spawn the Iperf
client.
ping
Average user: CGI code , library code , header file .
Iperf
Admin version: CGI code , server library code , server header file , client library code , client header file .
|