38#include <sys/socket.h>
39#include <netinet/in.h>
40#ifndef PCP_SOCKET_IS_VOIDPTR
51static PCP_SOCKET pcp_socket_create_impl(
int domain,
int type,
int protocol);
52static int pcp_socket_recvfrom_impl(
PCP_SOCKET sock,
void *buf,
size_t len,
53 int flags,
struct sockaddr *src_addr, socklen_t *addrlen);
54static int pcp_socket_sendto_impl(
PCP_SOCKET sock,
const void *buf,
55 size_t len,
int flags,
struct sockaddr *dest_addr, socklen_t addrlen);
56static int pcp_socket_close_impl(
PCP_SOCKET sock);
59 pcp_socket_create_impl,
60 pcp_socket_recvfrom_impl,
61 pcp_socket_sendto_impl,
67int pcp_win_sock_startup()
70 WORD wVersionRequested;
74 wVersionRequested=MAKEWORD(2, 2);
75 err=WSAStartup(wVersionRequested, &wsaData);
79 perror(
"WSAStartup failed with error");
89int pcp_win_sock_cleanup()
92 printf(
"WSACleanup failed.\n");
100 struct sockaddr *src)
102 if (src->sa_family == AF_INET) {
103 struct sockaddr_in *src_ip4=(
struct sockaddr_in *)src;
106 if (src_ip4->sin_addr.s_addr != INADDR_ANY) {
110 S6_ADDR32(dst_ip6)[3]=src_ip4->sin_addr.s_addr;
113 for (i=0; i < 4; ++i)
118 *dst_port=src_ip4->sin_port;
120 }
else if (src->sa_family == AF_INET6) {
121 struct sockaddr_in6 *src_ip6=(
struct sockaddr_in6 *)src;
124 memcpy(dst_ip6, src_ip6->sin6_addr.s6_addr,
sizeof(*dst_ip6));
127 *dst_port=src_ip6->sin6_port;
133 uint16_t sport,
int ret_ipv6_mapped_ipv4,
uint32_t scope_id)
135 if ((!ret_ipv6_mapped_ipv4) && (IN6_IS_ADDR_V4MAPPED(sip))) {
136 struct sockaddr_in *s=(
struct sockaddr_in *)dst;
138 s->sin_family=AF_INET;
143 struct sockaddr_in6 *s=(
struct sockaddr_in6 *)dst;
145 s->sin6_family=AF_INET6;
148 s->sin6_scope_id=scope_id;
153#ifndef PCP_SOCKET_IS_VOIDPTR
157 int errnum=WSAGetLastError();
190 int flags,
struct sockaddr *src_addr, socklen_t *addrlen)
199 int flags,
struct sockaddr *dest_addr, socklen_t addrlen)
214static PCP_SOCKET pcp_socket_create_impl(
int domain,
int type,
int protocol)
216#ifdef PCP_SOCKET_IS_VOIDPTR
221 unsigned long iMode=1;
222 struct sockaddr_storage sas;
223 struct sockaddr_in *
sin=(
struct sockaddr_in *)&sas;
224 struct sockaddr_in6 *sin6=(
struct sockaddr_in6 *)&sas;
229 memset(&sas, 0,
sizeof(sas));
230 sas.ss_family=(ADDRESS_FAMILY)domain;
231 if (domain == AF_INET) {
232 sin->sin_port=htons(5350);
234 }
else if (domain == AF_INET6) {
235 sin6->sin6_port=htons(5350);
236 SET_SA_LEN(sin6,
sizeof(
struct sockaddr_in6));
246 if (ioctlsocket(s, FIONBIO, &iMode)) {
248 "Unable to set nonblocking mode for socket.");
253 flg=fcntl(s, F_GETFL, 0);
254 if (fcntl(s, F_SETFL, flg | O_NONBLOCK)) {
256 "Unable to set nonblocking mode for socket.");
261#ifdef PCP_USE_IPV6_SOCKET
264 == setsockopt(s, IPPROTO_IPV6, IPV6_V6ONLY, (
char *)&flg,
267 "Dual-stack sockets are not supported on this platform. "
268 "Recompile library with disabled IPv6 support.");
273 while (bind(s, (
struct sockaddr *)&sas,
276 if (sas.ss_family == AF_INET) {
277 sin->sin_port=htons(ntohs(
sin->sin_port) + 1);
279 sin6->sin6_port=htons(ntohs(sin6->sin6_port) + 1);
292static int pcp_socket_recvfrom_impl(
PCP_SOCKET sock,
void *buf,
293 size_t len,
int flags,
struct sockaddr *src_addr, socklen_t *addrlen)
297#ifndef PCP_SOCKET_IS_VOIDPTR
298 ret=recvfrom(sock, (
char*)buf, (
int)len, flags, src_addr, addrlen);
311static int pcp_socket_sendto_impl(
PCP_SOCKET sock,
const void *buf,
312 size_t len,
int flags
UNUSED,
struct sockaddr *dest_addr, socklen_t addrlen)
316#ifndef PCP_SOCKET_IS_VOIDPTR
317 ret=sendto(sock, (
const char*)buf, (
int)len, 0, dest_addr, addrlen);
329static int pcp_socket_close_impl(
PCP_SOCKET sock)
331#ifndef PCP_SOCKET_IS_VOIDPTR
#define assert(condition)
float sin(float x) noexcept
#define PCP_LOG(level, fmt,...)
void pcp_fill_in6_addr(struct in6_addr *dst_ip6, uint16_t *dst_port, struct sockaddr *src)
int pcp_socket_close(struct pcp_ctx_s *ctx)
pcp_socket_vt_t default_socket_vt
ssize_t pcp_socket_recvfrom(struct pcp_ctx_s *ctx, void *buf, size_t len, int flags, struct sockaddr *src_addr, socklen_t *addrlen)
PCP_SOCKET pcp_socket_create(struct pcp_ctx_s *ctx, int domain, int type, int protocol)
void pcp_fill_sockaddr(struct sockaddr *dst, struct in6_addr *sip, uint16_t sport, int ret_ipv6_mapped_ipv4, uint32_t scope_id)
ssize_t pcp_socket_sendto(struct pcp_ctx_s *ctx, const void *buf, size_t len, int flags, struct sockaddr *dest_addr, socklen_t addrlen)
#define PCP_INVALID_SOCKET
pcp_socket_vt_t * virt_socket_tb
PCP_SOCKET(* sock_create)(int domain, int type, int protocol)
int(* sock_recvfrom)(PCP_SOCKET sockfd, void *buf, size_t len, int flags, struct sockaddr *src_addr, socklen_t *addrlen)
int(* sock_close)(PCP_SOCKET sockfd)
int(* sock_sendto)(PCP_SOCKET sockfd, const void *buf, size_t len, int flags, struct sockaddr *dest_addr, socklen_t addrlen)