ruby-libstorj 0.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (92) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +10 -0
  3. data/.gitmodules +3 -0
  4. data/.rspec +1 -0
  5. data/Gemfile +23 -0
  6. data/Gemfile.lock +111 -0
  7. data/Guardfile +21 -0
  8. data/LICENSE +502 -0
  9. data/README.md +262 -0
  10. data/Rakefile +76 -0
  11. data/ext/libstorj/.gitignore +47 -0
  12. data/ext/libstorj/.travis.yml +27 -0
  13. data/ext/libstorj/Doxyfile +2427 -0
  14. data/ext/libstorj/LICENSE +502 -0
  15. data/ext/libstorj/Makefile.am +6 -0
  16. data/ext/libstorj/README.md +198 -0
  17. data/ext/libstorj/autogen.sh +3 -0
  18. data/ext/libstorj/configure.ac +64 -0
  19. data/ext/libstorj/depends/Makefile +153 -0
  20. data/ext/libstorj/depends/config.guess +1462 -0
  21. data/ext/libstorj/depends/config.sub +1823 -0
  22. data/ext/libstorj/depends/extract-osx-sdk.sh +33 -0
  23. data/ext/libstorj/depends/packages/cctools.mk +7 -0
  24. data/ext/libstorj/depends/packages/clang.mk +7 -0
  25. data/ext/libstorj/depends/packages/gmp.mk +23 -0
  26. data/ext/libstorj/depends/packages/gnutls.mk +25 -0
  27. data/ext/libstorj/depends/packages/json-c.mk +7 -0
  28. data/ext/libstorj/depends/packages/libcurl.mk +39 -0
  29. data/ext/libstorj/depends/packages/libmicrohttpd.mk +7 -0
  30. data/ext/libstorj/depends/packages/libuv.mk +7 -0
  31. data/ext/libstorj/depends/packages/nettle.mk +30 -0
  32. data/ext/libstorj/libstorj.pc.in +11 -0
  33. data/ext/libstorj/src/Makefile.am +23 -0
  34. data/ext/libstorj/src/bip39.c +233 -0
  35. data/ext/libstorj/src/bip39.h +64 -0
  36. data/ext/libstorj/src/bip39_english.h +2074 -0
  37. data/ext/libstorj/src/cli.c +1494 -0
  38. data/ext/libstorj/src/crypto.c +525 -0
  39. data/ext/libstorj/src/crypto.h +178 -0
  40. data/ext/libstorj/src/downloader.c +1923 -0
  41. data/ext/libstorj/src/downloader.h +163 -0
  42. data/ext/libstorj/src/http.c +688 -0
  43. data/ext/libstorj/src/http.h +175 -0
  44. data/ext/libstorj/src/rs.c +962 -0
  45. data/ext/libstorj/src/rs.h +99 -0
  46. data/ext/libstorj/src/storj.c +1523 -0
  47. data/ext/libstorj/src/storj.h +1014 -0
  48. data/ext/libstorj/src/uploader.c +2736 -0
  49. data/ext/libstorj/src/uploader.h +181 -0
  50. data/ext/libstorj/src/utils.c +336 -0
  51. data/ext/libstorj/src/utils.h +65 -0
  52. data/ext/libstorj/test/Makefile.am +27 -0
  53. data/ext/libstorj/test/mockbridge.c +260 -0
  54. data/ext/libstorj/test/mockbridge.json +687 -0
  55. data/ext/libstorj/test/mockbridgeinfo.json +1836 -0
  56. data/ext/libstorj/test/mockfarmer.c +358 -0
  57. data/ext/libstorj/test/storjtests.h +41 -0
  58. data/ext/libstorj/test/tests.c +1617 -0
  59. data/ext/libstorj/test/tests_rs.c +869 -0
  60. data/ext/ruby-libstorj/extconf.rb +8 -0
  61. data/ext/ruby-libstorj/ruby-libstorj.cc +17 -0
  62. data/lib/ruby-libstorj.rb +1 -0
  63. data/lib/ruby-libstorj/arg_forwarding_task.rb +58 -0
  64. data/lib/ruby-libstorj/env.rb +178 -0
  65. data/lib/ruby-libstorj/ext/bucket.rb +71 -0
  66. data/lib/ruby-libstorj/ext/create_bucket_request.rb +53 -0
  67. data/lib/ruby-libstorj/ext/curl_code.rb +139 -0
  68. data/lib/ruby-libstorj/ext/ext.rb +71 -0
  69. data/lib/ruby-libstorj/ext/file.rb +84 -0
  70. data/lib/ruby-libstorj/ext/get_bucket_request.rb +45 -0
  71. data/lib/ruby-libstorj/ext/json_request.rb +51 -0
  72. data/lib/ruby-libstorj/ext/list_files_request.rb +63 -0
  73. data/lib/ruby-libstorj/ext/types.rb +226 -0
  74. data/lib/ruby-libstorj/ext/upload_options.rb +38 -0
  75. data/lib/ruby-libstorj/libstorj.rb +22 -0
  76. data/lib/ruby-libstorj/mixins/storj.rb +27 -0
  77. data/lib/ruby-libstorj/struct.rb +42 -0
  78. data/ruby-libstorj.gemspec +57 -0
  79. data/spec/helpers/options.yml.example +22 -0
  80. data/spec/helpers/shared_rake_examples.rb +132 -0
  81. data/spec/helpers/storj_options.rb +96 -0
  82. data/spec/helpers/upload.data +3 -0
  83. data/spec/helpers/upload.data.sha256 +1 -0
  84. data/spec/libstorj_spec.rb +0 -0
  85. data/spec/ruby-libstorj/arg_forwarding_task_spec.rb +311 -0
  86. data/spec/ruby-libstorj/env_spec.rb +353 -0
  87. data/spec/ruby-libstorj/ext_spec.rb +75 -0
  88. data/spec/ruby-libstorj/json_request_spec.rb +13 -0
  89. data/spec/ruby-libstorj/libstorj_spec.rb +81 -0
  90. data/spec/ruby-libstorj/struct_spec.rb +64 -0
  91. data/spec/spec_helper.rb +113 -0
  92. metadata +136 -0
