gateway.c 15.9 KB
Newer Older
1
2
3
4
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <sys/socket.h>
5
#include <sys/stat.h>
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
#include <arpa/inet.h> //inet_addr
#include <unistd.h>
#include <stdint.h>
#include <pthread.h>
#include <sys/time.h>
#include <libpq-fe.h>
#include <math.h>
#include <signal.h>
#include <time.h>

#include <errno.h>

#include "gateway_protocol.h"
#include "base64.h"
#include "task_queue.h"
21
#include "json.h"
22
#include "aes.h"
23

24
#define NTHREAD_MAX			10
Vladislav Rykov's avatar
Vladislav Rykov committed
25

Vladislav Rykov's avatar
Vladislav Rykov committed
26
27
28
#define TIMEDATE_LENGTH			32
#define PEND_SEND_RETRIES_MAX		5
#define GATEWAY_PROTOCOL_APP_KEY_SIZE	8
Vladislav Rykov's avatar
Vladislav Rykov committed
29
#define DEVICE_DATA_MAX_LENGTH		256
30
31
#define GATEWAY_SECURE_KEY_SIZE		16

Vladislav Rykov's avatar
Vladislav Rykov committed
32

33
34
typedef struct {
	char 		gw_id[17 +1];
35
	uint8_t 	gw_secure_key[GATEWAY_SECURE_KEY_SIZE];
36
37
	uint16_t 	gw_port;
	char 		db_type[20];
38
	uint32_t	telemetry_send_period;
39
40
} gw_conf_t;

41
42
43
44
45
46
47
48
typedef struct {
	char 		addr[15+1];
	uint16_t 	port;
	char 		db_name[32];
	char 		user_name[32];
	char 		user_pass[32];
} db_conf_t;

Vladislav Rykov's avatar
Vladislav Rykov committed
49
50
typedef struct {
	uint32_t utc;
Vladislav Rykov's avatar
Vladislav Rykov committed
51
	char timedate[TIMEDATE_LENGTH];
Vladislav Rykov's avatar
Vladislav Rykov committed
52

Vladislav Rykov's avatar
Vladislav Rykov committed
53
54
	uint8_t data[DEVICE_DATA_MAX_LENGTH];
	uint8_t data_length;
Vladislav Rykov's avatar
Vladislav Rykov committed
55
56
} sensor_data_t;

Vladislav Rykov's avatar
Vladislav Rykov committed
57
typedef struct {
Vladislav Rykov's avatar
Vladislav Rykov committed
58
	gateway_protocol_conf_t gwp_conf;
Vladislav Rykov's avatar
Vladislav Rykov committed
59
60
61
62
63
64
65
	int server_desc;
	int client_desc;
	struct sockaddr_in server;
	struct sockaddr_in client;
	int sock_len;
} gcom_ch_t; // gateway communication channel

66
67
68
69
70
71
72
typedef struct {
	gcom_ch_t gch;	
	gateway_protocol_packet_type_t packet_type;
	uint8_t packet[DEVICE_DATA_MAX_LENGTH];
	uint8_t packet_length;
} gcom_ch_request_t;

73
74
static const char * gw_conf_file = "gateway.conf";
static const char * db_conf_file = "db.conf";
75
static void process_gw_conf(json_value* value, gw_conf_t *gw_conf);
76
77
78
79
static void process_db_conf(json_value* value, db_conf_t *db_conf);
static json_value * read_json_conf(const char *file_path);
static int read_gw_conf(const char *gw_conf_file_path, gw_conf_t *gw_conf);
static int read_db_conf(const char *db_conf_file_path, db_conf_t *db_conf);
80

81
void process_packet(void *request);
Vladislav Rykov's avatar
Vladislav Rykov committed
82

Vladislav Rykov's avatar
Vladislav Rykov committed
83
84
85
int send_gcom_ch(gcom_ch_t *gch, uint8_t *pck, uint8_t pck_size);
int recv_gcom_ch(gcom_ch_t *gch, uint8_t *pck, uint8_t *pck_length, uint16_t pck_size);

