Finish implementation of synchronous host lookup.

This commit is contained in:
chris 2004-06-25 04:03:03 +00:00
parent 66d8d81882
commit 344907b564
12 changed files with 126 additions and 42 deletions

View File

@ -279,8 +279,33 @@ inline int inet_pton(int af, const char* src, void* dest)
#endif // defined(_WIN32)
}
inline hostent* gethostbyaddr_r(const char *addr, int length, int type,
hostent *result, char* buffer, int buflength, int* error)
inline int gethostname(char* name, int namelen)
{
set_error(0);
return error_wrapper(::gethostname(name, namelen));
}
inline int translate_netdb_error(int error)
{
switch (error)
{
case 0:
return socket_error::success;
case HOST_NOT_FOUND:
return socket_error::host_not_found;
case TRY_AGAIN:
return socket_error::host_not_found_try_again;
case NO_RECOVERY:
return socket_error::no_recovery;
case NO_DATA:
return socket_error::no_host_data;
default:
return get_error();
}
}
inline hostent* gethostbyaddr_r(const char* addr, int length, int type,
hostent* result, char* buffer, int buflength, int* error)
{
set_error(0);
#if defined(_WIN32)
@ -291,17 +316,20 @@ inline hostent* gethostbyaddr_r(const char *addr, int length, int type,
*result = *ent_result;
return result;
#elif defined(__sun)
return error_wrapper(::gethostbyaddr_r(addr, length, type, result, buffer,
buflength, error));
hostent* result = error_wrapper(::gethostbyaddr_r(addr, length, type, result,
buffer, buflength, error));
*error = translate_netdb_error(*error);
return result;
#else
hostent* ent_result = 0;
error_wrapper(::gethostbyaddr_r(addr, length, type, result, buffer,
buflength, &ent_result, error));
*error = translate_netdb_error(*error);
return ent_result;
#endif
}
inline hostent* gethostbyname_r(const char *name, struct hostent *result,
inline hostent* gethostbyname_r(const char* name, struct hostent* result,
char* buffer, int buflength, int* error)
{
set_error(0);
@ -313,12 +341,15 @@ inline hostent* gethostbyname_r(const char *name, struct hostent *result,
*result = *ent_result;
return result;
#elif defined(__sun)
return error_wrapper(::gethostbyname_r(name, result, buffer, buflength,
error));
hostent* result = error_wrapper(::gethostbyname_r(name, result, buffer,
buflength, error));
*error = translate_netdb_error(*error);
return ent_result;
#else
hostent* ent_result = 0;
error_wrapper(::gethostbyname_r(name, result, buffer, buflength, &ent_result,
error));
*error = translate_netdb_error(*error);
return ent_result;
#endif
}

View File

@ -93,7 +93,9 @@ public:
/**
* This function is used to obtain host information for the local machine.
*
* @param h A host object that receives information about the local machine.
* @param h A host object that receives information assocated with the
* specified address. After successful completion of this function, the host
* object is guaranteed to contain at least one address.
*
* @param error_handler The handler to be called when an error occurs. Copies
* will be made of the handler as required. The equivalent function signature
@ -116,7 +118,8 @@ public:
* @param addr An address object that identifies a host.
*
* @param h A host object that receives information assocated with the
* specified address.
* specified address. After successful completion of this function, the host
* object is guaranteed to contain at least one address.
*
* @throws socket_error Thrown on failure.
*/
@ -133,7 +136,8 @@ public:
* @param addr An address object that identifies a host.
*
* @param h A host object that receives information assocated with the
* specified address.
* specified address. After successful completion of this function, the host
* object is guaranteed to contain at least one address.
*
* @param error_handler The handler to be called when an error occurs. Copies
* will be made of the handler as required. The equivalent function signature

View File

@ -85,6 +85,11 @@ public:
template <typename Error_Handler>
void get_local_host(impl_type& impl, host& h, Error_Handler error_handler)
{
char name[1024];
if (asio::detail::socket_ops::gethostname(name, sizeof(name)) != 0)
error_handler(socket_error(asio::detail::socket_ops::get_error()));
else
get_host_by_name(impl, name, h, error_handler);
}
/// Get host information for a specified address.
@ -124,6 +129,7 @@ public:
populate_host_object(h, ent);
}
private:
// Populate a host object from a hostent structure.
void populate_host_object(host& h, hostent& ent)
{
@ -149,7 +155,6 @@ public:
h.addresses.swap(tmp.addresses);
}
private:
// The demuxer used for dispatching handlers.
Demuxer& demuxer_;
};

View File

@ -30,8 +30,10 @@ namespace asio {
#if defined(_WIN32)
# define ASIO_SOCKET_ERROR(e) WSA ## e
# define ASIO_NETDB_ERROR(e) WSA ## e
#else
# define ASIO_SOCKET_ERROR(e) e
# define ASIO_NETDB_ERROR(e) 16384 + e
#endif
/// The socket_error class is used to encapsulate socket error codes.
@ -70,10 +72,10 @@ public:
fault = ASIO_SOCKET_ERROR(EFAULT),
/// Host not found (authoritative).
host_not_found = ASIO_SOCKET_ERROR(HOST_NOT_FOUND),
host_not_found = ASIO_NETDB_ERROR(HOST_NOT_FOUND),
/// Host not found (non-authoritative).
host_not_found_try_again = ASIO_SOCKET_ERROR(TRY_AGAIN),
host_not_found_try_again = ASIO_NETDB_ERROR(TRY_AGAIN),
/// No route to host.
host_unreachable = ASIO_SOCKET_ERROR(EHOSTUNREACH),
@ -106,7 +108,7 @@ public:
no_buffer_space = ASIO_SOCKET_ERROR(ENOBUFS),
/// The host is valid but does not have address data.
no_host_data = ASIO_SOCKET_ERROR(NO_DATA),
no_host_data = ASIO_NETDB_ERROR(NO_DATA),
/// Cannot allocate memory.
no_memory = ENOMEM,
@ -118,7 +120,7 @@ public:
no_protocol_option = ASIO_SOCKET_ERROR(ENOPROTOOPT),
/// A non-recoverable error occurred.
no_recovery = ASIO_SOCKET_ERROR(NO_RECOVERY),
no_recovery = ASIO_NETDB_ERROR(NO_RECOVERY),
/// Transport endpoint is not connected.
not_connected = ASIO_SOCKET_ERROR(ENOTCONN),
@ -205,12 +207,29 @@ public:
msg.resize(msg.size() - 1);
return msg;
}
#elif defined(__sun)
#else // _WIN32
switch (code_)
{
case host_not_found:
return "Host not found (authoritative).";
case host_not_found_try_again:
return "Host not found (non-authoritative), try again later.";
case no_recovery:
return "A non-recoverable error occurred during database lookup.";
case no_host_data:
return "The name is valid, but it does not have associated data.";
default:
break;
}
#if defined(__sun)
return std::string(strerror(code_));
#else
#else // __sun
if (code_ == operation_aborted)
return "Operation cancelled.";
char buf[256] = "";
return std::string(strerror_r(code_, buf, sizeof(buf)));
#endif
#endif // __sun
#endif // _WIN32
}
struct unspecified_bool_type_t;

