-
Notifications
You must be signed in to change notification settings - Fork 37
Expand file tree
/
Copy pathSNMPInform.cpp
More file actions
143 lines (129 loc) · 5.38 KB
/
SNMPInform.cpp
File metadata and controls
143 lines (129 loc) · 5.38 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
#include "include/SNMPInform.h"
#include "SNMPTrap.h"
#include <list>
#ifdef COMPILING_TESTS
#include <tests/required/millis.h>
#endif
inline void delete_inform(struct InformItem* inform){
free(inform);
}
static void remove_inform_from_list(std::list<struct InformItem *> &list,
std::function<bool(struct InformItem *)> predicate) {
list.remove_if([&predicate](struct InformItem* item){
if(predicate(item)){
delete_inform(item);
return true;
}
return false;
});
}
snmp_request_id_t
queue_and_send_trap(std::list<struct InformItem *> &informList, SNMPTrap *trap, const IPAddress& ip, bool replaceQueuedRequests,
int retries, int delay_ms, CallbackFunctionSendStatus callbackFunctionSendStatus) {
bool buildStatus = trap->buildForSending();
if(!buildStatus) {
SNMP_LOGW("Couldn't build trap\n");
return INVALID_SNMP_REQUEST_ID;
};
SNMP_LOGD("%lu informs in informList", informList.size());
//TODO: could be race condition here, buildStatus to return packet?
if(replaceQueuedRequests){
SNMP_LOGD("Removing any outstanding informs for this trap\n");
remove_inform_from_list(informList, [trap](struct InformItem* informItem) -> bool {
if (informItem->callbackFunctionSendStatus){
SNMP_LOGD("callbackFunctionSendStatus is set\n");
delay(1);//If delete callback not working :(
informItem->callbackFunctionSendStatus(ssUnknow);
}
else{
SNMP_LOGW("callbackFunctionSendStatus not set\n");
}
return informItem->trap == trap;
});
}
if(trap->inform){
struct InformItem* item = (struct InformItem*)calloc(1, sizeof(struct InformItem));
item->delay_ms = delay_ms;
item->received = false;
item->requestID = trap->requestID;
item->retries = retries;
item->ip = ip;
item->lastSent = millis();
item->trap = trap;
item->missed = false;
item->callbackFunctionSendStatus = callbackFunctionSendStatus;
SNMP_LOGD("Adding Inform request to queue: %lu\n", item->requestID);
informList.push_back(item);
trap->sendTo(ip, true);
} else {
// normal send
SNMP_LOGD("Sending normal trap\n");
trap->sendTo(ip);
}
return trap->requestID;
}
void inform_callback(std::list<struct InformItem *> &informList, snmp_request_id_t requestID, bool responseReceiveSuccess) {
(void)responseReceiveSuccess;
SNMP_LOGD("Receiving InformCallback for requestID: %lu, success: %d\n", requestID, responseReceiveSuccess);
//TODO: if we ever want to keep received informs, change this logic
remove_inform_from_list(informList, [requestID](struct InformItem* informItem) -> bool {
if (informItem->callbackFunctionSendStatus){
SNMP_LOGD("callbackFunctionSendStatus is set\n");
delay(1);//If delete callback not working :(
informItem->callbackFunctionSendStatus(ssOk);
}
else{
SNMP_LOGW("callbackFunctionSendStatus not set\n");
}
return informItem->requestID == requestID;
});
SNMP_LOGD("Informs waiting for responses: %lu\n", informList.size());
}
void handle_inform_queue(std::list<struct InformItem *> &informList) {
auto thisLoop = millis();
bool flagRemove = false;
for(auto informItem : informList){
if(!informItem->received && thisLoop - informItem->lastSent > informItem->delay_ms){
SNMP_LOGD("Missed Inform receive\n");
// check if sending again
informItem->missed = true;
if(!informItem->retries){
SNMP_LOGD("No more retries for inform: %lu, removing\n", informItem->requestID);
flagRemove = true;
continue;
}
if(informItem->trap){
SNMP_LOGD("No response received in %lums, Resending Inform: %lu\n", thisLoop - informItem->lastSent, informItem->requestID);
informItem->trap->sendTo(informItem->ip, true);
informItem->lastSent = thisLoop;
informItem->missed = false;
informItem->retries--;
}
}
}
if (flagRemove) remove_inform_from_list(informList, [](struct InformItem* informItem) -> bool {
if (informItem->callbackFunctionSendStatus){
SNMP_LOGD("callbackFunctionSendStatus is set\n");
delay(1);//If delete callback not working :(
informItem->callbackFunctionSendStatus(ssError);
}
else{
SNMP_LOGW("callbackFunctionSendStatus not set\n");
}
return informItem->received || (informItem->retries == 0 && informItem->missed);
});
}
void mark_trap_deleted(std::list<struct InformItem *> &informList, SNMPTrap *trap) {
SNMP_LOGD("Removing waiting Informs tied to Trap.\n");
remove_inform_from_list(informList, [trap](struct InformItem* informItem) -> bool {
if (informItem->callbackFunctionSendStatus){
SNMP_LOGD("callbackFunctionSendStatus is set\n");
delay(1);//If delete callback not working :(
informItem->callbackFunctionSendStatus(ssUnknow);
}
else{
SNMP_LOGW("callbackFunctionSendStatus not set\n");
}
return informItem->trap == trap;
});
}