2013-07-18 17:18:40 -04:00
|
|
|
// SuperTuxKart - a fun racing game with go-kart
|
2015-03-29 20:31:42 -04:00
|
|
|
// Copyright (C) 2011-2015 Joerg Henrichs
|
2013-07-28 10:11:20 -04:00
|
|
|
// 2013 Glenn De Jonghe
|
|
|
|
//
|
2013-07-18 17:18:40 -04:00
|
|
|
// 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 3
|
|
|
|
// 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
|
|
|
|
|
|
|
#ifndef HEADER_ONLINE_REQUEST_HPP
|
|
|
|
#define HEADER_ONLINE_REQUEST_HPP
|
|
|
|
|
2013-07-31 14:03:11 -04:00
|
|
|
#include "io/file_manager.hpp"
|
2014-07-28 18:35:39 -04:00
|
|
|
#include "utils/cpp2011.hpp"
|
2014-01-13 00:21:48 -05:00
|
|
|
#include "utils/leak_check.hpp"
|
|
|
|
#include "utils/no_copy.hpp"
|
2013-07-18 17:18:40 -04:00
|
|
|
#include "utils/string_utils.hpp"
|
2013-07-19 17:20:32 -04:00
|
|
|
#include "utils/synchronised.hpp"
|
2013-07-18 17:18:40 -04:00
|
|
|
|
2013-07-31 14:03:11 -04:00
|
|
|
#ifdef WIN32
|
|
|
|
# include <winsock2.h>
|
|
|
|
#endif
|
|
|
|
#include <curl/curl.h>
|
2013-08-06 18:45:33 -04:00
|
|
|
#include <assert.h>
|
2013-07-31 14:03:11 -04:00
|
|
|
#include <string>
|
2013-08-18 18:22:00 -04:00
|
|
|
|
2014-01-08 23:57:58 -05:00
|
|
|
namespace Online
|
|
|
|
{
|
2014-03-29 06:33:43 -04:00
|
|
|
/** Stores a request for the HTTP Manager. They will be sorted by
|
2014-01-08 07:08:46 -05:00
|
|
|
* prioritiy. Requests have four different states they can be in, and
|
|
|
|
* this state determines which thread can access it. This allows
|
|
|
|
* the use of threading without adding more synchronisation overhead
|
|
|
|
* and code to the main thread. The states are:
|
2014-03-29 06:33:43 -04:00
|
|
|
* - Preparing\n The request is created, and parameter are set.
|
2014-01-08 07:08:46 -05:00
|
|
|
* Only the main thread can access this object.
|
2014-01-08 23:57:58 -05:00
|
|
|
* - Busy\n The request is put into the request_manager queue. It remains
|
2014-01-08 07:08:46 -05:00
|
|
|
* in this states till its operation is finished. No more changes
|
|
|
|
* to this object by the main thread are allowed, only the manager
|
|
|
|
* thread can change it now.
|
2014-03-29 06:33:43 -04:00
|
|
|
* - Executed\n The request was executed (its operation called and
|
2014-01-08 07:08:46 -05:00
|
|
|
* finished), but callbacks still need to be done by the manager
|
|
|
|
* thread (main reason for this state is to have asserts in
|
|
|
|
* function accessing data).
|
2014-03-29 06:33:43 -04:00
|
|
|
* - Done\n All callbacks are done (they will be executed by the main
|
2014-01-08 07:08:46 -05:00
|
|
|
* thread), the request was moved from the manager's request queue
|
|
|
|
* to its finished queue, executed its callbacks and was removed
|
|
|
|
* from the queue. The manager thread will not access this object
|
|
|
|
* anymore, and the main thread is now able to access the request
|
|
|
|
* object again.
|
2014-03-29 06:33:43 -04:00
|
|
|
*
|
2014-01-08 07:08:46 -05:00
|
|
|
* \ingroup online
|
|
|
|
*/
|
2014-01-13 00:21:48 -05:00
|
|
|
class Request : public NoCopy
|
2013-07-18 17:18:40 -04:00
|
|
|
{
|
2013-07-21 11:21:48 -04:00
|
|
|
private:
|
2014-01-13 00:21:48 -05:00
|
|
|
LEAK_CHECK()
|
|
|
|
|
2014-01-08 07:08:46 -05:00
|
|
|
/** Type of the request. Has 0 as default value. */
|
2014-03-04 16:21:19 -05:00
|
|
|
const int m_type;
|
|
|
|
|
2013-07-18 17:18:40 -04:00
|
|
|
/** True if the memory for this Request should be managed by
|
|
|
|
* http connector (i.e. this object is freed once the request
|
|
|
|
* is handled). Otherwise the memory is not freed, so it must
|
|
|
|
* be freed by the calling function. */
|
2014-03-04 16:21:19 -05:00
|
|
|
bool m_manage_memory;
|
|
|
|
|
2013-07-21 16:26:27 -04:00
|
|
|
/** The priority of this request. The higher the value the more
|
|
|
|
important this request is. */
|
2014-03-04 16:21:19 -05:00
|
|
|
const int m_priority;
|
2013-07-18 17:18:40 -04:00
|
|
|
|
2014-01-08 07:08:46 -05:00
|
|
|
/** The different state of the requst:
|
|
|
|
* - S_PREPARING:\n The request is created and can be configured, it
|
|
|
|
* is not yet started.
|
2014-03-29 06:33:43 -04:00
|
|
|
* - S_BUSY:\n The request is added to the execution queue of the
|
2014-01-08 23:57:58 -05:00
|
|
|
* request_manager (and potentially executing). This implies that
|
|
|
|
* now only the request_manager thread should access the requests's
|
2014-01-08 07:08:46 -05:00
|
|
|
* data structures.
|
|
|
|
* - S_EXECUTED:\n The request was executed, but was not yet marked
|
2014-01-08 23:57:58 -05:00
|
|
|
* as finished in the request_manager. This importantly indicates
|
2014-01-08 07:08:46 -05:00
|
|
|
* that the main thread should not yet access this request,
|
|
|
|
* since the http thread is still executing it.
|
|
|
|
* - S_DONE:\n The request is finished, and it is marked as
|
2014-01-08 23:57:58 -05:00
|
|
|
* finished in the request_manager. This implies that the main
|
2014-01-08 07:08:46 -05:00
|
|
|
* stk thread can access its data safely now.
|
|
|
|
*/
|
2013-08-06 18:45:33 -04:00
|
|
|
enum State
|
|
|
|
{
|
|
|
|
S_PREPARING,
|
|
|
|
S_BUSY,
|
2014-01-08 07:08:46 -05:00
|
|
|
S_EXECUTED,
|
2013-08-06 18:45:33 -04:00
|
|
|
S_DONE
|
|
|
|
};
|
|
|
|
|
2013-07-21 16:26:27 -04:00
|
|
|
protected:
|
|
|
|
|
|
|
|
/** Cancel this request if it is active. */
|
|
|
|
Synchronised<bool> m_cancel;
|
2014-06-04 03:05:35 -04:00
|
|
|
|
|
|
|
/** If this request can be aborted (at the end of STK). Most requests
|
|
|
|
* can, except the (final) logout and client-quit/signout-request,
|
|
|
|
* which must be finished even when STK is quitting. */
|
|
|
|
Synchronised<bool> m_is_abortable;
|
|
|
|
|
2014-01-08 07:08:46 -05:00
|
|
|
/** Set to though if the reply of the request is in and callbacks are
|
|
|
|
* executed */
|
2013-08-06 18:45:33 -04:00
|
|
|
Synchronised<State> m_state;
|
2013-07-19 18:12:36 -04:00
|
|
|
|
2014-01-08 07:08:46 -05:00
|
|
|
// --------------------------------------------------------------------
|
2014-03-29 06:33:43 -04:00
|
|
|
/** The actual operation to be executed. Empty as default, which
|
2014-01-08 07:08:46 -05:00
|
|
|
* allows to create a 'quit' request without any additional code. */
|
2013-07-28 10:11:20 -04:00
|
|
|
virtual void operation() {}
|
2014-08-04 11:41:47 -04:00
|
|
|
|
2014-01-08 07:08:46 -05:00
|
|
|
// --------------------------------------------------------------------
|
|
|
|
/** Virtual function to be called before an operation. */
|
|
|
|
virtual void prepareOperation() {}
|
2014-08-04 11:41:47 -04:00
|
|
|
|
2014-01-08 07:08:46 -05:00
|
|
|
// --------------------------------------------------------------------
|
|
|
|
/** Virtual function to be called after an operation. */
|
|
|
|
virtual void afterOperation() {}
|
2013-07-18 17:18:40 -04:00
|
|
|
|
|
|
|
public:
|
2013-07-21 11:21:48 -04:00
|
|
|
enum RequestType
|
|
|
|
{
|
2013-08-19 12:24:15 -04:00
|
|
|
RT_QUIT = 1
|
2013-07-21 11:21:48 -04:00
|
|
|
};
|
2013-07-18 17:18:40 -04:00
|
|
|
|
2014-08-04 11:41:47 -04:00
|
|
|
Request(bool manage_memory, int priority, int type);
|
2014-01-08 07:08:46 -05:00
|
|
|
virtual ~Request() {}
|
|
|
|
void execute();
|
|
|
|
void executeNow();
|
2014-01-12 06:20:32 -05:00
|
|
|
void queue();
|
2014-08-04 11:41:47 -04:00
|
|
|
|
2014-01-08 07:08:46 -05:00
|
|
|
// --------------------------------------------------------------------
|
|
|
|
/** Executed when a request has finished. */
|
|
|
|
virtual void callback() {}
|
2014-08-04 11:41:47 -04:00
|
|
|
|
2014-01-08 07:08:46 -05:00
|
|
|
// --------------------------------------------------------------------
|
|
|
|
/** Returns the type of the request. */
|
|
|
|
int getType() const { return m_type; }
|
2014-08-04 11:41:47 -04:00
|
|
|
|
2014-01-08 07:08:46 -05:00
|
|
|
// --------------------------------------------------------------------
|
2013-07-21 16:26:27 -04:00
|
|
|
/** Returns if the memory for this object should be managed by
|
|
|
|
* by network_http (i.e. freed once the request is handled). */
|
2014-01-08 07:08:46 -05:00
|
|
|
bool manageMemory() const { return m_manage_memory; }
|
2014-08-04 11:41:47 -04:00
|
|
|
|
2014-01-08 07:08:46 -05:00
|
|
|
// --------------------------------------------------------------------
|
2014-03-04 16:21:19 -05:00
|
|
|
/** Sets the memory management flag of this request. This function
|
|
|
|
* must only be called by the main thread, since it is only tested by
|
|
|
|
* the main thread. */
|
|
|
|
void setManageMemory(bool m) { m_manage_memory = m; }
|
2014-08-04 11:41:47 -04:00
|
|
|
|
2014-03-04 16:21:19 -05:00
|
|
|
// --------------------------------------------------------------------
|
2013-07-18 17:18:40 -04:00
|
|
|
/** Returns the priority of this request. */
|
2014-01-08 07:08:46 -05:00
|
|
|
int getPriority() const { return m_priority; }
|
2014-08-04 11:41:47 -04:00
|
|
|
|
2014-01-08 07:08:46 -05:00
|
|
|
// --------------------------------------------------------------------
|
2013-07-18 17:18:40 -04:00
|
|
|
/** Signals that this request should be canceled. */
|
2014-01-08 07:08:46 -05:00
|
|
|
void cancel() { m_cancel.setAtomic(true); }
|
2014-08-04 11:41:47 -04:00
|
|
|
|
2014-01-08 07:08:46 -05:00
|
|
|
// --------------------------------------------------------------------
|
2013-07-18 17:18:40 -04:00
|
|
|
/** Returns if this request is to be canceled. */
|
2014-01-08 07:08:46 -05:00
|
|
|
bool isCancelled() const { return m_cancel.getAtomic(); }
|
2014-08-04 11:41:47 -04:00
|
|
|
|
2014-01-08 07:08:46 -05:00
|
|
|
// --------------------------------------------------------------------
|
2014-06-04 03:05:35 -04:00
|
|
|
/** Returns if this request can be aborted. */
|
|
|
|
bool isAbortable() const { return m_is_abortable.getAtomic(); }
|
2014-08-04 11:41:47 -04:00
|
|
|
|
2014-06-04 03:05:35 -04:00
|
|
|
// --------------------------------------------------------------------
|
|
|
|
/** Sets if this request is abortable or not. */
|
|
|
|
void setAbortable(bool b) { m_is_abortable.setAtomic(b); }
|
2014-08-04 11:41:47 -04:00
|
|
|
|
2014-06-04 03:05:35 -04:00
|
|
|
// --------------------------------------------------------------------
|
2014-01-08 07:08:46 -05:00
|
|
|
/** Sets the request state to busy. */
|
|
|
|
void setBusy()
|
2014-03-29 06:33:43 -04:00
|
|
|
{
|
2014-08-04 11:41:47 -04:00
|
|
|
assert(m_state.getAtomic() == S_PREPARING);
|
2014-03-29 06:33:43 -04:00
|
|
|
m_state.setAtomic(S_BUSY);
|
2014-01-08 07:08:46 -05:00
|
|
|
} // setBusy
|
2014-08-04 11:41:47 -04:00
|
|
|
|
2014-01-08 07:08:46 -05:00
|
|
|
// --------------------------------------------------------------------
|
|
|
|
/** Sets the request to be completed. */
|
2014-03-29 06:33:43 -04:00
|
|
|
void setExecuted()
|
2014-01-08 07:08:46 -05:00
|
|
|
{
|
2014-08-04 11:41:47 -04:00
|
|
|
assert(m_state.getAtomic() == S_BUSY);
|
2014-03-29 06:33:43 -04:00
|
|
|
m_state.setAtomic(S_EXECUTED);
|
2014-01-08 07:08:46 -05:00
|
|
|
} // setExecuted
|
2014-08-04 11:41:47 -04:00
|
|
|
|
2014-01-08 07:08:46 -05:00
|
|
|
// --------------------------------------------------------------------
|
2013-08-18 18:22:00 -04:00
|
|
|
/** Should only be called by the manager */
|
2014-01-08 07:08:46 -05:00
|
|
|
void setDone()
|
|
|
|
{
|
2014-08-04 11:41:47 -04:00
|
|
|
assert(m_state.getAtomic() == S_EXECUTED);
|
2014-01-08 07:08:46 -05:00
|
|
|
m_state.setAtomic(S_DONE);
|
|
|
|
} // setDone
|
2014-08-04 11:41:47 -04:00
|
|
|
|
2014-01-08 07:08:46 -05:00
|
|
|
// --------------------------------------------------------------------
|
|
|
|
/** Returns if this request is done. */
|
|
|
|
bool isDone() const { return m_state.getAtomic() == S_DONE; }
|
2014-08-04 11:41:47 -04:00
|
|
|
|
2014-01-08 07:08:46 -05:00
|
|
|
// --------------------------------------------------------------------
|
2013-08-06 18:45:33 -04:00
|
|
|
/** Returns if this request is being prepared. */
|
2014-01-08 07:08:46 -05:00
|
|
|
bool isPreparing() const { return m_state.getAtomic() == S_PREPARING; }
|
2014-08-04 11:41:47 -04:00
|
|
|
|
2014-01-08 07:08:46 -05:00
|
|
|
// --------------------------------------------------------------------
|
2013-08-06 18:45:33 -04:00
|
|
|
/** Returns if this request is busy. */
|
2014-01-08 07:08:46 -05:00
|
|
|
bool isBusy() const { return m_state.getAtomic() == S_BUSY; }
|
2014-08-04 11:41:47 -04:00
|
|
|
|
2014-01-08 07:08:46 -05:00
|
|
|
// --------------------------------------------------------------------
|
|
|
|
/** Checks if the request has completed or done (i.e. callbacks were
|
2014-03-29 06:33:43 -04:00
|
|
|
* executed).
|
2014-01-08 07:08:46 -05:00
|
|
|
*/
|
2014-03-29 06:33:43 -04:00
|
|
|
bool hasBeenExecuted() const
|
2014-01-08 07:08:46 -05:00
|
|
|
{
|
|
|
|
State s = m_state.getAtomic();
|
2014-08-04 11:41:47 -04:00
|
|
|
return s == S_EXECUTED || s == S_DONE;
|
2014-01-08 07:08:46 -05:00
|
|
|
} // hasBeenExecuted
|
2014-08-04 11:41:47 -04:00
|
|
|
|
2014-01-08 07:08:46 -05:00
|
|
|
// --------------------------------------------------------------------
|
2014-03-29 06:33:43 -04:00
|
|
|
/** Virtual method to check if a request has initialized all needed
|
2014-01-08 07:08:46 -05:00
|
|
|
* members to a valid value. */
|
2013-08-06 18:45:33 -04:00
|
|
|
virtual bool isAllowedToAdd() const { return isPreparing(); }
|
2013-07-21 11:21:48 -04:00
|
|
|
|
2014-01-08 07:08:46 -05:00
|
|
|
// ====================================================================
|
2014-03-29 06:33:43 -04:00
|
|
|
/** This class is used by the priority queue to sort requests by
|
2014-01-08 07:08:46 -05:00
|
|
|
* priority.
|
2013-07-18 17:18:40 -04:00
|
|
|
*/
|
|
|
|
class Compare
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
/** Compares two requests, returns if the first request has a lower
|
|
|
|
* priority than the second one. */
|
|
|
|
bool operator() (const Request *a, const Request *b) const
|
2013-07-21 16:26:27 -04:00
|
|
|
{
|
|
|
|
return a->getPriority() < b->getPriority();
|
|
|
|
}
|
2014-01-08 23:57:58 -05:00
|
|
|
}; // class Compare
|
|
|
|
}; // class Request
|
2013-07-19 17:20:32 -04:00
|
|
|
} //namespace Online
|
2014-08-04 11:41:47 -04:00
|
|
|
#endif // HEADER_ONLINE_REQUEST_HPP
|