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