aboutsummaryrefslogtreecommitdiff
path: root/backends/networking/curl/request.h
blob: ff919e02f13c41c76ff78e38253a8d3937db4d2f (plain)
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
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
/* 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_REQUEST_H
#define BACKENDS_NETWORKING_CURL_REQUEST_H

#include "common/callback.h"
#include "common/scummsys.h"

namespace Networking {

class Request;

/**
* Response<T> is a struct to be returned from Request
* to user's callbacks. It's a type safe way to indicate
* which "return value" Request has and user awaits.
*
* It just keeps a Request pointer together with
* some T value (which might be a pointer, a reference
* or a plain type (copied by value)).
*
* To make it more convenient, typedefs are used.
* For example, Response<void *> is called DataResponse
* and corresponding callback pointer is DataCallback.
*/

template<typename T> struct Response {
	Request *request;
	T value;

	Response(Request *rq, T v) : request(rq), value(v) {}
};

typedef Response<void *> DataReponse;
typedef Common::BaseCallback<DataReponse> *DataCallback;

/**
* RequestState is used to indicate current Request state.
* ConnectionManager uses it to decide what to do with the Request.
*
* PROCESSING state indicates that Request is working.
* ConnectionManager calls handle() method of Requests in that state.
*
* PAUSED state indicates that Request is not working.
* ConnectionManager keeps Requests in that state and doesn't call any methods of those.
*
* RETRY state indicates that Request must restart after a few seconds.
* ConnectionManager calls handleRetry() method of Requests in that state.
* Default handleRetry() implementation decreases _retryInSeconds value
* until it reaches zero. When it does, Request's restart() method is called.
*
* FINISHED state indicates that Request did the work and might be deleted.
* ConnectionManager deletes Requests in that state.
* After this state is set, but before ConnectionManager deletes the Request,
* Request calls user's callback. User can ask Request to change its state
* by calling retry() or pause() methods and Request won't be deleted.
*/

enum RequestState {
	PROCESSING,
	PAUSED,
	RETRY,
	FINISHED
};

class Request {
protected:
	/**
	* Callback, which should be called when Request is finished.
	* That's the way Requests pass the result to the code which asked to create this request.
	*
	* @note some Requests use their own callbacks to return something but void *.
	* @note callback must be called in finish() or similar method.
	*/

	DataCallback _callback;

	/**
	* Request state, which is used by ConnectionManager to determine
	* whether request might be deleted or it's still working.
	*
	* State might be changed from outside with finish(), pause() or
	* retry() methods. Override these if you want to react to these
	* changes correctly.
	*/

	RequestState _state;

	/** In RETRY state this indicates whether it's time to call restart(). */
	uint32 _retryInSeconds;

public:
	Request(DataCallback cb): _callback(cb), _state(PROCESSING), _retryInSeconds(0) {}
	virtual ~Request() { delete _callback; }

	/** Method, which does actual work. Depends on what this Request is doing. */
	virtual void handle() = 0;

	/** Method, which is called by ConnectionManager when Request's state is RETRY.	 */
	virtual void handleRetry() {
		if (_retryInSeconds > 0) --_retryInSeconds;
		else {
			_state = PROCESSING;
			restart();
		}
	}

	/** Method, which is used to restart the Request. */
	virtual void restart() = 0;

	/** Method, which is called to pause the Request. */
	virtual void pause() { _state = PAUSED; }

	/**
	* Method, which is called to *interrupt* the Request.
	* When it's called, Request must stop its work and
	* call the callback to notify user of failure.
	*/
	virtual void finish() { _state = FINISHED; }

	/** Method, which is called to retry the Request. */
	virtual void retry(uint32 seconds) {		
		_state = RETRY;
		_retryInSeconds = seconds;
	}

	/** Returns Request's current state. */
	RequestState state() const { return _state; }
};

} //end of namespace Cloud

#endif