asio sync

This commit is contained in:
Marcos Pinto 2007-12-31 07:11:07 +00:00
commit 2d27cede5f
11 changed files with 94 additions and 23 deletions

View file

@ -35,11 +35,16 @@ public:
FD_ZERO(&fd_set_); FD_ZERO(&fd_set_);
} }
void set(socket_type descriptor) bool set(socket_type descriptor)
{ {
if (max_descriptor_ == invalid_socket || descriptor > max_descriptor_) if (descriptor < (socket_type)FD_SETSIZE)
max_descriptor_ = descriptor; {
FD_SET(descriptor, &fd_set_); if (max_descriptor_ == invalid_socket || descriptor > max_descriptor_)
max_descriptor_ = descriptor;
FD_SET(descriptor, &fd_set_);
return true;
}
return false;
} }
bool is_set(socket_type descriptor) const bool is_set(socket_type descriptor) const

View file

@ -173,8 +173,13 @@ public:
typename operation_map::iterator i = operations_.begin(); typename operation_map::iterator i = operations_.begin();
while (i != operations_.end()) while (i != operations_.end())
{ {
descriptors.set(i->first); Descriptor descriptor = i->first;
++i; ++i;
if (!descriptors.set(descriptor))
{
asio::error_code ec(error::fd_set_failure);
dispatch_all_operations(descriptor, ec);
}
} }
} }

View file

@ -1124,8 +1124,12 @@ inline void gai_free(void* p)
inline void gai_strcpy(char* target, const char* source, std::size_t max_size) inline void gai_strcpy(char* target, const char* source, std::size_t max_size)
{ {
using namespace std; using namespace std;
#if BOOST_WORKAROUND(BOOST_MSVC, >= 1400) && !defined(UNDER_CE)
strcpy_s(target, max_size, source);
#else
*target = 0; *target = 0;
strncat(target, source, max_size); strncat(target, source, max_size);
#endif
} }
enum { gai_clone_flag = 1 << 30 }; enum { gai_clone_flag = 1 << 30 };
@ -1658,7 +1662,11 @@ inline asio::error_code getnameinfo_emulation(
{ {
return ec = asio::error::no_buffer_space; return ec = asio::error::no_buffer_space;
} }
#if BOOST_WORKAROUND(BOOST_MSVC, >= 1400) && !defined(UNDER_CE)
sprintf_s(serv, servlen, "%u", ntohs(port));
#else
sprintf(serv, "%u", ntohs(port)); sprintf(serv, "%u", ntohs(port));
#endif
} }
else else
{ {
@ -1677,7 +1685,11 @@ inline asio::error_code getnameinfo_emulation(
{ {
return ec = asio::error::no_buffer_space; return ec = asio::error::no_buffer_space;
} }
#if BOOST_WORKAROUND(BOOST_MSVC, >= 1400) && !defined(UNDER_CE)
sprintf_s(serv, servlen, "%u", ntohs(port));
#else
sprintf(serv, "%u", ntohs(port)); sprintf(serv, "%u", ntohs(port));
#endif
} }
#if defined(BOOST_HAS_THREADS) && defined(BOOST_HAS_PTHREADS) #if defined(BOOST_HAS_THREADS) && defined(BOOST_HAS_PTHREADS)
::pthread_mutex_unlock(&mutex); ::pthread_mutex_unlock(&mutex);

View file

@ -92,7 +92,11 @@
# include <sys/ioctl.h> # include <sys/ioctl.h>
# include <sys/poll.h> # include <sys/poll.h>
# include <sys/types.h> # include <sys/types.h>
# include <sys/select.h> # if defined(__hpux)
# include <sys/time.h>
# else
# include <sys/select.h>
# endif
# include <sys/socket.h> # include <sys/socket.h>
# include <sys/uio.h> # include <sys/uio.h>
# include <netinet/in.h> # include <netinet/in.h>
@ -156,7 +160,16 @@ const int max_addr_v4_str_len = INET_ADDRSTRLEN;
const int max_addr_v6_str_len = INET6_ADDRSTRLEN + 1 + IF_NAMESIZE; const int max_addr_v6_str_len = INET6_ADDRSTRLEN + 1 + IF_NAMESIZE;
typedef sockaddr socket_addr_type; typedef sockaddr socket_addr_type;
typedef in_addr in4_addr_type; typedef in_addr in4_addr_type;
# if defined(__hpux)
// HP-UX doesn't provide ip_mreq when _XOPEN_SOURCE_EXTENDED is defined.
struct in4_mreq_type
{
struct in_addr imr_multiaddr;
struct in_addr imr_interface;
};
# else
typedef ip_mreq in4_mreq_type; typedef ip_mreq in4_mreq_type;
# endif
typedef sockaddr_in sockaddr_in4_type; typedef sockaddr_in sockaddr_in4_type;
typedef in6_addr in6_addr_type; typedef in6_addr in6_addr_type;
typedef ipv6_mreq in6_mreq_type; typedef ipv6_mreq in6_mreq_type;

View file

@ -36,13 +36,17 @@ public:
fd_set_.fd_count = 0; fd_set_.fd_count = 0;
} }
void set(socket_type descriptor) bool set(socket_type descriptor)
{ {
for (u_int i = 0; i < fd_set_.fd_count; ++i) for (u_int i = 0; i < fd_set_.fd_count; ++i)
if (fd_set_.fd_array[i] == descriptor) if (fd_set_.fd_array[i] == descriptor)
return; return true;
if (fd_set_.fd_count < win_fd_set_size) if (fd_set_.fd_count < win_fd_set_size)
{
fd_set_.fd_array[fd_set_.fd_count++] = descriptor; fd_set_.fd_array[fd_set_.fd_count++] = descriptor;
return true;
}
return false;
} }
bool is_set(socket_type descriptor) const bool is_set(socket_type descriptor) const