View File

@ -10,13 +10,12 @@ typedef std::deque<chat_message> chat_message_queue;
class chat_client
{
public:
chat_client(asio::demuxer& d, short port, const char* host)
chat_client(asio::demuxer& d, const asio::ipv4::tcp::endpoint& endpoint)
: demuxer_(d),
connector_(d),
socket_(d)
{
connector_.async_connect(socket_,
asio::ipv4::tcp::endpoint(port, asio::ipv4::address(host)),
connector_.async_connect(socket_, endpoint,
boost::bind(&chat_client::handle_connect, this, asio::arg::error));
}
@ -133,7 +132,12 @@ int main(int argc, char* argv[])
asio::demuxer d;
using namespace std; // For atoi, strlen and memcpy.
chat_client c(d, atoi(argv[2]), argv[1]);
asio::ipv4::host_resolver hr(d);
asio::ipv4::host h;
hr.get_host_by_name(argv[1], h);
asio::ipv4::tcp::endpoint ep(atoi(argv[2]), h.addresses[0]);
chat_client c(d, ep);
asio::detail::thread t(boost::bind(&asio::demuxer::run, &d));

View File

@ -161,9 +161,9 @@ typedef boost::shared_ptr<chat_session> chat_session_ptr;
class chat_server
{
public:
chat_server(asio::demuxer& d, short port)
chat_server(asio::demuxer& d, const asio::ipv4::tcp::endpoint& endpoint)
: demuxer_(d),
acceptor_(d, asio::ipv4::tcp::endpoint(port))
acceptor_(d, endpoint)
{
chat_session_ptr new_session(new chat_session(demuxer_, room_));
acceptor_.async_accept(new_session->socket(),
@ -210,7 +210,8 @@ int main(int argc, char* argv[])
for (int i = 1; i < argc; ++i)
{
using namespace std; // For atoi.
chat_server_ptr server(new chat_server(d, atoi(argv[i])));
asio::ipv4::tcp::endpoint endpoint(atoi(argv[i]));
chat_server_ptr server(new chat_server(d, endpoint));
servers.push_back(server);
}

View File

@ -17,11 +17,15 @@ int main(int argc, char* argv[])
asio::demuxer d;
asio::ipv4::host_resolver hr(d);
asio::ipv4::host h;
hr.get_host_by_name(argv[1], h);
asio::ipv4::tcp::endpoint ep(atoi(argv[2]), h.addresses[0]);
using namespace std; // For atoi and strlen.
asio::stream_socket s(d);
asio::socket_connector c(d);
c.connect(s,asio::ipv4::tcp::endpoint(atoi(argv[2]),
asio::ipv4::address(argv[1])));
c.connect(s, ep);
std::cout << "Enter message: ";
char request[max_length];

View File

@ -19,13 +19,16 @@ int main(int argc, char* argv[])
asio::dgram_socket s(d, asio::ipv4::udp::endpoint(0));
asio::ipv4::host_resolver hr(d);
asio::ipv4::host h;
hr.get_host_by_name(argv[1], h);
asio::ipv4::udp::endpoint receiver_endpoint(atoi(argv[2]), h.addresses[0]);
using namespace std; // For atoi and strlen.
std::cout << "Enter message: ";
char request[max_length];
std::cin.getline(request, max_length);
size_t request_length = strlen(request);
asio::ipv4::udp::endpoint receiver_endpoint(atoi(argv[2]),
asio::ipv4::address(argv[1]));
s.sendto(request, request_length, receiver_endpoint);
char reply[max_length];

View File

@ -13,11 +13,15 @@ int main(int argc, char* argv[])
asio::demuxer demuxer;
asio::ipv4::host_resolver host_resolver(demuxer);
asio::ipv4::host host;
host_resolver.get_host_by_name(argv[1], host);
asio::ipv4::tcp::endpoint remote_endpoint(13, host.addresses[0]);
asio::stream_socket socket(demuxer);
asio::socket_connector connector(demuxer);
connector.connect(socket,
asio::ipv4::tcp::endpoint(13, asio::ipv4::address(argv[1])));
connector.connect(socket, remote_endpoint);
char buf[128];
while (size_t len = socket.recv(buf, sizeof(buf)))

View File

@ -15,13 +15,17 @@ int main(int argc, char* argv[])
asio::dgram_socket socket(demuxer, asio::ipv4::udp::endpoint(0));
asio::ipv4::host_resolver host_resolver(demuxer);
asio::ipv4::host host;
host_resolver.get_host_by_name(argv[1], host);
asio::ipv4::udp::endpoint receiver_endpoint(13, host.addresses[0]);
char send_buf[1] = { 0 };
socket.sendto(send_buf, sizeof(send_buf),
asio::ipv4::udp::endpoint(13, asio::ipv4::address(argv[1])));
socket.sendto(send_buf, sizeof(send_buf), receiver_endpoint);
char recv_buf[128];
asio::ipv4::udp::endpoint remote_endpoint;
size_t len = socket.recvfrom(recv_buf, sizeof(recv_buf), remote_endpoint);
asio::ipv4::udp::endpoint sender_endpoint;
size_t len = socket.recvfrom(recv_buf, sizeof(recv_buf), sender_endpoint);
std::cout.write(recv_buf, len);
}
catch (asio::socket_error& e)

View File

@ -158,13 +158,13 @@ private:
class client
{
public:
client(demuxer& d, const char* host, short port, size_t block_size,
size_t session_count, int timeout)
client(demuxer& d, const ipv4::tcp::endpoint& server_endpoint,
size_t block_size, size_t session_count, int timeout)
: demuxer_(d),
dispatcher_(d),
stop_timer_(d, timer::from_now, timeout),
connector_(d),
server_endpoint_(port, ipv4::address(host)),
server_endpoint_(server_endpoint),
block_size_(block_size),
max_session_count_(session_count),
sessions_(),
@ -250,7 +250,12 @@ int main(int argc, char* argv[])
demuxer d;
client c(d, host, port, block_size, session_count, timeout);
ipv4::host_resolver hr(d);
ipv4::host h;
hr.get_host_by_name(host, h);
ipv4::tcp::endpoint ep(port, h.addresses[0]);
client c(d, ep, block_size, session_count, timeout);
std::list<thread*> threads;
while (--thread_count > 0)

View File

@ -124,14 +124,14 @@ private:
class server
{
public:
server(demuxer& d, short port, size_t block_size)
server(demuxer& d, const ipv4::tcp::endpoint& endpoint, size_t block_size)
: demuxer_(d),
acceptor_(d),
block_size_(block_size)
{
acceptor_.open(ipv4::tcp());
acceptor_.set_option(socket_option::reuse_address(1));
acceptor_.bind(ipv4::tcp::endpoint(port));
acceptor_.bind(endpoint);
acceptor_.listen();
session* new_session = new session(demuxer_, block_size_);
@ -177,7 +177,7 @@ int main(int argc, char* argv[])
demuxer d;
server s(d, port, block_size);
server s(d, ipv4::tcp::endpoint(port), block_size);
// Threads not currently supported in this test.
std::list<thread*> threads;