globus_connect_gridftp_server  15.95
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
18 
22 #ifndef GLOBUS_I_DSI_REST_H
23 #define GLOBUS_I_DSI_REST_H
24 
25 #ifdef __cplusplus
26 extern "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"
34 #include "globus_gridftp_server.h"
35 
36 #include <curl/curl.h>
37 #include <jansson.h>
38 
39 typedef
40 struct 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 }
47 globus_i_dsi_rest_read_json_arg_t;
48 
49 typedef struct
50 globus_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 }
58 globus_i_dsi_rest_buffer_t;
59 
60 typedef struct
61 globus_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 }
68 globus_i_dsi_rest_idle_arg_t;
69 
70 typedef
71 struct 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 }
96 globus_i_dsi_rest_gridftp_op_arg_t;
97 
98 
99 typedef
100 struct 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 }
111 globus_i_dsi_rest_write_multipart_arg_t;
112 
113 typedef
114 struct globus_i_dsi_rest_write_block_arg_s
115 {
117  void *block_data;
119  size_t block_len;
121  size_t offset;
122 }
123 globus_i_dsi_rest_write_block_arg_t;
124 
125 typedef
126 struct 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 }
132 globus_i_dsi_rest_write_blocks_arg_t;
133 
134 typedef
135 struct 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 }
143 globus_i_dsi_rest_write_part_t;
144 
145 typedef
146 struct 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_i_dsi_rest_read_part_t;
157 
158 typedef
159 struct globus_i_dsi_rest_read_multipart_arg_s
160 {
161  size_t num_parts;
162  size_t part_index;
163  globus_i_dsi_rest_read_part_t *parts;
164 
165  char *boundary;
166  size_t boundary_length;
167 
168  char *boundary_buffer;
169  size_t boundary_buffer_length;
170  size_t boundary_buffer_offset;
171 
172  size_t match_counter;
173 
174  bool need_header;
175  char *header_buffer;
176  size_t header_buffer_offset;
177 }
178 globus_i_dsi_rest_read_multipart_arg_t;
179 
183 typedef
184 struct globus_i_dsi_rest_request_s
185 {
186  CURL *handle;
187  globus_result_t result;
188  const char *method;
189  int response_code;
190  char response_reason[64];
191  struct curl_slist *request_headers;
192  char *complete_uri;
193 
194  off_t request_bytes_uploaded;
195  off_t response_bytes_downloaded;
196 
197  globus_i_dsi_rest_write_part_t write_part;
198  globus_i_dsi_rest_read_part_t read_part;
199 
200  globus_dsi_rest_response_t response_callback;
201  void *response_callback_arg;
202 
203  globus_dsi_rest_complete_t complete_callback;
204  void *complete_callback_arg;
205 
206  globus_dsi_rest_progress_t progress_callback;
207  void *progress_callback_arg;
208 
209  globus_i_dsi_rest_idle_arg_t idle_arg;
210 
211  uint64_t request_content_length;
212  bool request_content_length_set;
213 }
214 globus_i_dsi_rest_request_t;
215 
230 globus_result_t
231 globus_i_dsi_rest_handle_get(
232  CURL **handlep,
233  void *callback_arg);
234 
246 void
247 globus_i_dsi_rest_handle_release(
248  CURL *handle);
249 
250 
251 globus_result_t
252 globus_i_dsi_rest_compute_headers(
253  struct curl_slist **request_headers,
254  const globus_dsi_rest_key_array_t *headers);
255 
256 globus_result_t
257 globus_i_dsi_rest_set_request(
258  CURL *curl,
259  const char *method,
260  const char *uri,
261  struct curl_slist *headers,
262  const globus_dsi_rest_callbacks_t *callbacks);
263 
264 globus_result_t
265 globus_i_dsi_rest_add_header(
266  struct curl_slist **request_headers,
267  const char *header_name,
268  const char *header_value);
269 
270 globus_result_t
271 globus_i_dsi_rest_perform(
272  globus_i_dsi_rest_request_t *request);
273 
274 globus_result_t
275 globus_i_dsi_rest_encode_form_data(
276  const globus_dsi_rest_key_array_t *form_fields,
277  char **form_datap);
278 
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,
282  size_t size);
283 
284 void
285 globus_i_dsi_rest_uri_escape(
286  const char *raw,
287  char **encodedp,
288  size_t *availablep);
289 
290 globus_result_t
291 globus_i_dsi_rest_multipart_boundary_prepare(
292  const char *delimiter,
293  bool final,
294  globus_dsi_rest_key_array_t *part_header,
295  char **boundaryp,
296  size_t *boundary_lengthp);
297 
298 void
299 globus_i_dsi_rest_request_cleanup(
300  globus_i_dsi_rest_request_t *request);
301 
302 /* Callbacks that are passed to libcurl that cause user-specific callbacks */
303 int
304 globus_i_dsi_rest_xferinfo(
305  void *callback_arg,
306  curl_off_t dltotal,
307  curl_off_t dlnow,
308  curl_off_t ultotal,
309  curl_off_t ulnow);
310 
311 int
312 globus_i_dsi_rest_progress(
313  void *callback_arg,
314  double dltotal,
315  double dlnow,
316  double ultotal,
317  double ulnow);
318 
319 size_t
320 globus_i_dsi_rest_header(
321  char *buffer,
322  size_t size,
323  size_t nitems,
324  void *callback_arg);
325 
326 globus_result_t
327 globus_i_dsi_rest_header_parse(
329  char *buffer,
330  size_t size);
331 
332 size_t
333 globus_i_dsi_rest_write_data(
334  char *ptr,
335  size_t size,
336  size_t nmemb,
337  void *callback_arg);
338 
339 size_t
340 globus_i_dsi_rest_read_data(
341  char *buffer,
342  size_t size,
343  size_t nitems,
344  void *callback_arg);
345 
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))
362 
363 #define GlobusDsiRestErrorParameterObject() \
364  globus_error_construct_error( \
365  GLOBUS_DSI_REST_MODULE, \
366  NULL, \
367  GLOBUS_DSI_REST_ERROR_PARAMETER, \
368  __FILE__, \
369  __func__, \
370  __LINE__, \
371  "Invalid parameter")
372 #define GlobusDsiRestErrorMemoryObject() \
373  globus_error_construct_error( \
374  GLOBUS_DSI_REST_MODULE, \
375  NULL, \
376  GLOBUS_DSI_REST_ERROR_MEMORY, \
377  __FILE__, \
378  __func__, \
379  __LINE__, \
380  "Out of memory")
381 
382 #define GlobusDsiRestErrorParseObject(s) \
383  globus_error_construct_error( \
384  GLOBUS_DSI_REST_MODULE, \
385  NULL, \
386  GLOBUS_DSI_REST_ERROR_PARSE, \
387  __FILE__, \
388  __func__, \
389  __LINE__, \
390  "Unable to parse %s", s)
391 
392 #define GlobusDsiRestErrorCurlObject(rc) \
393  globus_error_construct_error( \
394  GLOBUS_DSI_REST_MODULE, \
395  NULL, \
396  GLOBUS_DSI_REST_ERROR_CURL, \
397  __FILE__, \
398  __func__, \
399  __LINE__, \
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, \
404  NULL, \
405  GLOBUS_DSI_REST_ERROR_JSON, \
406  __FILE__, \
407  __func__, \
408  __LINE__, \
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, \
414  NULL, \
415  GLOBUS_DSI_REST_ERROR_TIME_OUT, \
416  __FILE__, \
417  __func__, \
418  __LINE__, \
419  "Operation timed out")
420 #define GlobusDsiRestErrorThreadFailObject(rc) \
421  globus_error_construct_error( \
422  GLOBUS_DSI_REST_MODULE, \
423  NULL, \
424  GLOBUS_DSI_REST_ERROR_THREAD_FAIL, \
425  __FILE__, \
426  __func__, \
427  __LINE__, \
428  "Thread create failed: %d", rc)
429 #define GlobusDsiRestErrorUnexpectedDataObject(s,len) \
430  globus_error_construct_error( \
431  GLOBUS_DSI_REST_MODULE, \
432  NULL, \
433  GLOBUS_DSI_REST_ERROR_UNEXPECTED_DATA, \
434  __FILE__, \
435  __func__, \
436  __LINE__, \
437  "Unexpected data failed: %.*s", (int)len, s)
438 
439 /* Logging */
440 GlobusDebugDeclare(GLOBUS_DSI_REST);
441 
442 enum
443 {
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,
450 };
451 
452 extern const char * globus_i_dsi_rest_debug_level_names[];
453 
454 #define GlobusDsiRestLog(level, ...) \
455  do { \
456  int level__ = level; \
457  if (level__ > GLOBUS_DSI_REST_ERROR \
458  || level__ < 0 \
459  || globus_i_dsi_rest_debug_level_names[level__] == NULL) \
460  { \
461  level__ = 1; \
462  } \
463  if (GlobusDebugTrue(GLOBUS_DSI_REST, level__)) \
464  { \
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, \
471  (__VA_ARGS__)); \
472  funlockfile(GlobusDebugMyFile(GLOBUS_DSI_REST)); \
473  } \
474  } while (0)
475 
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__)
482 
483 #define GlobusDsiRestEnter() GlobusDsiRestTrace("enter\n")
484 #define GlobusDsiRestExit() GlobusDsiRestTrace("exit\n")
485 #define GlobusDsiRestExitResult(result) \
486  do { \
487  if (GlobusDebugTrue(GLOBUS_DSI_REST, GLOBUS_DSI_REST_TRACE)) \
488  { \
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"); \
492  free(errstr); \
493  } \
494  } while (0)
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)
499 
500 #define GlobusDsiRestLogResult(level, result) \
501  do { \
502  int __level = level; \
503  if (GlobusDebugTrue(GLOBUS_DSI_REST, (__level))) \
504  { \
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"); \
510  free(errstr); \
511  } \
512  } while (0)
513 
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;
518 
519 enum { GLOBUS_I_DSI_REST_HANDLE_CACHE_SIZE = 16 };
520 
521 #ifdef __cplusplus
522 }
523 #endif
524 
525 #endif /* GLOBUS_DSI_REST_H */
526 #endif /* GLOBUS_DONT_DOCUMENT_INTERNAL */
globus_dsi_rest_complete_t
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_dsi_rest_key_array_s
Key-Value Pair Array.
Definition: globus_dsi_rest.h:90
globus_dsi_rest_write_t
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_dsi_rest_progress_t
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
globus_dsi_rest.h
globus_gridftp_server.h
globus_dsi_rest_response_t
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
globus_dsi_rest_read_t
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