· 6 years ago · Jun 18, 2019, 09:36 AM
1#include <stdio.h>
2#include <stdlib.h>
3#include <sys/socket.h>
4#include <netinet/in.h>
5#include <string.h>
6
7#include <sys/time.h>
8#include <arpa/inet.h>
9#include <fcntl.h> // for open
10#include <unistd.h> // for close
11#include <pthread.h>
12#include <sys/inotify.h>
13#include <poll.h>
14#include <sqlite3.h>
15
16#include <iostream>
17#include <string>
18#include "database.cpp"
19
20#define LISTENING_IP "10.3.141.1"
21#define LISTENING_PORT 6667
22
23 using namespace std;
24
25pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER;
26
27
28
29
30
31void * socketThread(void *arg) {
32 int newSocket = *((int *)arg);
33
34 struct sockaddr_in addr;
35 socklen_t addr_size = sizeof(struct sockaddr_in);
36 int res = getpeername(newSocket, (struct sockaddr *)&addr, &addr_size);
37
38 string clientIp = inet_ntoa(addr.sin_addr);
39 cout << "Thread started for " << clientIp << "\n";
40
41 //Setting non blocking mode
42 int flags = fcntl(newSocket, F_GETFL);
43 fcntl(newSocket, F_SETFL, flags | O_NONBLOCK);
44
45 char buffer[128];
46 char message[128];
47
48
49 while(1){
50 string stateStr = getStateFromIp(clientIp);
51 if(stateStr.empty()){
52 cout << "Error, cant get state from database";
53 }
54
55 memset(message, 0, sizeof message);
56 strcpy(message, "<");
57 strcat(message, stateStr.c_str());
58 strcat(message, ">");
59 send(newSocket, message , 128 , MSG_NOSIGNAL | MSG_DONTWAIT);
60 printf("Sent : %s\n", message);
61
62
63 struct pollfd fd;
64 fd.fd = newSocket; // your socket handler
65 fd.events = POLLIN;
66 int ret = poll(&fd, 1, 5000); // 1 second for timeout
67 ssize_t rc = recv(newSocket, buffer, sizeof(buffer), 0);
68
69 if (rc == 0 || rc == -1 || ret == -1 || ret == 0) { //-1 is error, 0 is timeout
70 if(ret == 0){
71 printf("Closing socket because of timeout for %s\n", clientIp);
72 }
73 else{
74 printf("Closing socket because of error for %s\n", clientIp);
75 }
76 close(newSocket);
77 pthread_exit(NULL);
78 pthread_detach(pthread_self());
79 }
80 else {
81 string strResponse(buffer);
82 int batLvl = stoi(strResponse);
83 printf("Received: %s\n", buffer);
84 updateClientBatLevel(clientIp, batLvl);
85 }
86
87
88 int infd = inotify_init();
89 int wd = inotify_add_watch(infd, "trigger", IN_MODIFY);
90 struct pollfd fd2;
91 fd2.fd = infd;
92 fd2.events = POLLIN;
93
94 int rc2 = poll(&fd2, 1, 5000); //sleep 5 second if not change file
95 if(rc2 > 0){
96 printf("FILE MODIFIED");
97 usleep(50 * 1000);
98 }
99
100 inotify_rm_watch(infd, wd);
101 close(infd);
102
103 }
104
105 }
106
107
108
109
110 int main(){
111// openDatabase();
112 int serverSocket, newSocket;
113 struct sockaddr_in serverAddr;
114 struct sockaddr_storage serverStorage;
115 socklen_t addr_size;
116 serverSocket = socket(PF_INET, SOCK_STREAM, 0);
117 serverAddr.sin_family = AF_INET;
118 serverAddr.sin_port = htons(LISTENING_PORT);
119 serverAddr.sin_addr.s_addr = inet_addr(LISTENING_IP);
120 memset(serverAddr.sin_zero, '\0', sizeof serverAddr.sin_zero);
121
122
123 while(bind(serverSocket, (struct sockaddr *) &serverAddr, sizeof(serverAddr) ) < 0){
124 perror("ERROR on binding on port, retrying in 5 sec");
125 sleep(5);
126 }
127
128 if(listen(serverSocket, 50) == 0){
129 printf("Listening on %s:%d\n", LISTENING_IP, LISTENING_PORT);
130 }
131 else{
132 printf("Error\n");
133 }
134
135 pthread_t tid[60];
136 int i = 0;
137 while(1) {
138 addr_size = sizeof serverStorage;
139 newSocket = accept(serverSocket, (struct sockaddr *)&serverStorage, &addr_ size);
140 if (newSocket < 0) {
141 perror("ERROR on accept, retrying in 5 sec");
142 sleep(5);
143 }
144
145 if(pthread_create(&tid[i], NULL, socketThread, &newSocket) != 0 ){
146 printf("Failed to create thread\n");
147 }
148 }
149
150// closeDatabase();
151 printf("End\n");
152 return 0;
153 }
154
155
156
157
158
159
160
161
162
163
164
165
166#include <sqlite3.h>
167#include <iostream>
168#include <string>
169
170
171using namespace std;
172
173sqlite3 *db;
174
175void openDatabase(){
176 sqlite3_open("database.db", &db);
177}
178
179void closeDatabase(){
180 sqlite3_close(db);
181}
182
183
184
185void setDefaultState(const string &state){
186 sqlite3_stmt *stmt;
187 sqlite3_prepare_v2(db, "UPDATE state SET state = ? WHERE client_id IS NULL", -1, &stmt, NULL);
188 sqlite3_bind_text(stmt, 1, state.c_str(), -1, 0);
189 sqlite3_step(stmt);
190 sqlite3_finalize(stmt);
191}
192
193
194bool hasClientSpecificState(const string &ip){
195 sqlite3_stmt *stmt;
196 int rc;
197 sqlite3_prepare_v2(db, "SELECT COUNT(*) FROM state JOIN client ON client.id = state.client_id AND client.ip = ?;", -1, &stmt, NULL);
198 sqlite3_bind_text(stmt, 1, ip.c_str(), -1, 0);
199
200 while ((rc = sqlite3_step(stmt)) == SQLITE_ROW) {
201 int nb = sqlite3_column_int(stmt, 0);
202 sqlite3_finalize(stmt);
203 return nb > 0;
204 }
205 return false;
206}
207
208void setStateForIp(const string &state, const string &ip){
209 sqlite3_stmt *stmt;
210 string sql;
211
212 if(!hasClientSpecificState(ip)){
213 sql = "INSERT INTO state(client_id, state) VALUES((SELECT id FROM client WHERE client.ip = ?), ?);";
214 sqlite3_prepare_v2(db, sql.c_str(), -1, &stmt, NULL);
215 sqlite3_bind_text(stmt, 1, ip.c_str(), -1, 0);
216 sqlite3_bind_text(stmt, 2, state.c_str(), -1, 0);
217 }
218
219 else{
220 string sql = "UPDATE state SET state = ? WHERE EXISTS(SELECT * FROM client WHERE client.ip = ? AND client.id = client_id);";
221 sqlite3_prepare_v2(db, sql.c_str(), -1, &stmt, NULL);
222 sqlite3_bind_text(stmt, 1, state.c_str(), -1, 0);
223 sqlite3_bind_text(stmt, 2, ip.c_str(), -1, 0);
224 }
225
226 sqlite3_step(stmt);
227 sqlite3_finalize(stmt);
228}
229
230
231
232
233void updateClientBatLevel(const string &ip, int batLvl){
234 openDatabase();
235 sqlite3_stmt *stmt;
236 int rc;
237 string retStr;
238 sqlite3_prepare_v2(db, "UPDATE client SET bat_level = ? WHERE ip = ?", -1, &stmt, NULL);
239 sqlite3_bind_int(stmt, 1, batLvl);
240 sqlite3_bind_text(stmt, 2, ip.c_str(), -1, 0);
241 sqlite3_step(stmt);
242 sqlite3_finalize(stmt);
243 closeDatabase();
244}
245
246string getStateFromIp(const string &ip){
247 openDatabase();
248 sqlite3_stmt *stmt;
249 int rc;
250 string retStr;
251 sqlite3_prepare_v2(db, "SELECT state.state from state LEFT JOIN client ON client.id = state.client_id WHERE client.ip = ? OR state.client_id IS NULL ORDER BY client_id DESC LIMIT 1", -1, &stmt, NULL);
252 sqlite3_bind_text(stmt, 1, ip.c_str(), -1, 0);
253 while ((rc = sqlite3_step(stmt)) == SQLITE_ROW) {
254 retStr = string(reinterpret_cast<const char*>(sqlite3_column_text(stmt, 0)));
255 sqlite3_finalize(stmt);
256 break;
257 }
258 closeDatabase();
259 return retStr;
260}
261
262
263
264
265
266
267
268
269
270
271#!/bin/bash
272sqlite3 database.db <<EOF
273DROP TABLE IF EXISTS client;
274DROP TABLE IF EXISTS state;
275DROP TABLE IF EXISTS variable;
276
277CREATE TABLE client(id INTEGER NOT NULL PRIMARY KEY , mac VARCHAR(255), ip VARCHAR(25) NOT NULL, bat_level INTEGER, ttime INTEGER, signal INTEGER, inactive INTEGER);
278CREATE TABLE state(id INTEGER NOT NULL PRIMARY KEY , client_id INTEGER, state TEXT NOT NULL);
279CREATE TABLE variable(id INTEGER NOT NULL PRIMARY KEY, name VARCHAR(255) NOT NULL, value TEXT NOT NULL);
280
281INSERT INTO state(client_id, state) VALUES(NULL, '255,0,0;0.2;0.2;static;none');
282EOF