First of all I would like to thank for the wonderful piece of library. I was looking for a library of this sort for a long time.
I am working on creating a POP3 server. For this I had taken the EchoServer sample provided and modified it according to my need. But when i run this code i am unable to get the Read notification at all.
Further I noticed that even when I run the EchoServer example the first character is never reproduced. Only the next characters are echoed back. I would greatly appreciate if anybody could help in resolving this issue.
Regards,
Srinivasan.B
- Code: Select all
#include "Poco/Net/SocketReactor.h"
#include "Poco/Net/SocketAcceptor.h"
#include "Poco/Net/SocketNotification.h"
#include "Poco/Net/StreamSocket.h"
#include "Poco/Net/ServerSocket.h"
#include "Poco/Net/DialogSocket.h"
#include "Poco/Net/SocketAddress.h"
#include "Poco/NObserver.h"
#include "Poco/Timespan.h"
#include "Poco/StringTokenizer.h"
#include "Poco/Exception.h"
#include "Poco/Thread.h"
#include "Poco/Util/ServerApplication.h"
#include "Poco/Util/Option.h"
#include "Poco/Util/OptionSet.h"
#include "Poco/Util/HelpFormatter.h"
#include <iostream>
using Poco::Net::SocketReactor;
using Poco::Net::SocketAcceptor;
using Poco::Net::ReadableNotification;
using Poco::Net::ShutdownNotification;
using Poco::Net::WritableNotification;
using Poco::Net::ErrorNotification;
using Poco::Net::TimeoutNotification;
using Poco::Net::ServerSocket;
using Poco::Net::StreamSocket;
using Poco::NObserver;
using Poco::AutoPtr;
using Poco::Thread;
using Poco::Timespan;
using Poco::Util::ServerApplication;
using Poco::Util::Application;
using Poco::Util::Option;
using Poco::Util::OptionSet;
using Poco::Util::HelpFormatter;
using Poco::Net::DialogSocket;
using Poco::Net::SocketAddress;
using Poco::StringTokenizer;
class popServiceHandler
{
private:
enum
{
BUFFER_SIZE = 1024
};
enum
{
RESET = 0,
AUTHORIZATION =1,
TRANSACTION = 2,
UPDATE = 3
} state;
int have_username;
std::string username;
std::string extension;
std::string password;
DialogSocket _socket;
SocketReactor& _reactor;
public:
popServiceHandler(StreamSocket& socket, SocketReactor& reactor):
_socket(socket),
_reactor(reactor),
state(AUTHORIZATION)
{
Application& app = Application::instance();
app.logger().information("Connection from " + socket.peerAddress().toString());
app.logger().information("POP3 Server Ready for Authorization");
Timespan interval(1,0);
_reactor.setTimeout(interval);
_reactor.addEventHandler(_socket, NObserver<popServiceHandler, ReadableNotification>(*this, &popServiceHandler::onReadable));
//_reactor.addEventHandler(_socket, NObserver<popServiceHandler, WritableNotification>(*this, &popServiceHandler::onWritable));
//_reactor.addEventHandler(_socket, NObserver<popServiceHandler, ErrorNotification>(*this, &popServiceHandler::onError));
//_reactor.addEventHandler(_socket, NObserver<popServiceHandler, TimeoutNotification>(*this, &popServiceHandler::onTimeout));
_reactor.addEventHandler(_socket, NObserver<popServiceHandler, ShutdownNotification>(*this, &popServiceHandler::onShutdown));
}
~popServiceHandler()
{
Application& app = Application::instance();
try
{
app.logger().information("Disconnecting " + _socket.peerAddress().toString());
}
catch (...)
{
}
_reactor.removeEventHandler(_socket, NObserver<popServiceHandler, ReadableNotification>(*this, &popServiceHandler::onReadable));
//_reactor.removeEventHandler(_socket, NObserver<popServiceHandler, WritableNotification>(*this, &popServiceHandler::onWritable));
//_reactor.removeEventHandler(_socket, NObserver<popServiceHandler, ErrorNotification>(*this, &popServiceHandler::onError));
//_reactor.removeEventHandler(_socket, NObserver<popServiceHandler, TimeoutNotification>(*this, &popServiceHandler::onTimeout));
_reactor.removeEventHandler(_socket, NObserver<popServiceHandler, ShutdownNotification>(*this, &popServiceHandler::onShutdown));
//delete [] _pBuffer;
}
//void onWritable(const AutoPtr<WritableNotification>& pNf)
//{
// Application& app = Application::instance();
// app.logger().information("writable notification received");
// std::string msg = "+OK POP3 Server Ready";
//}
//void onError(const AutoPtr<ErrorNotification>& pNf)
//{
// Application& app = Application::instance();
// app.logger().information("Error notification received");
//}
//void onTimeout(const AutoPtr<TimeoutNotification>& pNf)
//{
// Application& app = Application::instance();
// app.logger().information("Timeout notification received");
//}
void onReadable(const AutoPtr<ReadableNotification>& pNf)
{
std::string msg = "";
_socket.receiveMessage(msg);
//int length = msg.length();
if (parseLine(msg)){
delete this;
}
}
void sendOk(std::string line)
{
line = "+OK " + line;
_socket.sendMessage(line);
//logger.fine("+OK " + line);
}
void sendErr(std::string line) {
line = "-ERR " + line;
_socket.sendMessage(line);
//logger.fine("-ERR " + line);
}
int parseLine(std::string line)
{
Application& app = Application::instance();
if (line.length() == 0) {
sendOk("Please Enter a valid POP3 COMMAND");
return false;
}
StringTokenizer toker(line," ",2);
/* Authorization state */
/* USER */
if (toker[0] == "USER") {
if (toker.count() == 2) {
std::string login = toker[1];
StringTokenizer extToker(login,"@",2);
if (extToker.count() != 0) {
username = extToker[0];
extension = extToker[1];
app.logger().information("Username: " + username);
app.logger().information("Extension: " + extension);
have_username = true;
sendOk("user " + login + " accepted");
return false;
} else {
sendErr(" please provide complete email address for username e.g. user@hotmail.com or user@yahoo.com");
return false;
}
}
else {
sendErr("Syntax: USER user@abc.com");
return false;
}
}
else if (toker[0] == "PASS") { /* PASS */
if (!have_username) {
sendErr("please provide username first");
return false;
}
if (toker.count() == 2) {
password = toker[1];
// switch (wms.login(login, password, false)) {
// case WebMailSession.WMS_LOGIN_OK:
// // All is good,
// break;
// case WebMailSession.WMS_LOGIN_FAILED:
// sendErr("Authorization failed. See ya.");
// logger.warning("'" + usernameExtension + "': Login unsuccessful");
// return true;
// case WebMailSession.WMS_PAGE_STRUCTURE:
// sendErr("Unexpected remote webmail page structure. See ya.");
// logger.warning("'" + usernameExtension + "': Login unsuccessful");
// return true;
// default:
// sendErr("Unexpected remote webmail page structure. See ya.");
// logger.warning("'" + usernameExtension + "': Login unsuccessful");
// return true;
// }
// logger.info("'" + usernameExtension + "': Logged in ok");
sendOk("password accepted");
state = TRANSACTION;
app.logger().information("Entering into transaction state");
return false;
}
else {
sendErr("Syntax: PASS xxxxxxxx");
return false;
}
}
else if (toker[0] == "QUIT") { /* QUIT */
sendOk("Good Bye");
//logger.info("'" + usernameExtension + "': Logged out ok");
return true;
}
else if (toker[0] == "NOOP") { /* NOOP */
if (state == TRANSACTION) {
sendOk("whatever");
} else {
sendErr("not in transaction state");
}
return false;
}
else if (toker[0] == "RSET") { /* RSET */
sendOk("");
return false;
}
else {
sendErr("Command not supported or recognized");
}
return false;
}
void onShutdown(const AutoPtr<ShutdownNotification>& pNf)
{
delete this;
}
};
class popServer: public Poco::Util::ServerApplication
{
public:
popServer(): _helpRequested(false)
{
}
~popServer()
{
}
protected:
void initialize(Application& self)
{
loadConfiguration(); // load default configuration files, if present
ServerApplication::initialize(self);
}
void uninitialize()
{
ServerApplication::uninitialize();
}
void defineOptions(OptionSet& options)
{
ServerApplication::defineOptions(options);
options.addOption(
Option("help", "h", "display help information on command line arguments")
.required(false)
.repeatable(false));
}
void handleOption(const std::string& name, const std::string& value)
{
ServerApplication::handleOption(name, value);
if (name == "help")
_helpRequested = true;
}
void displayHelp()
{
HelpFormatter helpFormatter(options());
helpFormatter.setCommand(commandName());
helpFormatter.setUsage("OPTIONS");
helpFormatter.setHeader("An echo server implemented using the Reactor and Acceptor patterns.");
helpFormatter.format(std::cout);
}
int main(const std::vector<std::string>& args)
{
if (_helpRequested)
{
displayHelp();
}
else
{
// get parameters from configuration file
unsigned short port = (unsigned short) config().getInt("popServer.port", 11110);
const std::string HOST("127.0.0.1");
const Timespan interval(10,0);
SocketAddress sa(HOST, port);
// set-up a server socket
ServerSocket svs(sa);
svs.setReceiveTimeout(interval);
svs.setSendTimeout(interval);
// set-up a SocketReactor...
SocketReactor reactor;
reactor.setTimeout(interval);
// ... and a SocketAcceptor
SocketAcceptor<popServiceHandler> acceptor(svs, reactor);
// run the reactor in its own thread so that we can wait for
// a termination request
Thread thread;
thread.start(reactor);
this->logger().information("POP Server Ready");
// wait for CTRL-C or kill
waitForTerminationRequest();
// Stop the SocketReactor
reactor.stop();
thread.join();
}
return Application::EXIT_OK;
}
private:
bool _helpRequested;
};
int main(int argc, char** argv)
{
popServer app;
return app.run(argc, argv);
}





