You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
Modelbahn/z21emu/udp.cc

184 lines
3.7 KiB

/*
*
*/
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <stdio.h>
#include <unistd.h> /* close() */
#include <string.h> /* memset() */
#include "udp.h"
char dnsip[NET_HOSTLEN];
int dns_filladdr (string host, string port, int ai_family, struct sockaddr_in *sAddr) {
struct addrinfo hints, *res;
int err;
/* we have to complete the sAddr struct */
bzero (&hints, sizeof (struct addrinfo));
hints.ai_family = ai_family;
hints.ai_socktype = SOCK_DGRAM;
if ((err = getaddrinfo (host.c_str(), port.c_str(), &hints, &res)) < 0) {
fprintf (stdout, "dns_filladdr (getaddrinfo):%s\n", gai_strerror (err));
return -1;
}
memcpy (sAddr, res->ai_addr, res->ai_addrlen);
freeaddrinfo (res);
return 1;
};
UDPConnection::UDPConnection() {
sock = -1;
port = "";
writecnt = 0;
readcnt = 0;
};
UDPConnection::~UDPConnection() {
Close();
}
void UDPConnection::Close () {
if (sock > -1) close (sock);
sock = -1;
}
int UDPConnection::Listen(int port) {
struct sockaddr_in servAddr;
/* socket creation */
if ((sock = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
printf("%s: socket error: %s \n",__FUNCTION__, strerror(errno));
return 0;
}
/* bind local server port */
servAddr.sin_family = AF_INET;
servAddr.sin_addr.s_addr = htonl(INADDR_ANY);
servAddr.sin_port = htons(port);
if (bind (sock, (struct sockaddr *) &servAddr,sizeof(servAddr)) < 0) {
printf("%s: bind error: %s \n",__FUNCTION__, strerror(errno));
return 0;
}
return 1;
}
int UDPConnection::Listen(string port) {
return Listen (atoi(port.c_str()));
}
long int UDPConnection::ReadTimeout(string *source, char *buffer, long int len, int timeout) {
int i;
i = isData(timeout);
if (i > 0) {
return Read (source, buffer, len);
}
else
return i;
}
long int UDPConnection::Read(string *source, char *buffer, long int len) {
int n;
socklen_t addrlen;
sockaddr_in srcAddr;
if (!isListen()) return -1;
memset(buffer, 0x0, len);
addrlen = sizeof(srcAddr);
n = recvfrom(sock, buffer, len, 0, (sockaddr *) &srcAddr, &addrlen);
if(n<0) {
printf("%s: recvfrom error:%s\n",__FUNCTION__, strerror(errno));
return -1;
}
/* print received message */
char addr[NET_HOSTLEN];
snprintf (addr, NET_HOSTLEN, "%s:%d", inet_ntoa(srcAddr.sin_addr), ntohs(srcAddr.sin_port));
(*source) = (char*)addr;
return n;
}
long int UDPConnection::Send(string destaddr, char *buffer, long int len) {
int s;
int addrlen = sizeof (struct sockaddr_in);
sockaddr_in dstAddr;
string host;
string port;
if (!isListen()) {
/* socket creation */
if ((s = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
printf("%s: socket error: %s \n",__FUNCTION__, strerror(errno));
return -1;
}
}
else s = sock;
int pos = destaddr.rfind(':', destaddr.length());
if (pos == -1) {
port = "NET_PORT";
host = destaddr;
}
else {
port = destaddr.substr (pos+1, destaddr.length() - pos);
host = destaddr.substr (0, pos);
}
dns_filladdr (host, port, PF_INET, &dstAddr);
if (sendto (s, buffer, len, 0, (sockaddr *) &dstAddr, addrlen) == -1) {
printf("%s: sendto error: %s \n",__FUNCTION__, strerror(errno));
return -1;
}
if (!isListen()) close (s);
return 1;
}
int UDPConnection::isListen() {
return (sock != -1);
}
int UDPConnection::isData(int timeout) {
fd_set sockset;
struct timeval tval;
if (sock <= 0) {
printf ("isData:socket error\n");
return -1;
}
FD_ZERO (&sockset);
FD_SET (sock, &sockset);
tval.tv_sec = timeout / 1000;
tval.tv_usec = (timeout % 1000);
if (select (sock + 1, &sockset, NULL, NULL, &tval) >= 0) {
if (FD_ISSET (sock, &sockset)) {
return 1;
}
}
return 0;
}