1 /* ScummVM - Graphic Adventure Engine
2  *
3  * ScummVM is the legal property of its developers, whose names
4  * are too numerous to list here. Please refer to the COPYRIGHT
5  * file distributed with this source distribution.
6  *
7  * This program is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU General Public License
9  * as published by the Free Software Foundation; either version 2
10  * of the License, or (at your option) any later version.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program; if not, write to the Free Software
19  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
20  *
21  */
22 
23 #ifndef BACKENDS_NETWORKING_CURL_REQUEST_H
24 #define BACKENDS_NETWORKING_CURL_REQUEST_H
25 
26 #include "common/callback.h"
27 #include "common/scummsys.h"
28 #include "common/str.h"
29 
30 namespace Networking {
31 
32 class Request;
33 
34 /**
35  * Response<T> is a struct to be returned from Request
36  * to user's callbacks. It's a type safe way to indicate
37  * which "return value" Request has and user awaits.
38  *
39  * It just keeps a Request pointer together with
40  * some T value (which might be a pointer, a reference
41  * or a plain type (copied by value)).
42  *
43  * To make it more convenient, typedefs are used.
44  * For example, Response<void *> is called DataResponse
45  * and corresponding callback pointer is DataCallback.
46  */
47 
48 template<typename T> struct Response {
49 	Request *request;
50 	T value;
51 
ResponseResponse52 	Response(Request *rq, T v) : request(rq), value(v) {}
53 };
54 
55 /**
56  * ErrorResponse is a struct to be returned from Request
57  * to user's failure callbacks.
58  *
59  * It keeps a Request pointer together with some useful
60  * information fields, which would explain why failure
61  * callback was called.
62  *
63  * <interrupted> flag is set when Request was interrupted,
64  * i.e. finished by user with finish() call.
65  *
66  * <failed> flag is set when Request has failed because of
67  * some error (bad server response, for example).
68  *
69  * <response> contains server's original response.
70  *
71  * <httpResponseCode> contains server's HTTP response code.
72  */
73 
74 struct ErrorResponse {
75 	Request *request;
76 	bool interrupted;
77 	bool failed;
78 	Common::String response;
79 	long httpResponseCode;
80 
81 	ErrorResponse(Request *rq, Common::String resp);
82 	ErrorResponse(Request *rq, bool interrupt, bool failure, Common::String resp, long httpCode);
83 };
84 
85 typedef Response<void *> DataReponse;
86 typedef Common::BaseCallback<DataReponse> *DataCallback;
87 typedef Common::BaseCallback<ErrorResponse> *ErrorCallback;
88 
89 /**
90  * RequestState is used to indicate current Request state.
91  * ConnectionManager uses it to decide what to do with the Request.
92  *
93  * PROCESSING state indicates that Request is working.
94  * ConnectionManager calls handle() method of Requests in that state.
95  *
96  * PAUSED state indicates that Request is not working.
97  * ConnectionManager keeps Requests in that state and doesn't call any methods of those.
98  *
99  * RETRY state indicates that Request must restart after a few seconds.
100  * ConnectionManager calls handleRetry() method of Requests in that state.
101  * Default handleRetry() implementation decreases _retryInSeconds value
102  * until it reaches zero. When it does, Request's restart() method is called.
103  *
104  * FINISHED state indicates that Request did the work and might be deleted.
105  * ConnectionManager deletes Requests in that state.
106  * After this state is set, but before ConnectionManager deletes the Request,
107  * Request calls user's callback. User can ask Request to change its state
108  * by calling retry() or pause() methods and Request won't be deleted.
109  *
110  * Request get a success and failure callbacks. Request must call one
111  * (and only one!) of these callbacks when it sets FINISHED state.
112  */
113 enum RequestState {
114 	PROCESSING,
115 	PAUSED,
116 	RETRY,
117 	FINISHED
118 };
119 
120 class Request {
121 protected:
122 	/**
123 	 * Callback, which should be called when Request is finished.
124 	 * That's the way Requests pass the result to the code which asked to create this request.
125 	 *
126 	 * @note some Requests use their own callbacks to return something but void *.
127 	 * @note callback must be called in finish() or similar method.
128 	 */
129 	DataCallback _callback;
130 
131 	/**
132 	* Callback, which should be called when Request is failed/interrupted.
133 	* That's the way Requests pass error information to the code which asked to create this request.
134 	* @note callback must be called in finish() or similar method.
135 	*/
136 	ErrorCallback _errorCallback;
137 
138 	/**
139 	 * Request state, which is used by ConnectionManager to determine
140 	 * whether request might be deleted or it's still working.
141 	 *
142 	 * State might be changed from outside with finish(), pause() or
143 	 * retry() methods. Override these if you want to react to these
144 	 * changes correctly.
145 	 */
146 	RequestState _state;
147 
148 	/** In RETRY state this indicates whether it's time to call restart(). */
149 	uint32 _retryInSeconds;
150 
151 	/** Sets FINISHED state and calls the _errorCallback with given error. */
152 	virtual void finishError(ErrorResponse error);
153 
154 	/** Sets FINISHED state. Implementations might extend it if needed. */
155 	virtual void finishSuccess();
156 
157 public:
158 	Request(DataCallback cb, ErrorCallback ecb);
159 	virtual ~Request();
160 
161 	/** Method, which does actual work. Depends on what this Request is doing. */
162 	virtual void handle() = 0;
163 
164 	/** Method, which is called by ConnectionManager when Request's state is RETRY.  */
165 	virtual void handleRetry();
166 
167 	/** Method, which is used to restart the Request. */
168 	virtual void restart() = 0;
169 
170 	/** Method, which is called to pause the Request. */
171 	virtual void pause();
172 
173 	/**
174 	 * Method, which is called to *interrupt* the Request.
175 	 * When it's called, Request must stop its work and
176 	 * call the failure callback to notify user.
177 	 */
178 	virtual void finish();
179 
180 	/** Method, which is called to retry the Request. */
181 	virtual void retry(uint32 seconds);
182 
183 	/** Returns Request's current state. */
184 	RequestState state() const;
185 
186 	/**
187 	 * Return date this Request received from server.
188 	 * It could be extracted from "Date" header,
189 	 * which is kept in NetworkReadStream.
190 	 *
191 	 * @note not all Requests do that, so "" is returned
192 	 * to indicate the date is unknown. That's also true
193 	 * if no server response available or no "Date" header
194 	 * was passed.
195 	 *
196 	 * @returns date from "Date" response header.
197 	 */
198 	virtual Common::String date() const;
199 };
200 
201 } // End of namespace Networking
202 
203 #endif
204