5 #include "networkInterfaces.h"
6 #include "configuration.h"
7 #include "gpsConversion.h"
20 /** The size of the buffer in which the received NMEA string is stored */
21 #define BUFFER_SIZE_RX_NMEA 2048
23 /** The size of the buffer in which the received downlink message is stored */
24 #define BUFFER_SIZE_RX_DOWNLINK 2048
26 /** The size of the buffer in which the converted NMEA string is assembled for
27 * transmission over OSLR */
28 #define BUFFER_SIZE_TX_OLSR 512
30 /** The de-duplication list */
31 static DeDupList deDupList;
34 Report a plugin error.
37 when true then errno is used in the error message; the error reason is also
40 a pointer to the format string
42 arguments to the format string
44 void pudError(bool useErrno, const char *format, ...) {
46 char *stringErr = NULL;
49 stringErr = strerror(errno);
52 if ((format == NULL) || (*format == '\0')) {
54 olsr_printf(0, "%s: %s\n", PUD_PLUGIN_ABBR, stringErr);
56 olsr_printf(0, "%s: Unknown error\n", PUD_PLUGIN_ABBR);
61 va_start(arglist, format);
62 vsnprintf(strDesc, sizeof(strDesc), format, arglist);
65 strDesc[sizeof(strDesc) - 1] = '\0'; /* Ensures null termination */
68 olsr_printf(0, "%s: %s: %s\n", PUD_PLUGIN_ABBR, strDesc, stringErr);
70 olsr_printf(0, "%s: %s\n", PUD_PLUGIN_ABBR, strDesc);
76 Sends a buffer out on all transmit interfaces
81 the number of bytes in the buffer
83 static void sendToAllTxInterfaces(unsigned char *buffer,
84 unsigned int bufferLength) {
85 union olsr_sockaddr * txAddress;
86 TRxTxNetworkInterface *txNetworkInterfaces = getTxNetworkInterfaces();
87 while (txNetworkInterfaces != NULL) {
88 TRxTxNetworkInterface *networkInterface = txNetworkInterfaces;
90 txAddress = getTxMcAddr();
91 if (sendto(networkInterface->socketFd, buffer, bufferLength, 0,
92 (struct sockaddr *) &txAddress->in, sizeof(txAddress->in)) < 0) {
93 pudError(true, "Transmit error on interface %s",
94 (char *) &networkInterface->name);
96 txNetworkInterfaces = networkInterface->next;
101 Called by OLSR core when a packet for the plugin is received from the OLSR
102 network. It converts the packet into an NMEA string and transmits it over all
103 transmit non-OLSR network interfaces.
106 a pointer to the received OLSR message
108 a pointer to the OLSR network interface on which the packet was received
110 a pointer to the IP address of the sender
113 - true when the packet was processed
116 bool packetReceivedFromOlsr(union olsr_message *olsrMessage,
117 struct interface *in_if __attribute__ ((unused)), union olsr_ip_addr *ipaddr __attribute__ ((unused))) {
118 const union olsr_ip_addr * originator = getOlsrMessageOriginator(
119 olsr_cnf->ip_version, olsrMessage);
120 unsigned int transmitStringLength;
121 unsigned char buffer[BUFFER_SIZE_TX_OLSR];
123 /* when we do not loopback then check if the message originated from this
125 if (!getUseLoopback() && ipequal(originator, &olsr_cnf->main_addr)) {
129 /* do deduplication: when we have already seen this message from the same
130 * originator then just back off */
131 if (likely(getUseDeDup())) {
132 if (isInDeDupList(&deDupList, olsrMessage)) {
136 addToDeDup(&deDupList, olsrMessage);
139 transmitStringLength = gpsFromOlsr(olsrMessage, &buffer[0], sizeof(buffer));
140 if (unlikely(transmitStringLength == 0)) {
144 sendToAllTxInterfaces(&buffer[0], transmitStringLength);
150 Called by OLSR core when a packet for the plugin is received from the downlink.
151 It unpacks the messages and distributes them into OLSR and on the LAN.
154 the socket file descriptor on which the packet is received
156 a pointer to the network interface structure on which the packet was received
160 static void packetReceivedFromDownlink(int skfd, void *data __attribute__ ((unused)), unsigned int flags __attribute__ ((unused))) {
162 unsigned char rxBuffer[BUFFER_SIZE_RX_DOWNLINK];
165 struct sockaddr sender;
166 socklen_t senderSize = sizeof(sender);
167 bool addedToDedup = false;
169 /* Receive the captured Ethernet frame */
170 memset(&sender, 0, senderSize);
172 rxCount = recvfrom(skfd, &rxBuffer[0], (sizeof(rxBuffer) - 1), 0,
173 &sender, &senderSize);
175 pudError(true, "Receive error in %s, ignoring message.", __func__);
179 while (rxIndex < rxCount) {
180 UplinkMessage * msg = (UplinkMessage *) &rxBuffer[rxIndex];
182 uint16_t uplinkMessageLength;
183 uint16_t olsrMessageLength;
185 union olsr_message * olsrMessage;
187 type = getUplinkMessageType(&msg->header);
188 if (type != POSITION) {
189 pudError(false, "Received wrong type (%d) in %s,"
190 " ignoring message.", type, __func__);
194 ipv6 = getUplinkMessageIPv6(&msg->header);
195 if (unlikely(ipv6 && (olsr_cnf->ip_version != AF_INET6))) {
196 pudError(false, "Received wrong IPv6 status (%s) in %s,"
197 " ignoring message.", (ipv6 ? "true" : "false"),
202 olsrMessageLength = getUplinkMessageLength(&msg->header);
203 uplinkMessageLength = olsrMessageLength + sizeof(UplinkHeader);
205 if (unlikely((rxIndex + uplinkMessageLength) > rxCount)) {
206 pudError(false, "Received wrong length (%d) in %s,"
207 " ignoring the rest of the messages.", olsrMessageLength,
212 olsrMessage = &msg->msg.olsrMessage;
214 /* we now have a position update (olsrMessage) of a certain length
215 * (length). this needs to be transmitted over OLSR and on the LAN */
217 if (likely(getUseDeDup()) && !isInDeDupList(&deDupList, olsrMessage)) {
218 addToDeDup(&deDupList, olsrMessage);
222 if (likely(addedToDedup) || unlikely(!getUseDeDup())) {
223 /* send out over OLSR interfaces */
225 struct interface *ifn;
226 for (ifn = ifnet; ifn; ifn = ifn->int_next) {
227 r = net_outbuffer_push(ifn, olsrMessage, olsrMessageLength);
228 if (r != (int) olsrMessageLength) {
231 "Could not send to OLSR interface %s: %s"
232 " (length=%u, r=%d)",
234 ((r == -1) ? "no buffer was found" :
235 (r == 0) ? "there was not enough room in the buffer" :
236 "unknown reason"), olsrMessageLength, r);
240 /* send out over tx interfaces */
241 (void) packetReceivedFromOlsr(olsrMessage, NULL, NULL);
243 rxIndex += uplinkMessageLength;
249 Called by OLSR core when a packet for the plugin is received from the non-OLSR
250 network. It converts the packet into the internal OLSR wire format for a
251 position update and transmits it over all OLSR network interfaces.
254 the socket file descriptor on which the packet is received
256 a pointer to the network interface structure on which the packet was received
260 static void packetReceivedForOlsr(int skfd, void *data __attribute__ ((unused)), unsigned int flags __attribute__ ((unused))) {
262 unsigned char rxBuffer[BUFFER_SIZE_RX_NMEA];
264 struct sockaddr sender;
265 socklen_t senderSize = sizeof(sender);
267 assert(data != NULL);
269 /* Receive the captured Ethernet frame */
270 memset(&sender, 0, senderSize);
272 rxCount = recvfrom(skfd, &rxBuffer[0], (sizeof(rxBuffer) - 1), 0,
273 &sender, &senderSize);
275 pudError(true, "Receive error in %s, ignoring message.", __func__);
279 /* make sure the string is null-terminated */
280 rxBuffer[rxCount] = '\0';
282 /* only accept messages from configured IP addresses */
283 if (!isRxAllowedSourceIpAddress(&sender)) {
287 /* we have the received string in the rxBuffer now */
289 /* hand the NMEA information to the receiver */
290 (void) receiverUpdateGpsInformation(&rxBuffer[0], rxCount);
295 Initialise the plugin: check the configuration, initialise the NMEA parser,
296 create network interface sockets, hookup the plugin to OLSR and setup data
297 that can be setup in advance.
304 if (!checkConfig()) {
305 pudError(false, "Invalid configuration");
310 pudError(false, "Could not initialise state");
314 if (!initDeDupList(&deDupList, getDeDupDepth())) {
315 pudError(false, "Could not initialise de-duplication list");
319 if (!startReceiver()) {
320 pudError(false, "Could not start receiver");
325 * Creates receive and transmit sockets and register the receive sockets
326 * with the OLSR stack
328 if (!createNetworkInterfaces(&packetReceivedForOlsr,
329 &packetReceivedFromDownlink)) {
330 pudError(false, "Could not create require network interfaces");
334 if (!checkRunSetup()) {
335 pudError(false, "Invalid configuration");
340 * Tell OLSR to call packetReceivedFromOlsr when the packets for this
341 * plugin arrive from the OLSR network
343 olsr_parser_add_function(&packetReceivedFromOlsr, PUD_OLSR_MSG_TYPE);
352 Stop the plugin: shut down all created network interface sockets and destroy
355 void closePud(void) {
356 olsr_parser_remove_function(&packetReceivedFromOlsr, PUD_OLSR_MSG_TYPE);
357 closeNetworkInterfaces();
359 destroyDeDupList(&deDupList);