1 /*===========================================================================
2 *
3 *                            PUBLIC DOMAIN NOTICE
4 *               National Center for Biotechnology Information
5 *
6 *  This software/database is a "United States Government Work" under the
7 *  terms of the United States Copyright Act.  It was written as part of
8 *  the author's official duties as a United States Government employee and
9 *  thus cannot be copyrighted.  This software/database is freely available
10 *  to the public for use. The National Library of Medicine and the U.S.
11 *  Government have not placed any restriction on its use or reproduction.
12 *
13 *  Although all reasonable efforts have been taken to ensure the accuracy
14 *  and reliability of the software and data, the NLM and the U.S.
15 *  Government do not and cannot warrant the performance or results that
16 *  may be obtained by using this software or data. The NLM and the U.S.
17 *  Government disclaim all warranties, express or implied, including
18 *  warranties of performance, merchantability or fitness for any particular
19 *  purpose.
20 *
21 *  Please cite the author in any work or product based on this material.
22 *
23 * ===========================================================================
24 *
25 */
26 
27 #ifndef _h_http_priv_
28 #define _h_http_priv_
29 
30 #ifndef _h_klib_defs_
31 #include <klib/defs.h>
32 #endif
33 
34 #ifndef _h_klib_text_
35 #include <klib/text.h>
36 #endif
37 
38 #ifndef _h_klib_data_buffer
39 #include <klib/data-buffer.h>
40 #endif
41 
42 #ifndef _h_klib_container
43 #include <klib/container.h>
44 #endif
45 
46 #ifndef _h_klib_refcount_
47 #include <klib/refcount.h>
48 #endif
49 
50 #ifndef _h_kns_mgr_priv_
51 #include <kns/kns-mgr-priv.h>
52 #endif
53 
54 #ifndef _h_kns_http_
55 #include <kns/http.h>
56 #endif
57 
58 #ifndef _h_kns_endpoint_
59 #include <kns/endpoint.h>
60 #endif
61 
62 /* timeout on Http Read */
63 #ifndef MAX_HTTP_READ_LIMIT
64 #define MAX_HTTP_READ_LIMIT ( 5 * 60 * 1000 ) /* 5 minutes */
65 #endif
66 
67 /* timeout on Http Write */
68 #ifndef MAX_HTTP_WRITE_LIMIT
69 #define MAX_HTTP_WRITE_LIMIT ( 15 * 1000 )
70 #endif
71 
72 /* timeout on Http Read loop */
73 #ifndef MAX_HTTP_TOTAL_READ_LIMIT
74 #define MAX_HTTP_TOTAL_READ_LIMIT ( 10 * 60 * 1000 ) /* 10 minutes */
75 #endif
76 
77 /* timeout on Http Connect loop */
78 #ifndef MAX_HTTP_TOTAL_CONNECT_LIMIT
79 #define MAX_HTTP_TOTAL_CONNECT_LIMIT ( 10 * 60 * 1000 ) /* 10 minutes */
80 #endif
81 
82 
83 #ifdef __cplusplus
84 extern "C" {
85 #endif
86 
87 struct KFile;
88 struct KNSManager;
89 struct KClientHttp;
90 struct KClientHttpRequest;
91 struct KEndPoint;
92 struct KStream;
93 struct timeout_t;
94 struct URLBlock;
95 
96 /* Form of Request-URI in HTTP Request-Line used when connecting via proxy */
97 typedef enum {
98     eUFUndefined,
99 
100     /* absoluteURI: https://tools.ietf.org/html/rfc2616#section-5.1.2
101        standard form recommended to use with proxies */
102     eUFAbsolute,
103 
104     /* origin-form: https://tools.ietf.org/html/rfc7230#section-5.3.1
105        use it when connect to googleapis.com: it rejects absoluteURI */
106     eUFOrigin,
107 } EUriForm;
108 
109 /*--------------------------------------------------------------------------
110  * KHttpHeader
111  *  node structure to place http header lines into a BSTree
112  */
113 typedef struct KHttpHeader KHttpHeader;
114 struct KHttpHeader
115 {
116     BSTNode dad;
117     String name;
118     String value;
119     KDataBuffer value_storage;
120 };
121 
122 extern void KHttpHeaderWhack ( BSTNode *n, void *ignore );
123 extern int64_t CC KHttpHeaderSort ( const BSTNode *na, const BSTNode *nb );
124 extern int64_t CC KHttpHeaderCmp ( const void *item, const BSTNode *n );
125 
126 extern rc_t KClientHttpGetHeaderLine ( struct KClientHttp *self, struct timeout_t *tm, BSTree *hdrs, bool *blank, bool * len_zero, bool *close_connection );
127 extern rc_t KClientHttpGetStatusLine ( struct KClientHttp *self, struct timeout_t *tm, String *msg, uint32_t *status, ver_t *version );
128 
129 
130 /* compatibility for existing code */
131 
132 #define KHttpGetHeaderLine KClientHttpGetHeaderLine
133 #define KHttpGetStatusLine KClientHttpGetStatusLine
134 
135 
136 rc_t KClientHttpGetHeaderLine ( struct KClientHttp * self,
137     struct timeout_t * tm, BSTree * hdrs, bool * blank, bool *  len_zero,
138     bool * close_connection );
139 rc_t KClientHttpGetStatusLine ( struct KClientHttp * self,
140     struct timeout_t * tm, String * msg, uint32_t * status, ver_t * version );
141 
142 
143 /*--------------------------------------------------------------------------
144  * KClientHttp
145  */
146 
147 struct KClientHttp
148 {
149     const struct KNSManager *mgr;
150     struct KStream * sock;
151     struct KStream * test_sock; /* if not NULL, use to communicate with a mocked server in testing, do not reopen on redirects */
152 
153     /* buffer for accumulating response data from "sock" */
154     KDataBuffer block_buffer;
155     size_t block_valid;         /* number of valid response bytes in buffer            */
156     size_t block_read;          /* number of bytes read out by line reader or stream   */
157     size_t body_start;          /* offset to first byte in body                        */
158 
159     KDataBuffer line_buffer;    /* data accumulates for reading headers and chunk size */
160     size_t line_valid;
161 
162     KDataBuffer hostname_buffer;
163     String hostname;
164     uint32_t port;
165 
166     ver_t vers;
167 
168     KRefcount refcount;
169 
170     int32_t read_timeout;
171     int32_t write_timeout;
172 
173     /* Remote EndPoint */
174     KEndPoint ep;
175     bool ep_valid;
176     bool proxy_ep;
177     bool proxy_default_port;
178 
179     KEndPoint local_ep; /* Local EndPoint */
180 
181     bool reliable;
182     bool tls;
183 
184     bool close_connection;
185 
186     EUriForm uf; /* Form of Request-URI in Request-Line when using proxy */
187 
188     char * ua; /* user agent */
189     char * ua_head; /* user agent for HEAD */
190 };
191 
192 void KClientHttpClose ( struct KClientHttp * self );
193 rc_t KClientHttpReopen ( struct KClientHttp * self );
194 
195 rc_t KNSManagerMakeClientHttpInt ( struct KNSManager const *self, struct KClientHttp **_http,
196     const KDataBuffer *hostname_buffer,  struct KStream *opt_conn,
197     ver_t vers, int32_t readMillis, int32_t writeMillis,
198     const String *host, uint32_t port, bool reliable, bool tls );
199 
200 rc_t KClientHttpVAddHeader ( BSTree *hdrs, bool add, const char *_name, const char *_val, va_list args );
201 rc_t KClientHttpFindHeader ( const BSTree *hdrs, const char *_name, char *buffer, size_t bsize, size_t *num_read );
202 rc_t KClientHttpAddHeader ( BSTree *hdrs, const char *name, const char *val, ... );
203 rc_t KClientHttpReplaceHeader ( BSTree *hdrs, const char *name, const char *val, ... );
204 
205 rc_t KClientHttpClear ( KClientHttp *self );
206 rc_t KClientHttpInit ( KClientHttp * http, const KDataBuffer *hostname_buffer, ver_t _vers, const String * _host, uint32_t port, bool tls );
207 
208 rc_t KClientHttpSendReceiveMsg ( KClientHttp *self, KClientHttpResult **rslt,
209     const char *buffer, size_t len, const KDataBuffer *body, const char *url );
210 
211 /*--------------------------------------------------------------------------
212  * KClientHttpRequest
213  */
214 
215 struct KClientHttpRequest
216 {
217     struct KClientHttp * http;
218 
219     URLBlock url_block;
220     KDataBuffer url_buffer;
221 
222     KDataBuffer body;
223 
224     BSTree hdrs;
225 
226     KRefcount refcount;
227     bool accept_not_modified;
228 
229     bool ceRequired; /* computing environment token required to access this URL */
230     bool payRequired; /* payment info required to access this URL */
231 
232     bool rangeRequested;
233 
234     bool head; /* is HEAD request */
235 };
236 
237 void KClientHttpGetRemoteEndpoint ( const struct KClientHttp * self,
238                                     struct KEndPoint * ep );
239 void KClientHttpGetLocalEndpoint ( const struct KClientHttp * self,
240                                    struct KEndPoint * ep );
241 
242 rc_t KClientHttpRequestAttachEnvironmentToken( struct KClientHttpRequest * self );
243 
244 /* exported private functions
245 */
246 
247 const char * KClientHttpRequestGetBody( struct KClientHttpRequest * self );
248 
249 /* exported private functions
250 */
251 
252 /* a hook to redefine KClientHttpReopen (for testing,_DEBUG only) */
253 #if _DEBUGGING
254 extern void SetClientHttpReopenCallback ( struct KStream * (*fn) ( void ) );
255 #endif
256 
257 /*--------------------------------------------------------------------------
258  * KClientHttpResult
259  *  hyper text transfer protocol
260  *  Holds all the headers in a BSTree
261  *  Records the status msg, status code and version of the response
262  */
263 struct KClientHttpResult
264 {
265     KClientHttp *http;
266 
267     BSTree hdrs;
268 
269     String msg;
270     uint32_t status;
271     ver_t version;
272 
273     KRefcount refcount;
274     bool len_zero;
275 
276     char * expiration;
277 
278     bool rangeRequested;
279 };
280 
281 /* internal encoding  function, exposed for testing */
282 extern rc_t KClientHttpRequestUrlEncodeBase64(const String ** encoding);
283 
284 #define SUPPORT_CHUNKED_READ 1
285 
286 rc_t KNSManagerVMakeHttpFileIntUnstableFromBuffer(const struct KNSManager *self,
287     const struct KFile **file, struct KStream *conn, ver_t vers, bool reliable,
288     bool need_env_token, bool payRequired, const char *url,
289     const KDataBuffer *buf);
290 
291 rc_t KNSManagerVMakeHttpFileIntUnstable(const struct KNSManager *self,
292     const struct KFile **file, struct KStream *conn, ver_t vers, bool reliable,
293     bool need_env_token, bool payRequired, const char *url, va_list args);
294 
295 bool KUnstableFileIsKHttpFile(const struct KFile * self);
296 
297 #ifdef __cplusplus
298 }
299 #endif
300 
301 #endif /* _h_kttp_priv_ */
302