int socket_tcp6b(void) { #ifdef LIBC_HAS_IP6 int s; #if WINDOWS_NATIVE __winsock_init(); #endif if(noipv6) goto compat; s = winsock2errno(socket(PF_INET6, SOCK_STREAM, 0)); if(s == -1) { if(errno == EINVAL || errno == EAFNOSUPPORT || errno == EPFNOSUPPORT || errno == EPROTONOSUPPORT) { compat: s = winsock2errno(socket(AF_INET, SOCK_STREAM, 0)); noipv6 = 1; if(s == -1) return -1; } else return -1; } #ifdef IPV6_V6ONLY { int zero = 0; winsock2errno(setsockopt(s, IPPROTO_IPV6, IPV6_V6ONLY, (void*)&zero, sizeof(zero))); } #endif return s; #else return socket_tcp4b(); #endif }
int socket_mcloop6(int s,char loop) { #ifdef LIBC_HAS_IP6 if (noipv6) return winsock2errno(setsockopt(s,IPPROTO_IP,IP_MULTICAST_LOOP,&loop,sizeof loop)); else return winsock2errno(setsockopt(s,IPPROTO_IPV6,IPV6_MULTICAST_LOOP,&loop,sizeof loop)); #else return winsock2errno(setsockopt(s,IPPROTO_IP,IP_MULTICAST_LOOP,&loop,sizeof loop)); #endif }
ssize_t socket_send6(int s,const char *buf,size_t len,const char ip[16],uint16 port,uint32 scope_id) { #ifdef LIBC_HAS_IP6 struct sockaddr_in6 si; #else struct sockaddr_in si; #endif byte_zero(&si,sizeof si); #ifdef LIBC_HAS_IP6 if (noipv6) { #endif if (ip6_isv4mapped(ip)) return socket_send4(s,buf,len,ip+12,port); if (byte_equal(ip,16,V6loopback)) return socket_send4(s,buf,len,ip4loopback,port); #ifdef LIBC_HAS_IP6 errno=EPROTONOSUPPORT; return -1; } si.sin6_family = AF_INET6; uint16_pack_big((char *) &si.sin6_port,port); byte_copy((char *) &si.sin6_addr,16,ip); #ifdef LIBC_HAS_SCOPE_ID si.sin6_scope_id=scope_id; #else si.sin6_scope_id=0; #endif return winsock2errno(sendto(s,buf,len,0,(void*) &si,sizeof si)); #else errno=EPROTONOSUPPORT; return -1; #endif }
int ndelay_on(int fd) { #ifdef __MINGW32__ unsigned long i=0; return winsock2errno(ioctlsocket( fd, FIONBIO, &i)); #else return fcntl(fd,F_SETFL,fcntl(fd,F_GETFL,0) | O_NDELAY); #endif }
int socket_bind4_reuse(int s,const char *ip,uint16 port) { int one=1; setsockopt(s,SOL_SOCKET,SO_REUSEADDR,&one,sizeof one); #ifdef SO_REUSEPORT setsockopt(s,SOL_SOCKET,SO_REUSEPORT,&one,sizeof one); #endif return winsock2errno(socket_bind4(s,ip,port)); }
int socket_udp4(void) { int s; __winsock_init(); s = winsock2errno(socket(PF_INET,SOCK_DGRAM,IPPROTO_UDP)); if (s == -1) return -1; if (ndelay_on(s) == -1) { close(s); return -1; } return s; }
ssize_t socket_send4(int s,const char *buf,size_t len,const char ip[4],uint16 port) { struct sockaddr_in si; byte_zero(&si,sizeof si); si.sin_family = AF_INET; uint16_pack_big((char*) &si.sin_port,port); *((uint32*)&si.sin_addr) = *((uint32*)ip); return winsock2errno(sendto(s,buf,len,0,(void*) &si,sizeof si)); }
int socket_connect4(int s, const char* ip, uint16 port) { struct sockaddr_in si; byte_zero(&si, sizeof(si)); si.sin_family = AF_INET; uint16_pack_big((char*)&si.sin_port, port); *((uint32*)&si.sin_addr) = *((uint32*)ip); return winsock2errno(connect(s, (struct sockaddr*)&si, sizeof(si))); }
ssize_t socket_recv4(int s,char *buf,size_t len,char ip[4],uint16 *port) { struct sockaddr_in si; socklen_t Len = sizeof si; ssize_t r; if ((r = recvfrom(s,buf,len,0,(struct sockaddr *) &si,&Len))<0) return winsock2errno(-1); if (ip) *(uint32*)ip = *(uint32*)&si.sin_addr; if (port) uint16_unpack_big((char *) &si.sin_port,port); return r; }
ssize_t socket_recv6(int s,char *buf,size_t len,char ip[16],uint16 *port,uint32 *scope_id) { #ifdef LIBC_HAS_IP6 struct sockaddr_in6 si; #else struct sockaddr_in si; #endif socklen_t Len = sizeof si; ssize_t r; byte_zero(&si,Len); if ((r = recvfrom(s,buf,len,0,(struct sockaddr *) &si,&Len))<0) return winsock2errno(-1); #ifdef LIBC_HAS_IP6 if (noipv6 || si.sin6_family==AF_INET || si.sin6_family==PF_INET) { struct sockaddr_in *si4=(struct sockaddr_in *)&si; if (ip) { byte_copy(ip,12,V4mappedprefix); byte_copy(ip+12,4,(char *) &si4->sin_addr); } if (port) uint16_unpack_big((char *) &si4->sin_port,port); return r; } if (ip) byte_copy(ip,16,(char *) &si.sin6_addr); if (port) uint16_unpack_big((char *) &si.sin6_port,port); #ifdef LIBC_HAS_SCOPE_ID if (scope_id) *scope_id=si.sin6_scope_id; #else if (scope_id) *scope_id=0; #endif #else if (ip) { byte_copy(ip,12,(char *)V4mappedprefix); byte_copy(ip+12,4,(char *) &si.sin_addr); } if (port) uint16_unpack_big((char *) &si.sin_port,port); if (scope_id) *scope_id=0; #endif return r; }
int socket_local6(int s,char ip[16],uint16 *port,uint32 *scope_id) { #ifdef LIBC_HAS_IP6 struct sockaddr_in6 si; #else struct sockaddr_in si; #endif socklen_t len = sizeof si; if (getsockname(s,(void*) &si,&len) == -1) return winsock2errno(-1); #ifdef LIBC_HAS_IP6 if (si.sin6_family==AF_INET) { struct sockaddr_in *si4=(void*)&si; if (ip) { byte_copy(ip,12,V4mappedprefix); byte_copy(ip+12,4,(char *) &si4->sin_addr); } if (port) uint16_unpack_big((char *) &si4->sin_port,port); return 0; } if (ip) byte_copy(ip,16,(char *) &si.sin6_addr); if (port) uint16_unpack_big((char *) &si.sin6_port,port); #ifdef LIBC_HAS_SCOPE_ID if (scope_id) *scope_id=si.sin6_scope_id; #else if (scope_id) *scope_id=0; #endif #else if (ip) { byte_copy(ip,12,V4mappedprefix); byte_copy(ip+12,4,(char *) &si.sin_addr); } if (port) uint16_unpack_big((char *) &si.sin_port,port); if (scope_id) *scope_id=0; #endif return 0; }
int socket_mcttl4(int s, char TTL) { return winsock2errno(setsockopt(s, IPPROTO_IP, IP_MULTICAST_TTL, (void*)&TTL, sizeof TTL)); }
int socket_mcloop4(int s,char loop) { return winsock2errno(setsockopt(s,IPPROTO_IP,IP_MULTICAST_LOOP,&loop,sizeof loop)); }
int socket_broadcast(int s) { int opt = 1; return winsock2errno(setsockopt(s,SOL_SOCKET,SO_BROADCAST,&opt,sizeof opt)); }
int socket_accept4(int s,char *ip,uint16 *port) { struct sockaddr_in si; socklen_t len = sizeof si; int fd; #ifdef __MINGW32__ io_entry* e=array_get(&io_fds,sizeof(io_entry),s); if (e && e->inuse) { int sa2len; fd=-1; if (e->acceptqueued==1) { errno=EAGAIN; return -1; } if (e->acceptqueued==2) { incoming: /* incoming! */ { struct sockaddr* x,* y; GetAcceptExSockaddrs(e->inbuf,0,200,200,&x,&sa2len,&y,&len); if (len>sizeof(si)) len=sizeof(si); memcpy(&si,y,len); } fd=e->next_accept; e->next_accept=0; if (e->nonblock) { if (io_fd(fd)) { io_entry* f=array_get(&io_fds,sizeof(io_entry),fd); if (f) { f->nonblock=1; /* printf("setting fd %lu to non-blocking\n",(int)fd);*/ } } } } /* no accept queued, queue one now. */ if (e->next_accept==0) { e->next_accept=socket(AF_INET,SOCK_STREAM,IPPROTO_TCP); if (e==-1) return winsock2errno(-1); } if (AcceptEx(s,e->next_accept,e->inbuf,0,200,200,&e->errorcode,&e->or)) goto incoming; if (WSAGetLastError() != ERROR_IO_PENDING) return winsock2errno(-1); e->acceptqueued=1; if (fd==-1) { errno=EAGAIN; return fd; } } else { #endif if ((fd=accept(s,(void*) &si,&len))==-1) return winsock2errno(-1); #ifdef __MINGW32__ } #endif if (ip) *(uint32*)ip = *(uint32*)&si.sin_addr; if (port) uint16_unpack_big((char *) &si.sin_port,port); return fd; }