- added UDP socket functions to Macos socket interface implementatio (LIB61850-360)

v1.6_develop_rgoose_sntp
Michael Zillgith 3 years ago
parent 0f544e9e25
commit f3eab207e8

@ -10,6 +10,7 @@
#include "hal_socket.h" #include "hal_socket.h"
#include <sys/socket.h> #include <sys/socket.h>
#include <sys/types.h> #include <sys/types.h>
#include <sys/select.h>
#include <arpa/inet.h> #include <arpa/inet.h>
#include <unistd.h> #include <unistd.h>
#include <string.h> #include <string.h>
@ -32,6 +33,10 @@
#define DEBUG_SOCKET 0 #define DEBUG_SOCKET 0
#endif #endif
#ifndef IPV6_ADD_MEMBERSHIP
#define IPV6_ADD_MEMBERSHIP IPV6_JOIN_GROUP
#endif
#ifndef MSG_NOSIGNAL #ifndef MSG_NOSIGNAL
#define MSG_NOSIGNAL 0 #define MSG_NOSIGNAL 0
#endif #endif
@ -46,6 +51,11 @@ struct sServerSocket {
int backLog; int backLog;
}; };
struct sUdpSocket {
int fd;
int namespace; /* IPv4: AF_INET; IPv6: AF_INET6 */
};
struct sHandleSet { struct sHandleSet {
LinkedList sockets; LinkedList sockets;
bool pollfdIsUpdated; bool pollfdIsUpdated;
@ -645,3 +655,238 @@ Socket_destroy(Socket self)
GLOBAL_FREEMEM(self); GLOBAL_FREEMEM(self);
} }
static UdpSocket
UdpSocket_createUsingNamespace(int namespace)
{
UdpSocket self = NULL;
int sock = socket(namespace, SOCK_DGRAM, IPPROTO_UDP);
if (sock != -1) {
self = (UdpSocket) GLOBAL_MALLOC(sizeof(struct sSocket));
if (self) {
self->fd = sock;
self->namespace = namespace;
}
else {
if (DEBUG_SOCKET)
printf("SOCKET: failed to allocate memory\n");
close(sock);
}
}
else {
if (DEBUG_SOCKET)
printf("SOCKET: failed to create UDP socket (errno=%i)\n", errno);
}
return self;
}
UdpSocket
UdpSocket_create()
{
return UdpSocket_createUsingNamespace(AF_INET);
}
UdpSocket
UdpSocket_createIpV6()
{
return UdpSocket_createUsingNamespace(AF_INET6);
}
bool
UdpSocket_addGroupMembership(UdpSocket self, const char* multicastAddress)
{
if (self->namespace == AF_INET) {
struct ip_mreq mreq;
if (!inet_aton(multicastAddress, &(mreq.imr_multiaddr))) {
printf("SOCKET: Invalid IPv4 multicast address\n");
return false;
}
else {
mreq.imr_interface.s_addr = htonl(INADDR_ANY);
if (setsockopt(self->fd, IPPROTO_IP, IP_ADD_MEMBERSHIP, &mreq, sizeof(mreq)) == -1) {
printf("SOCKET: failed to set IPv4 multicast group (errno: %i)\n", errno);
return false;
}
}
return true;
}
else if (self->namespace == AF_INET6) {
struct ipv6_mreq mreq;
if (inet_pton(AF_INET6, multicastAddress, &(mreq.ipv6mr_multiaddr)) < 1) {
printf("SOCKET: failed to set IPv6 multicast group (errno: %i)\n", errno);
return false;
}
mreq.ipv6mr_interface = 0;
if (setsockopt(self->fd, IPPROTO_IPV6, IPV6_ADD_MEMBERSHIP, &mreq, sizeof(mreq)) == -1) {
printf("SOCKET: failed to set IPv6 multicast group (errno: %i)\n", errno);
return false;
}
return true;
}
return false;
}
bool
UdpSocket_setMulticastTtl(UdpSocket self, int ttl)
{
if (self->namespace == AF_INET) {
if (setsockopt(self->fd, IPPROTO_IP, IP_MULTICAST_TTL, &ttl, sizeof(ttl)) == -1) {
printf("SOCKET: failed to set IPv4 multicast TTL (errno: %i)\n", errno);
return false;
}
return true;
}
else if (self->namespace == AF_INET6) {
if (setsockopt(self->fd, IPPROTO_IPV6, IPV6_MULTICAST_HOPS, &ttl, sizeof(ttl)) == -1) {
printf("SOCKET: failed to set IPv6 multicast TTL(hops) (errno: %i)\n", errno);
return false;
}
return true;
}
return false;
}
bool
UdpSocket_bind(UdpSocket self, const char* address, int port)
{
//TODO add support for IPv6
struct sockaddr_in localAddress;
if (!prepareAddress(address, port, &localAddress)) {
close(self->fd);
self->fd = 0;
return false;
}
int result = bind(self->fd, (struct sockaddr*)&localAddress, sizeof(localAddress));
if (result == -1) {
if (DEBUG_SOCKET)
printf("SOCKET: failed to bind UDP socket (errno=%i)\n", errno);
close(self->fd);
self->fd = 0;
return false;
}
return true;
}
bool
UdpSocket_sendTo(UdpSocket self, const char* address, int port, uint8_t* msg, int msgSize)
{
//TODO add support for IPv6
struct sockaddr_in remoteAddress;
if (!prepareAddress(address, port, &remoteAddress)) {
if (DEBUG_SOCKET)
printf("SOCKET: failed to lookup remote address %s\n", address);
return false;
}
int result = sendto(self->fd, msg, msgSize, 0, (struct sockaddr*)&remoteAddress, sizeof(remoteAddress));
if (result == msgSize) {
return true;
}
else if (result == -1) {
if (DEBUG_SOCKET)
printf("SOCKET: failed to send UDP message (errno=%i)\n", errno);
}
else {
if (DEBUG_SOCKET)
printf("SOCKET: failed to send UDP message (insufficient data sent)\n");
}
return false;
}
int
UdpSocket_receiveFrom(UdpSocket self, char* address, int maxAddrSize, uint8_t* msg, int msgSize)
{
//TODO add support for IPv6
struct sockaddr_storage remoteAddress;
socklen_t structSize = sizeof(struct sockaddr_storage);
int result = recvfrom(self->fd, msg, msgSize, MSG_DONTWAIT, (struct sockaddr*)&remoteAddress, &structSize);
if (result == -1) {
if (DEBUG_SOCKET)
printf("SOCKET: failed to receive UDP message (errno=%i)\n", errno);
}
if (address) {
bool isIPv6;
char addrString[INET6_ADDRSTRLEN + 7];
int port;
if (remoteAddress.ss_family == AF_INET) {
struct sockaddr_in* ipv4Addr = (struct sockaddr_in*) &remoteAddress;
port = ntohs(ipv4Addr->sin_port);
inet_ntop(AF_INET, &(ipv4Addr->sin_addr), addrString, INET_ADDRSTRLEN);
isIPv6 = false;
}
else if (remoteAddress.ss_family == AF_INET6) {
struct sockaddr_in6* ipv6Addr = (struct sockaddr_in6*) &remoteAddress;
port = ntohs(ipv6Addr->sin6_port);
inet_ntop(AF_INET6, &(ipv6Addr->sin6_addr), addrString, INET6_ADDRSTRLEN);
isIPv6 = true;
}
else
return -1;
if (isIPv6)
snprintf(address, maxAddrSize, "[%s]:%i", addrString, port);
else
snprintf(address, maxAddrSize, "%s:%i", addrString, port);
}
if (address) {
bool isIPv6;
char addrString[INET6_ADDRSTRLEN + 7];
int port;
if (remoteAddress.ss_family == AF_INET) {
struct sockaddr_in* ipv4Addr = (struct sockaddr_in*) &remoteAddress;
port = ntohs(ipv4Addr->sin_port);
inet_ntop(AF_INET, &(ipv4Addr->sin_addr), addrString, INET_ADDRSTRLEN);
isIPv6 = false;
}
else if (remoteAddress.ss_family == AF_INET6) {
struct sockaddr_in6* ipv6Addr = (struct sockaddr_in6*) &remoteAddress;
port = ntohs(ipv6Addr->sin6_port);
inet_ntop(AF_INET6, &(ipv6Addr->sin6_addr), addrString, INET6_ADDRSTRLEN);
isIPv6 = true;
}
else
return result;
if (isIPv6)
snprintf(address, maxAddrSize, "[%s]:%i", addrString, port);
else
snprintf(address, maxAddrSize, "%s:%i", addrString, port);
}
return result;
}

Loading…
Cancel
Save