HttpConnection-winrt.cpp 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747
  1. /****************************************************************************
  2. Copyright (c) 2012 greathqy
  3. Copyright (c) 2012 cocos2d-x.org
  4. Copyright (c) 2013-2016 Chukong Technologies Inc.
  5. Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd.
  6. http://www.cocos2d-x.org
  7. Permission is hereby granted, free of charge, to any person obtaining a copy
  8. of this software and associated documentation files (the "Software"), to deal
  9. in the Software without restriction, including without limitation the rights
  10. to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  11. copies of the Software, and to permit persons to whom the Software is
  12. furnished to do so, subject to the following conditions:
  13. The above copyright notice and this permission notice shall be included in
  14. all copies or substantial portions of the Software.
  15. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  16. IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  17. FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  18. AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  19. LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  20. OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  21. THE SOFTWARE.
  22. ****************************************************************************/
  23. #include "platform/CCPlatformConfig.h"
  24. #if (CC_TARGET_PLATFORM == CC_PLATFORM_WINRT)
  25. #include "network/HttpCookie.h"
  26. #include "network/HttpConnection-winrt.h"
  27. NS_CC_BEGIN
  28. namespace network {
  29. // Format and add default headers (Platform specific approach)
  30. static void formatHeaders(std::vector<std::string>& headers)
  31. {
  32. #if defined(_XBOX_ONE)
  33. for(auto& header : headers)
  34. {
  35. header += "\r\n";
  36. }
  37. // append default headers
  38. headers.emplace_back("User-Agent: XB1_IXHR2_HTTP\r\n");
  39. headers.emplace_back("x-xbl-device-type: XboxOne\r\n");
  40. headers.emplace_back("x-xbl-client-type: Console\r\n");
  41. headers.emplace_back("x-xbl-client-version: 1.0\r\n");
  42. headers.emplace_back("x-xbl-contract-version: 1\r\n");
  43. #endif
  44. }
  45. // Get user authentication token (Platform specific approach)
  46. static bool getAuthenticationToken(const std::string& verb, const std::string& url, const std::string& headersXST, const std::string& bodyXST, std::string& token, std::string& signature)
  47. {
  48. #if defined(_XBOX_ONE)
  49. using namespace Windows::Xbox::System;
  50. token = "";
  51. signature = "";
  52. User^ loggedInUser = nullptr;
  53. int ind = 0;
  54. while(ind < User::Users->Size)
  55. {
  56. loggedInUser = User::Users->GetAt(ind++);
  57. if(loggedInUser->IsSignedIn)
  58. break;
  59. loggedInUser = nullptr;
  60. }
  61. if(nullptr == loggedInUser)
  62. return false;
  63. Platform::Array<unsigned char>^ body;
  64. if(!bodyXST.empty()) {
  65. body = ref new Platform::Array<unsigned char>((unsigned char*)bodyXST.c_str(), bodyXST.size());
  66. }
  67. else {
  68. body = ref new Platform::Array<unsigned char>(1);
  69. body[0] = 0;
  70. }
  71. // this method will crash if TitleId & PrimaryServiceConfigId not specified in Package.appxmanifest.
  72. auto asynOp = loggedInUser->GetTokenAndSignatureAsync(
  73. ref new Platform::String(std::wstring(verb.begin(), verb.end()).c_str()),
  74. ref new Platform::String(std::wstring(url.begin(), url.end()).c_str()),
  75. ref new Platform::String(std::wstring(headersXST.begin(), headersXST.end()).c_str()), body);
  76. bool bRet = false;
  77. HRESULT hr = S_OK;
  78. asynOp->Completed = ref new Windows::Foundation::AsyncOperationCompletedHandler<GetTokenAndSignatureResult^>(
  79. [&token, &signature, &bRet, &hr](Windows::Foundation::IAsyncOperation<GetTokenAndSignatureResult^>^ operation, Windows::Foundation::AsyncStatus status)
  80. {
  81. if(status == Windows::Foundation::AsyncStatus::Completed) {
  82. try
  83. {
  84. auto result = operation->GetResults();
  85. std::wstring tok = result->Token->Data();
  86. std::wstring sig = result->Signature->Data();
  87. token = std::string(tok.begin(), tok.end());
  88. signature = std::string(sig.begin(), sig.end());
  89. bRet = true;
  90. }
  91. catch(Platform::Exception^ e)
  92. {
  93. bRet = false;
  94. }
  95. }
  96. else {
  97. hr = operation->ErrorCode.Value;
  98. if(hr == 0x87dd0021) //AM_E_NO_TOKEN_REQUIRED
  99. bRet = true;
  100. }
  101. });
  102. while(asynOp->Status == Windows::Foundation::AsyncStatus::Started)
  103. {
  104. ::Sleep(1);
  105. }
  106. return bRet;
  107. #else
  108. return false;
  109. #endif
  110. }
  111. // CXMLHTTPRequest2Callback
  112. CXHR2Callback::CXHR2Callback() :
  113. _statusCode(0),
  114. _hWfC(nullptr),
  115. _errorMsg("")
  116. {
  117. }
  118. CXHR2Callback::~CXHR2Callback()
  119. {
  120. if (nullptr != _hWfC)
  121. {
  122. CloseHandle(_hWfC);
  123. _hWfC = nullptr;
  124. }
  125. }
  126. HRESULT CXHR2Callback::RuntimeClassInitialize()
  127. {
  128. _hWfC = CreateEventEx(nullptr, nullptr, CREATE_EVENT_MANUAL_RESET, EVENT_ALL_ACCESS);
  129. return HRESULT_FROM_WIN32(GetLastError());
  130. }
  131. HRESULT CXHR2Callback::OnRedirect(IXMLHTTPRequest2 *pXHR, const WCHAR *pwszRedirectUrl)
  132. {
  133. UNREFERENCED_PARAMETER(pXHR);
  134. UNREFERENCED_PARAMETER(pwszRedirectUrl);
  135. return S_OK;
  136. }
  137. HRESULT CXHR2Callback::OnHeadersAvailable(IXMLHTTPRequest2 *pXHR, DWORD dwStatus, const WCHAR *pwszStatus)
  138. {
  139. _statusCode = dwStatus;
  140. if(nullptr == pXHR) {
  141. return E_INVALIDARG;
  142. }
  143. WCHAR *headers = nullptr;
  144. HRESULT hr = pXHR->GetAllResponseHeaders(&headers);
  145. if(SUCCEEDED(hr)) {
  146. std::wstring hdr = headers;
  147. _headers.insert(_headers.end(), hdr.begin(), hdr.end());
  148. }
  149. if(headers != nullptr) {
  150. CoTaskMemFree(headers);
  151. headers = nullptr;
  152. }
  153. return hr;
  154. }
  155. HRESULT CXHR2Callback::OnDataAvailable(IXMLHTTPRequest2 *pXHR, ISequentialStream *pResponseStream)
  156. {
  157. UNREFERENCED_PARAMETER(pXHR);
  158. return ReadStreamData(pResponseStream);
  159. }
  160. HRESULT CXHR2Callback::OnResponseReceived(IXMLHTTPRequest2 *pXHR, ISequentialStream *pResponseStream)
  161. {
  162. UNREFERENCED_PARAMETER(pXHR);
  163. HRESULT hr = ReadStreamData(pResponseStream);
  164. CompleteRequest(hr);
  165. return hr;
  166. }
  167. HRESULT CXHR2Callback::OnError(IXMLHTTPRequest2 *pXHR, HRESULT hrError)
  168. {
  169. CompleteRequest(hrError);
  170. return hrError;
  171. }
  172. HRESULT CXHR2Callback::WaitForComplete(PDWORD pdwStatus)
  173. {
  174. HRESULT hr = E_FAIL;
  175. if (NULL != _hWfC)
  176. {
  177. hr = S_OK;
  178. DWORD error;
  179. error = WaitForSingleObjectEx(_hWfC, INFINITE, FALSE);
  180. if (error == WAIT_FAILED) {
  181. hr = HRESULT_FROM_WIN32(GetLastError());
  182. }
  183. if (error != WAIT_OBJECT_0) {
  184. hr = E_ABORT;
  185. }
  186. }
  187. if (SUCCEEDED(hr)) {
  188. *pdwStatus = _statusCode;
  189. }
  190. return hr;
  191. }
  192. HRESULT CXHR2Callback::ReadStreamData(ISequentialStream* pResponseStream)
  193. {
  194. if(pResponseStream == NULL) {
  195. return E_INVALIDARG;
  196. }
  197. CCHAR buff[READ_BUFFER_MAX];
  198. DWORD totalBytes = 0;
  199. DWORD bytesRead = 0;
  200. HRESULT hr = S_OK;
  201. do
  202. {
  203. hr = pResponseStream->Read(buff, READ_BUFFER_MAX, &bytesRead);
  204. if(FAILED(hr)) {
  205. break;
  206. }
  207. _data.insert(_data.end(), &buff[0], buff + bytesRead);
  208. totalBytes += bytesRead;
  209. }
  210. while(hr == S_OK);
  211. if(SUCCEEDED(hr)) {
  212. hr = S_OK;
  213. }
  214. return hr;
  215. }
  216. void CXHR2Callback::CompleteRequest(HRESULT hrError)
  217. {
  218. if (NULL != _hWfC) {
  219. SetEvent(_hWfC);
  220. }
  221. switch (hrError)
  222. {
  223. case S_OK:
  224. case S_FALSE:
  225. _statusCode = 200;
  226. break;
  227. case INET_E_AUTHENTICATION_REQUIRED:
  228. _statusCode = 401;
  229. _errorMsg = ERR_MSG_401;
  230. break;
  231. case INET_E_DOWNLOAD_FAILURE:
  232. _statusCode = 500;
  233. _errorMsg = ERR_MSG_DL_FLD;
  234. break;
  235. case INET_E_FORBIDFRAMING:
  236. _statusCode = 403;
  237. _errorMsg = ERR_MSG_403;
  238. break;
  239. case INET_E_RESOURCE_NOT_FOUND:
  240. _statusCode = 404;
  241. _errorMsg = ERR_MSG_404;
  242. break;
  243. case RPC_S_PROXY_ACCESS_DENIED:
  244. _statusCode = 407;
  245. _errorMsg = ERR_MSG_407;
  246. break;
  247. case ERROR_RESOURCE_CALL_TIMED_OUT:
  248. _statusCode = 408;
  249. _errorMsg = ERR_MSG_408;
  250. break;
  251. case INET_E_INVALID_REQUEST:
  252. _statusCode = 400;
  253. _errorMsg = ERR_MSG_400;
  254. break;
  255. case E_ABORT:
  256. _statusCode = 412;
  257. _errorMsg = ERR_MSG_412;
  258. break;
  259. default:
  260. _statusCode = 500;
  261. _errorMsg = ERR_MSG_500;
  262. break;
  263. }
  264. }
  265. //CXHR2DataStream
  266. CXHR2DataStream::CXHR2DataStream() :
  267. _pData(nullptr),
  268. _dataSize(0),
  269. _seekIndex(0),
  270. _refCnt(1)
  271. {
  272. }
  273. CXHR2DataStream::~CXHR2DataStream()
  274. {
  275. if(nullptr != _pData)
  276. delete[] _pData;
  277. }
  278. ULONG CXHR2DataStream::Length()
  279. {
  280. return _dataSize;
  281. }
  282. HRESULT CXHR2DataStream::Init(const void *psBuffer, ULONG cbBufferSize)
  283. {
  284. HRESULT hr = S_OK;
  285. if(psBuffer == nullptr || cbBufferSize > REQUEST_BUFFER_MAX) {
  286. hr = E_INVALIDARG;
  287. }
  288. if(SUCCEEDED(hr)) {
  289. _dataSize = cbBufferSize;
  290. _seekIndex = 0;
  291. _pData = new (std::nothrow) BYTE[_dataSize];
  292. if(_pData == nullptr)
  293. hr = E_OUTOFMEMORY;
  294. }
  295. if(SUCCEEDED(hr)) {
  296. memcpy_s(_pData, _dataSize, psBuffer, cbBufferSize);
  297. }
  298. return hr;
  299. }
  300. HRESULT CXHR2DataStream::Read(void *pv, ULONG cb, ULONG *pcbRead)
  301. {
  302. HRESULT hr = S_OK;
  303. if(pv == nullptr) {
  304. hr = E_INVALIDARG;
  305. }
  306. if(SUCCEEDED(hr)) {
  307. BYTE* pOutput = (BYTE*)pv;
  308. BYTE* _pInput = _pData;
  309. for(*pcbRead = 0; *pcbRead < cb; (*pcbRead)++)
  310. {
  311. if(_seekIndex == _dataSize) {
  312. hr = S_FALSE;
  313. break;
  314. }
  315. pOutput[*pcbRead] = _pInput[*pcbRead];
  316. _seekIndex++;
  317. }
  318. }
  319. return hr;
  320. }
  321. HRESULT CXHR2DataStream::Write(const void *pv, ULONG cb, ULONG *pcbWritten)
  322. {
  323. HRESULT hr = E_NOTIMPL;
  324. UNREFERENCED_PARAMETER(pv);
  325. UNREFERENCED_PARAMETER(cb);
  326. UNREFERENCED_PARAMETER(pcbWritten);
  327. return hr;
  328. }
  329. ULONG CXHR2DataStream::AddRef()
  330. {
  331. return ::InterlockedIncrement(&_refCnt);
  332. }
  333. ULONG CXHR2DataStream::Release()
  334. {
  335. ULONG refCnt = ::InterlockedDecrement(&_refCnt);
  336. if(0 == refCnt) {
  337. delete this;
  338. }
  339. return refCnt;
  340. }
  341. HRESULT CXHR2DataStream::QueryInterface(REFIID riid, void **ppvObject)
  342. {
  343. HRESULT hr = S_OK;
  344. if(ppvObject == nullptr) {
  345. hr = E_INVALIDARG;
  346. }
  347. void *pObject = nullptr;
  348. if(SUCCEEDED(hr)) {
  349. if(riid == IID_IUnknown) {
  350. pObject = static_cast<IUnknown*>((IDispatch*)this);
  351. }
  352. else if(riid == IID_IDispatch) {
  353. pObject = static_cast<IDispatch*>(this);
  354. }
  355. else if(riid == IID_ISequentialStream) {
  356. pObject = static_cast<ISequentialStream*>(this);
  357. }
  358. else {
  359. hr = E_NOINTERFACE;
  360. }
  361. }
  362. if(SUCCEEDED(hr)) {
  363. AddRef();
  364. *ppvObject = pObject;
  365. pObject = nullptr;
  366. }
  367. return hr;
  368. }
  369. HRESULT CXHR2DataStream::GetTypeInfoCount(unsigned int FAR* pctinfo)
  370. {
  371. HRESULT hr = E_NOTIMPL;
  372. if(pctinfo)
  373. *pctinfo = 0;
  374. return hr;
  375. }
  376. HRESULT CXHR2DataStream::GetTypeInfo(unsigned int iTInfo, LCID lcid, ITypeInfo FAR* FAR* ppTInfo)
  377. {
  378. HRESULT hr = E_NOTIMPL;
  379. if(ppTInfo)
  380. *ppTInfo = 0;
  381. UNREFERENCED_PARAMETER(iTInfo);
  382. UNREFERENCED_PARAMETER(lcid);
  383. return hr;
  384. }
  385. HRESULT CXHR2DataStream::GetIDsOfNames(REFIID riid, OLECHAR FAR* FAR* rgszNames, unsigned int cNames, LCID lcid, DISPID FAR* rgDispId)
  386. {
  387. HRESULT hr = DISP_E_UNKNOWNNAME;
  388. UNREFERENCED_PARAMETER(riid);
  389. UNREFERENCED_PARAMETER(rgszNames);
  390. UNREFERENCED_PARAMETER(cNames);
  391. UNREFERENCED_PARAMETER(lcid);
  392. UNREFERENCED_PARAMETER(rgDispId);
  393. return hr;
  394. }
  395. HRESULT CXHR2DataStream::Invoke(DISPID dispIdMember, REFIID riid, LCID lcid, WORD wFlags, DISPPARAMS FAR* pDispParams, VARIANT FAR* pVarResult, EXCEPINFO FAR* pExcepInfo, unsigned int FAR* puArgErr)
  396. {
  397. HRESULT hr = S_OK;
  398. UNREFERENCED_PARAMETER(dispIdMember);
  399. UNREFERENCED_PARAMETER(riid);
  400. UNREFERENCED_PARAMETER(lcid);
  401. UNREFERENCED_PARAMETER(wFlags);
  402. UNREFERENCED_PARAMETER(pDispParams);
  403. UNREFERENCED_PARAMETER(pVarResult);
  404. UNREFERENCED_PARAMETER(pExcepInfo);
  405. UNREFERENCED_PARAMETER(puArgErr);
  406. return hr;
  407. }
  408. // HttpConnection
  409. HttpConnection::HttpConnection() :
  410. _isInitialized(false),
  411. _spXhr(nullptr),
  412. _spXhrCallback(nullptr),
  413. _spXhrRequestData(nullptr),
  414. _pRequest(nullptr),
  415. _timeOutInMs(0)
  416. {
  417. }
  418. HttpConnection::~HttpConnection()
  419. {
  420. }
  421. bool HttpConnection::init(HttpRequest *pRequest, DWORD timeOutInMs)
  422. {
  423. if (_isInitialized || nullptr == pRequest) {
  424. return _isInitialized;
  425. }
  426. HRESULT hr = CoInitializeEx(NULL, NULL);
  427. if (SUCCEEDED(hr)) {
  428. hr = CoCreateInstance(CLSID_FreeThreadedXMLHTTP60, NULL, CLSCTX_SERVER, IID_PPV_ARGS(&_spXhr));
  429. }
  430. if (SUCCEEDED(hr)) {
  431. hr = MakeAndInitialize<CXHR2Callback>(&_spXhrCallback);
  432. }
  433. if(SUCCEEDED(hr)) {
  434. _pRequest = pRequest;
  435. _timeOutInMs = timeOutInMs;
  436. LONG size = _pRequest->getRequestDataSize();
  437. if(size > 0) {
  438. _spXhrRequestData = Make<CXHR2DataStream>();
  439. hr = _spXhrRequestData->Init(_pRequest->getRequestData(), size);
  440. }
  441. }
  442. return _isInitialized = SUCCEEDED(hr);
  443. }
  444. bool HttpConnection::open(const std::string& verb)
  445. {
  446. return open(verb, false, "");
  447. }
  448. bool HttpConnection::open(const std::string& verb, bool userAuthentication)
  449. {
  450. return open(verb, userAuthentication, "");
  451. }
  452. bool HttpConnection::open(const std::string& verb, const std::string& cookieFile)
  453. {
  454. return open(verb, false, cookieFile);
  455. }
  456. bool HttpConnection::open(const std::string& verb, bool userAuthentication, const std::string& cookieFile)
  457. {
  458. if (!_isInitialized) {
  459. return false;
  460. }
  461. std::wstring method(verb.begin(), verb.end());
  462. std::string url(_pRequest->getUrl());
  463. std::wstring wUrl(url.begin(), url.end());
  464. HRESULT hr = _spXhr->Open(method.c_str(), wUrl.c_str(), _spXhrCallback.Get(), NULL, NULL, NULL, NULL);
  465. if(SUCCEEDED(hr) && _timeOutInMs != 0) {
  466. hr = _spXhr->SetProperty(XHR_PROP_TIMEOUT, _timeOutInMs);
  467. }
  468. #if 0
  469. if(SUCCEEDED(hr)) {
  470. hr = _spXhr->SetProperty(XHR_PROP_ONDATA_THRESHOLD, READ_BUFFER_MAX);
  471. }
  472. #endif
  473. auto headers = _pRequest->getHeaders();
  474. formatHeaders(headers);
  475. for(auto header : headers)
  476. {
  477. std::string key = header.substr(0, header.find_first_of(':'));
  478. std::string value = header.substr(header.find_first_of(':') + 1, header.size() - 1);
  479. if(SUCCEEDED(hr)) {
  480. hr = _spXhr->SetRequestHeader(std::wstring(key.begin(), key.end()).c_str(), std::wstring(value.begin(), value.end()).c_str());
  481. }
  482. }
  483. if(SUCCEEDED(hr) && userAuthentication) {
  484. std::string authHeaders = std::accumulate(headers.begin(), headers.end(), std::string(""));
  485. hr = authenticateUser(verb, url, authHeaders);
  486. }
  487. if(SUCCEEDED(hr) && !cookieFile.empty()) {
  488. hr = processCookieFile(url, cookieFile);
  489. }
  490. if(FAILED(hr)) {
  491. cancelRequest(hr);
  492. }
  493. return SUCCEEDED(hr);
  494. }
  495. HRESULT HttpConnection::authenticateUser(const std::string& verb, const std::string& url, const std::string& headers)
  496. {
  497. HRESULT hr = S_OK;
  498. std::string authToken;
  499. std::string authSig;
  500. std::string authBody;
  501. if(_pRequest->getRequestDataSize() > 0)
  502. authBody = _pRequest->getRequestData();
  503. if(getAuthenticationToken(verb, url, headers, authBody, authToken, authSig)) {
  504. hr = _spXhr->SetRequestHeader(L"Authorization", std::wstring(authToken.begin(), authToken.end()).c_str());
  505. if(SUCCEEDED(hr)) {
  506. hr = _spXhr->SetRequestHeader(L"Signature", std::wstring(authSig.begin(), authSig.end()).c_str());
  507. }
  508. }
  509. else
  510. {
  511. hr = INET_E_AUTHENTICATION_REQUIRED;
  512. }
  513. return hr;
  514. }
  515. HRESULT HttpConnection::processCookieFile(const std::string& url, const std::string& cookieFile)
  516. {
  517. HRESULT hr = S_OK;
  518. HttpCookie cookie;
  519. cookie.setCookieFileName(cookieFile);
  520. auto cookies = cookie.getCookies();
  521. std::string cookieInfo = "";
  522. int cCnt = 0;
  523. for(auto& cookie : *cookies)
  524. {
  525. if(url.find(cookie.domain) != std::string::npos)
  526. {
  527. std::string keyVal = cookie.name;
  528. keyVal.append("=");
  529. keyVal.append(cookie.value);
  530. if(cCnt != 0) {
  531. cookieInfo.append(";");
  532. }
  533. cookieInfo.append(keyVal);
  534. cCnt++;
  535. }
  536. }
  537. if(!cookieInfo.empty() && nullptr != _spXhr) {
  538. hr = _spXhr->SetRequestHeader(L"Cookie", std::wstring(cookieInfo.begin(), cookieInfo.end()).c_str());
  539. }
  540. return hr;
  541. }
  542. bool HttpConnection::send()
  543. {
  544. if (!_isInitialized) {
  545. return false;
  546. }
  547. HRESULT hr = E_FAIL;
  548. if(nullptr == _spXhrRequestData) {
  549. hr = _spXhr->Send(NULL, 0);
  550. }
  551. else {
  552. hr = _spXhr->Send(_spXhrRequestData.Get(), _spXhrRequestData->Length());
  553. }
  554. if(SUCCEEDED(hr)) {
  555. DWORD status = 0;
  556. hr = _spXhrCallback->WaitForComplete(&status);
  557. }
  558. else {
  559. cancelRequest(hr);
  560. }
  561. return SUCCEEDED(hr);
  562. }
  563. DWORD HttpConnection::getStatusCode()
  564. {
  565. return _spXhrCallback != nullptr ? _spXhrCallback->_statusCode : 500;
  566. }
  567. std::string HttpConnection::getErrorMessage()
  568. {
  569. return _spXhrCallback != nullptr ? _spXhrCallback->_errorMsg : ERR_MSG_500;
  570. }
  571. std::vector<char>* HttpConnection::getResponseHeader()
  572. {
  573. return _spXhrCallback != nullptr ? &_spXhrCallback->_headers : nullptr;
  574. }
  575. std::vector<char>* HttpConnection::getResponseData()
  576. {
  577. return _spXhrCallback != nullptr ? &_spXhrCallback->_data : nullptr;
  578. }
  579. void HttpConnection::cancelRequest(HRESULT hrError)
  580. {
  581. if(nullptr != _spXhr) {
  582. _spXhr->Abort();
  583. _spXhrCallback->CompleteRequest(hrError);
  584. }
  585. }
  586. }
  587. NS_CC_END
  588. #endif // #if (CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID)