43 #include <arpa/inet.h>
48 #include "include/private.h"
66 static int32_t hash_socket(
const void *data,
int key) {
69 const int *hashkey = (key) ? data : &sock->
sock;
86 static void clean_fwsocket(
void *data) {
106 if (sock->
sock >= 0) {
123 if (!(si =
objalloc(
sizeof(*si),clean_fwsocket))) {
127 if ((si->
sock = socket(family, type, proto)) < 0) {
146 socklen_t salen =
sizeof(si->
addr);
148 if (!(si =
objalloc(
sizeof(*si),clean_fwsocket))) {
170 static struct fwsocket *_opensocket(
int family,
int stype,
int proto,
const char *ipaddr,
const char *port,
void *
ssl,
int ctype,
int backlog) {
171 struct addrinfo hint, *result, *rp;
178 memset(&hint, 0,
sizeof(hint));
179 hint.ai_family = family;
180 hint.ai_socktype = stype;
181 hint.ai_protocol = proto;
183 if (getaddrinfo(ipaddr, port, &hint, &result) || !result) {
187 for(rp = result; rp; rp = result->ai_next) {
188 if (!(sock =
make_socket(rp->ai_family, rp->ai_socktype, rp->ai_protocol, ssl))) {
193 setsockopt(sock->
sock, SOL_SOCKET, SO_REUSEADDR, &on,
sizeof(on));
195 setsockopt(sock->
sock, SOL_SOCKET, SO_REUSEPORT, &on,
sizeof(on));
201 if ((!ctype && !connect(sock->
sock, rp->ai_addr, rp->ai_addrlen)) ||
202 (ctype && !bind(sock->
sock, rp->ai_addr, rp->ai_addrlen))) {
214 freeaddrinfo(result);
222 memcpy(&sock->
addr.
ss, rp->ai_addr,
sizeof(sock->
addr.
ss));
226 listen(sock->
sock, backlog);
232 getsockname(sock->
sock, &sock->
addr.
sa, &salen);
235 freeaddrinfo(result);
250 extern struct fwsocket *
sockconnect(
int family,
int stype,
int proto,
const char *ipaddr,
const char *port,
void *ssl) {
251 return(_opensocket(family, stype, proto, ipaddr, port, ssl, 0, 0));
263 return (_opensocket(PF_UNSPEC, SOCK_DGRAM, IPPROTO_UDP, ipaddr, port, ssl, 0, 0));
275 return (_opensocket(PF_UNSPEC, SOCK_STREAM, IPPROTO_TCP, ipaddr, port, ssl, 0, 0));
290 extern struct fwsocket *
sockbind(
int family,
int stype,
int proto,
const char *ipaddr,
const char *port,
void *ssl,
int backlog) {
291 return(_opensocket(family, stype, proto, ipaddr, port, ssl, 1, backlog));
303 return (_opensocket(PF_UNSPEC, SOCK_DGRAM, IPPROTO_UDP, ipaddr, port, ssl, 1, 0));
315 extern struct fwsocket *
tcpbind(
const char *ipaddr,
const char *port,
void *ssl,
int backlog) {
316 return (_opensocket(PF_UNSPEC, SOCK_STREAM, IPPROTO_TCP, ipaddr, port, ssl, 1, backlog));
319 static void _socket_handler_clean(
void *data) {
331 static void *_socket_handler(
void *data) {
336 fd_set rd_set, act_set;
337 int selfd, sockfd, type, flags;
351 FD_SET(sockfd, &rd_set);
359 selfd = select(sockfd + 1, &act_set, NULL, NULL, &tv);
363 if ((selfd < 0 && errno == EINTR) || (!selfd)) {
365 errcode = WSAGetLastError();
366 if (((selfd == SOCKET_ERROR) && (errcode == WSAEINTR)) || (!selfd)) {
372 }
else if (selfd < 0) {
376 if (FD_ISSET(sockfd, &act_set)) {
435 if (!sock || !read || !(sockh =
objalloc(
sizeof(*sockh), NULL))) {
467 if (sock->
flags & SOCK_FLAG_BIND) {
468 if (sock->
ssl || !(sock->
type == SOCK_DGRAM)) {
471 if (sock->
ssl && (sock->
type == SOCK_DGRAM)) {
480 _start_socket_handler(sock, read, acceptfunc, cleanup, data);
496 _start_socket_handler(sock, read, NULL, cleanup, data);
509 switch (addr->
ss.ss_family) {
536 struct fwsocket *
mcast_socket(
const char *iface,
int family,
const char *mcastip,
const char *port,
int flags) {
538 struct addrinfo hint, *result, *rp;
539 struct in_addr *srcif;
550 memset(&hint, 0,
sizeof(hint));
551 hint.ai_family = PF_UNSPEC;
552 hint.ai_socktype = SOCK_DGRAM;
553 hint.ai_protocol = IPPROTO_UDP;
560 if (getaddrinfo(srcip, port, &hint, &result) || !result) {
572 if (!srcip || (getaddrinfo(srcip, port, &hint, &result) || !result)) {
579 for(rp = result; rp; rp = result->ai_next) {
580 if (!(fws =
make_socket(rp->ai_family, rp->ai_socktype, rp->ai_protocol, NULL))) {
587 freeaddrinfo(result);
591 if(setsockopt(fws->
sock, SOL_SOCKET, SO_REUSEADDR, (
char*)&on,
sizeof(on))) {
593 freeaddrinfo(result);
597 if (rp->ai_family == PF_INET) {
598 struct in_addr mcastip4;
600 struct sockaddr_in *src_ip;
602 src_ip = (
struct sockaddr_in*)rp->ai_addr;
604 if (setsockopt(fws->
sock, IPPROTO_IP, IP_MULTICAST_TTL, (
char*)&ttl,
sizeof(ttl))) {
606 freeaddrinfo(result);
610 if (flags && setsockopt(fws->
sock, IPPROTO_IP, IP_MULTICAST_LOOP, (
char*)&off,
sizeof(off))) {
611 freeaddrinfo(result);
617 inet_lookup(PF_INET, mcastip, &mcastip4,
sizeof(mcastip4));
623 mg.imr_multiaddr = mcastip4;
624 mg.imr_interface.s_addr = src_ip->sin_addr.s_addr;
625 if (setsockopt(fws->
sock, IPPROTO_IP, IP_ADD_MEMBERSHIP, (
char*)&mg,
sizeof(mg))) {
631 memset(&srcif, 0,
sizeof(srcif));
632 srcif = &src_ip->sin_addr;
633 if(setsockopt(fws->
sock, IPPROTO_IP, IP_MULTICAST_IF, (
char*)srcif,
sizeof(*srcif))) {
638 src_ip->sin_addr.s_addr = mcastip4.s_addr;
639 }
else if (rp->ai_family == PF_INET6) {
640 struct in6_addr mcastip6;
642 struct sockaddr_in6 *src_ip;
647 src_ip = (
struct sockaddr_in6*)rp->ai_addr;
649 if (setsockopt(fws->
sock, IPPROTO_IPV6, IPV6_MULTICAST_HOPS, (
char*)&ttl,
sizeof(ttl))) {
651 freeaddrinfo(result);
655 if (flags && setsockopt(fws->
sock, IPPROTO_IPV6, IPV6_MULTICAST_LOOP, (
char*)&off,
sizeof(off))) {
656 freeaddrinfo(result);
662 inet_lookup(PF_INET6, mcastip, &mcastip6,
sizeof(mcastip6));
668 mg.ipv6mr_multiaddr = mcastip6;
669 mg.ipv6mr_interface = ifidx;
670 if (setsockopt(fws->
sock, IPPROTO_IPV6, IPV6_JOIN_GROUP, (
char*)&mg,
sizeof(mg))) {
676 if (setsockopt(fws->
sock, IPPROTO_IPV6, IPV6_MULTICAST_IF, (
char*)&ifidx,
sizeof(ifidx))) {
682 src_ip->sin6_addr = mcastip6;
685 if (bind(fws->
sock, (
struct sockaddr*)rp->ai_addr,
sizeof(
struct sockaddr_storage))) {
686 freeaddrinfo(result);
692 freeaddrinfo(result);
struct fwsocket * sockbind(int family, int stype, int proto, const char *ipaddr, const char *port, void *ssl, int backlog)
Generic server socket.
union sockstruct addr
system socket data structure.
void * create_bucketlist(int bitmask, blisthash hash_function)
const char * sockaddr2ip(union sockstruct *addr, char *buf, int len)
Return the ip address of a sockstruct addr.
socketrecv client
Callback called when the socket is ready to read.
void ssl_shutdown(void *ssl, int sock)
Shutdown the SSL connection.
int objref(void *data)
Reference a object.
#define testflag(obj, flag)
Atomically test a flag in the flags field of a referenced object.
struct fwsocket * dtls_listenssl(struct fwsocket *sock)
Implementation of "listen" for DTLSv1.
void mcast6_ip(struct in6_addr *addr)
Randomally assign a SSM Multicast address.param addr Ip address structure to fill out...
int inet_lookup(int family, const char *host, void *addr, socklen_t len)
Perform DNS lookup on a host/ip retun the IP address.
int objlock(void *data)
Lock the reference.
struct fwsocket * parent
Parent socket if we connected to a server and were spawned.
socketrecv connect
If a client connects to a bound port this callback is called on connect.
struct fwsocket * tcpbind(const char *ipaddr, const char *port, void *ssl, int backlog)
Generic server socket.
void * data
Reference to data passed in callbacks.
void dtlshandltimeout(struct fwsocket *sock)
Handle DTLSv1 timeout.
void * objalloc(int size, objdestroy)
Allocate a referenced lockable object.
Data structure containing interface information.
int idx
Interface index required for at least IPv6 multicast support.
struct ifinfo * get_ifinfo(const char *iface)
Return interface info for a specified interface.
#define setflag(obj, flag)
Atomically set a flag in the flags field of a referenced object.
void * next_bucket_loop(struct bucket_loop *bloop)
Return a reference to the next item in the list this could be the first item.
void close_socket(struct fwsocket *sock)
Mark the socket for closure and release the reference.
const char * get_ifipaddr(const char *iface, int family)
Find best IP adress for a interface.
Socket handling thread data.
DTS Application library API Include file.
void(* socketrecv)(struct fwsocket *, void *)
Callback function to register with a socket that will be called when there is data available...
int get_iface_index(const char *ifname)
Get the netlink interface for a named interface.
const char * ipv6addr
IPv6 address priorised by Local/6in4.
void tlsaccept(struct fwsocket *sock, struct ssldata *orig)
Create SSL session for new connection.
void startsslclient(struct fwsocket *sock)
Start SSL on a client socket.
The socket has been bound and awaiting connections.
const char * ipv4addr
IPv4 address priorotised by Routed/Reserved/Zeroconf.
struct thread_pvt * framework_mkthread(threadfunc, threadcleanup, threadsighandler, void *data, int flags)
create a thread result must be unreferenced
struct bucket_list * children
We are the parent this is a list of spawn.
int proto
Socket protocol.
struct ssldata * ssl
SSL structure for encryption.
struct fwsocket * udpconnect(const char *ipaddr, const char *port, void *ssl)
UDP Socket client.
struct sockaddr_in sa4
IPv4 socket addr structure.
void socketserver(struct fwsocket *sock, socketrecv connectfunc, socketrecv acceptfunc, threadcleanup cleanup, void *data)
Create a server thread with a socket that has been created with sockbind udpbind or tcpbind...
struct fwsocket * make_socket(int family, int type, int proto, void *ssl)
Allocate a socket structure and return reference.
int objunlock(void *data)
Unlock a reference.
void seedrand(void)
Seed openssl random number generator.
struct sockaddr_storage ss
Sockaddr storage is a "magic" struct been able to hold IPv4 or IPv6.
int framework_threadok(void)
let threads check there status.
struct fwsocket * sock
Socket this thread manages.
struct fwsocket * udpbind(const char *ipaddr, const char *port, void *ssl)
UDP server socket.
void socketclient(struct fwsocket *sock, void *data, socketrecv read, threadcleanup cleanup)
Create a server thread with a socket that has been created with sockbind udpbind or tcpbind...
struct fwsocket * mcast_socket(const char *iface, int family, const char *mcastip, const char *port, int flags)
Create a multicast socket.
void(* threadcleanup)(void *)
Function called after thread termination.
threadcleanup cleanup
Callback to call when the thread closes to allow additional cleanup.
struct fwsocket * sockconnect(int family, int stype, int proto, const char *ipaddr, const char *port, void *ssl)
Generic client socket.
struct sockaddr sa
Base socket addr structure.
void mcast4_ip(struct in_addr *addr)
Randomally assign a SSM Multicast address.
void remove_bucket_loop(struct bucket_loop *bloop)
Safely remove a item from a list while iterating in a loop.
void dtsl_serveropts(struct fwsocket *sock)
Start up the DTLSv1 Server.
struct fwsocket * accept_socket(struct fwsocket *sock)
Create and return a socket structure from accept()
const char * inet_ntop(int af, const void *src, char *dest, socklen_t size)
Win32 implementation of inet_ntop.
int addtobucket(struct bucket_list *blist, void *data)
Add a reference to the bucketlist.
void remove_bucket_item(struct bucket_list *blist, void *data)
Remove and unreference a item from the list.
struct sockaddr_in6 sa6
IPv6 socket addr structure.
Socket union describing all address types.
enum sock_flags flags
Socket control flags.
int objunref(void *data)
Drop reference held.
struct fwsocket * tcpconnect(const char *ipaddr, const char *port, void *ssl)
TCP Socket client.
struct bucket_loop * init_bucket_loop(struct bucket_list *blist)
Create a bucket list iterator to safely iterate the list.
The socket is going away stop processing in its thread.