summaryrefslogtreecommitdiff
path: root/src/utils/tokencollector.hpp
blob: 6a6fdd3624f3887a03bcc0718917a917f71a051d (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
/*
 *  The Mana World Server
 *  Copyright 2007 The Mana World Development Team
 *
 *  This file is part of The Mana World.
 *
 *  The Mana World  is free software; you can redistribute  it and/or modify it
 *  under the terms of the GNU General  Public License as published by the Free
 *  Software Foundation; either version 2 of the License, or any later version.
 *
 *  The Mana  World is  distributed in  the hope  that it  will be  useful, but
 *  WITHOUT ANY WARRANTY; without even  the implied warranty of MERCHANTABILITY
 *  or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
 *  more details.
 *
 *  You should  have received a  copy of the  GNU General Public  License along
 *  with The Mana  World; if not, write to the  Free Software Foundation, Inc.,
 *  59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
 */

#ifndef TOKENCOLLECTOR_HPP
#define TOKENCOLLECTOR_HPP

#include <string>
#include <list>
#include <time.h>

/**
 * Base class containing the generic implementation of TokenCollector.
 */
class TokenCollectorBase
{
        struct Item
        {
            std::string token; /**< Cookie used by the client. */
            intptr_t data;     /**< User data. */
            time_t timeStamp;  /**< Creation time. */
        };

        /**
         * List containing client already connected. Newer clients are at the
         * back of the list.
         */
        std::list<Item> mPendingClients;

        /**
         * List containing server data waiting for clients. Newer data are at
         * the back of the list.
         */
        std::list<Item> mPendingConnects;

        /**
         * Time at which the TokenCollector performed its last check.
         */
        time_t mLastCheck;

    protected:

        virtual void removedClient(intptr_t) = 0;
        virtual void removedConnect(intptr_t) = 0;
        virtual void foundMatch(intptr_t client, intptr_t connect) = 0;
        TokenCollectorBase();
        virtual ~TokenCollectorBase();
        void insertClient(const std::string &, intptr_t);
        void removeClient(intptr_t);
        void insertConnect(const std::string &, intptr_t);
        void removeOutdated(time_t);
};

/**
 * Compile-time check to ensure that Client and ServerData are simple enough
 * for TokenCollector.
 */
template< class T > struct _TC_CheckData;
template<> struct _TC_CheckData< int > {};
template< class T > struct _TC_CheckData< T * > {};

/**
 * A class for storing and matching tokens.
 *
 * The Handler class must provide three member functions:
 *  - deletePendingClient(Client),
 *  - deletePendingConnect(ServerData), and
 *  - tokenMatched(Client, ServerData).
 *
 * The delete members will be called whenever the collector considers that a
 * token has become obsolete and it is about to remove it.
 */
template< class Handler, class Client, class ServerData >
class TokenCollector: private TokenCollectorBase
{

    public:

        TokenCollector(Handler *h): mHandler(h)
        {
            _TC_CheckData<Client> ClientMustBeSimple;
            (void)&ClientMustBeSimple;
            _TC_CheckData<ServerData> ServerDataMustBeSimple;
            (void)&ServerDataMustBeSimple;
        }

        /**
         * Checks if the server expected this client token. If so, calls
         * Handler::tokenMatched. Otherwise marks the client as pending.
         */
        void addPendingClient(const std::string &token, Client data)
        { insertClient(token, (intptr_t)data); }

        /**
         * Checks if a client already registered this token. If so, calls
         * Handler::tokenMatched. Otherwise marks the data as pending.
         */
        void addPendingConnect(const std::string &token, ServerData data)
        { insertConnect(token, (intptr_t)data); }

        /**
         * Removes a pending client.
         * @note Does not call destroyPendingClient.
         */
        void deletePendingClient(Client data)
        { removeClient((intptr_t)data); }

    private:

        void removedClient(intptr_t data)
        { mHandler->deletePendingClient((Client)data); }

        void removedConnect(intptr_t data)
        { mHandler->deletePendingConnect((ServerData)data); }

        void foundMatch(intptr_t client, intptr_t data)
        { mHandler->tokenMatched((Client)client, (ServerData)data); }

        Handler *mHandler;
};

#endif // TOKENCOLLECTOR_HPP