Vladislav Rykov's avatar
Vladislav Rykov committed
86
void packet_encode(
Vladislav Rykov's avatar
Vladislav Rykov committed
87
88
89
90
91
	const uint8_t *app_key,
	const uint8_t dev_id, 
	const gateway_protocol_packet_type_t p_type, 
	const uint8_t payload_length,
	const uint8_t *payload,
Vladislav Rykov's avatar
Vladislav Rykov committed
92
93
94
	uint8_t *packet_length,
	uint8_t *packet);
uint8_t packet_decode(
Vladislav Rykov's avatar
Vladislav Rykov committed
95
	uint8_t *app_key,
Vladislav Rykov's avatar
Vladislav Rykov committed
96
97
98
99
	uint8_t *dev_id,
	gateway_protocol_packet_type_t *ptype,
	uint8_t *payload_length,
	uint8_t *payload,
Vladislav Rykov's avatar
Vladislav Rykov committed
100
101
	const uint8_t packet_length,
	const uint8_t *packet);
Vladislav Rykov's avatar
Vladislav Rykov committed
102
103
104
105
void gateway_protocol_data_send_payload_decode(
	sensor_data_t *sensor_data, 
	const uint8_t *payload, 
	const uint8_t payload_length);
Vladislav Rykov's avatar
Vladislav Rykov committed
106

Vladislav Rykov's avatar
Vladislav Rykov committed
107
108
109
110
111
112
113
114
void gateway_protocol_mk_stat(
	gcom_ch_t *gch,
	gateway_protocol_stat_t stat,
	uint8_t *pck,
	uint8_t *pck_len);

void send_utc(gcom_ch_t *pch);

Vladislav Rykov's avatar
Vladislav Rykov committed
115
116
void gateway_protocol_checkup_callback(gateway_protocol_conf_t *gwp_conf);

Vladislav Rykov's avatar
Vladislav Rykov committed
117
118
void ctrc_handler (int sig);
static volatile uint8_t working = 1;
Vladislav Rykov's avatar
Vladislav Rykov committed
119

120
121
122
pthread_mutex_t mutex;
PGconn *conn;