@@ -0,0 +1,99 @@
1
+ #ifndef __RS_H_
2
+ #define __RS_H_
3
+
4
+ /* use small value to save memory */
5
+ #ifndef DATA_SHARDS_MAX
6
+ #define DATA_SHARDS_MAX (255)
7
+ #endif
8
+
9
+ /* use other memory allocator */
10
+ #ifndef RS_MALLOC
11
+ #define RS_MALLOC(x) malloc(x)
12
+ #endif
13
+
14
+ #ifndef RS_FREE
15
+ #define RS_FREE(x) free(x)
16
+ #endif
17
+
18
+ #ifndef RS_CALLOC
19
+ #define RS_CALLOC(n, x) calloc(n, x)
20
+ #endif
21
+
22
+ typedef struct _reed_solomon {
23
+ int data_shards;
24
+ int parity_shards;
25
+ int shards;
26
+ uint8_t* m;
27
+ uint8_t* parity;
28
+ } reed_solomon;
29
+
30
+ /**
31
+ * @brief Initializes data structures used for computations in GF.
32
+ */
33
+ void fec_init(void);
34
+
35
+ /**
36
+ * @brief Will initialize new reed solomon
37
+ *
38
+ * @param[in] data_shards Total number of data shards
39
+ * @param[in] parity_shards The total number of parity shards
40
+ * @return A null value on error
41
+ */
42
+ reed_solomon* reed_solomon_new(int data_shards, int parity_shards);
43
+
44
+ /**
45
+ * @brief Will free existing reed solomon
46
+ *
47
+ * @param[in] rs
48
+ */
49
+ void reed_solomon_release(reed_solomon* rs);
50
+
51
+ int reed_solomon_encode(reed_solomon* rs,
52
+ uint8_t** data_blocks,
53
+ uint8_t** fec_blocks,
54
+ uint64_t block_size,
55
+ uint64_t total_bytes);
56
+
57
+
58
+ int reed_solomon_decode(reed_solomon* rs,
59
+ uint8_t **data_blocks,
60
+ uint64_t block_size,
61
+ uint8_t **dec_fec_blocks,
62
+ unsigned int *fec_block_nos,
63
+ unsigned int *erased_blocks,
64
+ int nr_fec_blocks,
65
+ uint64_t total_bytes);
66
+
67
+
68
+ /**
69
+ * @brief Will encode large buffer into parity shards
70
+ *
71
+ * @param[in] rs
72
+ * @param[in] data_blocks Data shards
73
+ * @param[in] fec_blocks Parity shards
74
+ * @param[in] nr_shards Total number of shards/blocks
75
+ * @param[in] block_size The size of each shard
76
+ * @param[in] total_bytes The total size used for zero padding the last shard
77
+ * @return A non-zero error value on failure and 0 on success.
78
+ */
79
+ int reed_solomon_encode2(reed_solomon* rs, uint8_t** data_blocks,
80
+ uint8_t** fec_blocks, int nr_shards, uint64_t block_size,
81
+ uint64_t total_bytes);
82
+
83
+ /**
84
+ * @brief Will repair missing data in blocks
85
+ *
86
+ * @param[in] rs
87
+ * @param[in] data_blocks Data shards
88
+ * @param[in] fec_blocks Parity shards
89
+ * @param[in] marks An array with 1 used to mark missing blocks
90
+ * @param[in] nr_shards Total number of shards/blocks
91
+ * @param[in] block_size The size of each shard
92
+ * @param[in] total_bytes The total size used for zero padding the last shard
93
+ * @return A non-zero error value on failure and 0 on success.
94
+ */
95
+ int reed_solomon_reconstruct(reed_solomon* rs, uint8_t** data_blocks,
96
+ uint8_t** fec_blocks, uint8_t* marks,
97
+ int nr_shards, uint64_t block_size,
98
+ uint64_t total_bytes);
99
+ #endif
@@ -0,0 +1,1523 @@
1
+ #include "storj.h"
2
+ #include "http.h"
3
+ #include "utils.h"
4
+ #include "crypto.h"
5
+
6
+ static inline void noop() {};
7
+
8
+ static void json_request_worker(uv_work_t *work)
9
+ {
10
+ json_request_t *req = work->data;
11
+ int status_code = 0;
12
+
13
+ req->error_code = fetch_json(req->http_options,
14
+ req->options, req->method, req->path, req->body,
15
+ req->auth, &req->response, &status_code);
16
+
17
+ req->status_code = status_code;
18
+ }
19
+
20
+ static void create_bucket_request_worker(uv_work_t *work)
21
+ {
22
+ create_bucket_request_t *req = work->data;
23
+ int status_code = 0;
24
+
25
+ // Derive a key based on the master seed and bucket name magic number
26
+ char *bucket_key_as_str = calloc(DETERMINISTIC_KEY_SIZE + 1, sizeof(char));
27
+ generate_bucket_key(req->encrypt_options->mnemonic,
28
+ BUCKET_NAME_MAGIC,
29
+ &bucket_key_as_str);
30
+
31
+ uint8_t *bucket_key = str2hex(strlen(bucket_key_as_str), bucket_key_as_str);
32
+ if (!bucket_key) {
33
+ req->error_code = STORJ_MEMORY_ERROR;
34
+ return;
35
+ }
36
+
37
+ free(bucket_key_as_str);
38
+
39
+ // Get bucket name encryption key with first half of hmac w/ magic
40
+ struct hmac_sha512_ctx ctx1;
41
+ hmac_sha512_set_key(&ctx1, SHA256_DIGEST_SIZE, bucket_key);
42
+ hmac_sha512_update(&ctx1, SHA256_DIGEST_SIZE, BUCKET_META_MAGIC);
43
+ uint8_t key[SHA256_DIGEST_SIZE];
44
+ hmac_sha512_digest(&ctx1, SHA256_DIGEST_SIZE, key);
45
+
46
+ // Generate the synthetic iv with first half of hmac w/ name
47
+ struct hmac_sha512_ctx ctx2;
48
+ hmac_sha512_set_key(&ctx2, SHA256_DIGEST_SIZE, bucket_key);
49
+ hmac_sha512_update(&ctx2, strlen(req->bucket_name),
50
+ (uint8_t *)req->bucket_name);
51
+ uint8_t bucketname_iv[SHA256_DIGEST_SIZE];
52
+ hmac_sha512_digest(&ctx2, SHA256_DIGEST_SIZE, bucketname_iv);
53
+
54
+ free(bucket_key);
55
+
56
+ // Encrypt the bucket name
57
+ char *encrypted_bucket_name;
58
+ encrypt_meta(req->bucket_name, key, bucketname_iv, &encrypted_bucket_name);
59
+ req->encrypted_bucket_name = encrypted_bucket_name;
60
+
61
+ struct json_object *body = json_object_new_object();
62
+ json_object *name = json_object_new_string(req->encrypted_bucket_name);
63
+ json_object_object_add(body, "name", name);
64
+
65
+ req->error_code = fetch_json(req->http_options,
66
+ req->bridge_options, "POST", "/buckets", body,
67
+ true, &req->response, &status_code);
68
+
69
+ json_object_put(body);
70
+
71
+ if (req->response != NULL) {
72
+ req->bucket = malloc(sizeof(storj_bucket_meta_t));
73
+
74
+ struct json_object *id;
75
+ json_object_object_get_ex(req->response, "id", &id);
76
+
77
+ req->bucket->id = json_object_get_string(id);
78
+ req->bucket->name = req->bucket_name;
79
+ req->bucket->decrypted = true;
80
+ }
81
+
82
+ req->status_code = status_code;
83
+ }
84
+
85
+ static void get_buckets_request_worker(uv_work_t *work)
86
+ {
87
+ get_buckets_request_t *req = work->data;
88
+ int status_code = 0;
89
+
90
+ req->error_code = fetch_json(req->http_options,
91
+ req->options, req->method, req->path, req->body,
92
+ req->auth, &req->response, &status_code);
93
+
94
+ req->status_code = status_code;
95
+
96
+ int num_buckets = 0;
97
+ if (req->response != NULL &&
98
+ json_object_is_type(req->response, json_type_array)) {
99
+ num_buckets = json_object_array_length(req->response);
100
+ }
101
+
102
+ if (num_buckets > 0) {
103
+ req->buckets = malloc(sizeof(storj_bucket_meta_t) * num_buckets);
104
+ req->total_buckets = num_buckets;
105
+ }
106
+
107
+ // Derive a key based on the master seed
108
+ char *bucket_key_as_str = calloc(DETERMINISTIC_KEY_SIZE + 1, sizeof(char));
109
+ generate_bucket_key(req->encrypt_options->mnemonic,
110
+ BUCKET_NAME_MAGIC,
111
+ &bucket_key_as_str);
112
+
113
+ uint8_t *bucket_key = str2hex(strlen(bucket_key_as_str), bucket_key_as_str);
114
+ if (!bucket_key) {
115
+ req->error_code = STORJ_MEMORY_ERROR;
116
+ return;
117
+ }
118
+
119
+ free(bucket_key_as_str);
120
+
121
+ // Get bucket name encryption key with first half of hmac w/ magic
122
+ struct hmac_sha512_ctx ctx1;
123
+ hmac_sha512_set_key(&ctx1, SHA256_DIGEST_SIZE, bucket_key);
124
+ hmac_sha512_update(&ctx1, SHA256_DIGEST_SIZE, BUCKET_META_MAGIC);
125
+ uint8_t key[SHA256_DIGEST_SIZE];
126
+ hmac_sha512_digest(&ctx1, SHA256_DIGEST_SIZE, key);
127
+
128
+ free(bucket_key);
129
+
130
+ struct json_object *bucket_item;
131
+ struct json_object *name;
132
+ struct json_object *created;
133
+ struct json_object *id;
134
+
135
+ for (int i = 0; i < num_buckets; i++) {
136
+ bucket_item = json_object_array_get_idx(req->response, i);
137
+
138
+ json_object_object_get_ex(bucket_item, "id", &id);
139
+ json_object_object_get_ex(bucket_item, "name", &name);
140
+ json_object_object_get_ex(bucket_item, "created", &created);
141
+
142
+ storj_bucket_meta_t *bucket = &req->buckets[i];
143
+ bucket->id = json_object_get_string(id);
144
+ bucket->decrypted = false;
145
+ bucket->created = json_object_get_string(created);
146
+ bucket->name = NULL;
147
+
148
+ // Attempt to decrypt the name, otherwise
149
+ // we will default the name to the encrypted text.
150
+ // The decrypted flag will be set to indicate the status
151
+ // of decryption for alternative display.
152
+ const char *encrypted_name = json_object_get_string(name);
153
+ if (!encrypted_name) {
154
+ continue;
155
+ }
156
+ char *decrypted_name;
157
+ int error_status = decrypt_meta(encrypted_name, key,
158
+ &decrypted_name);
159
+ if (!error_status) {
160
+ bucket->decrypted = true;
161
+ bucket->name = decrypted_name;
162
+ } else {
163
+ bucket->decrypted = false;
164
+ bucket->name = strdup(encrypted_name);
165
+ }
166
+ }
167
+ }
168
+
169
+ static void get_bucket_request_worker(uv_work_t *work)
170
+ {
171
+ get_bucket_request_t *req = work->data;
172
+ int status_code = 0;
173
+
174
+ req->error_code = fetch_json(req->http_options,
175
+ req->options, req->method, req->path, req->body,
176
+ req->auth, &req->response, &status_code);
177
+
178
+ req->status_code = status_code;
179
+
180
+ if (!req->response) {
181
+ req->bucket = NULL;
182
+ return;
183
+ }
184
+
185
+ // Derive a key based on the master seed
186
+ char *bucket_key_as_str = calloc(DETERMINISTIC_KEY_SIZE + 1, sizeof(char));
187
+ generate_bucket_key(req->encrypt_options->mnemonic,
188
+ BUCKET_NAME_MAGIC,
189
+ &bucket_key_as_str);
190
+
191
+ uint8_t *bucket_key = str2hex(strlen(bucket_key_as_str), bucket_key_as_str);
192
+ if (!bucket_key) {
193
+ req->error_code = STORJ_MEMORY_ERROR;
194
+ return;
195
+ }
196
+
197
+ free(bucket_key_as_str);
198
+
199
+ // Get bucket name encryption key with first half of hmac w/ magic
200
+ struct hmac_sha512_ctx ctx1;
201
+ hmac_sha512_set_key(&ctx1, SHA256_DIGEST_SIZE, bucket_key);
202
+ hmac_sha512_update(&ctx1, SHA256_DIGEST_SIZE, BUCKET_META_MAGIC);
203
+ uint8_t key[SHA256_DIGEST_SIZE];
204
+ hmac_sha512_digest(&ctx1, SHA256_DIGEST_SIZE, key);
205
+
206
+ free(bucket_key);
207
+
208
+ struct json_object *name;
209
+ struct json_object *created;
210
+ struct json_object *id;
211
+
212
+ json_object_object_get_ex(req->response, "id", &id);
213
+ json_object_object_get_ex(req->response, "name", &name);
214
+ json_object_object_get_ex(req->response, "created", &created);
215
+
216
+ req->bucket = malloc(sizeof(storj_bucket_meta_t));
217
+ req->bucket->id = json_object_get_string(id);
218
+ req->bucket->decrypted = false;
219
+ req->bucket->created = json_object_get_string(created);
220
+ req->bucket->name = NULL;
221
+
222
+ // Attempt to decrypt the name, otherwise
223
+ // we will default the name to the encrypted text.
224
+ // The decrypted flag will be set to indicate the status
225
+ // of decryption for alternative display.
226
+ const char *encrypted_name = json_object_get_string(name);
227
+ if (encrypted_name) {
228
+ char *decrypted_name;
229
+ int error_status = decrypt_meta(encrypted_name, key,
230
+ &decrypted_name);
231
+ if (!error_status) {
232
+ req->bucket->decrypted = true;
233
+ req->bucket->name = decrypted_name;
234
+ } else {
235
+ req->bucket->decrypted = false;
236
+ req->bucket->name = strdup(encrypted_name);
237
+ }
238
+ }
239
+ }
240
+
241
+ static void list_files_request_worker(uv_work_t *work)
242
+ {
243
+ list_files_request_t *req = work->data;
244
+ int status_code = 0;
245
+
246
+ req->error_code = fetch_json(req->http_options,
247
+ req->options, req->method, req->path, req->body,
248
+ req->auth, &req->response, &status_code);
249
+
250
+ req->status_code = status_code;
251
+
252
+ int num_files = 0;
253
+ if (req->response != NULL &&
254
+ json_object_is_type(req->response, json_type_array)) {
255
+ num_files = json_object_array_length(req->response);
256
+ }
257
+
258
+ if (num_files > 0) {
259
+ req->files = malloc(sizeof(storj_file_meta_t) * num_files);
260
+ req->total_files = num_files;
261
+ }
262
+
263
+ // Get the bucket key to encrypt the filename from bucket id
264
+ char *bucket_key_as_str = calloc(DETERMINISTIC_KEY_SIZE + 1, sizeof(char));
265
+ generate_bucket_key(req->encrypt_options->mnemonic,
266
+ req->bucket_id,
267
+ &bucket_key_as_str);
268
+
269
+ uint8_t *bucket_key = str2hex(strlen(bucket_key_as_str), bucket_key_as_str);
270
+ if (!bucket_key) {
271
+ req->error_code = STORJ_MEMORY_ERROR;
272
+ return;
273
+ }
274
+
275
+ free(bucket_key_as_str);
276
+
277
+ // Get file name encryption key with first half of hmac w/ magic
278
+ struct hmac_sha512_ctx ctx1;
279
+ hmac_sha512_set_key(&ctx1, SHA256_DIGEST_SIZE, bucket_key);
280
+ hmac_sha512_update(&ctx1, SHA256_DIGEST_SIZE, BUCKET_META_MAGIC);
281
+ uint8_t key[SHA256_DIGEST_SIZE];
282
+ hmac_sha512_digest(&ctx1, SHA256_DIGEST_SIZE, key);
283
+
284
+ free(bucket_key);
285
+
286
+ struct json_object *file;
287
+ struct json_object *filename;
288
+ struct json_object *mimetype;
289
+ struct json_object *size;
290
+ struct json_object *id;
291
+ struct json_object *created;
292
+
293
+ for (int i = 0; i < num_files; i++) {
294
+ file = json_object_array_get_idx(req->response, i);
295
+
296
+ json_object_object_get_ex(file, "filename", &filename);
297
+ json_object_object_get_ex(file, "mimetype", &mimetype);
298
+ json_object_object_get_ex(file, "size", &size);
299
+ json_object_object_get_ex(file, "id", &id);
300
+ json_object_object_get_ex(file, "created", &created);
301
+
302
+ storj_file_meta_t *file = &req->files[i];
303
+
304
+ file->created = json_object_get_string(created);
305
+ file->mimetype = json_object_get_string(mimetype);
306
+ file->size = json_object_get_int64(size);
307
+ file->erasure = NULL;
308
+ file->index = NULL;
309
+ file->hmac = NULL; // TODO though this value is not needed here
310
+ file->id = json_object_get_string(id);
311
+ file->decrypted = false;
312
+ file->filename = NULL;
313
+
314
+ // Attempt to decrypt the filename, otherwise
315
+ // we will default the filename to the encrypted text.
316
+ // The decrypted flag will be set to indicate the status
317
+ // of decryption for alternative display.
318
+ const char *encrypted_file_name = json_object_get_string(filename);
319
+ if (!encrypted_file_name) {
320
+ continue;
321
+ }
322
+ char *decrypted_file_name;
323
+ int error_status = decrypt_meta(encrypted_file_name, key,
324
+ &decrypted_file_name);
325
+ if (!error_status) {
326
+ file->decrypted = true;
327
+ file->filename = decrypted_file_name;
328
+ } else {
329
+ file->decrypted = false;
330
+ file->filename = strdup(encrypted_file_name);
331
+ }
332
+ }
333
+ }
334
+
335
+ static uv_work_t *uv_work_new()
336
+ {
337
+ uv_work_t *work = malloc(sizeof(uv_work_t));
338
+ return work;
339
+ }
340
+
341
+ static json_request_t *json_request_new(
342
+ storj_http_options_t *http_options,
343
+ storj_bridge_options_t *options,
344
+ char *method,
345
+ char *path,
346
+ struct json_object *request_body,
347
+ bool auth,
348
+ void *handle)
349
+ {
350
+
351
+ json_request_t *req = malloc(sizeof(json_request_t));
352
+ if (!req) {
353
+ return NULL;
354
+ }
355
+
356
+ req->http_options = http_options;
357
+ req->options = options;
358
+ req->method = method;
359
+ req->path = path;
360
+ req->auth = auth;
361
+ req->body = request_body;
362
+ req->response = NULL;
363
+ req->error_code = 0;
364
+ req->status_code = 0;
365
+ req->handle = handle;
366
+
367
+ return req;
368
+ }
369
+
370
+ static list_files_request_t *list_files_request_new(
371
+ storj_http_options_t *http_options,
372
+ storj_bridge_options_t *options,
373
+ storj_encrypt_options_t *encrypt_options,
374
+ const char *bucket_id,
375
+ char *method,
376
+ char *path,
377
+ struct json_object *request_body,
378
+ bool auth,
379
+ void *handle)
380
+ {
381
+ list_files_request_t *req = malloc(sizeof(list_files_request_t));
382
+ if (!req) {
383
+ return NULL;
384
+ }
385
+
386
+ req->http_options = http_options;
387
+ req->options = options;
388
+ req->encrypt_options = encrypt_options;
389
+ req->bucket_id = bucket_id;
390
+ req->method = method;
391
+ req->path = path;
392
+ req->auth = auth;
393
+ req->body = request_body;
394
+ req->response = NULL;
395
+ req->files = NULL;
396
+ req->total_files = 0;
397
+ req->error_code = 0;
398
+ req->status_code = 0;
399
+ req->handle = handle;
400
+
401
+ return req;
402
+ }
403
+
404
+ static create_bucket_request_t *create_bucket_request_new(
405
+ storj_http_options_t *http_options,
406
+ storj_bridge_options_t *bridge_options,
407
+ storj_encrypt_options_t *encrypt_options,
408
+ const char *bucket_name,
409
+ void *handle)
410
+ {
411
+ create_bucket_request_t *req = malloc(sizeof(create_bucket_request_t));
412
+ if (!req) {
413
+ return NULL;
414
+ }
415
+
416
+ req->http_options = http_options;
417
+ req->encrypt_options = encrypt_options;
418
+ req->bridge_options = bridge_options;
419
+ req->bucket_name = bucket_name;
420
+ req->encrypted_bucket_name = NULL;
421
+ req->response = NULL;
422
+ req->bucket = NULL;
423
+ req->error_code = 0;
424
+ req->status_code = 0;
425
+ req->handle = handle;
426
+
427
+ return req;
428
+ }
429
+
430
+ static get_buckets_request_t *get_buckets_request_new(
431
+ storj_http_options_t *http_options,
432
+ storj_bridge_options_t *options,
433
+ storj_encrypt_options_t *encrypt_options,
434
+ char *method,
435
+ char *path,
436
+ struct json_object *request_body,
437
+ bool auth,
438
+ void *handle)
439
+ {
440
+ get_buckets_request_t *req = malloc(sizeof(get_buckets_request_t));
441
+ if (!req) {
442
+ return NULL;
443
+ }
444
+
445
+ req->http_options = http_options;
446
+ req->options = options;
447
+ req->encrypt_options = encrypt_options;
448
+ req->method = method;
449
+ req->path = path;
450
+ req->auth = auth;
451
+ req->body = request_body;
452
+ req->response = NULL;
453
+ req->buckets = NULL;
454
+ req->total_buckets = 0;
455
+ req->error_code = 0;
456
+ req->status_code = 0;
457
+ req->handle = handle;
458
+
459
+ return req;
460
+ }
461
+
462
+ static get_bucket_request_t *get_bucket_request_new(
463
+ storj_http_options_t *http_options,
464
+ storj_bridge_options_t *options,
465
+ storj_encrypt_options_t *encrypt_options,
466
+ char *method,
467
+ char *path,
468
+ struct json_object *request_body,
469
+ bool auth,
470
+ void *handle)
471
+ {
472
+ get_bucket_request_t *req = malloc(sizeof(get_bucket_request_t));
473
+ if (!req) {
474
+ return NULL;
475
+ }
476
+
477
+ req->http_options = http_options;
478
+ req->options = options;
479
+ req->encrypt_options = encrypt_options;
480
+ req->method = method;
481
+ req->path = path;
482
+ req->auth = auth;
483
+ req->body = request_body;
484
+ req->response = NULL;
485
+ req->bucket = NULL;
486
+ req->error_code = 0;
487
+ req->status_code = 0;
488
+ req->handle = handle;
489
+
490
+ return req;
491
+ }
492
+
493
+ static uv_work_t *json_request_work_new(
494
+ storj_env_t *env,
495
+ char *method,
496
+ char *path,
497
+ struct json_object *request_body,
498
+ bool auth,
499
+ void *handle)
500
+ {
501
+ uv_work_t *work = uv_work_new();
502
+ if (!work) {
503
+ return NULL;
504
+ }
505
+ work->data = json_request_new(env->http_options,
506
+ env->bridge_options, method, path,
507
+ request_body, auth, handle);
508
+
509
+ if (!work->data) {
510
+ return NULL;
511
+ }
512
+
513
+ return work;
514
+ }
515
+
516
+ static void default_logger(const char *message,
517
+ int level,
518
+ void *handle)
519
+ {
520
+ puts(message);
521
+ }
522
+
523
+ static void log_formatter(storj_log_options_t *options,
524
+ void *handle,
525
+ int level,
526
+ const char *format,
527
+ va_list args)
528
+ {
529
+ va_list args_cpy;
530
+ va_copy(args_cpy, args);
531
+ int length = vsnprintf(0, 0, format, args_cpy);
532
+ va_end(args_cpy);
533
+
534
+ if (length > 0) {
535
+ char message[length + 1];
536
+ if (vsnprintf(message, length + 1, format, args)) {
537
+ options->logger(message, level, handle);
538
+ }
539
+ }
540
+ }
541
+
542
+ static void log_formatter_debug(storj_log_options_t *options, void *handle,
543
+ const char *format, ...)
544
+ {
545
+ va_list args;
546
+ va_start(args, format);
547
+ log_formatter(options, handle, 4, format, args);
548
+ va_end(args);
549
+ }
550
+
551
+ static void log_formatter_info(storj_log_options_t *options, void *handle,
552
+ const char *format, ...)
553
+ {
554
+ va_list args;
555
+ va_start(args, format);
556
+ log_formatter(options, handle, 3, format, args);
557
+ va_end(args);
558
+ }
559
+
560
+ static void log_formatter_warn(storj_log_options_t *options, void *handle,
561
+ const char *format, ...)
562
+ {
563
+ va_list args;
564
+ va_start(args, format);
565
+ log_formatter(options, handle, 2, format, args);
566
+ va_end(args);
567
+ }
568
+
569
+ static void log_formatter_error(storj_log_options_t *options, void *handle,
570
+ const char *format, ...)
571
+ {
572
+ va_list args;
573
+ va_start(args, format);
574
+ log_formatter(options, handle, 1, format, args);
575
+ va_end(args);
576
+ }
577
+
578
+ STORJ_API struct storj_env *storj_init_env(storj_bridge_options_t *options,
579
+ storj_encrypt_options_t *encrypt_options,
580
+ storj_http_options_t *http_options,
581
+ storj_log_options_t *log_options)
582
+ {
583
+ curl_global_init(CURL_GLOBAL_ALL);
584
+
585
+ uv_loop_t *loop = uv_default_loop();
586
+ if (!loop) {
587
+ return NULL;
588
+ }
589
+
590
+ storj_env_t *env = malloc(sizeof(storj_env_t));
591
+ if (!env) {
592
+ return NULL;
593
+ }
594
+
595
+ // setup the uv event loop
596
+ env->loop = loop;
597
+
598
+ // deep copy bridge options
599
+ storj_bridge_options_t *bo = malloc(sizeof(storj_bridge_options_t));
600
+ if (!bo) {
601
+ return NULL;
602
+ }
603
+
604
+ bo->proto = strdup(options->proto);
605
+ bo->host = strdup(options->host);
606
+ bo->port = options->port;
607
+ if (options->user) {
608
+ bo->user = strdup(options->user);
609
+ } else {
610
+ bo->user = NULL;
611
+ }
612
+
613
+ #ifdef _POSIX_MEMLOCK
614
+ int page_size = sysconf(_SC_PAGESIZE);
615
+ #elif _WIN32
616
+ SYSTEM_INFO si;
617
+ GetSystemInfo (&si);
618
+ uintptr_t page_size = si.dwPageSize;
619
+ #endif
620
+
621
+ if (options->pass) {
622
+ // prevent bridge password from being swapped unencrypted to disk
623
+ #ifdef _POSIX_MEMLOCK
624
+ int pass_len = strlen(options->pass);
625
+ if (pass_len >= page_size) {
626
+ return NULL;
627
+ }
628
+
629
+ #ifdef HAVE_ALIGNED_ALLOC
630
+ bo->pass = aligned_alloc(page_size, page_size);
631
+ #elif HAVE_POSIX_MEMALIGN
632
+ bo->pass = NULL;
633
+ if (posix_memalign((void *)&bo->pass, page_size, page_size)) {
634
+ return NULL;
635
+ }
636
+ #else
637
+ bo->pass = malloc(page_size);
638
+ #endif
639
+
640
+ if (bo->pass == NULL) {
641
+ return NULL;
642
+ }
643
+ memset((char *)bo->pass, 0, page_size);
644
+ memcpy((char *)bo->pass, options->pass, pass_len);
645
+ if (mlock(bo->pass, pass_len)) {
646
+ return NULL;
647
+ }
648
+ #elif _WIN32
649
+ int pass_len = strlen(options->pass);
650
+ bo->pass = VirtualAlloc(NULL, page_size, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE);
651
+ if (bo->pass == NULL) {
652
+ return NULL;
653
+ }
654
+ memset((char *)bo->pass, 0, page_size);
655
+ memcpy((char *)bo->pass, options->pass, pass_len);
656
+ if (!VirtualLock((char *)bo->pass, pass_len)) {
657
+ return NULL;
658
+ }
659
+ #else
660
+ bo->pass = strdup(options->pass);
661
+ #endif
662
+ } else {
663
+ bo->pass = NULL;
664
+ }
665
+
666
+ env->bridge_options = bo;
667
+
668
+ // deep copy encryption options
669
+ storj_encrypt_options_t *eo = malloc(sizeof(storj_encrypt_options_t));
670
+ if (!eo) {
671
+ return NULL;
672
+ }
673
+
674
+ if (encrypt_options && encrypt_options->mnemonic) {
675
+
676
+ // prevent file encryption mnemonic from being swapped unencrypted to disk
677
+ #ifdef _POSIX_MEMLOCK
678
+ int mnemonic_len = strlen(encrypt_options->mnemonic);
679
+ if (mnemonic_len >= page_size) {
680
+ return NULL;
681
+ }
682
+
683
+ #ifdef HAVE_ALIGNED_ALLOC
684
+ eo->mnemonic = aligned_alloc(page_size, page_size);
685
+ #elif HAVE_POSIX_MEMALIGN
686
+ eo->mnemonic = NULL;
687
+ if (posix_memalign((void *)&eo->mnemonic, page_size, page_size)) {
688
+ return NULL;
689
+ }
690
+ #else
691
+ eo->mnemonic = malloc(page_size);
692
+ #endif
693
+
694
+ if (eo->mnemonic == NULL) {
695
+ return NULL;
696
+ }
697
+
698
+ memset((char *)eo->mnemonic, 0, page_size);
699
+ memcpy((char *)eo->mnemonic, encrypt_options->mnemonic, mnemonic_len);
700
+ if (mlock(eo->mnemonic, mnemonic_len)) {
701
+ return NULL;
702
+ }
703
+ #elif _WIN32
704
+ int mnemonic_len = strlen(encrypt_options->mnemonic);
705
+ eo->mnemonic = VirtualAlloc(NULL, page_size, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE);
706
+ if (eo->mnemonic == NULL) {
707
+ return NULL;
708
+ }
709
+ memset((char *)eo->mnemonic, 0, page_size);
710
+ memcpy((char *)eo->mnemonic, encrypt_options->mnemonic, mnemonic_len);
711
+ if (!VirtualLock((char *)eo->mnemonic, mnemonic_len)) {
712
+ return NULL;
713
+ }
714
+ #else
715
+ eo->mnemonic = strdup(encrypt_options->mnemonic);
716
+ #endif
717
+ } else {
718
+ eo->mnemonic = NULL;
719
+ }
720
+
721
+ env->encrypt_options = eo;
722
+
723
+ // Set tmp_path
724
+ struct stat sb;
725
+ env->tmp_path = NULL;
726
+ if (env->tmp_path &&
727
+ stat(env->tmp_path, &sb) == 0 &&
728
+ S_ISDIR(sb.st_mode)) {
729
+ env->tmp_path = strdup(env->tmp_path);
730
+ } else if (getenv("STORJ_TEMP") &&
731
+ stat(getenv("STORJ_TEMP"), &sb) == 0 &&
732
+ S_ISDIR(sb.st_mode)) {
733
+ env->tmp_path = strdup(getenv("STORJ_TEMP"));
734
+ #ifdef _WIN32
735
+ } else if (getenv("TEMP") &&
736
+ stat(getenv("TEMP"), &sb) == 0 &&
737
+ S_ISDIR(sb.st_mode)) {
738
+ env->tmp_path = strdup(getenv("TEMP"));
739
+ #else
740
+ } else if ("/tmp" && stat("/tmp", &sb) == 0 && S_ISDIR(sb.st_mode)) {
741
+ env->tmp_path = strdup("/tmp");
742
+ #endif
743
+ } else {
744
+ env->tmp_path = NULL;
745
+ }
746
+
747
+ // deep copy the http options
748
+ storj_http_options_t *ho = malloc(sizeof(storj_http_options_t));
749
+ if (!ho) {
750
+ return NULL;
751
+ }
752
+ ho->user_agent = strdup(http_options->user_agent);
753
+ if (http_options->proxy_url) {
754
+ ho->proxy_url = strdup(http_options->proxy_url);
755
+ } else {
756
+ ho->proxy_url = NULL;
757
+ }
758
+ if (http_options->cainfo_path) {
759
+ ho->cainfo_path = strdup(http_options->cainfo_path);
760
+ } else {
761
+ ho->cainfo_path = NULL;
762
+ }
763
+ ho->low_speed_limit = http_options->low_speed_limit;
764
+ ho->low_speed_time = http_options->low_speed_time;
765
+ if (http_options->timeout == 0 ||
766
+ http_options->timeout >= STORJ_HTTP_TIMEOUT) {
767
+ ho->timeout = http_options->timeout;
768
+ } else {
769
+ ho->timeout = STORJ_HTTP_TIMEOUT;
770
+ }
771
+
772
+ env->http_options = ho;
773
+
774
+ // setup the log options
775
+ env->log_options = log_options;
776
+ if (!env->log_options->logger) {
777
+ env->log_options->logger = default_logger;
778
+ }
779
+
780
+ storj_log_levels_t *log = malloc(sizeof(storj_log_levels_t));
781
+ if (!log) {
782
+ return NULL;
783
+ }
784
+
785
+ log->debug = (storj_logger_format_fn)noop;
786
+ log->info = (storj_logger_format_fn)noop;
787
+ log->warn = (storj_logger_format_fn)noop;
788
+ log->error = (storj_logger_format_fn)noop;
789
+
790
+ switch(log_options->level) {
791
+ case 4:
792
+ log->debug = log_formatter_debug;
793
+ case 3:
794
+ log->info = log_formatter_info;
795
+ case 2:
796
+ log->warn = log_formatter_warn;
797
+ case 1:
798
+ log->error = log_formatter_error;
799
+ case 0:
800
+ break;
801
+ }
802
+
803
+ env->log = log;
804
+
805
+ return env;
806
+ }
807
+
808
+ STORJ_API int storj_destroy_env(storj_env_t *env)
809
+ {
810
+ int status = 0;
811
+
812
+ // free and destroy all bridge options
813
+ free((char *)env->bridge_options->proto);
814
+ free((char *)env->bridge_options->host);
815
+ free((char *)env->bridge_options->user);
816
+
817
+ // zero out password before freeing
818
+ if (env->bridge_options->pass) {
819
+ unsigned int pass_len = strlen(env->bridge_options->pass);
820
+ if (pass_len > 0) {
821
+ memset_zero((char *)env->bridge_options->pass, pass_len);
822
+ }
823
+ #ifdef _POSIX_MEMLOCK
824
+ status = munlock(env->bridge_options->pass, pass_len);
825
+ #elif _WIN32
826
+ if (!VirtualUnlock((char *)env->bridge_options->pass, pass_len)) {
827
+ status = 1;
828
+ }
829
+ #endif
830
+
831
+ #ifdef _WIN32
832
+ VirtualFree((char *)env->bridge_options, pass_len, MEM_RELEASE);
833
+ #else
834
+ free((char *)env->bridge_options->pass);
835
+ #endif
836
+
837
+ }
838
+
839
+ free(env->bridge_options);
840
+
841
+ // free and destroy all encryption options
842
+ if (env->encrypt_options && env->encrypt_options->mnemonic) {
843
+ unsigned int mnemonic_len = strlen(env->encrypt_options->mnemonic);
844
+
845
+ // zero out file encryption mnemonic before freeing
846
+ if (mnemonic_len > 0) {
847
+ memset_zero((char *)env->encrypt_options->mnemonic, mnemonic_len);
848
+ }
849
+ #ifdef _POSIX_MEMLOCK
850
+ status = munlock(env->encrypt_options->mnemonic, mnemonic_len);
851
+ #elif _WIN32
852
+ if (!VirtualUnlock((char *)env->encrypt_options->mnemonic, mnemonic_len)) {
853
+ status = 1;
854
+ }
855
+ #endif
856
+
857
+ #ifdef _WIN32
858
+ VirtualFree((char *)env->bridge_options, mnemonic_len, MEM_RELEASE);
859
+ #else
860
+ free((char *)env->encrypt_options->mnemonic);
861
+ #endif
862
+ }
863
+
864
+ if (env->tmp_path) {
865
+ free((char *)env->tmp_path);
866
+ }
867
+
868
+ free(env->encrypt_options);
869
+
870
+ // free all http options
871
+ free((char *)env->http_options->user_agent);
872
+ if (env->http_options->proxy_url) {
873
+ free((char *)env->http_options->proxy_url);
874
+ }
875
+ if (env->http_options->cainfo_path) {
876
+ free((char *)env->http_options->cainfo_path);
877
+ }
878
+ free(env->http_options);
879
+
880
+ // free the log levels
881
+ free(env->log);
882
+
883
+ // free the environment
884
+ free(env);
885
+
886
+ curl_global_cleanup();
887
+
888
+ return status;
889
+ }
890
+
891
+ STORJ_API int storj_encrypt_auth(const char *passphrase,
892
+ const char *bridge_user,
893
+ const char *bridge_pass,
894
+ const char *mnemonic,
895
+ char **buffer)
896
+ {
897
+ char *pass_encrypted;
898
+ int pass_length = strlen(bridge_pass);
899
+
900
+ if (encrypt_data(passphrase, bridge_user, bridge_pass,
901
+ &pass_encrypted)) {
902
+ return 1;
903
+ }
904
+
905
+ char *mnemonic_encrypted;
906
+ int mnemonic_length = strlen(mnemonic);
907
+
908
+ if (encrypt_data(passphrase, bridge_user, mnemonic,
909
+ &mnemonic_encrypted)) {
910
+ return 1;
911
+ }
912
+
913
+ struct json_object *body = json_object_new_object();
914
+ json_object *user_str = json_object_new_string(bridge_user);
915
+
916
+ json_object *pass_str = json_object_new_string(pass_encrypted);
917
+ json_object *mnemonic_str = json_object_new_string(mnemonic_encrypted);
918
+
919
+ json_object_object_add(body, "user", user_str);
920
+ json_object_object_add(body, "pass", pass_str);
921
+ json_object_object_add(body, "mnemonic", mnemonic_str);
922
+
923
+ const char *body_str = json_object_to_json_string(body);
924
+
925
+ *buffer = calloc(strlen(body_str) + 1, sizeof(char));
926
+ memcpy(*buffer, body_str, strlen(body_str) + 1);
927
+
928
+ json_object_put(body);
929
+ free(mnemonic_encrypted);
930
+ free(pass_encrypted);
931
+
932
+ return 0;
933
+ }
934
+
935
+ STORJ_API int storj_encrypt_write_auth(const char *filepath,
936
+ const char *passphrase,
937
+ const char *bridge_user,
938
+ const char *bridge_pass,
939
+ const char *mnemonic)
940
+ {
941
+ FILE *fp;
942
+ fp = fopen(filepath, "w");
943
+ if (fp == NULL) {
944
+ return 1;
945
+ }
946
+
947
+ char *buffer = NULL;
948
+ if (storj_encrypt_auth(passphrase, bridge_user,
949
+ bridge_pass, mnemonic, &buffer)) {
950
+ fclose(fp);
951
+ return 1;
952
+ }
953
+
954
+ fwrite(buffer, strlen(buffer), sizeof(char), fp);
955
+ fwrite("\n", 1, sizeof(char), fp);
956
+
957
+ free(buffer);
958
+ fclose(fp);
959
+
960
+ return 0;
961
+ }
962
+
963
+ STORJ_API int storj_decrypt_auth(const char *buffer,
964
+ const char *passphrase,
965
+ char **bridge_user,
966
+ char **bridge_pass,
967
+ char **mnemonic)
968
+ {
969
+ int status = 0;
970
+
971
+ json_object *body = json_tokener_parse(buffer);
972
+
973
+ struct json_object *user_value;
974
+ if (!json_object_object_get_ex(body, "user", &user_value)) {
975
+ status = 1;
976
+ goto clean_up;
977
+ }
978
+
979
+ *bridge_user = strdup((char *)json_object_get_string(user_value));
980
+
981
+ struct json_object *pass_value;
982
+ if (!json_object_object_get_ex(body, "pass", &pass_value)) {
983
+ status = 1;
984
+ goto clean_up;
985
+ }
986
+ char *pass_enc = (char *)json_object_get_string(pass_value);
987
+
988
+ struct json_object *mnemonic_value;
989
+ if (!json_object_object_get_ex(body, "mnemonic", &mnemonic_value)) {
990
+ status = 1;
991
+ goto clean_up;
992
+ }
993
+ char *mnemonic_enc = (char *)json_object_get_string(mnemonic_value);
994
+
995
+ if (decrypt_data(passphrase, *bridge_user, pass_enc, bridge_pass)) {
996
+ status = 1;
997
+ goto clean_up;
998
+ }
999
+
1000
+ if (decrypt_data(passphrase, *bridge_user, mnemonic_enc, mnemonic)) {
1001
+ status = 1;
1002
+ goto clean_up;
1003
+ }
1004
+
1005
+ clean_up:
1006
+ json_object_put(body);
1007
+
1008
+ return status;
1009
+ }
1010
+
1011
+ STORJ_API int storj_decrypt_read_auth(const char *filepath,
1012
+ const char *passphrase,
1013
+ char **bridge_user,
1014
+ char **bridge_pass,
1015
+ char **mnemonic)
1016
+ {
1017
+ FILE *fp;
1018
+ fp = fopen(filepath, "r");
1019
+ if (fp == NULL) {
1020
+ return 1;
1021
+ }
1022
+
1023
+ fseek(fp, 0, SEEK_END);
1024
+ int fsize = ftell(fp);
1025
+ fseek(fp, 0, SEEK_SET);
1026
+
1027
+ char *buffer = calloc(fsize + 1, sizeof(char));
1028
+ if (buffer == NULL) {
1029
+ return 1;
1030
+ }
1031
+
1032
+ int read_blocks = 0;
1033
+ while ((!feof(fp)) && (!ferror(fp))) {
1034
+ read_blocks = fread(buffer + read_blocks, 1, fsize, fp);
1035
+ if (read_blocks <= 0) {
1036
+ break;
1037
+ }
1038
+ }
1039
+
1040
+ int error = ferror(fp);
1041
+ fclose(fp);
1042
+
1043
+ if (error) {
1044
+ return error;
1045
+ }
1046
+
1047
+ int status = storj_decrypt_auth(buffer, passphrase, bridge_user,
1048
+ bridge_pass, mnemonic);
1049
+
1050
+ free(buffer);
1051
+
1052
+ return status;
1053
+
1054
+ }
1055
+
1056
+ STORJ_API uint64_t storj_util_timestamp()
1057
+ {
1058
+ return get_time_milliseconds();
1059
+ }
1060
+
1061
+ STORJ_API int storj_mnemonic_generate(int strength, char **buffer)
1062
+ {
1063
+ return mnemonic_generate(strength, buffer);
1064
+ }
1065
+
1066
+ STORJ_API bool storj_mnemonic_check(const char *mnemonic)
1067
+ {
1068
+ return mnemonic_check(mnemonic);
1069
+ }
1070
+
1071
+ STORJ_API char *storj_strerror(int error_code)
1072
+ {
1073
+ switch(error_code) {
1074
+ case STORJ_BRIDGE_REQUEST_ERROR:
1075
+ return "Bridge request error";
1076
+ case STORJ_BRIDGE_AUTH_ERROR:
1077
+ return "Bridge request authorization error";
1078
+ case STORJ_BRIDGE_TOKEN_ERROR:
1079
+ return "Bridge request token error";
1080
+ case STORJ_BRIDGE_POINTER_ERROR:
1081
+ return "Bridge request pointer error";
1082
+ case STORJ_BRIDGE_REPOINTER_ERROR:
1083
+ return "Bridge request replace pointer error";
1084
+ case STORJ_BRIDGE_TIMEOUT_ERROR:
1085
+ return "Bridge request timeout error";
1086
+ case STORJ_BRIDGE_INTERNAL_ERROR:
1087
+ return "Bridge request internal error";
1088
+ case STORJ_BRIDGE_RATE_ERROR:
1089
+ return "Bridge rate limit error";
1090
+ case STORJ_BRIDGE_BUCKET_NOTFOUND_ERROR:
1091
+ return "Bucket is not found";
1092
+ case STORJ_BRIDGE_FILE_NOTFOUND_ERROR:
1093
+ return "File is not found";
1094
+ case STORJ_BRIDGE_BUCKET_FILE_EXISTS:
1095
+ return "File already exists";
1096
+ case STORJ_BRIDGE_OFFER_ERROR:
1097
+ return "Unable to receive storage offer";
1098
+ case STORJ_BRIDGE_JSON_ERROR:
1099
+ return "Unexpected JSON response";
1100
+ case STORJ_BRIDGE_FILEINFO_ERROR:
1101
+ return "Bridge file info error";
1102
+ case STORJ_FARMER_REQUEST_ERROR:
1103
+ return "Farmer request error";
1104
+ case STORJ_FARMER_EXHAUSTED_ERROR:
1105
+ return "Farmer exhausted error";
1106
+ case STORJ_FARMER_TIMEOUT_ERROR:
1107
+ return "Farmer request timeout error";
1108
+ case STORJ_FARMER_AUTH_ERROR:
1109
+ return "Farmer request authorization error";
1110
+ case STORJ_FARMER_INTEGRITY_ERROR:
1111
+ return "Farmer request integrity error";
1112
+ case STORJ_FILE_INTEGRITY_ERROR:
1113
+ return "File integrity error";
1114
+ case STORJ_FILE_READ_ERROR:
1115
+ return "File read error";
1116
+ case STORJ_FILE_WRITE_ERROR:
1117
+ return "File write error";
1118
+ case STORJ_BRIDGE_FRAME_ERROR:
1119
+ return "Bridge frame request error";
1120
+ case STORJ_FILE_ENCRYPTION_ERROR:
1121
+ return "File encryption error";
1122
+ case STORJ_FILE_SIZE_ERROR:
1123
+ return "File size error";
1124
+ case STORJ_FILE_DECRYPTION_ERROR:
1125
+ return "File decryption error";
1126
+ case STORJ_FILE_GENERATE_HMAC_ERROR:
1127
+ return "File hmac generation error";
1128
+ case STORJ_FILE_SHARD_MISSING_ERROR:
1129
+ return "File missing shard error";
1130
+ case STORJ_FILE_RECOVER_ERROR:
1131
+ return "File recover error";
1132
+ case STORJ_FILE_RESIZE_ERROR:
1133
+ return "File resize error";
1134
+ case STORJ_FILE_UNSUPPORTED_ERASURE:
1135
+ return "File unsupported erasure code error";
1136
+ case STORJ_FILE_PARITY_ERROR:
1137
+ return "File create parity error";
1138
+ case STORJ_META_ENCRYPTION_ERROR:
1139
+ return "Meta encryption error";
1140
+ case STORJ_META_DECRYPTION_ERROR:
1141
+ return "Meta decryption error";
1142
+ case STORJ_TRANSFER_CANCELED:
1143
+ return "File transfer canceled";
1144
+ case STORJ_MEMORY_ERROR:
1145
+ return "Memory error";
1146
+ case STORJ_MAPPING_ERROR:
1147
+ return "Memory mapped file error";
1148
+ case STORJ_UNMAPPING_ERROR:
1149
+ return "Memory mapped file unmap error";
1150
+ case STORJ_QUEUE_ERROR:
1151
+ return "Queue error";
1152
+ case STORJ_HEX_DECODE_ERROR:
1153
+ return "Unable to decode hex string";
1154
+ case STORJ_TRANSFER_OK:
1155
+ return "No errors";
1156
+ default:
1157
+ return "Unknown error";
1158
+ }
1159
+ }
1160
+
1161
+ STORJ_API int storj_bridge_get_info(storj_env_t *env, void *handle, uv_after_work_cb cb)
1162
+ {
1163
+ uv_work_t *work = json_request_work_new(env,"GET", "/", NULL,
1164
+ false, handle);
1165
+ if (!work) {
1166
+ return STORJ_MEMORY_ERROR;
1167
+ }
1168
+
1169
+ return uv_queue_work(env->loop, (uv_work_t*) work, json_request_worker, cb);
1170
+ }
1171
+
1172
+ STORJ_API int storj_bridge_get_buckets(storj_env_t *env, void *handle, uv_after_work_cb cb)
1173
+ {
1174
+ uv_work_t *work = uv_work_new();
1175
+ if (!work) {
1176
+ return STORJ_MEMORY_ERROR;
1177
+ }
1178
+ work->data = get_buckets_request_new(env->http_options,
1179
+ env->bridge_options,
1180
+ env->encrypt_options,
1181
+ "GET", "/buckets",
1182
+ NULL, true, handle);
1183
+ if (!work->data) {
1184
+ return STORJ_MEMORY_ERROR;
1185
+ }
1186
+
1187
+ return uv_queue_work(env->loop, (uv_work_t*) work,
1188
+ get_buckets_request_worker, cb);
1189
+ }
1190
+
1191
+ STORJ_API void storj_free_get_buckets_request(get_buckets_request_t *req)
1192
+ {
1193
+ json_object_put(req->response);
1194
+ if (req->buckets && req->total_buckets > 0) {
1195
+ for (int i = 0; i < req->total_buckets; i++) {
1196
+ free((char *)req->buckets[i].name);
1197
+ }
1198
+ }
1199
+ free(req->buckets);
1200
+ free(req);
1201
+ }
1202
+
1203
+ STORJ_API int storj_bridge_create_bucket(storj_env_t *env,
1204
+ const char *name,
1205
+ void *handle,
1206
+ uv_after_work_cb cb)
1207
+ {
1208
+ uv_work_t *work = uv_work_new();
1209
+ if (!work) {
1210
+ return STORJ_MEMORY_ERROR;
1211
+ }
1212
+
1213
+ work->data = create_bucket_request_new(env->http_options,
1214
+ env->bridge_options,
1215
+ env->encrypt_options,
1216
+ name,
1217
+ handle);
1218
+ if (!work->data) {
1219
+ return STORJ_MEMORY_ERROR;
1220
+ }
1221
+
1222
+ return uv_queue_work(env->loop, (uv_work_t*) work,
1223
+ create_bucket_request_worker, cb);
1224
+ }
1225
+
1226
+ STORJ_API int storj_bridge_delete_bucket(storj_env_t *env,
1227
+ const char *id,
1228
+ void *handle,
1229
+ uv_after_work_cb cb)
1230
+ {
1231
+ char *path = str_concat_many(2, "/buckets/", id);
1232
+ if (!path) {
1233
+ return STORJ_MEMORY_ERROR;
1234
+ }
1235
+
1236
+ uv_work_t *work = json_request_work_new(env, "DELETE", path,
1237
+ NULL, true, handle);
1238
+ if (!work) {
1239
+ return STORJ_MEMORY_ERROR;
1240
+ }
1241
+
1242
+ return uv_queue_work(env->loop, (uv_work_t*) work, json_request_worker, cb);
1243
+ }
1244
+
1245
+ STORJ_API int storj_bridge_get_bucket(storj_env_t *env,
1246
+ const char *id,
1247
+ void *handle,
1248
+ uv_after_work_cb cb)
1249
+ {
1250
+ uv_work_t *work = uv_work_new();
1251
+ if (!work) {
1252
+ return STORJ_MEMORY_ERROR;
1253
+ }
1254
+
1255
+ char *path = str_concat_many(2, "/buckets/", id);
1256
+ if (!path) {
1257
+ return STORJ_MEMORY_ERROR;
1258
+ }
1259
+
1260
+ work->data = get_bucket_request_new(env->http_options,
1261
+ env->bridge_options,
1262
+ env->encrypt_options,
1263
+ "GET", path,
1264
+ NULL, true, handle);
1265
+ if (!work->data) {
1266
+ return STORJ_MEMORY_ERROR;
1267
+ }
1268
+
1269
+ return uv_queue_work(env->loop, (uv_work_t*) work, get_bucket_request_worker, cb);
1270
+ }
1271
+
1272
+ STORJ_API void storj_free_get_bucket_request(get_bucket_request_t *req)
1273
+ {
1274
+ json_object_put(req->response);
1275
+ free(req->path);
1276
+ if (req->bucket) {
1277
+ free((char *)req->bucket->name);
1278
+ }
1279
+ free(req->bucket);
1280
+ free(req);
1281
+ }
1282
+
1283
+ STORJ_API int storj_bridge_list_files(storj_env_t *env,
1284
+ const char *id,
1285
+ void *handle,
1286
+ uv_after_work_cb cb)
1287
+ {
1288
+ char *path = str_concat_many(3, "/buckets/", id, "/files");
1289
+ if (!path) {
1290
+ return STORJ_MEMORY_ERROR;
1291
+ }
1292
+
1293
+ uv_work_t *work = uv_work_new();
1294
+ if (!work) {
1295
+ return STORJ_MEMORY_ERROR;
1296
+ }
1297
+ work->data = list_files_request_new(env->http_options,
1298
+ env->bridge_options,
1299
+ env->encrypt_options,
1300
+ id, "GET", path,
1301
+ NULL, true, handle);
1302
+
1303
+ if (!work->data) {
1304
+ return STORJ_MEMORY_ERROR;
1305
+ }
1306
+
1307
+ return uv_queue_work(env->loop, (uv_work_t*) work,
1308
+ list_files_request_worker, cb);
1309
+ }
1310
+
1311
+ STORJ_API void storj_free_list_files_request(list_files_request_t *req)
1312
+ {
1313
+ json_object_put(req->response);
1314
+ free(req->path);
1315
+ if (req->files && req->total_files > 0) {
1316
+ for (int i = 0; i < req->total_files; i++) {
1317
+ free((char *)req->files[i].filename);
1318
+ }
1319
+ }
1320
+ free(req->files);
1321
+ free(req);
1322
+ }
1323
+
1324
+ STORJ_API int storj_bridge_create_bucket_token(storj_env_t *env,
1325
+ const char *bucket_id,
1326
+ storj_bucket_op_t operation,
1327
+ void *handle,
1328
+ uv_after_work_cb cb)
1329
+ {
1330
+ struct json_object *body = json_object_new_object();
1331
+ json_object *op_string = json_object_new_string(BUCKET_OP[operation]);
1332
+
1333
+ json_object_object_add(body, "operation", op_string);
1334
+
1335
+ char *path = str_concat_many(3, "/buckets/", bucket_id, "/tokens");
1336
+ if (!path) {
1337
+ return STORJ_MEMORY_ERROR;
1338
+ }
1339
+
1340
+ uv_work_t *work = json_request_work_new(env, "POST", path, body,
1341
+ true, handle);
1342
+ if (!work) {
1343
+ return STORJ_MEMORY_ERROR;
1344
+ }
1345
+
1346
+ return uv_queue_work(env->loop, (uv_work_t*) work, json_request_worker, cb);
1347
+ }
1348
+
1349
+ STORJ_API int storj_bridge_get_file_pointers(storj_env_t *env,
1350
+ const char *bucket_id,
1351
+ const char *file_id,
1352
+ void *handle,
1353
+ uv_after_work_cb cb)
1354
+ {
1355
+ char *path = str_concat_many(4, "/buckets/", bucket_id, "/files/", file_id);
1356
+ if (!path) {
1357
+ return STORJ_MEMORY_ERROR;
1358
+ }
1359
+
1360
+ uv_work_t *work = json_request_work_new(env, "GET", path, NULL,
1361
+ true, handle);
1362
+ if (!work) {
1363
+ return STORJ_MEMORY_ERROR;
1364
+ }
1365
+
1366
+ return uv_queue_work(env->loop, (uv_work_t*) work, json_request_worker, cb);
1367
+ }
1368
+
1369
+ STORJ_API int storj_bridge_delete_file(storj_env_t *env,
1370
+ const char *bucket_id,
1371
+ const char *file_id,
1372
+ void *handle,
1373
+ uv_after_work_cb cb)
1374
+ {
1375
+ char *path = str_concat_many(4, "/buckets/", bucket_id, "/files/", file_id);
1376
+ if (!path) {
1377
+ return STORJ_MEMORY_ERROR;
1378
+ }
1379
+
1380
+ uv_work_t *work = json_request_work_new(env, "DELETE", path, NULL,
1381
+ true, handle);
1382
+ if (!work) {
1383
+ return STORJ_MEMORY_ERROR;
1384
+ }
1385
+
1386
+ return uv_queue_work(env->loop, (uv_work_t*) work, json_request_worker, cb);
1387
+ }
1388
+
1389
+ STORJ_API int storj_bridge_create_frame(storj_env_t *env,
1390
+ void *handle,
1391
+ uv_after_work_cb cb)
1392
+ {
1393
+ uv_work_t *work = json_request_work_new(env, "POST", "/frames", NULL,
1394
+ true, handle);
1395
+ if (!work) {
1396
+ return STORJ_MEMORY_ERROR;
1397
+ }
1398
+
1399
+ return uv_queue_work(env->loop, (uv_work_t*) work, json_request_worker, cb);
1400
+ }
1401
+
1402
+ STORJ_API int storj_bridge_get_frames(storj_env_t *env,
1403
+ void *handle,
1404
+ uv_after_work_cb cb)
1405
+ {
1406
+ uv_work_t *work = json_request_work_new(env, "GET", "/frames", NULL,
1407
+ true, handle);
1408
+ if (!work) {
1409
+ return STORJ_MEMORY_ERROR;
1410
+ }
1411
+
1412
+ return uv_queue_work(env->loop, (uv_work_t*) work, json_request_worker, cb);
1413
+ }
1414
+
1415
+ STORJ_API int storj_bridge_get_frame(storj_env_t *env,
1416
+ const char *frame_id,
1417
+ void *handle,
1418
+ uv_after_work_cb cb)
1419
+ {
1420
+ char *path = str_concat_many(2, "/frames/", frame_id);
1421
+ if (!path) {
1422
+ return STORJ_MEMORY_ERROR;
1423
+ }
1424
+
1425
+ uv_work_t *work = json_request_work_new(env, "GET", path, NULL,
1426
+ true, handle);
1427
+ if (!work) {
1428
+ return STORJ_MEMORY_ERROR;
1429
+ }
1430
+
1431
+ return uv_queue_work(env->loop, (uv_work_t*) work, json_request_worker, cb);
1432
+
1433
+ }
1434
+
1435
+ STORJ_API int storj_bridge_delete_frame(storj_env_t *env,
1436
+ const char *frame_id,
1437
+ void *handle,
1438
+ uv_after_work_cb cb)
1439
+ {
1440
+ char *path = str_concat_many(2, "/frames/", frame_id);
1441
+ if (!path) {
1442
+ return STORJ_MEMORY_ERROR;
1443
+ }
1444
+
1445
+ uv_work_t *work = json_request_work_new(env, "DELETE", path, NULL,
1446
+ true, handle);
1447
+ if (!work) {
1448
+ return STORJ_MEMORY_ERROR;
1449
+ }
1450
+
1451
+ return uv_queue_work(env->loop, (uv_work_t*) work, json_request_worker, cb);
1452
+ }
1453
+
1454
+ STORJ_API int storj_bridge_get_file_info(storj_env_t *env,
1455
+ const char *bucket_id,
1456
+ const char *file_id,
1457
+ void *handle,
1458
+ uv_after_work_cb cb)
1459
+ {
1460
+ char *path = str_concat_many(5, "/buckets/", bucket_id, "/files/",
1461
+ file_id, "/info");
1462
+ if (!path) {
1463
+ return STORJ_MEMORY_ERROR;
1464
+ }
1465
+
1466
+ uv_work_t *work = json_request_work_new(env, "GET", path, NULL,
1467
+ true, handle);
1468
+ if (!work) {
1469
+ return STORJ_MEMORY_ERROR;
1470
+ }
1471
+
1472
+ return uv_queue_work(env->loop, (uv_work_t*) work, json_request_worker, cb);
1473
+ }
1474
+
1475
+ STORJ_API int storj_bridge_list_mirrors(storj_env_t *env,
1476
+ const char *bucket_id,
1477
+ const char *file_id,
1478
+ void *handle,
1479
+ uv_after_work_cb cb)
1480
+ {
1481
+ char *path = str_concat_many(5, "/buckets/", bucket_id, "/files/",
1482
+ file_id, "/mirrors");
1483
+ if (!path) {
1484
+ return STORJ_MEMORY_ERROR;
1485
+ }
1486
+
1487
+ uv_work_t *work = json_request_work_new(env, "GET", path, NULL,
1488
+ true, handle);
1489
+ if (!work) {
1490
+ return STORJ_MEMORY_ERROR;
1491
+ }
1492
+
1493
+ return uv_queue_work(env->loop, (uv_work_t*) work, json_request_worker, cb);
1494
+ }
1495
+
1496
+ STORJ_API int storj_bridge_register(storj_env_t *env,
1497
+ const char *email,
1498
+ const char *password,
1499
+ void *handle,
1500
+ uv_after_work_cb cb)
1501
+ {
1502
+ uint8_t sha256_digest[SHA256_DIGEST_SIZE];
1503
+ sha256_of_str((uint8_t *)password, strlen(password), sha256_digest);
1504
+
1505
+ char *hex_str = hex2str(SHA256_DIGEST_SIZE, sha256_digest);
1506
+ if (!hex_str) {
1507
+ return STORJ_MEMORY_ERROR;
1508
+ }
1509
+
1510
+ struct json_object *body = json_object_new_object();
1511
+ json_object *email_str = json_object_new_string(email);
1512
+ json_object *pass_str = json_object_new_string(hex_str);
1513
+ free(hex_str);
1514
+ json_object_object_add(body, "email", email_str);
1515
+ json_object_object_add(body, "password", pass_str);
1516
+
1517
+ uv_work_t *work = json_request_work_new(env, "POST", "/users", body, true,
1518
+ handle);
1519
+ if (!work) {
1520
+ return STORJ_MEMORY_ERROR;
1521
+ }
1522
+ return uv_queue_work(env->loop, (uv_work_t*) work, json_request_worker, cb);
1523
+ }