#include #include #include "IRCClient.hpp" #include "IRCParser.hpp" void irc_client::privmsg(const std::string &target, const std::string &msg) { std::string _msg = "PRIVMSG " + target + " :" + msg; write(_msg); } void irc_client::notice(const std::string &target, const std::string &msg) { std::string _msg = "NOTICE " + target + " :" + msg; write(_msg); } void irc_client::ctcp_req(const std::string &target, const std::string &msg) { std::string _msg = "\x01" + msg + "\0x1"; privmsg(target, _msg); } void irc_client::ctcp_reply(const std::string &target, const std::string &msg) { std::string _msg = "\x01" + msg + "\0x1"; notice(target, _msg); } void irc_client::write(std::string &msg) { #ifdef DEBUG std::cout << "<< " << msg << std::endl; std::cout.flush(); #endif msg += "\r\n"; _io_service.post(boost::bind(&irc_client::do_write, this, msg)); } void irc_client::handle_connect(const boost::system::error_code &error, boost::asio::ip::tcp::resolver::iterator it) { if(!error) { boost::asio::async_read_until(_socket, _in_msg, std::string("\r\n"), boost::bind(&irc_client::handle_read, this, boost::asio::placeholders::error, boost::asio::placeholders::bytes_transferred)); } else if (it != boost::asio::ip::tcp::resolver::iterator()) { _socket.close(); boost::asio::ip::tcp::endpoint ep = *it; _socket.async_connect(ep, boost::bind(&irc_client::handle_connect, this, boost::asio::placeholders::error, ++it)); } else { std::cerr << "Error: " << error.message() << std::endl; } } void irc_client::handle_read(const boost::system::error_code &error, std::size_t bytes_transferred) { if(!error) { std::string nick = "NICK " + _user; std::string user = "USER " + _user + " " + _user + " " + _user + " :" + _user; // Print message info std::istream msgstream(&_in_msg); std::string msg; std::getline(msgstream, msg); // do something with the message depending on state switch(_state) { case connecting: write(nick); write(user); // std::cout << "Sent nick and user.. connected! \n"; _state = connected; break; case connected: { irc_parser g; ircdata out; std::string::const_iterator begin = msg.begin(); std::string::const_iterator end = msg.end(); // parse it bool r = boost::spirit::qi::parse(begin, end, g, out); if (r && begin == end) { std::cout << ">> " << msg << std::endl; std::cout.flush(); irc_callbacks::iterator it = callbacks.find(out.command); if(it != callbacks.end() ) { //~ std::cerr << "Calling " << it->second.size() << "callbacks for command " << out.command << std::endl; // call each callback in order. irc_callback f; BOOST_FOREACH( f, it->second ) { f(*this, out); } } else { //~ std::cerr << "No callbacks found for command " << out.command << std::endl; } } else { std::cout << "Parsing " << msg << " failed." << std::endl; std::flush(std::cout); } } break; default: break; } // queue a read for another message boost::asio::async_read_until(_socket, _in_msg, std::string("\r\n"), boost::bind(&irc_client::handle_read, this, boost::asio::placeholders::error, boost::asio::placeholders::bytes_transferred)); } else { _state = disconnected; do_close(); } } void irc_client::do_write(const std::string &msg) { bool write_in_progress = !_out_msgs.empty(); _out_msgs.push_back(msg); if (!write_in_progress) { boost::asio::async_write(_socket, boost::asio::buffer(_out_msgs.front().data(), _out_msgs.front().size()), boost::bind(&irc_client::handle_write, this, boost::asio::placeholders::error)); } } void irc_client::handle_write(const boost::system::error_code &error) { if (!error) { //~ std::cerr << "Finished writing: " << _out_msgs.front() << std::endl; std::cout.flush(); _out_msgs.pop_front(); if (!_out_msgs.empty()) { boost::asio::async_write(_socket, boost::asio::buffer(_out_msgs.front().data(), _out_msgs.front().size()), boost::bind(&irc_client::handle_write, this, boost::asio::placeholders::error)); } } else { do_close(); } } /* std::string outmsg; std::string regex("(PING :)(.+)"); boost::regex pong(regex); boost::smatch what; if(regex_match(msg, what, pong)) { outmsg = "PONG "; outmsg += what[2].str(); write(outmsg); } else { } */