Vladislav Rykov's avatar
Vladislav Rykov committed
123
int main (int argc, char **argv) {
124
	gw_conf_t *gw_conf = (gw_conf_t *)malloc(sizeof(gw_conf_t));
125
	db_conf_t *db_conf = (db_conf_t *)malloc(sizeof(db_conf_t));
126
	char *db_conninfo = (char *)malloc(512);
127
	gcom_ch_t gch;
128
129
	task_queue_t *tq;

Vladislav Rykov's avatar
Vladislav Rykov committed
130
	signal(SIGINT, ctrc_handler);
131
	
132
133
134
135
136
137
138
139
140
	if(read_gw_conf(gw_conf_file, gw_conf)) {
		return EXIT_FAILURE;
	}

	//gw auth, then
	if(read_db_conf(db_conf_file, db_conf)) {
		return EXIT_FAILURE;
	}
	
141
142
	snprintf(db_conninfo, 512, 
			"hostaddr=%s port=%d dbname=%s user=%s password=%s", 
143
144
145
146
147
148
149
150
			db_conf->addr,
			db_conf->port,
			db_conf->db_name,
			db_conf->user_name,
			db_conf->user_pass);
	
	printf("db_conf : '%s'\n", db_conninfo);

151
	conn = PQconnectdb(db_conninfo);
152
153
154
155
156
157
158
159
160
161
	
	snprintf(db_conninfo, 512, 
			"id=%s secure_key=%s port=%d type=%s telemetry_send_period=%d\n", 
			gw_conf->gw_id,
			gw_conf->gw_secure_key,
			gw_conf->gw_port,
			gw_conf->db_type,
			gw_conf->telemetry_send_period);
	printf("gw_conf : '%s'\n", db_conninfo);
	
162
	free(db_conninfo);
Vladislav Rykov's avatar
Vladislav Rykov committed
163
	if (PQstatus(conn) == CONNECTION_BAD) {
Vladislav Rykov's avatar
Vladislav Rykov committed
164
		fprintf(stderr,"connection to db error: %s\n", PQerrorMessage(conn));
165
		free(gw_conf);
Vladislav Rykov's avatar
Vladislav Rykov committed
166
167
168
		return EXIT_FAILURE;
	}

Vladislav Rykov's avatar
Vladislav Rykov committed
169
	if ((gch.server_desc = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) < 0) {
Vladislav Rykov's avatar
Vladislav Rykov committed
170
		perror("socket creation error");
171
		free(gw_conf);
Vladislav Rykov's avatar
Vladislav Rykov committed
172
173
174
		return EXIT_FAILURE;
	}

Vladislav Rykov's avatar
Vladislav Rykov committed
175
	gch.server.sin_family 		= AF_INET;
176
	gch.server.sin_port		= htons(gw_conf->gw_port);
Vladislav Rykov's avatar
Vladislav Rykov committed
177
	gch.server.sin_addr.s_addr 	= INADDR_ANY;
Vladislav Rykov's avatar
Vladislav Rykov committed
178

Vladislav Rykov's avatar
Vladislav Rykov committed
179
	if (bind(gch.server_desc, (struct sockaddr *) &gch.server, sizeof(gch.server)) < 0) {
Vladislav Rykov's avatar
Vladislav Rykov committed
180
		perror("binding error");
181
		free(gw_conf);
Vladislav Rykov's avatar
Vladislav Rykov committed
182
183
184
		return EXIT_FAILURE;
	}

185
186
	if(!(tq = task_queue_create(NTHREAD_MAX))) {
		perror("task_queue creation error");
187
		free(gw_conf);
188
189
		return EXIT_FAILURE;
	}
190
191

	pthread_mutex_init(&mutex, NULL);
Vladislav Rykov's avatar
Vladislav Rykov committed
192
193

	gateway_protocol_set_checkup_callback(gateway_protocol_checkup_callback);
Vladislav Rykov's avatar
Vladislav Rykov committed
194
195
	
	while (working) {
196
197
198
		gcom_ch_request_t *req = (gcom_ch_request_t *)malloc(sizeof(gcom_ch_request_t));
		memset(req, 0x0, sizeof(gcom_ch_request_t));
		memcpy(&req->gch, &gch, sizeof(gcom_ch_t));
199
	
Vladislav Rykov's avatar
Vladislav Rykov committed
200
		printf("listenninig...\n");
201
		req->gch.sock_len = sizeof(req->gch.client);
Vladislav Rykov's avatar
Vladislav Rykov committed
202
		
203
204
		if (recv_gcom_ch(&req->gch, req->packet, &req->packet_length, DEVICE_DATA_MAX_LENGTH)) {
			task_queue_enqueue(tq, process_packet, req);
Vladislav Rykov's avatar
Vladislav Rykov committed
205
		} else {
206
			fprintf(stderr, "packet receive error\n");
Vladislav Rykov's avatar
Vladislav Rykov committed
207
		}
Vladislav Rykov's avatar
Vladislav Rykov committed
208
209
	}

210
	free(gw_conf);
211
	free(db_conf);
212
	pthread_mutex_destroy(&mutex);
Vladislav Rykov's avatar
Vladislav Rykov committed
213
	close(gch.server_desc);
Vladislav Rykov's avatar
Vladislav Rykov committed
214
	PQfinish(conn);
Vladislav Rykov's avatar
Vladislav Rykov committed
215

Vladislav Rykov's avatar
Vladislav Rykov committed
216
217
218
	return EXIT_SUCCESS;
}

Vladislav Rykov's avatar
Vladislav Rykov committed
219
220
221
222
void ctrc_handler (int sig) {
	working = 0;
}

