diff options
author | Treeki <treeki@gmail.com> | 2014-01-23 00:10:05 +0100 |
---|---|---|
committer | Treeki <treeki@gmail.com> | 2014-01-23 00:10:05 +0100 |
commit | 112d40591a6cfbbce62934753d60b0da03bfa848 (patch) | |
tree | 8c08c3c4c6320c55a3317f5a9ad5e4fb376b7a4a /ircserver.cpp | |
parent | e3e6a3f2c422a6b82b234f575a6b3bad459e5e0b (diff) | |
download | bounce4-112d40591a6cfbbce62934753d60b0da03bfa848.tar.gz bounce4-112d40591a6cfbbce62934753d60b0da03bfa848.zip |
initial bits for channel buffers, display join/privmsg in them
Diffstat (limited to '')
-rw-r--r-- | ircserver.cpp | 244 |
1 files changed, 244 insertions, 0 deletions
diff --git a/ircserver.cpp b/ircserver.cpp index f2189b2..9fafd97 100644 --- a/ircserver.cpp +++ b/ircserver.cpp @@ -9,6 +9,11 @@ IRCServer::IRCServer(Bouncer *_bouncer) : IRCServer::~IRCServer() { bouncer->deregisterWindow(&status); + + for (auto &i : channels) { + bouncer->deregisterWindow(i.second); + delete i.second; + } } void IRCServer::attachedToCore() { @@ -21,7 +26,36 @@ void IRCServer::connect() { } +void IRCServer::resetIRCState() { + strcpy(currentNick, ""); + + strcpy(serverPrefix, "@+"); + strcpy(serverPrefixMode, "ov"); +} + + +Channel *IRCServer::findChannel(const char *name, bool createIfNeeded) { + std::map<std::string, Channel *>::iterator + check = channels.find(name); + + if (check == channels.end()) { + if (createIfNeeded) { + Channel *c = new Channel(this, name); + channels[name] = c; + return c; + } else { + return 0; + } + } else { + return check->second; + } +} + + + void IRCServer::connectedEvent() { + resetIRCState(); + printf("[IRCServer:%p] connectedEvent\n", this); status.pushMessage("Connected, identifying to IRC..."); @@ -44,4 +78,214 @@ void IRCServer::lineReceivedEvent(char *line, int size) { printf("[%d] { %s }\n", size, line); status.pushMessage(line); + + + // Process this line...! + UserRef user; + + // Is there a prefix? + if (line[0] == ':') { + char nickBuf[512], identBuf[512], hostBuf[512]; + int nickPos = 0, identPos = 0, hostPos = 0; + int phase = 0; + + ++line; // skip colon + + while ((*line != ' ') && (*line != 0)) { + if (phase == 0) { + // Nick + if (*line == '!') + phase = 1; + else if (*line == '@') + phase = 2; + else { + if (nickPos < 511) + nickBuf[nickPos++] = *line; + } + } else if (phase == 1) { + // Ident + if (*line == '@') + phase = 2; + else { + if (identPos < 511) + identBuf[identPos++] = *line; + } + } else if (phase == 2) { + if (hostPos < 511) + hostBuf[hostPos++] = *line; + } + + ++line; + } + + if (*line == 0) { + // Invalid line. Can't parse this. + return; + } + + ++line; // skip the space + + nickBuf[nickPos] = 0; + identBuf[identPos] = 0; + hostBuf[hostPos] = 0; + + user.nick = nickBuf; + user.ident = identBuf; + user.hostmask = hostBuf; + + user.isValid = true; + user.isSelf = (strcmp(nickBuf, currentNick) == 0); + } + + // Get the command + char cmdBuf[512]; + int cmdPos = 0; + + while ((*line != ' ') && (*line != 0)) { + if (cmdPos < 511) + cmdBuf[cmdPos++] = *line; + ++line; + } + cmdBuf[cmdPos] = 0; + + if (*line == 0) { + // Invalid line. + return; + } + + ++line; // skip the space + + // Skip the : if there is one + if (*line == ':') + ++line; + + // Get the first param, or "target" in many cases + char *allParams = line; + char *paramsAfterFirst = line; + + char targetBuf[512]; + int targetPos = 0; + + while ((*paramsAfterFirst != ' ') && (*paramsAfterFirst != 0)) { + if (targetPos < 511) + targetBuf[targetPos++] = *paramsAfterFirst; + ++paramsAfterFirst; + } + + targetBuf[targetPos] = 0; + + // If we didn't reach the end of the line, skip the space + if (*paramsAfterFirst == ' ') + ++paramsAfterFirst; + + // And if the params begin with :, skip it + if (*paramsAfterFirst == ':') + ++paramsAfterFirst; + + // Now figure out what to do with this...! + + if (strcmp(cmdBuf, "PING") == 0) { + char out[512]; + snprintf(out, 512, "PONG %s", allParams); + sendLine(out); + + } else if (strcmp(cmdBuf, "JOIN") == 0) { + Channel *c = findChannel(targetBuf, true); + if (c) + c->handleJoin(user); + + } else if (strcmp(cmdBuf, "PRIVMSG") == 0) { + Channel *c = findChannel(targetBuf, true); + if (c) + c->handlePrivmsg(user, paramsAfterFirst); + + } else if (strcmp(cmdBuf, "001") == 0) { + status.pushMessage("[debug: currentNick change detected]"); + + strncpy(currentNick, targetBuf, sizeof(currentNick)); + currentNick[sizeof(currentNick) - 1] = 0; + + } else if (strcmp(cmdBuf, "005") == 0) { + processISupport(paramsAfterFirst); + + } else { + status.pushMessage("!! Unhandled !!"); + } +} + + +void IRCServer::processISupport(const char *line) { + while (*line != 0) { + char keyBuf[512], valueBuf[512]; + int keyPos = 0, valuePos = 0; + int phase = 0; + + // This means we've reached the end + if (*line == ':') + return; + + while ((*line != 0) && (*line != ' ')) { + if (phase == 0) { + if (*line == '=') + phase = 1; + else if (keyPos < 511) + keyBuf[keyPos++] = *line; + } else { + if (valuePos < 511) + valueBuf[valuePos++] = *line; + } + + ++line; + } + + if (*line == ' ') + ++line; + + keyBuf[keyPos] = 0; + valueBuf[valuePos] = 0; + + + // Now process the thing + + if (strcmp(keyBuf, "PREFIX") == 0) { + int prefixCount = (valuePos - 2) / 2; + + if (valueBuf[0] == '(' && valueBuf[1+prefixCount] == ')') { + if (prefixCount < 32) { + strncpy(serverPrefixMode, &valueBuf[1], prefixCount); + strncpy(serverPrefix, &valueBuf[2+prefixCount], prefixCount); + + serverPrefixMode[prefixCount] = 0; + serverPrefix[prefixCount] = 0; + } + } + } else if (strcmp(keyBuf, "CHANMODES") == 0) { + char *proc = &valueBuf[0]; + + for (int index = 0; index < 4; index++) { + if (*proc == 0) + break; + + char *start = proc; + char *end = proc; + + while ((*end != ',') && (*end != 0)) + ++end; + + // If this is a zero, we can't read any more + bool endsHere = (*end == 0); + *end = 0; + + serverChannelModes[index] = start; + char moof[1000]; + sprintf(moof, "set chanmodes %d to [%s]", index, serverChannelModes[index].c_str()); + status.pushMessage(moof); + + if (endsHere) + break; + else + proc = end + 1; + } + } + } } |