Boost logo

Boost Users :

From: n0vicd_c0der (alwaysme109_at_[hidden])
Date: 2008-08-21 15:17:35


Hi,
I am trying to code a simple POP3S client. I am using the boost::asio
sockets and SSL wrapper. Somehow, the output from the async_read_util is
directed to the input of the async_write. Not sure if the issue is the
memory or the order of calls. Any idea?
The code snippet is below, but here is the output of my program first (I
replaced the IP with x's)

bash# ./main 209.85.199.111 995 foo.bar_at_[hidden] pass_in_plain_text
Got RES (66) bytes
+OK Gpop ready for requests from xxx.xxx.xxx.xxx c20pf1156691rvf.3
Sent REQ: APOP foo.bar_at_[hidden] pass_in_plain_text
Got RES (36) bytes
-ERR bad command c20pf1156691rvf.3
Sent REQ: STAT
Read failed: End of file
Exception: End of file

and here is the code snippet

#include <cstdio>
#include <cstdlib>
#include <unistd.h>
#include <iostream>
#include <boost/bind.hpp>
#include <boost/asio.hpp>
#include <boost/asio/ssl.hpp>
#include <boost/asio/detail/throw_error.hpp>

enum { max_length = 8192 };
class client
{
public:
  client(boost::asio::io_service& io_service, boost::asio::ssl::context&
context,
      boost::asio::ip::tcp::endpoint& endpoint)
    : socket_(io_service, context)
  {
    //connect to the pop3 server
    socket_.lowest_layer().async_connect(endpoint,
        boost::bind(&client::handle_connect, this,
          boost::asio::placeholders::error));
  }
  ~client()
  {
     socket_.lowest_layer().close();
  }
  void handle_connect(const boost::system::error_code& error)
  {
    if (!error)
    {
      //do the SSL handshake
      socket_.async_handshake(boost::asio::ssl::stream_base::client,
          boost::bind(&client::handle_handshake, this,
            boost::asio::placeholders::error));
    }
    else
    {
      std::cerr << "Connection failed: " << error << "\n";
      boost::asio::detail::throw_error(error);
    }
  }
  void handle_handshake(const boost::system::error_code& error)
  {
    if (error)
    {
      std::cerr << "SSL Handshaking failed: " << error << "\n";
      boost::asio::detail::throw_error(error);
    }
  }
  void write(std::string buffer)
  {
     str_req=buffer;
     boost::asio::async_write(socket_,
        boost::asio::buffer(str_req),
           boost::bind(&client::handle_write, this,
           boost::asio::placeholders::error,
           boost::asio::placeholders::bytes_transferred));
  }
  void handle_write(const boost::system::error_code& error,
      size_t bytes)
  {
    if (!error)
    {
      std::cout << "Sent REQ: " << str_req <<std::endl;
      try{
         boost::asio::async_read_until(socket_, buff_, "\r\n",
           boost::bind(&client::handle_read_until, this,
            boost::asio::placeholders::error,
            boost::asio::placeholders::bytes_transferred));
      }catch(const boost::system::system_error &err){
         std::cerr << " code: " << err.code().value() << " :" <<
err.code().message() << std::endl;
      }
    }
    else
    {
      std::cerr << "Write failed: " << error.message() << "\n";
      boost::asio::detail::throw_error(error);
    }
  }
  void read()
  {
      try{
         boost::asio::async_read_until(socket_, buff_, "\r\n",
           boost::bind(&client::handle_read_until, this,
            boost::asio::placeholders::error,
            boost::asio::placeholders::bytes_transferred));
      }catch(const boost::system::system_error &err){
        std::cerr << " code: " << err.code().value() << " :" <<
err.code().message() << std::endl;
      }
  }
  void handle_read_until(const boost::system::error_code& error,
      size_t bytes_transferred)
  {
    if (!error)
    {
      std::cout << "Got RES (" << bytes_transferred<<") bytes\n";
      std::cout << &buff_;
      std::cout << "\n";
    }
    else
    {
      std::cout << "Read failed: " << error.message() << "\n";
      boost::asio::detail::throw_error(error);
    }
  }
private:
  boost::asio::ssl::stream<boost::asio::ip::tcp::socket> socket_;
  boost::asio::streambuf buff_; //for receiving
  std::string str_req; //for sending
};
int main(int argc, char* argv[])
{
  try
  {
    if (argc != 5)
    {
      std::cerr << "Usage: " << argv[0] << " <host> <port> <user> <pass>\n";
      return 1;
    }
    boost::asio::io_service io_service;
    boost::asio::ssl::context ctx(io_service,
boost::asio::ssl::context::sslv23);
    ctx.set_verify_mode(boost::asio::ssl::context::verify_none);
    boost::asio::ip::tcp::endpoint endpoint(
      boost::asio::ip::address::from_string(argv[1]), atoi(argv[2]));
    client c(io_service, ctx, endpoint);
    io_service.run(); //should execute till handshake completes
    //read the pop3 greeting
    io_service.reset();
    io_service.post(boost::bind(&client::read,&c));
    io_service.run();
    //send the authentication command
    std::string str_cmd="APOP " + std::string(argv[3]) + " " +
std::string(argv[4]) +"\r\n";
    io_service.reset();
    io_service.post(boost::bind(&client::write,&c,str_cmd));
    io_service.run();
    //get how many messages are in the inbox
    str_cmd="STAT\r\n";
    io_service.reset();
    io_service.post(boost::bind(&client::write,&c,str_cmd));
    io_service.run();
    //quit the pop3 session
    str_cmd="QUIT\r\n";
    io_service.reset();
    io_service.post(boost::bind(&client::write,&c,str_cmd));
    io_service.run();
  }
  catch (std::exception& e)
  {
    std::cerr << "Exception: " << e.what() << "\n";
  }
  return 0;
}

-- 
View this message in context: http://www.nabble.com/-asio--wacky-behavior-in-async_write-async_read-tp19095127p19095127.html
Sent from the Boost - Users mailing list archive at Nabble.com.

Boost-users list run by williamkempf at hotmail.com, kalb at libertysoft.com, bjorn.karlsson at readsoft.com, gregod at cs.rpi.edu, wekempf at cox.net