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
|
/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the COPYRIGHT
* file distributed with this source distribution.
*
* This program 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 (at your option) any later version.
*
* This program 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 this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
*/
#ifndef BACKENDS_NETWORKING_CURL_CONNECTIONMANAGER_H
#define BACKENDS_NETWORKING_CURL_CONNECTIONMANAGER_H
#include "backends/networking/curl/request.h"
#include "common/str.h"
#include "common/singleton.h"
#include "common/hashmap.h"
#include "common/mutex.h"
typedef void CURL;
typedef void CURLM;
struct curl_slist;
namespace Networking {
class NetworkReadStream;
class ConnectionManager : public Common::Singleton<ConnectionManager> {
static const uint32 FRAMES_PER_SECOND = 25;
static const uint32 TIMER_INTERVAL = 1000000 / FRAMES_PER_SECOND;
static const uint32 CLOUD_PERIOD = 1; //every frame
static const uint32 CURL_PERIOD = 1; //every frame
static const uint32 DEBUG_PRINT_PERIOD = FRAMES_PER_SECOND; // once per second
friend void connectionsThread(void *); //calls handle()
typedef Common::BaseCallback<Request *> *RequestCallback;
/**
* RequestWithCallback is used by ConnectionManager to
* storage the Request and a callback which should be
* called on Request delete.
*
* Usually one won't need to pass such callback, but
* in some cases you'd like to know whether Request is
* still running.
*
* For example, Cloud::Storage is keeping track of how
* many Requests are running, and thus it needs to know
* that Request was destroyed to decrease its counter.
*
* onDeleteCallback is called with *invalid* pointer.
* ConnectionManager deletes Request first and then passes
* the pointer to the callback. One may use the address
* to find it in own HashMap or Array and remove it.
* So, again, this pointer is for information only. One
* cannot use it.
*/
struct RequestWithCallback {
Request *request;
RequestCallback onDeleteCallback;
RequestWithCallback(Request *rq = nullptr, RequestCallback cb = nullptr): request(rq), onDeleteCallback(cb) {}
};
CURLM *_multi;
bool _timerStarted;
Common::Array<RequestWithCallback> _requests, _addedRequests;
Common::Mutex _handleMutex, _addedRequestsMutex;
uint32 _frame;
void startTimer(int interval = TIMER_INTERVAL);
void stopTimer();
void handle();
void interateRequests();
void processTransfers();
bool hasAddedRequests();
public:
ConnectionManager();
virtual ~ConnectionManager();
/**
* All libcurl transfers are going through this ConnectionManager.
* So, if you want to start any libcurl transfer, you must create
* an easy handle and register it using this method.
*/
void registerEasyHandle(CURL *easy) const;
/**
* Use this method to add new Request into manager's queue.
* Manager will periodically call handle() method of these
* Requests until they set their state to FINISHED.
*
* If Request's state is RETRY, handleRetry() is called instead.
*
* The passed callback would be called after Request is deleted.
*
* @note This method starts the timer if it's not started yet.
*
* @return the same Request pointer, just as a shortcut
*/
Request *addRequest(Request *request, RequestCallback callback = nullptr);
/** Return URL-encoded version of given string. */
Common::String urlEncode(Common::String s) const;
static uint32 getCloudRequestsPeriodInMicroseconds();
};
/** Shortcut for accessing the connection manager. */
#define ConnMan Networking::ConnectionManager::instance()
} // End of namespace Networking
#endif
|