kopia lustrzana https://github.com/sp9skp/spdxl
244 wiersze
5.0 KiB
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);
|
|
}
|
|
|