Browse Source

Fixed buffer splitting and cleaned up some code.

release/0.19
Jessica James 9 years ago
parent
commit
e656b6f6ba
  1. 198
      Jupiter/IRC_Client.cpp
  2. 5
      Jupiter/IRC_Client.h
  3. BIN
      Release/Jupiter.lib

198
Jupiter/IRC_Client.cpp

@ -61,7 +61,7 @@ struct JUPITER_API Jupiter::IRC::Client::Data
int connectionStatus;
Jupiter::StringS configSectionName;
Jupiter::CStringS logFileName;
Jupiter::ReferenceString buffer;
Jupiter::StringS last_line;
unsigned short serverPort;
Jupiter::CStringS serverHostname;
Jupiter::StringS serverName;
@ -549,28 +549,18 @@ unsigned int Jupiter::IRC::Client::messageChannels(const Jupiter::ReadableString
return total;
}
int Jupiter::IRC::Client::primaryHandler()
int Jupiter::IRC::Client::process_line(const Jupiter::ReadableString &line)
{
if (Jupiter::IRC::Client::data_->connectionStatus == 0) return -1;
int recvVal = Jupiter::IRC::Client::data_->sock->recv();
if (recvVal > 0)
if (line.isNotEmpty())
{
Jupiter::IRC::Client::data_->buffer = Jupiter::IRC::Client::data_->sock->getBuffer();
unsigned int totalLines = Jupiter::IRC::Client::data_->buffer.wordCount(ENDL);
for (unsigned int currentLine = 0; currentLine < totalLines; currentLine++)
{
Jupiter::ReferenceString buff = Jupiter::IRC::Client::data_->buffer.getWord(currentLine, ENDL);
if (buff.isNotEmpty())
{
Jupiter::IRC::Client::writeToLogs(buff);
Jupiter::IRC::Client::writeToLogs(line);
if (Jupiter::IRC::Client::data_->printOutput != nullptr)
{
buff.println(Jupiter::IRC::Client::data_->printOutput);
}
Jupiter::ReferenceString w1 = Jupiter::ReferenceString::getWord(buff, 0, WHITESPACE);
line.println(Jupiter::IRC::Client::data_->printOutput);
Jupiter::ReferenceString w1 = Jupiter::ReferenceString::getWord(line, 0, WHITESPACE);
if (w1.isNotEmpty())
{
Jupiter::ReferenceString w2 = Jupiter::ReferenceString::getWord(buff, 1, WHITESPACE);
Jupiter::ReferenceString w2 = Jupiter::ReferenceString::getWord(line, 1, WHITESPACE);
int numeric = w2.asInt(10);
if (w1[0] == ':') //Messages
{
@ -580,7 +570,7 @@ int Jupiter::IRC::Client::primaryHandler()
{
case IRC_RPL_BOUNCE: // 010
{
Jupiter::ReferenceString portToken = Jupiter::ReferenceString::getWord(buff, 4, " ");
Jupiter::ReferenceString portToken = Jupiter::ReferenceString::getWord(line, 4, " ");
unsigned short port;
if (portToken[0] == '+') // This is most likely not used anywhere.
{
@ -604,7 +594,7 @@ int Jupiter::IRC::Client::primaryHandler()
}
if (port != 0) // Don't default -- could be non-compliant input.
{
Jupiter::IRC::Client::data_->serverHostname = Jupiter::ReferenceString::getWord(buff, 3, WHITESPACE);
Jupiter::IRC::Client::data_->serverHostname = Jupiter::ReferenceString::getWord(line, 3, WHITESPACE);
Jupiter::IRC::Client::data_->serverPort = port;
puts("Reconnecting due to old bounce.");
this->reconnect();
@ -619,10 +609,10 @@ int Jupiter::IRC::Client::primaryHandler()
switch (numeric)
{
case IRC_RPL_BOUNCEOLD: // 005
if (buff.matchi("*:Try server *, port *"))
if (line.matchi("*:Try server *, port *"))
{
Jupiter::ReferenceString portToken = Jupiter::ReferenceString::getWord(buff, 6, " ");
unsigned short bouncePort = (unsigned short)Jupiter::ReferenceString::getWord(buff, 6, " ").asInt(10);
Jupiter::ReferenceString portToken = Jupiter::ReferenceString::getWord(line, 6, " ");
unsigned short bouncePort = (unsigned short)Jupiter::ReferenceString::getWord(line, 6, " ").asInt(10);
if (portToken[0] == '+') // This is almost certainly not used anywhere.
{
@ -646,7 +636,7 @@ int Jupiter::IRC::Client::primaryHandler()
}
if (bouncePort != 0)
{
Jupiter::IRC::Client::data_->serverHostname = Jupiter::ReferenceString::getWord(buff, 4, " ");
Jupiter::IRC::Client::data_->serverHostname = Jupiter::ReferenceString::getWord(line, 4, " ");
Jupiter::IRC::Client::data_->serverHostname.truncate(1); // trailing comma
Jupiter::IRC::Client::data_->serverPort = bouncePort;
puts("Reconnecting due to old bounce.");
@ -657,7 +647,7 @@ int Jupiter::IRC::Client::primaryHandler()
break;
case IRC_ERR_UNKNOWNCOMMAND: // 421
{
Jupiter::ReferenceString command = Jupiter::ReferenceString::getWord(buff, 2, " ");
Jupiter::ReferenceString command = Jupiter::ReferenceString::getWord(line, 2, " ");
if (command.equalsi("STARTTLS")) // Server doesn't support STARTTLS
{
Jupiter::IRC::Client::data_->startCAP();
@ -705,10 +695,10 @@ int Jupiter::IRC::Client::primaryHandler()
case 0:
if (w2.equalsi("CAP"))
{
Jupiter::ReferenceString w4 = Jupiter::ReferenceString::getWord(buff, 3, WHITESPACE);
Jupiter::ReferenceString w4 = Jupiter::ReferenceString::getWord(line, 3, WHITESPACE);
if (w4.equals("LS"))
{
Jupiter::ReferenceString listParams = buff.gotoWord(4, WHITESPACE);
Jupiter::ReferenceString listParams = Jupiter::ReferenceString::gotoWord(line, 4, WHITESPACE);
if (listParams[0] == ':') listParams.shiftRight(1);
unsigned int len = listParams.wordCount(WHITESPACE);
Jupiter::ReferenceString curr;
@ -763,7 +753,7 @@ int Jupiter::IRC::Client::primaryHandler()
{
// We'll take any of these 4, just in-case any of them are missing. In general, this will trigger on 001.
case IRC_RPL_MYINFO: // 004
Jupiter::IRC::Client::data_->serverName = Jupiter::ReferenceString::getWord(buff, 3, " ");
Jupiter::IRC::Client::data_->serverName = Jupiter::ReferenceString::getWord(line, 3, " ");
case IRC_RPL_WELCOME: // 001
case IRC_RPL_YOURHOST: // 002
case IRC_RPL_CREATED: // 003
@ -829,18 +819,18 @@ int Jupiter::IRC::Client::primaryHandler()
{
case IRC_RPL_ISUPPORT: // 005
{
size_t pos = buff.find("PREFIX=("_jrs);
size_t pos = line.find("PREFIX=("_jrs);
if (pos != Jupiter::INVALID_INDEX)
{
Jupiter::ReferenceString ref = Jupiter::ReferenceString::substring(buff, pos + 8);
Jupiter::ReferenceString ref = Jupiter::ReferenceString::substring(line, pos + 8);
Jupiter::IRC::Client::data_->prefixModes = Jupiter::ReferenceString::getWord(ref, 0, ")");
ref.shiftRight(ref.find(')') + 1);
Jupiter::IRC::Client::data_->prefixes = Jupiter::ReferenceString::getWord(ref, 0, " " ENDL);
}
pos = buff.find("CHANMODES="_jrs);
pos = line.find("CHANMODES="_jrs);
if (pos != Jupiter::INVALID_INDEX)
{
Jupiter::ReferenceString ref = Jupiter::ReferenceString::substring(buff, pos + 10);
Jupiter::ReferenceString ref = Jupiter::ReferenceString::substring(line, pos + 10);
ref = ref.getWord(0, " ");
size_t pos2 = ref.find(',', 0);
if (pos != INVALID_INDEX)
@ -862,10 +852,10 @@ int Jupiter::IRC::Client::primaryHandler()
}
}
}
pos = buff.find("CHANTYPES="_jrs);
pos = line.find("CHANTYPES="_jrs);
if (pos != Jupiter::INVALID_INDEX)
{
Jupiter::ReferenceString ref = Jupiter::ReferenceString::substring(buff, pos + 10);
Jupiter::ReferenceString ref = Jupiter::ReferenceString::substring(line, pos + 10);
Jupiter::IRC::Client::data_->chanTypes = ref.getWord(0, " ");
}
}
@ -910,13 +900,13 @@ int Jupiter::IRC::Client::primaryHandler()
default: // Post-registration.
if (w2.equalsi("PRIVMSG"))
{
Jupiter::ReferenceString chan = Jupiter::ReferenceString::getWord(buff, 2, WHITESPACE);
Jupiter::ReferenceString chan = Jupiter::ReferenceString::getWord(line, 2, WHITESPACE);
if (chan.isNotEmpty())
{
Jupiter::ReferenceString nick = getSender(buff);
Jupiter::ReferenceString nick = getSender(line);
if (nick.isNotEmpty())
{
Jupiter::ReferenceString premessage = Jupiter::ReferenceString::substring(buff, buff.find(':', 1) + 1);
Jupiter::ReferenceString premessage = Jupiter::ReferenceString::substring(line, line.find(':', 1) + 1);
if (premessage[0] == '\001') //CTCP (ACTIONs are included)
{
Jupiter::ReferenceString rawmessage(premessage.ptr() + 1, premessage.size() - 1);
@ -973,21 +963,21 @@ int Jupiter::IRC::Client::primaryHandler()
}
else if (w2.equalsi("NOTICE"))
{
Jupiter::ReferenceString chan = Jupiter::ReferenceString::getWord(buff, 2, WHITESPACE);
Jupiter::ReferenceString chan = Jupiter::ReferenceString::getWord(line, 2, WHITESPACE);
if (chan.isNotEmpty())
{
size_t pos = buff.find('!', 0);
auto message = Jupiter::ReferenceString::substring(buff, buff.find(':', 1) + 1, buff.size());
if (pos < buff.find(' '))
size_t pos = line.find('!', 0);
auto message = Jupiter::ReferenceString::substring(line, line.find(':', 1) + 1, line.size());
if (pos < line.find(' '))
{
auto nick = Jupiter::ReferenceString::substring(buff, 1, pos);
auto nick = Jupiter::ReferenceString::substring(line, 1, pos);
this->OnNotice(chan, nick, message);
for (size_t i = 0; i < Jupiter::plugins->size(); i++)
Jupiter::plugins->get(i)->OnNotice(this, chan, nick, message);
}
else
{
auto sender = getSender(buff);
auto sender = getSender(line);
if (sender.isNotEmpty())
{
this->OnServerNotice(chan, sender, message);
@ -999,8 +989,8 @@ int Jupiter::IRC::Client::primaryHandler()
}
else if (w2.equalsi("NICK"))
{
auto nick = getSender(buff);
Jupiter::ReferenceString newnick = Jupiter::ReferenceString::substring(buff, buff.find(' ', 1) + 1);
auto nick = getSender(line);
Jupiter::ReferenceString newnick = Jupiter::ReferenceString::substring(line, line.find(' ', 1) + 1);
if (newnick.isNotEmpty() && newnick[0] == ':') newnick.shiftRight(1);
if (nick.equalsi(Jupiter::IRC::Client::data_->nickname))
{
@ -1017,8 +1007,8 @@ int Jupiter::IRC::Client::primaryHandler()
}
else if (w2.equalsi("JOIN"))
{
auto nick = getSender(buff);
Jupiter::ReferenceString chan = Jupiter::ReferenceString::getWord(buff, 2, WHITESPACE);
auto nick = getSender(line);
Jupiter::ReferenceString chan = Jupiter::ReferenceString::getWord(line, 2, WHITESPACE);
if (chan[0] == ':') chan.shiftRight(1);
int i = Jupiter::IRC::Client::getChannelIndex(chan);
if (Jupiter::IRC::Client::data_->nickname.equalsi(nick))
@ -1040,10 +1030,10 @@ int Jupiter::IRC::Client::primaryHandler()
}
else if (w2.equalsi("PART"))
{
auto nick = getSender(buff);
auto nick = getSender(line);
if (nick.isNotEmpty())
{
Jupiter::ReferenceString chan = Jupiter::ReferenceString::getWord(buff, 2, WHITESPACE);
Jupiter::ReferenceString chan = Jupiter::ReferenceString::getWord(line, 2, WHITESPACE);
if (chan.isNotEmpty())
{
int i = Jupiter::IRC::Client::getChannelIndex(chan);
@ -1055,9 +1045,9 @@ int Jupiter::IRC::Client::primaryHandler()
Jupiter::IRC::Client::User *user = Jupiter::IRC::Client::data_->users.get(userIndex);
Jupiter::IRC::Client::data_->channels.get(i)->delUser(nick);
Jupiter::ReferenceString reason;
size_t pos = buff.find(':', 1);
size_t pos = line.find(':', 1);
if (pos != Jupiter::INVALID_INDEX)
reason = Jupiter::ReferenceString::substring(buff, pos + 1);
reason = Jupiter::ReferenceString::substring(line, pos + 1);
this->OnPart(chan, nick, reason);
for (i = Jupiter::plugins->size() - 1; i >= 0; i--) Jupiter::plugins->get(i)->OnPart(this, chan, nick, reason);
if (nick.equalsi(Jupiter::IRC::Client::data_->nickname)) Jupiter::IRC::Client::data_->delChannel(chan);
@ -1069,13 +1059,13 @@ int Jupiter::IRC::Client::primaryHandler()
}
else if (w2.equalsi("KICK"))
{
Jupiter::ReferenceString chan = Jupiter::ReferenceString::getWord(buff, 2, WHITESPACE);
Jupiter::ReferenceString chan = Jupiter::ReferenceString::getWord(line, 2, WHITESPACE);
if (chan.isNotEmpty())
{
Jupiter::ReferenceString kicker = getSender(buff);
Jupiter::ReferenceString kicker = getSender(line);
if (kicker.isNotEmpty())
{
Jupiter::ReferenceString kicked = Jupiter::ReferenceString::getWord(buff, 3, WHITESPACE);
Jupiter::ReferenceString kicked = Jupiter::ReferenceString::getWord(line, 3, WHITESPACE);
if (kicked.isNotEmpty())
{
int i = Jupiter::IRC::Client::getChannelIndex(chan);
@ -1086,10 +1076,10 @@ int Jupiter::IRC::Client::primaryHandler()
{
Jupiter::IRC::Client::User *user = Jupiter::IRC::Client::data_->users.get(userIndex);
Jupiter::IRC::Client::data_->channels.get(i)->delUser(kicked);
size_t pos = buff.find(':', 1);
size_t pos = line.find(':', 1);
Jupiter::ReferenceString reason;
if (pos != Jupiter::INVALID_INDEX)
reason = Jupiter::ReferenceString::substring(buff, pos + 1);
reason = Jupiter::ReferenceString::substring(line, pos + 1);
this->OnKick(chan, kicker, kicked, reason);
for (i = Jupiter::plugins->size() - 1; i >= 0; i--) Jupiter::plugins->get(i)->OnKick(this, chan, kicker, kicked, reason);
if (kicked.equalsi(Jupiter::IRC::Client::data_->nickname))
@ -1106,8 +1096,8 @@ int Jupiter::IRC::Client::primaryHandler()
}
else if (w2.equalsi("QUIT"))
{
Jupiter::ReferenceString nick = getSender(buff);
Jupiter::ReferenceString message = Jupiter::ReferenceString::substring(buff, buff.find(':', 1) + 1);
Jupiter::ReferenceString nick = getSender(line);
Jupiter::ReferenceString message = Jupiter::ReferenceString::substring(line, line.find(':', 1) + 1);
int userIndex = Jupiter::IRC::Client::getUserIndex(nick);
if (userIndex >= 0)
{
@ -1122,24 +1112,24 @@ int Jupiter::IRC::Client::primaryHandler()
}
else if (w2.equalsi("INVITE"))
{
Jupiter::ReferenceString inviter = getSender(buff);
Jupiter::ReferenceString invited = Jupiter::ReferenceString::getWord(buff, 2, WHITESPACE);
Jupiter::ReferenceString chan = Jupiter::ReferenceString::substring(buff, buff.find(':', 1) + 1);
Jupiter::ReferenceString inviter = getSender(line);
Jupiter::ReferenceString invited = Jupiter::ReferenceString::getWord(line, 2, WHITESPACE);
Jupiter::ReferenceString chan = Jupiter::ReferenceString::substring(line, line.find(':', 1) + 1);
this->OnInvite(chan, inviter, invited);
for (size_t i = 0; i < Jupiter::plugins->size(); i++)
Jupiter::plugins->get(i)->OnInvite(this, chan, inviter, invited);
}
else if (w2.equalsi("MODE"))
{
Jupiter::ReferenceString chan = Jupiter::ReferenceString::getWord(buff, 2, WHITESPACE);
Jupiter::ReferenceString chan = Jupiter::ReferenceString::getWord(line, 2, WHITESPACE);
if (chan.isNotEmpty())
{
if (Jupiter::IRC::Client::data_->chanTypes.contains(chan[0]))
{
auto nick = getSender(buff);
auto nick = getSender(line);
if (nick.isNotEmpty())
{
Jupiter::ReferenceString modestring = Jupiter::ReferenceString::substring(buff, buff.find(' ', 2) + 1);
Jupiter::ReferenceString modestring = Jupiter::ReferenceString::substring(line, line.find(' ', 2) + 1);
if (modestring.wordCount(" ") > 1)
{
Jupiter::ReferenceString modes = modestring.getWord(0, " ");
@ -1195,8 +1185,8 @@ int Jupiter::IRC::Client::primaryHandler()
// else if CHGHOST
else if (numeric == IRC_RPL_NAMREPLY) // Some names.
{
Jupiter::ReferenceString chan = Jupiter::ReferenceString::getWord(buff, 4, " ");
Jupiter::ReferenceString names = Jupiter::ReferenceString::substring(buff, buff.find(':', 1) + 1);
Jupiter::ReferenceString chan = Jupiter::ReferenceString::getWord(line, 4, " ");
Jupiter::ReferenceString names = Jupiter::ReferenceString::substring(line, line.find(':', 1) + 1);
int i = Jupiter::IRC::Client::getChannelIndex(chan);
if (i >= 0)
{
@ -1210,7 +1200,7 @@ int Jupiter::IRC::Client::primaryHandler()
}
else if (numeric == IRC_RPL_ENDOFNAMES) // We're done here.
{
Jupiter::ReferenceString chan = Jupiter::ReferenceString::getWord(buff, 3, " ");
Jupiter::ReferenceString chan = Jupiter::ReferenceString::getWord(line, 3, " ");
int i = Jupiter::IRC::Client::getChannelIndex(chan);
if (i >= 0) Jupiter::IRC::Client::data_->channels.get(i)->data_->isAddingNames = false;
}
@ -1231,7 +1221,7 @@ int Jupiter::IRC::Client::primaryHandler()
}
else if (w1.equals("ERROR"))
{
Jupiter::ReferenceString reason = Jupiter::ReferenceString::substring(buff, buff.find(':') + 1);
Jupiter::ReferenceString reason = Jupiter::ReferenceString::substring(line, line.find(':') + 1);
this->OnError(reason);
for (size_t i = 0; i < Jupiter::plugins->size(); i++)
Jupiter::plugins->get(i)->OnError(this, reason);
@ -1262,24 +1252,17 @@ int Jupiter::IRC::Client::primaryHandler()
}
if (numeric != 0)
{
this->OnNumeric(numeric, buff);
this->OnNumeric(numeric, line);
for (size_t i = 0; i < Jupiter::plugins->size(); i++)
Jupiter::plugins->get(i)->OnNumeric(this, numeric, buff);
Jupiter::plugins->get(i)->OnNumeric(this, numeric, line);
}
}
this->OnRaw(buff);
this->OnRaw(line);
for (size_t i = 0; i < Jupiter::plugins->size(); i++)
Jupiter::plugins->get(i)->OnRaw(this, buff);
}
}
return 0;
Jupiter::plugins->get(i)->OnRaw(this, line);
}
int lastError = Jupiter::IRC::Client::data_->sock->getLastError();
if (lastError == 10035)
return 0;
if (Jupiter::IRC::Client::data_->connectionStatus)
Jupiter::IRC::Client::disconnect();
return lastError;
}
bool Jupiter::IRC::Client::connect()
@ -1348,19 +1331,58 @@ void Jupiter::IRC::Client::reconnect()
int Jupiter::IRC::Client::think()
{
int r = Jupiter::IRC::Client::primaryHandler();
for (size_t i = 0; i < Jupiter::plugins->size(); i++)
Jupiter::plugins->get(i)->OnThink(this);
if (r)
auto handle_error = [this](int error_code)
{
if (this->data_->dead == true)
return error_code;
if (this->data_->maxReconnectAttempts < 0 || this->data_->reconnectAttempts < this->data_->maxReconnectAttempts)
{
if (!this->data_->reconnectDelay || this->data_->reconnectTime < time(0))
this->reconnect();
return 0;
}
return error_code;
};
if (Jupiter::IRC::Client::data_->connectionStatus == 0)
return handle_error(-1);
int tmp = Jupiter::IRC::Client::data_->sock->recv();
if (tmp > 0)
{
if (Jupiter::IRC::Client::data_->dead == true) return r;
if (Jupiter::IRC::Client::data_->maxReconnectAttempts < 0 || Jupiter::IRC::Client::data_->reconnectAttempts < Jupiter::IRC::Client::data_->maxReconnectAttempts)
// Process incoming data
Jupiter::ReadableString::TokenizeResult<Jupiter::Reference_String> result = Jupiter::ReferenceString::tokenize(Jupiter::IRC::Client::data_->sock->getBuffer(), "\r\n"_jrs);
if (result.token_count != 0)
{
if (!Jupiter::IRC::Client::data_->reconnectDelay || Jupiter::IRC::Client::data_->reconnectTime < time(0)) Jupiter::IRC::Client::reconnect();
Jupiter::IRC::Client::data_->last_line += result.tokens[0];
if (result.token_count != 1)
{
Jupiter::IRC::Client::process_line(Jupiter::IRC::Client::data_->last_line);
Jupiter::IRC::Client::data_->last_line = result.tokens[result.token_count - 1];
for (size_t index = 1; index != result.token_count - 1; ++index)
if (Jupiter::IRC::Client::process_line(result.tokens[index]) != 0)
return handle_error(1);
}
else return r;
}
return 0;
}
// No incoming data; check for errors
tmp = Jupiter::IRC::Client::data_->sock->getLastError();
if (tmp == 10035) // Operation would block
return 0;
// Serious error; disconnect if necessary
if (Jupiter::IRC::Client::data_->connectionStatus != 0)
Jupiter::IRC::Client::disconnect();
return handle_error(tmp);
}
const Jupiter::ReadableString &Jupiter::IRC::Client::readConfigValue(const Jupiter::ReadableString &key, const Jupiter::ReadableString &defaultValue) const

5
Jupiter/IRC_Client.h

@ -762,12 +762,11 @@ namespace Jupiter
void send(const Jupiter::ReadableString &rawMessage);
/**
* @brief Method that is called by think() to handle all of the IRC protocol.
* Note: This command should not be used unless you wish to bypass auto-reconnect abilities. Use think() instead.
* @brief Processes an input line of IRC protocol data.
*
* @return 0 upon success, an error code otherwise.
*/
int primaryHandler();
int process_line(const Jupiter::ReadableString &line);
/**
* @brief Returns a key's value.

BIN
Release/Jupiter.lib

Binary file not shown.
Loading…
Cancel
Save