HTEvent module for more information
on the arguments. Likewise if you are on for example a Windows NT platform
then use the following functions:
extern int HTEvent_RegisterTTY (SOCKET sockfd, HTRequest * request, SockOps ops, HTEventCallBack *cbf, HTPriority priority); extern int HTEvent_UnRegisterTTY(SOCKET sockfd, SockOps ops);
The return code from an event handler is simple but very important. There are two allowed values:
It helps understanding event handlers if you think of the Library as a coke machine (the ones with a coin slot only - the ones which also has a bill slot work differently!) Event handlers are the coin slot on top where you can request a service from the library. You are guaranteed that the machine never returns any coins to you the same way - they always come out at the bottom of the machine. This means that the Library always returns "Thanks, I have received your request - please look for the response at the bottom" on any request started from within an event handler. In the library case the result is always returned in the request termination handler that is the "bottom" of the Library machine.
The application can register a callback function that is called whenever a request has terminated, regardless. The callback function can furthermore be registered to be called regardless of the status code or on upon a specific codes. The set of status codes is:
HT_LOADED
HT_INTERRUPTED
HT_ERROR
HT_NO_DATA
HT_RETRY
extern time_t HTRequest_retryTime (HTRequest * request);
Return codes are not used from termination handlers.
If you have additional headers that you want to experiment with you can register a header parser to handle all unknown headers. This handler is called whenever an unknown header is encountered when parsing the object header. If the returns YES then the MIME parser stores the metainformation in the anchor object if self so that it can be found at a later point in time. If the handler returns NO, then the header is discarded.
The header passed to the call back function will be in normal NULL terminated C string without any CRLF. The line will also be unwrapped so that it is easier to parse for the call back function.
typedef int HTMIMEHandler (HTRequest * request, char * header); extern int HTMIME_register (HTMIMEHandler * cbf); extern int HTMIME_unRegister (void);
You can register a call back function together with a timeout that is used in the select call of the event loop. When the select() call times out, the call back function is called. The registration can either be so that the call back always is called when that the select call times out or only when Library sockets are in use.
typedef int HTEventTimeout (HTRequest *); extern BOOL HTEvent_registerTimeout (struct timeval *tp, HTRequest * request, HTEventTimeout *tcbf, BOOL always);
The Access module has a set of functions that works as a user interface to the request manager. You can call the request manager directly but often it is simpler to use the Access module. As mentioned, the request manager returns immediately and the result of the request is handled back to the application using the termination handlers.
The Library's represents internally location strings as URLs which means that they always are escaped. Only when it is required to access a resource are they unescaped, for example via FTP. All location strings passed to the Library are also treated as URLs which means that they must be escaped already. Hence in the case of the request methods mentioned aboce, all URL arguments must be escaped if the resource is to be found.
Most often this is only a problem when people type in location strings directly, for example using "goto location" etc. In the Escape module the Library provides two functions for escaping location strings into URLs and unescaping URLs into location strings:
typedef enum _HTURIEncoding {
URL_XALPHAS = 0x1,
URL_XPALPHAS = 0x2,
URL_PATH = 0x4
} HTURIEncoding;
extern char * HTEscape (const char * str, HTURIEncoding mask);
extern char * HTUnEscape (char * str);
Multiple simultaneous requests can be started at any time from within an event handler. It is simply a question of calling one of the load functions in the Access module. The Library keeps a request queue where all active requests are kept. The application can define the maximum number of open sockets that can be open at any one time. This number is by default 6 but can be changed using the following functions:
extern BOOL HTNet_setMaxSocket (int newmax); extern int HTNet_maxSocket (void);
If there are no free sockets available the request is put into a pending queue and started as soon as possible.
When multiple requests can be initiated simultaneously it is in general not possible to predict the order that the results return to the application. This is a function of the size of the individual data objects, net work speed etc. In order to keep track of ordering of the requests, for example in the history list, it is necessary to put them into some kind of context. The Library provides the hooks for maintaining a context together with the Request object by the following methods:
typedef int HTRequestCallback (HTRequest * request, void *param); extern void HTRequest_setCallback (HTRequest *request, HTRequestCallback *cb); extern HTRequestCallback *HTRequest_callback (HTRequest *request);
The callback function can be passed an arbitrary pointer (the void part) which can describe the context of the current request structure. If such context information is desired then it can be set using the following methods:
extern void HTRequest_setContext (HTRequest *request, void *context); extern void *HTRequest_context (HTRequest *request);
There is no limit to the definition of a context data object and the memory management if entirely up to the application. The Request object simply carries the information around.
Any request can be interrupted from an event handler by calling either of the functions (the first kills a specific request, the second is more radical and kills them all):
extern BOOL HTRequest_kill (HTRequest * request); extern BOOL HTNet_killAll (void);
The library has a set of modules that are not called from within the library at all but can be used by the application. Two examples are a History manager and a Log manager that provides functionality for keeping a history list of visited objects and to provide logging of the results. The application is free to use there modules but does not have to.
The library has a basic User Messages and Prompts module which is intended for the Line Mode Browser. In case you are building a GUI client you would probably want to write your own version using windows etc. This can be done by overriding the module in the Library with your own that has the same set of functions as described in the User's Guide.
This is a short set of recommendation on when to free objects in memory.