1 /*
2 * This software is Copyright (c) 2016-2017 Denis Burykin
3 * [denis_burykin yahoo com], [denis-burykin2014 yandex ru]
4 * and it is hereby released to the general public under the following terms:
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted.
7 *
8 */
9 #include <stdio.h>
10 #include <stdlib.h>
11 #include <string.h>
12
13 #include "../memory.h"
14
15 #include "task.h"
16 #include "jtr_device.h"
17 #include "jtr_mask.h"
18
19 #include "pkt_comm/pkt_comm.h"
20 #include "pkt_comm/word_list.h"
21 #include "pkt_comm/word_gen.h"
22 #include "pkt_comm/cmp_config.h"
23
24
25
task_result_list_init(struct task_result_list * list)26 static void task_result_list_init(struct task_result_list *list)
27 {
28 list->count = 0;
29 list->result_list = NULL;
30 list->index = NULL;
31 }
32
33
task_result_list_add(struct task_result_list * list,struct task_result * task_result)34 static void task_result_list_add(struct task_result_list *list,
35 struct task_result *task_result)
36 {
37 task_result->next = list->result_list;
38 list->result_list = task_result;
39 list->count++;
40 //MEM_FREE(list->index);
41 }
42
43
task_result_list_create_index(struct task_result_list * list)44 static void task_result_list_create_index(struct task_result_list *list)
45 {
46 MEM_FREE(list->index);
47 if (!list->count)
48 return;
49
50 list->index = mem_alloc(list->count * sizeof(struct task_result *));
51
52 struct task_result *result;
53 int i = 0;
54 for (result = list->result_list; result; result = result->next)
55 list->index[i++] = result;
56 }
57
58
task_result_new(struct task * task,char * key,unsigned char * range_info,unsigned int gen_id,struct db_password * pw)59 struct task_result *task_result_new(struct task *task,
60 char *key, unsigned char *range_info,
61 unsigned int gen_id, struct db_password *pw)
62 {
63 struct task_result *result = mem_alloc(sizeof(struct task_result));
64
65 int plaintext_len = jtr_fmt_params->plaintext_length;
66 result->key = mem_alloc(plaintext_len + 1);
67 result->key[plaintext_len] = 0;
68 memcpy(result->key, key, plaintext_len);
69
70 if (range_info)
71 mask_reconstruct_plaintext(result->key, range_info, gen_id);
72
73 result->pw = pw;
74 result->binary = NULL;
75
76 task_result_list_add(&task->result_list, result);
77 return result;
78 }
79
80
task_result_count(struct task * task)81 static int task_result_count(struct task *task)
82 {
83 return task->result_list.count;
84 }
85
86
task_result_list_clear(struct task_result_list * list)87 static void task_result_list_clear(struct task_result_list *list)
88 {
89 if (!list) {
90 fprintf(stderr,"task_result_list_clear: NULL\n");
91 return;
92 }
93 if (!list->result_list) {
94 if (list->count)
95 fprintf(stderr,"task_result_list_clear: result_list=NULL,"
96 " count=%d\n", list->count);
97 return;
98 }
99
100 struct task_result *result = list->result_list;
101 while (1) {
102 struct task_result *next = result->next;
103 MEM_FREE(result->key);
104 MEM_FREE(result->binary);
105 MEM_FREE(result);
106 if (!next)
107 break;
108 result = next;
109 }
110 list->count = 0;
111 MEM_FREE(list->index);
112 list->result_list = NULL;
113 }
114
115
task_new(struct task_list * task_list,int num_keys,char * keys,unsigned char * range_info)116 struct task *task_new(struct task_list *task_list,
117 int num_keys, char *keys,
118 unsigned char *range_info)
119 {
120 struct task *task = mem_alloc(sizeof(struct task));
121
122 task->next = task_list->task;
123 task_list->task = task;
124
125 task->status = TASK_NONE;
126 task->num_keys = num_keys;
127 task->keys = keys;
128 task->range_info = range_info;
129 task_result_list_init(&task->result_list);
130 task->jtr_device = NULL;
131 task->id = 0;
132
133 static struct timeval zero_time = { 0, 0 };
134 task->mtime = zero_time;
135
136 task->num_processed = 0;
137 return task;
138 }
139
140
task_assign(struct task * task,struct jtr_device * jtr_device)141 void task_assign(struct task *task, struct jtr_device *jtr_device)
142 {
143 task->jtr_device = jtr_device;
144 task->id = jtr_device->task_id_next++; // TODO: move 3 lines to jtr_device.c
145 if (jtr_device->task_id_next == 65536)
146 jtr_device->task_id_next = 1;
147 task->status = TASK_ASSIGNED;
148 task_update_mtime(task);
149 task_create_output_pkt_comm(task);
150 }
151
152
task_delete(struct task * task)153 void task_delete(struct task *task)
154 {
155 task_result_list_clear(&task->result_list);
156 MEM_FREE(task);
157 }
158
159
task_list_create(int num_keys,char * keys,unsigned char * range_info)160 struct task_list *task_list_create(int num_keys,
161 char *keys, unsigned char *range_info)
162 {
163 // distribute keys equally among devices
164 int num_devices = jtr_device_list_count();
165 if (!num_devices)
166 return NULL;
167
168 struct task_list *task_list = mem_alloc(sizeof(struct task_list));
169 task_list->task = NULL;
170
171 if (!num_keys) {
172 fprintf(stderr, "task_list_create: num_keys=0\n");
173 error();
174 }
175
176 int keys_per_device = num_keys / num_devices;
177 int num_extra_keys = num_keys % num_devices;
178
179 int keys_buffer_offset = 0;
180 int range_info_offset = 0;
181 struct jtr_device *dev;
182 for (dev = jtr_device_list->device; dev; dev = dev->next) {
183
184 int device_num_keys = keys_per_device;
185 if (num_extra_keys) {
186 device_num_keys++;
187 num_extra_keys--;
188 }
189
190 // No more keys for this device and remaining ones
191 if (!device_num_keys)
192 break;
193
194 // Number of keys in word_list/template_list is 16 bit value.
195 // There's also a limit on packet's data length.
196 // Create several tasks if necessary.
197 while (device_num_keys) {
198 // TODO: maybe create tasks of equal size
199 int task_num_keys = device_num_keys;
200 if (task_num_keys * jtr_fmt_params->plaintext_length
201 > PKT_MAX_DATA_LEN)
202 task_num_keys = PKT_MAX_DATA_LEN
203 / jtr_fmt_params->plaintext_length;
204 if (task_num_keys > 65535)
205 task_num_keys = 65535;
206 device_num_keys -= task_num_keys;
207
208 struct task *task = task_new(task_list, task_num_keys,
209 keys + keys_buffer_offset,
210 range_info ? range_info + range_info_offset : NULL);
211 task_assign(task, dev);
212
213 keys_buffer_offset += task_num_keys * jtr_fmt_params->plaintext_length;
214 if (range_info)
215 range_info_offset += task_num_keys * MASK_FMT_INT_PLHDR;
216 }
217 }
218
219 return task_list;
220 }
221
222
tasks_assign(struct task_list * task_list,struct jtr_device_list * jtr_device_list)223 void tasks_assign(struct task_list *task_list,
224 struct jtr_device_list *jtr_device_list)
225 {
226 int num_tasks = task_list_count_by_status(task_list, TASK_UNASSIGNED);
227 if (!num_tasks)
228 return;
229
230 int jtr_device_count = jtr_device_list_count();
231 if (!jtr_device_count)
232 return;
233
234 int min_tasks_per_device = num_tasks / jtr_device_count;
235 int extra_tasks = num_tasks % jtr_device_count;
236
237 struct jtr_device *dev;
238 for (dev = jtr_device_list->device; dev; dev = dev->next) {
239 int i;
240 for (i = 0; i < min_tasks_per_device; i++) {
241 struct task *task = task_find_by_status(task_list, TASK_UNASSIGNED);
242 if (!task) {
243 fprintf(stderr, "Error: task not found 1!\n");
244 break;
245 }
246 task_assign(task, dev);
247 }
248 if (extra_tasks) {
249 struct task *task = task_find_by_status(task_list, TASK_UNASSIGNED);
250 if (!task) {
251 fprintf(stderr, "Error: task not found 2!\n");
252 break;
253 }
254 task_assign(task, dev);
255 extra_tasks--;
256 }
257 }
258
259 }
260
261
task_deassign(struct task * task)262 void task_deassign(struct task *task)
263 {
264 task_result_list_clear(&task->result_list);
265 task->num_processed = 0;
266 task->status = TASK_UNASSIGNED;
267 task_update_mtime(task);
268 task->jtr_device = NULL;
269 }
270
271
tasks_deassign(struct task_list * task_list,struct jtr_device * jtr_device)272 int tasks_deassign(struct task_list *task_list, struct jtr_device *jtr_device)
273 {
274 int count = 0;
275 struct task *task;
276 for (task = task_list->task; task; task = task->next) {
277 if (task->status == TASK_ASSIGNED && task->jtr_device == jtr_device) {
278 task_deassign(task);
279 count++;
280 }
281 }
282 return count;
283 }
284
285
task_find(struct task_list * task_list,struct jtr_device * jtr_device,int id)286 struct task *task_find(struct task_list *task_list,
287 struct jtr_device *jtr_device, int id)
288 {
289 struct task *task;
290 for (task = task_list->task; task; task = task->next) {
291 if (task->id == id && task->jtr_device == jtr_device)
292 return task;
293 }
294 return NULL;
295 }
296
297
task_find_by_status(struct task_list * task_list,enum task_status status)298 struct task *task_find_by_status(struct task_list *task_list,
299 enum task_status status)
300 {
301 struct task *task;
302 for (task = task_list->task; task; task = task->next) {
303 if (task->status == status)
304 return task;
305 }
306 return NULL;
307 }
308
309
task_find_by_mtime(struct task_list * task_list,int tv_sec)310 struct task *task_find_by_mtime(struct task_list *task_list, int tv_sec)
311 {
312 struct task *task;
313 for (task = task_list->task; task; task = task->next) {
314 if (task->status == TASK_ASSIGNED && task->mtime.tv_sec < tv_sec)
315 return task;
316 }
317 return NULL;
318 }
319
320
task_create_output_pkt_comm(struct task * task)321 void task_create_output_pkt_comm(struct task *task)
322 {
323 struct jtr_device *dev = task->jtr_device;
324 if (!dev || task->status != TASK_ASSIGNED) {
325 fprintf(stderr, "task_list_create_output_pkt_comm: unassigned task\n");
326 error();
327 }
328 if (!task->num_keys || !task->keys) {
329 fprintf(stderr, "task_list_create_output_pkt_comm: task contains nothing\n");
330 error();
331 }
332 //fprintf(stderr,"task_create_output_pkt_comm\n");
333
334 // TODO: check if input queues are not full
335
336 // If on-device comparator is unconfigured or its configuration changes
337 //
338 // Issue. While sequential_id doesn't change, the content can change
339 // (hash removed). For now, re-create and resend cmp_config every time.
340 //
341 //if (dev->cmp_config_id == -1 || dev->cmp_config_id != cmp_config.id) {
342 if (1) {
343 struct pkt *pkt_cmp_config = pkt_cmp_config_new(&cmp_config);
344 if (!pkt_cmp_config) {
345 // some wrong input / internal error
346 fprintf(stderr, "task_list_create_output_pkt_comm: pkt_cmp_config_new\n");
347 exit(-1);
348 }
349 pkt_queue_push(dev->comm->output_queue, pkt_cmp_config);
350 dev->cmp_config_id = cmp_config.id;
351 //fprintf(stderr, "dev: %s cmp_config_id: %d num_hashes:%d\n",
352 // dev->device->ztex_device->snString, dev->cmp_config_id,
353 // cmp_config.num_hashes );
354 }
355
356 // Create and enqueue word generator configuration
357 //
358 struct pkt *pkt_word_gen = pkt_word_gen_new(mask_convert_to_word_gen());
359 pkt_word_gen->id = task->id;
360 pkt_queue_push(dev->comm->output_queue, pkt_word_gen);
361
362
363 // Create and enqueue template_list or word_list
364 //
365 struct pkt *pkt_list;
366 if (task->range_info)
367 pkt_list = pkt_template_list_new(task->keys, task->num_keys,
368 jtr_fmt_params->plaintext_length,
369 task->range_info, MASK_FMT_INT_PLHDR);
370 else
371 pkt_list = pkt_word_list_new(task->keys, task->num_keys,
372 jtr_fmt_params->plaintext_length);
373
374 pkt_queue_push(dev->comm->output_queue, pkt_list);
375 }
376
377
task_list_count_by_status(struct task_list * task_list,enum task_status status)378 int task_list_count_by_status(struct task_list *task_list,
379 enum task_status status)
380 {
381 int count = 0;
382 struct task *task;
383 for (task = task_list->task; task; task = task->next)
384 if (task->status == status)
385 count++;
386 return count;
387 }
388
389
task_list_all_completed(struct task_list * task_list)390 int task_list_all_completed(struct task_list *task_list)
391 {
392 struct task *task;
393 for (task = task_list->task; task; task = task->next) {
394 if (task->status != TASK_COMPLETE)
395 return 0;
396 }
397 return 1;
398 }
399
400
task_list_result_count(struct task_list * task_list)401 int task_list_result_count(struct task_list *task_list)
402 {
403 int count = 0;
404 struct task *task;
405 for (task = task_list->task; task; task = task->next) {
406 count += task_result_count(task);
407 }
408 return count;
409 }
410
411
task_result_execute(struct task_list * task_list,void (* func)(struct task_result * result))412 void task_result_execute(struct task_list *task_list,
413 void (*func)(struct task_result *result))
414 {
415 struct task *task;
416 for (task = task_list->task; task; task = task->next) {
417 struct task_result *result;
418 for (result = task->result_list.result_list; result;
419 result = result->next)
420 func(result);
421 }
422 }
423
424
task_list_create_index(struct task_list * task_list)425 void task_list_create_index(struct task_list *task_list)
426 {
427 struct task *task;
428 for (task = task_list->task; task; task = task->next)
429 task_result_list_create_index(&task->result_list);
430 }
431
432
task_result_by_index(struct task_list * task_list,int index)433 struct task_result *task_result_by_index(struct task_list *task_list, int index)
434 {
435 int count = 0;
436 struct task *task;
437 for (task = task_list->task; task; task = task->next) {
438 int cur_task_count = task_result_count(task);
439 if (!cur_task_count)
440 continue;
441 if (count + cur_task_count <= index) {
442 count += cur_task_count;
443 continue;
444 }
445 /*
446 struct task_result *result;
447 for (result = task->result_list.result_list; result;
448 result = result->next) {
449 if (count == index)
450 return result;
451 count++;
452 }
453 */
454
455 if (!task->result_list.index) {
456 fprintf(stderr,"task_result_by_index: index not created\n");
457 return NULL;
458 }
459 //fprintf(stderr,"task_result_by_index: i:%d c:%d\n",index, count);
460 return task->result_list.index[index - count];
461 }
462 return NULL;
463 }
464
465
task_list_delete(struct task_list * task_list)466 void task_list_delete(struct task_list *task_list)
467 {
468 if (!task_list)
469 return;
470 struct task *task = task_list->task;
471 if (!task)
472 return;
473
474 while (1) {
475 struct task *next = task->next;
476 task_delete(task);
477 if (!next)
478 break;
479 task = next;
480 }
481 MEM_FREE(task_list);
482 }
483
484
485
486