Commit 82065823 authored by rakshasa's avatar rakshasa

Only attempt to bind tracker udp address if bind_address is bindable.

parent f694548f
......@@ -77,6 +77,7 @@ public:
static const int pf_local = PF_UNIX;
#endif
bool is_any() const;
bool is_valid() const;
bool is_bindable() const;
bool is_address_any() const;
......@@ -93,6 +94,8 @@ public:
std::string address_str() const;
bool address_c_str(char* buf, socklen_t size) const;
std::string pretty_address_str() const;
// Attemts to set it as an inet, then an inet6 address. It will
// never set anything but net addresses, no local/unix.
bool set_address_str(const std::string& a) { return set_address_c_str(a.c_str()); }
......@@ -233,6 +236,18 @@ private:
struct sockaddr_in6 m_sockaddr;
};
inline bool
socket_address::is_any() const {
switch (family()) {
case af_inet:
return sa_inet()->is_any();
case af_inet6:
return sa_inet6()->is_any();
default:
return false;
}
}
inline bool
socket_address::is_valid() const {
switch (family()) {
......@@ -317,6 +332,22 @@ socket_address::address_c_str(char* buf, socklen_t size) const {
}
}
inline std::string
socket_address::pretty_address_str() const {
switch (family()) {
case af_inet:
return sa_inet()->address_str();
case af_inet6:
return sa_inet6()->address_str();
default:
if (port() == 0)
return std::string("no family");
else
return std::string("no family with port");
}
}
inline bool
socket_address::set_address_c_str(const char* a) {
if (sa_inet()->set_address_c_str(a)) {
......
......@@ -149,7 +149,7 @@ TrackerList::send_state(Tracker* tracker, int new_event) {
tracker->send_state(new_event);
tracker->inc_request_counter();
LT_LOG_TRACKER(INFO, "sending '%s' (group:%u url:'%s')",
LT_LOG_TRACKER(INFO, "sending '%s (group:%u url:%s)",
option_as_string(OPTION_TRACKER_EVENT, new_event),
tracker->group(), tracker->url().c_str());
}
......@@ -168,7 +168,7 @@ TrackerList::send_scrape(Tracker* tracker) {
tracker->send_scrape();
tracker->inc_request_counter();
LT_LOG_TRACKER(INFO, "sending 'scrape' (group:%u url:'%s')",
LT_LOG_TRACKER(INFO, "sending 'scrape' (group:%u url:%s)",
tracker->group(), tracker->url().c_str());
}
......@@ -204,7 +204,7 @@ TrackerList::insert_url(unsigned int group, const std::string& url, bool extra_t
tracker = new TrackerDht(this, url, flags);
} else {
LT_LOG_TRACKER(WARN, "could find matching tracker protocol (url:'%s')", url.c_str());
LT_LOG_TRACKER(WARN, "could find matching tracker protocol (url:%s)", url.c_str());
if (extra_tracker)
throw torrent::input_error("Could find matching tracker protocol for url: '" + url + "'.");
......@@ -212,7 +212,7 @@ TrackerList::insert_url(unsigned int group, const std::string& url, bool extra_t
return;
}
LT_LOG_TRACKER(INFO, "added tracker (group:%i url:'%s')", group, url.c_str());
LT_LOG_TRACKER(INFO, "added tracker (group:%i url:%s)", group, url.c_str());
insert(group, tracker);
}
......@@ -331,7 +331,7 @@ TrackerList::receive_success(Tracker* tb, AddressList* l) {
l->sort();
l->erase(std::unique(l->begin(), l->end()), l->end());
LT_LOG_TRACKER(INFO, "received %u peers (url:'%s')", l->size(), tb->url().c_str());
LT_LOG_TRACKER(INFO, "received %u peers (url:%s)", l->size(), tb->url().c_str());
tb->m_success_time_last = cachedTime.seconds();
tb->m_success_counter++;
......@@ -348,7 +348,7 @@ TrackerList::receive_failed(Tracker* tb, const std::string& msg) {
if (itr == end() || tb->is_busy())
throw internal_error("TrackerList::receive_failed(...) called but the iterator is invalid.");
LT_LOG_TRACKER(INFO, "failed to connect to tracker (url:'%s' msg:'%s')", tb->url().c_str(), msg.c_str());
LT_LOG_TRACKER(INFO, "failed to connect to tracker (url:%s msg:%s)", tb->url().c_str(), msg.c_str());
tb->m_failed_time_last = cachedTime.seconds();
tb->m_failed_counter++;
......@@ -362,7 +362,7 @@ TrackerList::receive_scrape_success(Tracker* tb) {
if (itr == end() || tb->is_busy())
throw internal_error("TrackerList::receive_success(...) called but the iterator is invalid.");
LT_LOG_TRACKER(INFO, "received scrape from tracker (url:'%s')", tb->url().c_str());
LT_LOG_TRACKER(INFO, "received scrape from tracker (url:%s)", tb->url().c_str());
tb->m_scrape_time_last = cachedTime.seconds();
tb->m_scrape_counter++;
......@@ -378,7 +378,7 @@ TrackerList::receive_scrape_failed(Tracker* tb, const std::string& msg) {
if (itr == end() || tb->is_busy())
throw internal_error("TrackerList::receive_failed(...) called but the iterator is invalid.");
LT_LOG_TRACKER(INFO, "failed to scrape tracker (url:'%s' msg:'%s')", tb->url().c_str(), msg.c_str());
LT_LOG_TRACKER(INFO, "failed to scrape tracker (url:%s msg:%s)", tb->url().c_str(), msg.c_str());
if (m_slot_scrape_failed)
m_slot_scrape_failed(tb, msg);
......
......@@ -40,9 +40,10 @@
#include <sys/types.h>
#include <torrent/connection_manager.h>
#include <cstdio>
#include "rak/error_number.h"
#include "net/address_list.h"
#include "torrent/exceptions.h"
#include "torrent/connection_manager.h"
......@@ -95,20 +96,12 @@ TrackerUdp::send_state(int state) {
close_directly();
m_latest_event = state;
// try {
// utils::uri_state uri_state;
// uri_parse_str(m_url, uri_state);
// } catch (utils::uri_error& e) {
// return receive_failed("Could not parse UDP hostname or port: " + std::string(e.what()));
// }
char hostname[1024];
if (std::sscanf(m_url.c_str(), "udp://%1023[^:]:%i", hostname, &m_port) != 2 ||
hostname[0] == '\0' ||
m_port <= 0 || m_port >= (1 << 16))
return receive_failed("Could not parse UDP hostname or port.");
return receive_failed("could not parse UDP hostname or port");
// Because we can only remember one slot, set any pending resolves blocked
// so that if this tracker is deleted, the member function won't be called.
......@@ -117,7 +110,7 @@ TrackerUdp::send_state(int state) {
m_slot_resolver = NULL;
}
LT_LOG_TRACKER(DEBUG, "hostname lookup (address:'%s')", hostname);
LT_LOG_TRACKER(DEBUG, "hostname lookup (address:%s)", hostname);
m_sendState = state;
m_slot_resolver = manager->connection_manager()->resolver()(hostname, PF_INET, SOCK_DGRAM,
......@@ -135,20 +128,24 @@ TrackerUdp::start_announce(const sockaddr* sa, int err) {
}
if (sa == NULL)
return receive_failed("Could not resolve hostname.");
return receive_failed("could not resolve hostname");
m_connectAddress = *rak::socket_address::cast_from(sa);
m_connectAddress.set_port(m_port);
LT_LOG_TRACKER(DEBUG, "address found (address:'%s')", m_connectAddress.address_str().c_str());
LT_LOG_TRACKER(DEBUG, "address found (address:%s)", m_connectAddress.address_str().c_str());
if (!m_connectAddress.is_valid())
return receive_failed("Invalid tracker address.");
return receive_failed("invalid tracker address");
if (!get_fd().open_datagram() ||
!get_fd().set_nonblock() ||
!get_fd().bind(*rak::socket_address::cast_from(manager->connection_manager()->bind_address())))
return receive_failed("Could not open UDP socket.");
// TODO: Make each of these a separate error... at the very least separate open and bind.
if (!get_fd().open_datagram() || !get_fd().set_nonblock())
return receive_failed("could not open UDP socket");
auto bind_address = rak::socket_address::cast_from(manager->connection_manager()->bind_address());
if (bind_address->is_bindable() && !get_fd().bind(*bind_address))
return receive_failed("failed to bind socket to udp address '" + bind_address->pretty_address_str() + "' with error '" + rak::error_number::current().c_str() + "'");
m_readBuffer = new ReadBuffer;
m_writeBuffer = new WriteBuffer;
......@@ -225,7 +222,7 @@ TrackerUdp::receive_timeout() {
throw internal_error("TrackerUdp::receive_timeout() called but m_taskTimeout is still scheduled.");
if (--m_tries == 0) {
receive_failed("Unable to connect to UDP tracker.");
receive_failed("unable to connect to UDP tracker");
} else {
priority_queue_insert(&taskScheduler, &m_taskTimeout, (cachedTime + rak::timer::from_seconds(m_parent->info()->udp_timeout())).round_seconds());
......@@ -291,10 +288,6 @@ TrackerUdp::event_write() {
int __UNUSED s = write_datagram(m_writeBuffer->begin(), m_writeBuffer->size_end(), &m_connectAddress);
// TODO: If send failed, retry shortly or do i call receive_failed?
// if (s != m_writeBuffer->size_end())
// ;
manager->poll()->remove_write(this);
}
......@@ -399,7 +392,7 @@ TrackerUdp::process_error_output() {
m_readBuffer->read_32() != m_transactionId)
return false;
receive_failed("Received error message: " + std::string(m_readBuffer->position(), m_readBuffer->end()));
receive_failed("received error message: " + std::string(m_readBuffer->position(), m_readBuffer->end()));
return true;
}
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment