Home   Info   Documentation   Installation   Configuration   History   Download   Mailing list   Feedback 

 Up - Design   Back - Protocol 

API Library

While this protocol can be implemented in any language capable of handling binary data and transferring data through TCP/IP connections, the API library is written in ANSI C with the purpose to be used in any environment, supporting that language or to be ported easily into any other language, if for some reason the use of original C implementation will be less desirable. While fhttpd itself is under GNU General Public License and some its components are under GNU General Library Public license, API library (servproc.c and servproc.h files) are under BSD-style license, so it's allowed to make derivative works and incorporate the code in any applications without creating additional distribution restrictions.

Data Structures

struct rline


struct rline{               /* request line */
long paramc;                /* parameters counter*/
char **params;              /* parameters*/
};
Common representation for line block or parsed HTTP from data or the parsed parameters list from URL. Used directly by the user's program and internally. While params isn't declared const modification of that data by the user is undesirable.

struct request


struct request{             /* parsed request */

/* Primary */
long buffsize;              /* buffer size */
char *buffer;               /* input buffer */
long id;                    /* request ID */
long reqtype;               /* request type */
long rlsize;                /* request line size */
char *rl;                   /* request line */
long nlines;                /* number of lines in request */
struct rline *lines;        /* request lines */
long databuffsize;          /* data buffer size */
char *databuffer;           /* data buffer */
int fd;                     /* file descriptor (if any) */

/* Secondary */
long nform;                 /* number of lines in form (if any) */
struct rline *form;         /* lines from form (if any) */
long narg;                  /* number of arguments (if any) */
struct rline *arg;          /* arguments (if any) */
const char *accept;         /* "Accept" */
const char *user_agent;     /* "User-Agent" */
const char *content_type;   /* "Content-type" */
const char *server_software;/* server software */
const char *server_name;    /* server hostname */
int server_port;            /* server port */
const char *script_name;    /* script name (if any) */
const char *script_name_resolved; /* resolved script name (if any) */
const char *query_string;   /* query string (if any) */
const char *remote_addr;    /* remote address (dot notation) (if any) */ 
const char *remote_host;    /* remote address (host/domain) (if any) */
const char *remote_user;    /* remote user (from security) (if any) */
int ver_major;              /* HTTP major version number (if any) */
int ver_minor;              /* HTTP minor version number (if any) */
int method;                 /* request method */
time_t ifmodifiedsince;     /* "If-Modified-Since" */
int keepalive;              /* keep-alive option requested */
struct http_server *httpserver; /* server */
struct httpclientsession *session; /* session (if any) */
const void *appinfo;        /* application info (if any) */
struct request *next;       /* next item pointer */
struct request *prev;       /* previous item pointer */
};
Representation for the parsed request, sent from the HTTP client. Allocated and returned by readrequest() or getrequest(), should be deallocated by deleterequest(), used by multiple functions and user's program.

All numeric fields are in local format, NOT in network byte order. const means const and what isn't const, is still a bad idea to modify.

"Primary" data is received from the server, "Secondary" fields are the result of parsing in parserequest()

readrequest() reads request from the server and makes this structure without parsing forms or arguments, so narg, arg, nform, form and session are zeroed. parserequest() checks if content_type is "application/x-www-form-urlencoded" and method is POST, and if so parses the form. data is changed in the proces of parsing by replacing field separators with zeroes and decoding URL-encoded data.

parserequest() also parses arguments the same way.

getrequest() calls readrequest(), then if it succeeds, calls parserequest().

struct httpresponse


struct httpresponse{
long buffsize;              /* allocated buffer size */
long datasize;              /* data size */
char *buffer;               /* buffer */
long id;                    /* request id */
int fd;                     /* file descriptor (if any) */
struct httpresponse *header;/* header of this response (if any) */
struct httpresponse *body;  /* body of this response (if it's a header) */
};
Representation of the response, prepared to be sent to the HTTP server or client. Response with the header is represented by two such structures -- for the response header and for response body. It allows to make the header (by makestandardheader() or makesessionheader()) after the response data is ready.

Allocated and returned by createresponse(), should be deallocated by deleteresponse(), used by API library functions.

struct multipartsegment


struct multipartsegment{
struct multipartresponse *parentresponse;
                            /* multipart response, this segment belongs to */
struct httpresponse *s_response; /* response segment body */
struct multipartresponse *m_response; /* response segment body (if multipart)*/
struct multipartsegment *next; /* next segment */
struct multipartsegment *prev; /* previous segment */
};

struct multipartresponse


