/* ** Server Processes Library header file ** servproc.h Copyright (C) 1995, 96 Alex Belits ** This code is a part of fhttpd distribution */ #ifndef INCLUDED_SERVPROC_H #define INCLUDED_SERVPROC_H #include #include #ifdef AIX4 #include #else #include #endif #include #include #include #include #include #include #include #ifdef AIX #include #endif #include #include #include /* for ALIGN macro needed by CMSG_DATA */ #include #include #include #include #include #include /* Requests from fhttpd to the process */ #define FHTTPD_REQUEST 1 /* request */ #define FHTTPD_DISCONNECT 2 /* client disconnected */ #define FHTTPD_ACK 3 /* acknowledge */ #define FHTTPD_EXITOK 4 /* exit ok, no requests will be directed to this instance until exit cancelled */ #define FHTTPD_LOG_REQUEST 5 /* log request */ /* Requests from the process to fhttpd */ #define FHTTPD_FINISH 0 /* finish response */ #define FHTTPD_SEND 1 /* send data */ #define FHTTPD_INST_SELECT 2 /* add selection configuration line */ #define FHTTPD_INST_DESELECT 3 /* remove selection configuration line */ #define FHTTPD_INST_CAP 4 /* set instance capabilities */ #define FHTTPD_FINISH_DROP 5 /* finish response and drop connection */ #define FHTTPD_INST_EXITREQ 6 /* request or cancel exit (server will return FHTTPD_EXITOK for exit) */ #define FHTTPD_LOG_MESSAGE 7 /* message into log */ /* Capabilities */ #define APP_CAP_KEEPALIVE 1 /* application instance supports Keep-Alive */ #define APP_CAP_ACKFINISH 2 /* acknowledge finished blocks */ /* Methods */ #define APP_METHOD_UNKNOWN 0 #define APP_METHOD_GET 1 #define APP_METHOD_HEAD 2 #define APP_METHOD_POST 3 #define APP_METHOD_PUT 4 /* Errors */ /* Connection to remote server */ #define APP_ERR_INSANE -1 /* Sanity check failed */ #define APP_ERR_HUMAN -2 /* Manual start with wrong parameters */ #define APP_ERR_DAEMON -3 /* Non-manual start with wrong parameters */ #define APP_ERR_AUTH -4 /* Authentication error */ #define APP_ERR_CONFIG -5 /* Unreadable configuration */ #define APP_ERR_READ -6 /* Socket read error */ #define APP_ERR_HOSTNAME -7 /* Wrong server hostname */ #define APP_ERR_SOCKET -8 /* Socket creation error */ #define APP_ERR_CONNECT -9 /* Connect to server failed */ #define APP_ERR_APPCONNECT -10 /* Application connected to the wrong server */ #define APP_ERR_USER -11 /* Username rejected */ #define APP_ERR_PASSWORD -12 /* Incorrect password */ #define APP_ERR_APPLICATION -13 /* Application instance request rejected */ #define ROOT_HTTPPROCRC "/usr/local/etc/httpprocrc" /* where root keeps its processes' parameters */ #define USER_HTTPPROCRC ".httpprocrc" /* where users keep their processes' parameters */ /* Request line */ struct rline{ /* request line */ long paramc; /* parameters counter*/ char **params; /* parameters*/ }; struct httpclientsession; /* 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 */ }; /* Response to the client */ 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) */ }; /* Multipart responses */ struct multipartresponse; /* Multipart response segment */ 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 */ }; /* Multipart response */ 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 */ }; /* Client session */ 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 */ }; /* 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; }; /* Functions */ /* Internal service functions, can be used for something else */ 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 */ /* Server descriptors manipulations */ /************************************************** ** Create server descriptor **************************************************/ struct http_server *createserver(void); /************************************************** ** Delete server descriptor **************************************************/ void deleteserver(struct http_server *server); /* Requests manipulation */ /************************************************** ** Get request from the server ** return request structure **************************************************/ struct request *readrequest(struct http_server *server); /************************************************** ** Parse request **************************************************/ void parserequest(struct request *req); /************************************************** ** Get request from the server, ** parse, return request structure **************************************************/ struct request *getrequest(struct http_server *server); /************************************************** ** Delete request **************************************************/ void deleterequest(struct request *req); /* Reply to server */ /************************************************** ** Send reply **************************************************/ void sendreply(struct http_server *server,long opnum,long size,long id, char *s); /************************************************** ** Send reply from zero-terminated string **************************************************/ void sendlinereply(struct http_server *server,long opnum,long id,char *s); /************************************************** ** Finish reply **************************************************/ void finishreply(struct http_server *server,long id); /************************************************** ** Finish reply, drop client **************************************************/ void finishdropreply(struct http_server *server,long id); /************************************************** ** Set capabilities **************************************************/ void setcapabilities(struct http_server *server,long newcap); /************************************************** ** Request/cancel exit **************************************************/ void requestexit(struct http_server *server,int newexitflag); /************************************************** ** Log message **************************************************/ void logmessage(struct http_server *server,struct httpresponse *response, char *key,char *value); /* HTTP response */ /************************************************** ** Create response **************************************************/ struct httpresponse *createresponse(int initsize,long id,int fd, int withheader); /************************************************** ** Delete response **************************************************/ void deleteresponse(struct httpresponse *response); /************************************************** ** Write data to response **************************************************/ int writetoresponse(struct httpresponse *response,const char *buffer,long l); /************************************************** ** Write zero-terminated string to response **************************************************/ int putlinetoresponse(struct httpresponse *response,const char *buffer); /************************************************** ** Write zero-terminated string, converted to HTML, ** to response **************************************************/ int putmlinetoresponse(struct httpresponse *response,const char *buffer); /************************************************** ** Write URL-encoded zero-terminated string ** to response **************************************************/ int putulinetoresponse(struct httpresponse *response,const char *buffer, char except); /************************************************** ** Write URL 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 zero-terminated string to response header **************************************************/ int putlinetoheader(struct httpresponse *response,const char *buffer); /************************************************** ** Fill buffer by requested URL (arguments replaced) **************************************************/ int makemyurl(char *dst,struct request *req,int maxsize, struct httpclientsession *session,char *arg); /************************************************** ** Write requested URL (arguments replaced) to response **************************************************/ int putmyurltoresponse(struct httpresponse *response,struct request *req, struct httpclientsession *session,char *arg); /************************************************** ** Write requested URL (arguments replaced) to header **************************************************/ int putmyurltoheader(struct httpresponse *response,struct request *req, struct httpclientsession *session,char *arg); /************************************************** ** Make random ID string **************************************************/ void makeid(char *dst); /************************************************** ** Make "standard" HTTP response header **************************************************/ int makestandardheader(struct httpresponse *response,int code, const char *contenttype,const char *servername,int keepalive); /************************************************** ** Make HTTP response header for session **************************************************/ int makesessionheader(struct httpresponse *response,int code, const char *contenttype,const char *servername, struct httpclientsession *session,int keepalive); /************************************************** ** Send response with header **************************************************/ int sendresponse(struct http_server *server,struct httpresponse *response); /************************************************** ** Send response without header **************************************************/ int sendshortresponse(struct http_server *server, struct httpresponse *response); /************************************************** ** Finish response **************************************************/ int finishresponse(struct http_server *server,struct httpresponse *response); /************************************************** ** Finish response, drop client **************************************************/ int finishdropresponse(struct http_server *server, struct httpresponse *response); /************************************************** ** Make, send and delete redirect message **************************************************/ int redirect(struct request *req,char *destination); /* Multipart response */ /************************************************** ** Create multipart response **************************************************/ struct multipartresponse *createmultipartresponse(long id,int fd); /************************************************** ** Delete multipart response **************************************************/ void deletemultipartresponse(struct multipartresponse *response,int clean); /************************************************** ** Create multipart response segment **************************************************/ struct multipartsegment *createmultipartsegment( struct multipartresponse *response,struct httpresponse *responsebody); /************************************************** ** Delete multipart response segment **************************************************/ void deletemultipartsegment(struct multipartsegment *segment,int clear); /************************************************** ** Write data to multipart response header **************************************************/ int writetomultipartresponseheader(struct multipartresponse *response, const char *buffer,long l); /************************************************** ** Write zero-terminated string to multipart ** response header **************************************************/ int putlinetomultipartheader(struct multipartresponse *response, const char *buffer); /************************************************** ** Make HTTP multipart response header **************************************************/ int makemultipartheader(struct multipartresponse *response,int code, const char *contenttype,const char *servername,int keepalive); /************************************************** ** Send multipart response header **************************************************/ int sendmultipartresponseheader(struct http_server *server, struct multipartresponse *response); /************************************************** ** Send multipart response segment **************************************************/ int sendmultipartresponsesegment(struct http_server *server, struct multipartsegment *segment); /************************************************** ** Send multipart response last boundary **************************************************/ int sendmultipartresponsefinish(struct http_server *server, struct multipartresponse *response); /************************************************** ** Send multipart response **************************************************/ int sendmultipartresponse(struct http_server *server, struct multipartresponse *response); /* Session */ /************************************************** ** Create client session **************************************************/ struct httpclientsession *createsession(struct request *req, const void *appinfo,char *cookie); /************************************************** ** Tell the server to send all requests from the ** client session to this instance **************************************************/ int selectinstancesession(struct httpclientsession *session); /************************************************** ** Delete instance selection **************************************************/ int deselectinstancesession(struct httpclientsession *session); /************************************************** ** Make, send and delete redirect message ** to create the session identifier in URL **************************************************/ int redirecttosession(struct httpclientsession *session); /************************************************** ** Delete client session (and its request, if any) **************************************************/ void deletesession(struct httpclientsession *mysession); /************************************************** ** Find next session to expire **************************************************/ struct httpclientsession *findsessiontoexpire(struct http_server *server, int maxcount,int maxlife, int maxidle); /************************************************** ** Find client session by request **************************************************/ struct httpclientsession *findsession(struct request *req,int autocreate); /* Initialization */ /************************************************** ** Set logger application flag **************************************************/ void set_logapplication(int logapplication); /************************************************** ** Read line (for login) **************************************************/ int readline(int h,char *buffer,int length); /************************************************** ** Connect to remote HTTP server **************************************************/ int connecttohttpd(char *host,int port,char *user,char *password, char *appname,int messagestostderr,int askpassword); /************************************************** ** Log an error through syslog (not recommended ** for regular application errors) **************************************************/ void errtosyslog(struct http_server *server,char *s); /************************************************** ** Smart[ass] application initialization **************************************************/ int servproc_init(struct http_server *server,int human,int argc,char **argv); #endif