1 //
2 // anyRemote
3 // a wi-fi or bluetooth remote for your PC.
4 //
5 // Copyright (C) 2006-2016 Mikhail Fedotov <anyremote@mail.ru>
6 //
7 // This program is free software; you can redistribute it and/or modify
8 // it under the terms of the GNU General Public License as published by
9 // the Free Software Foundation; either version 3 of the License, or
10 // (at your option) any later version.
11 //
12 // This program is distributed in the hope that it will be useful,
13 // but WITHOUT ANY WARRANTY; without even the implied warranty of
14 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 // GNU General Public License for more details.
16 //
17 // You should have received a copy of the GNU General Public License
18 // along with this program; if not, write to the Free Software
19 // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
20 //
21
22 #include <stdlib.h>
23 #include <stdio.h>
24 #include <string.h>
25 #include <sys/stat.h>
26 #include <time.h>
27 #include <sys/time.h>
28
29 #include "common.h"
30 #include "executor.h"
31 #include "dispatcher.h"
32 #include "utils.h"
33 #include "peer.h"
34 #include "alarm.h"
35
36 extern char tmp[MAXMAXLEN];
37
38 typedef struct {
39 char *file;
40 char *macro;
41 } type_alarm;
42
43
44 SingleList * _alarmList = NULL;
45
46 //////////////////////////////////////////////////////////////////////////////////
47 //
48 // Functions related to alarms
49 //
50 //////////////////////////////////////////////////////////////////////////////////
51
52 // mode: 0 - clear alarms
53 // 1 - if fired - process, then clear alarms
manageAlarms(int mode)54 void manageAlarms(int mode)
55 {
56 struct stat buf;
57
58 SingleList* list = _alarmList;
59 while (list) {
60
61 type_alarm * v = (type_alarm *) list->data;
62
63 // If file exists
64 int fs = stat(v->file, &buf);
65 if (fs == 0) {
66 if (mode == ALARM_CLEAN) {
67 logger(L_DBG,"[ML]: Remove file");
68 } else {
69 INFO2("[ML]: Alarm %s fired", v->macro);
70
71 eMessage* em = (eMessage*) malloc(sizeof(eMessage));
72 em->peer = 0;
73 em->type = EM_ALARM;
74 em->value = strdup(v->macro);
75
76 sendToExecutor(em);
77 }
78 remove(v->file);
79 }
80 list = listSingleNext(list);
81 }
82 }
83
getAlarms()84 SingleList * getAlarms()
85 {
86 return _alarmList;
87 }
88
forgetAlarms()89 void forgetAlarms() // just set to NULL, no cleanup
90 {
91 _alarmList = NULL;
92 }
93
addAlarm(char * file,char * macro)94 void addAlarm(char *file, char *macro)
95 {
96 sprintf(tmp,"addAlarm() >%s< >%s<\n", file,macro);
97 logger(L_DBG,tmp);
98
99 type_alarm * v = (type_alarm *) calloc(sizeof(type_alarm),1);
100 v->file = strdup(file);
101 v->macro = strdup(macro);
102
103 _alarmList = listSingleAppend(_alarmList, v);
104 }
105
destroyAlarm(void * ptr)106 void destroyAlarm(void* ptr)
107 {
108 type_alarm * v = (type_alarm *) ptr;
109
110 //sprintf(tmp,"destroyAlarm() >%s<", v->file);
111 //logger(L_DBG,tmp);
112
113 free(v->file);
114 free(v->macro);
115 free(v);
116 }
117
freeAlarms(SingleList * chain)118 void freeAlarms(SingleList* chain)
119 {
120 listSingleFullFree((chain ? chain : _alarmList), destroyAlarm);
121 if (!chain) {
122 _alarmList = NULL;
123 }
124 }
125
126 //////////////////////////////////////////////////////////////////////////////////
127 //
128 // Functions related to keepalive messages handling
129 //
130 //////////////////////////////////////////////////////////////////////////////////
131
132 static int _keepaliveTimeout = 0;
133 static int _keepaliveFlag = BOOL_YES;
134 static time_t _keepaliveSendTime;
135 static time_t _keepaliveDropTime;
136
checkKeepalive()137 static void checkKeepalive()
138 {
139 DEBUG2("[ML]: checkKeepalive %d", _keepaliveFlag);
140
141 if (!_keepaliveFlag) {
142
143 _keepaliveTimeout = 0;
144
145 DEBUG2("[ML]: no keepalive message, drop connection");
146
147 // drop connection
148 dMessage* dm = allocDMessage();
149 dm->type = DM_EVENT;
150 dm->subtype = ID_EVENT_DISCONNECT;
151
152 sendToDispatcher(dm);
153 }
154 _keepaliveFlag = BOOL_NO;
155 }
156
keepaliveTest()157 void keepaliveTest()
158 {
159 //DEBUG2("[ML]: keepaliveTest %d", _keepaliveTimeout);
160 if (_keepaliveTimeout > 0) {
161
162 time_t now = time(NULL);
163 double st = difftime(now, _keepaliveSendTime);
164 double dt = difftime(now, _keepaliveDropTime);
165
166 if (dt > _keepaliveTimeout * 2) { // about (_keepaliveTimeout * 2) seconds
167 checkKeepalive();
168 time(&_keepaliveDropTime);
169 }
170
171 if (st > _keepaliveTimeout) {
172
173 DEBUG2("[ML]: send keepalive message");
174
175 dMessage* dm = allocDMessage();
176 dm->value = strdup("Get(ping);");
177 dm->size = strlen(dm->value);
178 dm->type = DM_GET;
179 dm->subtype = ID_GET_PING;
180
181 sendToDispatcher(dm);
182
183 time(&_keepaliveSendTime);
184 }
185 }
186 }
187
addKeepalive(const char * tmout)188 void addKeepalive(const char* tmout)
189 {
190 if (!isServerMode()) {
191 logger(L_DBG,"[ML]: can not set keepalive timeout for non-Server mode");
192 return;
193 }
194
195 _keepaliveFlag = BOOL_YES;
196 _keepaliveTimeout = 0;
197
198 if (tmout && atoi(tmout) > 0) {
199
200 _keepaliveTimeout = atoi(tmout);
201 DEBUG2("[ML]: keepalive timeout set to %d seconds", _keepaliveTimeout);
202
203 time(&_keepaliveSendTime);
204 time(&_keepaliveDropTime);
205
206 } else {
207 _keepaliveTimeout = -1;
208 DEBUG2("[ML]: drop keepalive check");
209 }
210 }
211
useKeepalive()212 boolean_t useKeepalive()
213 {
214 return (_keepaliveTimeout > 0 ? BOOL_YES : BOOL_NO);
215 }
216
setKeepalive()217 void setKeepalive()
218 {
219 DEBUG2("[ML]: got keepalive message");
220 _keepaliveFlag = BOOL_YES;
221 }
222