diff options
| -rw-r--r-- | src/AppleMessageDigestImpl.cc | 17 | ||||
| -rw-r--r-- | src/AppleTLSContext.cc | 26 | ||||
| -rw-r--r-- | src/AppleTLSSession.cc | 62 | ||||
| -rw-r--r-- | src/DownloadEngine.cc | 88 | ||||
| -rw-r--r-- | src/DownloadEngineFactory.cc | 60 | ||||
| -rw-r--r-- | src/LibuvEventPoll.cc | 10 | ||||
| -rw-r--r-- | src/LibuvEventPoll.h | 6 | ||||
| -rw-r--r-- | src/MultiUrlRequestInfo.cc | 29 | ||||
| -rw-r--r-- | src/SocketCore.cc | 329 |
9 files changed, 308 insertions, 319 deletions
diff --git a/src/AppleMessageDigestImpl.cc b/src/AppleMessageDigestImpl.cc index 3416c257..b3966e32 100644 --- a/src/AppleMessageDigestImpl.cc +++ b/src/AppleMessageDigestImpl.cc @@ -37,6 +37,7 @@ #include <CommonCrypto/CommonDigest.h> #include "array_fun.h" +#include "a2functional.h" #include "HashFuncEntry.h" namespace aria2 { @@ -117,29 +118,31 @@ std::unique_ptr<MessageDigestImpl> MessageDigestImpl::create (const std::string& hashType) { if (hashType == "sha-1") { - return std::unique_ptr<MessageDigestImpl>(new MessageDigestSHA1()); + return make_unique<MessageDigestSHA1>(); } if (hashType == "sha-224") { - return std::unique_ptr<MessageDigestImpl>(new MessageDigestSHA224()); + return make_unique<MessageDigestSHA224>(); } if (hashType == "sha-256") { - return std::unique_ptr<MessageDigestImpl>(new MessageDigestSHA256()); + return make_unique<MessageDigestSHA256>(); } if (hashType == "sha-384") { - return std::unique_ptr<MessageDigestImpl>(new MessageDigestSHA384()); + return make_unique<MessageDigestSHA384>(); } if (hashType == "sha-512") { - return std::unique_ptr<MessageDigestImpl>(new MessageDigestSHA512()); + return make_unique<MessageDigestSHA512>(); } if (hashType == "md5") { - return std::unique_ptr<MessageDigestImpl>(new MessageDigestMD5()); + return make_unique<MessageDigestMD5>(); } return nullptr; } bool MessageDigestImpl::supports(const std::string& hashType) { - return hashType == "sha-1" || hashType == "sha-224" || hashType == "sha-256" || hashType == "sha-384" || hashType == "sha-512" || hashType == "md5"; + return hashType == "sha-1" || hashType == "sha-224" || + hashType == "sha-256" || hashType == "sha-384" || + hashType == "sha-512" || hashType == "md5"; } size_t MessageDigestImpl::getDigestLength(const std::string& hashType) diff --git a/src/AppleTLSContext.cc b/src/AppleTLSContext.cc index e4a45768..0c9fe999 100644 --- a/src/AppleTLSContext.cc +++ b/src/AppleTLSContext.cc @@ -58,11 +58,11 @@ namespace { }; #endif // defined(__MAC_10_7) - class cfrelease { + class CFReleaser { const void *ptr_; public: - inline cfrelease(const void *ptr) : ptr_(ptr) {} - inline ~cfrelease() { if (ptr_) CFRelease(ptr_); } + inline CFReleaser(const void *ptr) : ptr_(ptr) {} + inline ~CFReleaser() { if (ptr_) CFRelease(ptr_); } }; static inline bool isWhitespace(char c) @@ -123,13 +123,13 @@ namespace { A2_LOG_ERROR("Failed to get a certref!"); return false; } - cfrelease del_ref(ref); + CFReleaser del_ref(ref); CFDataRef data = SecCertificateCopyData(ref); if (!data) { A2_LOG_ERROR("Failed to get a data!"); return false; } - cfrelease del_data(data); + CFReleaser del_data(data); // Do try all supported hash algorithms. // Usually the fingerprint would be sha1 or md5, however this is more @@ -183,12 +183,12 @@ SecIdentityRef AppleTLSContext::getCredentials() bool AppleTLSContext::tryAsFingerprint(const std::string& fingerprint) { - std::string fp = stripWhitespace(fingerprint); + auto fp = stripWhitespace(fingerprint); // Verify this is a valid hex representation and normalize. fp = util::toHex(util::fromHex(fp.begin(), fp.end())); // Verify this can represent a hash - std::vector<std::string> ht = MessageDigest::getSupportedHashTypes(); + auto ht = MessageDigest::getSupportedHashTypes(); if (std::find_if(ht.begin(), ht.end(), hash_validator(fp)) == ht.end()) { A2_LOG_INFO(fmt("%s is not a fingerprint, invalid hash representation", fingerprint.c_str())); return false; @@ -198,25 +198,25 @@ bool AppleTLSContext::tryAsFingerprint(const std::string& fingerprint) A2_LOG_DEBUG(fmt("Looking for cert with fingerprint %s", fp.c_str())); // Build and run the KeyChain the query. - SecPolicyRef policy = SecPolicyCreateSSL(true, nullptr); + auto policy = SecPolicyCreateSSL(true, nullptr); if (!policy) { A2_LOG_ERROR("Failed to create SecPolicy"); return false; } - cfrelease del_policy(policy); + CFReleaser del_policy(policy); const void *query_values[] = { kSecClassIdentity, kCFBooleanTrue, policy, kSecMatchLimitAll }; - CFDictionaryRef query = CFDictionaryCreate(nullptr, query_keys, query_values, - 4, nullptr, nullptr); + auto query = CFDictionaryCreate(nullptr, query_keys, query_values, 4, + nullptr, nullptr); if (!query) { A2_LOG_ERROR("Failed to create identity query"); return false; } - cfrelease del_query(query); + CFReleaser del_query(query); CFArrayRef identities; OSStatus err = SecItemCopyMatching(query, (CFTypeRef*)&identities); if (err != errSecSuccess) { @@ -254,7 +254,7 @@ bool AppleTLSContext::tryAsFingerprint(const std::string& fingerprint) if (err != errSecSuccess) { A2_LOG_ERROR("Certificate search failed: " + errToString(err)); } - cfrelease del_search(search); + CFReleaser del_search(search); SecIdentityRef id; while (SecIdentitySearchCopyNext(search, &id) == errSecSuccess) { diff --git a/src/AppleTLSSession.cc b/src/AppleTLSSession.cc index d34282ec..074d27b0 100644 --- a/src/AppleTLSSession.cc +++ b/src/AppleTLSSession.cc @@ -326,8 +326,8 @@ AppleTLSSession::AppleTLSSession(AppleTLSContext* ctx) state_ = st_error; return; } - for (SSLCipherSuiteList::iterator i = enabled.begin(), e = enabled.end(); i != e; ++i) { - A2_LOG_INFO(fmt("AppleTLS: Enabled suite %s", suiteToString(*i))); + for (const auto& suite: enabled) { + A2_LOG_INFO(fmt("AppleTLS: Enabled suite %s", suiteToString(suite))); } if (SSLSetEnabledCiphers(sslCtx_, &enabled[0], enabled.size()) != noErr) { A2_LOG_ERROR("AppleTLS: Failed to set enabled ciphers list"); @@ -336,37 +336,39 @@ AppleTLSSession::AppleTLSSession(AppleTLSContext* ctx) } #endif - if (ctx->getSide() == TLS_SERVER) { - SecIdentityRef creds = ctx->getCredentials(); - if (!creds) { - A2_LOG_ERROR("AppleTLS: No credentials"); - state_ = st_error; - return; - } - CFArrayRef certs = CFArrayCreate(nullptr, (const void**)&creds, 1, nullptr); - if (!certs) { - A2_LOG_ERROR("AppleTLS: Failed to setup credentials"); - state_ = st_error; - return; - } - std::unique_ptr<void, decltype(&CFRelease)> del_certs((void*)certs, CFRelease); - lastError_ = SSLSetCertificate(sslCtx_, certs); - if (lastError_ != noErr) { - A2_LOG_ERROR(fmt("AppleTLS: Failed to set credentials: %s", getLastErrorString().c_str())); - state_ = st_error; - return; - } + if (ctx->getSide() != TLS_SERVER) { + // Done with client-only initialization + return; + } -#ifndef CIPHER_NO_DHPARAM - lastError_ = SSLSetDiffieHellmanParams(sslCtx_, dhparam, sizeof(dhparam)); - if (lastError_ != noErr) { - A2_LOG_WARN(fmt("AppleTLS: Failed to set DHParams: %s", getLastErrorString().c_str())); - // Engine will still generate some for us, so this is no problem, except - // it will take longer. - } -#endif // CIPHER_NO_DHPARAM + SecIdentityRef creds = ctx->getCredentials(); + if (!creds) { + A2_LOG_ERROR("AppleTLS: No credentials"); + state_ = st_error; + return; + } + CFArrayRef certs = CFArrayCreate(nullptr, (const void**)&creds, 1, nullptr); + if (!certs) { + A2_LOG_ERROR("AppleTLS: Failed to setup credentials"); + state_ = st_error; + return; + } + std::unique_ptr<void, decltype(&CFRelease)> del_certs((void*)certs, CFRelease); + lastError_ = SSLSetCertificate(sslCtx_, certs); + if (lastError_ != noErr) { + A2_LOG_ERROR(fmt("AppleTLS: Failed to set credentials: %s", getLastErrorString().c_str())); + state_ = st_error; + return; + } +#ifndef CIPHER_NO_DHPARAM + lastError_ = SSLSetDiffieHellmanParams(sslCtx_, dhparam, sizeof(dhparam)); + if (lastError_ != noErr) { + A2_LOG_WARN(fmt("AppleTLS: Failed to set DHParams: %s", getLastErrorString().c_str())); + // Engine will still generate some for us, so this is no problem, except + // it will take longer. } +#endif // CIPHER_NO_DHPARAM } AppleTLSSession::~AppleTLSSession() diff --git a/src/DownloadEngine.cc b/src/DownloadEngine.cc index 04c44d24..efa86950 100644 --- a/src/DownloadEngine.cc +++ b/src/DownloadEngine.cc @@ -124,27 +124,28 @@ void executeCommand(std::deque<std::unique_ptr<Command>>& commands, for(size_t i = 0; i < max; ++i) { auto com = std::move(commands.front()); commands.pop_front(); - if(com->statusMatch(statusFilter)) { - com->transitStatus(); - if(com->execute()) { - com.reset(); - } else { - com->clearIOEvents(); - com.release(); - } - } else { + if (!com->statusMatch(statusFilter)) { com->clearIOEvents(); commands.push_back(std::move(com)); + continue; + } + com->transitStatus(); + if (com->execute()) { + com.reset(); + } + else { + com->clearIOEvents(); + com.release(); } } } } // namespace namespace { -class GHR { +class GlobalHaltRequestedFinalizer { public: - GHR() {} - ~GHR() + GlobalHaltRequestedFinalizer() {} + ~GlobalHaltRequestedFinalizer() { global::globalHaltRequested = 5; } @@ -153,7 +154,7 @@ public: int DownloadEngine::run(bool oneshot) { - GHR ghr; + GlobalHaltRequestedFinalizer ghrf; while(!commands_.empty() || !routineCommands_.empty()) { if(!commands_.empty()) { waitData(); @@ -243,12 +244,16 @@ void DownloadEngine::afterEachIteration() global::globalHaltRequested = 2; setNoWait(true); setRefreshInterval(0); - } else if(global::globalHaltRequested == 3) { + return; + } + + if(global::globalHaltRequested == 3) { A2_LOG_NOTICE(_("Emergency shutdown sequence commencing...")); requestForceHalt(); global::globalHaltRequested = 4; setNoWait(true); setRefreshInterval(0); + return; } } @@ -300,20 +305,21 @@ void DownloadEngine::poolSocket(const std::string& key, std::multimap<std::string, SocketPoolEntry>::value_type p(key, entry); socketPool_.insert(p); - if(lastSocketPoolScan_.difference(global::wallclock()) >= 60) { - std::multimap<std::string, SocketPoolEntry> newPool; - A2_LOG_DEBUG("Scaning SocketPool and erasing timed out entry."); - lastSocketPoolScan_ = global::wallclock(); - for(auto & elem : socketPool_) { - if(!elem.second.isTimeout()) { - newPool.insert(elem); - } + if(lastSocketPoolScan_.difference(global::wallclock()) < 60) { + return; + } + std::multimap<std::string, SocketPoolEntry> newPool; + A2_LOG_DEBUG("Scaning SocketPool and erasing timed out entry."); + lastSocketPoolScan_ = global::wallclock(); + for(auto & elem : socketPool_) { + if(!elem.second.isTimeout()) { + newPool.insert(elem); } - A2_LOG_DEBUG(fmt("%lu entries removed.", - static_cast<unsigned long> - (socketPool_.size()-newPool.size()))); - socketPool_ = newPool; } + A2_LOG_DEBUG(fmt("%lu entries removed.", + static_cast<unsigned long> + (socketPool_.size()-newPool.size()))); + socketPool_ = newPool; } namespace { @@ -382,17 +388,18 @@ void DownloadEngine::poolSocket(const std::shared_ptr<Request>& request, const std::shared_ptr<SocketCore>& socket, time_t timeout) { - if(!proxyRequest) { - std::pair<std::string, uint16_t> peerInfo; - if(getPeerInfo(peerInfo, socket)) { - poolSocket(peerInfo.first, peerInfo.second, - A2STR::NIL, 0, socket, timeout); - } - } else { + if(proxyRequest) { // If proxy is defined, then pool socket with its hostname. poolSocket(request->getHost(), request->getPort(), proxyRequest->getHost(), proxyRequest->getPort(), socket, timeout); + return; + } + + std::pair<std::string, uint16_t> peerInfo; + if(getPeerInfo(peerInfo, socket)) { + poolSocket(peerInfo.first, peerInfo.second, + A2STR::NIL, 0, socket, timeout); } } @@ -404,17 +411,18 @@ void DownloadEngine::poolSocket const std::string& options, time_t timeout) { - if(!proxyRequest) { - std::pair<std::string, uint16_t> peerInfo; - if(getPeerInfo(peerInfo, socket)) { - poolSocket(peerInfo.first, peerInfo.second, username, - A2STR::NIL, 0, socket, options, timeout); - } - } else { + if(proxyRequest) { // If proxy is defined, then pool socket with its hostname. poolSocket(request->getHost(), request->getPort(), username, proxyRequest->getHost(), proxyRequest->getPort(), socket, options, timeout); + return; + } + + std::pair<std::string, uint16_t> peerInfo; + if(getPeerInfo(peerInfo, socket)) { + poolSocket(peerInfo.first, peerInfo.second, username, + A2STR::NIL, 0, socket, options, timeout); } } diff --git a/src/DownloadEngineFactory.cc b/src/DownloadEngineFactory.cc index 2cfef18a..1dd6aaa3 100644 --- a/src/DownloadEngineFactory.cc +++ b/src/DownloadEngineFactory.cc @@ -91,58 +91,54 @@ std::unique_ptr<EventPoll> createEventPoll(Option* op) #ifdef HAVE_LIBUV if (pollMethod == V_LIBUV) { auto ep = make_unique<LibuvEventPoll>(); - if(ep->good()) { - return std::move(ep); - } else { + if(!ep->good()) { throw DL_ABORT_EX("Initializing LibuvEventPoll failed." " Try --event-poll=select"); } + return std::move(ep); } else #endif // HAVE_LIBUV #ifdef HAVE_EPOLL if(pollMethod == V_EPOLL) { auto ep = make_unique<EpollEventPoll>(); - if(ep->good()) { - return std::move(ep); - } else { + if(!ep->good()) { throw DL_ABORT_EX("Initializing EpollEventPoll failed." " Try --event-poll=select"); } + return std::move(ep); } else #endif // HAVE_EPLL #ifdef HAVE_KQUEUE - if(pollMethod == V_KQUEUE) { - auto kp = make_unique<KqueueEventPoll>(); - if(kp->good()) { - return std::move(kp); - } else { - throw DL_ABORT_EX("Initializing KqueueEventPoll failed." - " Try --event-poll=select"); - } - } else + if(pollMethod == V_KQUEUE) { + auto kp = make_unique<KqueueEventPoll>(); + if(!kp->good()) { + throw DL_ABORT_EX("Initializing KqueueEventPoll failed." + " Try --event-poll=select"); + } + return std::move(kp); + } else #endif // HAVE_KQUEUE #ifdef HAVE_PORT_ASSOCIATE - if(pollMethod == V_PORT) { - auto pp = make_unique<PortEventPoll>(); - if(pp->good()) { - return std::move(pp); - } else { - throw DL_ABORT_EX("Initializing PortEventPoll failed." - " Try --event-poll=select"); - } - } else + if(pollMethod == V_PORT) { + auto pp = make_unique<PortEventPoll>(); + if(!pp->good()) { + throw DL_ABORT_EX("Initializing PortEventPoll failed." + " Try --event-poll=select"); + } + return std::move(pp); + } else #endif // HAVE_PORT_ASSOCIATE #ifdef HAVE_POLL - if(pollMethod == V_POLL) { - return make_unique<PollEventPoll>(); - } else + if(pollMethod == V_POLL) { + return make_unique<PollEventPoll>(); + } else #endif // HAVE_POLL - if(pollMethod == V_SELECT) { - return make_unique<SelectEventPoll>(); - } else { - assert(0); - } + if(pollMethod == V_SELECT) { + return make_unique<SelectEventPoll>(); + } + assert(0); + return nullptr; } } // namespace diff --git a/src/LibuvEventPoll.cc b/src/LibuvEventPoll.cc index 07d60a1e..791d8521 100644 --- a/src/LibuvEventPoll.cc +++ b/src/LibuvEventPoll.cc @@ -107,8 +107,8 @@ LibuvEventPoll::LibuvEventPoll() LibuvEventPoll::~LibuvEventPoll() { - for (KPolls::iterator i = polls_.begin(), e = polls_.end(); i != e; ++i) { - i->second->close(); + for (auto& p: polls_) { + p.second->close(); } // Actually kill the polls, and timers, if any. uv_run(loop_, (uv_run_mode)(UV_RUN_ONCE | UV_RUN_NOWAIT)); @@ -256,8 +256,8 @@ bool LibuvEventPoll::addEvents(sock_t socket, Command* command, int events, bool LibuvEventPoll::deleteEvents(sock_t socket, const LibuvEventPoll::KEvent& event) { - std::shared_ptr<KSocketEntry> socketEntry(new KSocketEntry(socket)); - KSocketEntrySet::iterator i = socketEntries_.find(socketEntry); + auto socketEntry = std::make_shared<KSocketEntry>(socket); + auto i = socketEntries_.find(socketEntry); if (i == socketEntries_.end()) { A2_LOG_DEBUG(fmt("Socket %d is not found in SocketEntries.", socket)); @@ -266,7 +266,7 @@ bool LibuvEventPoll::deleteEvents(sock_t socket, event.removeSelf(*i); - KPolls::iterator poll = polls_.find(socket); + auto poll = polls_.find(socket); if (poll == polls_.end()) { return false; } diff --git a/src/LibuvEventPoll.h b/src/LibuvEventPoll.h index a6974d1b..b56b9afb 100644 --- a/src/LibuvEventPoll.h +++ b/src/LibuvEventPoll.h @@ -76,7 +76,7 @@ private: uv_poll_t handle_; static void poll_callback(uv_poll_t* handle, int status, int events) { - KPoll* poll = static_cast<KPoll*>(handle->data); + auto poll = static_cast<KPoll*>(handle->data); poll->eventer_->pollCallback(poll, status, events); } static void close_callback(uv_handle_t* handle) { @@ -87,8 +87,8 @@ private: inline KPoll(LibuvEventPoll* eventer, KSocketEntry* entry, sock_t sock) : eventer_(eventer), entry_(entry) { - uv_poll_init_socket(eventer->loop_, &handle_, sock); - handle_.data = this; + uv_poll_init_socket(eventer->loop_, &handle_, sock); + handle_.data = this; } inline void start() { uv_poll_start(&handle_, entry_->getEvents() & IEV_RW, poll_callback); diff --git a/src/MultiUrlRequestInfo.cc b/src/MultiUrlRequestInfo.cc index 8f54c4e3..8347e331 100644 --- a/src/MultiUrlRequestInfo.cc +++ b/src/MultiUrlRequestInfo.cc @@ -134,14 +134,12 @@ std::unique_ptr<StatCalc> getStatCalc(const std::shared_ptr<Option>& op) { if(op->getAsBool(PREF_QUIET)) { return make_unique<NullStatCalc>(); - } else { - auto impl = make_unique<ConsoleStatCalc> - (op->getAsInt(PREF_SUMMARY_INTERVAL), - op->getAsBool(PREF_HUMAN_READABLE)); - impl->setReadoutVisibility(op->getAsBool(PREF_SHOW_CONSOLE_READOUT)); - impl->setTruncate(op->getAsBool(PREF_TRUNCATE_CONSOLE_READOUT)); - return std::move(impl); } + auto impl = make_unique<ConsoleStatCalc>(op->getAsInt(PREF_SUMMARY_INTERVAL), + op->getAsBool(PREF_HUMAN_READABLE)); + impl->setReadoutVisibility(op->getAsBool(PREF_SHOW_CONSOLE_READOUT)); + impl->setTruncate(op->getAsBool(PREF_TRUNCATE_CONSOLE_READOUT)); + return std::move(impl); } } // namespace @@ -183,21 +181,20 @@ int MultiUrlRequestInfo::prepare() #ifdef ENABLE_SSL if(option_->getAsBool(PREF_ENABLE_RPC) && option_->getAsBool(PREF_RPC_SECURE)) { - if(!option_->blank(PREF_RPC_CERTIFICATE) + if(option_->blank(PREF_RPC_CERTIFICATE) #ifndef HAVE_APPLETLS - && !option_->blank(PREF_RPC_PRIVATE_KEY) + || option_->blank(PREF_RPC_PRIVATE_KEY) #endif // HAVE_APPLETLS ) { - // We set server TLS context to the SocketCore before creating - // DownloadEngine instance. - std::shared_ptr<TLSContext> svTlsContext(TLSContext::make(TLS_SERVER)); - svTlsContext->addCredentialFile(option_->get(PREF_RPC_CERTIFICATE), - option_->get(PREF_RPC_PRIVATE_KEY)); - SocketCore::setServerTLSContext(svTlsContext); - } else { throw DL_ABORT_EX("Specify --rpc-certificate and --rpc-private-key " "options in order to use secure RPC."); } + // We set server TLS context to the SocketCore before creating + // DownloadEngine instance. + std::shared_ptr<TLSContext> svTlsContext(TLSContext::make(TLS_SERVER)); + svTlsContext->addCredentialFile(option_->get(PREF_RPC_CERTIFICATE), + option_->get(PREF_RPC_PRIVATE_KEY)); + SocketCore::setServerTLSContext(svTlsContext); } #endif // ENABLE_SSL diff --git a/src/SocketCore.cc b/src/SocketCore.cc index 64867536..585ec634 100644 --- a/src/SocketCore.cc +++ b/src/SocketCore.cc @@ -270,9 +270,8 @@ void SocketCore::bindWithFamily(uint16_t port, int family, int flags) sock_t fd = bindTo(nullptr, port, family, sockType_, flags, error); if(fd == (sock_t) -1) { throw DL_ABORT_EX(fmt(EX_SOCKET_BIND, error.c_str())); - } else { - sockfd_ = fd; } + sockfd_ = fd; } void SocketCore::bind @@ -288,30 +287,30 @@ void SocketCore::bind } if(!(flags&AI_PASSIVE) || bindAddrs_.empty()) { sock_t fd = bindTo(addrp, port, family, sockType_, flags, error); - if(fd != (sock_t) -1) { - sockfd_ = fd; + if(fd == (sock_t) -1) { + throw DL_ABORT_EX(fmt(EX_SOCKET_BIND, error.c_str())); } - } else { - for(std::vector<std::pair<sockaddr_union, socklen_t> >:: - const_iterator i = bindAddrs_.begin(), eoi = bindAddrs_.end(); - i != eoi; ++i) { - char host[NI_MAXHOST]; - int s; - s = getnameinfo(&(*i).first.sa, (*i).second, host, NI_MAXHOST, nullptr, 0, - NI_NUMERICHOST); - if(s) { - error = gai_strerror(s); - continue; - } - if(addrp && strcmp(host, addrp) != 0) { - error = "Given address and resolved address do not match."; - continue; - } - sock_t fd = bindTo(host, port, family, sockType_, flags, error); - if(fd != (sock_t)-1) { - sockfd_ = fd; - break; - } + sockfd_ = fd; + return; + } + + for (const auto& a : bindAddrs_) { + char host[NI_MAXHOST]; + int s; + s = getnameinfo(&a.first.sa, a.second, host, NI_MAXHOST, nullptr, 0, + NI_NUMERICHOST); + if(s) { + error = gai_strerror(s); + continue; + } + if(addrp && strcmp(host, addrp) != 0) { + error = "Given address and resolved address do not match."; + continue; + } + sock_t fd = bindTo(host, port, family, sockType_, flags, error); + if(fd != (sock_t)-1) { + sockfd_ = fd; + break; } } if(sockfd_ == (sock_t) -1) { @@ -329,11 +328,10 @@ void SocketCore::bind(const struct sockaddr* addr, socklen_t addrlen) closeConnection(); std::string error; sock_t fd = bindInternal(addr->sa_family, sockType_, 0, addr, addrlen, error); - if(fd != (sock_t)-1) { - sockfd_ = fd; - } else { + if(fd == (sock_t)-1) { throw DL_ABORT_EX(fmt(EX_SOCKET_BIND, error.c_str())); } + sockfd_ = fd; } void SocketCore::beginListen() @@ -486,11 +484,10 @@ void SocketCore::setMulticastInterface(const std::string& localAddr) in_addr addr; if(localAddr.empty()) { addr.s_addr = htonl(INADDR_ANY); - } else { - if(inetPton(AF_INET, localAddr.c_str(), &addr) != 0) { - throw DL_ABORT_EX(fmt("%s is not valid IPv4 numeric address", - localAddr.c_str())); - } + } + else if(inetPton(AF_INET, localAddr.c_str(), &addr) != 0) { + throw DL_ABORT_EX(fmt("%s is not valid IPv4 numeric address", + localAddr.c_str())); } setSockOpt(IPPROTO_IP, IP_MULTICAST_IF, &addr, sizeof(addr)); } @@ -517,11 +514,10 @@ void SocketCore::joinMulticastGroup in_addr ifAddr; if(localAddr.empty()) { ifAddr.s_addr = htonl(INADDR_ANY); - } else { - if(inetPton(AF_INET, localAddr.c_str(), &ifAddr) != 0) { - throw DL_ABORT_EX(fmt("%s is not valid IPv4 numeric address", - localAddr.c_str())); - } + } + else if(inetPton(AF_INET, localAddr.c_str(), &ifAddr) != 0) { + throw DL_ABORT_EX(fmt("%s is not valid IPv4 numeric address", + localAddr.c_str())); } struct ip_mreq mreq; memset(&mreq, 0, sizeof(mreq)); @@ -605,11 +601,11 @@ bool SocketCore::isWritable(time_t timeout) int errNum = SOCKET_ERRNO; if(r > 0) { return p.revents&(POLLOUT|POLLHUP|POLLERR); - } else if(r == 0) { + } + if(r == 0) { return false; - } else { - throw DL_RETRY_EX(fmt(EX_SOCKET_CHECK_WRITABLE, errorMsg(errNum).c_str())); } + throw DL_RETRY_EX(fmt(EX_SOCKET_CHECK_WRITABLE, errorMsg(errNum).c_str())); #else // !HAVE_POLL # ifndef __MINGW32__ CHECK_FD(sockfd_); @@ -626,17 +622,15 @@ bool SocketCore::isWritable(time_t timeout) int errNum = SOCKET_ERRNO; if(r == 1) { return true; - } else if(r == 0) { + } + if(r == 0) { // time out return false; - } else { - if(errNum == A2_EINPROGRESS || errNum == A2_EINTR) { - return false; - } else { - throw DL_RETRY_EX - (fmt(EX_SOCKET_CHECK_WRITABLE, errorMsg(errNum).c_str())); - } } + if(errNum == A2_EINPROGRESS || errNum == A2_EINTR) { + return false; + } + throw DL_RETRY_EX(fmt(EX_SOCKET_CHECK_WRITABLE, errorMsg(errNum).c_str())); #endif // !HAVE_POLL } @@ -651,11 +645,11 @@ bool SocketCore::isReadable(time_t timeout) int errNum = SOCKET_ERRNO; if(r > 0) { return p.revents&(POLLIN|POLLHUP|POLLERR); - } else if(r == 0) { + } + if(r == 0) { return false; - } else { - throw DL_RETRY_EX(fmt(EX_SOCKET_CHECK_READABLE, errorMsg(errNum).c_str())); } + throw DL_RETRY_EX(fmt(EX_SOCKET_CHECK_READABLE, errorMsg(errNum).c_str())); #else // !HAVE_POLL # ifndef __MINGW32__ CHECK_FD(sockfd_); @@ -672,17 +666,15 @@ bool SocketCore::isReadable(time_t timeout) int errNum = SOCKET_ERRNO; if(r == 1) { return true; - } else if(r == 0) { + } + if(r == 0) { // time out return false; - } else { - if(errNum == A2_EINPROGRESS || errNum == A2_EINTR) { - return false; - } else { - throw DL_RETRY_EX - (fmt(EX_SOCKET_CHECK_READABLE, errorMsg(errNum).c_str())); - } } + if(errNum == A2_EINPROGRESS || errNum == A2_EINTR) { + return false; + } + throw DL_RETRY_EX(fmt(EX_SOCKET_CHECK_READABLE, errorMsg(errNum).c_str())); #endif // !HAVE_POLL } @@ -706,12 +698,11 @@ ssize_t SocketCore::writeVector(a2iovec *iov, size_t iovcnt) #endif // !__MINGW32__ int errNum = SOCKET_ERRNO; if(ret == -1) { - if(A2_WOULDBLOCK(errNum)) { - wantWrite_ = true; - ret = 0; - } else { + if(!A2_WOULDBLOCK(errNum)) { throw DL_RETRY_EX(fmt(EX_SOCKET_SEND, errorMsg(errNum).c_str())); } + wantWrite_ = true; + ret = 0; } } else { // For SSL/TLS, we could not use writev, so just iterate vector @@ -739,28 +730,26 @@ ssize_t SocketCore::writeData(const void* data, size_t len) len, 0)) == -1 && SOCKET_ERRNO == A2_EINTR); int errNum = SOCKET_ERRNO; if(ret == -1) { - if(A2_WOULDBLOCK(errNum)) { - wantWrite_ = true; - ret = 0; - } else { + if(!A2_WOULDBLOCK(errNum)) { throw DL_RETRY_EX(fmt(EX_SOCKET_SEND, errorMsg(errNum).c_str())); } + wantWrite_ = true; + ret = 0; } } else { #ifdef ENABLE_SSL ret = tlsSession_->writeData(data, len); if(ret < 0) { - if(ret == TLS_ERR_WOULDBLOCK) { - if(tlsSession_->checkDirection() == TLS_WANT_READ) { - wantRead_ = true; - } else { - wantWrite_ = true; - } - ret = 0; - } else { + if(ret != TLS_ERR_WOULDBLOCK) { throw DL_RETRY_EX(fmt(EX_SOCKET_SEND, tlsSession_->getLastErrorString().c_str())); } + if(tlsSession_->checkDirection() == TLS_WANT_READ) { + wantRead_ = true; + } else { + wantWrite_ = true; + } + ret = 0; } #endif // ENABLE_SSL } @@ -779,28 +768,26 @@ void SocketCore::readData(void* data, size_t& len) SOCKET_ERRNO == A2_EINTR); int errNum = SOCKET_ERRNO; if(ret == -1) { - if(A2_WOULDBLOCK(errNum)) { - wantRead_ = true; - ret = 0; - } else { + if(!A2_WOULDBLOCK(errNum)) { throw DL_RETRY_EX(fmt(EX_SOCKET_RECV, errorMsg(errNum).c_str())); } + wantRead_ = true; + ret = 0; } } else { #ifdef ENABLE_SSL ret = tlsSession_->readData(data, len); if(ret < 0) { - if(ret == TLS_ERR_WOULDBLOCK) { - if(tlsSession_->checkDirection() == TLS_WANT_READ) { - wantRead_ = true; - } else { - wantWrite_ = true; - } - ret = 0; - } else { + if(ret != TLS_ERR_WOULDBLOCK) { throw DL_RETRY_EX(fmt(EX_SOCKET_SEND, tlsSession_->getLastErrorString().c_str())); } + if(tlsSession_->checkDirection() == TLS_WANT_READ) { + wantRead_ = true; + } else { + wantWrite_ = true; + } + ret = 0; } #endif // ENABLE_SSL } @@ -855,20 +842,20 @@ bool SocketCore::tlsHandshake(TLSContext* tlsctx, const std::string& hostname) } if(rv == TLS_ERR_OK) { secure_ = A2_TLS_CONNECTED; - } else if(rv == TLS_ERR_WOULDBLOCK) { - if(tlsSession_->checkDirection() == TLS_WANT_READ) { - wantRead_ = true; - } else { - wantWrite_ = true; - } - return false; - } else { + break; + } + if(rv != TLS_ERR_WOULDBLOCK) { throw DL_ABORT_EX(fmt("SSL/TLS handshake failure: %s", handshakeError.empty() ? tlsSession_->getLastErrorString().c_str() : handshakeError.c_str())); } - break; + if(tlsSession_->checkDirection() == TLS_WANT_READ) { + wantRead_ = true; + } else { + wantWrite_ = true; + } + return false; default: break; } @@ -931,12 +918,11 @@ ssize_t SocketCore::readDataFrom(void* data, size_t len, && A2_EINTR == SOCKET_ERRNO); int errNum = SOCKET_ERRNO; if(r == -1) { - if(A2_WOULDBLOCK(errNum)) { - wantRead_ = true; - r = 0; - } else { + if(!A2_WOULDBLOCK(errNum)) { throw DL_RETRY_EX(fmt(EX_SOCKET_RECV, errorMsg(errNum).c_str())); } + wantRead_ = true; + r = 0; } else { sender = util::getNumericNameInfo(&sockaddr.sa, sockaddrlen); } @@ -957,9 +943,8 @@ std::string SocketCore::getSocketError() const } if(error != 0) { return errorMsg(error); - } else { - return ""; } + return ""; } bool SocketCore::wantRead() const @@ -977,20 +962,17 @@ void SocketCore::bindAddress(const std::string& iface) std::vector<std::pair<sockaddr_union, socklen_t> > bindAddrs; getInterfaceAddress(bindAddrs, iface, protocolFamily_); if(bindAddrs.empty()) { - throw DL_ABORT_EX - (fmt(MSG_INTERFACE_NOT_FOUND, iface.c_str(), "not available")); - } else { - bindAddrs_.swap(bindAddrs); - for(std::vector<std::pair<sockaddr_union, socklen_t> >:: - const_iterator i = bindAddrs_.begin(), eoi = bindAddrs_.end(); - i != eoi; ++i) { - char host[NI_MAXHOST]; - int s; - s = getnameinfo(&(*i).first.sa, (*i).second, host, NI_MAXHOST, nullptr, 0, - NI_NUMERICHOST); - if(s == 0) { - A2_LOG_DEBUG(fmt("Sockets will bind to %s", host)); - } + throw DL_ABORT_EX(fmt(MSG_INTERFACE_NOT_FOUND, iface.c_str(), + "not available")); + } + bindAddrs_.swap(bindAddrs); + for (const auto& a: bindAddrs_) { + char host[NI_MAXHOST]; + int s; + s = getnameinfo(&a.first.sa, a.second, host, NI_MAXHOST, nullptr, 0, + NI_NUMERICHOST); + if(s == 0) { + A2_LOG_DEBUG(fmt("Sockets will bind to %s", host)); } } } @@ -1101,7 +1083,6 @@ int callGetaddrinfo int inetNtop(int af, const void* src, char* dst, socklen_t size) { - int s; sockaddr_union su; memset(&su, 0, sizeof(su)); if(af == AF_INET) { @@ -1110,20 +1091,19 @@ int inetNtop(int af, const void* src, char* dst, socklen_t size) su.in.sin_len = sizeof(su.in); #endif // HAVE_SOCKADDR_IN_SIN_LEN memcpy(&su.in.sin_addr, src, sizeof(su.in.sin_addr)); - s = getnameinfo(&su.sa, sizeof(su.in), - dst, size, nullptr, 0, NI_NUMERICHOST); - } else if(af == AF_INET6) { + return getnameinfo(&su.sa, sizeof(su.in), dst, size, nullptr, 0, + NI_NUMERICHOST); + } + if(af == AF_INET6) { su.in6.sin6_family = AF_INET6; #ifdef HAVE_SOCKADDR_IN6_SIN6_LEN su.in6.sin6_len = sizeof(su.in6); #endif // HAVE_SOCKADDR_IN6_SIN6_LEN memcpy(&su.in6.sin6_addr, src, sizeof(su.in6.sin6_addr)); - s = getnameinfo(&su.sa, sizeof(su.in6), - dst, size, nullptr, 0, NI_NUMERICHOST); - } else { - s = EAI_FAMILY; + return getnameinfo(&su.sa, sizeof(su.in6), dst, size, nullptr, 0, + NI_NUMERICHOST); } - return s; + return EAI_FAMILY; } int inetPton(int af, const char* src, void* dst) @@ -1139,16 +1119,17 @@ int inetPton(int af, const char* src, void* dst) } in_addr* addr = reinterpret_cast<in_addr*>(dst); addr->s_addr = binaddr.ipv4_addr; - } else if(af == AF_INET6) { + return 0; + } + if(af == AF_INET6) { if(len != 16) { return -1; } in6_addr* addr = reinterpret_cast<in6_addr*>(dst); memcpy(addr->s6_addr, binaddr.ipv6_addr, sizeof(addr->s6_addr)); - } else { - return -1; + return 0; } - return 0; + return -1; } namespace net { @@ -1200,14 +1181,15 @@ bool verifyHostname(const std::string& hostname, return true; } } - } else { - if(dnsNames.empty()) { - return util::tlsHostnameMatch(commonName, hostname); - } - for(auto i = dnsNames.begin(), eoi = dnsNames.end(); i != eoi; ++i) { - if(util::tlsHostnameMatch(*i, hostname)) { - return true; - } + return false; + } + + if(dnsNames.empty()) { + return util::tlsHostnameMatch(commonName, hostname); + } + for(auto i = dnsNames.begin(), eoi = dnsNames.end(); i != eoi; ++i) { + if(util::tlsHostnameMatch(*i, hostname)) { + return true; } } return false; @@ -1237,12 +1219,11 @@ void checkAddrconfig() do { buf = reinterpret_cast<IP_ADAPTER_ADDRESSES*>(malloc(bufsize)); retval = GetAdaptersAddresses(AF_UNSPEC, 0, 0, buf, &bufsize); - if(retval == ERROR_BUFFER_OVERFLOW) { - free(buf); - buf = 0; - } else { + if(retval != ERROR_BUFFER_OVERFLOW) { break; } + free(buf); + buf = 0; } while(retval == ERROR_BUFFER_OVERFLOW && numTry < MAX_TRY); if(retval != NO_ERROR) { A2_LOG_INFO("GetAdaptersAddresses failed. Assume both IPv4 and IPv6 " @@ -1261,44 +1242,46 @@ void checkAddrconfig() continue; } PIP_ADAPTER_UNICAST_ADDRESS ucaddr = p->FirstUnicastAddress; - if(ucaddr) { - for(PIP_ADAPTER_UNICAST_ADDRESS i = ucaddr; i; i = i->Next) { - bool found = false; - switch(i->Address.iSockaddrLength) { - case sizeof(sockaddr_in): { - memcpy(&ad.storage, i->Address.lpSockaddr, - i->Address.iSockaddrLength); - uint32_t haddr = ntohl(ad.in.sin_addr.s_addr); - if(haddr != INADDR_LOOPBACK && - (haddr < APIPA_IPV4_BEGIN || APIPA_IPV4_END <= haddr)) { - ipv4AddrConfigured = true; - found = true; - } - break; + if(!ucaddr) { + continue; + } + for(PIP_ADAPTER_UNICAST_ADDRESS i = ucaddr; i; i = i->Next) { + bool found = false; + switch(i->Address.iSockaddrLength) { + case sizeof(sockaddr_in): { + memcpy(&ad.storage, i->Address.lpSockaddr, + i->Address.iSockaddrLength); + uint32_t haddr = ntohl(ad.in.sin_addr.s_addr); + if(haddr != INADDR_LOOPBACK && + (haddr < APIPA_IPV4_BEGIN || APIPA_IPV4_END <= haddr)) { + ipv4AddrConfigured = true; + found = true; } - case sizeof(sockaddr_in6): - memcpy(&ad.storage, i->Address.lpSockaddr, - i->Address.iSockaddrLength); - if(!IN6_IS_ADDR_LOOPBACK(&ad.in6.sin6_addr) && - !IN6_IS_ADDR_LINKLOCAL(&ad.in6.sin6_addr)) { - ipv6AddrConfigured = true; - found = true; - } - break; + break; + } + case sizeof(sockaddr_in6): + memcpy(&ad.storage, i->Address.lpSockaddr, + i->Address.iSockaddrLength); + if(!IN6_IS_ADDR_LOOPBACK(&ad.in6.sin6_addr) && + !IN6_IS_ADDR_LINKLOCAL(&ad.in6.sin6_addr)) { + ipv6AddrConfigured = true; + found = true; } - rv = getnameinfo(i->Address.lpSockaddr, i->Address.iSockaddrLength, - host, NI_MAXHOST, 0, 0, NI_NUMERICHOST); - if(rv == 0) { - if(found) { - A2_LOG_INFO(fmt("Found configured address: %s", host)); - } else { - A2_LOG_INFO(fmt("Not considered: %s", host)); - } + break; + } + rv = getnameinfo(i->Address.lpSockaddr, i->Address.iSockaddrLength, + host, NI_MAXHOST, 0, 0, NI_NUMERICHOST); + if(rv == 0) { + if(found) { + A2_LOG_INFO(fmt("Found configured address: %s", host)); + } else { + A2_LOG_INFO(fmt("Not considered: %s", host)); } } } } free(buf); + A2_LOG_INFO(fmt("IPv4 configured=%d, IPv6 configured=%d", ipv4AddrConfigured, ipv6AddrConfigured)); #elif defined(HAVE_GETIFADDRS) |
