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