X-Git-Url: https://git.pterodactylus.net/?p=fms.git;a=blobdiff_plain;f=src%2Ffreenet%2Ffcpv2.cpp;fp=src%2Ffreenet%2Ffcpv2.cpp;h=ecd81e7705436efc8a6f27d746238f23dc8e5a69;hp=16a7348f224427988d2932661cb571d80ac7d180;hb=4e96d123460d6363cf7274e36bd9357768eb86ad;hpb=e662ea47fba8715474851ceebacba400984ee433 diff --git a/src/freenet/fcpv2.cpp b/src/freenet/fcpv2.cpp index 16a7348..ecd81e7 100644 --- a/src/freenet/fcpv2.cpp +++ b/src/freenet/fcpv2.cpp @@ -1,8 +1,8 @@ #include "../../include/freenet/fcpv2.h" -#include -#include + #include -#include +#include +#include #ifdef _WIN32 #include @@ -11,19 +11,83 @@ #include #endif -/* XMEM doesn't play nice with strtok - should replace strtok with something else anyway -#ifdef XMEM - #include -#endif +namespace FCPv2 +{ + +/* + + Message Methods + */ -#ifdef _WIN32 - bool FCPv2::m_wsastartup=false; -#endif +Message::Message():m_name("") +{ +} +Message::Message(const std::string &name):m_name(name) +{ + +} -FCPv2::FCPv2() +Message::Message(const std::string &name, const int fieldcount, ...):m_name(name) +{ + const char *field=0; + const char *val=0; + va_list args; + va_start(args,fieldcount); + + for(int i=0; i::const_iterator i=m_fields.begin(); i!=m_fields.end(); i++) + { + rval+=(*i).first; + rval+="="+(*i).second; + rval+="\n"; + } + if(m_name=="AllData") + { + rval+="Data\n"; + } + else + { + rval+="EndMessage\n"; + } + return rval; +} + + + + + +/* + + Connection Methods + +*/ + +#ifdef _WIN32 + bool Connection::m_wsastartup=false; +#endif + +Connection::Connection():m_socket(-1),m_tempbuffer(65535,0) { #ifdef _WIN32 if(m_wsastartup==false) @@ -33,68 +97,66 @@ FCPv2::FCPv2() m_wsastartup=true; } #endif - - // initialize socket to server - m_serversocket=-1; - - // initialize buffers - m_tempbuffer=new char[65535]; - } +Connection::Connection(const int sock):m_socket(sock),m_tempbuffer(65535,0) +{ +#ifdef _WIN32 + if(m_wsastartup==false) + { + WSAData wsadata; + WSAStartup(MAKEWORD(2,2),&wsadata); + m_wsastartup=true; + } +#endif +} -FCPv2::~FCPv2() +Connection::~Connection() { Disconnect(); #ifdef _WIN32 WSACleanup(); #endif - - delete [] m_tempbuffer; - } - -const bool FCPv2::Connect(const char *host, const int port) +const bool Connection::Connect(const std::string &fcphost, const int fcpport) { - // disconnect socket to server if it is currently open - if(Connected()) + + m_sendbuffer.clear(); + m_receivebuffer.clear(); + + if(IsConnected()==true) { Disconnect(); } int rval=-1; - struct sockaddr_storage m_serveraddr; - std::ostringstream portstring; addrinfo hint,*result,*current; - result=NULL; - portstring << port; - memset(&hint,0,sizeof(addrinfo)); + result=current=0; + portstring << fcpport; + std::memset(&hint,0,sizeof(hint)); hint.ai_socktype=SOCK_STREAM; - rval=getaddrinfo(host,portstring.str().c_str(),&hint,&result); - // erase any data in buffers - m_sendbuffer.clear(); - m_receivebuffer.clear(); + rval=getaddrinfo(fcphost.c_str(),portstring.str().c_str(),&hint,&result); if(result) { - for(current=result; current!=NULL && m_serversocket==-1; current=current->ai_next) + for(current=result; current!=0 && m_socket==-1; current=current->ai_next) { - memset(&m_serveraddr,0,sizeof(struct sockaddr_storage)); - m_serversocket=socket(current->ai_family,current->ai_socktype,current->ai_protocol); + m_socket=socket(current->ai_family,current->ai_socktype,current->ai_protocol); - if(m_serversocket!=-1) + if(m_socket!=-1) { - rval=connect(m_serversocket,current->ai_addr,current->ai_addrlen); + rval=connect(m_socket,current->ai_addr,current->ai_addrlen); if(rval==-1) { Disconnect(); } } + } freeaddrinfo(result); @@ -111,333 +173,293 @@ const bool FCPv2::Connect(const char *host, const int port) } -const bool FCPv2::Disconnect() +const bool Connection::Disconnect() { - if(Connected()) + m_sendbuffer.clear(); + m_receivebuffer.clear(); + if(IsConnected()) { #ifdef _WIN32 - closesocket(m_serversocket); + closesocket(m_socket); #else - close(m_serversocket); + close(m_socket); #endif - m_serversocket=-1; + m_socket=-1; } return true; } -int FCPv2::FindOnReceiveBuffer(const char *text) +void Connection::DoReceive() { - bool found; - std::vector::size_type i,j; - size_t tlen=strlen(text); - - if(m_receivebuffer.size()>=tlen) + if(IsConnected()) { - for(i=0; i<=m_receivebuffer.size()-tlen; i++) + int len=recv(m_socket,&m_tempbuffer[0],m_tempbuffer.size(),0); + if(len>0) { - found=true; - for(j=0; j0) + { + int len=send(m_socket,&m_sendbuffer[0],m_sendbuffer.size(),0); + if(len>0) + { + m_sendbuffer.erase(m_sendbuffer.begin(),m_sendbuffer.begin()+len); + } + else + { + Disconnect(); + } + } } -FCPMessage FCPv2::ReceiveMessage() +const bool Connection::MessageReady() const { - int field=0; - int len=0; - int endlen=0; - int endmessage=-1; - char *buffpos; - char *prevpos; - char *buffer; + std::vector::const_iterator tempi; + std::vector::size_type temp; + return MessageReady(tempi,temp); +} - FCPMessage message; +const bool Connection::MessageReady(std::vector::const_iterator &endpos, std::vector::size_type &endlen) const +{ + static std::string alldatastring="AllData\n"; + static std::string datastring="\nData\n"; // need the \n at the beginning to differentiate from AllData\n + static std::string endmessagestring="EndMessage\n"; + std::vector::const_iterator tempendpos=m_receivebuffer.end(); + std::vector::size_type tempendlen=0; - // there is data on the receive buffer if(m_receivebuffer.size()>0) { - - // find Data on a line by itself following AllData - if(FindOnReceiveBuffer("AllData\n")==0) + tempendpos=std::search(m_receivebuffer.begin(),m_receivebuffer.end(),alldatastring.begin(),alldatastring.end()); + if(tempendpos==m_receivebuffer.begin()) { - endmessage=FindOnReceiveBuffer("\nData\n"); - if(endmessage!=-1) + tempendpos=std::search(m_receivebuffer.begin(),m_receivebuffer.end(),datastring.begin(),datastring.end()); + if(tempendpos!=m_receivebuffer.end()) { - endmessage++; - endlen=5; + tempendpos+=1; + tempendlen=datastring.size()-1; } } - // otherwise this is a regular message - search for EndMessage else { - endmessage=FindOnReceiveBuffer("EndMessage\n"); - endlen=11; + tempendpos=std::search(m_receivebuffer.begin(),m_receivebuffer.end(),endmessagestring.begin(),endmessagestring.end()); + tempendlen=endmessagestring.size(); } - // continue if we found "EndMessage\n" or "Data\n" - if(endmessage!=-1) + if(tempendpos!=m_receivebuffer.end()) { - // total length of message (including ending \n) - len=endmessage+endlen; - - // allocate space for message - buffer=new char[len+1]; - - // copy message from receive buffer to message buffer - std::copy(m_receivebuffer.begin(),m_receivebuffer.begin()+len,buffer); - buffer[len]='\0'; - - // remove from receive buffer - m_receivebuffer.erase(m_receivebuffer.begin(),m_receivebuffer.begin()+len); - - // set buffer position - buffpos=buffer; - - // find message name - buffpos=strtok(buffer,"\n"); - message.SetName(buffer); - - do - { - // find next field - prevpos=buffpos; - buffpos=strtok(NULL,"="); - - // continue if we aren't at the end of a regular message, or at Data for an AllData message - if(strncmp(buffpos,"EndMessage\n",11)!=0 && strncmp(buffpos,"Data\n",5)!=0) //!(strncmp(message->MessageName,"AllData",7)==0 && strncmp(buffpos,"Data\n",5)==0)) - { - - // find next value - prevpos=buffpos; - buffpos=strtok(NULL,"\n"); - - if(prevpos && buffpos) - { - message[prevpos]=buffpos; - } - - field++; - } - else - { - buffpos=0; - } - - }while(buffpos!=0); - - delete [] buffer; - + endpos=tempendpos; + endlen=tempendlen; + return true; } + } - return message; + return false; } -const long FCPv2::ReceiveRaw(char *data, long &datalen) +const bool Connection::MessageReady(std::vector::iterator &endpos, std::vector::size_type &endlen) { - long len=0; - if(m_receivebuffer.size()>0 && datalen>0) + static std::string alldatastring="AllData\n"; + static std::string datastring="\nData\n"; // need the \n at the beginning to differentiate from AllData\n + static std::string endmessagestring="EndMessage\n"; + std::vector::iterator tempendpos=m_receivebuffer.end(); + std::vector::size_type tempendlen=0; + + if(m_receivebuffer.size()>0) { - if(datalen>m_receivebuffer.size()) + tempendpos=std::search(m_receivebuffer.begin(),m_receivebuffer.end(),alldatastring.begin(),alldatastring.end()); + if(tempendpos==m_receivebuffer.begin()) { - len=m_receivebuffer.size(); + tempendpos=std::search(m_receivebuffer.begin(),m_receivebuffer.end(),datastring.begin(),datastring.end()); + if(tempendpos!=m_receivebuffer.end()) + { + tempendpos+=1; + tempendlen=datastring.size()-1; + } } else { - len=datalen; + tempendpos=std::search(m_receivebuffer.begin(),m_receivebuffer.end(),endmessagestring.begin(),endmessagestring.end()); + tempendlen=endmessagestring.size(); } - std::copy(m_receivebuffer.begin(),m_receivebuffer.begin()+len,data); - - // erase bytes from receive buffer - m_receivebuffer.erase(m_receivebuffer.begin(),m_receivebuffer.begin()+len); + if(tempendpos!=m_receivebuffer.end()) + { + endpos=tempendpos; + endlen=tempendlen; + return true; + } } - datalen=len; - return datalen; -} -void FCPv2::SendBufferedText(const char *text) -{ - unsigned int i; - for(i=0; i::iterator endpos; + std::vector::size_type endlen; + if(MessageReady(endpos,endlen)==true) { - m_sendbuffer.push_back(data[i]); - } -} + std::vector fields; -const int FCPv2::SendMessage(const char *messagename, const int fieldcount, ...) -{ - va_list args; - const char *field; - const char *val; - std::vector::size_type bytecount=0; - int i; - std::vector::size_type startlen; + Split(std::string(m_receivebuffer.begin(),endpos),"\n=",fields); + m_receivebuffer.erase(m_receivebuffer.begin(),endpos+endlen); - startlen=m_sendbuffer.size(); + message.Clear(); - SendBufferedText(messagename); - SendBufferedText("\n"); - - va_start(args,fieldcount); + if(fields.size()>0) + { + message.SetName(fields[0]); + } - for(i=0; i1) + { + for(std::vector::iterator i=fields.begin()+1; i!=fields.end();) + { + if(i+1!=fields.end()) + { + message.GetFields()[(*i)]=(*(i+1)); + i+=2; + } + else + { + i++; + } + } + } - SendBufferedText(field); - SendBufferedText("="); - SendBufferedText(val); - SendBufferedText("\n"); } - - SendBufferedText("EndMessage\n"); - - bytecount=m_sendbuffer.size()-startlen; - - va_end(args); - - return bytecount; + return false; } -const int FCPv2::SendMessage(FCPMessage &message) +const bool Connection::Receive(std::vector &data, const std::vector::size_type len) { - std::vector::size_type bytecount=0; - std::vector::size_type startlen; - FCPMessage::iterator i; - - startlen=m_sendbuffer.size(); - - if(message.GetName()!="") + if(m_receivebuffer.size()>=len && len>=0) { - SendBufferedText(message.GetName().c_str()); - SendBufferedText("\n"); - - for(i=message.begin(); i!=message.end(); i++) - { - SendBufferedText((*i).first.c_str()); - SendBufferedText("="); - SendBufferedText((*i).second.c_str()); - SendBufferedText("\n"); - } - - SendBufferedText("EndMessage\n"); + data.insert(data.end(),m_receivebuffer.begin(),m_receivebuffer.begin()+len); + m_receivebuffer.erase(m_receivebuffer.begin(),m_receivebuffer.begin()+len); + return true; + } + else + { + return false; } - - bytecount=m_sendbuffer.size()-startlen; - - return bytecount; } - -const int FCPv2::SendRaw(const char *data, const int datalen) +const bool Connection::Receive(char *data, const size_t len) { - int bytecount=datalen; - - if(bytecount>0) + if(m_receivebuffer.size()>=len && len>=0) { - SendBufferedRaw(data,datalen); + std::copy(m_receivebuffer.begin(),m_receivebuffer.begin()+len,data); + m_receivebuffer.erase(m_receivebuffer.begin(),m_receivebuffer.begin()+len); + return true; + } + else + { + return false; } - - return bytecount; - } -void FCPv2::SocketReceive() +const bool Connection::ReceiveIgnore(const size_t len) { - int len=0; - - len=recv(m_serversocket,m_tempbuffer,65535,0); - - if(len>0) + if(m_receivebuffer.size()>=len && len>=0) { - - m_receivebuffer.resize(m_receivebuffer.size()+len); - std::copy(m_tempbuffer,&m_tempbuffer[len],m_receivebuffer.end()-len); - + m_receivebuffer.erase(m_receivebuffer.begin(),m_receivebuffer.begin()+len); + return true; } - // there was an error or server closed connection - disconnect socket else { - Disconnect(); + return false; } } -void FCPv2::SocketSend() +const bool Connection::Send(const Message &message) { - int len=0; - if(m_sendbuffer.size()>0) + if(message.GetName()!="") { - len=send(m_serversocket,&m_sendbuffer[0],m_sendbuffer.size(),0); - if(len>0) - { - // move remaining data in buffer to beginning of buffer (erase the bytes we just sent) - m_sendbuffer.erase(m_sendbuffer.begin(),m_sendbuffer.begin()+len); - } - // there was an error with send - disconnect socket - else - { - Disconnect(); - } + std::string fcpstring=message.GetFCPString(); + m_sendbuffer.insert(m_sendbuffer.end(),fcpstring.begin(),fcpstring.end()); + return true; } + return false; } +const bool Connection::Send(const std::vector &data) +{ + m_sendbuffer.insert(m_sendbuffer.end(),data.begin(),data.end()); + return true; +} -const bool FCPv2::Update(const long waittime) +const bool Connection::Send(const char *data, const size_t len) { + if(data) + { + m_sendbuffer.insert(m_sendbuffer.end(),data[0],data[0]+len); + return true; + } + return false; +} - if(Connected()) +void Connection::Split(const std::string &str, const std::string &separators, std::vector &elements) +{ + std::string::size_type offset = 0; + std::string::size_type delimIndex = 0; + + delimIndex = str.find_first_of(separators, offset); + + while (delimIndex != std::string::npos) + { + elements.push_back(str.substr(offset, delimIndex - offset)); + offset += delimIndex - offset + 1; + delimIndex = str.find_first_of(separators, offset); + } + + elements.push_back(str.substr(offset)); +} + +const bool Connection::Update(const unsigned long ms) +{ + if(IsConnected()) { - m_timeval.tv_sec=waittime; - m_timeval.tv_usec=0; + m_timeval.tv_sec=ms/1000; + m_timeval.tv_usec=(ms%1000)*1000; FD_ZERO(&m_readfs); FD_ZERO(&m_writefs); - FD_SET(m_serversocket,&m_readfs); - + FD_SET(m_socket,&m_readfs); + if(m_sendbuffer.size()>0) { - FD_SET(m_serversocket,&m_writefs); + FD_SET(m_socket,&m_writefs); } - select(m_serversocket+1,&m_readfs,&m_writefs,0,&m_timeval); + select(m_socket+1,&m_readfs,&m_writefs,0,&m_timeval); - if(FD_ISSET(m_serversocket,&m_readfs)) + if(FD_ISSET(m_socket,&m_readfs)) { - SocketReceive(); + DoReceive(); } - if(Connected() && FD_ISSET(m_serversocket,&m_writefs)) + if(IsConnected() && FD_ISSET(m_socket,&m_writefs)) { - SocketSend(); + DoSend(); } - return true; + } + if(IsConnected()) + { + return true; } else { @@ -445,3 +467,22 @@ const bool FCPv2::Update(const long waittime) } } + +const bool Connection::WaitForBytes(const unsigned long ms, const size_t len) +{ + while(IsConnected() && m_receivebuffer.size()=len) + { + return true; + } + else + { + return false; + } +} + +} // namespace