#include "tnplib.h"
#include <cstring>
#include <cstdlib>
#ifdef _DEBUG
#include <iostream>
#endif
#ifndef unix
#define socklen_t int
#else
#define closesocket close
#define ioctlsocket ioctl
#endif
int SocketLibStart() {
#ifdef WIN32
WSADATA wsaData;
return( WSAStartup(0x0101, &wsaData) );
#else
return(0);
#endif
}
void SocketLibEnd() {
#ifdef WIN32
WSACleanup();
#endif
}
SOCKET TCPStartServer(const int port, const int queue, const int reuse) {
struct sockaddr_in sad;
SOCKET sd;
memset((char *)&sad,0,sizeof(sad));
sad.sin_family = AF_INET;
sad.sin_addr.s_addr = htonl(INADDR_ANY);
sad.sin_port = htons((u_short)port);
sd = socket(PF_INET, SOCK_STREAM, 0);
if (int(sd)<0) {
#ifdef _DEBUG
std::cerr << "socket creation failed" << std::endl;
#endif
return(-1);
}
if (reuse!=0 && setsockopt(sd,SOL_SOCKET,SO_REUSEADDR,(char*)&reuse,sizeof(reuse)) <0 ) {
#ifdef _DEBUG
std::cerr << "reuse address option failed" << std::endl;
#endif
return(-1);
}
if (bind(sd, (struct sockaddr *)&sad, sizeof(sad)) < 0) {
#ifdef _DEBUG
std::cerr << "bind failed" << std::endl;
#endif
return(-1);
}
if (listen(sd, queue) < 0) {
#ifdef _DEBUG
std::cerr << "listen failed" << std::endl;
#endif
return(-1);
}
return(sd);
}
SOCKET TCPWaitForConnection(SOCKET sd) {
struct sockaddr_in cad;
socklen_t alen;
alen = sizeof(cad);
return( accept(sd, (struct sockaddr *)&cad, &alen) );
}
int TCPStopServerTCP(SOCKET sd) {
return( closesocket(sd) );
}
SOCKET TCPStartClient(const char *host, const char *port) {
struct addrinfo addr_req;
struct addrinfo *addr_res;
int sd;
memset(&addr_req, 0, sizeof(addr_req));
addr_req.ai_socktype = SOCK_STREAM;
addr_req.ai_family = AF_INET;
if (0 != getaddrinfo(host, port, &addr_req, &addr_res)) {
#ifdef _DEBUG
std::cerr << "cannot set up the destination address" << std::endl;
#endif
return(-1);
}
sd = (int)socket(addr_res->ai_family, addr_res->ai_socktype, addr_res->ai_protocol);
if (sd < 0) {
#ifdef _DEBUG
std::cerr << "socket creation failed" << std::endl;
#endif
freeaddrinfo(addr_res);
return(-1);
}
if (connect(sd, addr_res->ai_addr, addr_res->ai_addrlen) < 0) {
#ifdef _DEBUG
std::cerr << "connection failed" << std::endl;
#endif
freeaddrinfo(addr_res);
return(-1);
}
freeaddrinfo(addr_res);
return(sd);
}
int TCPStopClient(SOCKET sd) {
return( closesocket(sd) );
}
int TCPSetTTL(SOCKET sd, int ttl) {
return( setsockopt(sd,IPPROTO_IP,IP_TTL,(const char*)&ttl,sizeof(ttl)) );
}
int TCPSetTimeout(SOCKET sd, int tout) {
return( setsockopt(sd,SOL_SOCKET,SO_RCVTIMEO,(char*)&tout,sizeof(tout)) );
}
int TCPSetFragment(SOCKET sd, int isOk) {
return(0);
}
int TCPSetSocketReuse(SOCKET sd, int isOk) {
return(setsockopt(sd, SOL_SOCKET, SO_REUSEADDR, (char*)&isOk, sizeof(isOk)));
}
int TCPSetNoDelay(SOCKET sd, int isOk) {
#ifdef TCP_NODELAY
return( setsockopt(sd,IPPROTO_TCP,TCP_NODELAY,(char*)&isOk,sizeof(isOk)) );
#else
#ifdef _DEBUG
std::cerr << "TCP_NODELAY not supported by this platform - option ignored" << std::endl;
#endif
#endif
return(0);
}
int TCPPrepClose(SOCKET sd) {
return( shutdown(sd,SD_BOTH) );
}
int TCPRecvAny(SOCKET sd, char *buffer, const int maxsize) {
return( recv(sd,buffer,maxsize,0) );
}
int TCPRecvLine(SOCKET sd, char *line, const int maxsize) {
int status;
int len=0;
char bch;
while (1) {
status = recv(sd,&bch,1,0);
if (status<0) return(status);
if (len>=maxsize) return(-1);
if (bch=='\n')
{
line[len]='\0';
return(len);
}
else if (bch=='\r')
{
}
else
{
line[len]=bch;
len++;
}
}
}
int TCPRecvDumpLine(SOCKET sd) {
int status;
int len=0;
char bch;
while (1) {
status = recv(sd,&bch,1,0);
if (status<0) return(status);
if (bch=='\n') return(len);
if (bch!='\r') len++;
}
}
int TCPSendAny(SOCKET sd, const char *buffer, int size) {
return( send(sd,buffer,size,0) );
}
int TCPSendLine(SOCKET sd, const char *line) {
return( send(sd,line,int(strlen(line)),0) );
}
SOCKET UDPStartServer(const int port) {
return( UDPStartMServer(port, 0) );
}
SOCKET UDPStartMServer(const int port, int multiple) {
struct sockaddr_in sad;
SOCKET sd;
sd = socket(PF_INET, SOCK_DGRAM, 0);
if (int(sd)<0) {
#ifdef _DEBUG
std::cerr << "socket creation failed" << std::endl;
#endif
return(-1);
}
if (multiple!=0 && setsockopt(sd,SOL_SOCKET,SO_REUSEADDR,(char*) &multiple,sizeof(multiple)) <0 ) {
#ifdef _DEBUG
std::cerr << "reuse address option failed" << std::endl;
#endif
return(-1);
}
memset((char*)&sad,0,sizeof(sad));
sad.sin_family = AF_INET;
sad.sin_addr.s_addr = htonl(INADDR_ANY);
sad.sin_port = htons((u_short)port);
if (bind(sd, (struct sockaddr *)&sad, sizeof(sad)) < 0) {
#ifdef _DEBUG
std::cerr << "bind failed" << std::endl;
#endif
return(-1);
}
return(sd);
}
int UDPStopServer(SOCKET sd) {
return( closesocket(sd) );
}
SOCKET UDPStartClient() {
SOCKET sd;
sd=socket(PF_INET,SOCK_DGRAM,0);
if (int(sd)<0) {
#ifdef _DEBUG
std::cerr << "socket creation failed" << std::endl;
#endif
return(-1);
}
return(sd);
}
int UDPStopClient(SOCKET sd) {
return( closesocket(sd) );
}
int UDPSetTTL(SOCKET sd, int ttl) {
return( setsockopt(sd,IPPROTO_IP,IP_TTL,(const char*)&ttl,sizeof(ttl)) );
}
int UDPSetTimeout(SOCKET sd, int tout) {
return( setsockopt(sd,SOL_SOCKET,SO_RCVTIMEO,(char*)&tout,sizeof(tout)) );
}
int UDPSetFragment(SOCKET sd, int isOk) {
return(0);
}
int UDPSetSocketReuse(SOCKET sd, int isOk) {
return( setsockopt(sd,SOL_SOCKET,SO_REUSEADDR,(char*) &isOk,sizeof(isOk)) );
}
int UDPPrepClose(SOCKET sd) {
return( shutdown(sd,SD_BOTH) );
}
int UDPMulticastSetTTL(SOCKET sd, int ttl) {
return( setsockopt(sd,IPPROTO_IP,IP_MULTICAST_TTL,(char*) &ttl,sizeof(ttl)) );
}
int UDPMulticastJoin(SOCKET sd, const char* address) {
struct ip_mreq mreq;
inet_pton(AF_INET, address, &mreq.imr_multiaddr.s_addr);
mreq.imr_interface.s_addr = htonl(INADDR_ANY);
if(!IN_MULTICAST(ntohl(mreq.imr_multiaddr.s_addr))) {
#ifdef _DEBUG
std::cerr << "invalid multicast address: " << address << std::endl;
#endif
return(-1);
}
return( setsockopt(sd, IPPROTO_IP, IP_ADD_MEMBERSHIP, (char*)&mreq, sizeof(mreq)) );
}
int UDPMulticastDrop(SOCKET sd, const char* address) {
struct ip_mreq mreq;
inet_pton(AF_INET, address, &mreq.imr_multiaddr.s_addr);
mreq.imr_interface.s_addr = htonl(INADDR_ANY);
if(!IN_MULTICAST(ntohl(mreq.imr_multiaddr.s_addr))) {
#ifdef _DEBUG
std::cerr << "invalid multicast address: " << address << std::endl;
#endif
return(-1);
}
return( setsockopt(sd, IPPROTO_IP, IP_DROP_MEMBERSHIP, (char*)&mreq, sizeof(mreq)) );
}
int UDPRecvAny(SOCKET sd, char *buffer, const int maxsize, sockaddr_in* remoteaddr) {
socklen_t alen = sizeof(*remoteaddr);
return( recvfrom(sd,buffer,maxsize,0,(sockaddr *)remoteaddr,&alen) );
}
int UDPSendAny(SOCKET sd, const char *buffer, int size, const sockaddr_in* remoteaddr) {
socklen_t alen = sizeof(*remoteaddr);
return( sendto(sd,buffer,size,0,(sockaddr *)remoteaddr,alen) );
}
void CreateAddress(const char* address, const char *port, sockaddr_in * sad) {
struct addrinfo addr_req;
memset(&addr_req, 0, sizeof(addr_req));
addr_req.ai_family = AF_INET;
addr_req.ai_socktype = SOCK_DGRAM;
struct addrinfo* addr_res;
getaddrinfo(address, port, &addr_req, &addr_res);
memcpy(sad, addr_res->ai_addr, addr_res->ai_addrlen );
}