223
224
225
226
227
228
void process_packet(void *request) {
	gcom_ch_request_t *req = (gcom_ch_request_t *)request;
	uint8_t payload[DEVICE_DATA_MAX_LENGTH];
	uint8_t payload_length;	
	PGresult *res;

Vladislav Rykov's avatar
Vladislav Rykov committed
229
230
	if (gateway_protocol_packet_decode(
		&(req->gch.gwp_conf),
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
		&(req->packet_type),
		&payload_length, payload,
		req->packet_length, req->packet))
	{
		if (req->packet_type == GATEWAY_PROTOCOL_PACKET_TYPE_TIME_REQ) {
			printf("TIME REQ received\n");
			send_utc(&(req->gch));
		} else if (req->packet_type == GATEWAY_PROTOCOL_PACKET_TYPE_DATA_SEND) {
			sensor_data_t sensor_data;
			time_t t;
			// DEVICE_DATA_MAX_LENGTH*2 {hex} + 150
			char db_query[662];

			printf("DATA SEND received\n");
			gateway_protocol_data_send_payload_decode(&sensor_data, payload, payload_length);
			
			if (sensor_data.utc == 0) {
				struct timeval tv;
				gettimeofday(&tv, NULL);
				t = tv.tv_sec;
			} else {
				t = sensor_data.utc;
			}
			
			strftime(sensor_data.timedate, TIMEDATE_LENGTH, "%d/%m/%Y %H:%M:%S", localtime(&t));
			snprintf(db_query, sizeof(db_query), 
257
				"INSERT INTO dev_%s_%d VALUES (%lu, '%s', $1)", 
Vladislav Rykov's avatar
Vladislav Rykov committed
258
				(char *)req->gch.gwp_conf.app_key, req->gch.gwp_conf.dev_id, t, sensor_data.timedate
259
260
261
262
263
			);
			
			const char *params[1];
			int paramslen[1];
			int paramsfor[1];
264
			params[0] = (char *) sensor_data.data;
265
266
267
			paramslen[0] = sensor_data.data_length;
			paramsfor[0] = 1; // format - binary

268
			pthread_mutex_lock(&mutex);
269
			res = PQexecParams(conn, db_query, 1, NULL, params, paramslen, paramsfor, 0);
270
271
			pthread_mutex_unlock(&mutex);

272
273
274
275
276
			if (PQresultStatus(res) == PGRES_COMMAND_OK) {
				PQclear(res);

				snprintf(db_query, sizeof(db_query),
					 "SELECT * FROM pend_msgs WHERE app_key='%s' and dev_id = %d and ack = False", 
Vladislav Rykov's avatar
Vladislav Rykov committed
277
					(char *)req->gch.gwp_conf.app_key, req->gch.gwp_conf.dev_id
278
				);
279
280
				
				pthread_mutex_lock(&mutex);
281
				res = PQexec(conn, db_query);
282
283
				pthread_mutex_unlock(&mutex);
				
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
				if (PQresultStatus(res) == PGRES_TUPLES_OK && PQntuples(res)) {
					gateway_protocol_mk_stat(
						&(req->gch), 
						GATEWAY_PROTOCOL_STAT_ACK_PEND,
						req->packet, &(req->packet_length));
					printf("ACK_PEND prepared\n");
				} else {
					gateway_protocol_mk_stat(
						&(req->gch), 
						GATEWAY_PROTOCOL_STAT_ACK,
						req->packet, &(req->packet_length));
					printf("ACK prepared\n");
				}
				
				send_gcom_ch(&(req->gch), req->packet, req->packet_length);
			} else {
				fprintf(stderr, "database error : %s\n", PQerrorMessage(conn));
			}
			PQclear(res);
		} else if (req->packet_type == GATEWAY_PROTOCOL_PACKET_TYPE_PEND_REQ) {
			char db_query[200];
			snprintf(db_query, sizeof(db_query),
				 "SELECT * FROM pend_msgs WHERE app_key = '%s' AND dev_id = %d AND ack = False", 
Vladislav Rykov's avatar
Vladislav Rykov committed
307
				(char *)req->gch.gwp_conf.app_key, req->gch.gwp_conf.dev_id
308
			);
309
			pthread_mutex_lock(&mutex);
310
			res = PQexec(conn, db_query);
311
			pthread_mutex_unlock(&mutex);
312
313
314
315
316
317
318
319
320
321
322
323
324
325
			
			if (PQresultStatus(res) == PGRES_TUPLES_OK && PQntuples(res)) {
				char msg_cont[150];
				strncpy(msg_cont, PQgetvalue(res, 0, 2), sizeof(msg_cont));
				printf("PEND_SEND prepared : %s\n", msg_cont);
				PQclear(res);
			
				base64_decode(msg_cont, strlen(msg_cont)-1, payload);
				payload_length = BASE64_DECODE_OUT_SIZE(strlen(msg_cont));
				printf("prepared to send %d bytes : %s\n", payload_length, payload);
				
				// send the msg until ack is received
				uint8_t received_ack = 0;
				uint8_t pend_send_retries = PEND_SEND_RETRIES_MAX;
Vladislav Rykov's avatar
Vladislav Rykov committed
326
327
				gateway_protocol_packet_encode(
					&(req->gch.gwp_conf),
328
329
330
					GATEWAY_PROTOCOL_PACKET_TYPE_PEND_SEND,
					payload_length, payload,
					&(req->packet_length), req->packet);
331
332
				do {
					send_gcom_ch(&(req->gch), req->packet, req->packet_length);
333
334
335
336
337
338
339
340
341
342
343
					
					// 300 ms
					usleep(300000);

					pthread_mutex_lock(&mutex);
					res = PQexec(conn, db_query);
					pthread_mutex_unlock(&mutex);
					
					if (PQresultStatus(res) == PGRES_TUPLES_OK) {
						if (!PQntuples(res) || strcmp(PQgetvalue(res, 0, 2), msg_cont)) {
							received_ack = 1;
344
345
						}
					}
346
347
					PQclear(res);
					printf("received_ack = %d, retries = %d\n", received_ack, pend_send_retries);
348
349
350
351
352
353
354
355
356
				} while (!received_ack && pend_send_retries--);
			} else {
				gateway_protocol_mk_stat(
					&(req->gch),
					GATEWAY_PROTOCOL_STAT_NACK,
					req->packet, &(req->packet_length));
				
				send_gcom_ch(&(req->gch), req->packet, req->packet_length);
				
Vladislav Rykov's avatar
Vladislav Rykov committed
357
				printf("nothing for app %s dev %d\n", (char *)req->gch.gwp_conf.app_key, req->gch.gwp_conf.dev_id);
358
			}
359
360
361
362
363
364
		} else if (req->packet_type == GATEWAY_PROTOCOL_PACKET_TYPE_STAT) {
			// TODO change to ACK_PEND = 0x01
			if (payload[0] == 0x00) {
				char db_query[200];
				snprintf(db_query, sizeof(db_query),
					 "SELECT * FROM pend_msgs WHERE app_key = '%s' AND dev_id = %d AND ack = False", 
Vladislav Rykov's avatar
Vladislav Rykov committed
365
					(char *)req->gch.gwp_conf.app_key, req->gch.gwp_conf.dev_id
366
367
368
369
370
371
372
				);
				pthread_mutex_lock(&mutex);
				res = PQexec(conn, db_query);
				pthread_mutex_unlock(&mutex);
				if (PQresultStatus(res) == PGRES_TUPLES_OK && PQntuples(res)) {
					snprintf(db_query, sizeof(db_query),
						"UPDATE pend_msgs SET ack = True WHERE app_key = '%s' AND dev_id = %d AND msg = '%s'",
Vladislav Rykov's avatar
Vladislav Rykov committed
373
						(char *)req->gch.gwp_conf.app_key, req->gch.gwp_conf.dev_id, PQgetvalue(res, 0, 2)
374
375
376
377
378
379
380
381
382
383
384
385
386
					);
					PQclear(res);
					pthread_mutex_lock(&mutex);
					res = PQexec(conn, db_query);
					pthread_mutex_unlock(&mutex);
					if (PQresultStatus(res) == PGRES_COMMAND_OK) {
						printf("pend_msgs updated\n");
					} else {
						fprintf(stderr, "database error : %s\n", PQerrorMessage(conn));
					}
				}
				PQclear(res);
			}
387
388
389
390
391
392
393
394
		} else {
			gateway_protocol_mk_stat(
				&(req->gch),
				GATEWAY_PROTOCOL_STAT_NACK,
				req->packet, &(req->packet_length));
			
			send_gcom_ch(&(req->gch), req->packet, req->packet_length);
				
395
			fprintf(stderr, "packet type error : %02X\n", req->packet_type);
396
397
398
399
		}
	} else {
		fprintf(stderr, "payload decode error\n");
	}
400
401
	
	free(req);
402
403
}

