More code cleanups

pull/119/head
Nils Maier 2013-08-21 06:06:10 +02:00
parent 8526ceeb45
commit cf6f58ceec
9 changed files with 311 additions and 322 deletions

View File

@ -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)

View File

@ -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) {

View File

@ -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;
}
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
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()

View File

@ -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);
}
}
A2_LOG_DEBUG(fmt("%lu entries removed.",
static_cast<unsigned long>
(socketPool_.size()-newPool.size())));
socketPool_ = newPool;
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;
}
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);
}
}

View File

@ -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

View File

@ -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;
}

View File

@ -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);

View File

@ -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

View File

@ -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) {
return false;
} else {
throw DL_RETRY_EX(fmt(EX_SOCKET_CHECK_WRITABLE, errorMsg(errNum).c_str()));
}
if(r == 0) {
return false;
}
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) {
return false;
} else {
throw DL_RETRY_EX(fmt(EX_SOCKET_CHECK_READABLE, errorMsg(errNum).c_str()));
}
if(r == 0) {
return false;
}
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)