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