427 lines
22 KiB
TeX
427 lines
22 KiB
TeX
\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.
|
|
|
|
\begin{flushleft} \small
|
|
\begin{minipage}{\linewidth} \label{scrap1}
|
|
$\langle$condat {\footnotesize ?}$\rangle\equiv$
|
|
\vspace{-1ex}
|
|
\begin{list}{}{} \item
|
|
\mbox{}\verb@@\\
|
|
\mbox{}\verb@typedef int (*writeFunc)(struct __SConnection *pCon,@\\
|
|
\mbox{}\verb@ char *pMessage, int iCode);@\\
|
|
\mbox{}\verb@@\\
|
|
\mbox{}\verb@ typedef struct __SConnection {@\\
|
|
\mbox{}\verb@ /* object basics */@\\
|
|
\mbox{}\verb@ pObjectDescriptor pDes;@\\
|
|
\mbox{}\verb@ char *pName;@\\
|
|
\mbox{}\verb@ long lMagic;@\\
|
|
\mbox{}\verb@ @\\
|
|
\mbox{}\verb@ /* I/O control */@\\
|
|
\mbox{}\verb@ mkChannel *pSock;@\\
|
|
\mbox{}\verb@ FILE *pFiles[MAXLOGFILES];@\\
|
|
\mbox{}\verb@ int iMacro;@\\
|
|
\mbox{}\verb@ int iTelnet;@\\
|
|
\mbox{}\verb@ int iOutput; @\\
|
|
\mbox{}\verb@ int iFiles;@\\
|
|
\mbox{}\verb@ writeFunc write;@\\
|
|
\mbox{}\verb@ mkChannel *pDataSock;@\\
|
|
\mbox{}\verb@ char *pDataComp;@\\
|
|
\mbox{}\verb@ int iDataPort;@\\
|
|
\mbox{}\verb@@\\
|
|
\mbox{}\verb@ /* execution context */@\\
|
|
\mbox{}\verb@ int eInterrupt;@\\
|
|
\mbox{}\verb@ int iUserRights;@\\
|
|
\mbox{}\verb@ int inUse;@\\
|
|
\mbox{}\verb@ int iDummy;@\\
|
|
\mbox{}\verb@ int iGrab;@\\
|
|
\mbox{}\verb@ int iErrCode;@\\
|
|
\mbox{}\verb@ int parameterChange;@\\
|
|
\mbox{}\verb@ SicsInterp *pSics;@\\
|
|
\mbox{}\verb@ @\\
|
|
\mbox{}\verb@ /* a FIFO */@\\
|
|
\mbox{}\verb@ pCosta pStack;@\\
|
|
\mbox{}\verb@@\\
|
|
\mbox{}\verb@ /* callback registry */@\\
|
|
\mbox{}\verb@ int iList;@\\
|
|
\mbox{}\verb@@\\
|
|
\mbox{}\verb@ /* Tasking Stuff */@\\
|
|
\mbox{}\verb@ int iEnd;@\\
|
|
\mbox{}\verb@ /* for keeping track of the login@\\
|
|
\mbox{}\verb@ process on a non telnet connection.@\\
|
|
\mbox{}\verb@ Should only be used in SCTaskFunction@\\
|
|
\mbox{}\verb@ */@\\
|
|
\mbox{}\verb@ int iLogin;@\\
|
|
\mbox{}\verb@ time_t conStart;@\\
|
|
\mbox{}\verb@ }SConnection;@\\
|
|
\mbox{}\verb@@$\diamond$
|
|
\end{list}
|
|
\vspace{-1ex}
|
|
\footnotesize\addtolength{\baselineskip}{-1ex}
|
|
\begin{list}{}{\setlength{\itemsep}{-\parsep}\setlength{\itemindent}{-\leftmargin}}
|
|
\item Macro referenced in scrap ?.
|
|
\end{list}
|
|
\end{minipage}\\[4ex]
|
|
\end{flushleft}
|
|
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:
|
|
\begin{flushleft} \small
|
|
\begin{minipage}{\linewidth} \label{scrap2}
|
|
$\langle$conint {\footnotesize ?}$\rangle\equiv$
|
|
\vspace{-1ex}
|
|
\begin{list}{}{} \item
|
|
\mbox{}\verb@@\\
|
|
\mbox{}\verb@/*------------------------------ live & death ----------------------------*/@\\
|
|
\mbox{}\verb@ SConnection *SCreateConnection(SicsInterp *pSics, mkChannel *pSock,@\\
|
|
\mbox{}\verb@ int iUserRights);@\\
|
|
\mbox{}\verb@ SConnection *SCCreateDummyConnection(SicsInterp *pSics);@\\
|
|
\mbox{}\verb@ void SCDeleteConnection(void *pVictim);@\\
|
|
\mbox{}\verb@ @\\
|
|
\mbox{}\verb@/*------------------------------- tasking --------------------------------*/@\\
|
|
\mbox{}\verb@ int SCTaskFunction(void *pCon);@\\
|
|
\mbox{}\verb@ void SCSignalFunction(void *pCon, int iSignal, void *pSigData);@\\
|
|
\mbox{}\verb@/* ***************************** I/O ************************************** */@\\
|
|
\mbox{}\verb@ int SCAddLogFile(SConnection *self, char *name);@\\
|
|
\mbox{}\verb@ int SCDelLogFile(SConnection *pCon, int iFile);@\\
|
|
\mbox{}\verb@ void SCSetOutputClass(SConnection *self, int iClass);@\\
|
|
\mbox{}\verb@ int SCWrite(SConnection *self, char *pBuffer, int iOut);@\\
|
|
\mbox{}\verb@ int SCRead(SConnection *self, char *pBuffer, int iBufLen); @\\
|
|
\mbox{}\verb@ int SCPrompt(SConnection *pCon, char *pPrompt, char *pResult, int iLen);@\\
|
|
\mbox{}\verb@ int SCSendOK(SConnection *self);@\\
|
|
\mbox{}\verb@ int SCnoSock(SConnection *pCon);@\\
|
|
\mbox{}\verb@ int SCWriteUUencoded(SConnection *pCon, char *pName, void *iData, int iLen);@\\
|
|
\mbox{}\verb@ int SCWriteZipped(SConnection *pCon, char *pName, void *pData, int iDataLen);@\\
|
|
\mbox{}\verb@ writeFunc SCGetWriteFunc(SConnection *pCon);@\\
|
|
\mbox{}\verb@ void SCSetWriteFunc(SConnection *pCon, writeFunc x);@\\
|
|
\mbox{}\verb@ int SCOnlySockWrite(SConnection *self, char *buffer, int iOut);@\\
|
|
\mbox{}\verb@ int SCNotWrite(SConnection *self, char *buffer, int iOut);@\\
|
|
\mbox{}\verb@/************************* CallBack *********************************** */@\\
|
|
\mbox{}\verb@ int SCRegister(SConnection *pCon, SicsInterp *pSics,@\\
|
|
\mbox{}\verb@ void *pInter, long lID);@\\
|
|
\mbox{}\verb@ int SCUnregister(SConnection *pCon, void *pInter);@\\
|
|
\mbox{}\verb@/******************************* Error **************************************/@\\
|
|
\mbox{}\verb@ void SCSetInterrupt(SConnection *self, int eCode);@\\
|
|
\mbox{}\verb@ int SCGetInterrupt(SConnection *self); @\\
|
|
\mbox{}\verb@/****************************** Macro ***************************************/@\\
|
|
\mbox{}\verb@ int SCinMacro(SConnection *pCon);@\\
|
|
\mbox{}\verb@ int SCsetMacro(SConnection *pCon, int iMode); @\\
|
|
\mbox{}\verb@/************************** parameters changed ? **************************/@\\
|
|
\mbox{}\verb@ void SCparChange(SConnection *pCon);@\\
|
|
\mbox{}\verb@/* *************************** Info *************************************** */@\\
|
|
\mbox{}\verb@ int SCGetRights(SConnection *self);@\\
|
|
\mbox{}\verb@ int SCSetRights(SConnection *pCon, int iNew);@\\
|
|
\mbox{}\verb@ int SCMatchRights(SConnection *pCon, int iCode);@\\
|
|
\mbox{}\verb@ int SCGetOutClass(SConnection *self);@\\
|
|
\mbox{}\verb@ int SCGetGrab(SConnection *pCon);@\\
|
|
\mbox{}\verb@/********************* simulation mode ************************************/@\\
|
|
\mbox{}\verb@ void SCSetSimMode(SConnection *pCon, int value);@\\
|
|
\mbox{}\verb@ int SCinSimMode(SConnection *pCon);@\\
|
|
\mbox{}\verb@/* **************************** Invocation ******************************** */@\\
|
|
\mbox{}\verb@ int SCInvoke(SConnection *self,SicsInterp *pInter,char *pCommand);@\\
|
|
\mbox{}\verb@ @\\
|
|
\mbox{}\verb@/*************************** User Command **********************************/@\\
|
|
\mbox{}\verb@ int ConfigCon(SConnection *pCon, SicsInterp *pSics, void *pData,@\\
|
|
\mbox{}\verb@ int argc, char *argv[]); @\\
|
|
\mbox{}\verb@ int ConSicsAction(SConnection *pCon, SicsInterp *pSics, void *pData,@\\
|
|
\mbox{}\verb@ int argc, char *argv[]); @\\
|
|
\mbox{}\verb@ @\\
|
|
\mbox{}\verb@@$\diamond$
|
|
\end{list}
|
|
\vspace{-1ex}
|
|
\footnotesize\addtolength{\baselineskip}{-1ex}
|
|
\begin{list}{}{\setlength{\itemsep}{-\parsep}\setlength{\itemindent}{-\leftmargin}}
|
|
\item Macro referenced in scrap ?.
|
|
\end{list}
|
|
\end{minipage}\\[4ex]
|
|
\end{flushleft}
|
|
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}
|
|
|
|
\begin{flushleft} \small
|
|
\begin{minipage}{\linewidth} \label{scrap3}
|
|
\verb@"conman.h"@ {\footnotesize ? }$\equiv$
|
|
\vspace{-1ex}
|
|
\begin{list}{}{} \item
|
|
\mbox{}\verb@@\\
|
|
\mbox{}\verb@/*--------------------------------------------------------------------------@\\
|
|
\mbox{}\verb@ C O N N E C T I O N O B J E C T@\\
|
|
\mbox{}\verb@@\\
|
|
\mbox{}\verb@ This file defines the connection object data structure and the interface to@\\
|
|
\mbox{}\verb@ this data structure. This is one of the most important SICS components.@\\
|
|
\mbox{}\verb@@\\
|
|
\mbox{}\verb@@\\
|
|
\mbox{}\verb@ Substantially revised from a prior version.@\\
|
|
\mbox{}\verb@@\\
|
|
\mbox{}\verb@ Mark Koennecke, September 1997@\\
|
|
\mbox{}\verb@@\\
|
|
\mbox{}\verb@ Mark Koennecke, Aprl 2003@\\
|
|
\mbox{}\verb@@\\
|
|
\mbox{}\verb@ copyright: see copyright.h@\\
|
|
\mbox{}\verb@----------------------------------------------------------------------------*/@\\
|
|
\mbox{}\verb@#ifndef SICSCONNECT@\\
|
|
\mbox{}\verb@#define SICSCONNECT@\\
|
|
\mbox{}\verb@#include <stdio.h>@\\
|
|
\mbox{}\verb@#include "costa.h"@\\
|
|
\mbox{}\verb@#include "SCinter.h"@\\
|
|
\mbox{}\verb@#include "network.h"@\\
|
|
\mbox{}\verb@#include "obdes.h"@\\
|
|
\mbox{}\verb@@\\
|
|
\mbox{}\verb@#define MAXLOGFILES 10@\\
|
|
\mbox{}\verb@@$\langle$condat {\footnotesize ?}$\rangle$\verb@@\\
|
|
\mbox{}\verb@#include "nserver.h"@\\
|
|
\mbox{}\verb@@$\langle$conint {\footnotesize ?}$\rangle$\verb@@\\
|
|
\mbox{}\verb@@\\
|
|
\mbox{}\verb@#endif @\\
|
|
\mbox{}\verb@@$\diamond$
|
|
\end{list}
|
|
\vspace{-2ex}
|
|
\end{minipage}\\[4ex]
|
|
\end{flushleft}
|