From 1adcd6bcfb18395ccf247ab975ec16d57c668e75 Mon Sep 17 00:00:00 2001 From: Steffen Vogel Date: Sat, 18 Nov 2017 13:48:21 +0100 Subject: [PATCH 01/14] fixed typo --- src/hal/inc/hal_socket.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/hal/inc/hal_socket.h b/src/hal/inc/hal_socket.h index a6d64c08..c9520579 100644 --- a/src/hal/inc/hal_socket.h +++ b/src/hal/inc/hal_socket.h @@ -63,7 +63,7 @@ HandleSet Handleset_new(void); /** - * \brief add a soecket to an existing handle set + * \brief add a socket to an existing handle set * * \param self the HandleSet instance * \param sock the socket to add From d77144490439dc24c75b70bfc9e15c4bb291ed9d Mon Sep 17 00:00:00 2001 From: Steffen Vogel Date: Sat, 18 Nov 2017 15:00:15 +0100 Subject: [PATCH 02/14] add EthernetHandleSet implementation for Linux --- src/hal/ethernet/linux/ethernet_linux.c | 55 +++++++++++++++++++++++++ src/hal/inc/hal_ethernet.h | 44 ++++++++++++++++++++ 2 files changed, 99 insertions(+) diff --git a/src/hal/ethernet/linux/ethernet_linux.c b/src/hal/ethernet/linux/ethernet_linux.c index cff4f068..a2e3e8c9 100644 --- a/src/hal/ethernet/linux/ethernet_linux.c +++ b/src/hal/ethernet/linux/ethernet_linux.c @@ -23,6 +23,7 @@ #include #include +#include #include #include #include @@ -40,6 +41,60 @@ struct sEthernetSocket { struct sockaddr_ll socketAddress; }; +struct sEthernetHandleSet { + fd_set handles; + int maxHandle; +}; + +EthernetHandleSet +EthernetHandleSet_new(void) +{ + EthernetHandleSet result = (EthernetHandleSet) GLOBAL_MALLOC(sizeof(struct sEthernetHandleSet)); + + if (result != NULL) { + FD_ZERO(&result->handles); + result->maxHandle = -1; + } + + return result; +} + +void +EthernetHandleSet_addSocket(EthernetHandleSet self, const EthernetSocket sock) +{ + if (self != NULL && sock != NULL && sock->rawSocket != -1) { + FD_SET(sock->rawSocket, &self->handles); + if (sock->rawSocket > self->maxHandle) { + self->maxHandle = sock->rawSocket; + } + } +} + +int +EthernetHandleSet_waitReady(EthernetHandleSet self, unsigned int timeoutMs) +{ + int result; + + if ((self != NULL) && (self->maxHandle >= 0)) { + struct timeval timeout; + + timeout.tv_sec = timeoutMs / 1000; + timeout.tv_usec = (timeoutMs % 1000) * 1000; + result = select(self->maxHandle + 1, &self->handles, NULL, NULL, &timeout); + } + else { + result = -1; + } + + return result; +} + +void +EthernetHandleSet_destroy(EthernetHandleSet self) +{ + GLOBAL_FREEMEM(self); +} + static int getInterfaceIndex(int sock, const char* deviceName) { diff --git a/src/hal/inc/hal_ethernet.h b/src/hal/inc/hal_ethernet.h index 137e717c..5fa6e412 100644 --- a/src/hal/inc/hal_ethernet.h +++ b/src/hal/inc/hal_ethernet.h @@ -48,6 +48,50 @@ extern "C" { */ typedef struct sEthernetSocket* EthernetSocket; +/** Opaque reference for a set of ethernet socket handles */ +typedef struct sEthernetHandleSet* EthernetHandleSet; + +/** + * \brief Create a new connection handle set (EthernetHandleSet) + * + * \return new EthernetHandleSet instance + */ +EthernetHandleSet +EthernetHandleSet_new(void); + +/** + * \brief add a socket to an existing handle set + * + * \param self the HandleSet instance + * \param sock the socket to add + */ +void +EthernetHandleSet_addSocket(EthernetHandleSet self, const EthernetSocket sock); + + +/** + * \brief wait for a socket to become ready + * + * This function is corresponding to the BSD socket select function. + * It returns the number of sockets on which data is pending or 0 if no data is pending + * on any of the monitored connections. The function will return after "timeout" ms if no + * data is pending. + * The function shall return -1 if a socket error occures. + * + * \param self the EthernetHandleSet instance + * \param timeout in milliseconds (ms) + */ +int +EthernetHandleSet_waitReady(EthernetHandleSet self, unsigned int timeoutMs); + +/** + * \brief destroy the EthernetHandleSet instance + * + * \param self the HandleSet instance to destroy + */ +void +EthernetHandleSet_destroy(EthernetHandleSet self); + /** * \brief Return the MAC address of an Ethernet interface. * From 89661b471f6b0f15f5c67ac41587107cc3fd6283 Mon Sep 17 00:00:00 2001 From: Steffen Vogel Date: Sat, 18 Nov 2017 15:01:16 +0100 Subject: [PATCH 03/14] add EthernetHandleSet implementation for BSD --- src/hal/ethernet/bsd/ethernet_bsd.c | 53 +++++++++++++++++++++++++++++ 1 file changed, 53 insertions(+) diff --git a/src/hal/ethernet/bsd/ethernet_bsd.c b/src/hal/ethernet/bsd/ethernet_bsd.c index fe601996..4020d9d8 100644 --- a/src/hal/ethernet/bsd/ethernet_bsd.c +++ b/src/hal/ethernet/bsd/ethernet_bsd.c @@ -22,6 +22,7 @@ */ #include #include +#include #include #include #include @@ -47,6 +48,58 @@ struct sEthernetSocket { }; int _Ethernet_activateBpdFilter(EthernetSocket self) +struct sEthernetHandleSet { + fd_set handles; + int maxHandle; +}; + +EthernetHandleSet +EthernetHandleSet_new(void) +{ + EthernetHandleSet result = (EthernetHandleSet) GLOBAL_MALLOC(sizeof(struct sEthernetHandleSet)); + + if (result != NULL) { + FD_ZERO(&result->handles); + result->maxHandle = -1; + } + return result; +} + +void +EthernetHandleSet_addSocket(EthernetHandleSet self, const EthernetSocket sock) +{ + if (self != NULL && sock != NULL && sock->bpf != -1) { + FD_SET(sock->bpf, &self->handles); + if (sock->bpf > self->maxHandle) { + self->maxHandle = sock->bpf; + } + } +} + +int +EthernetHandleSet_waitReady(EthernetHandleSet self, unsigned int timeoutMs) +{ + int result; + + if ((self != NULL) && (self->maxHandle >= 0)) { + struct timeval timeout; + + timeout.tv_sec = timeoutMs / 1000; + timeout.tv_usec = (timeoutMs % 1000) * 1000; + result = select(self->maxHandle + 1, &self->handles, NULL, NULL, &timeout); + } else { + result = -1; + } + + return result; +} + +void +EthernetHandleSet_destroy(EthernetHandleSet self) +{ + GLOBAL_FREEMEM(self); +} + { return ioctl(self->bpf, BIOCSETF, &self->bpfProgram); } From c082f09aef3b4c29081b2690296d1a4e059495bd Mon Sep 17 00:00:00 2001 From: Steffen Vogel Date: Sat, 18 Nov 2017 15:43:22 +0100 Subject: [PATCH 04/14] add EthernetHandleSet implementation for Windows --- src/hal/ethernet/win32/ethernet_win32.c | 80 ++++++++++++++++++++++++- 1 file changed, 77 insertions(+), 3 deletions(-) diff --git a/src/hal/ethernet/win32/ethernet_win32.c b/src/hal/ethernet/win32/ethernet_win32.c index dddbaf40..e7e91100 100644 --- a/src/hal/ethernet/win32/ethernet_win32.c +++ b/src/hal/ethernet/win32/ethernet_win32.c @@ -47,6 +47,8 @@ #define HAVE_REMOTE +// Enable WinPcap specific extension: pcap_getevent() +#define WPCAP #include "pcap.h" struct sEthernetSocket { @@ -54,6 +56,11 @@ struct sEthernetSocket { struct bpf_program etherTypeFilter; }; +struct sEthernetHandleSet { + HANDLE *handles; + int nhandles; +}; + #ifdef __GNUC__ /* detect MINGW */ #ifndef __MINGW64_VERSION_MAJOR @@ -90,7 +97,6 @@ typedef ULONG (WINAPI* pgetadaptersaddresses)(ULONG family, ULONG flags, PVOID r static pgetadaptersaddresses GetAdaptersAddresses; - static bool dllLoaded = false; static void @@ -115,6 +121,54 @@ loadDLLs(void) #endif /* __GNUC__ */ +EthernetHandleSet +EthernetHandleSet_new(void) +{ + EthernetHandleSet result = (EthernetHandleSet) GLOBAL_MALLOC(sizeof(struct sEthernetHandleSet)); + + if (result != NULL) { + result->handles = NULL; + result->nhandles = 0; + } + + return result; +} + +void +EthernetHandleSet_addSocket(EthernetHandleSet self, const EthernetSocket sock) +{ + if (self != NULL && sock != NULL) { + int i = self->nhandles++; + self->handles = (HANDLE *) realloc(self->handles, self->nhandles * sizeof(HANDLE)); + + self->handles[i] = pcap_getevent(sock->rawSocket); + } +} + +int +EthernetHandleSet_waitReady(EthernetHandleSet self, unsigned int timeoutMs) +{ + int result; + + if ((self != NULL) && (self->nhandles > 0)) { + result = WaitForMultipleObjects(self->nhandles, self->handles, 0, timeoutMs); + } + else { + result = -1; + } + + return result; +} + +void +EthernetHandleSet_destroy(EthernetHandleSet self) +{ + if (self->handles) + free(self->handles); + + GLOBAL_FREEMEM(self); +} + static char* getInterfaceName(int interfaceIndex) { @@ -215,8 +269,6 @@ getAdapterMacAddress(char* pcapAdapterName, uint8_t* macAddress) } } - - void Ethernet_getInterfaceMACAddress(const char* interfaceId, uint8_t* addr) { @@ -338,6 +390,28 @@ Ethernet_isSupported() return false; } +EthernetHandleSet +EthernetHandleSet_new(void) +{ + return NULL; +} + +void +EthernetHandleSet_addSocket(EthernetHandleSet self, const EthernetSocket sock) +{ +} + +int +EthernetHandleSet_waitReady(EthernetHandleSet self, unsigned int timeoutMs) +{ + return 0; +} + +void +EthernetHandleSet_destroy(EthernetHandleSet self) +{ +} + void Ethernet_getInterfaceMACAddress(const char* interfaceId, uint8_t* addr) { From dec12b61a80345c22b503ee8c3843a6d0274b712 Mon Sep 17 00:00:00 2001 From: Steffen Vogel Date: Sat, 18 Nov 2017 15:02:04 +0100 Subject: [PATCH 05/14] refactor: declare private functions static --- src/hal/ethernet/bsd/ethernet_bsd.c | 31 ++++++++++++++++++----------- 1 file changed, 19 insertions(+), 12 deletions(-) diff --git a/src/hal/ethernet/bsd/ethernet_bsd.c b/src/hal/ethernet/bsd/ethernet_bsd.c index 4020d9d8..fdb395d0 100644 --- a/src/hal/ethernet/bsd/ethernet_bsd.c +++ b/src/hal/ethernet/bsd/ethernet_bsd.c @@ -47,7 +47,6 @@ struct sEthernetSocket { struct bpf_program bpfProgram; // BPF filter machine code program. }; -int _Ethernet_activateBpdFilter(EthernetSocket self) struct sEthernetHandleSet { fd_set handles; int maxHandle; @@ -100,11 +99,14 @@ EthernetHandleSet_destroy(EthernetHandleSet self) GLOBAL_FREEMEM(self); } +int +activateBpdFilter(EthernetSocket self) { return ioctl(self->bpf, BIOCSETF, &self->bpfProgram); } -int _Ethernet_setBpfEthernetAddressFilter(EthernetSocket self, uint8_t *addr) +static int +setBpfEthernetAddressFilter(EthernetSocket self, uint8_t *addr) { if (addr) { @@ -115,18 +117,19 @@ int _Ethernet_setBpfEthernetAddressFilter(EthernetSocket self, uint8_t *addr) memcpy((void *)&self->bpfProgram.bf_insns[3].k, &addr[2], 4); memcpy((void *)&self->bpfProgram.bf_insns[5].k, &addr, 2); - return _Ethernet_activateBpdFilter(self); + return activateBpdFilter(self); } else { // Disable Ethernet address filter. self->bpfProgram.bf_insns[0].k = 0; - return _Ethernet_activateBpdFilter(self); + return activateBpdFilter(self); } } -int _Ethernet_setBpfEthertypeFilter(EthernetSocket self, uint16_t etherType) +static int +setBpfEthertypeFilter(EthernetSocket self, uint16_t etherType) { if (etherType) { @@ -136,14 +139,14 @@ int _Ethernet_setBpfEthertypeFilter(EthernetSocket self, uint16_t etherType) // Set protocol. self->bpfProgram.bf_insns[9].k = etherType; - return _Ethernet_activateBpdFilter(self); + return activateBpdFilter(self); } else { // Disable Ethertype filter. self->bpfProgram.bf_insns[6].k = 0; - return _Ethernet_activateBpdFilter(self); + return activateBpdFilter(self); } } @@ -336,13 +339,15 @@ Ethernet_createSocket(const char* interfaceId, uint8_t* destAddress) return self; } -void Ethernet_setProtocolFilter(EthernetSocket self, uint16_t etherType) +void +Ethernet_setProtocolFilter(EthernetSocket self, uint16_t etherType) { - if (!self || !self->bpfProgram.bf_insns || _Ethernet_setBpfEthertypeFilter(self, etherType)) + if (!self || !self->bpfProgram.bf_insns || setBpfEthertypeFilter(self, etherType)) printf("Unable to set ethertype filter!\n"); } -int Ethernet_receivePacket(EthernetSocket self, uint8_t* buffer, int bufferSize) +int +Ethernet_receivePacket(EthernetSocket self, uint8_t* buffer, int bufferSize) { // If the actual buffer is empty, make a read call to the BSP device in order to get new data. if (self->bpfEnd - self->bpfPositon < 4) @@ -388,13 +393,15 @@ int Ethernet_receivePacket(EthernetSocket self, uint8_t* buffer, int bufferSize) return 0; } -void Ethernet_sendPacket(EthernetSocket self, uint8_t* buffer, int packetSize) +void +Ethernet_sendPacket(EthernetSocket self, uint8_t* buffer, int packetSize) { // Just send the packet as it is. write(self->bpf, buffer, packetSize); } -void Ethernet_destroySocket(EthernetSocket self) +void +Ethernet_destroySocket(EthernetSocket self) { // Close the BPF device. close(self->bpf); From b6cf079a9471cc93b2ced50106c397b11871a2eb Mon Sep 17 00:00:00 2001 From: Steffen Vogel Date: Sun, 19 Nov 2017 11:01:37 +0100 Subject: [PATCH 06/14] add support for new EthernetHandleSet to SV subscriber --- src/sampled_values/sv_subscriber.c | 5 +++++ src/sampled_values/sv_subscriber.h | 14 ++++++++++++++ 2 files changed, 19 insertions(+) diff --git a/src/sampled_values/sv_subscriber.c b/src/sampled_values/sv_subscriber.c index 1a0e2583..48b0a697 100644 --- a/src/sampled_values/sv_subscriber.c +++ b/src/sampled_values/sv_subscriber.c @@ -229,6 +229,11 @@ SVReceiver_stopThreadless(SVReceiver self) self->running = false; } +void +SVReceiver_addHandleSet(SVReceiver self, EthernetHandleSet handles) +{ + return EthernetHandleSet_addSocket(handles, self->ethSocket); +} static void parseASDU(SVReceiver self, SVSubscriber subscriber, uint8_t* buffer, int length) diff --git a/src/sampled_values/sv_subscriber.h b/src/sampled_values/sv_subscriber.h index 16ae7443..d3390c20 100644 --- a/src/sampled_values/sv_subscriber.h +++ b/src/sampled_values/sv_subscriber.h @@ -213,6 +213,20 @@ SVReceiver_stopThreadless(SVReceiver self); bool SVReceiver_tick(SVReceiver self); +/* Forward declaration */ +typedef struct sEthernetHandleSet* EthernetHandleSet; + +/** + * \brief Add the receiver to a handleset for multiplexed asynchronous IO. + * + * Note: This function must only be called after SVReceiver_startThreadless(). + * + * \param[in] self The SVReceiver instance. + * \param[inout] handles The EthernetHandleSet to which the EthernetSocket of this receiver should be added. + */ +void +SVReceiver_addHandleSet(SVReceiver self, EthernetHandleSet handles); + /* * Subscriber */ From 646c9cf073ec360bbbcc53da34ed5da44d6c8093 Mon Sep 17 00:00:00 2001 From: Steffen Vogel Date: Sun, 19 Nov 2017 11:01:54 +0100 Subject: [PATCH 07/14] add support for new EthernetHandleSet to GOOSE subscriber --- src/goose/goose_receiver.c | 7 +++++++ src/goose/goose_receiver.h | 14 ++++++++++++++ 2 files changed, 21 insertions(+) diff --git a/src/goose/goose_receiver.c b/src/goose/goose_receiver.c index 0f1b5355..c99e0426 100644 --- a/src/goose/goose_receiver.c +++ b/src/goose/goose_receiver.c @@ -811,3 +811,10 @@ GooseReceiver_tick(GooseReceiver self) else return false; } + +void +GooseReceiver_addHandleSet(GooseReceiver self, EthernetHandleSet handles) +{ + return EthernetHandleSet_addSocket(handles, self->ethSocket); +} + diff --git a/src/goose/goose_receiver.h b/src/goose/goose_receiver.h index 8ba5648c..8fa77379 100644 --- a/src/goose/goose_receiver.h +++ b/src/goose/goose_receiver.h @@ -133,6 +133,20 @@ GooseReceiver_stopThreadless(GooseReceiver self); bool GooseReceiver_tick(GooseReceiver self); +/* Forward declaration */ +typedef struct sEthernetHandleSet* EthernetHandleSet; + +/** + * \brief Add the receiver to a handleset for multiplexed asynchronous IO. + * + * Note: This function must only be called after GooseReceiver_startThreadless(). + * + * \param[in] self The SVReceiver instance. + * \param[inout] handles The EthernetHandleSet to which the EthernetSocket of this receiver should be added. + */ +void +GooseReceiver_addHandleSet(GooseReceiver self, EthernetHandleSet handles); + /**@}*/ #ifdef __cplusplus From 63b6da6ae7403567643c6e435d5bbbbda733b462 Mon Sep 17 00:00:00 2001 From: Steffen Vogel Date: Sun, 19 Nov 2017 11:38:00 +0100 Subject: [PATCH 08/14] improve documentation of HandleSet_waitReady() --- src/hal/inc/hal_ethernet.h | 13 ++++++------- src/hal/inc/hal_socket.h | 13 ++++++------- 2 files changed, 12 insertions(+), 14 deletions(-) diff --git a/src/hal/inc/hal_ethernet.h b/src/hal/inc/hal_ethernet.h index 5fa6e412..dd9e7ea4 100644 --- a/src/hal/inc/hal_ethernet.h +++ b/src/hal/inc/hal_ethernet.h @@ -68,18 +68,17 @@ EthernetHandleSet_new(void); void EthernetHandleSet_addSocket(EthernetHandleSet self, const EthernetSocket sock); - /** * \brief wait for a socket to become ready * * This function is corresponding to the BSD socket select function. - * It returns the number of sockets on which data is pending or 0 if no data is pending - * on any of the monitored connections. The function will return after "timeout" ms if no - * data is pending. - * The function shall return -1 if a socket error occures. + * The function will return after \p timeoutMs ms if no data is pending. * - * \param self the EthernetHandleSet instance - * \param timeout in milliseconds (ms) + * \param self the HandleSet instance + * \param timeout in milliseconds (ms) + * \return It returns the number of sockets on which data is pending + * or 0 if no data is pending on any of the monitored connections. + * The function shall return -1 if a socket error occures. */ int EthernetHandleSet_waitReady(EthernetHandleSet self, unsigned int timeoutMs); diff --git a/src/hal/inc/hal_socket.h b/src/hal/inc/hal_socket.h index c9520579..3fddd3f2 100644 --- a/src/hal/inc/hal_socket.h +++ b/src/hal/inc/hal_socket.h @@ -71,18 +71,17 @@ Handleset_new(void); void Handleset_addSocket(HandleSet self, const Socket sock); - /** * \brief wait for a socket to become ready * * This function is corresponding to the BSD socket select function. - * It returns the number of sockets on which data is pending or 0 if no data is pending - * on any of the monitored connections. The function will return after "timeout" ms if no - * data is pending. - * The function shall return -1 if a socket error occures. + * The function will return after \p timeoutMs ms if no data is pending. * - * \param self the HandleSet instance - * \param timeout in milliseconds (ms) + * \param self the HandleSet instance + * \param timeout in milliseconds (ms) + * \return It returns the number of sockets on which data is pending + * or 0 if no data is pending on any of the monitored connections. + * The function shall return -1 if a socket error occures. */ int Handleset_waitReady(HandleSet self, unsigned int timeoutMs); From 20f654bbc3ea6ea94454790a8d61e7e667137030 Mon Sep 17 00:00:00 2001 From: Steffen Vogel Date: Sun, 19 Nov 2017 11:38:20 +0100 Subject: [PATCH 09/14] add documentation to SVReceiver_tick() --- src/sampled_values/sv_subscriber.h | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/sampled_values/sv_subscriber.h b/src/sampled_values/sv_subscriber.h index d3390c20..5f8ae98b 100644 --- a/src/sampled_values/sv_subscriber.h +++ b/src/sampled_values/sv_subscriber.h @@ -210,6 +210,15 @@ SVReceiver_startThreadless(SVReceiver self); void SVReceiver_stopThreadless(SVReceiver self); +/** + * \brief Parse SV messages if they are available. + * + * Call after reception of ethernet frame and periodically to to house keeping tasks + * + * \param self the receiver object + * + * \return true if a message was available and has been parsed, false otherwise + */ bool SVReceiver_tick(SVReceiver self); From 967e6ef5b3a68de9e40acfb2814d9598edd63c6b Mon Sep 17 00:00:00 2001 From: Steffen Vogel Date: Sun, 19 Nov 2017 13:51:48 +0100 Subject: [PATCH 10/14] use poll() instead of select() --- src/hal/ethernet/bsd/ethernet_bsd.c | 41 +++++++++++++------------ src/hal/ethernet/linux/ethernet_linux.c | 32 +++++++++---------- 2 files changed, 37 insertions(+), 36 deletions(-) diff --git a/src/hal/ethernet/bsd/ethernet_bsd.c b/src/hal/ethernet/bsd/ethernet_bsd.c index fdb395d0..51ac3901 100644 --- a/src/hal/ethernet/bsd/ethernet_bsd.c +++ b/src/hal/ethernet/bsd/ethernet_bsd.c @@ -22,7 +22,7 @@ */ #include #include -#include +#include #include #include #include @@ -48,8 +48,8 @@ struct sEthernetSocket { }; struct sEthernetHandleSet { - fd_set handles; - int maxHandle; + struct pollfd *handles; + int nhandles; }; EthernetHandleSet @@ -58,20 +58,22 @@ EthernetHandleSet_new(void) EthernetHandleSet result = (EthernetHandleSet) GLOBAL_MALLOC(sizeof(struct sEthernetHandleSet)); if (result != NULL) { - FD_ZERO(&result->handles); - result->maxHandle = -1; + result->handles = NULL; + result->nhandles = 0; } + return result; } void EthernetHandleSet_addSocket(EthernetHandleSet self, const EthernetSocket sock) { - if (self != NULL && sock != NULL && sock->bpf != -1) { - FD_SET(sock->bpf, &self->handles); - if (sock->bpf > self->maxHandle) { - self->maxHandle = sock->bpf; - } + if (self != NULL && sock != NULL) { + int i = self->nhandles++; + self->handles = realloc(self->handles, self->nhandles * sizeof(struct pollfd)); + + self->handles[i].fd = sock->bpf; + self->handles[i].events = POLLIN; } } @@ -80,25 +82,24 @@ EthernetHandleSet_waitReady(EthernetHandleSet self, unsigned int timeoutMs) { int result; - if ((self != NULL) && (self->maxHandle >= 0)) { - struct timeval timeout; - - timeout.tv_sec = timeoutMs / 1000; - timeout.tv_usec = (timeoutMs % 1000) * 1000; - result = select(self->maxHandle + 1, &self->handles, NULL, NULL, &timeout); - } else { - result = -1; + if ((self != NULL) && (self->nhandles >= 0)) { + result = poll(self->handles, self->nhandles, timeoutMs); + } + else { + result = -1; } - + return result; } void EthernetHandleSet_destroy(EthernetHandleSet self) { + if (self->nhandles) + free(self->handles); + GLOBAL_FREEMEM(self); } - int activateBpdFilter(EthernetSocket self) { diff --git a/src/hal/ethernet/linux/ethernet_linux.c b/src/hal/ethernet/linux/ethernet_linux.c index a2e3e8c9..5de14d34 100644 --- a/src/hal/ethernet/linux/ethernet_linux.c +++ b/src/hal/ethernet/linux/ethernet_linux.c @@ -23,7 +23,7 @@ #include #include -#include +#include #include #include #include @@ -42,8 +42,8 @@ struct sEthernetSocket { }; struct sEthernetHandleSet { - fd_set handles; - int maxHandle; + struct pollfd *handles; + int nhandles; }; EthernetHandleSet @@ -52,8 +52,8 @@ EthernetHandleSet_new(void) EthernetHandleSet result = (EthernetHandleSet) GLOBAL_MALLOC(sizeof(struct sEthernetHandleSet)); if (result != NULL) { - FD_ZERO(&result->handles); - result->maxHandle = -1; + result->handles = NULL; + result->nhandles = 0; } return result; @@ -62,11 +62,12 @@ EthernetHandleSet_new(void) void EthernetHandleSet_addSocket(EthernetHandleSet self, const EthernetSocket sock) { - if (self != NULL && sock != NULL && sock->rawSocket != -1) { - FD_SET(sock->rawSocket, &self->handles); - if (sock->rawSocket > self->maxHandle) { - self->maxHandle = sock->rawSocket; - } + if (self != NULL && sock != NULL) { + int i = self->nhandles++; + self->handles = realloc(self->handles, self->nhandles * sizeof(struct pollfd)); + + self->handles[i].fd = sock->rawSocket; + self->handles[i].events = POLLIN; } } @@ -75,12 +76,8 @@ EthernetHandleSet_waitReady(EthernetHandleSet self, unsigned int timeoutMs) { int result; - if ((self != NULL) && (self->maxHandle >= 0)) { - struct timeval timeout; - - timeout.tv_sec = timeoutMs / 1000; - timeout.tv_usec = (timeoutMs % 1000) * 1000; - result = select(self->maxHandle + 1, &self->handles, NULL, NULL, &timeout); + if ((self != NULL) && (self->nhandles >= 0)) { + result = poll(self->handles, self->nhandles, timeoutMs); } else { result = -1; @@ -92,6 +89,9 @@ EthernetHandleSet_waitReady(EthernetHandleSet self, unsigned int timeoutMs) void EthernetHandleSet_destroy(EthernetHandleSet self) { + if (self->nhandles) + free(self->handles); + GLOBAL_FREEMEM(self); } From 979656094d07bdbca4b7a24f701db3c1bd5059bf Mon Sep 17 00:00:00 2001 From: Steffen Vogel Date: Sun, 19 Nov 2017 13:52:55 +0100 Subject: [PATCH 11/14] add ability to remove sockets from EthernetHandleSet --- src/hal/ethernet/bsd/ethernet_bsd.c | 14 ++++++++++++++ src/hal/ethernet/linux/ethernet_linux.c | 14 ++++++++++++++ src/hal/ethernet/win32/ethernet_win32.c | 16 ++++++++++++++++ src/hal/inc/hal_ethernet.h | 9 +++++++++ 4 files changed, 53 insertions(+) diff --git a/src/hal/ethernet/bsd/ethernet_bsd.c b/src/hal/ethernet/bsd/ethernet_bsd.c index 51ac3901..3fe7fbca 100644 --- a/src/hal/ethernet/bsd/ethernet_bsd.c +++ b/src/hal/ethernet/bsd/ethernet_bsd.c @@ -77,6 +77,20 @@ EthernetHandleSet_addSocket(EthernetHandleSet self, const EthernetSocket sock) } } +void +EthernetHandleSet_removeSocket(EthernetHandleSet self, const EthernetSocket sock) +{ + if ((self != NULL) && (sock != NULL)) { + for (unsigned i = 0; i < self->nhandles; i++) { + if (self->handles[i].fd == sock->bpf) { + memmove(&self->handles[i], &self->handles[i+1], sizeof(struct pollfd) * (self->nhandles - i - 1)); + self->nhandles--; + return; + } + } + } +} + int EthernetHandleSet_waitReady(EthernetHandleSet self, unsigned int timeoutMs) { diff --git a/src/hal/ethernet/linux/ethernet_linux.c b/src/hal/ethernet/linux/ethernet_linux.c index 5de14d34..2bd069e8 100644 --- a/src/hal/ethernet/linux/ethernet_linux.c +++ b/src/hal/ethernet/linux/ethernet_linux.c @@ -71,6 +71,20 @@ EthernetHandleSet_addSocket(EthernetHandleSet self, const EthernetSocket sock) } } +void +EthernetHandleSet_removeSocket(EthernetHandleSet self, const EthernetSocket sock) +{ + if ((self != NULL) && (sock != NULL)) { + for (unsigned i = 0; i < self->nhandles; i++) { + if (self->handles[i].fd == sock->rawSocket) { + memmove(&self->handles[i], &self->handles[i+1], sizeof(struct pollfd) * (self->nhandles - i - 1)); + self->nhandles--; + return; + } + } + } +} + int EthernetHandleSet_waitReady(EthernetHandleSet self, unsigned int timeoutMs) { diff --git a/src/hal/ethernet/win32/ethernet_win32.c b/src/hal/ethernet/win32/ethernet_win32.c index e7e91100..9fb87716 100644 --- a/src/hal/ethernet/win32/ethernet_win32.c +++ b/src/hal/ethernet/win32/ethernet_win32.c @@ -145,6 +145,22 @@ EthernetHandleSet_addSocket(EthernetHandleSet self, const EthernetSocket sock) } } +void +EthernetHandleSet_removeSocket(EthernetHandleSet self, const EthernetSocket sock) +{ + if ((self != NULL) && (sock != NULL)) { + HANDLE h = pcap_getevent(socket->rawSocket); + + for (unsigned i = 0; i < self->nhandles; i++) { + if (self->handles[i] == h) { + memmove(&self->handles[i], &self->handles[i+1], sizeof(HANDLE) * (self->nhandles - i - 1)); + self->nhandles--; + return; + } + } + } +} + int EthernetHandleSet_waitReady(EthernetHandleSet self, unsigned int timeoutMs) { diff --git a/src/hal/inc/hal_ethernet.h b/src/hal/inc/hal_ethernet.h index dd9e7ea4..4efb3670 100644 --- a/src/hal/inc/hal_ethernet.h +++ b/src/hal/inc/hal_ethernet.h @@ -68,6 +68,15 @@ EthernetHandleSet_new(void); void EthernetHandleSet_addSocket(EthernetHandleSet self, const EthernetSocket sock); +/** + * \brief remove a socket from an existing handle set + * + * \param self the HandleSet instance + * \param sock the socket to add + */ +void +EthernetHandleSet_removeSocket(EthernetHandleSet self, const EthernetSocket sock); + /** * \brief wait for a socket to become ready * From 8a83b535a9b398d0eb71acf77d5de2144330a682 Mon Sep 17 00:00:00 2001 From: Steffen Vogel Date: Sun, 19 Nov 2017 14:00:07 +0100 Subject: [PATCH 12/14] install hal_ethernet.h --- CMakeLists.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/CMakeLists.txt b/CMakeLists.txt index cff01918..20762b89 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -74,6 +74,7 @@ set(API_HEADERS src/hal/inc/hal_time.h src/hal/inc/hal_thread.h src/hal/inc/hal_filesystem.h + src/hal/inc/hal_ethernet.h src/hal/inc/platform_endian.h src/common/inc/libiec61850_common_api.h src/common/inc/libiec61850_platform_includes.h From dfd077c4c290309bbb695b606dff472a1e9008c8 Mon Sep 17 00:00:00 2001 From: Steffen Vogel Date: Sun, 19 Nov 2017 14:01:41 +0100 Subject: [PATCH 13/14] declarations in for loops are only allowed in C99 --- src/hal/ethernet/bsd/ethernet_bsd.c | 3 ++- src/hal/ethernet/linux/ethernet_linux.c | 3 ++- src/hal/ethernet/win32/ethernet_win32.c | 3 ++- 3 files changed, 6 insertions(+), 3 deletions(-) diff --git a/src/hal/ethernet/bsd/ethernet_bsd.c b/src/hal/ethernet/bsd/ethernet_bsd.c index 3fe7fbca..f35d8b5d 100644 --- a/src/hal/ethernet/bsd/ethernet_bsd.c +++ b/src/hal/ethernet/bsd/ethernet_bsd.c @@ -81,7 +81,8 @@ void EthernetHandleSet_removeSocket(EthernetHandleSet self, const EthernetSocket sock) { if ((self != NULL) && (sock != NULL)) { - for (unsigned i = 0; i < self->nhandles; i++) { + unsigned i; + for (i = 0; i < self->nhandles; i++) { if (self->handles[i].fd == sock->bpf) { memmove(&self->handles[i], &self->handles[i+1], sizeof(struct pollfd) * (self->nhandles - i - 1)); self->nhandles--; diff --git a/src/hal/ethernet/linux/ethernet_linux.c b/src/hal/ethernet/linux/ethernet_linux.c index 2bd069e8..6715c526 100644 --- a/src/hal/ethernet/linux/ethernet_linux.c +++ b/src/hal/ethernet/linux/ethernet_linux.c @@ -75,7 +75,8 @@ void EthernetHandleSet_removeSocket(EthernetHandleSet self, const EthernetSocket sock) { if ((self != NULL) && (sock != NULL)) { - for (unsigned i = 0; i < self->nhandles; i++) { + unsigned i; + for (i = 0; i < self->nhandles; i++) { if (self->handles[i].fd == sock->rawSocket) { memmove(&self->handles[i], &self->handles[i+1], sizeof(struct pollfd) * (self->nhandles - i - 1)); self->nhandles--; diff --git a/src/hal/ethernet/win32/ethernet_win32.c b/src/hal/ethernet/win32/ethernet_win32.c index 9fb87716..df76eaab 100644 --- a/src/hal/ethernet/win32/ethernet_win32.c +++ b/src/hal/ethernet/win32/ethernet_win32.c @@ -151,7 +151,8 @@ EthernetHandleSet_removeSocket(EthernetHandleSet self, const EthernetSocket sock if ((self != NULL) && (sock != NULL)) { HANDLE h = pcap_getevent(socket->rawSocket); - for (unsigned i = 0; i < self->nhandles; i++) { + unsigned i; + for (i = 0; i < self->nhandles; i++) { if (self->handles[i] == h) { memmove(&self->handles[i], &self->handles[i+1], sizeof(HANDLE) * (self->nhandles - i - 1)); self->nhandles--; From 694866cf02b9a0029867f7a6564f3dac81e1ccc1 Mon Sep 17 00:00:00 2001 From: Steffen Vogel Date: Sun, 19 Nov 2017 14:08:24 +0100 Subject: [PATCH 14/14] includes without 'libiec61850' prefix wont compile installed versions of the library at '/usr/local/include/libiec61850' --- examples/goose_subscriber/goose_subscriber_example.c | 1 + src/goose/goose_receiver.h | 5 +++-- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/examples/goose_subscriber/goose_subscriber_example.c b/examples/goose_subscriber/goose_subscriber_example.c index 5d28534b..511a9cf8 100644 --- a/examples/goose_subscriber/goose_subscriber_example.c +++ b/examples/goose_subscriber/goose_subscriber_example.c @@ -7,6 +7,7 @@ */ #include "goose_receiver.h" +#include "goose_subscriber.h" #include "hal_thread.h" #include diff --git a/src/goose/goose_receiver.h b/src/goose/goose_receiver.h index 8fa77379..7d854ae0 100644 --- a/src/goose/goose_receiver.h +++ b/src/goose/goose_receiver.h @@ -24,18 +24,19 @@ #ifndef GOOSE_RECEIVER_H_ #define GOOSE_RECEIVER_H_ -#include - #ifdef __cplusplus extern "C" { #endif +#include + /** * \addtogroup goose_api_group */ /**@{*/ +typedef struct sGooseSubscriber* GooseSubscriber; typedef struct sGooseReceiver* GooseReceiver;