1 /* 2 * InspIRCd -- Internet Relay Chat Daemon 3 * 4 * Copyright (C) 2018, 2020-2021 Sadie Powell <sadie@witchery.services> 5 * Copyright (C) 2018 Attila Molnar <attilamolnar@hush.com> 6 * 7 * This file is part of InspIRCd. InspIRCd is free software: you can 8 * redistribute it and/or modify it under the terms of the GNU General Public 9 * License as published by the Free Software Foundation, version 2. 10 * 11 * This program is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS 13 * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more 14 * details. 15 * 16 * You should have received a copy of the GNU General Public License 17 * along with this program. If not, see <http://www.gnu.org/licenses/>. 18 */ 19 20 21 #pragma once 22 23 namespace ClientProtocol 24 { 25 namespace Messages 26 { 27 class Numeric; 28 class Join; 29 struct Part; 30 struct Kick; 31 struct Quit; 32 struct Nick; 33 class Mode; 34 struct Topic; 35 class Privmsg; 36 struct Invite; 37 struct Ping; 38 struct Pong; 39 struct Error; 40 } 41 } 42 43 /** Numeric message. 44 * Doesn't have a fixed command name, it's always a 3 digit number padded with zeroes if necessary. 45 * The first parameter is the target of the numeric which is almost always the nick of the user 46 * the numeric will be sent to. 47 */ 48 class ClientProtocol::Messages::Numeric : public ClientProtocol::Message 49 { 50 char numericstr[4]; 51 InitCommand(unsigned int number)52 void InitCommand(unsigned int number) 53 { 54 snprintf(numericstr, sizeof(numericstr), "%03u", number); 55 SetCommand(numericstr); 56 } 57 InitFromNumeric(const::Numeric::Numeric & numeric)58 void InitFromNumeric(const ::Numeric::Numeric& numeric) 59 { 60 InitCommand(numeric.GetNumeric()); 61 for (std::vector<std::string>::const_iterator i = numeric.GetParams().begin(); i != numeric.GetParams().end(); ++i) 62 PushParamRef(*i); 63 } 64 65 public: 66 /** Constructor, target is a User. 67 * @param num Numeric object to send. Must remain valid as long as this object is alive and must not be modified. 68 * @param user User to send the numeric to. May be unregistered, must remain valid as long as this object is alive. 69 */ Numeric(const::Numeric::Numeric & num,User * user)70 Numeric(const ::Numeric::Numeric& num, User* user) 71 : ClientProtocol::Message(NULL, (num.GetServer() ? num.GetServer() : ServerInstance->FakeClient->server)->GetName()) 72 { 73 if (user->registered & REG_NICK) 74 PushParamRef(user->nick); 75 else 76 PushParam("*"); 77 InitFromNumeric(num); 78 } 79 80 /** Constructor, target is a string. 81 * @param num Numeric object to send. Must remain valid as long as this object is alive and must not be modified. 82 * @param target Target string, must stay valid as long as this object is alive. 83 */ Numeric(const::Numeric::Numeric & num,const std::string & target)84 Numeric(const ::Numeric::Numeric& num, const std::string& target) 85 : ClientProtocol::Message(NULL, (num.GetServer() ? num.GetServer() : ServerInstance->FakeClient->server)->GetName()) 86 { 87 PushParamRef(target); 88 InitFromNumeric(num); 89 } 90 91 /** Constructor. Only the numeric number has to be specified. 92 * @param num Numeric number. 93 */ Numeric(unsigned int num)94 Numeric(unsigned int num) 95 : ClientProtocol::Message(NULL, ServerInstance->Config->GetServerName()) 96 { 97 InitCommand(num); 98 PushParam("*"); 99 } 100 }; 101 102 /** JOIN message. 103 * Sent when a user joins a channel. 104 */ 105 class ClientProtocol::Messages::Join : public ClientProtocol::Message 106 { 107 Membership* memb; 108 109 public: 110 /** Constructor. Does not populate parameters, call SetParams() before sending the message. 111 */ Join()112 Join() 113 : ClientProtocol::Message("JOIN") 114 , memb(NULL) 115 { 116 } 117 118 /** Constructor. 119 * @param Memb Membership of the joining user. 120 */ Join(Membership * Memb)121 Join(Membership* Memb) 122 : ClientProtocol::Message("JOIN", Memb->user) 123 { 124 SetParams(Memb); 125 } 126 127 /** Constructor. 128 * @param Memb Membership of the joining user. 129 * @param sourcestrref Message source string, must remain valid as long as this object is alive. 130 */ Join(Membership * Memb,const std::string & sourcestrref)131 Join(Membership* Memb, const std::string& sourcestrref) 132 : ClientProtocol::Message("JOIN", sourcestrref, Memb->user) 133 { 134 SetParams(Memb); 135 } 136 137 /** Populate parameters from a Membership 138 * @param Memb Membership of the joining user. 139 */ SetParams(Membership * Memb)140 void SetParams(Membership* Memb) 141 { 142 memb = Memb; 143 PushParamRef(memb->chan->name); 144 } 145 146 /** Get the Membership of the joining user. 147 * @return Membership of the joining user. 148 */ GetMember()149 Membership* GetMember() const { return memb; } 150 }; 151 152 /** PART message. 153 * Sent when a user parts a channel. 154 */ 155 struct ClientProtocol::Messages::Part : public ClientProtocol::Message 156 { 157 /** Constructor. 158 * @param memb Member parting. 159 * @param reason Part reason, may be empty. If non-empty, must remain valid as long as this object is alive. 160 */ PartPart161 Part(Membership* memb, const std::string& reason) 162 : ClientProtocol::Message("PART", memb->user) 163 { 164 PushParamRef(memb->chan->name); 165 if (!reason.empty()) 166 PushParamRef(reason); 167 } 168 }; 169 170 /** KICK message. 171 * Sent when a user is kicked from a channel. 172 */ 173 struct ClientProtocol::Messages::Kick : public ClientProtocol::Message 174 { 175 /** Constructor. 176 * @param source User that does the kick. 177 * @param memb Membership of the user being kicked. 178 * @param reason Kick reason. Must remain valid as long as this object is alive. 179 */ KickKick180 Kick(User* source, Membership* memb, const std::string& reason) 181 : ClientProtocol::Message("KICK", source) 182 { 183 PushParamRef(memb->chan->name); 184 PushParamRef(memb->user->nick); 185 PushParamRef(reason); 186 } 187 }; 188 189 /** QUIT message. 190 * Sent when a user quits. 191 */ 192 struct ClientProtocol::Messages::Quit : public ClientProtocol::Message 193 { 194 /** Constructor. 195 * @param source User quitting. 196 * @param reason Quit reason, may be empty. Must remain valid as long as this object is alive. 197 */ QuitQuit198 Quit(User* source, const std::string& reason) 199 : ClientProtocol::Message("QUIT", source) 200 { 201 if (!reason.empty()) 202 PushParamRef(reason); 203 } 204 }; 205 206 /** NICK message. 207 * Sent when a user changes their nickname. 208 */ 209 struct ClientProtocol::Messages::Nick : public ClientProtocol::Message 210 { 211 /** Constructor. 212 * @param source User changing nicks. 213 * @param newnick New nickname. Must remain valid as long as this object is alive. 214 */ NickNick215 Nick(User* source, const std::string& newnick) 216 : ClientProtocol::Message("NICK", source) 217 { 218 PushParamRef(newnick); 219 } 220 }; 221 222 /** MODE message. 223 * Sent when modes are changed on a user or channel. 224 */ 225 class ClientProtocol::Messages::Mode : public ClientProtocol::Message 226 { 227 Channel* chantarget; 228 User* usertarget; 229 Modes::ChangeList::List::const_iterator beginit; 230 Modes::ChangeList::List::const_iterator lastit; 231 232 /** Convert a range of a mode change list to mode letters and '+', '-' symbols. 233 * @param list Mode change list. 234 * @param maxlinelen Maximum output length. 235 * @param beginit Iterator to the first element in 'list' to process. 236 * @param lastit Iterator which is set to the first element not processed due to length limitations by the method. 237 */ ToModeLetters(const Modes::ChangeList::List & list,std::string::size_type maxlinelen,Modes::ChangeList::List::const_iterator beginit,Modes::ChangeList::List::const_iterator & lastit)238 static std::string ToModeLetters(const Modes::ChangeList::List& list, std::string::size_type maxlinelen, Modes::ChangeList::List::const_iterator beginit, Modes::ChangeList::List::const_iterator& lastit) 239 { 240 std::string ret; 241 std::string::size_type paramlength = 0; 242 char output_pm = '\0'; // current output state, '+' or '-' 243 244 Modes::ChangeList::List::const_iterator i; 245 for (i = beginit; i != list.end(); ++i) 246 { 247 const Modes::Change& item = *i; 248 249 const char needed_pm = (item.adding ? '+' : '-'); 250 if (needed_pm != output_pm) 251 { 252 output_pm = needed_pm; 253 ret.push_back(output_pm); 254 } 255 256 if (!item.param.empty()) 257 paramlength += item.param.length() + 1; 258 if (ret.length() + 1 + paramlength > maxlinelen) 259 { 260 // Mode sequence is getting too long 261 const char c = *ret.rbegin(); 262 if ((c == '+') || (c == '-')) 263 ret.erase(ret.size()-1); 264 break; 265 } 266 267 ret.push_back(item.mh->GetModeChar()); 268 } 269 270 lastit = i; 271 return ret; 272 } 273 274 /** Push mode parameters for modes that have one, starting at beginit to lastit (not including lastit). 275 */ PushModeParams()276 void PushModeParams() 277 { 278 for (Modes::ChangeList::List::const_iterator i = beginit; i != lastit; ++i) 279 { 280 const Modes::Change& item = *i; 281 if (!item.param.empty()) 282 PushParamRef(item.param); 283 } 284 } 285 286 public: 287 /** Convert an entire mode change list into mode letters and '+' and '-' characters. 288 * @param changelist Mode change list to convert into mode letters. 289 * @return Mode letters. 290 */ ToModeLetters(const Modes::ChangeList & changelist)291 static std::string ToModeLetters(const Modes::ChangeList& changelist) 292 { 293 // TODO: This assumes that std::string::max_size() >= UINT_MAX 294 Modes::ChangeList::List::const_iterator dummy; 295 return ToModeLetters(changelist.getlist(), UINT_MAX, changelist.getlist().begin(), dummy); 296 } 297 298 /** Constructor, populate parameters starting from a given position in a mode change list. 299 * @param source User doing the mode change. 300 * @param Chantarget Channel target of the mode change. May be NULL if Usertarget is non-NULL. 301 * @param Usertarget User target of the mode change. May be NULL if Chantarget is non-NULL. 302 * @param changelist Mode change list. Must remain valid and unchanged as long as this object is alive or until the next SetParams() call. 303 * @param beginiter Starting position of mode changes in 'changelist'. 304 */ Mode(User * source,Channel * Chantarget,User * Usertarget,const Modes::ChangeList & changelist,Modes::ChangeList::List::const_iterator beginiter)305 Mode(User* source, Channel* Chantarget, User* Usertarget, const Modes::ChangeList& changelist, Modes::ChangeList::List::const_iterator beginiter) 306 : ClientProtocol::Message("MODE", source) 307 , chantarget(Chantarget) 308 , usertarget(Usertarget) 309 , beginit(beginiter) 310 { 311 PushParamRef(GetStrTarget()); 312 PushParam(ToModeLetters(changelist.getlist(), 450, beginit, lastit)); 313 PushModeParams(); 314 } 315 316 /** Constructor, populate parameters starting from the beginning of a mode change list. 317 * @param source User doing the mode change. 318 * @param Chantarget Channel target of the mode change. May be NULL if Usertarget is non-NULL. 319 * @param Usertarget User target of the mode change. May be NULL if Chantarget is non-NULL. 320 * @param changelist Mode change list. Must remain valid and unchanged as long as this object is alive or until the next SetParams() call. 321 */ Mode(User * source,Channel * Chantarget,User * Usertarget,const Modes::ChangeList & changelist)322 Mode(User* source, Channel* Chantarget, User* Usertarget, const Modes::ChangeList& changelist) 323 : ClientProtocol::Message("MODE", source) 324 , chantarget(Chantarget) 325 , usertarget(Usertarget) 326 , beginit(changelist.getlist().begin()) 327 { 328 PushParamRef(GetStrTarget()); 329 PushParam(ToModeLetters(changelist.getlist(), 450, beginit, lastit)); 330 PushModeParams(); 331 } 332 333 /** Constructor. Does not populate parameters, call SetParams() before sending the message. 334 * The message source is set to the local server. 335 */ Mode()336 Mode() 337 : ClientProtocol::Message("MODE", ServerInstance->FakeClient) 338 , chantarget(NULL) 339 , usertarget(NULL) 340 { 341 } 342 343 /** Set parameters 344 * @param Chantarget Channel target of the mode change. May be NULL if Usertarget is non-NULL. 345 * @param Usertarget User target of the mode change. May be NULL if Chantarget is non-NULL. 346 * @param changelist Mode change list. Must remain valid and unchanged as long as this object is alive or until the next SetParams() call. 347 */ SetParams(Channel * Chantarget,User * Usertarget,const Modes::ChangeList & changelist)348 void SetParams(Channel* Chantarget, User* Usertarget, const Modes::ChangeList& changelist) 349 { 350 ClearParams(); 351 352 chantarget = Chantarget; 353 usertarget = Usertarget; 354 beginit = changelist.getlist().begin(); 355 356 PushParamRef(GetStrTarget()); 357 PushParam(ToModeLetters(changelist.getlist(), 450, beginit, lastit)); 358 PushModeParams(); 359 } 360 361 /** Get first mode change included in this MODE message. 362 * @return Iterator to the first mode change that is included in this MODE message. 363 */ GetBeginIterator()364 Modes::ChangeList::List::const_iterator GetBeginIterator() const { return beginit; } 365 366 /** Get first mode change not included in this MODE message. 367 * @return Iterator to the first mode change that is not included in this MODE message. 368 */ GetEndIterator()369 Modes::ChangeList::List::const_iterator GetEndIterator() const { return lastit; } 370 371 /** Get mode change target as a string. 372 * This is the name of the channel if the mode change targets a channel or the nickname of the user 373 * if the target is a user. 374 * @return Name of target as a string. 375 */ GetStrTarget()376 const std::string& GetStrTarget() const { return (chantarget ? chantarget->name : usertarget->nick); } 377 378 /** Get user target. 379 * @return User target or NULL if the mode change targets a channel. 380 */ GetUserTarget()381 User* GetUserTarget() const { return usertarget; } 382 383 /** Get channel target. 384 * @return Channel target or NULL if the mode change targets a user. 385 */ GetChanTarget()386 Channel* GetChanTarget() const { return chantarget; } 387 }; 388 389 /** TOPIC message. 390 */ 391 struct ClientProtocol::Messages::Topic : public ClientProtocol::Message 392 { 393 /** Constructor. 394 * @param source User changing the topic. 395 * @param chan Channel the topic is being changed on. 396 * @param newtopic New topic. May be empty, must remain valid as long as this object is alive. 397 */ TopicTopic398 Topic(User* source, const Channel* chan, const std::string& newtopic) 399 : ClientProtocol::Message("TOPIC", source) 400 { 401 PushParamRef(chan->name); 402 PushParamRef(newtopic); 403 } 404 }; 405 406 /** PRIVMSG and NOTICE message. 407 */ 408 class ClientProtocol::Messages::Privmsg : public ClientProtocol::Message 409 { PushTargetChan(char status,const Channel * targetchan)410 void PushTargetChan(char status, const Channel* targetchan) 411 { 412 if (status) 413 { 414 std::string rawtarget(1, status); 415 rawtarget.append(targetchan->name); 416 PushParam(rawtarget); 417 } 418 else 419 { 420 PushParamRef(targetchan->name); 421 } 422 } 423 PushTargetUser(const User * targetuser)424 void PushTargetUser(const User* targetuser) 425 { 426 if (targetuser->registered & REG_NICK) 427 PushParamRef(targetuser->nick); 428 else 429 PushParam("*"); 430 } 431 432 public: 433 /** Used to differentiate constructors that copy the text from constructors that do not. 434 */ 435 enum NoCopy { nocopy }; 436 437 /** Get command name from MessageType. 438 * @param mt Message type to get command name for. 439 * @return Command name for the message type. 440 */ CommandStrFromMsgType(MessageType mt)441 static const char* CommandStrFromMsgType(MessageType mt) 442 { 443 return ((mt == MSG_PRIVMSG) ? "PRIVMSG" : "NOTICE"); 444 } 445 446 /** Constructor, user source, string target, copies text. 447 * @param source Source user. 448 * @param target Privmsg target string. 449 * @param text Privmsg text, will be copied. 450 * @param mt Message type. 451 */ 452 Privmsg(User* source, const std::string& target, const std::string& text, MessageType mt = MSG_PRIVMSG) Message(CommandStrFromMsgType (mt),source)453 : ClientProtocol::Message(CommandStrFromMsgType(mt), source) 454 { 455 PushParam(target); 456 PushParam(text); 457 } 458 459 /** Constructor, user source, user target, copies text. 460 * @param source Source user. 461 * @param targetchan Target channel. 462 * @param text Privmsg text, will be copied. 463 * @param mt Message type. 464 * @param status Prefix character for status messages. If non-zero the message is a status message. Optional, defaults to 0. 465 */ 466 Privmsg(User* source, const Channel* targetchan, const std::string& text, MessageType mt = MSG_PRIVMSG, char status = 0) Message(CommandStrFromMsgType (mt),source)467 : ClientProtocol::Message(CommandStrFromMsgType(mt), source) 468 { 469 PushTargetChan(status, targetchan); 470 PushParam(text); 471 } 472 473 /** Constructor, user source, user target, copies text. 474 * @param source Source user. 475 * @param targetuser Target user. 476 * @param text Privmsg text, will be copied. 477 * @param mt Message type. 478 */ 479 Privmsg(User* source, const User* targetuser, const std::string& text, MessageType mt = MSG_PRIVMSG) Message(CommandStrFromMsgType (mt),source)480 : ClientProtocol::Message(CommandStrFromMsgType(mt), source) 481 { 482 PushTargetUser(targetuser); 483 PushParam(text); 484 } 485 486 /** Constructor, string source, string target, copies text. 487 * @param source Source user. 488 * @param target Target string. 489 * @param text Privmsg text, will be copied. 490 * @param mt Message type. 491 * @param status Prefix character for status messages. If non-zero the message is a status message. Optional, defaults to 0. 492 */ 493 Privmsg(const std::string& source, const std::string& target, const std::string& text, MessageType mt = MSG_PRIVMSG, char status = 0) Message(CommandStrFromMsgType (mt),source)494 : ClientProtocol::Message(CommandStrFromMsgType(mt), source) 495 { 496 if (status) 497 { 498 std::string rawtarget(1, status); 499 rawtarget.append(target); 500 PushParam(rawtarget); 501 } 502 else 503 { 504 PushParam(target); 505 } 506 PushParam(text); 507 } 508 509 /** Constructor, string source, channel target, copies text. 510 * @param source Source string. 511 * @param targetchan Target channel. 512 * @param text Privmsg text, will be copied. 513 * @param status Prefix character for status messages. If non-zero the message is a status message. Optional, defaults to 0. 514 * @param mt Message type. 515 */ 516 Privmsg(const std::string& source, const Channel* targetchan, const std::string& text, MessageType mt = MSG_PRIVMSG, char status = 0) Message(CommandStrFromMsgType (mt),source)517 : ClientProtocol::Message(CommandStrFromMsgType(mt), source) 518 { 519 PushTargetChan(status, targetchan); 520 PushParam(text); 521 } 522 523 /** Constructor, string source, user target, copies text. 524 * @param source Source string. 525 * @param targetuser Target user. 526 * @param text Privmsg text, will be copied. 527 * @param mt Message type. 528 */ 529 Privmsg(const std::string& source, const User* targetuser, const std::string& text, MessageType mt = MSG_PRIVMSG) Message(CommandStrFromMsgType (mt),source)530 : ClientProtocol::Message(CommandStrFromMsgType(mt), source) 531 { 532 PushTargetUser(targetuser); 533 PushParam(text); 534 } 535 536 /** Constructor, user source, string target, copies text. 537 * @param source Source user. 538 * @param target Target string. 539 * @param text Privmsg text, will not be copied. 540 * @param mt Message type. 541 */ 542 Privmsg(NoCopy, User* source, const std::string& target, const std::string& text, MessageType mt = MSG_PRIVMSG) Message(CommandStrFromMsgType (mt),source)543 : ClientProtocol::Message(CommandStrFromMsgType(mt), source) 544 { 545 PushParam(target); 546 PushParamRef(text); 547 } 548 549 /** Constructor, user source, channel target, does not copy text. 550 * @param source Source user. 551 * @param targetchan Target channel. 552 * @param text Privmsg text, will not be copied. 553 * @param status Prefix character for status messages. If non-zero the message is a status message. Optional, defaults to 0. 554 * @param mt Message type. 555 */ 556 Privmsg(NoCopy, User* source, const Channel* targetchan, const std::string& text, MessageType mt = MSG_PRIVMSG, char status = 0) Message(CommandStrFromMsgType (mt),source)557 : ClientProtocol::Message(CommandStrFromMsgType(mt), source) 558 { 559 PushTargetChan(status, targetchan); 560 PushParamRef(text); 561 } 562 563 /** Constructor, user source, user target, does not copy text. 564 * @param source Source user. 565 * @param targetuser Target user. 566 * @param text Privmsg text, will not be copied. 567 * @param mt Message type. 568 */ 569 Privmsg(NoCopy, User* source, const User* targetuser, const std::string& text, MessageType mt = MSG_PRIVMSG) Message(CommandStrFromMsgType (mt),source)570 : ClientProtocol::Message(CommandStrFromMsgType(mt), source) 571 { 572 PushTargetUser(targetuser); 573 PushParamRef(text); 574 } 575 576 /** Constructor, string source, string target, does not copy text. 577 * @param source Source string. 578 * @param target Target string. 579 * @param text Privmsg text, will not be copied. 580 * @param mt Message type. 581 */ 582 Privmsg(NoCopy, const std::string& source, const std::string& target, const std::string& text, MessageType mt = MSG_PRIVMSG) Message(CommandStrFromMsgType (mt),source)583 : ClientProtocol::Message(CommandStrFromMsgType(mt), source) 584 { 585 PushParam(target); 586 PushParamRef(text); 587 } 588 589 /** Constructor, string source, channel target, does not copy text. 590 * @param source Source string. 591 * @param targetchan Target channel. 592 * @param text Privmsg text, will not be copied. 593 * @param status Prefix character for status messages. If non-zero the message is a status message. Optional, defaults to 0. 594 * @param mt Message type. 595 */ 596 Privmsg(NoCopy, const std::string& source, const Channel* targetchan, const std::string& text, MessageType mt = MSG_PRIVMSG, char status = 0) Message(CommandStrFromMsgType (mt),source)597 : ClientProtocol::Message(CommandStrFromMsgType(mt), source) 598 { 599 PushTargetChan(status, targetchan); 600 PushParamRef(text); 601 } 602 603 /** Constructor, string source, user target, does not copy text. 604 * @param source Source string. 605 * @param targetuser Target user. 606 * @param text Privmsg text, will not be copied. 607 * @param mt Message type. 608 */ 609 Privmsg(NoCopy, const std::string& source, const User* targetuser, const std::string& text, MessageType mt = MSG_PRIVMSG) Message(CommandStrFromMsgType (mt),source)610 : ClientProtocol::Message(CommandStrFromMsgType(mt), source) 611 { 612 PushTargetUser(targetuser); 613 PushParamRef(text); 614 } 615 }; 616 617 /** INVITE message. 618 * Sent when a user is invited to join a channel. 619 */ 620 struct ClientProtocol::Messages::Invite : public ClientProtocol::Message 621 { 622 /** Constructor. 623 * @param source User inviting the target user. 624 * @param target User being invited by source. 625 * @param chan Channel the target user is being invited to. 626 */ InviteInvite627 Invite(User* source, User* target, Channel* chan) 628 : ClientProtocol::Message("INVITE", source) 629 { 630 PushParamRef(target->nick); 631 PushParamRef(chan->name); 632 } 633 }; 634 635 /** PING message. 636 * Used to check if a connection is still alive. 637 */ 638 struct ClientProtocol::Messages::Ping : public ClientProtocol::Message 639 { 640 /** Constructor. 641 * The ping cookie is the name of the local server. 642 */ PingPing643 Ping() 644 : ClientProtocol::Message("PING") 645 { 646 PushParamRef(ServerInstance->Config->GetServerName()); 647 } 648 649 /** Constructor. 650 * @param cookie Ping cookie. Must remain valid as long as this object is alive. 651 */ PingPing652 Ping(const std::string& cookie) 653 : ClientProtocol::Message("PING") 654 { 655 PushParamRef(cookie); 656 } 657 }; 658 659 /** PONG message. 660 * Sent as a reply to PING. 661 */ 662 struct ClientProtocol::Messages::Pong : public ClientProtocol::Message 663 { 664 /** Constructor. 665 * @param cookie Ping cookie. Must remain valid as long as this object is alive. 666 * @param server Pinged server. Must remain valid as long as this object is alive if non-empty. 667 */ 668 Pong(const std::string& cookie, const std::string& server = "") 669 : ClientProtocol::Message("PONG", ServerInstance->Config->GetServerName()) 670 { 671 if (server.empty()) 672 PushParamRef(ServerInstance->Config->GetServerName()); 673 else 674 PushParam(server); 675 PushParamRef(cookie); 676 } 677 }; 678 679 /** ERROR message. 680 * Sent to clients upon disconnection. 681 */ 682 struct ClientProtocol::Messages::Error : public ClientProtocol::Message 683 { 684 /** Constructor. 685 * @param text Error text. 686 */ ErrorError687 Error(const std::string& text) 688 : ClientProtocol::Message("ERROR") 689 { 690 PushParam(text); 691 } 692 }; 693