Vladislav Rykov's avatar
Vladislav Rykov committed
404
void gateway_protocol_data_send_payload_decode(
Vladislav Rykov's avatar
Vladislav Rykov committed
405
406
407
408
	sensor_data_t *sensor_data, 
	const uint8_t *payload, 
	const uint8_t payload_length) 
{
Vladislav Rykov's avatar
Vladislav Rykov committed
409
410
411
412
413
	uint8_t p_len = 0;

	memcpy(&sensor_data->utc, &payload[p_len], sizeof(sensor_data->utc));
	p_len += sizeof(sensor_data->utc);

Vladislav Rykov's avatar
Vladislav Rykov committed
414
415
	memcpy(sensor_data->data, &payload[p_len], payload_length - p_len);
	sensor_data->data_length = payload_length - p_len;
Vladislav Rykov's avatar
Vladislav Rykov committed
416
417
}

Vladislav Rykov's avatar
Vladislav Rykov committed
418
419
420
421
422
423
void gateway_protocol_mk_stat(
	gcom_ch_t *gch,
	gateway_protocol_stat_t stat,
	uint8_t *pck,
	uint8_t *pck_len)
{
Vladislav Rykov's avatar
Vladislav Rykov committed
424
425
	gateway_protocol_packet_encode(
		&(gch->gwp_conf),
Vladislav Rykov's avatar
Vladislav Rykov committed
426
		GATEWAY_PROTOCOL_PACKET_TYPE_STAT,
Vladislav Rykov's avatar
Vladislav Rykov committed
427
		1, (uint8_t *)&stat,
Vladislav Rykov's avatar
Vladislav Rykov committed
428
		pck_len, pck);
Vladislav Rykov's avatar
Vladislav Rykov committed
429
430
}

