/* 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 { static const uint32 FRAMES_PER_SECOND = 20; static const uint32 TIMER_INTERVAL = 1000000 / FRAMES_PER_SECOND; static const uint32 CLOUD_PERIOD = 20; //every 20th frame static const uint32 CURL_PERIOD = 1; //every frame friend void connectionsThread(void *); //calls handle() typedef Common::BaseCallback *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 _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