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