Vladislav Rykov's avatar
Vladislav Rykov committed
431
432


Vladislav Rykov's avatar
Vladislav Rykov committed
433
void send_utc(gcom_ch_t *gch) {
Vladislav Rykov's avatar
Vladislav Rykov committed
434
	uint8_t buf[50];
Vladislav Rykov's avatar
Vladislav Rykov committed
435
436
437
438
439
	uint8_t buf_len = 0;
	struct timeval tv;
				
	gettimeofday(&tv, NULL);
				
Vladislav Rykov's avatar
Vladislav Rykov committed
440
441
	gateway_protocol_packet_encode (
		&(gch->gwp_conf),
Vladislav Rykov's avatar
Vladislav Rykov committed
442
		GATEWAY_PROTOCOL_PACKET_TYPE_TIME_SEND,
Vladislav Rykov's avatar
Vladislav Rykov committed
443
		sizeof(uint32_t), (uint8_t *)&tv.tv_sec,
Vladislav Rykov's avatar
Vladislav Rykov committed
444
445
446
447
448
449
		&buf_len, buf
	);
					
	send_gcom_ch(gch, buf, buf_len);
}

Vladislav Rykov's avatar
Vladislav Rykov committed
450
451
452
void gateway_protocol_checkup_callback(gateway_protocol_conf_t *gwp_conf) {
	PGresult *res;
	char db_query[200];
453
	
Vladislav Rykov's avatar
Vladislav Rykov committed
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
	snprintf(db_query, sizeof(db_query), 
		"SELECT secure_key, secure FROM applications WHERE app_key = '%s'", (char *)gwp_conf->app_key
	);
	pthread_mutex_lock(&mutex);
	res = PQexec(conn, db_query);
	pthread_mutex_unlock(&mutex);

	if ((PQresultStatus(res) == PGRES_TUPLES_OK) && PQntuples(res)) {
		base64_decode(PQgetvalue(res, 0, 0), strlen(PQgetvalue(res, 0, 0))-1, gwp_conf->secure_key);
		gwp_conf->secure = PQgetvalue(res, 0, 1)[0] == 't';
	} else {
		perror("gateway_protocol_checkup_callback error");
	}
	PQclear(res);
}

Vladislav Rykov's avatar
Vladislav Rykov committed
470
int send_gcom_ch(gcom_ch_t *gch, uint8_t *pck, uint8_t pck_size) {
471
	int ret;
Vladislav Rykov's avatar
Vladislav Rykov committed
472
	
473
	if ((ret = sendto(gch->server_desc, (char *)pck, pck_size, 0, (struct sockaddr *)&gch->client, gch->sock_len)) < 0) {
Vladislav Rykov's avatar
Vladislav Rykov committed
474
475
		perror("sendto error");
	}
476

Vladislav Rykov's avatar
Vladislav Rykov committed
477
478
479
480
	return ret;
}

