146 lines
7.0 KiB
OpenEdge ABL
146 lines
7.0 KiB
OpenEdge ABL
\subsection{The Network Reader}
|
|
The network readers task is to read incoming messages for the SICS server.
|
|
These may come in four main forms.
|
|
\begin{itemize}
|
|
\item connection requests
|
|
\item commands
|
|
\item interrupts
|
|
through a command channel
|
|
\item interrupt messages on the UDP port.
|
|
\end{itemize}
|
|
A prior
|
|
version of SICS had a select system call for each of these cases. It was
|
|
found, that the code spent most of its time in the select system call
|
|
thus introducing a major performance problem.
|
|
|
|
The select system call can handle more then one file descriptor in one call.
|
|
This is exactly what this module handles. It does a global select on
|
|
all open sockets and forwards any pending data to appropriate handlers.
|
|
This scheme brought a drastic
|
|
performance improvement.
|
|
|
|
Each of the messages to SICS is handled
|
|
differently:
|
|
|
|
A connection request will be validated, a new connection object will be
|
|
created and a new task for this connection object will be started.
|
|
|
|
A command will be placed in the appropriate command stack for the task
|
|
belonging to this connection to work on in a later stage. The netreader will
|
|
also take care that all commands are complete, this is the terminator
|
|
\verb+\n+ or \verb+\r+ has been sent.
|
|
|
|
Both forms of interrupt will be interpreted and a suitable signal
|
|
will be sent to all running tasks if the interrupt request is valid.
|
|
|
|
In order to perform his tasks the network reader needs to maintain a list of
|
|
all open sockets and their types. Additionally it needs to know about the
|
|
SICS tasker.
|
|
|
|
The early version of SICS only supported connections on a plain
|
|
socket. This feauture is not used any more in favour of the Telnet
|
|
option described below. However, as this may be used to transport
|
|
binary data, the obsolete code has not been removed.
|
|
|
|
Support for the internet TCP/IP standard telnet protocoll has been added in
|
|
January 1998. Telnet things need to be handled differently, therefore two
|
|
more socket types have been defined: A telnet listen socket on which
|
|
requests for telnet connections are listened for, and a telnet command
|
|
socket which actually process the telnet messages.
|
|
|
|
Support for user sockets was added in February 1998. User sockets provides a
|
|
primitive interface to the network readers monitoring functions. This is
|
|
part of a solution to one problem which can occur in SICS: The whole server
|
|
is blocked if one of the serial devices is slow in responding. User sockets
|
|
now provide a method for client code to register a socket for monitoring
|
|
with the network reader and find out if data is pending at it. This support
|
|
is provided by the functions: NetReadRegisterUserSocket,
|
|
NetReadRemoveUserSocket, NetReadReadable and NetReadResetUser described
|
|
below. NetReadWait4Data is a special wait function which waits for data to
|
|
come in on a user socket. This function is problematic with dynamically
|
|
creates and deleted objects such as environment device objects. Its use is
|
|
therefore no longer recommended.
|
|
|
|
In January 2009 a new asynchronous I/O structure was devised. This makes most of
|
|
NetReader obsolete. However, it was decided to keep the old structure for the
|
|
time being. A new function, NetReadInstallANETPort was added to install server
|
|
ports for the new system.
|
|
|
|
Thus the interface looks like this:
|
|
|
|
@d nrint @{
|
|
/*--------------------------------------------------------------------------*/
|
|
typedef struct __netreader *pNetRead;
|
|
typedef enum {naccept, command, udp, user, taccept, tcommand} eNRType;
|
|
/*--------------------------------------------------------------------------*/
|
|
pNetRead CreateNetReader(pServer pServ, int iPasswdTimeout,
|
|
int iReadTimeout);
|
|
void DeleteNetReader(void *pData);
|
|
/*--------------------------------------------------------------------------*/
|
|
int NetReadRegister(pNetRead self, mkChannel *pSock, eNRType eType,
|
|
SConnection *pCon);
|
|
int NetReadRegisterUserSocket(pNetRead self, int iSocket);
|
|
int NetReadRemove(pNetRead self, mkChannel *pSock);
|
|
int NetReadRemoveUserSocket(pNetRead self, int iSocket);
|
|
/*-------------------------------------------------------------------------*/
|
|
int NetReaderTask(void *pReader);
|
|
void NetReaderSignal(void *pUser, int iSignal, void *pSigData);
|
|
int NetReadWait4Data(pNetRead self, int iSocket);
|
|
int NetReadReadable(pNetRead self, int iSocket);
|
|
int NetReadResetUser(pNetRead self, int iSocket);
|
|
/*--------------------------------------------------------------------------*/
|
|
int NetReadInstallANETPort(pNetRead self, eNRType eType, int iPort);
|
|
@}
|
|
|
|
This starts off with the definition of a data type for the net reader and an
|
|
enum which denotes the possible types of connections.
|
|
\begin{description}
|
|
\item[CreateNetReader] sets a new net reader up. Only parameter is a pointer
|
|
to the task manager to use while creating new connections. iPasswdTimeout
|
|
is the period in which a client is expected to send his userid/password
|
|
pair. iReadTimeout is the time to wait on the select statement for a
|
|
channel to become readable. Both time values are specified in milliseconds.
|
|
\item[DeleteNetReader] deletes the net reader and all its data structures.
|
|
Must be called in order to free all memory.
|
|
\item[NetReadRegister] register the channel pSock of type eType with the net
|
|
reader self. The parameter pData will only be interpreted for connections
|
|
of type command. It must point to the command stack belonging to the
|
|
connection which registers this socket.
|
|
\item[NetReadRegisterUserSocket] registers a socket from within SICS foth
|
|
the network reader. The client code to this module may then find out with a
|
|
call to NetReadReadable if data is pending on this socket. This a
|
|
convenience wrapper to NetReadRegister.
|
|
\item[NetReadRemove] removes the socket pSock from the net reader. This must
|
|
be done when closing the socket, otherwise the net reader will continue
|
|
checking for pending data on this socket.
|
|
\item[NetReadRemoveUserSocket] removes a user socket from
|
|
monitoring. Again, this is a vonvenience wrapper around NetReadRemove.
|
|
\item[NetReaderTask] is the net reader task function which will be
|
|
registered with the task manager. This function builds the select
|
|
mask, does the select and forwards incoming data to the appropriate
|
|
handler functions. These are not documented here, as they are file
|
|
static function in nread.c.
|
|
\item[NetReaderSignal] is the signal handler for the net reader. It
|
|
just stops the NetReaderTask when the SICS server is run down.
|
|
\item[NetReadReadable] returns 1 if data is pending at the user socket or 0
|
|
if not.
|
|
\item[NetReadResetUser] resets a user socket to not readable.
|
|
\end{description}
|
|
|
|
@o nread.h @{
|
|
/*------------------------------------------------------------------------
|
|
N E T R E A D E R
|
|
|
|
This module will check for pending requests to the SICS server and
|
|
initiate apropriate actions.
|
|
|
|
Mark Koenencke, September 1997
|
|
|
|
copyright: see copyright.h
|
|
|
|
----------------------------------------------------------------------------*/
|
|
#ifndef SICSNETREADER
|
|
#define SICSNETREADER
|
|
@<nrint@>
|
|
#endif
|
|
@} |