struct multipartresponse{
long headerbuffsize;        /* allocated header buffer size */
long headerdatasize;        /* header data size */
long id;                    /* request id */
int fd;                     /* file descriptor (if any) */
char *headerbuffer;         /* header buffer */
char *boundary;             /* boundary buffer */
int boundarysize;           /* size of the boundary buffer */
int nsegments;              /* number of segments */
struct multipartsegment *first; /* first segment */
struct multipartsegment *last;  /* last segment */
};
Representation of the MIME multipart response and its segment. Multipart response consists of multiple segments that have headers (but no code) and separated by boundary lines (see MIME RFC 1521). Multipart responses are primarily used for the Netscape-specific server push with the "multipart/x-mixed-replace" content type.

struct multipartresponse is allocated and returned by createmultipartresponse() and should be deallocated by deletemultipartresponse(), struct multipartsegment is allocated and returned by createmultipartsegment() and should be deallocated by deletemultipartsegment().

makemultipartheader() writes multipart response header in a way similar to makestandardheader(), although it doesn't include Content-Length in the header, so it can be called before the response is ready.

struct httpclientsession


struct httpclientsession{
struct request *currequest; /* current request */
char *useragent;            /* "User-Agent" */
char *username;             /* remote user (from security) (if any) */
int ver_major;              /* HTTP major version number (if any) */
int ver_minor;              /* HTTP minor version number (if any) */
long useragentcap;          /* capabilities, not supported */
time_t created;             /* created */
time_t lastaccessed;        /* last accessed */
char *cookie;               /* cookie assigned to the session */
int cookieinurl;            /* cookie in URL for non-cookie-supporting
                               browsers */
struct http_server *httpserver; /* server */
const void *appinfo;        /* application info (if any) */
struct httpclientsession *next; /* next item pointer */
struct httpclientsession *prev; /* previous item pointer */
};
Representation of the session, attached to some session identifier, included in URL or used as HTTP cookie. Created by createsession(), should be deallocated by deletesession(), used by multiple session-supporting functions.

Session support is provided, but it isn't mandatory for the API functionality, and it doesn't disallow the program to use its own means to identify the user or session.

Two pointers to other struct httpclientsession's are used to support the list of sessions, they are handled automatically and should not be used by the user's program.

struct http_server


struct http_server{
int infd; /* file descriptors, connected to server */
int outfd;
char *app_progname;
char *app_name;
char *app_hostname;
char *app_username;
char *app_password;
int app_port;
int app_hostname_allocated;
int app_username_allocated;
int app_password_allocated;
struct httpclientsession *client_sessions;
struct httpclientsession *client_last_session;
struct request *requests;
struct request *lastrequest;
int session_created; /* will be 1 after findsession(???,1),
                     if the session was created */
int session_expired; /* will be 1 after findsession(),
                     if the cookie from expired session was found */
long capabilities;
int exitflag;
int use_af_unix_socket; /* use AF_UNIX socket */
int *connectionfds;
int connectionfdshead;
int connectionfdstail;
int connectionfdscount;
int connectionfdsallocated;
};
Representation of the HTTP server. Usually only one server is used, although multiple ones are allowed. Allocated by createserver(), deallocated by deleteserver() and usually initialized by servproc_init().

Functions

Server descriptors manipulation

struct http_server *createserver(void);
Create server descriptor

void deleteserver(struct http_server *server);
Delete server descriptor

Requests manipulation

struct request *readrequest(struct http_server *server);
Get request from the server, return request structure

void parserequest(struct request *req);
Parse request

struct request *getrequest(struct http_server *server);
Get request from the server, parse, return request structure

void deleterequest(struct request *req);
Delete request

Reply to server

void sendreply(struct http_server *server,long opnum,long size,long id,char *s);
Send reply

void sendlinereply(struct http_server *server,long opnum,long id,char *s);
Send reply from zero-terminated string

void finishreply(struct http_server *server,long id);
Finish reply

void finishdropreply(struct http_server *server,long id);
Finish reply, drop client

void setcapabilities(struct http_server *server,long newcap);
Set capabilities

void requestexit(struct http_server *server,int newexitflag);
Request/cancel exit

HTTP response

struct httpresponse *createresponse(int initsize,long id,int fd,int withheader);
Create response

void deleteresponse(struct httpresponse *response);
Delete response

int writetoresponse(struct httpresponse *response,const char *buffer,long l);
Write data to response

int putlinetoresponse(struct httpresponse *response,const char *buffer);
Write zero-terminated string to response

int putmlinetoresponse(struct httpresponse *response,const char *buffer);
Write zero-terminated string, converted to HTML, to response

