/** * Copyright - See the COPYRIGHT that is included with this distribution. * pvxs is distributed subject to a Software License Agreement found * in file LICENSE that is included with this distribution. */ #include #include #include #include #include #include #include #include "utilpvt.h" namespace pvxs { #define stringify(X) #X const char *version_str() { return "PVXS " stringify(PVXS_MAJOR_VERSION); } unsigned long version_int() { return PVXS_VERSION; } namespace detail { std::ostream& operator<<(std::ostream& strm, const Escaper& esc) { const char *s = esc.val; if(!s) { strm<<""; } else { for(; *s; s++) { char c = *s, next; switch(c) { case '\a': next = 'a'; break; case '\b': next = 'b'; break; case '\f': next = 'f'; break; case '\n': next = 'n'; break; case '\r': next = 'r'; break; case '\t': next = 't'; break; case '\v': next = 'v'; break; case '\\': next = '\\'; break; case '\'': next = '\''; break; default: if(isprint(c)) { strm.put(c); } else { strm<<"\\x"<sa_family) { if(len<0 || len>ev_socklen_t(size())) throw std::invalid_argument("Truncated Address"); memcpy(&store, addr, len); } size_t SockAddr::size() const { switch(store.sa.sa_family) { case AF_INET: return sizeof(store.in); #ifdef AF_INET6 case AF_INET6: return sizeof(store.in6); #endif default: // AF_UNSPEC and others return sizeof(store); } } unsigned short SockAddr::port() const { switch(store.sa.sa_family) { case AF_INET: return ntohs(store.in.sin_port); #ifdef AF_INET6 case AF_INET6:return ntohs(store.in6.sin6_port); #endif default: return 0; } } void SockAddr::setPort(unsigned short port) { switch(store.sa.sa_family) { case AF_INET: store.in.sin_port = htons(port); break; #ifdef AF_INET6 case AF_INET6:store.in6.sin6_port = htons(port); break; #endif default: throw std::logic_error("SockAddr: set family before port"); } } void SockAddr::setAddress(const char *name, unsigned short port) { SockAddr temp; int templen = sizeof(temp.store); if(evutil_parse_sockaddr_port(name, &temp->sa, &templen)) throw std::runtime_error(std::string("Unable to parse as IP addresss: ")+name); if(temp.port()==0) temp.setPort(port); (*this) = temp; } bool SockAddr::isAny() const { switch(store.sa.sa_family) { case AF_INET: return store.in.sin_addr.s_addr==htonl(INADDR_ANY); #ifdef AF_INET6 case AF_INET6: return IN6_IS_ADDR_UNSPECIFIED(&store.in6.sin6_addr); #endif default: return false; } } bool SockAddr::isLO() const { switch(store.sa.sa_family) { case AF_INET: return store.in.sin_addr.s_addr==htonl(INADDR_LOOPBACK); #ifdef AF_INET6 case AF_INET6: return IN6_IS_ADDR_LOOPBACK(&store.in6.sin6_addr); #endif default: return false; } } std::string SockAddr::tostring() const { std::ostringstream strm; strm<<(*this); return strm.str(); } SockAddr SockAddr::any(int af, unsigned port) { SockAddr ret(af); switch(af) { case AF_INET: ret->in.sin_addr.s_addr = htonl(INADDR_ANY); ret->in.sin_port = htons(port); break; #ifdef AF_INET6 case AF_INET6: ret->in6.sin6_addr = IN6ADDR_ANY_INIT; ret->in6.sin6_port = htons(port); break; #endif default: throw std::invalid_argument("Unsupported address family"); } return ret; } SockAddr SockAddr::loopback(int af, unsigned port) { SockAddr ret(af); switch(af) { case AF_INET: ret->in.sin_addr.s_addr = htonl(INADDR_LOOPBACK); ret->in.sin_port = htons(port); break; #ifdef AF_INET6 case AF_INET6: ret->in6.sin6_addr = IN6ADDR_LOOPBACK_INIT; ret->in6.sin6_port = htons(port); break; #endif default: throw std::invalid_argument("Unsupported address family"); } return ret; } std::ostream& operator<<(std::ostream& strm, const SockAddr& addr) { switch(addr->sa.sa_family) { case AF_INET: { char buf[INET_ADDRSTRLEN+1]; if(evutil_inet_ntop(AF_INET, &addr->in.sin_addr, buf, sizeof(buf))) { buf[sizeof(buf)-1] = '\0'; // paranoia } else { strm<<"<\?\?\?>"; } strm<in.sin_port); break; } #ifdef AF_INET6 case AF_INET6: { char buf[INET6_ADDRSTRLEN+1]; if(evutil_inet_ntop(AF_INET6, &addr->in6.sin6_addr, buf, sizeof(buf))) { buf[sizeof(buf)-1] = '\0'; // paranoia } else { strm<<"<\?\?\?>"; } strm<in6.sin6_port); break; } #endif case AF_UNSPEC: strm<<"<>"; break; default: strm<<"<\?\?\?>"; } return strm; } } namespace pvxsimpl { namespace detail { template<> unsigned short as_str::op(const char *s) { epicsUInt16 ret; if(int err = epicsParseUInt16(s, &ret, 0, nullptr)) { (void)err; throw std::runtime_error(SB()<<"Unable to parse as uint16 : "<