int recv_gcom_ch(gcom_ch_t *gch, uint8_t *pck, uint8_t *pck_length, uint16_t pck_size) {
481
	int ret;
482
	if ((ret = recvfrom(gch->server_desc, (char *)pck, pck_size, MSG_WAITALL, (struct sockaddr *)&gch->client, &gch->sock_len)) < 0) {
Vladislav Rykov's avatar
Vladislav Rykov committed
483
		perror("socket receive error");
484
485
	} else {
		*pck_length = ret;
486
		
Vladislav Rykov's avatar
Vladislav Rykov committed
487
	}
488

489
	return ret;
Vladislav Rykov's avatar
Vladislav Rykov committed
490
}
491
492
493


static void process_gw_conf(json_value* value, gw_conf_t *gw_conf) {
494
495
496
497
498
499
	strncpy(gw_conf->gw_id, value->u.object.values[0].value->u.string.ptr, sizeof(gw_conf->gw_id));
	strncpy(gw_conf->gw_secure_key, value->u.object.values[1].value->u.string.ptr, sizeof(gw_conf->gw_secure_key));
	gw_conf->gw_port = value->u.object.values[2].value->u.integer;
	strncpy(gw_conf->db_type, value->u.object.values[3].value->u.string.ptr, sizeof(gw_conf->db_type));
	gw_conf->telemetry_send_period = value->u.object.values[4].value->u.integer;
}
500

501
502
503
504
505
506
static void process_db_conf(json_value* value, db_conf_t *db_conf) {
	strncpy(db_conf->addr, value->u.object.values[0].value->u.string.ptr, sizeof(db_conf->addr));
	db_conf->port = value->u.object.values[1].value->u.integer;
	strncpy(db_conf->db_name, value->u.object.values[2].value->u.string.ptr, sizeof(db_conf->db_name));
	strncpy(db_conf->user_name, value->u.object.values[3].value->u.string.ptr, sizeof(db_conf->user_name));
	strncpy(db_conf->user_pass, value->u.object.values[4].value->u.string.ptr, sizeof(db_conf->user_pass));
507
508
}

509
static json_value * read_json_conf(const char *file_path) {
510
511
512
513
514
515
	struct stat filestatus;
	FILE *fp;
	char *file_contents;
	json_char *json;
	json_value *jvalue;

516
517
518
	if (stat(file_path, &filestatus)) {
		fprintf(stderr, "File %s not found.", file_path);
		return NULL;
519
520
521
	}
	file_contents = (char *)malloc(filestatus.st_size);
	if (!file_contents) {
522
523
		fprintf(stderr, "Memory error allocating %d bytes.", (int) filestatus.st_size);
		return NULL;
524
	}
525
	fp = fopen(file_path, "rt");
526
	if (!fp) {
527
		fprintf(stderr, "Unable to open %s.", file_path);
528
529
		fclose(fp);
		free(file_contents);
530
		return NULL;
531
532
	}
	if (fread(file_contents, filestatus.st_size, 1, fp) != 1) {
533
		fprintf(stderr, "Unable to read %s.", file_path);
534
535
		fclose(fp);
		free(file_contents);
536
		return NULL;
537
538
539
	}
	fclose(fp);
	
540
541
	file_contents[filestatus.st_size] = '\0';
	printf("file content : \n'%s'\n", file_contents);
542
543
544
545
546
547
	
	json = (json_char *)file_contents;
	jvalue = json_parse(json, filestatus.st_size);
	if (!jvalue) {
		perror("Unable to parse json.");
		free(file_contents);
548
		return NULL;
549
550
	}
	
551
552
553
554
555
556
557
558
559
560
561
562
	free(file_contents);
	
	return jvalue;
}

static int read_gw_conf(const char *gw_conf_file_path, gw_conf_t *gw_conf) {
	json_value *jvalue;
	
	jvalue = read_json_conf(gw_conf_file_path);
	if (!jvalue) {
		return 1;
	}
563
564
565
566
567
568
	process_gw_conf(jvalue, gw_conf);

	json_value_free(jvalue);
	
	return 0;
}
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583

static int read_db_conf(const char *db_conf_file_path, db_conf_t *db_conf) {
	json_value *jvalue;
	
	jvalue = read_json_conf(db_conf_file_path);
	if (!jvalue) {
		return 1;
	}
	process_db_conf(jvalue, db_conf);

	json_value_free(jvalue);
	
	return 0;
}