/* CIRCDDB - ircDDB client library in C++ Copyright (C) 2010 Michael Dirska, DL1BFF (dl1bff@mdx.de) This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . */ #if defined(WIN32) #define WIN32_LEAN_AND_MEAN #include #include #else #include #include #endif #include "IRCReceiver.h" #include IRCReceiver::IRCReceiver(int sock, IRCMessageQueue * q ) : wxThread(wxTHREAD_JOINABLE) { this->sock = sock; recvQ = q; } IRCReceiver::~IRCReceiver() { } void IRCReceiver::startWork() { terminateThread = false; Create(); Run(); } void IRCReceiver::stopWork() { terminateThread = true; Wait(); } static int doRead( int sock, char * buf, int buf_size ) { struct timeval tv; tv.tv_sec = 1; tv.tv_usec = 0; fd_set rdset; fd_set errset; FD_ZERO(&rdset); FD_ZERO(&errset); FD_SET(sock, &rdset); FD_SET(sock, &errset); int res; res = select(sock+1, &rdset, NULL, &errset, &tv); if ( res < 0 ) { wxLogSysError(wxT("IRCReceiver::doRead: select")); return -1; } else if ( res > 0 ) { if (FD_ISSET(sock, &errset)) { wxLogVerbose(wxT("IRCReceiver::doRead: select (FD_ISSET(sock, exceptfds))")); return -1; } if (FD_ISSET(sock, &rdset)) { res = recv(sock, buf, buf_size, 0); if (res < 0) { wxLogSysError(wxT("IRCReceiver::doRead: read")); return -1; } else if (res == 0) { wxLogVerbose(wxT("IRCReceiver::doRead: EOF read==0")); return -1; } else { return res; } } } return 0; } wxThread::ExitCode IRCReceiver::Entry () { IRCMessage * m = new IRCMessage(); int i; int state = 0; while (!terminateThread) { // wxLogVerbose(wxT("IRCReceiver: tick")); char buf[200]; int r = doRead( sock, buf, sizeof buf ); if (r < 0) { recvQ -> signalEOF(); delete m; // delete unfinished IRCMessage break; } for (i=0; i < r; i++) { char b = buf[i]; if (b > 0) { if (b == 10) { recvQ -> putMessage(m); m = new IRCMessage(); state = 0; } else if (b == 13) { // do nothing } else switch (state) { case 0: if (b == ':') { state = 1; // prefix } else if (b == 32) { // do nothing } else { m -> command.Append(wxChar(b)); state = 2; // command } break; case 1: if (b == 32) { state = 2; // command is next } else { m -> prefix.Append(wxChar(b)); } break; case 2: if (b == 32) { state = 3; // params m -> numParams = 1; m -> params.Add(wxT("")); } else { m -> command.Append(wxChar(b)); } break; case 3: if (b == 32) { m -> numParams ++; if (m -> numParams >= 15) { state = 5; // ignore the rest } m -> params.Add(wxT("")); } else if ((b == ':') && (m -> params[ m -> numParams-1 ].Len() == 0)) { state = 4; // rest of line is this param } else { m -> params[ m -> numParams-1 ].Append(wxChar(b)); } break; case 4: m -> params[ m -> numParams-1 ].Append(wxChar(b)); break; } // switch } // if } // for } // while return 0; }