]> git.netwichtig.de Git - user/henk/code/inspircd.git/blob - include/clientprotocol.h
Implement support for the SERVLIST command.
[user/henk/code/inspircd.git] / include / clientprotocol.h
1 /*
2  * InspIRCd -- Internet Relay Chat Daemon
3  *
4  *   Copyright (C) 2018-2020 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 #include "event.h"
24
25 namespace ClientProtocol
26 {
27         class EventHook;
28         class MessageSource;
29         struct RFCEvents;
30         struct ParseOutput;
31         class TagSelection;
32 }
33
34 /** Contains a message parsed from wire format.
35  * Used by Serializer::Parse().
36  */
37 struct ClientProtocol::ParseOutput
38 {
39         /** Command name, must not be empty.
40          */
41         std::string cmd;
42
43         /** Parameter list, may be empty.
44          */
45         ClientProtocol::ParamList params;
46
47         /** Message tags, may be empty.
48          */
49         ClientProtocol::TagMap tags;
50 };
51
52 /** A selection of zero or more tags in a TagMap.
53  */
54 class ClientProtocol::TagSelection
55 {
56         std::bitset<64> selection;
57
58  public:
59         /** Check if a tag is selected.
60          * @param tags TagMap the tag is in. The TagMap must contain the same tags as it had when the tag
61          * was selected with Select(), otherwise the result is not meaningful.
62          * @param it Iterator to the tag to check.
63          * @return True if the tag is selected, false otherwise.
64          */
65         bool IsSelected(const TagMap& tags, TagMap::const_iterator it) const
66         {
67                 const size_t index = std::distance(tags.begin(), it);
68                 return ((index < selection.size()) && (selection[index]));
69         }
70
71         /** Select a tag.
72          * @param tags TagMap the tag is in. This parameter must be the same every time the method is called.
73          * The TagMap must not be altered otherwise the results of IsSelected() is not meaningful.
74          * @param it Iterator to the tag to mark as selected.
75          */
76         void Select(const TagMap& tags, TagMap::const_iterator it)
77         {
78                 const size_t index = std::distance(tags.begin(), it);
79                 if (index < selection.size())
80                         selection[index] = true;
81         }
82
83         /** Check if a TagSelection is equivalent to this object.
84          * @param other Other TagSelection object to compare this with.
85          * @return True if the objects are equivalent, false if they aren't.
86          */
87         bool operator==(const TagSelection& other) const
88         {
89                 return (this->selection == other.selection);
90         }
91 };
92
93 class ClientProtocol::MessageSource
94 {
95         User* sourceuser;
96         const std::string* sourcestr;
97
98  public:
99         /** Constructor, sets the source to be the full host of a user or sets it to be nothing.
100          * The actual source string when serializing will be obtained from User::GetFullHost() if the user is non-NULL.
101          * @param Sourceuser User to set as source of the message. If NULL, the message won't have a source when serialized.
102          * Optional, defaults to NULL.
103          */
104         MessageSource(User* Sourceuser = NULL)
105         {
106                 SetSourceUser(Sourceuser);
107         }
108
109         /** Constructor, sets the source to the supplied string and optionally sets the source user.
110          * @param Sourcestr String to use as message source for serialization purposes. Must remain valid
111          * as long as this object is alive.
112          * @param Sourceuser User to set as source. Optional, defaults to NULL. It will not be used for serialization but
113          * if provided it may be used internally, for example to create message tags.
114          * Useful when the source string is synthesized but it is still related to a User.
115          */
116         MessageSource(const std::string& Sourcestr, User* Sourceuser = NULL)
117         {
118                 SetSource(Sourcestr, Sourceuser);
119         }
120
121         /** Get the source of this message as a string.
122          * @return Pointer to the message source string or NULL if there is no source.
123          */
124         const std::string* GetSource() const
125         {
126                 // Return string if there's one explicitly set
127                 if (sourcestr)
128                         return sourcestr;
129                 if (sourceuser)
130                         return &sourceuser->GetFullHost();
131                 return NULL;
132         }
133
134         /** Get the source User.
135          * This shouldn't be used for serialization, use GetSource() for that.
136          * @return User pointer if the message has a source user, NULL otherwise.
137          */
138         User* GetSourceUser() const { return sourceuser; }
139
140         /** Set the source of this message to a User.
141          * See the one parameter constructor for a more detailed description.
142          * @param Sourceuser User to set as source.
143          */
144         void SetSourceUser(User* Sourceuser)
145         {
146                 sourceuser = Sourceuser;
147                 sourcestr = NULL;
148         }
149
150         /** Set the source string and optionally source user.
151          * See the two parameter constructor for a more detailed description.
152          * @param Sourcestr String source, to be used for serialization purposes. Must remain valid as long
153          * as this object is alive.
154          * @param Sourceuser Source user to set, optional.
155          */
156         void SetSource(const std::string& Sourcestr, User* Sourceuser = NULL)
157         {
158                 sourcestr = &Sourcestr;
159                 sourceuser = Sourceuser;
160         }
161
162         /** Copy the source from a MessageSource object.
163          * @param other MessageSource object to copy from.
164          */
165         void SetSource(const MessageSource& other)
166         {
167                 sourcestr = other.sourcestr;
168                 sourceuser = other.sourceuser;
169         }
170 };
171
172 /** Outgoing client protocol message.
173  * Represents a high level client protocol message which is turned into raw or wire format
174  * by a Serializer. Messages can be serialized into different format by different serializers.
175  *
176  * Messages are created on demand and are disposed of after they have been sent.
177  *
178  * All messages have a command name, a list of parameters and a map of tags, the last two can be empty.
179  * They also always have a source, see class MessageSource.
180  */
181 class ClientProtocol::Message : public ClientProtocol::MessageSource
182 {
183  public:
184         /** Contains information required to identify a specific version of a serialized message.
185          */
186         struct SerializedInfo
187         {
188                 const Serializer* serializer;
189                 TagSelection tagwl;
190
191                 /** Constructor.
192                  * @param Ser Serializer used to serialize the message.
193                  * @param Tagwl Tag whitelist used to serialize the message.
194                  */
195                 SerializedInfo(const Serializer* Ser, const TagSelection& Tagwl)
196                         : serializer(Ser)
197                         , tagwl(Tagwl)
198                 {
199                 }
200
201                 /** Check if a SerializedInfo object is equivalent to this object.
202                  * @param other Other SerializedInfo object.
203                  * @return True if other is equivalent to this object, false otherwise.
204                  */
205                 bool operator==(const SerializedInfo& other) const
206                 {
207                         return ((serializer == other.serializer) && (tagwl == other.tagwl));
208                 }
209         };
210
211         class Param
212         {
213                 const std::string* ptr;
214                 insp::aligned_storage<std::string> str;
215                 bool owned;
216
217                 void InitFrom(const Param& other)
218                 {
219                         owned = other.owned;
220                         if (owned)
221                                 new(str) std::string(*other.str);
222                         else
223                                 ptr = other.ptr;
224                 }
225
226          public:
227                 operator const std::string&() const { return (owned ? *str : *ptr); }
228
229                 Param()
230                         : ptr(NULL)
231                         , owned(false)
232                 {
233                 }
234
235                 Param(const std::string& s)
236                         : ptr(&s)
237                         , owned(false)
238                 {
239                 }
240
241                 Param(int, const char* s)
242                         : owned(true)
243                 {
244                         new(str) std::string(s);
245                 }
246
247                 Param(int, const std::string& s)
248                         : owned(true)
249                 {
250                          new(str) std::string(s);
251                 }
252
253                 Param(const Param& other)
254                 {
255                         InitFrom(other);
256                 }
257
258                 ~Param()
259                 {
260                         using std::string;
261                         if (owned)
262                                 str->~string();
263                 }
264
265                 Param& operator=(const Param& other)
266                 {
267                         if (&other == this)
268                                 return *this;
269
270                         using std::string;
271                         if (owned)
272                                 str->~string();
273                         InitFrom(other);
274                         return *this;
275                 }
276
277                 bool IsOwned() const { return owned; }
278         };
279
280         typedef std::vector<Param> ParamList;
281
282  private:
283         typedef std::vector<std::pair<SerializedInfo, SerializedMessage> > SerializedList;
284
285         ParamList params;
286         TagMap tags;
287         std::string command;
288         bool msginit_done;
289         mutable SerializedList serlist;
290         bool sideeffect;
291
292  protected:
293         /** Set command string.
294          * @param cmd Command string to set.
295          */
296         void SetCommand(const char* cmd)
297         {
298                 command.clear();
299                 if (cmd)
300                         command = cmd;
301         }
302
303  public:
304         /** Constructor.
305          * @param cmd Command name, e.g. "JOIN", "NICK". May be NULL. If NULL, the command must be set
306          * with SetCommand() before the message is serialized.
307          * @param Sourceuser See the one parameter constructor of MessageSource for description.
308          */
309         Message(const char* cmd, User* Sourceuser = NULL)
310                 : ClientProtocol::MessageSource(Sourceuser)
311                 , command(cmd ? cmd : std::string())
312                 , msginit_done(false)
313                 , sideeffect(false)
314         {
315                 params.reserve(8);
316                 serlist.reserve(8);
317         }
318
319         /** Constructor.
320          * @param cmd Command name, e.g. "JOIN", "NICK". May be NULL. If NULL, the command must be set
321          * with SetCommand() before the message is serialized.
322          * @param Sourcestr See the two parameter constructor of MessageSource for description.
323          * Must remain valid as long as this object is alive.
324          * @param Sourceuser See the two parameter constructor of MessageSource for description.
325          */
326         Message(const char* cmd, const std::string& Sourcestr, User* Sourceuser = NULL)
327                 : ClientProtocol::MessageSource(Sourcestr, Sourceuser)
328                 , command(cmd ? cmd : std::string())
329                 , msginit_done(false)
330                 , sideeffect(false)
331         {
332                 params.reserve(8);
333                 serlist.reserve(8);
334         }
335
336         /** Get the parameters of this message.
337          * @return List of parameters.
338          */
339         const ParamList& GetParams() const { return params; }
340
341         /** Get a map of tags attached to this message.
342          * The map contains the tag providers that attached the tag to the message.
343          * @return Map of tags.
344          */
345         const TagMap& GetTags() const { return tags; }
346
347         /** Get the command string.
348          * @return Command string, e.g. "NICK", "001".
349          */
350         const char* GetCommand() const { return command.c_str(); }
351
352         /** Add a parameter to the parameter list.
353          * @param str String to add, will be copied.
354          */
355         void PushParam(const char* str) { params.push_back(Param(0, str)); }
356
357         /** Add a parameter to the parameter list.
358          * @param str String to add, will be copied.
359          */
360         void PushParam(const std::string& str) { params.push_back(Param(0, str)); }
361
362         /** Add a parameter to the parameter list.
363          * @param str String to add.
364          * The string will NOT be copied, it must remain alive until ClearParams() is called or until the object is destroyed.
365          */
366         void PushParamRef(const std::string& str) { params.push_back(str); }
367
368         /** Add a placeholder parameter to the parameter list.
369          * Placeholder parameters must be filled in later with actual parameters using ReplaceParam() or ReplaceParamRef().
370          */
371         void PushParamPlaceholder() { params.push_back(Param()); }
372
373         /** Replace a parameter or a placeholder that is already in the parameter list.
374          * @param index Index of the parameter to replace. Must be less than GetParams().size().
375          * @param str String to replace the parameter or placeholder with, will be copied.
376          */
377         void ReplaceParam(unsigned int index, const char* str) { params[index] = Param(0, str); }
378
379         /** Replace a parameter or a placeholder that is already in the parameter list.
380          * @param index Index of the parameter to replace. Must be less than GetParams().size().
381          * @param str String to replace the parameter or placeholder with, will be copied.
382          */
383         void ReplaceParam(unsigned int index, const std::string& str) { params[index] = Param(0, str); }
384
385         /** Replace a parameter or a placeholder that is already in the parameter list.
386          * @param index Index of the parameter to replace. Must be less than GetParams().size().
387          * @param str String to replace the parameter or placeholder with.
388          * The string will NOT be copied, it must remain alive until ClearParams() is called or until the object is destroyed.
389          */
390         void ReplaceParamRef(unsigned int index, const std::string& str) { params[index] = Param(str); }
391
392         /** Add a tag.
393          * @param tagname Raw name of the tag to use in the protocol.
394          * @param tagprov Provider of the tag.
395          * @param val Tag value. If empty no value will be sent with the tag.
396          * @param tagdata Tag provider specific data, will be passed to MessageTagProvider::ShouldSendTag(). Optional, defaults to NULL.
397          */
398         void AddTag(const std::string& tagname, MessageTagProvider* tagprov, const std::string& val, void* tagdata = NULL)
399         {
400                 tags.insert(std::make_pair(tagname, MessageTagData(tagprov, val, tagdata)));
401         }
402
403         /** Add all tags in a TagMap to the tags in this message. Existing tags will not be overwritten.
404          * @param newtags New tags to add.
405          */
406         void AddTags(const ClientProtocol::TagMap& newtags)
407         {
408                 tags.insert(newtags.begin(), newtags.end());
409         }
410
411         /** Get the message in a serialized form.
412          * @param serializeinfo Information about which exact serialized form of the message is the caller asking for
413          * (which serializer to use and which tags to include).
414          * @return Serialized message according to serializeinfo. The returned reference remains valid until the
415          * next call to this method.
416          */
417         const SerializedMessage& GetSerialized(const SerializedInfo& serializeinfo) const;
418
419         /** Clear the parameter list and tags.
420          */
421         void ClearParams()
422         {
423                 msginit_done = false;
424                 params.clear();
425                 tags.clear();
426                 InvalidateCache();
427         }
428
429         /** Remove all serialized messages.
430          * If a parameter is changed after the message has been sent at least once, this method must be called before
431          * serializing the message again to ensure the cache won't contain stale data.
432          */
433         void InvalidateCache()
434         {
435                 serlist.clear();
436         }
437
438         void CopyAll()
439         {
440                 size_t j = 0;
441                 for (ParamList::iterator i = params.begin(); i != params.end(); ++i, j++)
442                 {
443                         Param& curr = *i;
444                         if (!curr.IsOwned())
445                                 ReplaceParam(j, curr);
446                 }
447         }
448
449         void SetSideEffect(bool Sideeffect) { sideeffect = Sideeffect; }
450         bool IsSideEffect() const { return sideeffect; }
451
452         friend class Serializer;
453 };
454
455 /** Client protocol event class.
456  * All messages sent to a user must be part of an event. A single event may result in more than one protocol message
457  * being sent, for example a join event may result in a JOIN and a MODE protocol message sent to members of the channel
458  * if the joining user has some prefix modes set.
459  *
460  * Event hooks attached to a specific event can alter the messages sent for that event.
461  */
462 class ClientProtocol::Event
463 {
464         EventProvider* event;
465         Message* initialmsg;
466         const MessageList* initialmsglist;
467         bool eventinit_done;
468
469  public:
470         /** Constructor.
471          * @param protoeventprov Protocol event provider the event is an instance of.
472          */
473         Event(EventProvider& protoeventprov)
474                 : event(&protoeventprov)
475                 , initialmsg(NULL)
476                 , initialmsglist(NULL)
477                 , eventinit_done(false)
478         {
479         }
480
481         /** Constructor.
482          * @param protoeventprov Protocol event provider the event is an instance of.
483          * @param msg Message to include in this event by default.
484          */
485         Event(EventProvider& protoeventprov, ClientProtocol::Message& msg)
486                 : event(&protoeventprov)
487                 , initialmsg(&msg)
488                 , initialmsglist(NULL)
489                 , eventinit_done(false)
490         {
491         }
492
493         /** Set a single message as the initial message in the event.
494          * Modules may alter this later.
495          */
496         void SetMessage(Message* msg)
497         {
498                 initialmsg = msg;
499                 initialmsglist = NULL;
500         }
501
502         /** Set a list of messages as the initial messages in the event.
503          * Modules may alter this later.
504          */
505         void SetMessageList(const MessageList& msglist)
506         {
507                 initialmsg = NULL;
508                 initialmsglist = &msglist;
509         }
510
511         /** Get a list of messages to send to a user.
512          * The exact messages sent to a user are determined by the initial message(s) set and hooks.
513          * @param user User to get the messages for.
514          * @param messagelist List to fill in with messages to send to the user for the event
515          */
516         void GetMessagesForUser(LocalUser* user, MessageList& messagelist);
517 };
518
519 class ClientProtocol::MessageTagEvent
520         : public Events::ModuleEventProvider
521 {
522  public:
523         MessageTagEvent(Module* mod)
524                 : ModuleEventProvider(mod, "event/messagetag")
525         {
526         }
527 };
528
529 /** Base class for message tag providers.
530  * All message tags belong to a message tag provider. Message tag providers can populate messages
531  * with tags before the message is sent and they have the job of determining whether a user should
532  * get a message tag or be allowed to send one.
533  */
534 class ClientProtocol::MessageTagProvider : public Events::ModuleEventListener
535 {
536  public:
537         /** Constructor.
538          * @param mod Module owning the provider.
539          */
540         MessageTagProvider(Module* mod)
541                 : Events::ModuleEventListener(mod, "event/messagetag")
542         {
543         }
544
545         /** Called when a message is ready to be sent to give the tag provider a chance to add tags to the message.
546          * To add tags call Message::AddTag(). If the provided tag or tags have been added already elsewhere or if the
547          * provider doesn't want its tag(s) to be on the message, the implementation doesn't have to do anything special.
548          * The default implementation does nothing.
549          * @param msg Message to be populated with tags.
550          */
551         virtual void OnPopulateTags(ClientProtocol::Message& msg)
552         {
553         }
554
555         /** Called for each tag that the server receives from a client in a message.
556          * @param user User that sent the tag.
557          * @param tagname Name of the tag.
558          * @param tagvalue Value of the tag, empty string if the tag has no value. May be modified.
559          * @return MOD_RES_ALLOW to accept the tag with the value in 'value', MOD_RES_DENY to reject the tag and act as if it wasn't sent,
560          * MOD_RES_PASSTHRU to make no decision. If no hooks accept a tag, the tag is rejected.
561          * The default implementation returns MOD_RES_PASSTHRU.
562          */
563         virtual ModResult OnProcessTag(User* user, const std::string& tagname, std::string& tagvalue)
564         {
565                 return MOD_RES_PASSTHRU;
566         }
567
568         /** Called whenever a user is about to receive a message that has a tag attached which is provided by this provider
569          * to determine whether or not the user should get the tag.
570          * @param user User in question.
571          * @param tagdata Tag in question.
572          * @return True if the tag should be sent to the user, false otherwise.
573          */
574         virtual bool ShouldSendTag(LocalUser* user, const MessageTagData& tagdata) = 0;
575 };
576
577 /** Base class for client protocol event hooks.
578  * A protocol event hook is attached to a single event type. It has the ability to alter or block messages
579  * sent to users which belong to the event the hook is attached to.
580  */
581 class ClientProtocol::EventHook : public Events::ModuleEventListener
582 {
583  public:
584         static std::string GetEventName(const std::string& name)
585         {
586                 return "event/protoevent_" + name;
587         }
588
589         /** Constructor.
590          * @param mod Owner of the hook.
591          * @param name Name of the event to hook.
592          * @param priority Priority of the hook. Determines the order in which hooks for the same event get called.
593          * Optional.
594          */
595         EventHook(Module* mod, const std::string& name, unsigned int priority = Events::ModuleEventListener::DefaultPriority)
596                 : Events::ModuleEventListener(mod, GetEventName(name), priority)
597         {
598         }
599
600         /** Called exactly once before an event is sent to any user.
601          * The default implementation doesn't do anything.
602          * @param ev Event being sent to one or more users.
603          */
604         virtual void OnEventInit(const ClientProtocol::Event& ev)
605         {
606         }
607
608         /** Called for each user that may receive the event.
609          * The hook may alter the messages sent to the user and decide whether further hooks should be executed.
610          * @param user User the message list is being prepared to be sent to.
611          * @param ev Event associated with the messages.
612          * @param messagelist List of messages to send to the user. The hook can alter this in any way it sees fit, for example it can replace messages,
613          * add new messages, etc. The list must not be empty when the method returns.
614          * @return MOD_RES_PASSTHRU to run hooks after the called hook or if no hooks are after the called hook, send the messages in messagelist to the user.
615          * MOD_RES_DENY to not send any messages to the user and to not run other hooks,
616          * MOD_RES_ALLOW to send the messages in messagelist to the user and to not run other hooks.
617          */
618         virtual ModResult OnPreEventSend(LocalUser* user, const ClientProtocol::Event& ev, ClientProtocol::MessageList& messagelist) = 0;
619 };
620
621 /** Event provider for client protocol events.
622  * Protocol event hooks can be attached to the instances of these providers. The core has event
623  * providers for most common IRC events defined in RFC1459.
624  */
625 class ClientProtocol::EventProvider : public Events::ModuleEventProvider
626 {
627  public:
628         /** Constructor.
629          * @param Mod Module that owns the event provider.
630          * @param eventname Name of the event this provider is for, e.g. "JOIN", "PART", "NUMERIC".
631          * Should match command name if applicable.
632          */
633         EventProvider(Module* Mod, const std::string& eventname)
634                 : Events::ModuleEventProvider(Mod, ClientProtocol::EventHook::GetEventName(eventname))
635         {
636         }
637 };
638
639 /** Commonly used client protocol events.
640  * Available via InspIRCd::GetRFCEvents().
641  */
642 struct ClientProtocol::RFCEvents
643 {
644         EventProvider numeric;
645         EventProvider join;
646         EventProvider part;
647         EventProvider kick;
648         EventProvider quit;
649         EventProvider nick;
650         EventProvider mode;
651         EventProvider topic;
652         EventProvider privmsg;
653         EventProvider invite;
654         EventProvider ping;
655         EventProvider pong;
656         EventProvider error;
657
658         RFCEvents()
659                 : numeric(NULL, "NUMERIC")
660                 , join(NULL, "JOIN")
661                 , part(NULL, "PART")
662                 , kick(NULL, "KICK")
663                 , quit(NULL, "QUIT")
664                 , nick(NULL, "NICK")
665                 , mode(NULL, "MODE")
666                 , topic(NULL, "TOPIC")
667                 , privmsg(NULL, "PRIVMSG")
668                 , invite(NULL, "INVITE")
669                 , ping(NULL, "PING")
670                 , pong(NULL, "PONG")
671                 , error(NULL, "ERROR")
672         {
673         }
674 };
675
676 /** Base class for client protocol serializers.
677  * A serializer has to implement serialization and parsing of protocol messages to/from wire format.
678  */
679 class CoreExport ClientProtocol::Serializer : public DataProvider
680 {
681  private:
682         ClientProtocol::MessageTagEvent evprov;
683
684         /** Make a white list containing which tags a user should get.
685          * @param user User in question.
686          * @param tagmap Tag map that contains all possible tags.
687          * @return Whitelist of tags to send to the user.
688          */
689         TagSelection MakeTagWhitelist(LocalUser* user, const TagMap& tagmap) const;
690
691  public:
692         /** Constructor.
693          * @param mod Module owning the serializer.
694          * @param Name Name of the serializer, e.g. "rfc".
695          */
696         Serializer(Module* mod, const char* Name);
697
698         /** Handle a tag in a message being parsed. Call this method for each parsed tag.
699          * @param user User sending the tag.
700          * @param tagname Name of the tag.
701          * @param tagvalue Tag value, may be empty.
702          * @param tags TagMap to place the tag into, if it gets accepted.
703          * @return True if no error occured, false if the tag name is invalid or if this tag already exists.
704          */
705         bool HandleTag(LocalUser* user, const std::string& tagname, std::string& tagvalue, TagMap& tags) const;
706
707         /** Serialize a message for a user.
708          * @param user User to serialize the message for.
709          * @param msg Message to serialize.
710          * @return Raw serialized message, only containing the appropriate tags for the user.
711          * The reference is guaranteed to be valid as long as the Message object is alive and until the same
712          * Message is serialized for another user.
713          */
714         const SerializedMessage& SerializeForUser(LocalUser* user, Message& msg);
715
716         /** Serialize a high level protocol message into wire format.
717          * @param msg High level message to serialize. Contains all necessary information about the message, including all possible tags.
718          * @param tagwl Message tags to include in the serialized message. Tags attached to the message but not included in the whitelist must not
719          * appear in the output. This is because each user may get a different set of tags for the same message.
720          * @return Protocol message in wire format. Must contain message delimiter as well, if any (e.g. CRLF for RFC1459).
721          */
722         virtual std::string Serialize(const Message& msg, const TagSelection& tagwl) const = 0;
723
724         /** Parse a protocol message from wire format.
725          * @param user Source of the message.
726          * @param line Raw protocol message.
727          * @param parseoutput Output of the parser.
728          * @return True if the message was parsed successfully into parseoutput and should be processed, false to drop the message.
729          */
730         virtual bool Parse(LocalUser* user, const std::string& line, ParseOutput& parseoutput) = 0;
731 };
732
733 inline ClientProtocol::MessageTagData::MessageTagData(MessageTagProvider* prov, const std::string& val, void* data)
734         : tagprov(prov)
735         , value(val)
736         , provdata(data)
737 {
738 }