diff --git a/include/mav/MessageSet.h b/include/mav/MessageSet.h index b87da1c..39fd23a 100644 --- a/include/mav/MessageSet.h +++ b/include/mav/MessageSet.h @@ -44,6 +44,9 @@ #include "rapidxml/rapidxml.hpp" #include "rapidxml/rapidxml_utils.hpp" +// Hack to avoid filesystem issues on windows +#define _NO_STD_FILESYSTEM + #ifdef _LIBCPP_VERSION #if _LIBCPP_VERSION < 11000 #define _NO_STD_FILESYSTEM diff --git a/include/mav/TCPClient.h b/include/mav/TCPClient.h index 5eacce2..ade1d8f 100644 --- a/include/mav/TCPClient.h +++ b/include/mav/TCPClient.h @@ -35,13 +35,20 @@ #ifndef LIBMAVLINK_TCP_H #define LIBMAVLINK_TCP_H -#include -#include -#include +#include +#include +#include +#include /* For O_RDWR */ +#include /* For open(), creat() */ +#include + +// #include +// #include +// #include #include #include #include -#include +// #include #include "Network.h" namespace mav { @@ -84,7 +91,7 @@ namespace mav { void stop() { _should_terminate.store(true); if (_socket >= 0) { - ::shutdown(_socket, SHUT_RDWR); + ::shutdown(_socket, SD_BOTH); ::close(_socket); _socket = -1; } diff --git a/include/mav/TCPServer.h b/include/mav/TCPServer.h index 80107d0..81d4421 100644 --- a/include/mav/TCPServer.h +++ b/include/mav/TCPServer.h @@ -34,21 +34,28 @@ #ifndef LIBMAVLINK_TCPSERVER_H #define LIBMAVLINK_TCPSERVER_H -#include -#include -#include -#include -#include +/* clang-format off */ +#include +#include +/* clang-format on */ +#include + +#include "poll.h" +// #include +// #include +// #include +#include #include + +#include #include + #include "Network.h" -#include namespace mav { class TCPServer : public mav::NetworkInterface { - - private: + private: mutable std::atomic_bool _should_terminate{false}; int _master_socket = -1; mutable std::mutex _client_sockets_mutex; @@ -106,19 +113,22 @@ namespace mav { public: TCPServer(int port) { + WSADATA wsaData; + WSAStartup(MAKEWORD(1, 0), &wsaData); _master_socket = socket(AF_INET, SOCK_STREAM, 0); if (_master_socket < 0) { throw NetworkError("Could not create socket: " + std::to_string(_master_socket)); } // Mark socket as non-blocking - if (fcntl(_master_socket, F_SETFL, O_NONBLOCK) < 0) { + u_long mode = 1; // 1 to enable non-blocking socket + if (ioctlsocket(_master_socket, FIONBIO, &mode) < 0) { ::close(_master_socket); throw NetworkError("Could not set socket to non-blocking", errno); } - const int enable = 1; - if (setsockopt(_master_socket, SOL_SOCKET, SO_REUSEADDR, &enable, sizeof(int)) < 0) { + const char enable = 1; + if (setsockopt(_master_socket, SOL_SOCKET, SO_REUSEADDR, &enable, sizeof(char))) { ::close(_master_socket); throw NetworkError("Could not set socket options", errno); } @@ -144,14 +154,14 @@ namespace mav { _should_terminate.store(true); if (_master_socket >= 0) { _removeFd(_master_socket); - ::shutdown(_master_socket, SHUT_RDWR); + ::shutdown(_master_socket, SD_BOTH); ::close(_master_socket); _master_socket = -1; } std::lock_guard lock(_client_sockets_mutex); for (auto client_socket : _partner_to_fd) { _removeFd(client_socket.second); - ::shutdown(client_socket.second, SHUT_RDWR); + ::shutdown(client_socket.second, SD_BOTH); ::close(client_socket.second); } _partner_to_fd.clear(); @@ -276,6 +286,7 @@ namespace mav { virtual ~TCPServer() { stop(); + WSACleanup(); } }; diff --git a/include/mav/UDPClient.h b/include/mav/UDPClient.h index 4c3e7bd..2d9f6a3 100644 --- a/include/mav/UDPClient.h +++ b/include/mav/UDPClient.h @@ -35,9 +35,20 @@ #ifndef LIBMAVLINK_UDPCLIENT_H #define LIBMAVLINK_UDPCLIENT_H -#include -#include -#include +#include +#include +#include +#include +#include +#include + +// #include +// #include +// #include + +// #include +// #include +// #include #include #include #include @@ -86,7 +97,7 @@ namespace mav { void stop() { _should_terminate.store(true); if (_socket >= 0) { - ::shutdown(_socket, SHUT_RDWR); + ::shutdown(_socket, SD_BOTH); ::close(_socket); _socket = -1; } @@ -101,7 +112,7 @@ namespace mav { while (_bytes_available < size && !_should_terminate.load()) { // If there are residual bytes from last packet, but not enough for parsing new packet, clear out _bytes_available = 0; - ssize_t ret = ::recvfrom(_socket, _rx_buffer.data(), RX_BUFFER_SIZE, 0, + ssize_t ret = ::recvfrom(_socket, (char*)_rx_buffer.data(), RX_BUFFER_SIZE, 0, (struct sockaddr *) nullptr, nullptr); if (ret < 0) { throw NetworkError("Could not receive from socket", errno); @@ -121,7 +132,7 @@ namespace mav { void send(const uint8_t *data, uint32_t size, ConnectionPartner) override { // no need to specify target here, as we called the udp connect function in constructor - if (sendto(_socket, data, size, 0, (struct sockaddr *) nullptr, 0) < 0) { + if (sendto(_socket, (const char*)data, size, 0, (struct sockaddr *) nullptr, 0) < 0) { throw NetworkError("Could not send to socket", errno); } } diff --git a/include/mav/UDPServer.h b/include/mav/UDPServer.h index 70eaf17..b5a4fa0 100644 --- a/include/mav/UDPServer.h +++ b/include/mav/UDPServer.h @@ -35,11 +35,13 @@ #ifndef LIBMAVLINK_UDPSERVER_H #define LIBMAVLINK_UDPSERVER_H -#include -#include -#include +#include +// #include +// #include +// #include #include #include +#include #include #include #include @@ -79,7 +81,7 @@ namespace mav { void stop() const { _should_terminate.store(true); if (_socket >= 0) { - ::shutdown(_socket, SHUT_RDWR); + ::shutdown(_socket, SD_BOTH); ::close(_socket); } } @@ -95,7 +97,7 @@ namespace mav { _bytes_available = 0; struct sockaddr_in source_address{}; socklen_t source_address_length = sizeof(source_address); - ssize_t ret = ::recvfrom(_socket, _rx_buffer.data(), RX_BUFFER_SIZE, 0, + ssize_t ret = ::recvfrom(_socket, (char*)_rx_buffer.data(), RX_BUFFER_SIZE, 0, (struct sockaddr*)&source_address, &source_address_length); if (ret < 0) { throw NetworkError("Could not receive from socket", errno); @@ -130,7 +132,7 @@ namespace mav { server_address.sin_port = target.port(); server_address.sin_addr.s_addr = target.address(); - if (sendto(_socket, data, size, 0, (struct sockaddr *) &server_address, sizeof(server_address)) < 0) { + if (sendto(_socket, (const char*)data, size, 0, (struct sockaddr *) &server_address, sizeof(server_address)) < 0) { ::close(_socket); throw NetworkError("Could not send to socket", errno); } diff --git a/include/mav/poll.h b/include/mav/poll.h new file mode 100644 index 0000000..6e895f1 --- /dev/null +++ b/include/mav/poll.h @@ -0,0 +1,63 @@ +#ifndef __POLL_H +#define __POLL_H + +#include +#include + +#include +#define POLLIN 0x0001 +#define POLLPRI 0x0002 /* not used */ +#define POLLOUT 0x0004 +#define POLLERR 0x0008 +#define POLLHUP 0x0010 /* not used */ +#define POLLNVAL 0x0020 /* not used */ + +struct pollfd { +int fd; +int events = 0; /* in param: what to poll for */ +int revents = 0; /* out param: what events occured */ +}; + +int poll (struct pollfd *p, int num, int timeout) +{ + struct timeval tv; + fd_set read, write, except; + int i, n, ret; + + FD_ZERO(&read); + FD_ZERO(&write); + FD_ZERO(&except); + + n = -1; + for (i = 0; i < num; i++) { + if (p[i].fd < 0) continue; + if (p[i].events & POLLIN) FD_SET(p[i].fd, &read); + if (p[i].events & POLLOUT) FD_SET(p[i].fd, &write); + if (p[i].events & POLLERR) FD_SET(p[i].fd, &except); + if (p[i].fd > n) n = p[i].fd; + } + + if (n == -1) return (0); + + if (timeout < 0) + ret = select(n + 1, &read, &write, &except, NULL); + else { + tv.tv_sec = timeout / 1000; + tv.tv_usec = 1000 * (timeout % 1000); + ret = select(n + 1, &read, &write, &except, &tv); + } + + for (i = 0; ret >= 0 && i < num; i++) { + p[i].revents = 0; + if (FD_ISSET(p[i].fd, &read)) p[i].revents |= POLLIN; + if (FD_ISSET(p[i].fd, &write)) p[i].revents |= POLLOUT; + if (FD_ISSET(p[i].fd, &except)) p[i].revents |= POLLERR; + } + return (ret); +}; + +int read(int one, uint8_t two, int three) { + return 0; +} + +#endif /* __POLL_H */ diff --git a/tests/MessageSet.cpp b/tests/MessageSet.cpp index 6bfecfc..46093ed 100644 --- a/tests/MessageSet.cpp +++ b/tests/MessageSet.cpp @@ -1,7 +1,6 @@ // // Created by thomas on 01.02.23. // -#include #include "doctest.h" #include "mav/MessageSet.h" #include "minimal.h" @@ -17,7 +16,7 @@ std::string dump_minimal_xml() { std::ofstream out(xml_file); out << minimal_xml; out.close(); - return xml_file; + return xml_file.u8string(); } TEST_CASE("Message set creation") {