View file

@ -194,7 +194,10 @@ enum misc_errors
eof, eof,
/// Element not found. /// Element not found.
not_found not_found,
/// The descriptor cannot fit into the select system call's fd_set.
fd_set_failure
}; };
enum ssl_errors enum ssl_errors

View file

@ -112,7 +112,11 @@ public:
{ {
}; };
typedef unspecified_bool_type_t* unspecified_bool_type; typedef void (*unspecified_bool_type)(unspecified_bool_type_t);
static void unspecified_bool_true(unspecified_bool_type_t)
{
}
/// Operator returns non-null if there is a non-success error code. /// Operator returns non-null if there is a non-success error code.
operator unspecified_bool_type() const operator unspecified_bool_type() const
@ -120,7 +124,7 @@ public:
if (value_ == 0) if (value_ == 0)
return 0; return 0;
else else
return reinterpret_cast<unspecified_bool_type>(1); return &error_code::unspecified_bool_true;
} }
/// Operator to test if the error represents success. /// Operator to test if the error represents success.

View file

@ -35,6 +35,8 @@ inline std::string error_code::message() const
return "Already open."; return "Already open.";
if (*this == error::not_found) if (*this == error::not_found)
return "Not found."; return "Not found.";
if (*this == error::fd_set_failure)
return "The descriptor does not fit into the select call's fd_set.";
if (category_ == error::get_ssl_category()) if (category_ == error::get_ssl_category())
return "SSL error."; return "SSL error.";
#if defined(BOOST_WINDOWS) || defined(__CYGWIN__) #if defined(BOOST_WINDOWS) || defined(__CYGWIN__)

View file

