585 lines
17 KiB
C++
585 lines
17 KiB
C++
#include <yproxy/YProxyThread.hpp>
|
|
#include <yproxy/NNTPCommands.hpp>
|
|
#include <yproxy/NewsDecoder.hpp>
|
|
#include <nntp/listitms.hpp>
|
|
#include <nntp/grpitem.hpp>
|
|
#include <nntp/iterator.hpp>
|
|
#include <common/console.hpp>
|
|
#include <common/file.hpp>
|
|
|
|
struct ConnectionInfo
|
|
{
|
|
Socket *pSocketControl;
|
|
String *pHost;
|
|
String *pUser;
|
|
String *pPassword;
|
|
};
|
|
|
|
YProxyThread::YProxyThread()
|
|
: mIsDebug(false)
|
|
{
|
|
consoleMessage("[YProxyThread::YProxyThread] Thread started");
|
|
mThreadHandler.setCallback(this,&YProxyThread::threadHandler);
|
|
insertHandler(&mThreadHandler);
|
|
mThreadName=getThreadName();
|
|
}
|
|
|
|
YProxyThread::~YProxyThread()
|
|
{
|
|
}
|
|
|
|
bool YProxyThread::accept(Socket &socketControl,const String &host,const String &user,const String &password)
|
|
{
|
|
ConnectionInfo *pConnectionInfo=::new ConnectionInfo();
|
|
pConnectionInfo->pHost=::new String(host);
|
|
pConnectionInfo->pUser=::new String(user);
|
|
pConnectionInfo->pPassword=::new String(password);
|
|
pConnectionInfo->pSocketControl=&socketControl;
|
|
ThreadMessage threadMessage(ThreadMessage::TM_USER,AcceptMessage,(DWORD)pConnectionInfo);
|
|
postMessage(threadMessage);
|
|
message("[YProxyThread::accept] Waiting for bind.");
|
|
mAcceptEvent.waitEvent();
|
|
return true;
|
|
}
|
|
|
|
DWORD YProxyThread::threadHandler(ThreadMessage &threadMessage)
|
|
{
|
|
switch(threadMessage.message())
|
|
{
|
|
case ThreadMessage::TM_VOID :
|
|
break;
|
|
case ThreadMessage::TM_CREATE :
|
|
break;
|
|
case ThreadMessage::TM_DESTROY :
|
|
break;
|
|
case ThreadMessage::TM_USER :
|
|
switch(threadMessage.userDataOne())
|
|
{
|
|
case AcceptMessage :
|
|
thAccept(threadMessage);
|
|
break;
|
|
}
|
|
break;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
void YProxyThread::thAccept(ThreadMessage &threadMessage)
|
|
{
|
|
INETSocketAddress inetSocketAddress;
|
|
String stringData;
|
|
|
|
ConnectionInfo *pConnectionInfo=(ConnectionInfo*)threadMessage.userDataTwo();
|
|
Socket &socketControl=*pConnectionInfo->pSocketControl;
|
|
String user=*pConnectionInfo->pUser;
|
|
String password=*pConnectionInfo->pPassword;
|
|
String host=*pConnectionInfo->pHost;
|
|
::delete pConnectionInfo->pUser;
|
|
::delete pConnectionInfo->pPassword;
|
|
::delete pConnectionInfo->pHost;
|
|
::delete pConnectionInfo;
|
|
if(!socketControl.accept(mSocketControl,inetSocketAddress))return;
|
|
if(!mNNTPClient.open(host,user,password))
|
|
{
|
|
mSocketControl.send("400 Service not available");
|
|
consoleMessage(String("[YProxyThread::accept] Unable to connect to news server")+inetSocketAddress.internetAddress().toString());
|
|
mSocketControl.destroy();
|
|
return;
|
|
}
|
|
mSocketControl.setDontLinger();
|
|
consoleMessage(String("[YProxyThread::accept]Service started from ")+inetSocketAddress.internetAddress().toString());
|
|
consoleMessage("[YProxyThread::accept]Socket is bound ");
|
|
mAcceptEvent.setEvent();
|
|
sendConnectResponse();
|
|
while(true)
|
|
{
|
|
if(!mSocketControl.isOkay())
|
|
{
|
|
consoleMessage("[YProxyThread::thAccept] socket error, closing connection.");
|
|
break;
|
|
}
|
|
if(mSocketControl.receive(stringData))
|
|
{
|
|
if(stringData.isNull())continue;
|
|
consoleMessage(String("[YProxyThread::thAccept] Received '")+stringData+String("'"));
|
|
if(!stringHandler(stringData))break;
|
|
}
|
|
else
|
|
{
|
|
consoleMessage("[YProxyThread::thAccept] connection dropped.");
|
|
break;
|
|
}
|
|
}
|
|
mSocketControl.destroy();
|
|
}
|
|
|
|
void YProxyThread::sendConnectResponse()
|
|
{
|
|
consoleMessage("[YProxyThread::sendConnectResponse] sending connection response.");
|
|
mSocketControl.send("200 YProxy v1.00 copyright(c) 2002 Diversified Software Solutions.");
|
|
if(!mNNTPClient.isConnected())consoleMessage("[YProxyThread::sendConnectResponse] Proxy is not connected to server.");
|
|
}
|
|
|
|
// virtuals
|
|
|
|
bool YProxyThread::stringHandler(const String &string)
|
|
{
|
|
bool returnCode=true;
|
|
switch(NNTPCommands::getInstance().interpretCommand(string))
|
|
{
|
|
case NNTPCommands::Article :
|
|
handleArticle(string);
|
|
break;
|
|
case NNTPCommands::Body :
|
|
handleBody(string);
|
|
break;
|
|
case NNTPCommands::Group :
|
|
handleGroup(string);
|
|
break;
|
|
case NNTPCommands::Head :
|
|
handleHead(string);
|
|
break;
|
|
case NNTPCommands::Help :
|
|
handleHelp(string);
|
|
break;
|
|
case NNTPCommands::IHave :
|
|
handleIHave(string);
|
|
break;
|
|
case NNTPCommands::Last :
|
|
handleLast(string);
|
|
break;
|
|
case NNTPCommands::List :
|
|
handleList(string);
|
|
break;
|
|
case NNTPCommands::NewGroups :
|
|
handleNewGroups(string);
|
|
break;
|
|
case NNTPCommands::NewNews :
|
|
handleNewNews(string);
|
|
break;
|
|
case NNTPCommands::Next :
|
|
handleNext(string);
|
|
break;
|
|
case NNTPCommands::Post :
|
|
handlePost(string);
|
|
break;
|
|
case NNTPCommands::Quit :
|
|
handleQuit(string);
|
|
returnCode=false;
|
|
break;
|
|
case NNTPCommands::Slave :
|
|
handleSlave(string);
|
|
break;
|
|
case NNTPCommands::Stat :
|
|
handleStat(string);
|
|
break;
|
|
case NNTPCommands::ListGroup :
|
|
handleListGroup(string);
|
|
break;
|
|
case NNTPCommands::AuthInfoUser :
|
|
handleAuthInfoUser(string);
|
|
break;
|
|
case NNTPCommands::AuthInfoPass :
|
|
handleAuthInfoPass(string);
|
|
break;
|
|
case NNTPCommands::ModeReader :
|
|
handleModeReader(string);
|
|
break;
|
|
case NNTPCommands::XOver :
|
|
handleXOver(string);
|
|
break;
|
|
case NNTPCommands::InvalidCommand :
|
|
consoleMessage(NNTPCommands::getInstance().toString(NNTPCommands::InvalidCommand)+String(" '")+string+String("'"));
|
|
break;
|
|
}
|
|
return returnCode;
|
|
}
|
|
|
|
// *****************************************************************************************************
|
|
// command handlers
|
|
|
|
void YProxyThread::handleModeReader(const String &string)
|
|
{
|
|
consoleMessage(String("[YProxyThread::handleModeReader]")+NNTPCommands::getInstance().toString(NNTPCommands::ModeReader));
|
|
mSocketControl.send("200 OK");
|
|
}
|
|
|
|
void YProxyThread::handleList(const String &string)
|
|
{
|
|
consoleMessage(String("[YProxyThread::handleList]")+NNTPCommands::getInstance().toString(NNTPCommands::List));
|
|
if(isDebug())
|
|
{
|
|
mSocketControl.send("215 list of newsgroups follows");
|
|
mSocketControl.send("a.bsu.programming 00543 00501 y");
|
|
mSocketControl.send("a.bsu.religion 10125 10011 y");
|
|
mSocketControl.send("a.bsu.talk 10125 10011 y");
|
|
mSocketControl.send("abg.atari 10125 10011 y");
|
|
mSocketControl.send(".");
|
|
}
|
|
else if(mNNTPClient.isConnected())
|
|
{
|
|
ListItems listItems;
|
|
mNNTPClient.list(listItems);
|
|
mSocketControl.send("215 list of newsgroups follows");
|
|
for(int index=0;index<listItems.size();index++)
|
|
mSocketControl.send(listItems[index].toString());
|
|
mSocketControl.send(".");
|
|
}
|
|
else
|
|
{
|
|
mSocketControl.send("500 Proxy is not connected to server");
|
|
}
|
|
}
|
|
|
|
void YProxyThread::handleGroup(const String &string)
|
|
{
|
|
String strGroup=string.betweenString(' ','\0');
|
|
|
|
consoleMessage(String("[YProxyThread::handleGroup]")+NNTPCommands::getInstance().toString(NNTPCommands::Group));
|
|
if(isDebug())
|
|
{
|
|
GroupItem groupItem(strGroup);
|
|
groupItem.articlesInGroup(3);
|
|
groupItem.firstArticle(1);
|
|
groupItem.lastArticle(3);
|
|
mSocketControl.send(String("211 ")+groupItem.toString());
|
|
}
|
|
else if(mNNTPClient.isConnected())
|
|
{
|
|
GroupItem groupItem(strGroup);
|
|
mNNTPClient.group(groupItem);
|
|
mSocketControl.send(String("211 ")+groupItem.toString());
|
|
}
|
|
else
|
|
{
|
|
mSocketControl.send("411 Proxy is not connected to server");
|
|
}
|
|
}
|
|
|
|
void YProxyThread::handleXOver(const String &string)
|
|
{
|
|
Block<String> overview;
|
|
String first;
|
|
String last;
|
|
|
|
consoleMessage(String("[YProxyThread::handleXOver]")+NNTPCommands::getInstance().toString(NNTPCommands::XOver));
|
|
first=string.betweenString(' ','-');
|
|
last=string.betweenString('-','\0');
|
|
if(isDebug())
|
|
{
|
|
mSocketControl.send("500 Unsupported");
|
|
}
|
|
else if(mNNTPClient.isConnected())
|
|
{
|
|
mNNTPClient.xover(first.toInt(),last.toInt(),overview);
|
|
mSocketControl.send(String("224 Overview information follows "));
|
|
for(int index=0;index<overview.size();index++)
|
|
mSocketControl.send(overview[index]);
|
|
mSocketControl.send(".");
|
|
}
|
|
else
|
|
{
|
|
mSocketControl.send("411 Proxy is not connected to server");
|
|
}
|
|
}
|
|
|
|
void YProxyThread::handleArticle(const String &string)
|
|
{
|
|
Block<String> articleText;
|
|
Block<String> uuencodedLines;
|
|
|
|
consoleMessage(String("[YProxyThread::handleArticle]")+NNTPCommands::getInstance().toString(NNTPCommands::Article));
|
|
if(isDebug())
|
|
{
|
|
String selector;
|
|
String messageID;
|
|
DWORD articleNumber;
|
|
|
|
selector=string.betweenString(' ','\0');
|
|
articleNumber=selector.toInt();
|
|
consoleMessage(String("220 ")+String().fromInt(articleNumber)+String(" <")+messageID+String(">"));
|
|
mSocketControl.send(String("220 ")+String().fromInt(articleNumber)+String(" <")+messageID+String(">"));
|
|
NewsDecoder::decode("d:\\work\\yproxy\\1392078.txt",uuencodedLines);
|
|
for(int index=0;index<uuencodedLines.size();index++)
|
|
mSocketControl.send(uuencodedLines[index]);
|
|
}
|
|
else if(mNNTPClient.isConnected())
|
|
{
|
|
String selector;
|
|
String messageID;
|
|
|
|
selector=string.betweenString(' ','\0');
|
|
if(selector.betweenString('<','>').length())
|
|
{
|
|
MsgID msgID=selector.betweenString('<','>');
|
|
mNNTPClient.article(msgID,articleText,messageID);
|
|
consoleMessage(String("220 ")+String().fromInt(0)+String(" <")+messageID+String(">"));
|
|
mSocketControl.send(String("220 ")+String().fromInt(0)+String(" <")+messageID+String(">"));
|
|
NewsDecoder::decode(messageID,articleText,uuencodedLines);
|
|
}
|
|
else
|
|
{
|
|
DWORD articleNumber=selector.toInt();
|
|
mNNTPClient.article(articleNumber,articleText,messageID);
|
|
consoleMessage(String("220 ")+String().fromInt(articleNumber)+String(" <")+messageID+String(">"));
|
|
mSocketControl.send(String("220 ")+String().fromInt(articleNumber)+String(" <")+messageID+String(">"));
|
|
NewsDecoder::decode(String().fromInt(articleNumber),articleText,uuencodedLines);
|
|
}
|
|
if(uuencodedLines.size())
|
|
{
|
|
for(int index=0;index<uuencodedLines.size();index++)
|
|
mSocketControl.send(uuencodedLines[index]);
|
|
}
|
|
else
|
|
{
|
|
for(int index=0;index<articleText.size();index++)
|
|
mSocketControl.send(articleText[index]);
|
|
}
|
|
mSocketControl.send(".");
|
|
}
|
|
else
|
|
{
|
|
mSocketControl.send("500 Proxy is not connected to server");
|
|
}
|
|
}
|
|
|
|
void YProxyThread::handleBody(const String &string)
|
|
{
|
|
Block<String> articleText;
|
|
|
|
consoleMessage(String("[YProxyThread::handleBody]")+NNTPCommands::getInstance().toString(NNTPCommands::Body));
|
|
if(isDebug())
|
|
{
|
|
consoleMessage("YProxyThread::handleBody] No debug version.");
|
|
}
|
|
else if(mNNTPClient.isConnected())
|
|
{
|
|
String selector;
|
|
String messageID;
|
|
|
|
selector=string.betweenString(' ','\0');
|
|
if(selector.betweenString('<','>').length())
|
|
{
|
|
MsgID msgID=selector.betweenString('<','>');
|
|
mNNTPClient.body(msgID,articleText,messageID);
|
|
mSocketControl.send(String("220 ")+String().fromInt(0)+String(" <")+messageID+String(">"));
|
|
}
|
|
else
|
|
{
|
|
DWORD articleNumber=selector.toInt();
|
|
mNNTPClient.body(articleNumber,articleText,messageID);
|
|
mSocketControl.send(String("220 ")+String().fromInt(articleNumber)+String(" <")+messageID+String(">"));
|
|
}
|
|
for(int index=0;index<articleText.size();index++)
|
|
{
|
|
consoleMessage(articleText[index].isNull()?" ":articleText[index]);
|
|
if(articleText[index].isNull())mSocketControl.send(" ");
|
|
else mSocketControl.send(articleText[index]);
|
|
}
|
|
mSocketControl.send(".");
|
|
}
|
|
else
|
|
{
|
|
mSocketControl.send("500 Proxy is not connected to server");
|
|
}
|
|
}
|
|
|
|
void YProxyThread::handleHead(const String &string)
|
|
{
|
|
Block<String> articleText;
|
|
|
|
consoleMessage(String("[YProxyThread::handleHead]")+NNTPCommands::getInstance().toString(NNTPCommands::Head));
|
|
if(isDebug())
|
|
{
|
|
consoleMessage("YProxyThread::handleHead] No debug version.");
|
|
}
|
|
else if(mNNTPClient.isConnected())
|
|
{
|
|
String selector;
|
|
String messageID;
|
|
|
|
selector=string.betweenString(' ','\0');
|
|
if(selector.betweenString('<','>').length())
|
|
{
|
|
MsgID msgID=selector.betweenString('<','>');
|
|
mNNTPClient.head(msgID,articleText,messageID);
|
|
mSocketControl.send(String("220 ")+String().fromInt(0)+String(" <")+messageID+String(">"));
|
|
}
|
|
else
|
|
{
|
|
DWORD articleNumber=selector.toInt();
|
|
mNNTPClient.head(articleNumber,articleText,messageID);
|
|
mSocketControl.send(String("220 ")+String().fromInt(articleNumber)+String(" <")+messageID+String(">"));
|
|
}
|
|
for(int index=0;index<articleText.size();index++)
|
|
{
|
|
consoleMessage(articleText[index].isNull()?" ":articleText[index]);
|
|
if(articleText[index].isNull())mSocketControl.send(" ");
|
|
else mSocketControl.send(articleText[index]);
|
|
}
|
|
mSocketControl.send(".");
|
|
}
|
|
else
|
|
{
|
|
mSocketControl.send("500 Proxy is not connected to server");
|
|
}
|
|
}
|
|
|
|
void YProxyThread::handleHelp(const String &string)
|
|
{
|
|
consoleMessage(String("[YProxyThread::handleHelp]")+NNTPCommands::getInstance().toString(NNTPCommands::Help));
|
|
|
|
if(isDebug())
|
|
{
|
|
mSocketControl.send("100 help text follows");
|
|
mSocketControl.send("YProxy v1.00 prototype");
|
|
mSocketControl.send(".");
|
|
}
|
|
else if(mNNTPClient.isConnected())
|
|
{
|
|
Block<String> cmdLines;
|
|
mNNTPClient.help(cmdLines);
|
|
mSocketControl.send("100 help text follows");
|
|
for(int index=0;index<cmdLines.size();index++)
|
|
mSocketControl.send(cmdLines[index]);
|
|
mSocketControl.send(".");
|
|
}
|
|
else
|
|
{
|
|
mSocketControl.send("500 Proxy is not connected to server");
|
|
}
|
|
}
|
|
|
|
void YProxyThread::handleIHave(const String &string)
|
|
{
|
|
String messageID;
|
|
|
|
consoleMessage(String("[YProxyThread::handleIHave]")+NNTPCommands::getInstance().toString(NNTPCommands::IHave));
|
|
messageID=string.betweenString('<','>');
|
|
if(isDebug())
|
|
{
|
|
mSocketControl.send("435 article not wanted - do not send it");
|
|
}
|
|
else if(mNNTPClient.isConnected())
|
|
{
|
|
if(!mNNTPClient.iHave(messageID))mSocketControl.send("435 article not wanted - do not send it");
|
|
else mSocketControl.send("335 send article to be transferred. End with <CR-LF>.<CR-LF>");
|
|
}
|
|
else
|
|
{
|
|
mSocketControl.send("500 Proxy is not connected to server");
|
|
}
|
|
}
|
|
|
|
void YProxyThread::handleNext(const String &string)
|
|
{
|
|
consoleMessage(String("[YProxyThread::handleNext]")+NNTPCommands::getInstance().toString(NNTPCommands::Next));
|
|
consoleMessage(String("[YProxyThread::handleLast]")+NNTPCommands::getInstance().toString(NNTPCommands::Last));
|
|
|
|
if(isDebug())
|
|
{
|
|
}
|
|
else if(mNNTPClient.isConnected())
|
|
{
|
|
GroupIterator groupIterator;
|
|
if(!mNNTPClient.next(groupIterator))
|
|
mSocketControl.send(String("223 ")+groupIterator.toString());
|
|
else
|
|
mSocketControl.send("420 no current article has been selected");
|
|
}
|
|
else
|
|
{
|
|
mSocketControl.send("500 Proxy is not connected to server");
|
|
}
|
|
}
|
|
|
|
void YProxyThread::handleLast(const String &string)
|
|
{
|
|
consoleMessage(String("[YProxyThread::handleLast]")+NNTPCommands::getInstance().toString(NNTPCommands::Last));
|
|
|
|
if(isDebug())
|
|
{
|
|
}
|
|
else if(mNNTPClient.isConnected())
|
|
{
|
|
GroupIterator groupIterator;
|
|
if(!mNNTPClient.last(groupIterator))
|
|
mSocketControl.send(String("223 ")+groupIterator.toString());
|
|
else
|
|
mSocketControl.send("420 no current article has been selected");
|
|
}
|
|
else
|
|
{
|
|
mSocketControl.send("500 Proxy is not connected to server");
|
|
}
|
|
}
|
|
|
|
void YProxyThread::handleNewGroups(const String &string)
|
|
{
|
|
// "NEWGROUPS 030305 024721 "
|
|
consoleMessage(String("[YProxyThread::handleNewGroups]")+NNTPCommands::getInstance().toString(NNTPCommands::NewGroups));
|
|
// bool NNTPClient::newGroups(ListItems &listItems,Block<String> &distributionGroups,const SystemTime &systemTime,bool isGMT)
|
|
}
|
|
|
|
void YProxyThread::handleNewNews(const String &string)
|
|
{
|
|
consoleMessage(String("[YProxyThread::handleNewNews]")+NNTPCommands::getInstance().toString(NNTPCommands::NewNews));
|
|
}
|
|
|
|
void YProxyThread::handlePost(const String &string)
|
|
{
|
|
consoleMessage(String("[YProxyThread::handlePost]")+NNTPCommands::getInstance().toString(NNTPCommands::Post));
|
|
}
|
|
|
|
void YProxyThread::handleQuit(const String &string)
|
|
{
|
|
consoleMessage(String("[YProxyThread::handleQuit]")+NNTPCommands::getInstance().toString(NNTPCommands::Quit));
|
|
mSocketControl.send("Goodbye.");
|
|
}
|
|
|
|
void YProxyThread::handleSlave(const String &string)
|
|
{
|
|
consoleMessage(String("[YProxyThread::handleSlave]")+NNTPCommands::getInstance().toString(NNTPCommands::Slave));
|
|
}
|
|
|
|
void YProxyThread::handleStat(const String &string)
|
|
{
|
|
consoleMessage(String("[YProxyThread::handleStat]")+NNTPCommands::getInstance().toString(NNTPCommands::Stat));
|
|
}
|
|
|
|
void YProxyThread::handleListGroup(const String &string)
|
|
{
|
|
consoleMessage(String("[YProxyThread::handleListGroup]")+NNTPCommands::getInstance().toString(NNTPCommands::ListGroup));
|
|
}
|
|
|
|
void YProxyThread::handleAuthInfoUser(const String &string)
|
|
{
|
|
consoleMessage(String("[YProxyThread::handleAuthInfoUser]")+NNTPCommands::getInstance().toString(NNTPCommands::AuthInfoUser));
|
|
if(!mNNTPClient.isConnected())mSocketControl.send("500 Proxy is not connected to server");
|
|
else mSocketControl.send("300 Continue with password");
|
|
}
|
|
|
|
void YProxyThread::handleAuthInfoPass(const String &string)
|
|
{
|
|
consoleMessage(String("[YProxyThread::handleAuthInfoPass]")+NNTPCommands::getInstance().toString(NNTPCommands::AuthInfoPass));
|
|
if(!mNNTPClient.isConnected())mSocketControl.send("500 Proxy is not connected to server");
|
|
else mSocketControl.send("202 user authenticated.");
|
|
}
|
|
|
|
//******************************************************************************************************
|
|
// virtual overloads
|
|
|
|
void YProxyThread::consoleMessage(const String &message)
|
|
{
|
|
::printf("Thread:%s %s\n",getThreadName().str(),message.str());
|
|
}
|
|
|
|
void YProxyThread::message(String messageString)
|
|
{
|
|
}
|
|
|
|
void YProxyThread::message(Block<String> &messageStrings)
|
|
{
|
|
}
|
|
|