globus_dsi_rest  0.18
 All Data Structures Files Functions Variables Typedefs Groups Pages
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 <stdbool.h>
30 
31 #include "globus_dsi_rest.h"
32 #include "globus_common.h"
33 #include "globus_gridftp_server.h"
34 
35 #include <curl/curl.h>
36 #include <jansson.h>
37 
38 typedef
39 struct globus_i_dsi_rest_read_json_arg_s
40 {
41  size_t buffer_used;
42  size_t buffer_len;
43  char *buffer;
44  json_t **json_out;
45 }
46 globus_i_dsi_rest_read_json_arg_t;
47 
48 typedef struct
49 globus_i_dsi_rest_buffer_s
50 {
51  size_t buffer_len;
52  size_t buffer_used;
53  uint64_t transfer_offset;
54  struct globus_i_dsi_rest_buffer_s *next;
55  unsigned char buffer[];
56 }
57 globus_i_dsi_rest_buffer_t;
58 
59 typedef struct
60 globus_i_dsi_rest_idle_arg_s
61 {
62  globus_abstime_t last_activity;
63  uintptr_t idle_timeout;
64  uint64_t last_amt_read;
65  uint64_t last_amt_written;
66 }
67 globus_i_dsi_rest_idle_arg_t;
68 
69 typedef
70 struct globus_i_dsi_rest_gridftp_op_arg_s
71 {
72  globus_gfs_operation_t op;
73  globus_mutex_t mutex;
74  globus_cond_t cond;
75  globus_result_t result;
76 
77  uint64_t offset;
78  uint64_t end_offset;
79  // If we hit EOF or end of expected read
80  bool eof;
81  // Points to app's gridftp_op_arg's eof field, only set to true
82  // if we get an eof response from the GridFTP server.
83  bool *eofp;
84 
85  globus_i_dsi_rest_buffer_t *pending_buffers;
86  globus_i_dsi_rest_buffer_t **pending_buffers_last;
87  globus_i_dsi_rest_buffer_t *current_buffer;
88  globus_i_dsi_rest_buffer_t *registered_buffers;
89  globus_i_dsi_rest_buffer_t *free_buffers;
90 }
91 globus_i_dsi_rest_gridftp_op_arg_t;
92 
93 
94 typedef
95 struct globus_i_dsi_rest_multipart_arg_s
96 {
97  char *boundary;
98  size_t num_parts;
99  size_t part_index;
100  char *current_boundary;
101  size_t current_boundary_offset;
102  size_t current_boundary_length;
103  struct globus_i_dsi_rest_part_s *parts;
104 }
105 globus_i_dsi_rest_multipart_arg_t;
106 
107 typedef
108 struct globus_i_dsi_rest_part_s
109 {
111  globus_dsi_rest_key_array_t malloced_headers;
112 
113  globus_dsi_rest_write_t data_write_callback;
114  void *data_write_callback_arg;
115 
116  globus_dsi_rest_write_block_arg_t write_block_callback_arg;
117  globus_dsi_rest_write_block_arg_t write_block_callback_arg_orig;
118  globus_i_dsi_rest_gridftp_op_arg_t gridftp_op_arg;
119  globus_i_dsi_rest_multipart_arg_t multipart_write_arg;
120 }
121 globus_i_dsi_rest_part_t;
122 
126 typedef
127 struct globus_i_dsi_rest_request_s
128 {
129  CURL *handle;
130  globus_result_t result;
131  const char *method;
132  int response_code;
133  char response_reason[64];
134  struct curl_slist *request_headers;
135  globus_dsi_rest_key_array_t response_headers;
136  char *complete_uri;
137 
138  off_t request_bytes_uploaded;
139  off_t response_bytes_downloaded;
140 
141  globus_thread_t thread;
142 
143  globus_i_dsi_rest_part_t write_part;
144  globus_i_dsi_rest_read_json_arg_t read_json_arg;
145  globus_i_dsi_rest_gridftp_op_arg_t read_gridftp_op_arg;
146 
147  globus_dsi_rest_read_t data_read_callback;
148  void *data_read_callback_arg;
149 
150  globus_dsi_rest_response_t response_callback;
151  void *response_callback_arg;
152 
153  globus_dsi_rest_complete_t complete_callback;
154  void *complete_callback_arg;
155 
156  globus_dsi_rest_progress_t progress_callback;
157  void *progress_callback_arg;
158 
159  globus_i_dsi_rest_idle_arg_t idle_arg;
160 
161  uint64_t request_content_length;
162  bool request_content_length_set;
163 }
164 globus_i_dsi_rest_request_t;
165 
180 globus_result_t
181 globus_i_dsi_rest_handle_get(
182  CURL **handlep,
183  void *callback_arg);
184 
196 void
197 globus_i_dsi_rest_handle_release(
198  CURL *handle);
199 
200 
201 globus_result_t
202 globus_i_dsi_rest_compute_headers(
203  struct curl_slist **request_headers,
204  const globus_dsi_rest_key_array_t *headers);
205 
206 globus_result_t
207 globus_i_dsi_rest_set_request(
208  CURL *curl,
209  const char *method,
210  const char *uri,
211  struct curl_slist *headers,
212  const globus_dsi_rest_callbacks_t *callbacks);
213 
214 globus_result_t
215 globus_i_dsi_rest_add_header(
216  struct curl_slist **request_headers,
217  const char *header_name,
218  const char *header_value);
219 
220 globus_result_t
221 globus_i_dsi_rest_perform(
222  globus_i_dsi_rest_request_t *request);
223 
224 globus_result_t
225 globus_i_dsi_rest_encode_form_data(
226  const globus_dsi_rest_key_array_t *form_fields,
227  char **form_datap);
228 
229 globus_i_dsi_rest_buffer_t *
230 globus_i_dsi_rest_buffer_get(
231  globus_i_dsi_rest_gridftp_op_arg_t *gridftp_op_arg,
232  size_t size);
233 
234 void
235 globus_i_dsi_rest_uri_escape(
236  const char *raw,
237  char **encodedp,
238  size_t *availablep);
239 
240 globus_result_t
241 globus_i_dsi_rest_multipart_boundary_prepare(
242  const char *delimiter,
243  bool final,
244  globus_dsi_rest_key_array_t *part_header,
245  char **boundaryp,
246  size_t *boundary_lengthp);
247 
248 void
249 globus_i_dsi_rest_request_cleanup(
250  globus_i_dsi_rest_request_t *request);
251 
252 /* Callbacks that are passed to libcurl that cause user-specific callbacks */
253 int
254 globus_i_dsi_rest_xferinfo(
255  void *callback_arg,
256  curl_off_t dltotal,
257  curl_off_t dlnow,
258  curl_off_t ultotal,
259  curl_off_t ulnow);
260 
261 int
262 globus_i_dsi_rest_progress(
263  void *callback_arg,
264  double dltotal,
265  double dlnow,
266  double ultotal,
267  double ulnow);
268 
269 size_t
270 globus_i_dsi_rest_header(
271  char *buffer,
272  size_t size,
273  size_t nitems,
274  void *callback_arg);
275 
276 size_t
277 globus_i_dsi_rest_write_data(
278  char *ptr,
279  size_t size,
280  size_t nmemb,
281  void *callback_arg);
282 
283 size_t
284 globus_i_dsi_rest_read_data(
285  char *buffer,
286  size_t size,
287  size_t nitems,
288  void *callback_arg);
289 
290 enum
291 {
292  GLOBUS_DSI_REST_ERROR_PARAMETER = 1,
293  GLOBUS_DSI_REST_ERROR_MEMORY,
294  GLOBUS_DSI_REST_ERROR_PARSE,
295  GLOBUS_DSI_REST_ERROR_CURL,
296  GLOBUS_DSI_REST_ERROR_JSON,
297  GLOBUS_DSI_REST_ERROR_TIME_OUT,
298  GLOBUS_DSI_REST_ERROR_THREAD_FAIL,
299  GLOBUS_DSI_REST_ERROR_UNEXPECTED_DATA,
300 };
301 
302 #define GlobusDsiRestErrorParameter() \
303  globus_error_put(GlobusDsiRestErrorParameterObject())
304 #define GlobusDsiRestErrorMemory() \
305  globus_error_put(GlobusDsiRestErrorMemoryObject())
306 #define GlobusDsiRestErrorParse(s) \
307  globus_error_put(GlobusDsiRestErrorParseObject(s))
308 #define GlobusDsiRestErrorCurl(rc) \
309  globus_error_put(GlobusDsiRestErrorCurlObject(rc))
310 #define GlobusDsiRestErrorJson(err) \
311  globus_error_put(GlobusDsiRestErrorJsonObject(err))
312 #define GlobusDsiRestErrorTimeOut() \
313  globus_error_put(GlobusDsiRestErrorTimeOutObject())
314 #define GlobusDsiRestErrorThreadFail(rc) \
315  globus_error_put(GlobusDsiRestErrorThreadFailObject(rc))
316 #define GlobusDsiRestErrorUnexpectedData(s, len) \
317  globus_error_put(GlobusDsiRestErrorUnexpectedDataObject(s, len))
318 
319 #define GlobusDsiRestErrorParameterObject() \
320  globus_error_construct_error( \
321  GLOBUS_DSI_REST_MODULE, \
322  NULL, \
323  GLOBUS_DSI_REST_ERROR_PARAMETER, \
324  __FILE__, \
325  __func__, \
326  __LINE__, \
327  "Invalid parameter")
328 #define GlobusDsiRestErrorMemoryObject() \
329  globus_error_construct_error( \
330  GLOBUS_DSI_REST_MODULE, \
331  NULL, \
332  GLOBUS_DSI_REST_ERROR_MEMORY, \
333  __FILE__, \
334  __func__, \
335  __LINE__, \
336  "Out of memory")
337 
338 #define GlobusDsiRestErrorParseObject(s) \
339  globus_error_construct_error( \
340  GLOBUS_DSI_REST_MODULE, \
341  NULL, \
342  GLOBUS_DSI_REST_ERROR_PARSE, \
343  __FILE__, \
344  __func__, \
345  __LINE__, \
346  "Unable to parse %s", s)
347 
348 #define GlobusDsiRestErrorCurlObject(rc) \
349  globus_error_construct_error( \
350  GLOBUS_DSI_REST_MODULE, \
351  NULL, \
352  GLOBUS_DSI_REST_ERROR_CURL, \
353  __FILE__, \
354  __func__, \
355  __LINE__, \
356  "libcurl error %d: %s", rc, curl_easy_strerror(rc))
357 #define GlobusDsiRestErrorJsonObject(err) \
358  globus_error_construct_error( \
359  GLOBUS_DSI_REST_MODULE, \
360  NULL, \
361  GLOBUS_DSI_REST_ERROR_JSON, \
362  __FILE__, \
363  __func__, \
364  __LINE__, \
365  "json error %s", (err)->text)
366 #define GlobusDsiRestErrorTimeOutObject() \
367  globus_error_construct_error( \
368  GLOBUS_DSI_REST_MODULE, \
369  NULL, \
370  GLOBUS_DSI_REST_ERROR_TIME_OUT, \
371  __FILE__, \
372  __func__, \
373  __LINE__, \
374  "Operation timed out")
375 #define GlobusDsiRestErrorThreadFailObject(rc) \
376  globus_error_construct_error( \
377  GLOBUS_DSI_REST_MODULE, \
378  NULL, \
379  GLOBUS_DSI_REST_ERROR_THREAD_FAIL, \
380  __FILE__, \
381  __func__, \
382  __LINE__, \
383  "Thread create failed: %d", rc)
384 #define GlobusDsiRestErrorUnexpectedDataObject(s,len) \
385  globus_error_construct_error( \
386  GLOBUS_DSI_REST_MODULE, \
387  NULL, \
388  GLOBUS_DSI_REST_ERROR_UNEXPECTED_DATA, \
389  __FILE__, \
390  __func__, \
391  __LINE__, \
392  "Unexpected data failed: %.*s", (int)len, s)
393 
394 /* Logging */
395 GlobusDebugDeclare(GLOBUS_DSI_REST);
396 
397 enum
398 {
399  GLOBUS_DSI_REST_DATA = 1<<0,
400  GLOBUS_DSI_REST_TRACE = 1<<1,
401  GLOBUS_DSI_REST_INFO = 1<<2,
402  GLOBUS_DSI_REST_DEBUG = 1<<3,
403  GLOBUS_DSI_REST_WARN = 1<<4,
404  GLOBUS_DSI_REST_ERROR = 1<<5,
405 };
406 
407 extern const char * globus_i_dsi_rest_debug_level_names[];
408 
409 #define GlobusDsiRestLog(level, ...) \
410  do { \
411  int level__ = level; \
412  if (level__ > GLOBUS_DSI_REST_ERROR || level__ < 0) { \
413  level__ = 1; \
414  } \
415  if (GlobusDebugTrue(GLOBUS_DSI_REST, level__)) \
416  { \
417  flockfile(GlobusDebugMyFile(GLOBUS_DSI_REST)); \
418  GlobusDebugPrintf(GLOBUS_DSI_REST, level__, \
419  ("dsi_rest: %5s: %"PRIiMAX": %s: ", \
420  globus_i_dsi_rest_debug_level_names[level__], \
421  (intmax_t) getpid(), __func__)); \
422  GlobusDebugMyPrintf(GLOBUS_DSI_REST, \
423  (__VA_ARGS__)); \
424  funlockfile(GlobusDebugMyFile(GLOBUS_DSI_REST)); \
425  } \
426  } while (0)
427 
428 #define GlobusDsiRestData(...) GlobusDsiRestLog(GLOBUS_DSI_REST_DATA, __VA_ARGS__)
429 #define GlobusDsiRestTrace(...) GlobusDsiRestLog(GLOBUS_DSI_REST_TRACE, __VA_ARGS__)
430 #define GlobusDsiRestInfo(...) GlobusDsiRestLog(GLOBUS_DSI_REST_INFO, __VA_ARGS__)
431 #define GlobusDsiRestDebug(...) GlobusDsiRestLog(GLOBUS_DSI_REST_DEBUG, __VA_ARGS__)
432 #define GlobusDsiRestWarn(...) GlobusDsiRestLog(GLOBUS_DSI_REST_WARN, __VA_ARGS__)
433 #define GlobusDsiRestError(...) GlobusDsiRestLog(GLOBUS_DSI_REST_ERROR, __VA_ARGS__)
434 
435 #define GlobusDsiRestEnter() GlobusDsiRestTrace("enter\n")
436 #define GlobusDsiRestExit() GlobusDsiRestTrace("exit\n")
437 #define GlobusDsiRestExitResult(result) \
438  do { \
439  if (GlobusDebugTrue(GLOBUS_DSI_REST, GLOBUS_DSI_REST_TRACE)) \
440  { \
441  globus_object_t * obj = globus_error_peek(result); \
442  char *errstr = obj?globus_error_print_friendly(obj):strdup("Success"); \
443  GlobusDsiRestTrace("exit: %#x: %s\n", (unsigned) result, errstr?errstr:"UNKNOWN ERROR"); \
444  free(errstr); \
445  } \
446  } while (0)
447 #define GlobusDsiRestExitSizeT(size) GlobusDsiRestTrace("exit: %zu\n", size)
448 #define GlobusDsiRestExitInt(rc) GlobusDsiRestTrace("exit: %d\n", rc)
449 #define GlobusDsiRestExitBool(rc) GlobusDsiRestTrace("exit: %s\n", rc?"true":"false")
450 #define GlobusDsiRestExitPointer(p) GlobusDsiRestTrace("exit: %p\n", (void *)p)
451 
452 #define GlobusDsiRestLogResult(level, result) \
453  do { \
454  int __level = level; \
455  if (GlobusDebugTrue(GLOBUS_DSI_REST, (__level))) \
456  { \
457  globus_object_t * obj = globus_error_peek(result); \
458  char *errstr = obj?globus_error_print_friendly(obj):strdup("Success"); \
459  GlobusDsiRestLog(__level, "result=%#x message=%s\n", \
460  (unsigned int) result, \
461  errstr?errstr:"UNKNOWN ERROR"); \
462  free(errstr); \
463  } \
464  } while (0)
465 
466 extern globus_mutex_t globus_i_dsi_rest_handle_cache_mutex;
467 extern size_t globus_i_dsi_rest_handle_cache_index;
468 extern CURL *globus_i_dsi_rest_handle_cache[];
469 
470 enum { GLOBUS_I_DSI_REST_HANDLE_CACHE_SIZE = 16 };
471 
472 #ifdef __cplusplus
473 }
474 #endif
475 
476 #endif /* GLOBUS_DSI_REST_H */
477 #endif /* GLOBUS_DONT_DOCUMENT_INTERNAL */
Key-Value Pair Array.
Definition: globus_dsi_rest.h:90
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_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_read_t)(void *read_callback_arg, void *buffer, size_t buffer_length)
Data Read Callback Signature.
Definition: globus_dsi_rest.h:207
Single-block write specialization data_write_callback_arg.
Definition: globus_dsi_rest.h:427
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