globus_connect_gridftp_server 16.16~rc1
Loading...
Searching...
No Matches
globus_i_dsi_rest.h
1/*
2 * Copyright 1999-2016 University of Chicago
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#ifndef GLOBUS_DONT_DOCUMENT_INTERNAL
21
22#ifndef GLOBUS_I_DSI_REST_H
23#define GLOBUS_I_DSI_REST_H
24
25#ifdef __cplusplus
26extern "C" {
27#endif
28
29#include "globus_i_gridftp_server_config.h"
30#include <stdbool.h>
31
32#include "globus_dsi_rest.h"
33#include "globus_common.h"
35
36#include <curl/curl.h>
37#include <jansson.h>
38
39typedef
40struct globus_i_dsi_rest_read_json_arg_s
41{
42 size_t buffer_used;
43 size_t buffer_len;
44 char *buffer;
45 json_t **json_out;
46}
47globus_i_dsi_rest_read_json_arg_t;
48
49typedef struct
50globus_i_dsi_rest_buffer_s
51{
52 size_t buffer_len;
53 size_t buffer_used;
54 uint64_t transfer_offset;
55 struct globus_i_dsi_rest_buffer_s *next;
56 unsigned char buffer[];
57}
58globus_i_dsi_rest_buffer_t;
59
60typedef struct
61globus_i_dsi_rest_idle_arg_s
62{
63 globus_abstime_t last_activity;
64 uintptr_t idle_timeout;
65 uint64_t last_amt_read;
66 uint64_t last_amt_written;
67}
68globus_i_dsi_rest_idle_arg_t;
69
70typedef
71struct globus_i_dsi_rest_gridftp_op_arg_s
72{
73 globus_gfs_operation_t op;
74 globus_mutex_t mutex;
75 globus_cond_t cond;
76 globus_result_t result;
77
78 uint64_t offset;
79 uint64_t end_offset;
80 // If we hit EOF or end of expected read
81 bool eof;
82 // Points to app's gridftp_op_arg's eof field, only set to true
83 // if we get an eof response from the GridFTP server.
84 bool *eofp;
85
86 globus_i_dsi_rest_buffer_t *pending_buffers;
87 globus_i_dsi_rest_buffer_t **pending_buffers_last;
88
89 globus_i_dsi_rest_buffer_t *current_buffer;
90
91 globus_i_dsi_rest_buffer_t *registered_buffers;
92 int registered_buffers_count;
93
94 globus_i_dsi_rest_buffer_t *free_buffers;
95}
96globus_i_dsi_rest_gridftp_op_arg_t;
97
98
99typedef
100struct globus_i_dsi_rest_write_multipart_arg_s
101{
102 char *boundary;
103 size_t num_parts;
104 size_t part_index;
105 char *current_boundary;
106 size_t current_boundary_offset;
107 size_t current_boundary_length;
108 struct globus_i_dsi_rest_write_part_s
109 *parts;
110}
111globus_i_dsi_rest_write_multipart_arg_t;
112
113typedef
114struct globus_i_dsi_rest_write_block_arg_s
115{
117 void *block_data;
119 size_t block_len;
121 size_t offset;
122}
123globus_i_dsi_rest_write_block_arg_t;
124
125typedef
126struct globus_i_dsi_rest_write_blocks_arg_s
127{
128 size_t block_count;
129 size_t current_block;
130 globus_i_dsi_rest_write_block_arg_t*blocks;
131}
132globus_i_dsi_rest_write_blocks_arg_t;
133
134typedef
135struct globus_i_dsi_rest_write_part_s
136{
138 globus_dsi_rest_key_array_t malloced_headers;
139
140 globus_dsi_rest_write_t data_write_callback;
141 void *data_write_callback_arg;
142}
143globus_i_dsi_rest_write_part_t;
144
145typedef
146struct globus_i_dsi_rest_read_part_s
147{
149
150 globus_dsi_rest_response_t response_callback;
151 void *response_callback_arg;
152
153 globus_dsi_rest_read_t data_read_callback;
154 void *data_read_callback_arg;
155
156 globus_dsi_rest_read_t data_peek_callback;
157 void *data_peek_callback_arg;
158}
159globus_i_dsi_rest_read_part_t;
160
161typedef
162struct globus_i_dsi_rest_read_multipart_arg_s
163{
164 size_t num_parts;
165 size_t part_index;
166 globus_i_dsi_rest_read_part_t *parts;
167
168 char *boundary;
169 size_t boundary_length;
170
171 char *boundary_buffer;
172 size_t boundary_buffer_length;
173 size_t boundary_buffer_offset;
174
175 size_t match_counter;
176
177 bool need_header;
178 char *header_buffer;
179 size_t header_buffer_offset;
180}
181globus_i_dsi_rest_read_multipart_arg_t;
182
186typedef
187struct globus_i_dsi_rest_request_s
188{
189 CURL *handle;
190 globus_result_t result;
191 const char *method;
192 int response_code;
193 char response_reason[64];
194 struct curl_slist *request_headers;
195 char *complete_uri;
196
197 off_t request_bytes_uploaded;
198 off_t response_bytes_downloaded;
199
200 globus_i_dsi_rest_write_part_t write_part;
201 globus_i_dsi_rest_read_part_t read_part;
202
203 globus_dsi_rest_response_t response_callback;
204 void *response_callback_arg;
205
206 globus_dsi_rest_complete_t complete_callback;
207 void *complete_callback_arg;
208
209 globus_dsi_rest_progress_t progress_callback;
210 void *progress_callback_arg;
211
212 globus_i_dsi_rest_idle_arg_t idle_arg;
213
214 uint64_t request_content_length;
215 bool request_content_length_set;
216}
217globus_i_dsi_rest_request_t;
218
233globus_result_t
234globus_i_dsi_rest_handle_get(
235 CURL **handlep,
236 void *callback_arg);
237
249void
250globus_i_dsi_rest_handle_release(
251 CURL *handle);
252
253
254globus_result_t
255globus_i_dsi_rest_compute_headers(
256 struct curl_slist **request_headers,
257 const globus_dsi_rest_key_array_t *headers);
258
259globus_result_t
260globus_i_dsi_rest_set_request(
261 CURL *curl,
262 const char *method,
263 const char *uri,
264 struct curl_slist *headers,
265 const globus_dsi_rest_callbacks_t *callbacks);
266
267globus_result_t
268globus_i_dsi_rest_add_header(
269 struct curl_slist **request_headers,
270 const char *header_name,
271 const char *header_value);
272
273globus_result_t
274globus_i_dsi_rest_perform(
275 globus_i_dsi_rest_request_t *request);
276
277globus_result_t
278globus_i_dsi_rest_encode_form_data(
279 const globus_dsi_rest_key_array_t *form_fields,
280 char **form_datap);
281
282globus_i_dsi_rest_buffer_t *
283globus_i_dsi_rest_buffer_get(
284 globus_i_dsi_rest_gridftp_op_arg_t *gridftp_op_arg,
285 size_t size);
286
287void
288globus_i_dsi_rest_uri_escape(
289 const char *raw,
290 char **encodedp,
291 size_t *availablep);
292
293globus_result_t
294globus_i_dsi_rest_multipart_boundary_prepare(
295 const char *delimiter,
296 bool final,
297 globus_dsi_rest_key_array_t *part_header,
298 char **boundaryp,
299 size_t *boundary_lengthp);
300
301void
302globus_i_dsi_rest_request_cleanup(
303 globus_i_dsi_rest_request_t *request);
304
305/* Callbacks that are passed to libcurl that cause user-specific callbacks */
306int
307globus_i_dsi_rest_xferinfo(
308 void *callback_arg,
309 curl_off_t dltotal,
310 curl_off_t dlnow,
311 curl_off_t ultotal,
312 curl_off_t ulnow);
313
314int
315globus_i_dsi_rest_progress(
316 void *callback_arg,
317 double dltotal,
318 double dlnow,
319 double ultotal,
320 double ulnow);
321
322size_t
323globus_i_dsi_rest_header(
324 char *buffer,
325 size_t size,
326 size_t nitems,
327 void *callback_arg);
328
329globus_result_t
330globus_i_dsi_rest_header_parse(
332 char *buffer,
333 size_t size);
334
335size_t
336globus_i_dsi_rest_write_data(
337 char *ptr,
338 size_t size,
339 size_t nmemb,
340 void *callback_arg);
341
342size_t
343globus_i_dsi_rest_read_data(
344 char *buffer,
345 size_t size,
346 size_t nitems,
347 void *callback_arg);
348
349#define GlobusDsiRestErrorParameter() \
350 globus_error_put(GlobusDsiRestErrorParameterObject())
351#define GlobusDsiRestErrorMemory() \
352 globus_error_put(GlobusDsiRestErrorMemoryObject())
353#define GlobusDsiRestErrorParse(s) \
354 globus_error_put(GlobusDsiRestErrorParseObject(s))
355#define GlobusDsiRestErrorCurl(rc) \
356 globus_error_put(GlobusDsiRestErrorCurlObject(rc))
357#define GlobusDsiRestErrorJson(buffer, buffer_len, err) \
358 globus_error_put(GlobusDsiRestErrorJsonObject(buffer, buffer_len, err))
359#define GlobusDsiRestErrorTimeOut() \
360 globus_error_put(GlobusDsiRestErrorTimeOutObject())
361#define GlobusDsiRestErrorThreadFail(rc) \
362 globus_error_put(GlobusDsiRestErrorThreadFailObject(rc))
363#define GlobusDsiRestErrorUnexpectedData(s, len) \
364 globus_error_put(GlobusDsiRestErrorUnexpectedDataObject(s, len))
365
366#define GlobusDsiRestErrorParameterObject() \
367 globus_error_construct_error( \
368 GLOBUS_DSI_REST_MODULE, \
369 NULL, \
370 GLOBUS_DSI_REST_ERROR_PARAMETER, \
371 __FILE__, \
372 __func__, \
373 __LINE__, \
374 "Invalid parameter")
375#define GlobusDsiRestErrorMemoryObject() \
376 globus_error_construct_error( \
377 GLOBUS_DSI_REST_MODULE, \
378 NULL, \
379 GLOBUS_DSI_REST_ERROR_MEMORY, \
380 __FILE__, \
381 __func__, \
382 __LINE__, \
383 "Out of memory")
384
385#define GlobusDsiRestErrorParseObject(s) \
386 globus_error_construct_error( \
387 GLOBUS_DSI_REST_MODULE, \
388 NULL, \
389 GLOBUS_DSI_REST_ERROR_PARSE, \
390 __FILE__, \
391 __func__, \
392 __LINE__, \
393 "Unable to parse %s", s)
394
395#define GlobusDsiRestErrorCurlObject(rc) \
396 globus_error_construct_error( \
397 GLOBUS_DSI_REST_MODULE, \
398 NULL, \
399 GLOBUS_DSI_REST_ERROR_CURL, \
400 __FILE__, \
401 __func__, \
402 __LINE__, \
403 "libcurl error %d: %s", rc, curl_easy_strerror(rc))
404#define GlobusDsiRestErrorJsonObject(buffer, buffer_len, err) \
405 globus_error_construct_error( \
406 GLOBUS_DSI_REST_MODULE, \
407 NULL, \
408 GLOBUS_DSI_REST_ERROR_JSON, \
409 __FILE__, \
410 __func__, \
411 __LINE__, \
412 "Error parsing \"%.*s\" as json: %s", \
413 (int) buffer_len, buffer, (err)->text)
414#define GlobusDsiRestErrorTimeOutObject() \
415 globus_error_construct_error( \
416 GLOBUS_DSI_REST_MODULE, \
417 NULL, \
418 GLOBUS_DSI_REST_ERROR_TIME_OUT, \
419 __FILE__, \
420 __func__, \
421 __LINE__, \
422 "Operation timed out")
423#define GlobusDsiRestErrorThreadFailObject(rc) \
424 globus_error_construct_error( \
425 GLOBUS_DSI_REST_MODULE, \
426 NULL, \
427 GLOBUS_DSI_REST_ERROR_THREAD_FAIL, \
428 __FILE__, \
429 __func__, \
430 __LINE__, \
431 "Thread create failed: %d", rc)
432#define GlobusDsiRestErrorUnexpectedDataObject(s,len) \
433 globus_error_construct_error( \
434 GLOBUS_DSI_REST_MODULE, \
435 NULL, \
436 GLOBUS_DSI_REST_ERROR_UNEXPECTED_DATA, \
437 __FILE__, \
438 __func__, \
439 __LINE__, \
440 "Unexpected data failed: %.*s", (int)len, s)
441
442/* Logging */
443GlobusDebugDeclare(GLOBUS_DSI_REST);
444
445enum
446{
447 GLOBUS_DSI_REST_DATA = 1<<0,
448 GLOBUS_DSI_REST_TRACE = 1<<1,
449 GLOBUS_DSI_REST_INFO = 1<<2,
450 GLOBUS_DSI_REST_DEBUG = 1<<3,
451 GLOBUS_DSI_REST_WARN = 1<<4,
452 GLOBUS_DSI_REST_ERROR = 1<<5,
453};
454
455extern const char * globus_i_dsi_rest_debug_level_names[];
456
457#define GlobusDsiRestLog(level, ...) \
458 do { \
459 int level__ = level; \
460 if (level__ > GLOBUS_DSI_REST_ERROR \
461 || level__ < 0 \
462 || globus_i_dsi_rest_debug_level_names[level__] == NULL) \
463 { \
464 level__ = 1; \
465 } \
466 if (GlobusDebugTrue(GLOBUS_DSI_REST, level__)) \
467 { \
468 flockfile(GlobusDebugMyFile(GLOBUS_DSI_REST)); \
469 GlobusDebugPrintf(GLOBUS_DSI_REST, level__, \
470 ("dsi_rest: %5s: %"PRIiMAX": %s: ", \
471 globus_i_dsi_rest_debug_level_names[level__], \
472 (intmax_t) getpid(), __func__)); \
473 GlobusDebugMyPrintf(GLOBUS_DSI_REST, \
474 (__VA_ARGS__)); \
475 funlockfile(GlobusDebugMyFile(GLOBUS_DSI_REST)); \
476 } \
477 } while (0)
478
479#define GlobusDsiRestData(...) GlobusDsiRestLog(GLOBUS_DSI_REST_DATA, __VA_ARGS__)
480#define GlobusDsiRestTrace(...) GlobusDsiRestLog(GLOBUS_DSI_REST_TRACE, __VA_ARGS__)
481#define GlobusDsiRestInfo(...) GlobusDsiRestLog(GLOBUS_DSI_REST_INFO, __VA_ARGS__)
482#define GlobusDsiRestDebug(...) GlobusDsiRestLog(GLOBUS_DSI_REST_DEBUG, __VA_ARGS__)
483#define GlobusDsiRestWarn(...) GlobusDsiRestLog(GLOBUS_DSI_REST_WARN, __VA_ARGS__)
484#define GlobusDsiRestError(...) GlobusDsiRestLog(GLOBUS_DSI_REST_ERROR, __VA_ARGS__)
485
486#define GlobusDsiRestEnter() GlobusDsiRestTrace("enter\n")
487#define GlobusDsiRestExit() GlobusDsiRestTrace("exit\n")
488#define GlobusDsiRestExitResult(result) \
489 do { \
490 if (GlobusDebugTrue(GLOBUS_DSI_REST, GLOBUS_DSI_REST_TRACE)) \
491 { \
492 if (result == GLOBUS_SUCCESS) \
493 {\
494 GlobusDsiRestTrace("exit: Success");\
495 }\
496 else\
497 {\
498 char *errstr; \
499 globus_object_t * obj = globus_error_peek(result); \
500 errstr = globus_error_print_friendly(obj); \
501 GlobusDsiRestTrace("exit: %#x: %s\n", (unsigned) result, errstr?errstr:"UNKNOWN ERROR"); \
502 if (errstr != NULL) \
503 { \
504 free(errstr); \
505 } \
506 }\
507 } \
508 } while (0)
509#define GlobusDsiRestExitSizeT(size) GlobusDsiRestTrace("exit: %zu\n", size)
510#define GlobusDsiRestExitInt(rc) GlobusDsiRestTrace("exit: %d\n", rc)
511#define GlobusDsiRestExitBool(rc) GlobusDsiRestTrace("exit: %s\n", rc?"true":"false")
512#define GlobusDsiRestExitPointer(p) GlobusDsiRestTrace("exit: %p\n", (void *)p)
513
514#define GlobusDsiRestLogResult(level, result) \
515 do { \
516 int __level = level; \
517 if (GlobusDebugTrue(GLOBUS_DSI_REST, (__level))) \
518 { \
519 globus_object_t * obj = globus_error_peek(result); \
520 char *errstr = obj?globus_error_print_friendly(obj):strdup("Success"); \
521 GlobusDsiRestLog(__level, "result=%#x message=%s\n", \
522 (unsigned int) result, \
523 errstr?errstr:"UNKNOWN ERROR"); \
524 free(errstr); \
525 } \
526 } while (0)
527
528extern globus_mutex_t globus_i_dsi_rest_handle_cache_mutex;
529extern size_t globus_i_dsi_rest_handle_cache_index;
530extern CURL *globus_i_dsi_rest_handle_cache[];
531extern CURLSH *globus_i_dsi_rest_share;
532
533enum { GLOBUS_I_DSI_REST_HANDLE_CACHE_SIZE = 16 };
534
535#ifdef __cplusplus
536}
537#endif
538
539#endif /* GLOBUS_DSI_REST_H */
540#endif /* GLOBUS_DONT_DOCUMENT_INTERNAL */
globus_result_t(* globus_dsi_rest_read_t)(void *read_callback_arg, void *buffer, size_t buffer_length)
Data Read Callback Signature.
Definition globus_dsi_rest.h:207
globus_result_t(* globus_dsi_rest_write_t)(void *write_callback_arg, void *buffer, size_t buffer_length, size_t *amount_copied)
Data Write Callback Signature.
Definition globus_dsi_rest.h:168
globus_result_t(* globus_dsi_rest_progress_t)(void *progress_callback_arg, uint64_t total_read, uint64_t amt_read, uint64_t total_written, uint64_t amt_written)
Request Progress Callback Signature.
Definition globus_dsi_rest.h:268
void(* globus_dsi_rest_complete_t)(void *complete_callback_arg, globus_result_t result)
Request Complete Callback Signature.
Definition globus_dsi_rest.h:230
globus_result_t(* globus_dsi_rest_response_t)(void *response_callback_arg, int response_code, const char *response_status, const globus_dsi_rest_key_array_t *response_headers)
Response Callback Signature.
Definition globus_dsi_rest.h:130
struct globus_dsi_rest_key_array_s globus_dsi_rest_key_array_t
Key-Value Pair Array.