/**************************************************************************** Copyright (c) 2012 greathqy Copyright (c) 2012 cocos2d-x.org Copyright (c) 2013-2014 Chukong Technologies Inc. http://www.cocos2d-x.org Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ****************************************************************************/ #include "network/HttpRequest.h" #include "network/HttpClient.h" #include #include #include #include #include #include #if defined(_XBOX_ONE) #include #else #include #endif using namespace Microsoft::WRL; using namespace Microsoft::WRL::Details; #include "base/CCVector.h" #include "base/CCDirector.h" #include "base/CCScheduler.h" #include "platform/CCFileUtils.h" NS_CC_BEGIN namespace network { const int READ_BUFFER_MAX = 16 * 1024; const int REQUEST_BUFFER_MAX = 4 * 1024 * 1024; const char ERR_MSG_500[] = "Internal server error"; const char ERR_MSG_400[] = "Invalid request"; const char ERR_MSG_401[] = "Authentication is required to access this resource"; const char ERR_MSG_403[] = "Forbidden"; const char ERR_MSG_404[] = "Specified resource could not be found"; const char ERR_MSG_407[] = "Proxy authentication failed"; const char ERR_MSG_408[] = "Request timed out"; const char ERR_MSG_412[] = "Request aborted"; const char ERR_MSG_DL_FLD[] = "The download of the specified resource has failed"; class CXHR2Callback : public Microsoft::WRL::RuntimeClass, IXMLHTTPRequest2Callback> { public: CXHR2Callback(); ~CXHR2Callback(); HRESULT RuntimeClassInitialize(); HRESULT ReadStreamData(ISequentialStream* pResponseStream); STDMETHODIMP OnRedirect(IXMLHTTPRequest2 *pXHR, const WCHAR *pwszRedirectUrl); STDMETHODIMP OnHeadersAvailable(IXMLHTTPRequest2 *pXHR, DWORD dwStatus, const WCHAR *pwszStatus); STDMETHODIMP OnDataAvailable(IXMLHTTPRequest2 *pXHR, ISequentialStream *pResponseStream); STDMETHODIMP OnResponseReceived(IXMLHTTPRequest2 *pXHR, ISequentialStream *pResponseStream); STDMETHODIMP OnError(IXMLHTTPRequest2 *pXHR, HRESULT hrError); STDMETHODIMP WaitForComplete(PDWORD pdwStatus); protected: void CompleteRequest(HRESULT hrError); private: HANDLE _hWfC; DWORD _statusCode; std::string _errorMsg; std::vector _headers; std::vector _data; friend class HttpConnection; }; class CXHR2DataStream : public Microsoft::WRL::RuntimeClass, ISequentialStream, IDispatch> { public: CXHR2DataStream(); ~CXHR2DataStream(); STDMETHODIMP_(ULONG) Length(); STDMETHODIMP Init(const void *psBuffer, ULONG cbBufferSize); STDMETHODIMP Read(void *pv, ULONG cb, ULONG *pcbRead); STDMETHODIMP Write(const void *pv, ULONG cb, ULONG *pcbWritten); STDMETHODIMP_(ULONG) AddRef(); STDMETHODIMP_(ULONG) Release(); STDMETHODIMP QueryInterface(REFIID riid, void **ppvObject); STDMETHODIMP GetTypeInfoCount(unsigned int FAR* pctinfo); STDMETHODIMP GetTypeInfo(unsigned int iTInfo, LCID lcid, ITypeInfo FAR* FAR* ppTInfo); STDMETHODIMP GetIDsOfNames(REFIID riid, OLECHAR FAR* FAR* rgszNames, unsigned int cNames, LCID lcid, DISPID FAR* rgDispId); STDMETHODIMP Invoke(DISPID dispIdMember, REFIID riid, LCID lcid, WORD wFlags, DISPPARAMS FAR* pDispParams, VARIANT FAR* pVarResult, EXCEPINFO FAR* pExcepInfo, unsigned int FAR* puArgErr); private: ULONG _refCnt; BYTE* _pData; ULONG _dataSize; ULONG _seekIndex; }; class HttpConnection { public: HttpConnection(); ~HttpConnection(); bool init(HttpRequest *pRequest, DWORD timeOutInMs = 0); bool open(std::string verb); bool open(std::string verb, bool userAuthentication); bool open(std::string verb, std::string cookieFile); bool open(std::string verb, bool userAuthentication, std::string cookieFile); bool send(); DWORD getStatusCode(); std::string getErrorMessage(); std::vector* getResponseHeader(); std::vector* getResponseData(); protected: void cancelRequest(HRESULT hrError); HRESULT authenticateUser(std::string& verb, std::string& url, std::string& headers); HRESULT processCookieFile(std::string& url, std::string& cookieFile); private: bool _isInitialized; ComPtr _spXhr; ComPtr _spXhrCallback; ComPtr _spXhrRequestData; DWORD _timeOutInMs; cocos2d::network::HttpRequest* _pRequest; }; } NS_CC_END