📄 socket.cpp
字号:
return error(errServiceUnavailable,"Multicast not supported");#endif}#endif#ifdef HAVE_GETADDRINFOUDPSocket::UDPSocket(const char *name, Family fam) :Socket(fam, SOCK_DGRAM, IPPROTO_UDP){ char namebuf[128], *cp; struct addrinfo hint, *list = NULL, *first; family = fam; switch(fam) {#ifdef CCXX_IPV6 case IPV6: peer.ipv6.sin6_family = family; break;#endif default: peer.ipv4.sin_family = family; } snprintf(namebuf, sizeof(namebuf), "%s", name); cp = strrchr(namebuf, '/'); if(!cp && family == IPV4) cp = strrchr(namebuf, ':'); if(!cp) { cp = namebuf; name = NULL; } else { name = namebuf; *(cp++) = 0; if(!strcmp(name, "*")) name = NULL; } memset(&hint, 0, sizeof(hint)); hint.ai_family = family; hint.ai_socktype = SOCK_DGRAM; hint.ai_protocol = IPPROTO_UDP; hint.ai_flags = AI_PASSIVE; if(getaddrinfo(name, cp, &hint, &list) || !list) { error(errBindingFailed, "Could not find service", errno); endSocket(); return; }#if defined(SO_REUSEADDR) && !defined(WIN32) int opt = 1; setsockopt(so, SOL_SOCKET, SO_REUSEADDR, (char *)&opt, (socklen_t)sizeof(opt));#endif first = list; while(list) { if(!bind(so, list->ai_addr, (socklen_t)list->ai_addrlen)) { state = BOUND; break; } list = list->ai_next; } freeaddrinfo(first); if(state != BOUND) { endSocket(); error(errBindingFailed, "Count not bind socket", errno); return; }}#elseUDPSocket::UDPSocket(const char *name, Family fam) :Socket(fam, SOCK_DGRAM, IPPROTO_UDP){ char namebuf[128], *cp; tpport_t port; struct servent *svc; socklen_t alen; struct sockaddr *addr; family = fam; snprintf(namebuf, sizeof(namebuf), "%s", name); cp = strrchr(namebuf, '/'); if(!cp && family == IPV4) cp = strrchr(namebuf, ':'); if(!cp) { cp = namebuf; name = "*"; } else { name = namebuf; *(cp++) = 0; } if(isdigit(*cp)) port = atoi(cp); else { mutex.enter(); svc = getservbyname(cp, "udp"); if(svc) port = ntohs(svc->s_port); mutex.leave(); if(!svc) { error(errBindingFailed, "Could not find service", errno); endSocket(); return; } } struct sockaddr_in addr4; IPV4Address ia4(name);#ifdef CCXX_IPV6 struct sockaddr_in6 addr6; IPV6Address ia6(name);#endif switch(family) {#ifdef CCXX_IPV6 case IPV6: peer.ipv6.sin6_family = family; memset(&addr6, 0, sizeof(addr6)); addr6.sin6_family = family; addr6.sin6_addr = getaddress(ia6); addr6.sin6_port = htons(port); alen = sizeof(addr6); addr = (struct sockaddr *)&addr6; break;#endif case IPV4: peer.ipv4.sin_family = family; memset(&addr4, 0, sizeof(addr4)); addr4.sin_family = family; addr4.sin_addr = getaddress(ia4); addr4.sin_port = htons(port); alen = sizeof(&addr4); addr = (struct sockaddr *)&addr4; }#if defined(SO_REUSEADDR) && !defined(WIN32) int opt = 1; setsockopt(so, SOL_SOCKET, SO_REUSEADDR, (char *)&opt, (socklen_t)sizeof(opt));#endif if(!bind(so, addr, alen)) state = BOUND; if(state != BOUND) { endSocket(); error(errBindingFailed, "Count not bind socket", errno); return; }}#endifUDPSocket::UDPSocket(Family fam) :Socket(fam, SOCK_DGRAM, IPPROTO_UDP){ family = fam; memset(&peer, 0, sizeof(peer)); switch(fam) {#ifdef CCXX_IPV6 case IPV6: peer.ipv6.sin6_family = family; break;#endif default: peer.ipv4.sin_family = family; }}UDPSocket::UDPSocket(const IPV4Address &ia, tpport_t port) :Socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP){ family = IPV4; memset(&peer.ipv4, 0, sizeof(peer)); peer.ipv4.sin_family = AF_INET; peer.ipv4.sin_addr = getaddress(ia); peer.ipv4.sin_port = htons(port);#if defined(SO_REUSEADDR) && !defined(WIN32) int opt = 1; setsockopt(so, SOL_SOCKET, SO_REUSEADDR, (char *)&opt, (socklen_t)sizeof(opt));#endif if(bind(so, (struct sockaddr *)&peer.ipv4, sizeof(peer.ipv4))) { endSocket(); error(errBindingFailed,"Could not bind socket",socket_errno); return; } state = BOUND;}#ifdef CCXX_IPV6UDPSocket::UDPSocket(const IPV6Address &ia, tpport_t port) :Socket(AF_INET6, SOCK_DGRAM, IPPROTO_UDP){ family = IPV6; memset(&peer.ipv6, 0, sizeof(peer)); peer.ipv6.sin6_family = AF_INET6; peer.ipv6.sin6_addr = getaddress(ia); peer.ipv6.sin6_port = htons(port);#if defined(SO_REUSEADDR) && !defined(WIN32) int opt = 1; setsockopt(so, SOL_SOCKET, SO_REUSEADDR, (char *)&opt, (socklen_t)sizeof(opt));#endif if(bind(so, (struct sockaddr *)&peer.ipv6, sizeof(peer.ipv6))) { endSocket(); error(errBindingFailed,"Could not bind socket",socket_errno); return; } state = BOUND;}#endifUDPSocket::~UDPSocket(){ endSocket();}ssize_t UDPSocket::send(const void *buf, size_t len){ struct sockaddr *addr; socklen_t alen; switch(family) {#ifdef CCXX_IPV6 case IPV6: addr = (struct sockaddr *)&peer.ipv6; alen = sizeof(struct sockaddr_in6); break;#endif case IPV4: addr = (struct sockaddr *)&peer.ipv4; alen = sizeof(struct sockaddr_in); } if(isConnected()) { addr = NULL; alen = 0; } return _IORET64 ::sendto(so, (const char *)buf, _IOLEN64 len, 0, addr, alen);}ssize_t UDPSocket::receive(void *buf, size_t len, bool reply){ struct sockaddr *addr; struct sockaddr_in senderAddress; // DMC 2/7/05 ADD for use below. socklen_t alen; switch(family) {#ifdef CCXX_IPV6 case IPV6: addr = (struct sockaddr *)&peer.ipv6; alen = sizeof(struct sockaddr_in6); break;#endif case IPV4: addr = (struct sockaddr *)&peer.ipv4; alen = sizeof(struct sockaddr_in); } if(isConnected() || !reply) { // DMC 2/7/05 MOD to use senderAddress instead of NULL, to prevent 10014 error // from recvfrom. //addr = NULL; //alen = 0; addr = (struct sockaddr*)(&senderAddress); alen = sizeof(struct sockaddr_in); } int bytes = ::recvfrom(so, (char *)buf, _IOLEN64 len, 0, addr, &alen);#ifdef WIN32 int code = 0; if (bytes == SOCKET_ERROR) { code = WSAGetLastError(); }#endif return _IORET64 bytes;}Socket::Error UDPSocket::join(const IPV4Multicast &ia,int InterfaceIndex){#ifdef WIN32 // DMC 2/7/05: Added WIN32 block. Win32 does not define the ip_mreqn structure, // so we must use ip_mreq with INADDR_ANY. struct ip_mreq group; struct sockaddr_in myaddr; socklen_t len = sizeof(myaddr); if(!flags.multicast) return error(errMulticastDisabled); memset(&group, 0, sizeof(group)); getsockname(so, (struct sockaddr *)&myaddr, &len); group.imr_multiaddr.s_addr = ia.getAddress().s_addr; group.imr_interface.s_addr = INADDR_ANY; int retval = setsockopt(so, IPPROTO_IP, IP_ADD_MEMBERSHIP, (char *)&group, sizeof(group)); return errSuccess;#elif defined(IP_ADD_MEMBERSHIP) && defined(SIOCGIFINDEX) && !defined(__FreeBSD__) && !defined(_OSF_SOURCE) && !defined(__hpux) && !defined(__GNU__) struct ip_mreqn group; struct sockaddr_in myaddr; socklen_t len = sizeof(myaddr); if(!flags.multicast) return error(errMulticastDisabled); getsockname(so, (struct sockaddr *)&myaddr, &len); memset(&group, 0, sizeof(group)); memcpy(&group.imr_address, &myaddr.sin_addr, sizeof(&myaddr.sin_addr)); group.imr_multiaddr = getaddress(ia); group.imr_ifindex = InterfaceIndex; setsockopt(so, IPPROTO_IP, IP_ADD_MEMBERSHIP, (char *)&group, sizeof(group)); return errSuccess;#elif defined(IP_ADD_MEMBERSHIP) // if no by index, use INADDR_ANY struct ip_mreq group; struct sockaddr_in myaddr; socklen_t len = sizeof(myaddr); if(!flags.multicast) return error(errMulticastDisabled); getsockname(so, (struct sockaddr *)&myaddr, &len); memset(&group, sizeof(group), 0); group.imr_multiaddr.s_addr = ia.getAddress().s_addr; group.imr_interface.s_addr = INADDR_ANY; setsockopt(so, IPPROTO_IP, IP_ADD_MEMBERSHIP, (char *)&group, sizeof(group)); return errSuccess;#else return error(errServiceUnavailable);#endif}Socket::Error UDPSocket::getInterfaceIndex(const char *DeviceName,int& InterfaceIndex){#ifndef WIN32#if defined(IP_ADD_MEMBERSHIP) && defined(SIOCGIFINDEX) && !defined(__FreeBSD__) && !defined(_OSF_SOURCE) && !defined(__hpux) && !defined(__GNU__) struct ip_mreqn mreqn; struct ifreq m_ifreq; int i; sockaddr* sa = (sockaddr*) &peer.ipv4; InterfaceIndex = -1; mreqn.imr_multiaddr = *(struct in_addr *) &(sa->sa_data[2]); for (i = 0; i < IFNAMSIZ && DeviceName[i]; ++i) m_ifreq.ifr_name[i] = DeviceName[i]; for (; i < IFNAMSIZ; ++i) m_ifreq.ifr_name[i] = 0; if (ioctl (so, SIOCGIFINDEX, &m_ifreq)) return error(errServiceUnavailable);#if defined(__FreeBSD__) || defined(__GNU__) InterfaceIndex = m_ifreq.ifr_ifru.ifru_index;#else InterfaceIndex = m_ifreq.ifr_ifindex;#endif return errSuccess;#else return error(errServiceUnavailable);#endif#else return error(errServiceUnavailable);#endif // WIN32}#ifdef AF_UNSPECSocket::Error UDPSocket::disconnect(void){ struct sockaddr_in addr; int len = sizeof(addr); if(so == INVALID_SOCKET) return errSuccess; Socket::state = BOUND; memset(&addr, 0, len);#ifndef WIN32 addr.sin_family = AF_UNSPEC;#else addr.sin_family = AF_INET; addr.sin_addr.s_addr = INADDR_NONE;#endif if(::connect(so, (sockaddr *)&addr, len)) return connectError(); return errSuccess;}#else Socket::Error UDPSocket::disconnect(void){ if(so == INVALID_SOCKET) return errSuccess; Socket::state = BOUND; return connect(getLocal());}#endifvoid UDPSocket::setPeer(const IPV4Host &ia, tpport_t port){ memset(&peer.ipv4, 0, sizeof(peer.ipv4)); peer.ipv4.sin_family = AF_INET; peer.ipv4.sin_addr = getaddress(ia); peer.ipv4.sin_port = htons(port);}void UDPSocket::connect(const IPV4Host &ia, tpport_t port){ setPeer(ia, port); if(so == INVALID_SOCKET) return; if(!::connect(so, (struct sockaddr *)&peer.ipv4, sizeof(struct sockaddr_in))) Socket::state = CONNECTED;}#ifdef CCXX_IPV6void UDPSocket::setPeer(const IPV6Host &ia, tpport_t port){ memset(&peer.ipv6, 0, sizeof(peer.ipv6)); peer.ipv6.sin6_family = AF_INET6; peer.ipv6.sin6_addr = getaddress(ia); peer.ipv6.sin6_port = htons(port);}void UDPSocket::connect(const IPV6Host &ia, tpport_t port){ setPeer(ia, port); if(so == INVALID_SOCKET) return; if(!::connect(so, (struct sockaddr *)&peer.ipv6, sizeof(struct sockaddr_in6))) Socket::state = CONNECTED;}#endif#ifdef HAVE_GETADDRINFOvoid UDPSocket::setPeer(const char *name){ char namebuf[128], *cp; struct addrinfo hint, *list; snprintf(namebuf, sizeof(namebuf), "%s", name); cp = strrchr(namebuf, '/'); if(!cp) cp = strrchr(namebuf, ':'); if(!cp) return; memset(&hint, 0, sizeof(hint)); hint.ai_family = family; hint.ai_socktype = SOCK_DGRAM; hint.ai_protocol = IPPROTO_UDP; if(getaddrinfo(namebuf, cp, &hint, &list) || !list) return; switch(family) {#ifdef CCXX_IPV6 case IPV6: memcpy(&peer.ipv6, list->ai_addr, sizeof(peer.ipv6)); break;#endif case IPV4: memcpy(&peer.ipv4, list->ai_addr, sizeof(peer.ipv4)); } freeaddrinfo(list);}#elsevoid UDPSocket::setPeer(const char *name){ char namebuf[128], *cp; struct servent *svc; tpport_t port; struct sockaddr *addr; socklen_t alen; snprintf(namebuf, sizeof(namebuf), "%s", name); cp = strrchr(namebuf, '/'); if(!cp) cp = strrchr(namebuf, ':'); if(!cp) return; if(isdigit(*cp)) port = atoi(cp); else { mutex.enter(); svc = getservbyname(cp, "udp"); if(svc) port = ntohs(svc->s_port); mutex.leave(); if(!svc) return; } memset(&peer, 0, sizeof(peer)); switch(family) {#ifdef CCXX_IPV6 case IPV6: setPeer(IPV6Host(namebuf), port); break;#endif case IPV4: setPeer(IPV4Host(namebuf), port); } }#endifvoid UDPSocket::connect(const char *service){ int rtn; setPeer(service); if(so == INVALID_SOCKET) return; switch(family) {#ifdef CCXX_IPV6 case IPV6: rtn = ::connect(so, (struct sockaddr *)&peer.ipv6, sizeof(struct sockaddr_in6)); break;#endif case IPV4: rtn = ::connect(so, (struct sockaddr *)&peer.ipv4, sizeof(struct sockaddr_in)); } if(!rtn) Socket::state = CONNECTED;}IPV4Host UDPSocket::getIPV4Peer(tpport_t *port) const{ // FIXME: insufficient buffer // how to retrieve peer ?? char buf; socklen_t len = sizeof(peer.ipv4); int rtn = ::recvfrom(so, &buf, 1, MSG_PEEK, (struct sockaddr *)&peer.ipv4, &len);#ifdef WIN32 if(rtn < 1 && WSAGetLastError() != WSAEMSGSIZE) { if(port) *port = 0; memset((void*) &peer.ipv4, 0, sizeof(peer.ipv4)); }#else if(rtn < 1) { if(port) *port = 0; memset((void*) &peer.ipv4, 0, sizeof(peer.ipv4)); }#endif else { if(port) *port = ntohs(peer.ipv4.sin_port); } return IPV4Host(peer.ipv4.sin_addr);}#ifdef CCXX_IPV6IPV6Host UDPSocket::getIPV6Peer(tpport_t *port) const{ // FIXME: insufficient buffer // how to retrieve peer ?? char buf; socklen_t len = sizeof(peer.ipv6); int rtn = ::recvfrom(so, &buf, 1, MSG_PEEK, (struct sockaddr *)&peer.ipv6, &len);#ifdef WIN32 if(rtn < 1 && WSAGetLastError() != WSAEMSGSIZE) { if(port)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -