spdxl/src/tcp.c

244 wiersze
5.0 KiB
C

/*
* dxlAPRS toolchain
*
* Copyright (C) Christian Rabler <oe5dxl@oevsv.at>
*
* SPDX-License-Identifier: GPL-2.0+
*/
//#define _GNU_SOURCE
#include <sys/socket.h>
#include <sys/types.h>
#include <arpa/inet.h>
#include <string.h>
#include <stdlib.h>
#include <fcntl.h>
#include <netdb.h>
#include <errno.h>
#include <sys/ioctl.h>
#include <unistd.h>
#include <netinet/tcp.h>
#ifndef MSG_MORE
#define MSG_MORE 0
#endif
#ifndef MSG_NOSIGNAL
#define MSG_NOSIGNAL 0
#endif
//--------------------
int resolv(char *url, int *host)
{
struct hostent *h;
h=gethostbyname(url);
if ((h==0) || (h->h_addr_list==0)) return -1;
memcpy(host, *(h->h_addr_list), 4);
return 0;
}
//--------------------
int opentcp()
{
return socket(PF_INET, SOCK_STREAM, 0);
}
int tcpconnect(int fd, int toport, int toip)
{
//struct sockaddr addr;
//memset(&addr, 0, sizeof(addr));
//addr.sa_family = AF_INET;
//addr.sa_port=htons(toport);
//addr.sa_addr.s_addr=htonl(toip);
//return sendto(fd, buf, blen, 0, (struct sockaddr *) &addr, sizeof(addr));
}
//--------------------
/*
int connectto1(char *url, char *port)
{
struct gaicb req;
struct addrinfo *rp;
int sockfd;
memset(&req, 0, sizeof req);
req.ar_name = url;
if (getaddrinfo_a(GAI_WAIT, &req, 1, NULL) != 0) return -1;
usleep(5000000);
if (gai_error(&req != 0)) return -1;
for (rp = req.ar_result; rp != NULL; rp = rp->ai_next) {
sockfd = socket(rp->ai_family, rp->ai_socktype, rp->ai_protocol);
if (sockfd<0) continue;
int flags=fcntl(sockfd, F_GETFL, 0);
if (flags<0) return -1;
flags|=O_NONBLOCK;
fcntl(sockfd, F_SETFL, flags);
if (connect(sockfd, rp->ai_addr, rp->ai_addrlen) < 0) break;
close(sockfd);
}
freeaddrinfo(req.ar_result);
if (rp = NULL) return -1;
return sockfd;
}
*/
//--------------------
int connectto(char *url, char *port)
{
struct addrinfo hints, *res, *rp;
int sockfd;
memset(&hints, 0, sizeof hints);
hints.ai_family = AF_UNSPEC;
hints.ai_socktype = SOCK_STREAM;
if (getaddrinfo(url, port, &hints, &res) != 0) return -1;
// if (res == 0) return -1;
for (rp = res; rp != NULL; rp = rp->ai_next) {
sockfd = socket(rp->ai_family, rp->ai_socktype, rp->ai_protocol);
if (sockfd<0) continue;
//nodelay
int flag_TCP_nodelay = 1;
if ( (setsockopt( sockfd, IPPROTO_TCP, TCP_NODELAY,
(char *)&flag_TCP_nodelay, sizeof(flag_TCP_nodelay))) < 0) return -1;
//nodelay
int flags=fcntl(sockfd, F_GETFL, 0);
if (flags<0) return -1;
flags|=O_NONBLOCK;
fcntl(sockfd, F_SETFL, flags);
if (connect(sockfd, rp->ai_addr, rp->ai_addrlen) < 0) break;
close(sockfd);
}
freeaddrinfo(res);
if (rp == NULL)
return -1;
return sockfd;
}
//--------------------
int waitconnect(char *port, int maxconn)
{
struct addrinfo hints, *res;
int sockfd;
memset(&hints, 0, sizeof hints);
hints.ai_family = AF_UNSPEC; // use IPv4 or IPv6, whichever
// hints.ai_family = AF_INET6; // use IPv6
// hints.ai_family = AF_INET; // use IPv4
hints.ai_socktype = SOCK_STREAM;
hints.ai_flags = AI_PASSIVE; // fill in my IP for me
getaddrinfo(NULL, port, &hints, &res);
sockfd = socket(res->ai_family, res->ai_socktype, res->ai_protocol);
if (sockfd<0) return -1;
if (bind(sockfd, res->ai_addr, res->ai_addrlen)<0) {close(sockfd); return -1;}
listen(sockfd, maxconn);
return sockfd;
}
//---------------------
int acceptconnect(int fd, char *addr, int *len)
{
return accept(fd, (struct sockaddr *)addr, len);
}
void ipnum2str(const struct sockaddr *sa, char *s, size_t maxlen)
{
switch(sa->sa_family) {
case AF_INET:
inet_ntop(AF_INET, &(((struct sockaddr_in *)sa)->sin_addr), s, maxlen);
break;
case AF_INET6:
inet_ntop(AF_INET6, &(((struct sockaddr_in6 *)sa)->sin6_addr), s, maxlen);
break;
default:
strncpy(s, "Unknown AF", maxlen);
}
}
//---------------------
void ipnumport2str(const struct sockaddr *sa, socklen_t salen, char *ip, size_t maxiplen, char *port, size_t maxportlen)
{
getnameinfo(sa, salen, ip, maxiplen, port, maxportlen, NI_NUMERICHOST|NI_NUMERICSERV);
}
//--------------------
int sendmore(int fd, char *buf, int len)
{
return send(fd, buf, len, MSG_NOSIGNAL | MSG_MORE);
}
//--------------------
int sendsock(int fd, char *buf, int len)
{
return send(fd, buf, len, MSG_NOSIGNAL);
}
//--------------------
int readsock(int fd, char *buf, int len)
{
int res=recv(fd, buf, len, MSG_DONTWAIT);
if (res==0) return -1;
if ((res<0) && (errno==EAGAIN)) return 0;
return res;
}
//--------------------
int getsockipnum(int fd, char *addr, int *len)
{
return getsockname(fd, (struct sockaddr *)addr, len);
}
//--------------------
int getpeeripnum(int fd, char *addr, int *len)
{
return getpeername(fd, (struct sockaddr *)addr, len);
}
//--------------------
int getunack(int fd)
{
int unak=-1;
ioctl(fd, TIOCOUTQ, &unak);
return unak;
}
//--------------------
void stoptxrx(int fd, int how)
// how 0 rx, 1 tx, 2 rxtx
{
shutdown(fd, how);
}