DS3 C SDK  4.1.0
Provides access to the Spectra S3 API with C
ds3_net.c
Go to the documentation of this file.
1 
2 /*
3  * ******************************************************************************
4  * Copyright 2014-2017 Spectra Logic Corporation. All Rights Reserved.
5  * Licensed under the Apache License, Version 2.0 (the "License"). You may not use
6  * this file except in compliance with the License. A copy of the License is located at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * or in the "license" file accompanying this file.
11  * This file is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
12  * CONDITIONS OF ANY KIND, either express or implied. See the License for the
13  * specific language governing permissions and limitations under the License.
14  * ****************************************************************************
15  */
16 
17 /* This Code is Auto-Generated; DO NOT MODIFY! */
18 
19 
20 #include <curl/curl.h>
21 
22 #include "ds3_request.h"
23 #include "ds3_net.h"
24 #include "ds3_utils.h"
26 #include "ds3_connection.h"
27 
28 static void _init_curl(void) {
29  static ds3_bool initialized = False;
30 
31  if (!initialized) {
32  if (curl_global_init(CURL_GLOBAL_ALL) != 0) {
33  fprintf(stderr, "Encountered an error initializing libcurl\n");
34  }
35  initialized = True;
36  }
37 }
38 
39 static char* _net_get_verb(http_verb verb) {
40  switch(verb) {
41  case HTTP_GET: return "GET";
42  case HTTP_PUT: return "PUT";
43  case HTTP_POST: return "POST";
44  case HTTP_DELETE : return "DELETE";
45  case HTTP_HEAD : return "HEAD";
46  }
47 
48  return NULL;
49 }
50 
51 static char* _get_checksum_type_header(const ds3_checksum_type type) {
52  switch(type) {
53  case DS3_CHECKSUM_TYPE_MD5: return "Content-MD5:";
54  case DS3_CHECKSUM_TYPE_SHA_256: return "Content-SHA256:";
55  case DS3_CHECKSUM_TYPE_SHA_512: return "Content-SHA512:";
56  case DS3_CHECKSUM_TYPE_CRC_32: return "Content-CRC32:";
57  case DS3_CHECKSUM_TYPE_CRC_32C: return "Content-CRC32C:";
58  }
59 
60  return NULL;
61 }
62 
63 
64 // curl_easy_escape'd strings must be freed using curl_free. Copy
65 // the escaped string, using glib, since users of this function will
66 // eventually wind up freeing it with g_free.
67 char* escape_url(const char* url) {
68  char* curl_escaped_url = curl_easy_escape(NULL, url, 0);
69  char* escaped_url = g_strdup(curl_escaped_url);
70  curl_free(curl_escaped_url);
71  return escaped_url;
72 }
73 
74 // Like escape_url but don't encode the given delimiters.
75 char* escape_url_extended(const char* url, const char** delimiters, uint32_t num_delimiters) {
76  gchar** split = g_strsplit(url, delimiters[num_delimiters-1], 0);
77  gchar** ptr;
78  gchar* escaped_ptr;
79  for (ptr = split; *ptr; ptr++) {
80  if( num_delimiters > 1){
81  escaped_ptr = escape_url_extended(*ptr, delimiters, num_delimiters-1);
82  }else{
83  escaped_ptr = escape_url(*ptr);
84  }
85  g_free(*ptr);
86  *ptr = escaped_ptr;
87  }
88  escaped_ptr = g_strjoinv(delimiters[num_delimiters-1], split);
89  g_strfreev(split);
90  return escaped_ptr;
91 }
92 
93 // Like escape_url but don't encode "/".
94 char* escape_url_object_name(const char* url) {
95  const char *delimiters[1]={"/"};
96  return escape_url_extended(url, delimiters, 1);
97 }
98 
99 // Like escape_url but don't encode "=".
100 char* escape_url_range_header(const char* url) {
101  const char *delimiters[2]={"=", ","};
102  return escape_url_extended(url, delimiters, 2);
103 }
104 
105 static unsigned char* _generate_signature_str(http_verb verb, char* resource_name, char* date,
106  char* content_type, char* checksum_value, char* amz_headers) {
107  char* verb_str;
108  if (resource_name == NULL) {
109  fprintf(stderr, "resource_name is required\n");
110  return NULL;
111  }
112  if (date == NULL) {
113  fprintf(stderr, "date is required");
114  return NULL;
115  }
116  verb_str = _net_get_verb(verb);
117 
118  return (unsigned char*) g_strconcat(verb_str, "\n", checksum_value, "\n", content_type, "\n", date, "\n", amz_headers, resource_name, NULL);
119 }
120 
121 static char* _generate_date_string(void) {
122  GDateTime* time = g_date_time_new_now_local();
123  char* date_string = g_date_time_format(time, "%a, %d %b %Y %H:%M:%S %z");
124 
125  g_date_time_unref(time);
126 
127  return date_string;
128 }
129 
130 static char* _net_compute_signature(const ds3_log* log, const ds3_creds* creds, http_verb verb, char* resource_name,
131  char* date, char* content_type, char* checksum_value, char* amz_headers) {
132  GHmac* hmac;
133  gchar* signature;
134  gsize bufSize = 256;
135  guint8 buffer[256];
136 
137  unsigned char* signature_str = _generate_signature_str(verb, resource_name, date, content_type, checksum_value, amz_headers);
138  char* escaped_str = g_strescape((char*) signature_str, NULL);
139 
140  ds3_log_message(log, DS3_DEBUG, "signature string: %s", escaped_str);
141  g_free(escaped_str);
142 
143  hmac = g_hmac_new(G_CHECKSUM_SHA1, (unsigned char*) creds->secret_key->value, creds->secret_key->size);
144  g_hmac_update(hmac, signature_str, strlen((const char*)signature_str));
145  g_hmac_get_digest(hmac, buffer, &bufSize);
146 
147  signature = g_base64_encode(buffer, bufSize);
148 
149  g_free(signature_str);
150  g_hmac_unref(hmac);
151 
152  return signature;
153 }
154 
155 typedef struct {
156  char** entries;
157  size_t size;
158 }query_entries;
159 
160 static void _hash_for_each(gpointer _key, gpointer _value, gpointer _user_data) {
161  char* key = (char*) _key;
162  char* value = (char*) _value;
163  query_entries* entries = (query_entries*) _user_data;
164  if (value == NULL) {
165  entries->entries[entries->size] = g_strconcat(key, NULL);
166  } else {
167  entries->entries[entries->size] = g_strconcat(key, "=", value, NULL);
168  }
169  entries->size++;
170 }
171 
172 static char* _net_gen_query_params(GHashTable* query_params) {
173  if (g_hash_table_size(query_params) > 0) {
174  query_entries q_entries;
175  char** entries;
176  char* return_string;
177  int i;
178  //build the query string
179  memset(&q_entries, 0, sizeof(query_entries));
180 
181  //We need the +1 so that it is NULL terminating for g_strjoinv
182  entries = g_new0(char*, g_hash_table_size(query_params) + 1);
183  q_entries.entries = entries;
184  g_hash_table_foreach(query_params, _hash_for_each, &q_entries);
185 
186  return_string = g_strjoinv("&", entries);
187 
188  for (i = 0; ; i++) {
189  char* current_string = entries[i];
190  if (current_string == NULL) {
191  break;
192  }
193  g_free(current_string);
194  }
195 
196  g_free(entries);
197 
198  return return_string;
199  } else {
200  return NULL;
201  }
202 }
203 
204 static struct curl_slist* _append_headers(struct curl_slist* header_list, GHashTable* headers_map) {
205  GHashTableIter iter;
206  gpointer key, value;
207  struct curl_slist* updated_list = header_list;
208  g_hash_table_iter_init(&iter, headers_map);
209 
210  while (g_hash_table_iter_next(&iter, &key, &value)) {
211  char* header_value = g_strconcat((char*)key, ": ", (char*)value, NULL);
212  updated_list = curl_slist_append(updated_list, header_value);
213  g_free(header_value);
214  }
215  return updated_list;
216 }
217 
218 static int ds3_curl_logger(CURL *handle, curl_infotype type, char* data, size_t size, void* userp) {
219  char* text = "curl_log";
220  ds3_log* log = (ds3_log*) userp;
221  char* message;
222  switch(type) {
223  case CURLINFO_HEADER_OUT:
224  text = "HEADER_SENT";
225  break;
226  case CURLINFO_HEADER_IN:
227  text = "HEADER_RECV";
228  break;
229 
230  case CURLINFO_DATA_IN:
231  case CURLINFO_DATA_OUT:
232  case CURLINFO_SSL_DATA_IN:
233  case CURLINFO_SSL_DATA_OUT:
234  // do not log any payload data
235  return 0;
236  default:
237  break;
238  }
239 
240  message = g_strndup(data, size);
241 
242  ds3_log_message(log, DS3_TRACE, "%s: %s", text, g_strchomp(message));
243 
244  g_free(message);
245  return 0;
246 }
247 
248 static gint _gstring_sort(gconstpointer a, gconstpointer b) {
249  char** val1 = (char**)a;
250  char** val2 = (char**)b;
251 
252  return g_strcmp0(*val1, *val2);
253 }
254 
255 static char* _canonicalize_amz_headers(GHashTable* headers) {
256  GList* keys = g_hash_table_get_keys(headers);
257  GList* key = keys;
258  GString* canonicalized_headers = g_string_new("");
259  GPtrArray *signing_strings = g_ptr_array_new_with_free_func(g_free); // stores char*
260  GString* header_signing_value;
261  char* signing_value;
262  unsigned int i;
263 
264  while(key != NULL) {
265  if(g_str_has_prefix((char*)key->data, "x-amz")){
266  header_signing_value = g_string_new((gchar*)key->data);
267  header_signing_value = g_string_append(g_string_ascii_down(header_signing_value), ":");
268  header_signing_value = g_string_append(header_signing_value, (gchar*)g_hash_table_lookup(headers, key->data));
269 
270  signing_value = g_string_free(header_signing_value, FALSE);
271  g_ptr_array_add(signing_strings, signing_value);
272  }
273  key = key->next;
274  }
275 
276  g_ptr_array_sort(signing_strings, _gstring_sort);
277 
278  for (i = 0; i < signing_strings->len; i++) {
279  g_string_append(canonicalized_headers, (gchar*)g_ptr_array_index(signing_strings, i));
280  g_string_append(canonicalized_headers, "\n");
281  }
282 
283  g_list_free(keys);
284  g_ptr_array_free(signing_strings, TRUE);
285 
286  return g_string_free(canonicalized_headers, FALSE);
287 }
288 
289 static char* _canonicalized_resource(ds3_str* path, GHashTable* query_params) {
290  if (g_hash_table_contains(query_params, "delete")) {
291  return g_strconcat(path->value, "?delete", NULL);
292  } else {
293  return g_strdup(path->value);
294  }
295 }
296 
297 static size_t _process_header_line(void* buffer, size_t size, size_t nmemb, void* user_data) {
298  size_t to_read;
299  char* header_buff;
300  char** split_result;
301  ds3_str* header_key;
302  ds3_str* header_value;
303  ds3_response_data* response_data = (ds3_response_data*) user_data;
304 
305  to_read = size * nmemb;
306  if (to_read < 2) {
307  return 0;
308  }
309 
310  header_buff = g_new0(char, to_read+1); //+1 for the null byte
311  strncpy(header_buff, (char*)buffer, to_read);
312  header_buff = g_strchomp(header_buff);
313 
314  // If we have read all the headers, then the last line will only be \n\r
315  if (strlen(header_buff) == 0) {
316  g_free(header_buff);
317  return to_read;
318  }
319 
320  if (response_data->header_count < 1) {
321  if (g_str_has_prefix(header_buff, "HTTP/1.1") == TRUE) {
322  // parse out status code and the status string
323  char* endpointer;
324  uint64_t status_code;
325  split_result = g_strsplit(header_buff, " ", 1000);
326  status_code = g_ascii_strtoll(split_result[1], &endpointer, 10);
327  if (status_code == 0 && endpointer != NULL) {
328  fprintf(stderr, "Encountered a problem parsing the status code\n");
329  g_strfreev(split_result);
330  g_free(header_buff);
331  return 0;
332  }
333  if (status_code == 100) {
334  g_free(header_buff);
335  g_strfreev(split_result);
336  return to_read;
337  } else {
338  char* status_message = g_strjoinv(" ", split_result + 2);
339  response_data->status_code = status_code;
340  response_data->status_message = ds3_str_init(status_message);
341  g_free(status_message);
342  g_strfreev(split_result);
343  }
344  } else {
345  fprintf(stderr, "Unsupported Protocol\n");
346  g_free(header_buff);
347  return 0;
348  }
349  } else {
350  split_result = g_strsplit(header_buff, ": ", 2);
351  header_key = ds3_str_init(split_result[0]);
352  header_value = ds3_str_init(split_result[1]);
353 
354  ds3_string_multimap_insert(response_data->headers, header_key, header_value);
355  ds3_str_free(header_key);
356  ds3_str_free(header_value);
357  g_strfreev(split_result);
358  }
359  response_data->header_count++;
360  g_free(header_buff);
361  return to_read;
362 }
363 
364 static size_t _process_response_body(void* buffer, size_t size, size_t nmemb, void* user_data) {
365  ds3_response_data* response_data = (ds3_response_data*) user_data;
366 
367  // If we got an error, collect the error body
368  if (response_data->status_code >= 300) {
369  return ds3_load_buffer(buffer, size, nmemb, response_data->body);
370  } else { // If we did not get an error, call the user's defined callbacks.
371  return response_data->user_func(buffer, size, nmemb, response_data->user_data);
372  }
373 }
374 
376  const ds3_request* _request,
377  void* read_user_struct,
378  size_t (*read_handler_func)(void*, size_t, size_t, void*),
379  void* write_user_struct,
380  size_t (*write_handler_func)(void*, size_t, size_t, void*),
381  ds3_string_multimap** return_headers) {
382  struct _ds3_request* request = (struct _ds3_request*) _request;
383  CURL* handle;
384  CURLcode res;
385  char* url;
386  int retry_count = 0;
387  char* query_params;
388 
389  _init_curl();
390 
392 
393  if (query_params == NULL) {
394  url = g_strconcat(client->endpoint->value, request->path->value, NULL);
395  } else {
396  url = g_strconcat(client->endpoint->value, request->path->value,"?",query_params, NULL);
397  g_free(query_params);
398  }
399  ds3_log_message(client->log, DS3_DEBUG, "URL[%s]", url);
400 
401  while (retry_count < client->num_redirects) {
402  ds3_log_message(client->log, DS3_DEBUG, "Acquiring connection...");
403  handle = ds3_connection_acquire(client->connection_pool);
404  ds3_log_message(client->log, DS3_DEBUG, "Connection acquired.");
405 
406  if (handle) {
407  char* amz_headers;
408  char* canonicalized_resource;
409  char* date;
410  char* date_header;
411  char* signature;
412  struct curl_slist* headers;
413  char* auth_header;
414  char* checksum_value;
415  ds3_response_data response_data;
416  ds3_string_multimap* response_headers = ds3_string_multimap_init();
417 
418  ds3_log_message(client->log, DS3_DEBUG, "Preparing to send request");
419 
420  memset(&response_data, 0, sizeof(ds3_response_data));
421  response_data.headers = response_headers;
422  response_data.body = g_byte_array_new();
423 
424  if (client->log != NULL) {
425  curl_easy_setopt(handle, CURLOPT_DEBUGFUNCTION, ds3_curl_logger);
426  curl_easy_setopt(handle, CURLOPT_DEBUGDATA, client->log);
427  curl_easy_setopt(handle, CURLOPT_VERBOSE, 1L); // turn on verbose logging
428  }
429 
430  curl_easy_setopt(handle, CURLOPT_URL, url);
431 
432  curl_easy_setopt(handle, CURLOPT_FOLLOWLOCATION, 0); // explicitly disable
433 
434  // Setup header collection
435  curl_easy_setopt(handle, CURLOPT_HEADERFUNCTION, _process_header_line);
436  curl_easy_setopt(handle, CURLOPT_HEADERDATA, &response_data);
437 
438  if (client->proxy != NULL) {
439  curl_easy_setopt(handle, CURLOPT_PROXY, client->proxy->value);
440  }
441 
442  // Register the read and write handlers if they are set
443  if (read_user_struct != NULL && read_handler_func != NULL) {
444  response_data.user_data = read_user_struct;
445  response_data.user_func = read_handler_func;
446  }
447 
448  // We must always set this so we can collect the error message body
449  curl_easy_setopt(handle, CURLOPT_WRITEFUNCTION, _process_response_body);
450  curl_easy_setopt(handle, CURLOPT_WRITEDATA, &response_data);
451 
452  if (write_user_struct != NULL && write_handler_func != NULL) {
453  curl_easy_setopt(handle, CURLOPT_READFUNCTION, write_handler_func);
454  curl_easy_setopt(handle, CURLOPT_READDATA, write_user_struct);
455  }
456 
457  switch(request->verb) {
458  case HTTP_POST: {
459  curl_easy_setopt(handle, CURLOPT_CUSTOMREQUEST, "POST");
460  curl_easy_setopt(handle, CURLOPT_UPLOAD, 1L);
461  curl_easy_setopt(handle, CURLOPT_INFILESIZE_LARGE, request->length);
462  break;
463  }
464  case HTTP_PUT: {
465  curl_easy_setopt(handle, CURLOPT_PUT, 1L);
466  curl_easy_setopt(handle, CURLOPT_UPLOAD, 1L);
467  curl_easy_setopt(handle, CURLOPT_INFILESIZE_LARGE, request->length);
468  break;
469  }
470  case HTTP_DELETE: {
471  curl_easy_setopt(handle, CURLOPT_CUSTOMREQUEST, "DELETE");
472  break;
473  }
474  case HTTP_HEAD: {
475  curl_easy_setopt(handle, CURLOPT_CUSTOMREQUEST, "HEAD");
476  curl_easy_setopt(handle, CURLOPT_NOBODY, 1L);
477  break;
478  }
479  case HTTP_GET: {
480  //Placeholder if we need to put anything here.
481  break;
482  }
483  }
484 
485  date = _generate_date_string();
486  date_header = g_strconcat("Date: ", date, NULL);
487  headers = NULL;
488 
489  if (request->checksum == NULL) {
490  checksum_value = "";
491  } else {
492  char* checksum_header;
493  checksum_value = request->checksum->value;
494  checksum_header = g_strconcat(_get_checksum_type_header(request->checksum_type), checksum_value, NULL);
495  headers = curl_slist_append(headers, checksum_header);
496  g_free(checksum_header);
497  }
498  amz_headers = _canonicalize_amz_headers(request->headers);
499  canonicalized_resource = _canonicalized_resource(request->path, request->query_params);
500  signature = _net_compute_signature(client->log, client->creds, request->verb, canonicalized_resource, date, "", checksum_value, amz_headers);
501 
502  g_free(amz_headers);
503  g_free(canonicalized_resource);
504 
505  auth_header = g_strconcat("Authorization: AWS ", client->creds->access_id->value, ":", signature, NULL);
506 
507  headers = curl_slist_append(headers, auth_header);
508  headers = curl_slist_append(headers, date_header);
509  headers = _append_headers(headers, request->headers);
510 
511  curl_easy_setopt(handle, CURLOPT_HTTPHEADER, headers);
512 
513  ds3_log_message(client->log, DS3_DEBUG, "Attempt curl_easy_perform...");
514  res = curl_easy_perform(handle);
515  ds3_log_message(client->log, DS3_DEBUG, "curl_easy_perform done.");
516 
517  g_free(date);
518  g_free(date_header);
519  g_free(signature);
520  g_free(auth_header);
521  curl_slist_free_all(headers);
522  ds3_log_message(client->log, DS3_DEBUG, "Releasing connection...");
523  ds3_connection_release(client->connection_pool, handle);
524  ds3_log_message(client->log, DS3_DEBUG, "Connection released.");
525 
526  //process the response
527  if (res != CURLE_OK) {
528  char * message = g_strconcat("Request failed: ", curl_easy_strerror(res), NULL);
530  g_free(url);
531  g_byte_array_free(response_data.body, TRUE);
532  ds3_str_free(response_data.status_message);
533  ds3_string_multimap_free(response_headers);
534  g_free(message);
535  return error;
536  }
537 
538  ds3_log_message(client->log, DS3_DEBUG, "Request completed with status code of: %d", response_data.status_code);
539 
540  if (response_data.status_code < 200 || response_data.status_code >= 300) {
541  ds3_error* error = ds3_create_error(DS3_ERROR_BAD_STATUS_CODE, "Got an unexpected status code.");
542  error->error = g_new0(ds3_error_response, 1);
543  error->error->http_error_code = response_data.status_code;
544  error->error->code = ds3_str_init(response_data.status_message->value);
545  if (response_data.body != NULL) {
546  error->error->message = ds3_str_init_with_size((char*)response_data.body->data, response_data.body->len);
547  g_byte_array_free(response_data.body, TRUE);
548  } else {
549  ds3_log_message(client->log, DS3_ERROR, "The response body for the error is empty");
550  error->error->message = NULL;
551  }
552  ds3_string_multimap_free(response_headers);
553  ds3_str_free(response_data.status_message);
554  g_free(url);
555 
556  if (response_data.status_code == 307) {
557  ds3_log_message(client->log, DS3_INFO, "Request encountered a 307 redirect");
558 
559  retry_count++;
560  ds3_log_message(client->log, DS3_DEBUG, "Retry Attempt: %d | Max Retries: %d", retry_count, client->num_redirects);
561 
562  if (retry_count == client->num_redirects) {
563  ds3_str_free(error->message);
564  error->message = ds3_str_init("Encountered too many redirects while attempting to fulfill the request");
566  } else {
567  continue;
568  }
569  }
570  return error;
571  }
572  g_byte_array_free(response_data.body, TRUE);
573  ds3_str_free(response_data.status_message);
574 
575  if (return_headers != NULL) {
576  *return_headers = response_headers;
577  } else {
578  ds3_string_multimap_free(response_headers);
579  }
580 
581  break;
582  } else {
583  return ds3_create_error(DS3_ERROR_CURL_HANDLE, "Failed to create curl handle");
584  }
585  }
586  g_free(url);
587 
588  return NULL;
589 }
590 
591 void net_cleanup(void) {
592  curl_global_cleanup();
593 }
594 
Definition: ds3.h:85
ds3_checksum_type checksum_type
Definition: ds3_request.h:35
int http_error_code
Definition: ds3.h:1520
static size_t _process_header_line(void *buffer, size_t size, size_t nmemb, void *user_data)
Definition: ds3_net.c:297
char * escape_url(const char *url)
Definition: ds3_net.c:67
ds3_str * message
Definition: ds3.h:1521
size_t size
Definition: ds3_string.h:38
static size_t _process_response_body(void *buffer, size_t size, size_t nmemb, void *user_data)
Definition: ds3_net.c:364
uint64_t length
Definition: ds3_request.h:33
static void _hash_for_each(gpointer _key, gpointer _value, gpointer _user_data)
Definition: ds3_net.c:160
Definition: ds3.h:92
static char * _get_checksum_type_header(const ds3_checksum_type type)
Definition: ds3_net.c:51
ds3_checksum_type
Definition: ds3.h:623
ds3_creds * creds
Definition: ds3.h:2137
char * escape_url_object_name(const char *url)
Definition: ds3_net.c:94
ds3_bool
Definition: ds3.h:72
ds3_error_code code
Definition: ds3.h:2128
static char * _canonicalize_amz_headers(GHashTable *headers)
Definition: ds3_net.c:255
void ds3_log_message(const ds3_log *log, ds3_log_lvl lvl, const char *message,...)
Definition: ds3_utils.c:38
ds3_log * log
Definition: ds3.h:2138
ds3_str * path
Definition: ds3_request.h:32
Definition: ds3.h:81
char * escape_url_extended(const char *url, const char **delimiters, uint32_t num_delimiters)
Definition: ds3_net.c:75
Definition: ds3.h:73
Definition: ds3.h:98
char * escape_url_range_header(const char *url)
Definition: ds3_net.c:100
ds3_str * status_message
Definition: ds3_request.h:51
ds3_str * code
Definition: ds3.h:1519
static char * _net_gen_query_params(GHashTable *query_params)
Definition: ds3_net.c:172
ds3_error * ds3_create_error(ds3_error_code code, const char *message)
Definition: ds3_utils.c:22
ds3_str * checksum
Definition: ds3_request.h:34
http_verb verb
Definition: ds3_request.h:31
http_verb
Definition: ds3.h:76
static int ds3_curl_logger(CURL *handle, curl_infotype type, char *data, size_t size, void *userp)
Definition: ds3_net.c:218
ds3_string_multimap * headers
Definition: ds3_request.h:53
ds3_str * access_id
Definition: ds3.h:99
GHashTable * query_params
Definition: ds3_request.h:37
size_t ds3_load_buffer(void *buffer, size_t size, size_t nmemb, void *user_data)
Definition: ds3_utils.c:30
Definition: ds3.h:79
void ds3_str_free(ds3_str *string)
Definition: ds3_string.c:50
static char * _net_get_verb(http_verb verb)
Definition: ds3_net.c:39
uint64_t num_redirects
Definition: ds3.h:2136
static char * _net_compute_signature(const ds3_log *log, const ds3_creds *creds, http_verb verb, char *resource_name, char *date, char *content_type, char *checksum_value, char *amz_headers)
Definition: ds3_net.c:130
ds3_string_multimap * ds3_string_multimap_init(void)
void net_cleanup(void)
Definition: ds3_net.c:591
static struct curl_slist * _append_headers(struct curl_slist *header_list, GHashTable *headers_map)
Definition: ds3_net.c:204
Definition: ds3.h:87
void ds3_connection_release(ds3_connection_pool *pool, ds3_connection *connection)
static unsigned char * _generate_signature_str(http_verb verb, char *resource_name, char *date, char *content_type, char *checksum_value, char *amz_headers)
Definition: ds3_net.c:105
ds3_error_response * error
Definition: ds3.h:2130
void ds3_string_multimap_free(ds3_string_multimap *map)
ds3_str * message
Definition: ds3.h:2129
ds3_str * ds3_str_init_with_size(const char *string, size_t size)
Definition: ds3_string.c:25
static char * _generate_date_string(void)
Definition: ds3_net.c:121
GHashTable * headers
Definition: ds3_request.h:36
ds3_str * proxy
Definition: ds3.h:2135
void ds3_string_multimap_insert(ds3_string_multimap *map, const ds3_str *key, const ds3_str *value)
Definition: ds3.h:77
ds3_error * net_process_request(const ds3_client *client, const ds3_request *_request, void *read_user_struct, size_t(*read_handler_func)(void *, size_t, size_t, void *), void *write_user_struct, size_t(*write_handler_func)(void *, size_t, size_t, void *), ds3_string_multimap **return_headers)
Definition: ds3_net.c:375
size_t(* user_func)(void *, size_t, size_t, void *)
Definition: ds3_request.h:58
GByteArray * body
Definition: ds3_request.h:56
Definition: ds3.h:89
ds3_connection_pool * connection_pool
Definition: ds3.h:2146
ds3_connection * ds3_connection_acquire(ds3_connection_pool *pool)
uint64_t status_code
Definition: ds3_request.h:50
static char * _canonicalized_resource(ds3_str *path, GHashTable *query_params)
Definition: ds3_net.c:289
ds3_str * ds3_str_init(const char *string)
Definition: ds3_string.c:20
static void _init_curl(void)
Definition: ds3_net.c:28
ds3_str * secret_key
Definition: ds3.h:100
Definition: ds3.h:78
static gint _gstring_sort(gconstpointer a, gconstpointer b)
Definition: ds3_net.c:248
Definition: ds3.h:73
ds3_str * endpoint
Definition: ds3.h:2134
char * value
Definition: ds3_string.h:37
Definition: ds3.h:88