1 /*
2  *  Copyright (C) 2004-2008 Christos Tsantilas
3  *
4  *  This program is free software; you can redistribute it and/or
5  *  modify it under the terms of the GNU Lesser General Public
6  *  License as published by the Free Software Foundation; either
7  *  version 2.1 of the License, or (at your option) any later version.
8  *
9  *  This program is distributed in the hope that it will be useful,
10  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
11  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  *  Lesser General Public License for more details.
13  *
14  *  You should have received a copy of the GNU Lesser General Public
15  *  License along with this library; if not, write to the Free Software
16  *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
17  *  MA  02110-1301  USA.
18  */
19 
20 
21 #ifndef __SERVICE_H
22 #define __SERVICE_H
23 
24 #include "header.h"
25 #include "cfg_param.h"
26 #include "ci_threads.h"
27 
28 #ifdef __cplusplus
29 extern "C"
30 {
31 #endif
32 
33 /**
34  \defgroup SERVICES Services API
35  \ingroup API
36  * Services related API. For detailed information about implementing a service
37  * look the documentation of struct ci_service_module
38  */
39 
40 #define CI_MOD_NOT_READY  0
41 #define CI_MOD_DONE       1
42 #define CI_MOD_CONTINUE 100
43 #define CI_MOD_ALLOW204 204
44 #define CI_MOD_ALLOW206 206
45 #define CI_MOD_ERROR     -1
46 
47 #define MAX_SERVICE_NAME  63
48 #define MAX_SERVICE_ARGS 255
49 
50 #define CI_ISTAG_SIZE 32
51 #define SERVICE_ISTAG_SIZE 26 /* Deprecated */
52 #define CI_SERVICE_ISTAG_SIZE 26
53 #define XINCLUDES_SIZE    511 /* it is enough I think ....*/
54 
55 #define CI_XCLIENTIP              1
56 #define CI_XSERVERIP              2
57 #define CI_XSUBSCRIBERID          4
58 #define CI_XAUTHENTICATEDUSER     8
59 #define CI_XAUTHENTICATEDGROUPS  16
60 
61 struct ci_request;
62 struct ci_list;
63 
64 typedef struct  ci_service_module ci_service_module_t;
65 
66 enum SERVICE_STATUS {CI_SERVICE_NOT_INITIALIZED = -1,
67                      CI_SERVICE_OK = 0,
68                      CI_SERVICE_ERROR = 1
69                     };
70 
71 /*For internal use only*/
72 struct ci_option_handler {
73     char name[64];
74     int (*handler)(struct ci_request *);
75 };
76 
77 
78 /**
79  \typedef  ci_service_xdata_t
80  \ingroup SERVICES
81  *Stores required data and settings for a service
82  */
83 typedef struct ci_service_xdata {
84     ci_thread_rwlock_t lock;
85     int status;
86     struct ci_conf_entry *intl_srv_conf_table;
87     uint64_t xopts;
88     char ISTag[sizeof("ISTag: \"") + CI_ISTAG_SIZE + sizeof("\"") + 1];
89     char xincludes[XINCLUDES_SIZE+1];
90     char TransferPreview[MAX_HEADER_SIZE+1];
91     char TransferIgnore[MAX_HEADER_SIZE+1];
92     char TransferComplete[MAX_HEADER_SIZE+1];
93     int preview_size;
94     int max_connections;
95     int options_ttl;
96     int allow_204;
97     int allow_206;
98     int disable_206; /*even if service support it do not use 206*/
99     struct ci_list *option_handlers;
100     /*statistics IDS*/
101     int stat_bytes_in;
102     int stat_bytes_out;
103     int stat_http_bytes_in;
104     int stat_http_bytes_out;
105     int stat_body_bytes_in;
106     int stat_body_bytes_out;
107     int stat_reqmods;
108     int stat_respmods;
109     int stat_options;
110     int stat_allow204;
111 } ci_service_xdata_t;
112 
113 /**
114  \ingroup SERVICES
115  * Is the structure  which implements a service
116  *
117  * To implement a service someones needs to implement the member functions of
118  * this struct. These functions will be called by c-icap as follows:
119  *   - When a new request arrives for this service then the
120  *     ci_service_module::mod_init_request_data is called
121  *   - When the icap client sends preview data then the
122  *     ci_service_module::mod_check_preview_handler is called.
123  *     If this function return CI_MOD_ALLOW204 the ICAP transaction stops here.
124  *     If this function return CI_MOD_CONTINUE the ICAP client will send the
125  *     rest body data if exists.
126  *   - When he client starts sends more data then the
127  *     ci_service_module::mod_service_io is called multiple times
128  *     untill the client has send all the body data. The service
129  *     can start send data using this function to the client
130  *     before all data received
131  *   - When the client finishes sending body data the
132  *     ci_service_module::mod_end_of_data_handler is called
133  *   - While the icap client waits to read the body data from
134  *     the c-icap then the ci_service_module::mod_service_io
135  *     is called multiple times until all the body data sent to
136  *     the client
137  */
138 struct  ci_service_module {
139 
140     /**
141      \example services/echo/srv_echo.c
142      \ingroup SERVICES
143      \brief The srv_echo.c is an example service implementation,
144      *       which does not modifies the content
145      *
146      */
147     /**
148       \brief The service name
149      */
150     const char *mod_name;
151 
152     /**
153       \brief Service short description
154      */
155     const char *mod_short_descr;
156 
157     /**
158      \brief Service type
159      *
160      * The service type can be ICAP_RESPMOD for a responce modification
161      * service, ICAP_REQMOD for request modification service or
162      * ICAP_RESPMOD|ICAP_REQMOD for a service implements both response and
163      * request modification
164      */
165     int  mod_type;
166 
167     /**
168        \brief Pointer to the function called when the service loaded.
169      *
170      * This function called exactly when the service loaded by c-icap. Can
171      * be used to initialize the service.
172      \param srv_xdata Pointer to the ci_service_xdata_t object of this service
173      \param server_conf Pointer to the struct holds the main c-icap server
174             configuration
175      \return CI_OK on success, CI_ERROR on any error.
176      */
177     int (*mod_init_service)(ci_service_xdata_t *srv_xdata,struct ci_server_conf *server_conf);
178 
179     /**
180        \brief Pointer to the function which called after the c-icap initialized,
181      * but before the c-icap start serves requests.
182      *
183      * This function can be used to initialize the service. Unlike to the
184      * ci_service_module::mod_init_service, when this function called the
185      * c-icap has initialized and it is known system parameters like the
186      * services and modules which are loaded, network ports and addresses
187      * the c-icap is listening to, etc.
188      \param srv_xdata Pointer to the ci_service_xadata_t object of this service
189      \param server_conf Pointer to the struct holds the main c-icap server
190             configuration
191      \return CI_OK on success, CI_ERROR on errors.
192      */
193     int (*mod_post_init_service)(ci_service_xdata_t *srv_xdata,struct ci_server_conf *server_conf);
194 
195     /**
196      \brief Pointer to the function which called on c-icap server shutdown
197      *
198      * This function can be used to release service allocated resources
199      */
200     void (*mod_close_service)();
201 
202     /**
203      \brief Pointer to the function called when a new request for this services
204      * arrives to c-icap server.
205      *
206      * This function should inititalize the data and structures required for
207      * serving the request.
208      *
209      \param req a pointer to the related ci_request_t structure
210      \return a void pointer to the "service data", the user defined data
211      *       required for serving the
212      *       request.The developer can obtain the service data from the
213      *       related ci_request_t object using the macro ci_service_data
214      */
215     void *(*mod_init_request_data)(struct ci_request *req);
216 
217     /**
218      \brief Pointer to the function which releases the service data.
219      *
220      * This function called after the user request served to release the
221      * service data
222      \param srv_data pointer to the service data returned by the
223      *      ci_service_module::mod_init_request_data call
224      */
225     void (*mod_release_request_data)(void *srv_data);
226 
227     /**
228      \brief Pointer to the function which is used to preview the ICAP client
229      *      request
230      *
231      * The client if supports preview sends some data for examination.
232      * The service using this function will decide if the client request must
233      * processed so the client must send more data or no processing is needed
234      * so the request ended here.
235      \param preview_data Pointer to the preview data
236      \param preview_data_len The size of preview data
237      \param req Pointer to the related ci_request struct
238      \return CI_MOD_CONTINUE if the client must send more data, CI_MOD_ALLOW204
239      * if the service does not want to modify anything, or CI_ERROR on errors.
240      */
241     int (*mod_check_preview_handler)(char *preview_data,int preview_data_len,struct ci_request *req);
242 
243     /**
244      \brief Pointer to the function called when the icap client has send all the data to the service
245      *
246      *This function called when the ICAP client has send all data.
247      \param req pointer to the related ci_request struct
248      \return CI_MOD_DONE if all are OK, CI_MOD_ALLOW204 if the ICAP client
249      *       request supports 204 responses and we are not planning to modify
250      *       anything, or CI_ERROR on errors.
251      *       The service must not return CI_MOD_ALLOW204 if has already send
252      *       some data to the client, or when the client does not support
253      *       allow204 responses. To examine if client supports 204 responses
254      *       the ci_req_allow204 macro can be used
255      */
256     int (*mod_end_of_data_handler)(struct ci_request *req);
257 
258     /**
259      \brief Pointer to the function called to read/send body data from/to
260      *      icap client.
261      *
262      * This function reads body data from the ICAP client and sends back the
263      * modified body data. To allow c-icap send data to the ICAP client before
264      * all data received by the c-icap, a call to the ci_req_unlock_data
265      * function is required.
266      \param wbuf The buffer for writing data to the ICAP client
267      \param wlen The size of the write buffer. It must modified to be the size
268      *      of writing data. If the service has send all the data to the
269      *      client, this parameter must set to CI_EOF.
270      \param rbuf Pointer to the data read from the ICAP client
271      \param rlen The lenght of the data read from the ICAP client. If this
272      *      function for a reason can not read all the data, it must modify
273      *      the rlen to be equal to the read data
274      \param iseof It has non zero value if the data in rbuf buffer are the
275      *      last data from the ICAP client.
276      \param req pointer to the related ci_request struct
277      \return Return CI_OK if all are OK or CI_ERROR on errors
278      */
279     int (*mod_service_io)(char *wbuf,int *wlen,char *rbuf,int *rlen,int iseof, struct ci_request *req);
280 
281     /**
282      \brief Pointer to the config table of the service
283      *
284      * Is an array which contains the definitions of configuration parameters
285      * used by the service. The configuration parameters defined in this array
286      * can be used in c-icap.conf file.
287      */
288     struct ci_conf_entry *mod_conf_table;
289 
290     /**
291      \brief NULL pointer
292      *
293      * This field does not used. Set it to NULL.
294      */
295     void *mod_data;
296 };
297 
298 typedef struct service_alias {
299     char alias[MAX_SERVICE_NAME+1];
300     char args[MAX_SERVICE_ARGS+1];
301     ci_service_module_t *service;
302 } service_alias_t;
303 
304 /*Internal function */
305 ci_service_module_t *add_service(ci_service_module_t *service);
306 ci_service_module_t *register_service(const char *module_file, const char *argv[]);
307 
308 service_alias_t *add_service_alias(const char *service_alias, const char *service_name,const char *args);
309 ci_service_module_t *find_service(const char *service_name);
310 service_alias_t *find_service_alias(const char *service_name);
311 ci_service_xdata_t *service_data(ci_service_module_t *srv);
312 int init_services();
313 int post_init_services();
314 int release_services();
315 int run_services_option_handlers(ci_service_xdata_t *srv_xdata, struct ci_request *req);
316 
317 /*Library functions */
318 /*Undocumented, are not usefull to users*/
319 CI_DECLARE_FUNC(void) ci_service_data_read_lock(ci_service_xdata_t *srv_xdata);
320 CI_DECLARE_FUNC(void) ci_service_data_read_unlock(ci_service_xdata_t *srv_xdata);
321 
322 /**
323  \ingroup SERVICES
324  \brief Sets the ISTAG for the service.
325  *
326  *Normally this function called in ci_service_module::mod_init_service()  or
327  * ci_service_module::mod_post_init_service() function, while the service
328  * initialization.
329  \param srv_xdata is a pointer to the c-icap internal service data.
330  \param istag is a string contains the new ISTAG for the service. The istag
331  *      size can not be more than a size of SERVICE_ISTAG_SIZE. If the length
332  *      of istag is greater than SERVICE_ISTAG_SIZE the extra bytes are ignored.
333  */
334 CI_DECLARE_FUNC(void) ci_service_set_istag(ci_service_xdata_t *srv_xdata, const char *istag);
335 
336 /**
337  \ingroup SERVICES
338  \brief Sets the service x-headers mask which defines the X-Headers supported
339  *      by the service.The c-icap server will advertise these headers in
340  *      options responses.
341  *
342  * Normally this function called in ci_service_module::mod_init_service()  or
343  * ci_service_module::mod_post_init_service() function, while the service
344  * is initialized.
345  \param srv_xdata is a pointer to the c-icap internal service data.
346  \param xopts is a compination of one or more of the following defines:
347  * - CI_XCLIENTIP: Refers to the X-Client-IP header. The HTTP proxy (or the
348  *   ICAP client) will sends  the ip address of the HTTP client using this
349  *   header if supports this header.
350  * - CI_XSERVERIP: The X-Server-IP header. The HTTP proxy will incluse the IP
351  *   of the HTTP destination host in the X-Server-IP header if supports this
352  *   header.
353  * - CI_XSUBSCRIBERID: The X-Subscriber-ID header. This header can include a
354  *   unique subscriber ID of the user who issued the HTTP request
355  * - CI_XAUTHENTICATEDUSER: The X-Authenticated-User header. If the user
356  *   authenticated on  HTTP proxy side includes the username
357  * - CI_XAUTHENTICATEDGROUPS: The X-Authenticated-Group header. If the user is
358  *   authenticated on HTTP proxy side includes the user groups
359  *
360  * example usage:
361  \code
362  * ci_service_set_xopts(srv_xdata,CI_XCLIENTIP|CI_XAUTHENTICATEDUSER);
363  \endcode
364  *
365  * For more informations about ICAP common X-Headers look at:
366  * http://www.icap-forum.org/documents/specification/draft-stecher-icap-subid-00.txt
367  */
368 CI_DECLARE_FUNC(void) ci_service_set_xopts(ci_service_xdata_t *srv_xdata, uint64_t xopts);
369 
370 /**
371  \ingroup SERVICES
372  \brief it is similar to the function ci_service_set_xopts but just adds
373  *      (not sets) the X-Headers defined by the xopts parameter to the
374  *      existing x-headers mask of service.
375  *
376  */
377 CI_DECLARE_FUNC(void) ci_service_add_xopts(ci_service_xdata_t *srv_xdata, uint64_t xopts);
378 
379 /**
380  \ingroup SERVICES
381  \brief Set the list of file extensions that should previewed by the service.
382  *
383  * The c-icap will inform the ICAP client that should send preview data for the
384  * files which have the extensions contained in the preview string. The
385  * wildcard value "*" specifies all files extensions, which is the default.
386  \param srv_xdata is a pointer to the c-icap internal service data.
387  \param preview is the string which contains the list of the file extensions.
388  *
389  * example usage:
390  \code
391  *   ci_service_set_transfer_preview(srv_xdata,"zip, tar");
392  \endcode
393  */
394 CI_DECLARE_FUNC(void) ci_service_set_transfer_preview(ci_service_xdata_t *srv_xdata,const char *preview);
395 
396 /**
397  \ingroup SERVICES
398  \brief Set the list of file extensions that should NOT be send for this
399  *      service.
400  *
401  * The c-icap will inform the ICAP client that should not send files which
402  * have the extensions contained in the ignore string.
403  \param srv_xdata is a pointer to the c-icap internal service data.
404  \param ignore is the string which contains the list of the file extensions.
405  *
406  * example usage:
407  \code
408  *   ci_service_set_transfer_ignore(srv_xdata,"gif, jpeg");
409  \endcode
410  */
411 CI_DECLARE_FUNC(void) ci_service_set_transfer_ignore(ci_service_xdata_t *srv_xdata, const char *ignore);
412 
413 /**
414  \ingroup SERVICES
415  \brief Set the list of file extensions that should be send in their entirety
416  *      (without preview) to this service.
417  *
418  * The c-icap will inform the ICAP client that should send files which have
419  * the extensions contained in the complete string, in their entirety to this
420  * service.
421  \param srv_xdata is a pointer to the c-icap internal service data.
422  \param complete is the string which contains the list of the file extensions.
423  *
424  *example usage:
425  \code
426  *   ci_service_set_transfer_complete(srv_xdata,"exe, bat, com, ole");
427  \endcode
428  */
429 CI_DECLARE_FUNC(void) ci_service_set_transfer_complete(ci_service_xdata_t *srv_xdata, const char *complete);
430 
431 /**
432   \ingroup SERVICES
433   \brief Sets the maximum preview size supported by this service
434   *
435   \param srv_xdata is a pointer to the c-icap internal service data.
436   \param preview is the size of preview data supported by this service
437  */
438 CI_DECLARE_FUNC(void) ci_service_set_preview(ci_service_xdata_t *srv_xdata, int preview);
439 
440 
441 /**
442   \ingroup SERVICES
443   \brief  Enable the allow 204 responses for this service.
444   *
445   * The service will supports the allow 204 responses if the icap client
446   * support it too.
447   \param srv_xdata is a pointer to the c-icap internal service data.
448  */
449 CI_DECLARE_FUNC(void) ci_service_enable_204(ci_service_xdata_t *srv_xdata);
450 
451 /**
452   \ingroup SERVICES
453   \brief  Enable the Partial Content 206 responses for this service.
454   *
455   * The service will supports the Partial Content 206 responses if the icap
456   * client support it too.
457   \param srv_xdata is a pointer to the c-icap internal service data.
458  */
459 CI_DECLARE_FUNC(void) ci_service_enable_206(ci_service_xdata_t *srv_xdata);
460 
461 /**
462   \ingroup SERVICES
463   \brief Sets the maximum connection should opened by icap client to the c-icap
464   *      for this service
465   *
466   \param srv_xdata is a pointer to the c-icap internal service data.
467   \param max_connections is the maximum connections
468  */
469 CI_DECLARE_FUNC(void) ci_service_set_max_connections(ci_service_xdata_t *srv_xdata, int max_connections);
470 
471 /**
472   \ingroup SERVICES
473   \brief Sets the Options ttl for this service
474   *
475   \param srv_xdata is a pointer to the c-icap internal service data.
476   \param ttl is the ttl value in seconds
477  */
478 CI_DECLARE_FUNC(void) ci_service_set_options_ttl(ci_service_xdata_t *srv_xdata, int ttl);
479 
480 CI_DECLARE_FUNC(void) ci_service_add_xincludes(ci_service_xdata_t *srv_xdata, char **xincludes);
481 
482 /**
483   \ingroup SERVICES
484   \brief Add a service handler for the service
485   *
486   * Normally this function called in ci_service_module::mod_init_service()  or
487   * ci_service_module::mod_post_init_service() function.
488   * The options handlers are running when the service receives an OPTIONS
489   * request to check for service health. They can add ICAP headers to the
490   * OPTIONS response and must return CI_OK on success, or CI_ERROR on failure.
491   * If one or more handlers failed the c-icap will produce a "500 Server Error"
492   * response.
493   *
494   \param srv_xdata is a pointer to the c-icap internal service data.
495   \param name a name for the handler, used for debuging reasons
496   \param handler the handler
497 */
498 CI_DECLARE_FUNC(void) ci_service_add_option_handler(ci_service_xdata_t *srv_xdata, const char *name, int (*handler)(struct ci_request *));
499 
500 #ifdef __CI_COMPAT
501 #define service_module_t ci_service_module_t
502 #define service_extra_data_t ci_service_xdata_t
503 
504 /*The Old CI_X* defines*/
505 #define CI_XClientIP              1
506 #define CI_XServerIP              2
507 #define CI_XSubscriberID          4
508 #define CI_XAuthenticatedUser     8
509 #define CI_XAuthenticatedGroups  16
510 
511 #endif
512 
513 #ifdef __cplusplus
514 }
515 #endif
516 
517 #endif
518