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 \defgroup ICAPCLIENT ICAP client request API 22 \ingroup API 23 * API for implementing ICAP clients 24 */ 25 26 #ifndef _REQUEST_H 27 #define _REQUEST_H 28 29 #include "header.h" 30 #include "service.h" 31 #include "net_io.h" 32 #include "array.h" 33 34 #ifdef __cplusplus 35 extern "C" 36 { 37 #endif 38 39 /** 40 \defgroup REQUEST ICAP request API 41 \ingroup API 42 * ICAP request related API. 43 */ 44 45 /** 46 \defgroup ICAPCLIENT ICAP client request API 47 \ingroup API 48 * API for implementing ICAP clients 49 */ 50 51 //enum REQUEST_STATUS { WAIT,SERVED }; 52 53 enum GETDATA_STATUS {GET_NOTHING = 0,GET_HEADERS,GET_PREVIEW,GET_BODY,GET_EOF}; 54 enum SENDDATA_STATUS {SEND_NOTHING = 0, SEND_RESPHEAD, SEND_HEAD1, SEND_HEAD2, SEND_HEAD3, SEND_BODY, SEND_EOF }; 55 56 /*enum BODY_RESPONCE_STATUS{ CHUNK_DEF = 1,CHUNK_BODY,CHUNK_END};*/ 57 58 enum CLIENT_STATUS { 59 CLIENT_INIT = 0, 60 CLIENT_SEND_HEADERS, 61 CLIENT_SEND_HEADERS_WRITE_NOTHING = CLIENT_SEND_HEADERS, 62 CLIENT_SEND_HEADERS_WRITE_ICAP_HEADERS, 63 CLIENT_SEND_HEADERS_WRITE_REQ_HEADERS, 64 CLIENT_SEND_HEADERS_WRITE_RES_HEADERS, 65 CLIENT_SEND_HEADERS_WRITE_PREVIEW_INFO, 66 CLIENT_SEND_HEADERS_WRITE_PREVIEW, 67 CLIENT_SEND_HEADERS_WRITE_EOF_INFO, 68 CLIENT_SEND_HEADERS_FINISHED, 69 70 CLIENT_READ_PREVIEW_RESPONSE, 71 72 CLIENT_PROCESS_DATA, 73 CLIENT_PROCESS_DATA_GET_NOTHING = CLIENT_PROCESS_DATA, 74 CLIENT_PROCESS_DATA_GET_HEADERS, 75 CLIENT_PROCESS_DATA_HEADERS_FINISHED, 76 CLIENT_PROCESS_DATA_GET_BODY, 77 CLIENT_PROCESS_DATA_GET_EOF 78 }; 79 80 #define NEEDS_TO_READ_FROM_ICAP 0x1 81 #define NEEDS_TO_WRITE_TO_ICAP 0x2 82 #define NEEDS_TO_READ_USER_DATA 0x4 83 #define NEEDS_TO_WRITE_USER_DATA 0x8 84 85 86 #define CI_NO_STATUS 0 87 #define CI_OK 1 88 #define CI_NEEDS_MORE 2 89 #define CI_ERROR -1 90 #define CI_EOF -2 91 92 93 #define EXTRA_CHUNK_SIZE 30 94 #define MAX_CHUNK_SIZE 4064 /*4096 -EXTRA_CHUNK_SIZE-2*/ 95 #define MAX_USERNAME_LEN 255 96 97 typedef struct ci_buf { 98 char *buf; 99 int size; 100 int used; 101 } ci_buf_t; 102 103 104 struct ci_service_module; 105 struct ci_ring_buf; 106 107 /** 108 \typedef ci_request_t 109 \ingroup REQUEST 110 * This is the struct which holds all the data which represent an ICAP 111 * request. The developers should not access directly the fields of 112 * this struct but better use the documented macros and functions 113 */ 114 typedef struct ci_request { 115 ci_connection_t *connection; 116 int packed; 117 int type; 118 char req_server[CI_MAXHOSTNAMELEN+1]; 119 int access_type; 120 char user[MAX_USERNAME_LEN+1]; 121 char service[MAX_SERVICE_NAME+1]; 122 char args[MAX_SERVICE_ARGS + 1]; 123 int preview; 124 int keepalive; 125 int allow204; 126 int hasbody; 127 int responce_hasbody; 128 struct ci_buf preview_data; 129 struct ci_service_module *current_service_mod; 130 ci_headers_list_t *request_header; 131 ci_headers_list_t *response_header; 132 ci_encaps_entity_t *entities[5];//At most 3 and 1 for termination..... 133 ci_encaps_entity_t *trash_entities[7]; 134 ci_headers_list_t *xheaders; 135 136 void *service_data; 137 138 char rbuf[BUFSIZE]; 139 char wbuf[MAX_CHUNK_SIZE+EXTRA_CHUNK_SIZE+2]; 140 int eof_received; 141 int eof_sent; 142 int data_locked; 143 144 char *pstrblock_read; 145 int pstrblock_read_len; 146 unsigned int current_chunk_len; 147 unsigned int chunk_bytes_read; 148 unsigned int write_to_module_pending; 149 150 int status; 151 int return_code; 152 char *pstrblock_responce; 153 int remain_send_block_bytes; 154 155 /*Used to echo data back to a client which does not support preview 156 in the case of 204 outside preview.*/ 157 struct ci_ring_buf *echo_body; 158 159 /*Caching values for various subsystems*/ 160 int preview_data_type; 161 int auth_required; 162 163 /*log string*/ 164 char *log_str; 165 ci_str_array_t *attributes; 166 167 /* statistics */ 168 uint64_t bytes_in; /*May include bytes from next pipelined request*/ 169 uint64_t bytes_out; 170 uint64_t request_bytes_in; /*Current request input bytes*/ 171 uint64_t http_bytes_in; 172 uint64_t http_bytes_out; 173 uint64_t body_bytes_in; 174 uint64_t body_bytes_out; 175 176 /* added flags/variables*/ 177 int allow206; 178 int64_t i206_use_original_body; 179 ci_ip_t xclient_ip; 180 } ci_request_t; 181 182 #define lock_data(req) (req->data_locked = 1) 183 #define unlock_data(req) (req->data_locked = 0) 184 185 /*This functions needed in server (mpmt_server.c ) */ 186 ci_request_t *newrequest(ci_connection_t *connection); 187 int recycle_request(ci_request_t *req,ci_connection_t *connection); 188 int keepalive_request(ci_request_t *req); 189 int process_request(ci_request_t *); 190 191 /*Functions used in both server and icap-client library*/ 192 CI_DECLARE_FUNC(int) parse_chunk_data(ci_request_t *req, char **wdata); 193 CI_DECLARE_FUNC(int) net_data_read(ci_request_t *req); 194 CI_DECLARE_FUNC(int) process_encapsulated(ci_request_t *req, const char *buf); 195 196 /*********************************************/ 197 /*Buffer functions (I do not know if they must included in ci library....) */ 198 CI_DECLARE_FUNC(void) ci_buf_init(struct ci_buf *buf); 199 CI_DECLARE_FUNC(void) ci_buf_reset(struct ci_buf *buf); 200 CI_DECLARE_FUNC(int) ci_buf_mem_alloc(struct ci_buf *buf,int size); 201 CI_DECLARE_FUNC(void) ci_buf_mem_free(struct ci_buf *buf); 202 CI_DECLARE_FUNC(int) ci_buf_write(struct ci_buf *buf,char *data,int len); 203 CI_DECLARE_FUNC(int) ci_buf_reset_size(struct ci_buf *buf,int req_size); 204 205 /***************/ 206 /*API defines */ 207 #define ci_service_data(req) ((req)->service_data) 208 #define ci_allow204(req) ((req)->allow204) 209 #define ci_allow206(req) ((req)->allow206) 210 /*API functions ......*/ 211 CI_DECLARE_FUNC(ci_request_t *) ci_request_alloc(ci_connection_t *connection); 212 CI_DECLARE_FUNC(void) ci_request_reset(ci_request_t *req); 213 CI_DECLARE_FUNC(void) ci_request_destroy(ci_request_t *req); 214 CI_DECLARE_FUNC(void) ci_request_pack(ci_request_t *req); 215 CI_DECLARE_FUNC(void) ci_response_pack(ci_request_t *req); 216 CI_DECLARE_FUNC(ci_encaps_entity_t *) ci_request_alloc_entity(ci_request_t *req,int type,int val); 217 CI_DECLARE_FUNC(int) ci_request_release_entity(ci_request_t *req,int pos); 218 CI_DECLARE_FUNC(char *) ci_request_set_log_str(ci_request_t *req, char *logstr); 219 CI_DECLARE_FUNC(int) ci_request_set_str_attribute(ci_request_t *req, const char *name, const char *value); 220 221 CI_DECLARE_FUNC(int) ci_request_206_origin_body(ci_request_t *req, uint64_t offset); 222 223 /*ICAP client api*/ 224 CI_DECLARE_FUNC(ci_request_t *) ci_client_request(ci_connection_t *conn,const char *server,const char *service); 225 CI_DECLARE_FUNC(void) ci_client_request_reuse(ci_request_t *req); 226 227 CI_DECLARE_FUNC(int) ci_client_get_server_options(ci_request_t *req,int timeout); 228 CI_DECLARE_FUNC(int) ci_client_get_server_options_nonblocking(ci_request_t *req); 229 230 CI_DECLARE_FUNC(int) ci_client_icapfilter(ci_request_t *req, 231 int timeout, 232 ci_headers_list_t *req_headers, 233 ci_headers_list_t *resp_headers, 234 void *data_source, 235 int (*source_read)(void *,char *,int), 236 void *data_dest, 237 int (*dest_write) (void *,char *,int)); 238 239 /** 240 \ingroup ICAPCLIENT 241 * Function to send HTTP objects to an ICAP server for processing. It sends 242 * the HTTP request headers, and the HTTP response from HTTP server (headers 243 * plus body data), and receives modified HTTP response headers and body data. 244 \param req The ci_request_t object. 245 \param io_action is a combination set of ci_wait_for_read and 246 * ci_wait_for_write flags. It has the meaning that the 247 * ci_client_icapfilter_nonblocking can read from or write to ICAP server. 248 \param req_headers The HTTP request headers to use. 249 \param resp_headers The HTTP response headers to use. 250 \param data_source User data to use with source_read callback function. 251 \param source_read Callback function to use for reading HTTP object body data. 252 \param data_dest User data to use with dest_write callback function. 253 \param dest_write Callback function to use for storing modified body data. 254 \return combination of the following flags: NEEDS_TO_READ_FROM_ICAP, 255 * NEEDS_TO_WRITE_TO_ICAP, NEEDS_TO_READ_USER_DATA and 256 * NEEDS_TO_WRITE_USER_DATA. 257 */ 258 CI_DECLARE_FUNC(int) ci_client_icapfilter_nonblocking(ci_request_t * req, int io_action, 259 ci_headers_list_t * req_headers, 260 ci_headers_list_t * resp_headers, 261 void *data_source, 262 int (*source_read) (void *, char *, int), 263 void *data_dest, 264 int (*dest_write) (void *, char *, int)); 265 266 CI_DECLARE_FUNC(int) ci_client_http_headers_completed(ci_request_t * req); 267 268 CI_DECLARE_FUNC(void) ci_client_set_user_agent(const char *agent); 269 270 CI_DECLARE_FUNC(void) ci_client_library_init(); 271 272 CI_DECLARE_FUNC(void) ci_client_library_release(); 273 274 /** Deprecated. Use ci_connect_to declared in net_io.h instead. */ 275 CI_DECLARE_FUNC(ci_connection_t *) ci_client_connect_to(char *servername,int port,int proto); 276 277 #ifdef __CI_COMPAT 278 #define request_t ci_request_t 279 #endif 280 281 #ifdef __cplusplus 282 } 283 #endif 284 285 #endif 286