Protocol Implementations
There is a protocol implementation for each protocol that netlib can handle.
The protocol implementation defines how to negotiate a transaction over
a connection. The ftp protocol implementation knows how to negotiate (ask
for and handle directory listings, send and receive files, etc.) with an
ftp server. The http protocol knows how to negotiate with an http server.
All the specifics inherent in a protocol specification are implemented
in that protocol's respective implementation. Netlib maintains a list of
the protocols that have registered themselves, and consults this list in
a call to NET_GetURL() to hook-up the appropriate
protocol implementation with the given url.
A protocol implementation is a NET_ProtoImpl struct defined in ns/lib/libnet/mkgeturl.h.
This struct simply consists of four function pointers; an initialization
function, a processing function, an interrupt function, and a cleanup function.
The Initialization function
The initialization function must allocate, initialize (this includes acquiring
a cached socket or creating a new one), and associate with the active entry,
the connection data. One of the responsibilities of the connection data
is to maintain the current state of the load. At the end of initialization
a call to the protocol implementation's process routine is made to initiate
the load.
The Processing function
The processing function drives the protocol implementation's state machine
and is repeatedly called from a main application loop, until the load is
complete. A url load can complete is a single call to the process function,
or in many. It determines the current state of the load (by consulting
the state member of the connection data) and calls the appropriate function.
Depending on the result of that call it can also determine what the next
state should be (next state can also be determined by the processing help
routines that do the actual work (parsing, data push and receive, etc.)).
The Interrupt function
It's the responsibility of the interrupt function to properly stop a load.
It must ensure that memory associated with the load is freed and that the
ActiveEntry that was interrupted is removed from the netlib active entry
list. The Interrupt function itself can do all of this, or (as is the more
common case) it can simply set the next state of the connection data to
the protocol implementations FREE, COMPLETE, or CLEANUP routine.
The Cleanup function
The cleanup function simply free's any memory associated with a given active
entry load and removes it from the netlib net_EntryList.
Pluggable Protocols
As of the first free source drop netlib does not allow protocols to be
dynamically loaded. This means protocols via plugins are not possible.
The State Machine
The mechanism utilized by all the current (as of the first free source
release) netlib protocol implementations to send and receive data is a
state machine. Each url to be loaded is placed in an active entry which
is then placed in netlib's active entry list. An active entry also contains
some connection data which maintains the state of the url load at any point
in time. This state is updated throughout the url load. For example, for
an http url, one of the things the http protocol implementation's initialization
routine does is set the next state to HTTP_SEND_REQUEST or HTTP_BEGIN_UPLOAD_FILE.
This way, when the http protocol implementation's process routine is called,
it knows what to do, send the request or begin uploading the file. Basically
all a protocol implementation's process routine consists of is a switch
statement that checks the current state of the active entry and makes makes
appropriate function calls. Because the state is maintained in the active
entry, netlib can return without completing the entire url load. The next
time that url is processed, it simply picks up where it left off previously.
Judson Valeski,
1998