开源的socket服务端客户端,支持C# C++

HttpClient.cpp 10KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357
  1. /*
  2. * Copyright: JessMA Open Source (ldcsaa@gmail.com)
  3. *
  4. * Version : 4.1.3
  5. * Author : Bruce Liang
  6. * Website : http://www.jessma.org
  7. * Project : https://github.com/ldcsaa
  8. * Blog : http://www.cnblogs.com/ldcsaa
  9. * Wiki : http://www.oschina.net/p/hp-socket
  10. * QQ Group : 75375912
  11. *
  12. * Licensed under the Apache License, Version 2.0 (the "License");
  13. * you may not use this file except in compliance with the License.
  14. * You may obtain a copy of the License at
  15. *
  16. * http://www.apache.org/licenses/LICENSE-2.0
  17. *
  18. * Unless required by applicable law or agreed to in writing, software
  19. * distributed under the License is distributed on an "AS IS" BASIS,
  20. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  21. * See the License for the specific language governing permissions and
  22. * limitations under the License.
  23. */
  24. #include "stdafx.h"
  25. #include "HttpClient.h"
  26. template<class R, class T, USHORT default_port> BOOL CHttpClientT<R, T, default_port>::CheckParams()
  27. {
  28. if(m_enLocalVersion != HV_1_1 && m_enLocalVersion != HV_1_0)
  29. {
  30. SetLastError(SE_INVALID_PARAM, __FUNCTION__, ERROR_INVALID_PARAMETER);
  31. return FALSE;
  32. }
  33. return __super::CheckParams();
  34. }
  35. template<class R, class T, USHORT default_port> BOOL CHttpClientT<R, T, default_port>::SendRequest(LPCSTR lpszMethod, LPCSTR lpszPath, const THeader lpHeaders[], int iHeaderCount, const BYTE* pBody, int iLength)
  36. {
  37. USES_CONVERSION;
  38. WSABUF szBuffer[2];
  39. CStringA strHeader;
  40. LPCSTR lpszHost = nullptr;
  41. USHORT usPort = 0;
  42. GetRemoteHost(&lpszHost, &usPort);
  43. if(usPort == default_port) usPort = 0;
  44. ::MakeRequestLine(lpszMethod, lpszPath, m_enLocalVersion, strHeader);
  45. ::MakeHeaderLines(lpHeaders, iHeaderCount, &m_objHttp.GetCookieMap(), iLength, TRUE, lpszHost, usPort, strHeader);
  46. ::MakeHttpPacket(strHeader, pBody, iLength, szBuffer);
  47. return SendPackets(szBuffer, 2);
  48. }
  49. template<class R, class T, USHORT default_port> BOOL CHttpClientT<R, T, default_port>::SendLocalFile(LPCSTR lpszFileName, LPCSTR lpszMethod, LPCSTR lpszPath, const THeader lpHeaders[] = nullptr, int iHeaderCount = 0)
  50. {
  51. if(
  52. strcmp(lpszMethod, HTTP_METHOD_POST) != 0 &&
  53. strcmp(lpszMethod, HTTP_METHOD_PUT) != 0 &&
  54. strcmp(lpszMethod, HTTP_METHOD_PATCH) != 0 )
  55. {
  56. ::SetLastError(ERROR_INVALID_PARAMETER);
  57. return FALSE;
  58. }
  59. CAtlFile file;
  60. CAtlFileMapping<> fmap;
  61. HRESULT hr = ::ReadSmallFile(CA2T(lpszFileName), file, fmap);
  62. if(FAILED(hr))
  63. {
  64. ::SetLastError(HRESULT_CODE(hr));
  65. return FALSE;
  66. }
  67. return SendRequest(lpszMethod, lpszPath, lpHeaders, iHeaderCount, (BYTE*)(char*)fmap, (int)fmap.GetMappingSize());
  68. }
  69. template<class R, class T, USHORT default_port> BOOL CHttpClientT<R, T, default_port>::SendWSMessage(BOOL bFinal, BYTE iReserved, BYTE iOperationCode, const BYTE lpszMask[4], BYTE* pData, int iLength, ULONGLONG ullBodyLen)
  70. {
  71. WSABUF szBuffer[2];
  72. BYTE szHeader[HTTP_MAX_WS_HEADER_LEN];
  73. if(!::MakeWSPacket(bFinal, iReserved, iOperationCode, lpszMask, pData, iLength, ullBodyLen, szHeader, szBuffer))
  74. return FALSE;
  75. return SendPackets(szBuffer, 2);
  76. }
  77. // ------------------------------------------------------------------------------------------------------------- //
  78. template<class T, USHORT default_port> BOOL CHttpSyncClientT<T, default_port>::Start(LPCTSTR lpszRemoteAddress, USHORT usPort, BOOL bAsyncConnect, LPCTSTR lpszBindAddress)
  79. {
  80. CleanupRequestResult();
  81. if(!__super::Start(lpszRemoteAddress, usPort, TRUE, lpszBindAddress))
  82. return FALSE;
  83. DWORD dwWait = m_dwConnectTimeout != 0 ? m_dwConnectTimeout : INFINITE;
  84. BOOL isOK = ::WaitForSingleObject(m_evWait, dwWait) == WAIT_OBJECT_0;
  85. if(!isOK || m_enProgress != HSRP_DONE)
  86. {
  87. int ec = m_enProgress == HSRP_WAITING ? WSAETIMEDOUT : WSAECONNREFUSED;
  88. if(!isOK) Stop();
  89. SetLastError(SE_CONNECT_SERVER, __FUNCTION__, ec);
  90. return FALSE;
  91. }
  92. return TRUE;
  93. }
  94. template<class T, USHORT default_port> BOOL CHttpSyncClientT<T, default_port>::SendRequest(LPCSTR lpszMethod, LPCSTR lpszPath, const THeader lpHeaders[], int iHeaderCount, const BYTE* pBody, int iLength)
  95. {
  96. CleanupRequestResult();
  97. if(!__super::SendRequest(lpszMethod, lpszPath, lpHeaders, iHeaderCount, pBody, iLength))
  98. return FALSE;
  99. DWORD dwWait = m_dwRequestTimeout != 0 ? m_dwRequestTimeout : INFINITE;
  100. BOOL isOK = ::WaitForSingleObject(m_evWait, dwWait) == WAIT_OBJECT_0;
  101. if(!isOK || m_enProgress != HSRP_DONE)
  102. {
  103. int ec = m_enProgress == HSRP_WAITING ? WSAETIMEDOUT :
  104. (m_enProgress == HSRP_CLOSE ? WSAECONNABORTED : ERROR_INVALID_DATA);
  105. if(!isOK) Stop();
  106. SetLastError(SE_DATA_SEND, __FUNCTION__, ec);
  107. return FALSE;
  108. }
  109. return TRUE;
  110. }
  111. template<class T, USHORT default_port> BOOL CHttpSyncClientT<T, default_port>::SendWSMessage(BOOL bFinal, BYTE iReserved, BYTE iOperationCode, const BYTE lpszMask[4], BYTE* pData, int iLength, ULONGLONG ullBodyLen)
  112. {
  113. CleanupRequestResult();
  114. if(!__super::SendWSMessage(bFinal, iReserved, iOperationCode, lpszMask, pData, iLength, ullBodyLen))
  115. return FALSE;
  116. DWORD dwWait = m_dwRequestTimeout != 0 ? m_dwRequestTimeout : INFINITE;
  117. BOOL isOK = ::WaitForSingleObject(m_evWait, dwWait) == WAIT_OBJECT_0;
  118. if(!isOK || m_enProgress != HSRP_DONE)
  119. {
  120. int ec = m_enProgress == HSRP_WAITING ? WSAETIMEDOUT :
  121. (m_enProgress == HSRP_CLOSE ? WSAECONNABORTED : ERROR_INVALID_DATA);
  122. if(!isOK) Stop();
  123. SetLastError(SE_DATA_SEND, __FUNCTION__, ec);
  124. return FALSE;
  125. }
  126. return TRUE;
  127. }
  128. template<class T, USHORT default_port> BOOL CHttpSyncClientT<T, default_port>::OpenUrl(LPCSTR lpszMethod, LPCSTR lpszUrl, const THeader lpHeaders[], int iHeaderCount, const BYTE* pBody, int iLength, BOOL bForceReconnect)
  129. {
  130. BOOL bHttps;
  131. USHORT usPort;
  132. CStringA strHost;
  133. CStringA strPath;
  134. if(!::ParseUrl(lpszUrl, bHttps, strHost, usPort, strPath))
  135. {
  136. SetLastError(SE_CONNECT_SERVER, __FUNCTION__, WSAEADDRNOTAVAIL);
  137. return FALSE;
  138. }
  139. if((bHttps && default_port == HTTP_DEFAULT_PORT) || (!bHttps && default_port == HTTPS_DEFAULT_PORT))
  140. {
  141. SetLastError(SE_CONNECT_SERVER, __FUNCTION__, WSAEPROTOTYPE);
  142. return FALSE;
  143. }
  144. if(HasStarted())
  145. {
  146. BOOL bNeedStop = bForceReconnect;
  147. if(!bNeedStop)
  148. {
  149. LPCSTR lpszHost = nullptr;
  150. USHORT usPort2 = 0;
  151. GetRemoteHost(&lpszHost, &usPort2);
  152. if(strHost.CompareNoCase(lpszHost) != 0 || usPort != usPort2)
  153. bNeedStop = TRUE;
  154. }
  155. if(bNeedStop) Stop();
  156. }
  157. EnServiceState state = GetState();
  158. if(state != SS_STARTED)
  159. {
  160. if(state == SS_STARTING)
  161. {
  162. do
  163. {
  164. ::Sleep(50);
  165. state = GetState();
  166. } while(state != SS_STARTED && state != SS_STOPPED);
  167. }
  168. else
  169. {
  170. while(state != SS_STOPPED)
  171. {
  172. ::Sleep(50);
  173. state = GetState();
  174. }
  175. Start(CA2T(strHost), usPort, FALSE, nullptr);
  176. state = GetState();
  177. }
  178. if(state == SS_STOPPED)
  179. return FALSE;
  180. }
  181. return SendRequest(lpszMethod, strPath, lpHeaders, iHeaderCount, pBody, iLength);
  182. }
  183. template<class T, USHORT default_port> BOOL CHttpSyncClientT<T, default_port>::CleanupRequestResult()
  184. {
  185. m_szBuffer.Free();
  186. m_objHttp2.Reset();
  187. ResetRequestEvent();
  188. return TRUE;
  189. }
  190. template<class T, USHORT default_port> void CHttpSyncClientT<T, default_port>::ResetRequestEvent()
  191. {
  192. m_enProgress = HSRP_WAITING;
  193. m_evWait.Reset();
  194. }
  195. template<class T, USHORT default_port> void CHttpSyncClientT<T, default_port>::SetRequestEvent(EnHttpSyncRequestProgress enProgress)
  196. {
  197. if(m_enProgress == HSRP_WAITING)
  198. {
  199. m_enProgress = enProgress;
  200. m_evWait.Set();}
  201. }
  202. template<class T, USHORT default_port> BOOL CHttpSyncClientT<T, default_port>::GetResponseBody(LPCBYTE* lpszBody, int* iLength)
  203. {
  204. ASSERT(lpszBody && iLength);
  205. *lpszBody = m_szBuffer.Ptr();
  206. *iLength = (int)m_szBuffer.Size();
  207. return TRUE;
  208. }
  209. template<class T, USHORT default_port> EnHandleResult CHttpSyncClientT<T, default_port>::OnHandShake(ITcpClient* pSender, CONNID dwConnID)
  210. {
  211. SetRequestEvent(HSRP_DONE);
  212. return HR_OK;
  213. }
  214. template<class T, USHORT default_port> EnHandleResult CHttpSyncClientT<T, default_port>::OnClose(ITcpClient* pSender, CONNID dwConnID, EnSocketOperation enOperation, int iErrorCode)
  215. {
  216. SetRequestEvent(HSRP_CLOSE);
  217. return HR_OK;
  218. }
  219. template<class T, USHORT default_port> EnHttpParseResult CHttpSyncClientT<T, default_port>::OnHeadersComplete(IHttpClient* pSender, CONNID dwConnID)
  220. {
  221. return HPR_OK;
  222. }
  223. template<class T, USHORT default_port> EnHttpParseResult CHttpSyncClientT<T, default_port>::OnBody(IHttpClient* pSender, CONNID dwConnID, const BYTE* pData, int iLength)
  224. {
  225. m_szBuffer.Cat(pData, iLength);
  226. return HPR_OK;
  227. }
  228. template<class T, USHORT default_port> EnHttpParseResult CHttpSyncClientT<T, default_port>::OnMessageComplete(IHttpClient* pSender, CONNID dwConnID)
  229. {
  230. m_objHttp2.CopyData(m_objHttp);
  231. if(GetUpgradeType() == HUT_NONE)
  232. SetRequestEvent(HSRP_DONE);
  233. return HPR_OK;
  234. }
  235. template<class T, USHORT default_port> EnHttpParseResult CHttpSyncClientT<T, default_port>::OnUpgrade(IHttpClient* pSender, CONNID dwConnID, EnHttpUpgradeType enUpgradeType)
  236. {
  237. if(enUpgradeType == HUT_WEB_SOCKET)
  238. {
  239. SetRequestEvent(HSRP_DONE);
  240. return HPR_OK;
  241. }
  242. else
  243. {
  244. SetRequestEvent(HSRP_ERROR);
  245. return HPR_ERROR;
  246. }
  247. }
  248. template<class T, USHORT default_port> EnHttpParseResult CHttpSyncClientT<T, default_port>::OnParseError(IHttpClient* pSender, CONNID dwConnID, int iErrorCode, LPCSTR lpszErrorDesc)
  249. {
  250. m_objHttp2.CopyData(m_objHttp);
  251. SetRequestEvent(HSRP_ERROR);
  252. return HPR_OK;
  253. }
  254. template<class T, USHORT default_port> EnHandleResult CHttpSyncClientT<T, default_port>::OnWSMessageBody(IHttpClient* pSender, CONNID dwConnID, const BYTE* pData, int iLength)
  255. {
  256. m_szBuffer.Cat(pData, iLength);
  257. return HR_OK;
  258. }
  259. template<class T, USHORT default_port> EnHandleResult CHttpSyncClientT<T, default_port>::OnWSMessageComplete(IHttpClient* pSender, CONNID dwConnID)
  260. {
  261. m_objHttp2.CopyWSContext(m_objHttp);
  262. SetRequestEvent(HSRP_DONE);
  263. return HR_OK;
  264. }
  265. // ------------------------------------------------------------------------------------------------------------- //
  266. template class CHttpClientT<IHttpRequester, CTcpClient, HTTP_DEFAULT_PORT>;
  267. template class CHttpSyncClientT<CTcpClient, HTTP_DEFAULT_PORT>;
  268. #ifdef _SSL_SUPPORT
  269. #include "SSLClient.h"
  270. template class CHttpClientT<IHttpRequester, CSSLClient, HTTPS_DEFAULT_PORT>;
  271. template class CHttpSyncClientT<CSSLClient, HTTPS_DEFAULT_PORT>;
  272. #endif