DS3 C SDK  5.0.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  gchar* versioning_query = NULL;
291 
292  gchar* path_copy = g_strdup(path->value);
293  gchar* canonicalized_query;
294  gchar** query_strings;
295  GPtrArray* array = g_ptr_array_new();
296 
297  // Canonicalize required query parameters in alpha numberic order
298  if (g_hash_table_contains(query_params, "delete")) {
299  g_ptr_array_add(array, "delete");
300  }
301 
302  if (g_hash_table_contains(query_params, "versioning")) {
303  gchar* version_level = g_hash_table_lookup(query_params, "versioning");
304  versioning_query = g_strdup_printf("versioning=%s", version_level);
305  g_ptr_array_add(array, versioning_query);
306  }
307 
308  if (g_hash_table_contains(query_params, "versions")) {
309  g_ptr_array_add(array, "versions");
310  }
311 
312  // Finish the array with a terminating NULL
313  g_ptr_array_add(array, NULL);
314  query_strings = (gchar**)g_ptr_array_free(array, FALSE);
315 
316  canonicalized_query = g_strjoinv("&", query_strings);
317 
318  // Free individual dynamically allocated query strings
319  if (versioning_query != NULL) {
320  g_free(versioning_query);
321  }
322  g_free(query_strings);
323 
324  if (strlen(canonicalized_query) > 0) {
325  gchar* canonicalized_path = g_strjoin("?", path_copy, canonicalized_query, NULL);
326  g_free(canonicalized_query);
327  g_free(path_copy);
328  return canonicalized_path;
329  }
330  g_free(canonicalized_query);
331  return path_copy;
332 }
333 
334 static size_t _process_header_line(void* buffer, size_t size, size_t nmemb, void* user_data) {
335  size_t to_read;
336  char* header_buff;
337  char** split_result;
338  ds3_str* header_key;
339  ds3_str* header_value;
340  ds3_response_data* response_data = (ds3_response_data*) user_data;
341 
342  to_read = size * nmemb;
343  if (to_read < 2) {
344  return 0;
345  }
346 
347  header_buff = g_new0(char, to_read+1); //+1 for the null byte
348  strncpy(header_buff, (char*)buffer, to_read);
349  header_buff = g_strchomp(header_buff);
350 
351  // If we have read all the headers, then the last line will only be \n\r
352  if (strlen(header_buff) == 0) {
353  g_free(header_buff);
354  return to_read;
355  }
356 
357  if (response_data->header_count < 1) {
358  if (g_str_has_prefix(header_buff, "HTTP/1.1") == TRUE) {
359  // parse out status code and the status string
360  char* endpointer;
361  uint64_t status_code;
362  split_result = g_strsplit(header_buff, " ", 1000);
363  status_code = g_ascii_strtoll(split_result[1], &endpointer, 10);
364  if (status_code == 0 && endpointer != NULL) {
365  fprintf(stderr, "Encountered a problem parsing the status code\n");
366  g_strfreev(split_result);
367  g_free(header_buff);
368  return 0;
369  }
370  if (status_code == 100) {
371  g_free(header_buff);
372  g_strfreev(split_result);
373  return to_read;
374  } else {
375  char* status_message = g_strjoinv(" ", split_result + 2);
376  response_data->status_code = status_code;
377  response_data->status_message = ds3_str_init(status_message);
378  g_free(status_message);
379  g_strfreev(split_result);
380  }
381  } else {
382  fprintf(stderr, "Unsupported Protocol\n");
383  g_free(header_buff);
384  return 0;
385  }
386  } else {
387  split_result = g_strsplit(header_buff, ": ", 2);
388  header_key = ds3_str_init(split_result[0]);
389  header_value = ds3_str_init(split_result[1]);
390 
391  ds3_string_multimap_insert(response_data->headers, header_key, header_value);
392  ds3_str_free(header_key);
393  ds3_str_free(header_value);
394  g_strfreev(split_result);
395  }
396  response_data->header_count++;
397  g_free(header_buff);
398  return to_read;
399 }
400 
401 static size_t _process_response_body(void* buffer, size_t size, size_t nmemb, void* user_data) {
402  ds3_response_data* response_data = (ds3_response_data*) user_data;
403 
404  // If we got an error, collect the error body
405  if (response_data->status_code >= 300) {
406  return ds3_load_buffer(buffer, size, nmemb, response_data->body);
407  } else { // If we did not get an error, call the user's defined callbacks.
408  return response_data->user_func(buffer, size, nmemb, response_data->user_data);
409  }
410 }
411 
413  const ds3_request* _request,
414  void* read_user_struct,
415  size_t (*read_handler_func)(void*, size_t, size_t, void*),
416  void* write_user_struct,
417  size_t (*write_handler_func)(void*, size_t, size_t, void*),
418  ds3_string_multimap** return_headers) {
419  struct _ds3_request* request = (struct _ds3_request*) _request;
420  CURL* handle;
421  CURLcode res;
422  char* url;
423  int retry_count = 0;
424  char* query_params;
425 
426  _init_curl();
427 
429 
430  if (query_params == NULL) {
431  url = g_strconcat(client->endpoint->value, request->path->value, NULL);
432  } else {
433  url = g_strconcat(client->endpoint->value, request->path->value,"?",query_params, NULL);
434  g_free(query_params);
435  }
436  ds3_log_message(client->log, DS3_DEBUG, "URL[%s]", url);
437 
438  while (retry_count < client->num_redirects) {
439  ds3_log_message(client->log, DS3_DEBUG, "Acquiring connection...");
440  handle = ds3_connection_acquire(client->connection_pool);
441  ds3_log_message(client->log, DS3_DEBUG, "Connection acquired.");
442 
443  if (handle) {
444  char* amz_headers;
445  char* canonicalized_resource;
446  char* date;
447  char* date_header;
448  char* signature;
449  struct curl_slist* headers;
450  char* auth_header;
451  char* checksum_value;
452  ds3_response_data response_data;
453  ds3_string_multimap* response_headers = ds3_string_multimap_init();
454 
455  ds3_log_message(client->log, DS3_DEBUG, "Preparing to send request");
456 
457  memset(&response_data, 0, sizeof(ds3_response_data));
458  response_data.headers = response_headers;
459  response_data.body = g_byte_array_new();
460 
461  if (client->log != NULL) {
462  curl_easy_setopt(handle, CURLOPT_DEBUGFUNCTION, ds3_curl_logger);
463  curl_easy_setopt(handle, CURLOPT_DEBUGDATA, client->log);
464  curl_easy_setopt(handle, CURLOPT_VERBOSE, 1L); // turn on verbose logging
465  }
466 
467  curl_easy_setopt(handle, CURLOPT_URL, url);
468 
469  curl_easy_setopt(handle, CURLOPT_FOLLOWLOCATION, 0); // explicitly disable
470 
471  // Setup header collection
472  curl_easy_setopt(handle, CURLOPT_HEADERFUNCTION, _process_header_line);
473  curl_easy_setopt(handle, CURLOPT_HEADERDATA, &response_data);
474 
475  if (client->proxy != NULL) {
476  curl_easy_setopt(handle, CURLOPT_PROXY, client->proxy->value);
477  }
478 
479  // Register the read and write handlers if they are set
480  if (read_user_struct != NULL && read_handler_func != NULL) {
481  response_data.user_data = read_user_struct;
482  response_data.user_func = read_handler_func;
483  }
484 
485  // We must always set this so we can collect the error message body
486  curl_easy_setopt(handle, CURLOPT_WRITEFUNCTION, _process_response_body);
487  curl_easy_setopt(handle, CURLOPT_WRITEDATA, &response_data);
488 
489  if (write_user_struct != NULL && write_handler_func != NULL) {
490  curl_easy_setopt(handle, CURLOPT_READFUNCTION, write_handler_func);
491  curl_easy_setopt(handle, CURLOPT_READDATA, write_user_struct);
492  }
493 
494  switch(request->verb) {
495  case HTTP_POST: {
496  curl_easy_setopt(handle, CURLOPT_CUSTOMREQUEST, "POST");
497  curl_easy_setopt(handle, CURLOPT_UPLOAD, 1L);
498  curl_easy_setopt(handle, CURLOPT_INFILESIZE_LARGE, request->length);
499  break;
500  }
501  case HTTP_PUT: {
502  curl_easy_setopt(handle, CURLOPT_PUT, 1L);
503  curl_easy_setopt(handle, CURLOPT_UPLOAD, 1L);
504  curl_easy_setopt(handle, CURLOPT_INFILESIZE_LARGE, request->length);
505  break;
506  }
507  case HTTP_DELETE: {
508  curl_easy_setopt(handle, CURLOPT_CUSTOMREQUEST, "DELETE");
509  break;
510  }
511  case HTTP_HEAD: {
512  curl_easy_setopt(handle, CURLOPT_CUSTOMREQUEST, "HEAD");
513  curl_easy_setopt(handle, CURLOPT_NOBODY, 1L);
514  break;
515  }
516  case HTTP_GET: {
517  //Placeholder if we need to put anything here.
518  break;
519  }
520  }
521 
522  date = _generate_date_string();
523  date_header = g_strconcat("Date: ", date, NULL);
524  headers = NULL;
525 
526  if (request->checksum == NULL) {
527  checksum_value = "";
528  } else {
529  char* checksum_header;
530  checksum_value = request->checksum->value;
531  checksum_header = g_strconcat(_get_checksum_type_header(request->checksum_type), checksum_value, NULL);
532  headers = curl_slist_append(headers, checksum_header);
533  g_free(checksum_header);
534  }
535  amz_headers = _canonicalize_amz_headers(request->headers);
536  canonicalized_resource = _canonicalized_resource(request->path, request->query_params);
537  signature = _net_compute_signature(client->log, client->creds, request->verb, canonicalized_resource, date, "", checksum_value, amz_headers);
538 
539  g_free(amz_headers);
540  g_free(canonicalized_resource);
541 
542  auth_header = g_strconcat("Authorization: AWS ", client->creds->access_id->value, ":", signature, NULL);
543 
544  headers = curl_slist_append(headers, auth_header);
545  headers = curl_slist_append(headers, date_header);
546  headers = _append_headers(headers, request->headers);
547 
548  curl_easy_setopt(handle, CURLOPT_HTTPHEADER, headers);
549 
550  ds3_log_message(client->log, DS3_DEBUG, "Attempt curl_easy_perform...");
551  res = curl_easy_perform(handle);
552  ds3_log_message(client->log, DS3_DEBUG, "curl_easy_perform done.");
553 
554  g_free(date);
555  g_free(date_header);
556  g_free(signature);
557  g_free(auth_header);
558  curl_slist_free_all(headers);
559  ds3_log_message(client->log, DS3_DEBUG, "Releasing connection...");
560  ds3_connection_release(client->connection_pool, handle);
561  ds3_log_message(client->log, DS3_DEBUG, "Connection released.");
562 
563  //process the response
564  if (res != CURLE_OK) {
565  char * message = g_strconcat("Request failed: ", curl_easy_strerror(res), NULL);
567  g_free(url);
568  g_byte_array_free(response_data.body, TRUE);
569  ds3_str_free(response_data.status_message);
570  ds3_string_multimap_free(response_headers);
571  g_free(message);
572  return error;
573  }
574 
575  ds3_log_message(client->log, DS3_DEBUG, "Request completed with status code of: %d", response_data.status_code);
576 
577  if (response_data.status_code < 200 || response_data.status_code >= 300) {
578  ds3_error* error = ds3_create_error(DS3_ERROR_BAD_STATUS_CODE, "Got an unexpected status code.");
579  error->error = g_new0(ds3_error_response, 1);
580  error->error->http_error_code = response_data.status_code;
581  error->error->code = ds3_str_init(response_data.status_message->value);
582  if (response_data.body != NULL) {
583  error->error->message = ds3_str_init_with_size((char*)response_data.body->data, response_data.body->len);
584  g_byte_array_free(response_data.body, TRUE);
585  } else {
586  ds3_log_message(client->log, DS3_ERROR, "The response body for the error is empty");
587  error->error->message = NULL;
588  }
589  ds3_string_multimap_free(response_headers);
590  ds3_str_free(response_data.status_message);
591  g_free(url);
592 
593  if (response_data.status_code == 307) {
594  ds3_log_message(client->log, DS3_INFO, "Request encountered a 307 redirect");
595 
596  retry_count++;
597  ds3_log_message(client->log, DS3_DEBUG, "Retry Attempt: %d | Max Retries: %d", retry_count, client->num_redirects);
598 
599  if (retry_count == client->num_redirects) {
600  ds3_str_free(error->message);
601  error->message = ds3_str_init("Encountered too many redirects while attempting to fulfill the request");
603  } else {
604  continue;
605  }
606  }
607  return error;
608  }
609  g_byte_array_free(response_data.body, TRUE);
610  ds3_str_free(response_data.status_message);
611 
612  if (return_headers != NULL) {
613  *return_headers = response_headers;
614  } else {
615  ds3_string_multimap_free(response_headers);
616  }
617 
618  break;
619  } else {
620  return ds3_create_error(DS3_ERROR_CURL_HANDLE, "Failed to create curl handle");
621  }
622  }
623  g_free(url);
624 
625  return NULL;
626 }
627 
628 void net_cleanup(void) {
629  curl_global_cleanup();
630 }
631 
Definition: ds3.h:73
ds3_checksum_type checksum_type
Definition: ds3_request.h:35
int http_error_code
Definition: ds3.h:1525
static size_t _process_header_line(void *buffer, size_t size, size_t nmemb, void *user_data)
Definition: ds3_net.c:334
char * escape_url(const char *url)
Definition: ds3_net.c:67
ds3_str * message
Definition: ds3.h:1526
size_t size
Definition: ds3_string.h:28
static size_t _process_response_body(void *buffer, size_t size, size_t nmemb, void *user_data)
Definition: ds3_net.c:401
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:80
static char * _get_checksum_type_header(const ds3_checksum_type type)
Definition: ds3_net.c:51
ds3_checksum_type
Definition: ds3.h:620
ds3_creds * creds
Definition: ds3.h:2147
char * escape_url_object_name(const char *url)
Definition: ds3_net.c:94
ds3_error_code code
Definition: ds3.h:2138
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:2148
ds3_str * path
Definition: ds3_request.h:32
Definition: ds3.h:69
Definition: ds3_bool.h:24
char * escape_url_extended(const char *url, const char **delimiters, uint32_t num_delimiters)
Definition: ds3_net.c:75
Definition: ds3.h:86
char * escape_url_range_header(const char *url)
Definition: ds3_net.c:100
ds3_str * status_message
Definition: ds3_request.h:54
ds3_str * code
Definition: ds3.h:1524
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:64
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:56
ds3_str * access_id
Definition: ds3.h:87
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:67
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:2146
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)
Definition: ds3_bool.h:24
void net_cleanup(void)
Definition: ds3_net.c:628
static struct curl_slist * _append_headers(struct curl_slist *header_list, GHashTable *headers_map)
Definition: ds3_net.c:204
Definition: ds3.h:75
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:2140
void ds3_string_multimap_free(ds3_string_multimap *map)
ds3_str * message
Definition: ds3.h:2139
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:2145
void ds3_string_multimap_insert(ds3_string_multimap *map, const ds3_str *key, const ds3_str *value)
Definition: ds3.h:65
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:412
size_t(* user_func)(void *, size_t, size_t, void *)
Definition: ds3_request.h:61
GByteArray * body
Definition: ds3_request.h:59
Definition: ds3.h:77
ds3_connection_pool * connection_pool
Definition: ds3.h:2156
ds3_connection * ds3_connection_acquire(ds3_connection_pool *pool)
uint64_t status_code
Definition: ds3_request.h:53
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:88
Definition: ds3.h:66
static gint _gstring_sort(gconstpointer a, gconstpointer b)
Definition: ds3_net.c:248
ds3_str * endpoint
Definition: ds3.h:2144
char * value
Definition: ds3_string.h:27
Definition: ds3.h:76
ds3_bool
Definition: ds3_bool.h:23