#include "SimpleUDPPeer.h" #include #include #include #include #include #include #include #include #include #include struct AsyncStub { pthread_t async_recv_thid; SimpleUDPPeer& sock; SimpleUDPPeer::proc_func_t proc; bool running; void* args; static AsyncStub* m_this; AsyncStub(SimpleUDPPeer& _sock) : async_recv_thid(0), sock(_sock), proc(nullptr), running(false), args(nullptr) { m_this = this; } bool start() { if (async_recv_thid != 0) return false; running = true; int ret = pthread_create(&async_recv_thid, NULL, async_recv_thd, this); if(ret != 0) return false; } void stop() { running = false; //#todo join thread } static void* async_recv_thd(void* arg) { AsyncStub* stub = (AsyncStub*)arg; uint8_t* buffer = new uint8_t[stub->sock.cfg.maxBuffSize]; size_t buffSize = 0; while (stub->running) { buffSize = stub->sock.cfg.maxBuffSize; bool ret = stub->sock.recv_sync(buffer, buffSize); if (ret && stub->proc != nullptr) stub->proc(m_this->args, buffer, buffSize); } delete[] buffer; buffer = nullptr; } }; SimpleUDPPeer::SimpleUDPPeer() : cfg(), remote_address(), fd(-1), asyncStub(nullptr) { } SimpleUDPPeer::~SimpleUDPPeer() { //#todo dlete asyncStub // close fd } void SimpleUDPPeer::set_config(const Config& _cfg) { cfg = _cfg; } const SimpleUDPPeer::Config& SimpleUDPPeer::get_config() const { } bool SimpleUDPPeer::init() { if (fd != -1) return false; memset(&local_address, sizeof(local_address), 0); local_address.sin_family = AF_INET; if (cfg.local_ip.empty()) local_address.sin_addr.s_addr = htonl(INADDR_ANY); else local_address.sin_addr.s_addr = inet_addr(cfg.local_ip.c_str()); local_address.sin_port = htons(cfg.local_port); memset(&remote_address, sizeof(remote_address), 0); remote_address.sin_family = AF_INET; remote_address.sin_addr.s_addr = inet_addr(cfg.remote_ip.c_str()); remote_address.sin_port = htons(cfg.remote_port); socklen_t sin_len = sizeof(sockaddr_in); fd = socket(AF_INET, SOCK_DGRAM, 0); if (fd <= 0) return false; if (cfg.defaultTimeout.tv_sec != 0 || cfg.defaultTimeout.tv_usec != 0) { int ret = setsockopt(fd, SOL_SOCKET, SO_RCVTIMEO, (const char *) &(cfg.defaultTimeout), sizeof(timeval)); if (ret != 0) return false; } int ret = bind(fd, (struct sockaddr *)&local_address, sizeof(local_address)); if (ret != 0) return false; return true; } void SimpleUDPPeer::teardown() { } bool SimpleUDPPeer::send_sync(const uint8_t* buffer, size_t& buffSize) { if (fd == -1) return -1; ssize_t ret = sendto(fd, buffer, buffSize, 0, (struct sockaddr *)&remote_address, sizeof(remote_address)); if (ret <= 0) { buffSize = 0; return false; } else { buffSize = ret; return true; } } bool SimpleUDPPeer::recv_sync(uint8_t* buffer, size_t& buffSize) { if (fd == -1) return -1; ssize_t ret = recv(fd, buffer, buffSize, 0); int _errno = errno; if(ret <= 0) { buffSize = 0; return false; } else { buffSize = ret; return true; } } bool SimpleUDPPeer::recv_async_start(proc_func_t proc, void* args) { if (asyncStub == nullptr) asyncStub = new AsyncStub(*this); asyncStub->args = args; asyncStub->proc = proc; return asyncStub->start(); } void SimpleUDPPeer::recv_async_stop() { if (asyncStub == nullptr) asyncStub = new AsyncStub(*this); asyncStub->stop(); }