int putulinetoresponse(struct httpresponse *response,const char *buffer,char except);
Write URL-encoded zero-terminated string to response

int puturltoresponse(struct httpresponse *response,struct httpclientsession *session,const char *protocol,const char *host,int port,const char *path,const char *arg,const char *fragment);
Write URL to response

int putlinetoheader(struct httpresponse *response,const char *buffer);
Write zero-terminated string to response header

int makemyurl(char *dst,struct request *req,int maxsize, struct httpclientsession *session,char *arg);
Fill buffer by requested URL (arguments replaced)

int putmyurltoresponse(struct httpresponse *response,struct request *req,struct httpclientsession *session,char *arg);
Write requested URL (arguments replaced) to response

int putmyurltoheader(struct httpresponse *response,struct request *req,struct httpclientsession *session,char *arg);
Write requested URL (arguments replaced) to header

int makestandardheader(struct httpresponse *response,int code,const char *contenttype,const char *servername,int keepalive);
Make "standard" HTTP response header

int makesessionheader(struct httpresponse *response,int code,const char *contenttype,const char *servername,struct httpclientsession *session,int keepalive);
Make HTTP response header for session

int sendresponse(struct http_server *server,struct httpresponse *response);
Send response with header

int sendshortresponse(struct http_server *server,struct httpresponse *response);
Send response without header

int finishresponse(struct http_server *server,struct httpresponse *response);
Finish response

int finishdropresponse(struct http_server *server,struct httpresponse *response);
Finish response, drop client

int redirect(struct request *req,char *destination);
Make, send and delete redirect message

Multipart response

struct multipartresponse *createmultipartresponse(long id,int fd);
Create multipart response

void deletemultipartresponse(struct multipartresponse *response,int clean);
Delete multipart response

struct multipartsegment *createmultipartsegment(struct multipartresponse *response,struct httpresponse *responsebody);
Create multipart response segment

void deletemultipartsegment(struct multipartsegment *segment,int clear);
Delete multipart response segment

int writetomultipartresponseheader(struct multipartresponse *response,const char *buffer,long l);
Write data to multipart response header

int putlinetomultipartheader(struct multipartresponse *response, const char *buffer);
Write zero-terminated string to multipart response header

int makemultipartheader(struct multipartresponse *response,int code, const char *contenttype,const char *servername,int keepalive);
Make HTTP multipart response header

int sendmultipartresponseheader(struct http_server *server,struct multipartresponse *response);
Send multipart response header

int sendmultipartresponsesegment(struct http_server *server,struct multipartsegment *segment);
Send multipart response segment

int sendmultipartresponsefinish(struct http_server *server,struct multipartresponse *response);
Send multipart response last boundary

int sendmultipartresponse(struct http_server *server,struct multipartresponse *response);
Send multipart response

Session

struct httpclientsession *createsession(struct request *req,const void *appinfo,char *cookie);
Create client session

int selectinstancesession(,struct httpclientsession *session);
Tell the server to send all requests from the client session to this instance

int deselectinstancesession(struct httpclientsession *session);
Delete instance selection

int redirecttosession(struct httpclientsession *session);
Make, send and delete redirect message to create the session identifier in URL

void deletesession(struct httpclientsession *mysession);
Delete client session (and its request, if any)

struct httpclientsession *findsessiontoexpire(struct http_server *server,int maxcount,int maxlife,int maxidle);
Find next session to expire

struct httpclientsession *findsession(struct request *req,int autocreate);
Find client session by request

Initialization

int connecttohttpd(char *host,int port,char *user,char *password,char *appname,int messagestostderr,int askpassword);
Connect to remote HTTP server

void errtosyslog(struct http_server *server,char *s);
Log an error through syslog (not recommended for regular application errors)

int servproc_init(struct http_server *server,int human,int argc,char **argv);
Smart[ass] application initialization

Internal service functions

signed char base64char(signed char c);
Encode BASE64 6-bit character

signed char char64value(signed char c);
Decode BASE64 6-bit character

void en64(char *dst,const char *src,long l);
BASE64 encode

unsigned long un64(char *s);
Decode BASE64-encoded data

int urlencode(char *dst,const char *src,char except);
URL-encode data

void unescape(char *s);
Decode URL-encoded data

char *linefromtime(char *s,time_t t);
Make standard time string for HTTP

void makeid(char *dst);
Make random ID string

int readline(int h,char *buffer,int length);
Read line (for login)


Alex Belits
Last modified: Wed Jun 23 02:06:36 PDT 1999
 Up - Design   Back - Protocol 

 Home   Info   Documentation   Installation   Configuration   History   Download   Mailing list   Feedback