17 #ifndef GLOBUS_DONT_DOCUMENT_INTERNAL
22 #ifndef GLOBUS_I_DSI_REST_H
23 #define GLOBUS_I_DSI_REST_H
29 #include "globus_i_gridftp_server_config.h"
33 #include "globus_common.h"
36 #include <curl/curl.h>
40 struct globus_i_dsi_rest_read_json_arg_s
47 globus_i_dsi_rest_read_json_arg_t;
50 globus_i_dsi_rest_buffer_s
54 uint64_t transfer_offset;
55 struct globus_i_dsi_rest_buffer_s *next;
56 unsigned char buffer[];
58 globus_i_dsi_rest_buffer_t;
61 globus_i_dsi_rest_idle_arg_s
63 globus_abstime_t last_activity;
64 uintptr_t idle_timeout;
65 uint64_t last_amt_read;
66 uint64_t last_amt_written;
68 globus_i_dsi_rest_idle_arg_t;
71 struct globus_i_dsi_rest_gridftp_op_arg_s
73 globus_gfs_operation_t op;
76 globus_result_t result;
86 globus_i_dsi_rest_buffer_t *pending_buffers;
87 globus_i_dsi_rest_buffer_t **pending_buffers_last;
89 globus_i_dsi_rest_buffer_t *current_buffer;
91 globus_i_dsi_rest_buffer_t *registered_buffers;
92 int registered_buffers_count;
94 globus_i_dsi_rest_buffer_t *free_buffers;
96 globus_i_dsi_rest_gridftp_op_arg_t;
100 struct globus_i_dsi_rest_write_multipart_arg_s
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
111 globus_i_dsi_rest_write_multipart_arg_t;
114 struct globus_i_dsi_rest_write_block_arg_s
123 globus_i_dsi_rest_write_block_arg_t;
126 struct globus_i_dsi_rest_write_blocks_arg_s
129 size_t current_block;
130 globus_i_dsi_rest_write_block_arg_t*blocks;
132 globus_i_dsi_rest_write_blocks_arg_t;
135 struct globus_i_dsi_rest_write_part_s
141 void *data_write_callback_arg;
143 globus_i_dsi_rest_write_part_t;
146 struct globus_i_dsi_rest_read_part_s
151 void *response_callback_arg;
154 void *data_read_callback_arg;
156 globus_i_dsi_rest_read_part_t;
159 struct globus_i_dsi_rest_read_multipart_arg_s
163 globus_i_dsi_rest_read_part_t *parts;
166 size_t boundary_length;
168 char *boundary_buffer;
169 size_t boundary_buffer_length;
170 size_t boundary_buffer_offset;
172 size_t match_counter;
176 size_t header_buffer_offset;
178 globus_i_dsi_rest_read_multipart_arg_t;
184 struct globus_i_dsi_rest_request_s
187 globus_result_t result;
190 char response_reason[64];
191 struct curl_slist *request_headers;
194 off_t request_bytes_uploaded;
195 off_t response_bytes_downloaded;
197 globus_i_dsi_rest_write_part_t write_part;
198 globus_i_dsi_rest_read_part_t read_part;
201 void *response_callback_arg;
204 void *complete_callback_arg;
207 void *progress_callback_arg;
209 globus_i_dsi_rest_idle_arg_t idle_arg;
211 uint64_t request_content_length;
212 bool request_content_length_set;
214 globus_i_dsi_rest_request_t;
231 globus_i_dsi_rest_handle_get(
247 globus_i_dsi_rest_handle_release(
252 globus_i_dsi_rest_compute_headers(
253 struct curl_slist **request_headers,
257 globus_i_dsi_rest_set_request(
261 struct curl_slist *headers,
262 const globus_dsi_rest_callbacks_t *callbacks);
265 globus_i_dsi_rest_add_header(
266 struct curl_slist **request_headers,
267 const char *header_name,
268 const char *header_value);
271 globus_i_dsi_rest_perform(
272 globus_i_dsi_rest_request_t *request);
275 globus_i_dsi_rest_encode_form_data(
279 globus_i_dsi_rest_buffer_t *
280 globus_i_dsi_rest_buffer_get(
281 globus_i_dsi_rest_gridftp_op_arg_t *gridftp_op_arg,
285 globus_i_dsi_rest_uri_escape(
291 globus_i_dsi_rest_multipart_boundary_prepare(
292 const char *delimiter,
296 size_t *boundary_lengthp);
299 globus_i_dsi_rest_request_cleanup(
300 globus_i_dsi_rest_request_t *request);
304 globus_i_dsi_rest_xferinfo(
312 globus_i_dsi_rest_progress(
320 globus_i_dsi_rest_header(
327 globus_i_dsi_rest_header_parse(
333 globus_i_dsi_rest_write_data(
340 globus_i_dsi_rest_read_data(
346 #define GlobusDsiRestErrorParameter() \
347 globus_error_put(GlobusDsiRestErrorParameterObject())
348 #define GlobusDsiRestErrorMemory() \
349 globus_error_put(GlobusDsiRestErrorMemoryObject())
350 #define GlobusDsiRestErrorParse(s) \
351 globus_error_put(GlobusDsiRestErrorParseObject(s))
352 #define GlobusDsiRestErrorCurl(rc) \
353 globus_error_put(GlobusDsiRestErrorCurlObject(rc))
354 #define GlobusDsiRestErrorJson(buffer, buffer_len, err) \
355 globus_error_put(GlobusDsiRestErrorJsonObject(buffer, buffer_len, err))
356 #define GlobusDsiRestErrorTimeOut() \
357 globus_error_put(GlobusDsiRestErrorTimeOutObject())
358 #define GlobusDsiRestErrorThreadFail(rc) \
359 globus_error_put(GlobusDsiRestErrorThreadFailObject(rc))
360 #define GlobusDsiRestErrorUnexpectedData(s, len) \
361 globus_error_put(GlobusDsiRestErrorUnexpectedDataObject(s, len))
363 #define GlobusDsiRestErrorParameterObject() \
364 globus_error_construct_error( \
365 GLOBUS_DSI_REST_MODULE, \
367 GLOBUS_DSI_REST_ERROR_PARAMETER, \
372 #define GlobusDsiRestErrorMemoryObject() \
373 globus_error_construct_error( \
374 GLOBUS_DSI_REST_MODULE, \
376 GLOBUS_DSI_REST_ERROR_MEMORY, \
382 #define GlobusDsiRestErrorParseObject(s) \
383 globus_error_construct_error( \
384 GLOBUS_DSI_REST_MODULE, \
386 GLOBUS_DSI_REST_ERROR_PARSE, \
390 "Unable to parse %s", s)
392 #define GlobusDsiRestErrorCurlObject(rc) \
393 globus_error_construct_error( \
394 GLOBUS_DSI_REST_MODULE, \
396 GLOBUS_DSI_REST_ERROR_CURL, \
400 "libcurl error %d: %s", rc, curl_easy_strerror(rc))
401 #define GlobusDsiRestErrorJsonObject(buffer, buffer_len, err) \
402 globus_error_construct_error( \
403 GLOBUS_DSI_REST_MODULE, \
405 GLOBUS_DSI_REST_ERROR_JSON, \
409 "Error parsing \"%.*s\" as json: %s", \
410 (int) buffer_len, buffer, (err)->text)
411 #define GlobusDsiRestErrorTimeOutObject() \
412 globus_error_construct_error( \
413 GLOBUS_DSI_REST_MODULE, \
415 GLOBUS_DSI_REST_ERROR_TIME_OUT, \
419 "Operation timed out")
420 #define GlobusDsiRestErrorThreadFailObject(rc) \
421 globus_error_construct_error( \
422 GLOBUS_DSI_REST_MODULE, \
424 GLOBUS_DSI_REST_ERROR_THREAD_FAIL, \
428 "Thread create failed: %d", rc)
429 #define GlobusDsiRestErrorUnexpectedDataObject(s,len) \
430 globus_error_construct_error( \
431 GLOBUS_DSI_REST_MODULE, \
433 GLOBUS_DSI_REST_ERROR_UNEXPECTED_DATA, \
437 "Unexpected data failed: %.*s", (int)len, s)
440 GlobusDebugDeclare(GLOBUS_DSI_REST);
444 GLOBUS_DSI_REST_DATA = 1<<0,
445 GLOBUS_DSI_REST_TRACE = 1<<1,
446 GLOBUS_DSI_REST_INFO = 1<<2,
447 GLOBUS_DSI_REST_DEBUG = 1<<3,
448 GLOBUS_DSI_REST_WARN = 1<<4,
449 GLOBUS_DSI_REST_ERROR = 1<<5,
452 extern const char * globus_i_dsi_rest_debug_level_names[];
454 #define GlobusDsiRestLog(level, ...) \
456 int level__ = level; \
457 if (level__ > GLOBUS_DSI_REST_ERROR \
459 || globus_i_dsi_rest_debug_level_names[level__] == NULL) \
463 if (GlobusDebugTrue(GLOBUS_DSI_REST, level__)) \
465 flockfile(GlobusDebugMyFile(GLOBUS_DSI_REST)); \
466 GlobusDebugPrintf(GLOBUS_DSI_REST, level__, \
467 ("dsi_rest: %5s: %"PRIiMAX": %s: ", \
468 globus_i_dsi_rest_debug_level_names[level__], \
469 (intmax_t) getpid(), __func__)); \
470 GlobusDebugMyPrintf(GLOBUS_DSI_REST, \
472 funlockfile(GlobusDebugMyFile(GLOBUS_DSI_REST)); \
476 #define GlobusDsiRestData(...) GlobusDsiRestLog(GLOBUS_DSI_REST_DATA, __VA_ARGS__)
477 #define GlobusDsiRestTrace(...) GlobusDsiRestLog(GLOBUS_DSI_REST_TRACE, __VA_ARGS__)
478 #define GlobusDsiRestInfo(...) GlobusDsiRestLog(GLOBUS_DSI_REST_INFO, __VA_ARGS__)
479 #define GlobusDsiRestDebug(...) GlobusDsiRestLog(GLOBUS_DSI_REST_DEBUG, __VA_ARGS__)
480 #define GlobusDsiRestWarn(...) GlobusDsiRestLog(GLOBUS_DSI_REST_WARN, __VA_ARGS__)
481 #define GlobusDsiRestError(...) GlobusDsiRestLog(GLOBUS_DSI_REST_ERROR, __VA_ARGS__)
483 #define GlobusDsiRestEnter() GlobusDsiRestTrace("enter\n")
484 #define GlobusDsiRestExit() GlobusDsiRestTrace("exit\n")
485 #define GlobusDsiRestExitResult(result) \
487 if (GlobusDebugTrue(GLOBUS_DSI_REST, GLOBUS_DSI_REST_TRACE)) \
489 globus_object_t * obj = globus_error_peek(result); \
490 char *errstr = obj?globus_error_print_friendly(obj):strdup("Success"); \
491 GlobusDsiRestTrace("exit: %#x: %s\n", (unsigned) result, errstr?errstr:"UNKNOWN ERROR"); \
495 #define GlobusDsiRestExitSizeT(size) GlobusDsiRestTrace("exit: %zu\n", size)
496 #define GlobusDsiRestExitInt(rc) GlobusDsiRestTrace("exit: %d\n", rc)
497 #define GlobusDsiRestExitBool(rc) GlobusDsiRestTrace("exit: %s\n", rc?"true":"false")
498 #define GlobusDsiRestExitPointer(p) GlobusDsiRestTrace("exit: %p\n", (void *)p)
500 #define GlobusDsiRestLogResult(level, result) \
502 int __level = level; \
503 if (GlobusDebugTrue(GLOBUS_DSI_REST, (__level))) \
505 globus_object_t * obj = globus_error_peek(result); \
506 char *errstr = obj?globus_error_print_friendly(obj):strdup("Success"); \
507 GlobusDsiRestLog(__level, "result=%#x message=%s\n", \
508 (unsigned int) result, \
509 errstr?errstr:"UNKNOWN ERROR"); \
514 extern globus_mutex_t globus_i_dsi_rest_handle_cache_mutex;
515 extern size_t globus_i_dsi_rest_handle_cache_index;
516 extern CURL *globus_i_dsi_rest_handle_cache[];
517 extern CURLSH *globus_i_dsi_rest_share;
519 enum { GLOBUS_I_DSI_REST_HANDLE_CACHE_SIZE = 16 };