]> git.netwichtig.de Git - user/henk/code/inspircd.git/blob - include/clientprotocol.h
Fix a bunch of weird indentation and spacing issues.
[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                         : ptr(NULL)
243                         , owned(true)
244                 {
245                         new(str) std::string(s);
246                 }
247
248                 Param(int, const std::string& s)
249                         : ptr(NULL)
250                         , owned(true)
251                 {
252                         new(str) std::string(s);
253                 }
254
255                 Param(const Param& other)
256                 {
257                         InitFrom(other);
258                 }
259
260                 ~Param()
261                 {
262                         using std::string;
263                         if (owned)
264                                 str->~string();
265                 }
266
267                 Param& operator=(const Param& other)
268                 {
269                         if (&other == this)
270                                 return *this;
271
272                         using std::string;
273                         if (owned)
274                                 str->~string();
275                         InitFrom(other);
276                         return *this;
277                 }
278
279                 bool IsOwned() const { return owned; }
280         };
281
282         typedef std::vector<Param> ParamList;
283
284  private:
285         typedef std::vector<std::pair<SerializedInfo, SerializedMessage> > SerializedList;
286
287         ParamList params;
288         TagMap tags;
289         std::string command;
290         bool msginit_done;
291         mutable SerializedList serlist;
292         bool sideeffect;
293
294  protected:
295         /** Set command string.
296          * @param cmd Command string to set.
297          */
298         void SetCommand(const char* cmd)
299         {
300                 command.clear();
301                 if (cmd)
302                         command = cmd;
303         }
304
305  public:
306         /** Constructor.
307          * @param cmd Command name, e.g. "JOIN", "NICK". May be NULL. If NULL, the command must be set
308          * with SetCommand() before the message is serialized.
309          * @param Sourceuser See the one parameter constructor of MessageSource for description.
310          */
311         Message(const char* cmd, User* Sourceuser = NULL)
312                 : ClientProtocol::MessageSource(Sourceuser)
313                 , command(cmd ? cmd : std::string())
314                 , msginit_done(false)
315                 , sideeffect(false)
316         {
317                 params.reserve(8);
318                 serlist.reserve(8);
319         }
320
321         /** Constructor.
322          * @param cmd Command name, e.g. "JOIN", "NICK". May be NULL. If NULL, the command must be set
323          * with SetCommand() before the message is serialized.
324          * @param Sourcestr See the two parameter constructor of MessageSource for description.
325          * Must remain valid as long as this object is alive.
326          * @param Sourceuser See the two parameter constructor of MessageSource for description.
327          */
328         Message(const char* cmd, const std::string& Sourcestr, User* Sourceuser = NULL)
329                 : ClientProtocol::MessageSource(Sourcestr, Sourceuser)
330                 , command(cmd ? cmd : std::string())
331                 , msginit_done(false)
332                 , sideeffect(false)
333         {
334                 params.reserve(8);
335                 serlist.reserve(8);
336         }
337
338         /** Get the parameters of this message.
339          * @return List of parameters.
340          */
341         const ParamList& GetParams() const { return params; }
342
343         /** Get a map of tags attached to this message.
344          * The map contains the tag providers that attached the tag to the message.
345          * @return Map of tags.
346          */
347         const TagMap& GetTags() const { return tags; }
348
349         /** Get the command string.
350          * @return Command string, e.g. "NICK", "001".
351          */
352         const char* GetCommand() const { return command.c_str(); }
353
354         /** Add a parameter to the parameter list.
355          * @param str String to add, will be copied.
356          */
357         void PushParam(const char* str) { params.push_back(Param(0, str)); }
358
359         /** Add a parameter to the parameter list.
360          * @param str String to add, will be copied.
361          */
362         void PushParam(const std::string& str) { params.push_back(Param(0, str)); }
363
364         /** Add a parameter to the parameter list.
365          * @param str String to add.
366          * The string will NOT be copied, it must remain alive until ClearParams() is called or until the object is destroyed.
367          */
368         void PushParamRef(const std::string& str) { params.push_back(str); }
369
370         /** Add a placeholder parameter to the parameter list.
371          * Placeholder parameters must be filled in later with actual parameters using ReplaceParam() or ReplaceParamRef().
372          */
373         void PushParamPlaceholder() { params.push_back(Param()); }
374
375         /** Replace a parameter or a placeholder that is already in the parameter list.
376          * @param index Index of the parameter to replace. Must be less than GetParams().size().
377          * @param str String to replace the parameter or placeholder with, will be copied.
378          */
379         void ReplaceParam(unsigned int index, const char* str) { params[index] = Param(0, str); }
380
381         /** Replace a parameter or a placeholder that is already in the parameter list.
382          * @param index Index of the parameter to replace. Must be less than GetParams().size().
383          * @param str String to replace the parameter or placeholder with, will be copied.
384          */
385         void ReplaceParam(unsigned int index, const std::string& str) { params[index] = Param(0, str); }
386
387         /** Replace a parameter or a placeholder that is already in the parameter list.
388          * @param index Index of the parameter to replace. Must be less than GetParams().size().
389          * @param str String to replace the parameter or placeholder with.
390          * The string will NOT be copied, it must remain alive until ClearParams() is called or until the object is destroyed.
391          */
392         void ReplaceParamRef(unsigned int index, const std::string& str) { params[index] = Param(str); }
393
394         /** Add a tag.
395          * @param tagname Raw name of the tag to use in the protocol.
396          * @param tagprov Provider of the tag.
397          * @param val Tag value. If empty no value will be sent with the tag.
398          * @param tagdata Tag provider specific data, will be passed to MessageTagProvider::ShouldSendTag(). Optional, defaults to NULL.
399          */
400         void AddTag(const std::string& tagname, MessageTagProvider* tagprov, const std::string& val, void* tagdata = NULL)
401         {
402                 tags.insert(std::make_pair(tagname, MessageTagData(tagprov, val, tagdata)));
403         }
404
405         /** Add all tags in a TagMap to the tags in this message. Existing tags will not be overwritten.
406          * @param newtags New tags to add.
407          */
408         void AddTags(const ClientProtocol::TagMap& newtags)
409         {
410                 tags.insert(newtags.begin(), newtags.end());
411         }
412
413         /** Get the message in a serialized form.
414          * @param serializeinfo Information about which exact serialized form of the message is the caller asking for
415          * (which serializer to use and which tags to include).
416          * @return Serialized message according to serializeinfo. The returned reference remains valid until the
417          * next call to this method.
418          */
419         const SerializedMessage& GetSerialized(const SerializedInfo& serializeinfo) const;
420
421         /** Clear the parameter list and tags.
422          */
423         void ClearParams()
424         {
425                 msginit_done = false;
426                 params.clear();
427                 tags.clear();
428                 InvalidateCache();
429         }
430
431         /** Remove all serialized messages.
432          * If a parameter is changed after the message has been sent at least once, this method must be called before
433          * serializing the message again to ensure the cache won't contain stale data.
434          */
435         void InvalidateCache()
436         {
437                 serlist.clear();
438         }
439
440         void CopyAll()
441         {
442                 size_t j = 0;
443                 for (ParamList::iterator i = params.begin(); i != params.end(); ++i, j++)
444                 {
445                         Param& curr = *i;
446                         if (!curr.IsOwned())
447                                 ReplaceParam(j, curr);
448                 }
449         }
450
451         void SetSideEffect(bool Sideeffect) { sideeffect = Sideeffect; }
452         bool IsSideEffect() const { return sideeffect; }
453
454         friend class Serializer;
455 };
456
457 /** Client protocol event class.
458  * All messages sent to a user must be part of an event. A single event may result in more than one protocol message
459  * being sent, for example a join event may result in a JOIN and a MODE protocol message sent to members of the channel
460  * if the joining user has some prefix modes set.
461  *
462  * Event hooks attached to a specific event can alter the messages sent for that event.
463  */
464 class ClientProtocol::Event
465 {
466         EventProvider* event;
467         Message* initialmsg;
468         const MessageList* initialmsglist;
469         bool eventinit_done;
470
471  public:
472         /** Constructor.
473          * @param protoeventprov Protocol event provider the event is an instance of.
474          */
475         Event(EventProvider& protoeventprov)
476                 : event(&protoeventprov)
477                 , initialmsg(NULL)
478                 , initialmsglist(NULL)
479                 , eventinit_done(false)
480         {
481         }
482
483         /** Constructor.
484          * @param protoeventprov Protocol event provider the event is an instance of.
485          * @param msg Message to include in this event by default.
486          */
487         Event(EventProvider& protoeventprov, ClientProtocol::Message& msg)
488                 : event(&protoeventprov)
489                 , initialmsg(&msg)
490                 , initialmsglist(NULL)
491                 , eventinit_done(false)
492         {
493         }
494
495         /** Set a single message as the initial message in the event.
496          * Modules may alter this later.
497          */
498         void SetMessage(Message* msg)
499         {
500                 initialmsg = msg;
501                 initialmsglist = NULL;
502         }
503
504         /** Set a list of messages as the initial messages in the event.
505          * Modules may alter this later.
506          */
507         void SetMessageList(const MessageList& msglist)
508         {
509                 initialmsg = NULL;
510                 initialmsglist = &msglist;
511         }
512
513         /** Get a list of messages to send to a user.
514          * The exact messages sent to a user are determined by the initial message(s) set and hooks.
515          * @param user User to get the messages for.
516          * @param messagelist List to fill in with messages to send to the user for the event
517          */
518         void GetMessagesForUser(LocalUser* user, MessageList& messagelist);
519 };
520
521 class ClientProtocol::MessageTagEvent
522         : public Events::ModuleEventProvider
523 {
524  public:
525         MessageTagEvent(Module* mod)
526                 : ModuleEventProvider(mod, "event/messagetag")
527         {
528         }
529 };
530
531 /** Base class for message tag providers.
532  * All message tags belong to a message tag provider. Message tag providers can populate messages
533  * with tags before the message is sent and they have the job of determining whether a user should
534  * get a message tag or be allowed to send one.
535  */
536 class ClientProtocol::MessageTagProvider : public Events::ModuleEventListener
537 {
538  public:
539         /** Constructor.
540          * @param mod Module owning the provider.
541          */
542         MessageTagProvider(Module* mod)
543                 : Events::ModuleEventListener(mod, "event/messagetag")
544         {
545         }
546
547         /** Called when a message is ready to be sent to give the tag provider a chance to add tags to the message.
548          * To add tags call Message::AddTag(). If the provided tag or tags have been added already elsewhere or if the
549          * provider doesn't want its tag(s) to be on the message, the implementation doesn't have to do anything special.
550          * The default implementation does nothing.
551          * @param msg Message to be populated with tags.
552          */
553         virtual void OnPopulateTags(ClientProtocol::Message& msg)
554         {
555         }
556
557         /** Called for each tag that the server receives from a client in a message.
558          * @param user User that sent the tag.
559          * @param tagname Name of the tag.
560          * @param tagvalue Value of the tag, empty string if the tag has no value. May be modified.
561          * @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,
562          * MOD_RES_PASSTHRU to make no decision. If no hooks accept a tag, the tag is rejected.
563          * The default implementation returns MOD_RES_PASSTHRU.
564          */
565         virtual ModResult OnProcessTag(User* user, const std::string& tagname, std::string& tagvalue)
566         {
567                 return MOD_RES_PASSTHRU;
568         }
569
570         /** Called whenever a user is about to receive a message that has a tag attached which is provided by this provider
571          * to determine whether or not the user should get the tag.
572          * @param user User in question.
573          * @param tagdata Tag in question.
574          * @return True if the tag should be sent to the user, false otherwise.
575          */
576         virtual bool ShouldSendTag(LocalUser* user, const MessageTagData& tagdata) = 0;
577 };
578
579 /** Base class for client protocol event hooks.
580  * A protocol event hook is attached to a single event type. It has the ability to alter or block messages
581  * sent to users which belong to the event the hook is attached to.
582  */
583 class ClientProtocol::EventHook : public Events::ModuleEventListener
584 {
585  public:
586         static std::string GetEventName(const std::string& name)
587         {
588                 return "event/protoevent_" + name;
589         }
590
591         /** Constructor.
592          * @param mod Owner of the hook.
593          * @param name Name of the event to hook.
594          * @param priority Priority of the hook. Determines the order in which hooks for the same event get called.
595          * Optional.
596          */
597         EventHook(Module* mod, const std::string& name, unsigned int priority = Events::ModuleEventListener::DefaultPriority)
598                 : Events::ModuleEventListener(mod, GetEventName(name), priority)
599         {
600         }
601
602         /** Called exactly once before an event is sent to any user.
603          * The default implementation doesn't do anything.
604          * @param ev Event being sent to one or more users.
605          */
606         virtual void OnEventInit(const ClientProtocol::Event& ev)
607         {
608         }
609
610         /** Called for each user that may receive the event.
611          * The hook may alter the messages sent to the user and decide whether further hooks should be executed.
612          * @param user User the message list is being prepared to be sent to.
613          * @param ev Event associated with the messages.
614          * @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,
615          * add new messages, etc. The list must not be empty when the method returns.
616          * @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.
617          * MOD_RES_DENY to not send any messages to the user and to not run other hooks,
618          * MOD_RES_ALLOW to send the messages in messagelist to the user and to not run other hooks.
619          */
620         virtual ModResult OnPreEventSend(LocalUser* user, const ClientProtocol::Event& ev, ClientProtocol::MessageList& messagelist) = 0;
621 };
622
623 /** Event provider for client protocol events.
624  * Protocol event hooks can be attached to the instances of these providers. The core has event
625  * providers for most common IRC events defined in RFC1459.
626  */
627 class ClientProtocol::EventProvider : public Events::ModuleEventProvider
628 {
629  public:
630         /** Constructor.
631          * @param Mod Module that owns the event provider.
632          * @param eventname Name of the event this provider is for, e.g. "JOIN", "PART", "NUMERIC".
633          * Should match command name if applicable.
634          */
635         EventProvider(Module* Mod, const std::string& eventname)
636                 : Events::ModuleEventProvider(Mod, ClientProtocol::EventHook::GetEventName(eventname))
637         {
638         }
639 };
640
641 /** Commonly used client protocol events.
642  * Available via InspIRCd::GetRFCEvents().
643  */
644 struct ClientProtocol::RFCEvents
645 {
646         EventProvider numeric;
647         EventProvider join;
648         EventProvider part;
649         EventProvider kick;
650         EventProvider quit;
651         EventProvider nick;
652         EventProvider mode;
653         EventProvider topic;
654         EventProvider privmsg;
655         EventProvider invite;
656         EventProvider ping;
657         EventProvider pong;
658         EventProvider error;
659
660         RFCEvents()
661                 : numeric(NULL, "NUMERIC")
662                 , join(NULL, "JOIN")
663                 , part(NULL, "PART")
664                 , kick(NULL, "KICK")
665                 , quit(NULL, "QUIT")
666                 , nick(NULL, "NICK")
667                 , mode(NULL, "MODE")
668                 , topic(NULL, "TOPIC")
669                 , privmsg(NULL, "PRIVMSG")
670                 , invite(NULL, "INVITE")
671                 , ping(NULL, "PING")
672                 , pong(NULL, "PONG")
673                 , error(NULL, "ERROR")
674         {
675         }
676 };
677
678 /** Base class for client protocol serializers.
679  * A serializer has to implement serialization and parsing of protocol messages to/from wire format.
680  */
681 class CoreExport ClientProtocol::Serializer : public DataProvider
682 {
683  private:
684         ClientProtocol::MessageTagEvent evprov;
685
686         /** Make a white list containing which tags a user should get.
687          * @param user User in question.
688          * @param tagmap Tag map that contains all possible tags.
689          * @return Whitelist of tags to send to the user.
690          */
691         TagSelection MakeTagWhitelist(LocalUser* user, const TagMap& tagmap) const;
692
693  public:
694         /** Constructor.
695          * @param mod Module owning the serializer.
696          * @param Name Name of the serializer, e.g. "rfc".
697          */
698         Serializer(Module* mod, const char* Name);
699
700         /** Handle a tag in a message being parsed. Call this method for each parsed tag.
701          * @param user User sending the tag.
702          * @param tagname Name of the tag.
703          * @param tagvalue Tag value, may be empty.
704          * @param tags TagMap to place the tag into, if it gets accepted.
705          * @return True if no error occurred, false if the tag name is invalid or if this tag already exists.
706          */
707         bool HandleTag(LocalUser* user, const std::string& tagname, std::string& tagvalue, TagMap& tags) const;
708
709         /** Serialize a message for a user.
710          * @param user User to serialize the message for.
711          * @param msg Message to serialize.
712          * @return Raw serialized message, only containing the appropriate tags for the user.
713          * The reference is guaranteed to be valid as long as the Message object is alive and until the same
714          * Message is serialized for another user.
715          */
716         const SerializedMessage& SerializeForUser(LocalUser* user, Message& msg);
717
718         /** Serialize a high level protocol message into wire format.
719          * @param msg High level message to serialize. Contains all necessary information about the message, including all possible tags.
720          * @param tagwl Message tags to include in the serialized message. Tags attached to the message but not included in the whitelist must not
721          * appear in the output. This is because each user may get a different set of tags for the same message.
722          * @return Protocol message in wire format. Must contain message delimiter as well, if any (e.g. CRLF for RFC1459).
723          */
724         virtual std::string Serialize(const Message& msg, const TagSelection& tagwl) const = 0;
725
726         /** Parse a protocol message from wire format.
727          * @param user Source of the message.
728          * @param line Raw protocol message.
729          * @param parseoutput Output of the parser.
730          * @return True if the message was parsed successfully into parseoutput and should be processed, false to drop the message.
731          */
732         virtual bool Parse(LocalUser* user, const std::string& line, ParseOutput& parseoutput) = 0;
733 };
734
735 inline ClientProtocol::MessageTagData::MessageTagData(MessageTagProvider* prov, const std::string& val, void* data)
736         : tagprov(prov)
737         , value(val)
738         , provdata(data)
739 {
740 }