Initial revision
This commit is contained in:
356
nconman.w
Normal file
356
nconman.w
Normal file
@ -0,0 +1,356 @@
|
||||
\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 follwoing 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.
|
||||
\item As of recent the output function can be modified by setting a
|
||||
new function. One sich function exists which supresses all output to
|
||||
the socket. This is done in order to help when the connection gets
|
||||
lost. For instance with the cron command.
|
||||
\end{itemize}
|
||||
This aspect of the connection object could do with a cleanup. A
|
||||
possible cleanup path is the implementation of the different output
|
||||
strategies in different functions and devise a SCsetOutMode function which
|
||||
switches between the various possibilities. Also, it can be argued if
|
||||
the client specific log files are still needed. Then this part of the
|
||||
code can be cleaned out as well.
|
||||
|
||||
|
||||
\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 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;
|
||||
int (*write)(struct __SConnection *pCon,
|
||||
char *pMessage, int iCode);
|
||||
mkChannel *pDataSock;
|
||||
char *pDataComp;
|
||||
int iDataPort;
|
||||
|
||||
/* execution context */
|
||||
int eInterrupt;
|
||||
int iUserRights;
|
||||
int inUse;
|
||||
int iDummy;
|
||||
int iGrab;
|
||||
int iErrCode;
|
||||
SicsInterp *pSics;
|
||||
|
||||
/* a FIFO */
|
||||
pCosta pStack;
|
||||
|
||||
/* callback registry */
|
||||
int iList;
|
||||
|
||||
/* Tasking Stuff */
|
||||
int iEnd;
|
||||
}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.
|
||||
\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);
|
||||
/************************* 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);
|
||||
void SCSetError(SConnection *pCon, int iCode);
|
||||
int SCGetError(SConnection *pCon);
|
||||
/****************************** Macro ***************************************/
|
||||
int SCinMacro(SConnection *pCon);
|
||||
int SCsetMacro(SConnection *pCon, int iMode);
|
||||
|
||||
/* *************************** 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);
|
||||
|
||||
/* **************************** 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[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[SCSetError] sets an error code in the connection.
|
||||
\item[SCGetError] retreives the current error code on the connection.
|
||||
\item[SCinMacro] returns true if the connection is executing a tcl script,
|
||||
returns false otherwise.
|
||||
\item[SCsetMacro] sets the iMacro flag.
|
||||
\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[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
|
||||
|
||||
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
|
||||
@}
|
||||
|
Reference in New Issue
Block a user