2017-09-11 20:51:11 +00:00
|
|
|
#include <assert.h>
|
2017-10-18 17:49:17 +00:00
|
|
|
#include <new>
|
2017-09-11 20:51:11 +00:00
|
|
|
#include <stdio.h>
|
|
|
|
#include <stdlib.h>
|
|
|
|
#include <string.h>
|
|
|
|
#include <sys/types.h>
|
|
|
|
|
2017-10-18 17:49:17 +00:00
|
|
|
#include "TracyAlloc.hpp"
|
2017-09-11 20:51:11 +00:00
|
|
|
#include "TracySocket.hpp"
|
|
|
|
|
2019-01-19 11:03:30 +00:00
|
|
|
#ifdef _WIN32
|
2019-10-10 18:29:06 +00:00
|
|
|
# ifndef NOMINMAX
|
|
|
|
# define NOMINMAX
|
|
|
|
# endif
|
2017-09-11 20:51:11 +00:00
|
|
|
# include <winsock2.h>
|
|
|
|
# include <ws2tcpip.h>
|
2019-01-19 11:03:30 +00:00
|
|
|
# ifdef _MSC_VER
|
|
|
|
# pragma warning(disable:4244)
|
|
|
|
# pragma warning(disable:4267)
|
|
|
|
# endif
|
2019-02-10 14:45:23 +00:00
|
|
|
# define poll WSAPoll
|
2017-09-11 20:51:11 +00:00
|
|
|
#else
|
2019-06-17 17:51:58 +00:00
|
|
|
# include <arpa/inet.h>
|
2017-09-11 20:51:11 +00:00
|
|
|
# include <sys/socket.h>
|
2019-11-21 01:03:32 +00:00
|
|
|
# include <sys/param.h>
|
2019-11-21 00:27:27 +00:00
|
|
|
# include <netinet/in.h>
|
2017-09-11 20:51:11 +00:00
|
|
|
# include <netdb.h>
|
|
|
|
# include <unistd.h>
|
2019-02-10 14:45:23 +00:00
|
|
|
# include <poll.h>
|
2017-09-11 20:51:11 +00:00
|
|
|
#endif
|
|
|
|
|
2017-11-02 10:31:54 +00:00
|
|
|
#ifndef MSG_NOSIGNAL
|
|
|
|
# define MSG_NOSIGNAL 0
|
|
|
|
#endif
|
|
|
|
|
2017-09-11 20:51:11 +00:00
|
|
|
namespace tracy
|
|
|
|
{
|
|
|
|
|
2019-01-19 11:03:30 +00:00
|
|
|
#ifdef _WIN32
|
2018-08-01 17:18:40 +00:00
|
|
|
typedef SOCKET socket_t;
|
|
|
|
#else
|
|
|
|
typedef int socket_t;
|
|
|
|
#endif
|
|
|
|
|
2019-01-19 11:03:30 +00:00
|
|
|
#ifdef _WIN32
|
2017-09-14 00:13:45 +00:00
|
|
|
struct __wsinit
|
2017-09-11 20:51:11 +00:00
|
|
|
{
|
2017-09-14 00:13:45 +00:00
|
|
|
__wsinit()
|
2017-09-11 20:51:11 +00:00
|
|
|
{
|
|
|
|
WSADATA wsaData;
|
|
|
|
if( WSAStartup( MAKEWORD( 2, 2 ), &wsaData ) != 0 )
|
|
|
|
{
|
|
|
|
fprintf( stderr, "Cannot init winsock.\n" );
|
|
|
|
exit( 1 );
|
|
|
|
}
|
|
|
|
}
|
2017-09-18 16:55:25 +00:00
|
|
|
};
|
|
|
|
|
2018-08-19 15:45:03 +00:00
|
|
|
void InitWinSock()
|
2017-09-18 16:55:25 +00:00
|
|
|
{
|
|
|
|
static __wsinit init;
|
|
|
|
}
|
2017-09-11 20:51:11 +00:00
|
|
|
#endif
|
|
|
|
|
2019-12-08 22:14:48 +00:00
|
|
|
|
|
|
|
enum { BufSize = 128 * 1024 };
|
|
|
|
|
2017-09-11 20:51:11 +00:00
|
|
|
Socket::Socket()
|
2019-01-29 20:56:10 +00:00
|
|
|
: m_buf( (char*)tracy_malloc( BufSize ) )
|
2018-07-15 17:34:47 +00:00
|
|
|
, m_bufPtr( nullptr )
|
2019-01-29 20:56:10 +00:00
|
|
|
, m_sock( -1 )
|
2018-07-15 17:34:47 +00:00
|
|
|
, m_bufLeft( 0 )
|
2017-09-11 20:51:11 +00:00
|
|
|
{
|
2019-01-19 11:03:30 +00:00
|
|
|
#ifdef _WIN32
|
2017-09-18 16:55:25 +00:00
|
|
|
InitWinSock();
|
|
|
|
#endif
|
2017-09-11 20:51:11 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
Socket::Socket( int sock )
|
2019-01-29 20:56:10 +00:00
|
|
|
: m_buf( (char*)tracy_malloc( BufSize ) )
|
2018-07-15 17:34:47 +00:00
|
|
|
, m_bufPtr( nullptr )
|
2019-01-29 20:56:10 +00:00
|
|
|
, m_sock( sock )
|
2018-07-15 17:34:47 +00:00
|
|
|
, m_bufLeft( 0 )
|
2017-09-11 20:51:11 +00:00
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
Socket::~Socket()
|
|
|
|
{
|
2018-07-15 17:34:47 +00:00
|
|
|
tracy_free( m_buf );
|
2017-09-11 20:51:11 +00:00
|
|
|
if( m_sock != -1 )
|
|
|
|
{
|
|
|
|
Close();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-09-21 13:43:01 +00:00
|
|
|
bool Socket::Connect( const char* addr, int port )
|
2017-09-11 20:51:11 +00:00
|
|
|
{
|
|
|
|
assert( m_sock == -1 );
|
|
|
|
|
|
|
|
struct addrinfo hints;
|
|
|
|
struct addrinfo *res, *ptr;
|
|
|
|
|
|
|
|
memset( &hints, 0, sizeof( hints ) );
|
|
|
|
hints.ai_family = AF_UNSPEC;
|
|
|
|
hints.ai_socktype = SOCK_STREAM;
|
|
|
|
|
2019-09-21 13:43:01 +00:00
|
|
|
char portbuf[32];
|
|
|
|
sprintf( portbuf, "%i", port );
|
|
|
|
|
|
|
|
if( getaddrinfo( addr, portbuf, &hints, &res ) != 0 ) return false;
|
2018-08-01 12:07:30 +00:00
|
|
|
int sock = 0;
|
2017-09-11 20:51:11 +00:00
|
|
|
for( ptr = res; ptr; ptr = ptr->ai_next )
|
|
|
|
{
|
|
|
|
if( ( sock = socket( ptr->ai_family, ptr->ai_socktype, ptr->ai_protocol ) ) == -1 ) continue;
|
2017-11-03 10:09:31 +00:00
|
|
|
#if defined __APPLE__
|
2017-11-02 10:37:10 +00:00
|
|
|
int val = 1;
|
2019-04-01 18:14:00 +00:00
|
|
|
setsockopt( sock, SOL_SOCKET, SO_NOSIGPIPE, &val, sizeof( val ) );
|
2017-11-02 10:37:10 +00:00
|
|
|
#endif
|
2017-09-11 20:51:11 +00:00
|
|
|
if( connect( sock, ptr->ai_addr, ptr->ai_addrlen ) == -1 )
|
|
|
|
{
|
2019-01-19 11:03:30 +00:00
|
|
|
#ifdef _WIN32
|
2017-09-11 20:51:11 +00:00
|
|
|
closesocket( sock );
|
|
|
|
#else
|
|
|
|
close( sock );
|
|
|
|
#endif
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
freeaddrinfo( res );
|
|
|
|
if( !ptr ) return false;
|
|
|
|
|
|
|
|
m_sock = sock;
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
void Socket::Close()
|
|
|
|
{
|
|
|
|
assert( m_sock != -1 );
|
2019-01-19 11:03:30 +00:00
|
|
|
#ifdef _WIN32
|
2017-09-11 20:51:11 +00:00
|
|
|
closesocket( m_sock );
|
|
|
|
#else
|
|
|
|
close( m_sock );
|
|
|
|
#endif
|
|
|
|
m_sock = -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
int Socket::Send( const void* _buf, int len )
|
|
|
|
{
|
|
|
|
auto buf = (const char*)_buf;
|
|
|
|
assert( m_sock != -1 );
|
|
|
|
auto start = buf;
|
|
|
|
while( len > 0 )
|
|
|
|
{
|
2017-09-22 18:02:15 +00:00
|
|
|
auto ret = send( m_sock, buf, len, MSG_NOSIGNAL );
|
2017-09-11 20:51:11 +00:00
|
|
|
if( ret == -1 ) return -1;
|
|
|
|
len -= ret;
|
|
|
|
buf += ret;
|
|
|
|
}
|
2017-10-16 18:42:53 +00:00
|
|
|
return int( buf - start );
|
2017-09-11 20:51:11 +00:00
|
|
|
}
|
|
|
|
|
2019-04-01 16:50:37 +00:00
|
|
|
int Socket::GetSendBufSize()
|
|
|
|
{
|
|
|
|
int bufSize;
|
|
|
|
#if defined _WIN32 || defined __CYGWIN__
|
2019-04-01 18:43:42 +00:00
|
|
|
int sz = sizeof( bufSize );
|
2019-04-01 16:50:37 +00:00
|
|
|
getsockopt( m_sock, SOL_SOCKET, SO_SNDBUF, (char*)&bufSize, &sz );
|
|
|
|
#else
|
2019-04-01 18:43:42 +00:00
|
|
|
socklen_t sz = sizeof( bufSize );
|
2019-04-01 16:50:37 +00:00
|
|
|
getsockopt( m_sock, SOL_SOCKET, SO_SNDBUF, &bufSize, &sz );
|
|
|
|
#endif
|
|
|
|
return bufSize;
|
|
|
|
}
|
|
|
|
|
2019-02-10 14:45:23 +00:00
|
|
|
int Socket::RecvBuffered( void* buf, int len, int timeout )
|
2018-07-15 17:34:47 +00:00
|
|
|
{
|
|
|
|
if( len <= m_bufLeft )
|
|
|
|
{
|
|
|
|
memcpy( buf, m_bufPtr, len );
|
|
|
|
m_bufPtr += len;
|
|
|
|
m_bufLeft -= len;
|
|
|
|
return len;
|
|
|
|
}
|
|
|
|
|
|
|
|
if( m_bufLeft > 0 )
|
|
|
|
{
|
|
|
|
memcpy( buf, m_bufPtr, m_bufLeft );
|
|
|
|
const auto ret = m_bufLeft;
|
|
|
|
m_bufLeft = 0;
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2019-02-10 14:45:23 +00:00
|
|
|
if( len >= BufSize ) return Recv( buf, len, timeout );
|
2018-07-15 17:34:47 +00:00
|
|
|
|
2019-02-10 14:45:23 +00:00
|
|
|
m_bufLeft = Recv( m_buf, BufSize, timeout );
|
2018-07-15 17:34:47 +00:00
|
|
|
if( m_bufLeft <= 0 ) return m_bufLeft;
|
|
|
|
|
2019-11-05 19:09:40 +00:00
|
|
|
const auto sz = len < m_bufLeft ? len : m_bufLeft;
|
2018-07-15 17:34:47 +00:00
|
|
|
memcpy( buf, m_buf, sz );
|
|
|
|
m_bufPtr = m_buf + sz;
|
|
|
|
m_bufLeft -= sz;
|
|
|
|
return sz;
|
|
|
|
}
|
|
|
|
|
2019-02-10 14:45:23 +00:00
|
|
|
int Socket::Recv( void* _buf, int len, int timeout )
|
2017-09-11 20:51:11 +00:00
|
|
|
{
|
|
|
|
auto buf = (char*)_buf;
|
2017-09-12 23:53:47 +00:00
|
|
|
|
2019-02-10 14:45:23 +00:00
|
|
|
struct pollfd fd;
|
|
|
|
fd.fd = (socket_t)m_sock;
|
|
|
|
fd.events = POLLIN;
|
2017-09-12 23:53:47 +00:00
|
|
|
|
2019-02-10 14:45:23 +00:00
|
|
|
if( poll( &fd, 1, timeout ) > 0 )
|
2017-09-12 23:53:47 +00:00
|
|
|
{
|
|
|
|
return recv( m_sock, buf, len, 0 );
|
|
|
|
}
|
|
|
|
else
|
2017-09-11 20:51:11 +00:00
|
|
|
{
|
2017-09-12 23:53:47 +00:00
|
|
|
return -1;
|
2017-09-11 20:51:11 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-02-10 14:45:23 +00:00
|
|
|
bool Socket::Read( void* _buf, int len, int timeout, std::function<bool()> exitCb )
|
2017-09-13 00:08:30 +00:00
|
|
|
{
|
|
|
|
auto buf = (char*)_buf;
|
|
|
|
|
|
|
|
while( len > 0 )
|
|
|
|
{
|
|
|
|
if( exitCb() ) return false;
|
2019-02-10 14:45:23 +00:00
|
|
|
const auto sz = RecvBuffered( buf, len, timeout );
|
2017-09-13 21:26:18 +00:00
|
|
|
switch( sz )
|
|
|
|
{
|
|
|
|
case 0:
|
|
|
|
return false;
|
|
|
|
case -1:
|
2017-09-15 19:43:57 +00:00
|
|
|
#ifdef _WIN32
|
|
|
|
{
|
|
|
|
auto err = WSAGetLastError();
|
2017-11-04 16:19:28 +00:00
|
|
|
if( err == WSAECONNABORTED || err == WSAECONNRESET ) return false;
|
2017-09-15 19:43:57 +00:00
|
|
|
}
|
|
|
|
#endif
|
2017-09-13 21:26:18 +00:00
|
|
|
break;
|
|
|
|
default:
|
|
|
|
len -= sz;
|
|
|
|
buf += sz;
|
|
|
|
break;
|
|
|
|
}
|
2017-09-13 00:08:30 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2019-02-10 14:45:23 +00:00
|
|
|
bool Socket::ReadRaw( void* _buf, int len, int timeout )
|
2018-09-09 16:24:58 +00:00
|
|
|
{
|
|
|
|
auto buf = (char*)_buf;
|
|
|
|
while( len > 0 )
|
|
|
|
{
|
2019-02-10 14:45:23 +00:00
|
|
|
const auto sz = Recv( buf, len, timeout );
|
2018-09-09 16:24:58 +00:00
|
|
|
if( sz <= 0 ) return false;
|
|
|
|
len -= sz;
|
|
|
|
buf += sz;
|
|
|
|
}
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2017-09-13 23:12:27 +00:00
|
|
|
bool Socket::HasData()
|
|
|
|
{
|
2018-07-15 17:52:22 +00:00
|
|
|
if( m_bufLeft > 0 ) return true;
|
|
|
|
|
2019-02-10 14:45:23 +00:00
|
|
|
struct pollfd fd;
|
|
|
|
fd.fd = (socket_t)m_sock;
|
|
|
|
fd.events = POLLIN;
|
2017-09-13 23:12:27 +00:00
|
|
|
|
2019-02-10 14:45:23 +00:00
|
|
|
return poll( &fd, 1, 0 ) > 0;
|
2017-09-13 23:12:27 +00:00
|
|
|
}
|
|
|
|
|
2019-12-19 16:23:40 +00:00
|
|
|
bool Socket::IsValid() const
|
|
|
|
{
|
|
|
|
return m_sock >= 0;
|
|
|
|
}
|
|
|
|
|
2017-09-11 20:51:11 +00:00
|
|
|
|
|
|
|
ListenSocket::ListenSocket()
|
|
|
|
: m_sock( -1 )
|
|
|
|
{
|
2019-01-19 11:03:30 +00:00
|
|
|
#ifdef _WIN32
|
2017-09-18 16:55:25 +00:00
|
|
|
InitWinSock();
|
|
|
|
#endif
|
2017-09-11 20:51:11 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
ListenSocket::~ListenSocket()
|
|
|
|
{
|
2019-06-09 16:14:04 +00:00
|
|
|
if( m_sock != -1 ) Close();
|
2017-09-11 20:51:11 +00:00
|
|
|
}
|
|
|
|
|
2019-09-21 13:11:15 +00:00
|
|
|
bool ListenSocket::Listen( int port, int backlog )
|
2017-09-11 20:51:11 +00:00
|
|
|
{
|
|
|
|
assert( m_sock == -1 );
|
|
|
|
|
|
|
|
struct addrinfo* res;
|
|
|
|
struct addrinfo hints;
|
|
|
|
|
|
|
|
memset( &hints, 0, sizeof( hints ) );
|
|
|
|
hints.ai_family = AF_INET6;
|
|
|
|
hints.ai_socktype = SOCK_STREAM;
|
|
|
|
hints.ai_flags = AI_PASSIVE;
|
|
|
|
|
2019-09-21 13:11:15 +00:00
|
|
|
char portbuf[32];
|
|
|
|
sprintf( portbuf, "%i", port );
|
|
|
|
|
|
|
|
if( getaddrinfo( nullptr, portbuf, &hints, &res ) != 0 ) return false;
|
2017-09-11 20:51:11 +00:00
|
|
|
|
|
|
|
m_sock = socket( res->ai_family, res->ai_socktype, res->ai_protocol );
|
2019-01-19 11:03:30 +00:00
|
|
|
#if defined _WIN32 || defined __CYGWIN__
|
2017-09-23 18:20:41 +00:00
|
|
|
unsigned long val = 0;
|
2017-09-11 20:51:11 +00:00
|
|
|
setsockopt( m_sock, IPPROTO_IPV6, IPV6_V6ONLY, (const char*)&val, sizeof( val ) );
|
2019-11-21 01:03:32 +00:00
|
|
|
#elif defined BSD
|
|
|
|
int val = 0;
|
|
|
|
setsockopt( m_sock, IPPROTO_IPV6, IPV6_V6ONLY, (const char*)&val, sizeof( val ) );
|
2019-11-21 19:38:15 +00:00
|
|
|
val = 1;
|
|
|
|
setsockopt( m_sock, SOL_SOCKET, SO_REUSEADDR, &val, sizeof( val ) );
|
2018-04-27 17:18:09 +00:00
|
|
|
#else
|
|
|
|
int val = 1;
|
|
|
|
setsockopt( m_sock, SOL_SOCKET, SO_REUSEADDR, &val, sizeof( val ) );
|
2017-09-11 20:51:11 +00:00
|
|
|
#endif
|
2019-10-27 12:39:01 +00:00
|
|
|
if( bind( m_sock, res->ai_addr, res->ai_addrlen ) == -1 ) { freeaddrinfo( res ); return false; }
|
|
|
|
if( listen( m_sock, backlog ) == -1 ) { freeaddrinfo( res ); return false; }
|
|
|
|
freeaddrinfo( res );
|
2017-09-11 20:51:11 +00:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2017-10-18 17:49:17 +00:00
|
|
|
Socket* ListenSocket::Accept()
|
2017-09-11 20:51:11 +00:00
|
|
|
{
|
|
|
|
struct sockaddr_storage remote;
|
|
|
|
socklen_t sz = sizeof( remote );
|
|
|
|
|
2019-02-10 14:45:23 +00:00
|
|
|
struct pollfd fd;
|
|
|
|
fd.fd = (socket_t)m_sock;
|
|
|
|
fd.events = POLLIN;
|
2017-09-11 20:51:11 +00:00
|
|
|
|
2019-02-10 14:45:23 +00:00
|
|
|
if( poll( &fd, 1, 10 ) > 0 )
|
2017-09-11 20:51:11 +00:00
|
|
|
{
|
|
|
|
int sock = accept( m_sock, (sockaddr*)&remote, &sz);
|
2019-04-01 18:08:27 +00:00
|
|
|
if( sock == -1 ) return nullptr;
|
|
|
|
|
2017-11-03 10:09:31 +00:00
|
|
|
#if defined __APPLE__
|
2017-11-02 10:37:10 +00:00
|
|
|
int val = 1;
|
2017-11-03 10:20:39 +00:00
|
|
|
setsockopt( sock, SOL_SOCKET, SO_NOSIGPIPE, &val, sizeof( val ) );
|
2017-11-02 10:37:10 +00:00
|
|
|
#endif
|
2019-04-01 18:08:27 +00:00
|
|
|
|
|
|
|
auto ptr = (Socket*)tracy_malloc( sizeof( Socket ) );
|
|
|
|
new(ptr) Socket( sock );
|
|
|
|
return ptr;
|
2017-09-11 20:51:11 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void ListenSocket::Close()
|
|
|
|
{
|
|
|
|
assert( m_sock != -1 );
|
2019-01-19 11:03:30 +00:00
|
|
|
#ifdef _WIN32
|
2017-09-11 20:51:11 +00:00
|
|
|
closesocket( m_sock );
|
|
|
|
#else
|
|
|
|
close( m_sock );
|
|
|
|
#endif
|
|
|
|
m_sock = -1;
|
|
|
|
}
|
|
|
|
|
2019-06-17 00:24:55 +00:00
|
|
|
UdpBroadcast::UdpBroadcast()
|
|
|
|
: m_sock( -1 )
|
|
|
|
{
|
|
|
|
#ifdef _WIN32
|
|
|
|
InitWinSock();
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
|
|
UdpBroadcast::~UdpBroadcast()
|
|
|
|
{
|
|
|
|
if( m_sock != -1 ) Close();
|
|
|
|
}
|
|
|
|
|
2019-09-21 13:11:15 +00:00
|
|
|
bool UdpBroadcast::Open( const char* addr, int port )
|
2019-06-17 00:24:55 +00:00
|
|
|
{
|
|
|
|
assert( m_sock == -1 );
|
|
|
|
|
|
|
|
struct addrinfo hints;
|
|
|
|
struct addrinfo *res, *ptr;
|
|
|
|
|
|
|
|
memset( &hints, 0, sizeof( hints ) );
|
|
|
|
hints.ai_family = AF_INET;
|
|
|
|
hints.ai_socktype = SOCK_DGRAM;
|
|
|
|
|
2019-09-21 13:11:15 +00:00
|
|
|
char portbuf[32];
|
|
|
|
sprintf( portbuf, "%i", port );
|
|
|
|
|
|
|
|
if( getaddrinfo( addr, portbuf, &hints, &res ) != 0 ) return false;
|
2019-06-17 00:24:55 +00:00
|
|
|
int sock = 0;
|
|
|
|
for( ptr = res; ptr; ptr = ptr->ai_next )
|
|
|
|
{
|
|
|
|
if( ( sock = socket( ptr->ai_family, ptr->ai_socktype, ptr->ai_protocol ) ) == -1 ) continue;
|
|
|
|
#if defined __APPLE__
|
|
|
|
int val = 1;
|
|
|
|
setsockopt( sock, SOL_SOCKET, SO_NOSIGPIPE, &val, sizeof( val ) );
|
|
|
|
#endif
|
|
|
|
#if defined _WIN32 || defined __CYGWIN__
|
|
|
|
unsigned long broadcast = 1;
|
|
|
|
if( setsockopt( sock, SOL_SOCKET, SO_BROADCAST, (const char*)&broadcast, sizeof( broadcast ) ) == -1 )
|
|
|
|
#else
|
|
|
|
int broadcast = 1;
|
|
|
|
if( setsockopt( sock, SOL_SOCKET, SO_BROADCAST, &broadcast, sizeof( broadcast ) ) == -1 )
|
|
|
|
#endif
|
|
|
|
{
|
|
|
|
#ifdef _WIN32
|
|
|
|
closesocket( sock );
|
|
|
|
#else
|
|
|
|
close( sock );
|
|
|
|
#endif
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
freeaddrinfo( res );
|
|
|
|
if( !ptr ) return false;
|
|
|
|
|
|
|
|
m_sock = sock;
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
void UdpBroadcast::Close()
|
|
|
|
{
|
|
|
|
assert( m_sock != -1 );
|
|
|
|
#ifdef _WIN32
|
|
|
|
closesocket( m_sock );
|
|
|
|
#else
|
|
|
|
close( m_sock );
|
|
|
|
#endif
|
|
|
|
m_sock = -1;
|
|
|
|
}
|
|
|
|
|
2019-06-17 16:37:34 +00:00
|
|
|
int UdpBroadcast::Send( int port, const void* data, int len )
|
2019-06-17 00:24:55 +00:00
|
|
|
{
|
|
|
|
assert( m_sock != -1 );
|
|
|
|
struct sockaddr_in addr;
|
|
|
|
addr.sin_family = AF_INET;
|
2019-06-17 16:37:34 +00:00
|
|
|
addr.sin_port = htons( port );
|
2019-06-17 00:24:55 +00:00
|
|
|
addr.sin_addr.s_addr = INADDR_BROADCAST;
|
|
|
|
return sendto( m_sock, (const char*)data, len, MSG_NOSIGNAL, (sockaddr*)&addr, sizeof( addr ) );
|
|
|
|
}
|
|
|
|
|
2019-06-17 17:23:43 +00:00
|
|
|
IpAddress::IpAddress()
|
|
|
|
: m_number( 0 )
|
|
|
|
{
|
|
|
|
*m_text = '\0';
|
|
|
|
}
|
|
|
|
|
|
|
|
IpAddress::~IpAddress()
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
void IpAddress::Set( const struct sockaddr& addr )
|
|
|
|
{
|
2019-08-04 09:00:38 +00:00
|
|
|
#if __MINGW32__
|
|
|
|
auto ai = (struct sockaddr_in*)&addr;
|
|
|
|
#else
|
2019-06-17 17:23:43 +00:00
|
|
|
auto ai = (const struct sockaddr_in*)&addr;
|
2019-08-04 09:00:38 +00:00
|
|
|
#endif
|
2019-06-26 15:58:23 +00:00
|
|
|
inet_ntop( AF_INET, &ai->sin_addr, m_text, 17 );
|
2019-06-17 17:23:43 +00:00
|
|
|
m_number = ai->sin_addr.s_addr;
|
|
|
|
}
|
|
|
|
|
|
|
|
UdpListen::UdpListen()
|
|
|
|
: m_sock( -1 )
|
|
|
|
{
|
|
|
|
#ifdef _WIN32
|
|
|
|
InitWinSock();
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
|
|
UdpListen::~UdpListen()
|
|
|
|
{
|
|
|
|
if( m_sock != -1 ) Close();
|
|
|
|
}
|
|
|
|
|
|
|
|
bool UdpListen::Listen( int port )
|
|
|
|
{
|
|
|
|
assert( m_sock == -1 );
|
|
|
|
|
|
|
|
int sock;
|
|
|
|
if( ( sock = socket( AF_INET, SOCK_DGRAM, 0 ) ) == -1 ) return false;
|
|
|
|
|
|
|
|
#if defined __APPLE__
|
|
|
|
int val = 1;
|
|
|
|
setsockopt( sock, SOL_SOCKET, SO_NOSIGPIPE, &val, sizeof( val ) );
|
|
|
|
#endif
|
|
|
|
#if defined _WIN32 || defined __CYGWIN__
|
|
|
|
unsigned long reuse = 1;
|
|
|
|
setsockopt( m_sock, SOL_SOCKET, SO_REUSEADDR, (const char*)&reuse, sizeof( reuse ) );
|
|
|
|
#else
|
|
|
|
int reuse = 1;
|
|
|
|
setsockopt( m_sock, SOL_SOCKET, SO_REUSEADDR, &reuse, sizeof( reuse ) );
|
|
|
|
#endif
|
|
|
|
#if defined _WIN32 || defined __CYGWIN__
|
|
|
|
unsigned long broadcast = 1;
|
|
|
|
if( setsockopt( sock, SOL_SOCKET, SO_BROADCAST, (const char*)&broadcast, sizeof( broadcast ) ) == -1 )
|
|
|
|
#else
|
|
|
|
int broadcast = 1;
|
|
|
|
if( setsockopt( sock, SOL_SOCKET, SO_BROADCAST, &broadcast, sizeof( broadcast ) ) == -1 )
|
|
|
|
#endif
|
|
|
|
{
|
|
|
|
#ifdef _WIN32
|
|
|
|
closesocket( sock );
|
|
|
|
#else
|
|
|
|
close( sock );
|
|
|
|
#endif
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
struct sockaddr_in addr;
|
|
|
|
addr.sin_family = AF_INET;
|
|
|
|
addr.sin_port = htons( port );
|
|
|
|
addr.sin_addr.s_addr = INADDR_ANY;
|
|
|
|
|
|
|
|
if( bind( sock, (sockaddr*)&addr, sizeof( addr ) ) == -1 )
|
|
|
|
{
|
|
|
|
#ifdef _WIN32
|
|
|
|
closesocket( sock );
|
|
|
|
#else
|
|
|
|
close( sock );
|
|
|
|
#endif
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
m_sock = sock;
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
void UdpListen::Close()
|
|
|
|
{
|
|
|
|
assert( m_sock != -1 );
|
|
|
|
#ifdef _WIN32
|
|
|
|
closesocket( m_sock );
|
|
|
|
#else
|
|
|
|
close( m_sock );
|
|
|
|
#endif
|
|
|
|
m_sock = -1;
|
|
|
|
}
|
|
|
|
|
2019-06-22 12:08:48 +00:00
|
|
|
const char* UdpListen::Read( size_t& len, IpAddress& addr )
|
2019-06-17 17:23:43 +00:00
|
|
|
{
|
|
|
|
static char buf[2048];
|
|
|
|
|
|
|
|
struct pollfd fd;
|
|
|
|
fd.fd = (socket_t)m_sock;
|
|
|
|
fd.events = POLLIN;
|
|
|
|
if( poll( &fd, 1, 10 ) <= 0 ) return nullptr;
|
|
|
|
|
|
|
|
sockaddr sa;
|
|
|
|
socklen_t salen = sizeof( struct sockaddr );
|
2019-06-22 12:08:48 +00:00
|
|
|
len = (size_t)recvfrom( m_sock, buf, 2048, 0, &sa, &salen );
|
2019-06-17 17:23:43 +00:00
|
|
|
addr.Set( sa );
|
|
|
|
|
|
|
|
return buf;
|
|
|
|
}
|
|
|
|
|
2017-09-11 20:51:11 +00:00
|
|
|
}
|