#include "SimpleUDPPeer.h"
|
|
#include <stdio.h>
|
#include <stdlib.h>
|
#include <string.h>
|
#include <errno.h>
|
#include <sys/socket.h>
|
#include <netinet/in.h>
|
#include <arpa/inet.h>
|
#include <netdb.h>
|
#include <unistd.h>
|
|
#include <pthread.h>
|
|
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();
|
}
|