\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 #include "costa.h" #include "SCinter.h" #include "network.h" #include "obdes.h" #define MAXLOGFILES 10 @ #include "nserver.h" @ #endif @}