anope- supernets anope source code & configuration |
git clone git://git.acid.vegas/anope.git |
Log | Files | Refs | Archive | README |
process.cpp (4686B)
1 /* Main processing code for Services. 2 * 3 * (C) 2003-2022 Anope Team 4 * Contact us at team@anope.org 5 * 6 * Please read COPYING and README for further details. 7 * 8 * Based on the original code of Epona by Lara. 9 * Based on the original code of Services by Andy Church. 10 */ 11 12 #include "services.h" 13 #include "modules.h" 14 #include "protocol.h" 15 #include "servers.h" 16 #include "users.h" 17 #include "regchannel.h" 18 19 void Anope::Process(const Anope::string &buffer) 20 { 21 /* If debugging, log the buffer */ 22 Log(LOG_RAWIO) << "Received: " << buffer; 23 24 if (buffer.empty()) 25 return; 26 27 Anope::map<Anope::string> tags; 28 Anope::string source, command; 29 std::vector<Anope::string> params; 30 31 if (!IRCD->Parse(buffer, tags, source, command, params)) 32 return; 33 34 if (Anope::ProtocolDebug) 35 { 36 if (tags.empty()) 37 Log() << "No tags"; 38 else 39 for (Anope::map<Anope::string>::const_iterator it = tags.begin(); it != tags.end(); ++it) 40 Log() << "tags " << it->first << ": " << it->second; 41 42 Log() << "Source : " << (source.empty() ? "No source" : source); 43 Log() << "Command: " << command; 44 45 if (params.empty()) 46 Log() << "No params"; 47 else 48 for (unsigned i = 0; i < params.size(); ++i) 49 Log() << "params " << i << ": " << params[i]; 50 } 51 52 static const Anope::string proto_name = ModuleManager::FindFirstOf(PROTOCOL) ? ModuleManager::FindFirstOf(PROTOCOL)->name : ""; 53 54 MessageSource src(source); 55 56 EventReturn MOD_RESULT; 57 FOREACH_RESULT(OnMessage, MOD_RESULT, (src, command, params)); 58 if (MOD_RESULT == EVENT_STOP) 59 return; 60 61 ServiceReference<IRCDMessage> m("IRCDMessage", proto_name + "/" + command.lower()); 62 if (!m) 63 { 64 Log(LOG_DEBUG) << "unknown message from server (" << buffer << ")"; 65 return; 66 } 67 68 if (m->HasFlag(IRCDMESSAGE_SOFT_LIMIT) ? (params.size() < m->GetParamCount()) : (params.size() != m->GetParamCount())) 69 Log(LOG_DEBUG) << "invalid parameters for " << command << ": " << params.size() << " != " << m->GetParamCount(); 70 else if (m->HasFlag(IRCDMESSAGE_REQUIRE_USER) && !src.GetUser()) 71 Log(LOG_DEBUG) << "unexpected non-user source " << source << " for " << command; 72 else if (m->HasFlag(IRCDMESSAGE_REQUIRE_SERVER) && !source.empty() && !src.GetServer()) 73 Log(LOG_DEBUG) << "unexpected non-server source " << source << " for " << command; 74 else 75 m->Run(src, params, tags); 76 } 77 78 bool IRCDProto::Parse(const Anope::string &buffer, Anope::map<Anope::string> &tags, Anope::string &source, Anope::string &command, std::vector<Anope::string> ¶ms) 79 { 80 MessageTokenizer tokens(buffer); 81 82 // This will always exist because of the check in Anope::Process. 83 Anope::string token; 84 tokens.GetMiddle(token); 85 86 if (token[0] == '@') 87 { 88 // The line begins with message tags. 89 sepstream tagstream(token.substr(1), ';'); 90 while (tagstream.GetToken(token)) 91 { 92 const Anope::string::size_type valsep = token.find('='); 93 if (valsep == Anope::string::npos) 94 { 95 // Tag has no value. 96 tags[token]; 97 } 98 else 99 { 100 // Tag has a value 101 tags[token.substr(0, valsep)] = token.substr(valsep + 1); 102 } 103 } 104 105 if (!tokens.GetMiddle(token)) 106 return false; 107 } 108 109 if (token[0] == ':') 110 { 111 source = token.substr(1); 112 if (!tokens.GetMiddle(token)) 113 return false; 114 } 115 116 // Store the command name. 117 command = token; 118 119 // Retrieve all of the parameters. 120 while (tokens.GetTrailing(token)) 121 params.push_back(token); 122 123 return true; 124 } 125 126 Anope::string IRCDProto::Format(const Anope::string &source, const Anope::string &message) 127 { 128 if (!source.empty()) 129 return ":" + source + " " + message; 130 else 131 return message; 132 } 133 134 MessageTokenizer::MessageTokenizer(const Anope::string &msg) 135 : message(msg) 136 , position(0) 137 { 138 } 139 140 bool MessageTokenizer::GetMiddle(Anope::string &token) 141 { 142 // If we are past the end of the string we can't do anything. 143 if (position >= message.length()) 144 { 145 token.clear(); 146 return false; 147 } 148 149 // If we can't find another separator this is the last token in the message. 150 Anope::string::size_type separator = message.find(' ', position); 151 if (separator == Anope::string::npos) 152 { 153 token = message.substr(position); 154 position = message.length(); 155 return true; 156 } 157 158 token = message.substr(position, separator - position); 159 position = message.find_first_not_of(' ', separator); 160 return true; 161 } 162 163 bool MessageTokenizer::GetTrailing(Anope::string &token) 164 { 165 // If we are past the end of the string we can't do anything. 166 if (position >= message.length()) 167 { 168 token.clear(); 169 return false; 170 } 171 172 // If this is true then we have a <trailing> token! 173 if (message[position] == ':') 174 { 175 token = message.substr(position + 1); 176 position = message.length(); 177 return true; 178 } 179 180 // There is no <trailing> token so it must be a <middle> token. 181 return GetMiddle(token); 182 }