@ -100,6 +100,10 @@ public:
&openssl_operation::do_async_write, &openssl_operation::do_async_write,
this, boost::arg<1>(), boost::arg<2>() this, boost::arg<1>(), boost::arg<2>()
); );
read_ = boost::bind(
&openssl_operation::do_async_read,
this
);
handler_= boost::bind( handler_= boost::bind(
&openssl_operation::async_user_handler, &openssl_operation::async_user_handler,
this, boost::arg<1>(), boost::arg<2>() this, boost::arg<1>(), boost::arg<2>()
@ -122,6 +126,10 @@ public:
&openssl_operation::do_sync_write, &openssl_operation::do_sync_write,
this, boost::arg<1>(), boost::arg<2>() this, boost::arg<1>(), boost::arg<2>()
); );
read_ = boost::bind(
&openssl_operation::do_sync_read,
this
);
handler_ = boost::bind( handler_ = boost::bind(
&openssl_operation::sync_user_handler, &openssl_operation::sync_user_handler,
this, boost::arg<1>(), boost::arg<2>() this, boost::arg<1>(), boost::arg<2>()
@ -134,7 +142,7 @@ public:
int start() int start()
{ {
int rc = primitive_( session_ ); int rc = primitive_( session_ );
int sys_error_code = ERR_get_error();
bool is_operation_done = (rc > 0); bool is_operation_done = (rc > 0);
// For connect/accept/shutdown, the operation // For connect/accept/shutdown, the operation
// is done, when return code is 1 // is done, when return code is 1
@ -144,6 +152,8 @@ public:
int error_code = !is_operation_done ? int error_code = !is_operation_done ?
::SSL_get_error( session_, rc ) : ::SSL_get_error( session_, rc ) :
0; 0;
int sys_error_code = ERR_get_error();
bool is_read_needed = (error_code == SSL_ERROR_WANT_READ); bool is_read_needed = (error_code == SSL_ERROR_WANT_READ);
bool is_write_needed = (error_code == SSL_ERROR_WANT_WRITE || bool is_write_needed = (error_code == SSL_ERROR_WANT_WRITE ||
::BIO_ctrl_pending( ssl_bio_ )); ::BIO_ctrl_pending( ssl_bio_ ));
@ -211,6 +221,10 @@ public:
return start(); return start();
} }
else if (is_read_needed)
{
return read_();
}
} }
// Continue with operation, flush any SSL data out to network... // Continue with operation, flush any SSL data out to network...
@ -222,10 +236,12 @@ private:
typedef boost::function<int (const asio::error_code&, int)> typedef boost::function<int (const asio::error_code&, int)>
int_handler_func; int_handler_func;
typedef boost::function<int (bool, int)> write_func; typedef boost::function<int (bool, int)> write_func;
typedef boost::function<int ()> read_func;
ssl_primitive_func primitive_; ssl_primitive_func primitive_;
user_handler_func user_handler_; user_handler_func user_handler_;
write_func write_; write_func write_;
read_func read_;
int_handler_func handler_; int_handler_func handler_;
net_buffer send_buf_; // buffers for network IO net_buffer send_buf_; // buffers for network IO
@ -249,8 +265,15 @@ private:
throw asio::system_error(error); throw asio::system_error(error);
} }
int async_user_handler(const asio::error_code& error, int rc) int async_user_handler(asio::error_code error, int rc)
{ {
if (rc < 0)
{
if (!error)
error = asio::error::no_recovery;
rc = 0;
}
user_handler_(error, rc); user_handler_(error, rc);
return 0; return 0;
} }
@ -315,8 +338,8 @@ private:
} }
// OPeration is not done and writing to net has been made... // OPeration is not done and writing to net has been made...
// start reading... // start operation again
do_async_read(); start();
return 0; return 0;
} }
@ -339,7 +362,7 @@ private:
handler_(error, rc); handler_(error, rc);
} }
void do_async_read() int do_async_read()
{ {
// Wait for new data // Wait for new data
socket_.async_read_some socket_.async_read_some
@ -354,6 +377,7 @@ private:
asio::placeholders::bytes_transferred asio::placeholders::bytes_transferred
) )
); );
return 0;
} }
void async_read_handler(const asio::error_code& error, void async_read_handler(const asio::error_code& error,
@ -432,8 +456,8 @@ private:
// Finish the operation, with success // Finish the operation, with success
return rc; return rc;
// Operation is not finished, read data from net... // Operation is not finished, start again.
return do_sync_read(); return start();
} }
int do_sync_read() int do_sync_read()

View file

@ -44,16 +44,15 @@ namespace ssl {
* @e Shared @e objects: Unsafe. * @e Shared @e objects: Unsafe.
* *
* @par Example * @par Example
* To use the SSL stream template with a stream_socket, you would write: * To use the SSL stream template with an ip::tcp::socket, you would write:
* @code * @code
* asio::io_service io_service; * asio::io_service io_service;
* asio::ssl::context context(io_service, asio::ssl::context::sslv23); * asio::ssl::context context(io_service, asio::ssl::context::sslv23);
* asio::ssl::stream<asio::stream_socket> sock(io_service, context); * asio::ssl::stream<asio::ip::tcp::socket> sock(io_service, context);
* @endcode * @endcode
* *
* @par Concepts: * @par Concepts:
* Async_Object, Async_Read_Stream, Async_Write_Stream, Error_Source, Stream, * AsyncReadStream, AsyncWriteStream, Stream, SyncRead_Stream, SyncWriteStream.
* Sync_Read_Stream, Sync_Write_Stream.
*/ */
template <typename Stream, typename Service = stream_service> template <typename Stream, typename Service = stream_service>
class stream class stream

View file

@ -18,6 +18,6 @@
// ASIO_VERSION % 100 is the sub-minor version // ASIO_VERSION % 100 is the sub-minor version
// ASIO_VERSION / 100 % 1000 is the minor version // ASIO_VERSION / 100 % 1000 is the minor version
// ASIO_VERSION / 100000 is the major version // ASIO_VERSION / 100000 is the major version
#define ASIO_VERSION 308 // 0.3.8 #define ASIO_VERSION 309 // 0.3.9
#endif // ASIO_VERSION_HPP #endif // ASIO_VERSION_HPP