394 lines
19 KiB
OpenEdge ABL
394 lines
19 KiB
OpenEdge ABL
\subsection{The Connection Object}
|
|
The connection object is a major player in the SICS world. The connection
|
|
object represents an active connection between the SICS server and a client.
|
|
There will be one connection object for each client connection. A lot of
|
|
stuff is associated with a client connection:
|
|
\begin{itemize}
|
|
\item A task. This task will read one command from the command fifo and
|
|
execute it.
|
|
\item A command fifo which will be filled by the network reader.
|
|
\item An execution context consisting of user rights for this connection
|
|
and interrupt status.
|
|
\item A communication channel to the client.
|
|
\item A list of log files to which all traffic on the connection will be
|
|
logged.
|
|
\item An interface to the SICS interpreter which allows to configure
|
|
certain aspects of the connection and makes the connection available as
|
|
a command.
|
|
\item A list of callbacks registered for the connection. A connection can
|
|
be automatically notified about changes in system state. These callbacks
|
|
have to be removed when the client server connection terminates. Otherwise
|
|
callback code would write to a dead connection causing the program to
|
|
crash.
|
|
\end{itemize}
|
|
|
|
\subsubsection{Connection I/O}
|
|
Due to user requirements for features not considered in the design the
|
|
I/O facilities of connection have become quite involved.
|
|
|
|
Incoming commands are printed into client log files if configured, and
|
|
into the commandlog if the connection has a privilege $\ge$ user
|
|
privilege. This is implemented in SCInvoke. Also each command is
|
|
printed to the server log.
|
|
|
|
Output is more sophisticated. First of all there are different output
|
|
codes given as last parameter to SCWrite. The most important of these
|
|
are:
|
|
\begin{description}
|
|
\item[eError] Error messages.
|
|
\item[Warning] warnings.
|
|
\item[Value] values requested by the client.
|
|
\item[Status] status messages.
|
|
\end{description}
|
|
Clients can choose to suppress certain types of messages in order to
|
|
reduce I/O.
|
|
|
|
The logic is mostly implemented in the
|
|
file static function SCNormalWrite. The following conditions are
|
|
implemented:
|
|
\begin{itemize}
|
|
\item Any output is logged to the
|
|
server log.
|
|
\item If the privilege of the connection is $\ge$ user the
|
|
output is printed to the commandlog as well.
|
|
\item If the command is executing as part of a Tcl--macro script
|
|
output to the socket is suppressed. The output is copied into the
|
|
interpreter for further evaluation instead. This is done in order to
|
|
prevent excessive output during macro evaluation and in order to make
|
|
SICS results available in the Tcl interpreter. However, messages of
|
|
type error or warning are printed to the socket even during macro
|
|
evaluation.
|
|
\item In the normal case the output is printed to the socket and all
|
|
log files configured for the connection.
|
|
\end{itemize}
|
|
The above described the default. It turned out that many special cases
|
|
exist where it is feasible to suppress parts of the output. In order
|
|
to take care of this, SCWrite calls a configurable write
|
|
function. This write function can be retrieved and set with
|
|
SCGetWriteFunc and SCSetWriteFunc. SCnoSock, SConlySock, SCnotWrite
|
|
select some predefined write functions for special cases. Please note
|
|
that each of these calls switches the write function for the lifetime
|
|
of the connection or until it is set to a new one through
|
|
SCSetWriteFunc.
|
|
|
|
|
|
|
|
\subsubsection{Command Execution Path}
|
|
In the course of the SICS development the path of a command through
|
|
the system has become more complex as well. This section describes how
|
|
it works. The incoming command is collected at the socket by the
|
|
NetReaderTask. This does a little processing and checks for interrupts
|
|
issued on the connection and invokes them. But any normal command is
|
|
put into the connections Command-FIFO. Thus ends the business of the
|
|
NetReaderTask. The connections task function SCTaskFunction is
|
|
invoked by the task manager in due time and checks for pending
|
|
commands on the command stack. If a command is pending it is taken
|
|
from the stack and executed through SCInvoke.
|
|
|
|
\subsubsection{Execution context}
|
|
Each connection has a user right code associated with it. The there is
|
|
a second protection scheme in SICS with the token system. This system
|
|
reserves command input to a certain connection. In the connection
|
|
object this scheme requires the iGrab field which defines if this
|
|
connection may execute commands or not. This field is modified through
|
|
the tasks signal handling function. Code implementing a command may
|
|
call SCMatchRights in order to check for permission. SCMatchRights
|
|
will also send appropriate error messages.
|
|
|
|
Errors are usually signalled by setting an interrupt code on the
|
|
connection. An additional field, iError allows to give a more detailed
|
|
error description if required.
|
|
|
|
\subsubsection{Callbacks}
|
|
SICS can be configured to forward notifications about certain state
|
|
changes to a connection automatically. This is implemented through the
|
|
callback system. For more details see \ref{inter}. However, it is
|
|
important that any callback acting on a connection is registered with
|
|
the connection object. This allows the removal of the callback when
|
|
the connection is closed. Otherwsie the system gets filled up with
|
|
dead callbacks which usuallly cause core dumps when it is tried to
|
|
send a message to a dead connection.
|
|
|
|
|
|
\subsubsection{The Connection Data Structure}
|
|
Given the plethora of things to take care of, each connection is
|
|
represented by a rather large data structure.
|
|
|
|
@d condat @{
|
|
typedef int (*writeFunc)(struct __SConnection *pCon,
|
|
char *pMessage, int iCode);
|
|
|
|
typedef struct __SConnection {
|
|
/* object basics */
|
|
pObjectDescriptor pDes;
|
|
char *pName;
|
|
long lMagic;
|
|
|
|
/* I/O control */
|
|
mkChannel *pSock;
|
|
FILE *pFiles[MAXLOGFILES];
|
|
int iMacro;
|
|
int iTelnet;
|
|
int iOutput;
|
|
int iFiles;
|
|
writeFunc write;
|
|
mkChannel *pDataSock;
|
|
char *pDataComp;
|
|
int iDataPort;
|
|
|
|
/* execution context */
|
|
int eInterrupt;
|
|
int iUserRights;
|
|
int inUse;
|
|
int iDummy;
|
|
int iGrab;
|
|
int iErrCode;
|
|
int parameterChange;
|
|
SicsInterp *pSics;
|
|
|
|
/* a FIFO */
|
|
pCosta pStack;
|
|
|
|
/* callback registry */
|
|
int iList;
|
|
|
|
/* Tasking Stuff */
|
|
int iEnd;
|
|
/* for keeping track of the login
|
|
process on a non telnet connection.
|
|
Should only be used in SCTaskFunction
|
|
*/
|
|
int iLogin;
|
|
time_t conStart;
|
|
}SConnection;
|
|
@}
|
|
|
|
The fields are:
|
|
\begin{description}
|
|
\item[pDes] The usual object descriptor belonging to any object within the
|
|
SICS interpreter. See \ref{inter} for details.
|
|
\item[pName] The automatically generated name of the connection object in the
|
|
interpreter.
|
|
\item[lMagic] is a magic number used internally in order to check if
|
|
the connection object given as a parameter is valid.
|
|
|
|
\item[pChannel] A pointer to a network channel structure. This channel
|
|
will be used for I/O to the client. If thispointer is NULL I/O is done onto
|
|
stdin/stdout instead.
|
|
\item[pFiles] An array of file to which all I/O on this connection will be
|
|
logged.
|
|
\item[iOutPut] The currently valid output mask. SICS messages are classified
|
|
into several output classes. If a message is going to be printed it must
|
|
have a output class above the one configured as the mask. This was made in
|
|
order to allow clients to suppress certain messages which are not of
|
|
interest.
|
|
\item[iFiles] The number of configured log files.
|
|
\item[write] a pointer to a function which does the actual writing of
|
|
a message to the connection.
|
|
\item[iTelnet] is true when I/O is through a telnet connection.
|
|
\item[iMacro] This flag is set when the connection is executing a Tcl
|
|
script. In this mode mode all output is written into the Tcl interpreter and
|
|
not written to the client. Thus a script can execute silently. As always,
|
|
there is an exception: errors and warning will still be written to the
|
|
client.
|
|
|
|
\item[iGrab] This is 0 when the connection may execute commands. It is 1 if
|
|
another connection has grabbed the control token and commands may not be
|
|
executed. For details about the token system, see the token reference.
|
|
\item[eInterrupt] This is the current interrupt status of the connection.
|
|
\item[iUserRights] This integer denotes the user rights associated with the
|
|
connection. This value is initially deducted from the username password pair
|
|
given at login to SICS. The value can be configured otherwise afterwards.
|
|
iUserRights will be used to check at object level if a client may perform
|
|
the requested operation or not.
|
|
\item[iErrCode] is the last error code. I think this field is no longer
|
|
used.
|
|
|
|
\item[pSics] is a pointer to an SICS interpreter where to invoke commands.
|
|
\item[pStack] Is the command FIFO.
|
|
\item[iList] This is the identifier of a lld list which holds the callbacks
|
|
registered on this connection object.
|
|
\item[iEnd] iEnd is a flag which is usually 0. It is set by certain
|
|
interrupts or if the connection is broken and causes the connection task to
|
|
end and the connection data structure to be removed from the system.
|
|
\item[iLogin] A flag which is set when we are not yet logged in.
|
|
\item[conStart] The time the connection was established. Used to
|
|
timeout connections when no valid login comes within a decent time
|
|
intervall.
|
|
\end{description}
|
|
Quite a few places in SICS refer to this data structure directly,
|
|
without a function interface. The reason for this is performance. Therefore
|
|
this data structure is made public in the conman.h file.
|
|
|
|
|
|
\subsubsection{Connection Functions}
|
|
The interface to this data structure is defined by the following functions:
|
|
@d conint @{
|
|
/*------------------------------ live & death ----------------------------*/
|
|
SConnection *SCreateConnection(SicsInterp *pSics, mkChannel *pSock,
|
|
int iUserRights);
|
|
SConnection *SCCreateDummyConnection(SicsInterp *pSics);
|
|
void SCDeleteConnection(void *pVictim);
|
|
|
|
/*------------------------------- tasking --------------------------------*/
|
|
int SCTaskFunction(void *pCon);
|
|
void SCSignalFunction(void *pCon, int iSignal, void *pSigData);
|
|
/* ***************************** I/O ************************************** */
|
|
int SCAddLogFile(SConnection *self, char *name);
|
|
int SCDelLogFile(SConnection *pCon, int iFile);
|
|
void SCSetOutputClass(SConnection *self, int iClass);
|
|
int SCWrite(SConnection *self, char *pBuffer, int iOut);
|
|
int SCRead(SConnection *self, char *pBuffer, int iBufLen);
|
|
int SCPrompt(SConnection *pCon, char *pPrompt, char *pResult, int iLen);
|
|
int SCSendOK(SConnection *self);
|
|
int SCnoSock(SConnection *pCon);
|
|
int SCWriteUUencoded(SConnection *pCon, char *pName, void *iData, int iLen);
|
|
int SCWriteZipped(SConnection *pCon, char *pName, void *pData, int iDataLen);
|
|
writeFunc SCGetWriteFunc(SConnection *pCon);
|
|
void SCSetWriteFunc(SConnection *pCon, writeFunc x);
|
|
int SCOnlySockWrite(SConnection *self, char *buffer, int iOut);
|
|
int SCNotWrite(SConnection *self, char *buffer, int iOut);
|
|
/************************* CallBack *********************************** */
|
|
int SCRegister(SConnection *pCon, SicsInterp *pSics,
|
|
void *pInter, long lID);
|
|
int SCUnregister(SConnection *pCon, void *pInter);
|
|
/******************************* Error **************************************/
|
|
void SCSetInterrupt(SConnection *self, int eCode);
|
|
int SCGetInterrupt(SConnection *self);
|
|
/****************************** Macro ***************************************/
|
|
int SCinMacro(SConnection *pCon);
|
|
int SCsetMacro(SConnection *pCon, int iMode);
|
|
/************************** parameters changed ? **************************/
|
|
void SCparChange(SConnection *pCon);
|
|
/* *************************** Info *************************************** */
|
|
int SCGetRights(SConnection *self);
|
|
int SCSetRights(SConnection *pCon, int iNew);
|
|
int SCMatchRights(SConnection *pCon, int iCode);
|
|
int SCGetOutClass(SConnection *self);
|
|
int SCGetGrab(SConnection *pCon);
|
|
/********************* simulation mode ************************************/
|
|
void SCSetSimMode(SConnection *pCon, int value);
|
|
int SCinSimMode(SConnection *pCon);
|
|
/* **************************** Invocation ******************************** */
|
|
int SCInvoke(SConnection *self,SicsInterp *pInter,char *pCommand);
|
|
|
|
/*************************** User Command **********************************/
|
|
int ConfigCon(SConnection *pCon, SicsInterp *pSics, void *pData,
|
|
int argc, char *argv[]);
|
|
int ConSicsAction(SConnection *pCon, SicsInterp *pSics, void *pData,
|
|
int argc, char *argv[]);
|
|
|
|
@}
|
|
The functions in more detail:
|
|
\begin{description}
|
|
\item[SCreateConnection] creates a new connection object. Parameters to this
|
|
call are a pointer to a server data structure, a pointer to a network
|
|
connection object and the user rights to use in this connection. This
|
|
also adds a new task function for this connection to the task object.
|
|
\item[SCCreateDummyConnection] creates a dummy connection for use during
|
|
system initialisation. Printing to a socket will be suppressed for such a connection. But the output is printed to stdout.
|
|
|
|
\item[SCTaskFunction] is the task function which will be registered with the
|
|
Tasker. This function reads a new command from the command stack (if
|
|
available) and executes it in the interpreter.
|
|
\item[SCSignalFunction] is the signal function for the connection
|
|
object. This function handles interrupts and the token security
|
|
system.
|
|
\item[SCDeleteConnection] deletes a connection object and all its data
|
|
structures. This function will be automatically called by the tasker when
|
|
the task function returns with a 0.
|
|
\item[SCAddLogFile] configures the log file name into the connection object.
|
|
If this suceeds all I/O to the connection will be logged to this file as
|
|
well.
|
|
\item[SCSetOutputClass] sets the output class for the connection.
|
|
\item[SCGetOutClass] returns the output class of the connection.
|
|
\item[SCWrite] is the most important function of SConnection. Writes the
|
|
buffer pBuffer with output code iOut to the client. {\em All output to the
|
|
client has to be channelled through this function!}
|
|
\item[SCRead] reads data from the client connection into the buffer pBuffer,
|
|
but maximum iBufLen bytes.
|
|
\item[SCPrompt] prompts the client for a reply. But waits only for certain
|
|
timeout period. pPrompt is the prompt for the client, pResult is the buffer
|
|
with the client reply. Maximum iLen bytes will be copied to
|
|
pResult. Returns true (1) on a successfull read, else 0 (false).
|
|
\item[SCSendOK] A short cut which sends OK to the client.
|
|
\item[SCnoSock] Suppress output onto the client socket but keeps on
|
|
logging output to file. This is mostly used when the socket connection
|
|
closes with a batch file still being active.
|
|
\item[SCWriteUUencoded] sends iData in UU encoded form. For
|
|
communication with status clients.
|
|
\item[SCWriteZipped] writes pData in zipped form. Works only if the
|
|
connection is a plain connection, no telnet mode. This first sends a
|
|
line: SICSBIN ZIP dataname datalength followed by datalength bytes of
|
|
zipped data after the newline. Used for transferring larger amounts of
|
|
data to status clients.
|
|
\item[SCGetWriteFunc] gets the currently active write function.
|
|
\item[SCSetWriteFunc] sets a new write function.
|
|
\item[SCOnlySockWrite] write only to socket, not to log files.
|
|
\item[SCNotWrite] do not write at all.
|
|
\item[SCRegister] registers a callback with the connection. Parameters are:
|
|
The interpreter to use, the interface with which the callback was
|
|
registered and the ID of the callback. All automatic notifications to a
|
|
client MUST be registered with this call. When the connection is deleted all
|
|
these callbacks will be removed as well. Otherwise a core dump is bound to
|
|
happen.
|
|
\item[SCUnregister] will remove all callbacks on interface pInter for this
|
|
connection.
|
|
\item[SCSetInterrupt] sets an interrupt on the connection.
|
|
\item[SCGetInterrupt] retrives the current interrupt status of the
|
|
connection.
|
|
\item[SCinMacro] returns true if the connection is executing a tcl script,
|
|
returns false otherwise.
|
|
\item[SCsetMacro] sets the iMacro flag.
|
|
\item[SCparChange] sets the flag that a parameter was changed and the
|
|
status file needs to be rewritten.
|
|
\item[SCGetRights] returns the current user rights associated with the
|
|
connection.
|
|
\item[SCGetGrab] gets the status of the control token for this connection.
|
|
This calls returns 0 if the connection may execute commands and 1 if another
|
|
connection has the control token.
|
|
\item[SCSetRights] sets the user rights for the connection to a new value.
|
|
\item[SCMatchRights] return true (1) if the iCode matches with the user
|
|
rights of the connection, 0 (false) otherwise. SCMatchRights also checks for
|
|
the status of the control token. Suitable error messages are written to pCon
|
|
if the user rights do not match.
|
|
\item[SCSetSimMode] sets this connection into simulation mode.
|
|
\item[SCinSimMode] checks for the simulation mode flag.
|
|
\item[SCInvoke] invokes pCommand in the SICS interpreter pSics for the
|
|
connection pCon. This function also prints the executed command into
|
|
logfiles and into the commandlog.
|
|
\end{description}
|
|
|
|
@o conman.h @{
|
|
/*--------------------------------------------------------------------------
|
|
C O N N E C T I O N O B J E C T
|
|
|
|
This file defines the connection object data structure and the interface to
|
|
this data structure. This is one of the most important SICS components.
|
|
|
|
|
|
Substantially revised from a prior version.
|
|
|
|
Mark Koennecke, September 1997
|
|
|
|
Mark Koennecke, Aprl 2003
|
|
|
|
copyright: see copyright.h
|
|
----------------------------------------------------------------------------*/
|
|
#ifndef SICSCONNECT
|
|
#define SICSCONNECT
|
|
#include <stdio.h>
|
|
#include "costa.h"
|
|
#include "SCinter.h"
|
|
#include "network.h"
|
|
#include "obdes.h"
|
|
|
|
#define MAXLOGFILES 10
|
|
@<condat@>
|
|
#include "nserver.h"
|
|
@<conint@>
|
|
|
|
#endif
|
|
@}
|
|
|