HttpServer.cpp 8.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361
  1. /*
  2. * Copyright: JessMA Open Source (ldcsaa@gmail.com)
  3. *
  4. * Version : 3.6.1
  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 "HttpServer.h"
  26. template<class T> BOOL CHttpServerT<T>::Start(LPCTSTR lpszBindAddress, USHORT usPort)
  27. {
  28. BOOL isOK = __super::Start(lpszBindAddress, usPort);
  29. if(isOK) VERIFY(m_thCleaner.Start(this));
  30. return isOK;
  31. }
  32. template<class T> BOOL CHttpServerT<T>::CheckParams()
  33. {
  34. if ((m_enLocalVersion != HV_1_1 && m_enLocalVersion != HV_1_0) ||
  35. (m_dwReleaseDelay < MIN_HTTP_RELEASE_DELAY || m_dwReleaseDelay > MAX_HTTP_RELEASE_DELAY))
  36. {
  37. SetLastError(SE_INVALID_PARAM, __FUNCTION__, ERROR_INVALID_PARAMETER);
  38. return FALSE;
  39. }
  40. return __super::CheckParams();
  41. }
  42. template<class T> BOOL CHttpServerT<T>::SendResponse(CONNID dwConnID, USHORT usStatusCode, LPCSTR lpszDesc, const THeader lpHeaders[], int iHeaderCount, const BYTE* pData, int iLength)
  43. {
  44. WSABUF szBuffer[2];
  45. CStringA strHeader;
  46. ::MakeStatusLine(m_enLocalVersion, usStatusCode, lpszDesc, strHeader);
  47. ::MakeHeaderLines(lpHeaders, iHeaderCount, nullptr, iLength, FALSE, strHeader);
  48. ::MakeHttpPacket(strHeader, pData, iLength, szBuffer);
  49. return SendPackets(dwConnID, szBuffer, 2);
  50. }
  51. template<class T> BOOL CHttpServerT<T>::Release(CONNID dwConnID)
  52. {
  53. THttpObj* pHttpObj = FindHttpObj(dwConnID);
  54. if(pHttpObj == nullptr || pHttpObj->HasReleased())
  55. return FALSE;
  56. pHttpObj->Release();
  57. m_lsDyingQueue.PushBack(TDyingConnection::Construct(dwConnID));
  58. return TRUE;
  59. }
  60. template<class T> UINT CHttpServerT<T>::Run()
  61. {
  62. TRACE("---------------> Connection Cleaner Thread 0x%08X started <---------------\n", ::GetCurrentThreadId());
  63. DWORD dwRetValue = 0;
  64. DWORD dwInterval = max(MIN_HTTP_RELEASE_CHECK_INTERVAL, (m_dwReleaseDelay - MIN_HTTP_RELEASE_DELAY / 2));
  65. while(HasStarted())
  66. {
  67. dwRetValue = ::WaitForSingleObject(m_evCleaner, dwInterval);
  68. if(dwRetValue == WAIT_TIMEOUT)
  69. KillDyingConnection();
  70. else if(dwRetValue == WAIT_OBJECT_0)
  71. break;
  72. else
  73. ASSERT(FALSE);
  74. }
  75. TRACE("---------------> Connection Cleaner Thread 0x%08X stoped <---------------\n", ::GetCurrentThreadId());
  76. return 0;
  77. }
  78. template<class T> void CHttpServerT<T>::KillDyingConnection()
  79. {
  80. TDyingConnection* pDyingConn = nullptr;
  81. DWORD now = ::TimeGetTime();
  82. while(m_lsDyingQueue.UnsafePeekFront(&pDyingConn))
  83. {
  84. if((int)(now - pDyingConn->killTime) < (int)m_dwReleaseDelay)
  85. break;
  86. Disconnect(pDyingConn->connID, TRUE);
  87. VERIFY(m_lsDyingQueue.UnsafePopFront(&pDyingConn));
  88. TDyingConnection::Destruct(pDyingConn);
  89. }
  90. }
  91. template<class T> EnHandleResult CHttpServerT<T>::DoFireAccept(TSocketObj* pSocketObj)
  92. {
  93. EnHandleResult result = __super::DoFireAccept(pSocketObj);
  94. if(result != HR_ERROR)
  95. VERIFY(SetConnectionReserved(pSocketObj, THttpObj::Construct(TRUE, this, pSocketObj)));
  96. return result;
  97. }
  98. template<class T> EnHandleResult CHttpServerT<T>::DoFireReceive(TSocketObj* pSocketObj, const BYTE* pData, int iLength)
  99. {
  100. THttpObj* pHttpObj = FindHttpObj(pSocketObj);
  101. ASSERT(pHttpObj);
  102. if(pHttpObj->HasReleased())
  103. return HR_IGNORE;
  104. return pHttpObj->Execute(pData, iLength);
  105. }
  106. template<class T> EnHandleResult CHttpServerT<T>::DoFireClose(TSocketObj* pSocketObj, EnSocketOperation enOperation, int iErrorCode)
  107. {
  108. EnHandleResult result = __super::DoFireClose(pSocketObj, enOperation, iErrorCode);
  109. THttpObj* pHttpObj = FindHttpObj(pSocketObj);
  110. if(pHttpObj != nullptr)
  111. THttpObj::Destruct(pHttpObj);
  112. return result;
  113. }
  114. template<class T> EnHandleResult CHttpServerT<T>::DoFireShutdown()
  115. {
  116. EnHandleResult result = __super::DoFireShutdown();
  117. WaitForCleanerThreadEnd();
  118. ReleaseDyingConnection();
  119. return result;
  120. }
  121. template<class T> void CHttpServerT<T>::WaitForCleanerThreadEnd()
  122. {
  123. if(m_thCleaner.IsValid())
  124. {
  125. m_evCleaner.Set();
  126. m_thCleaner.Join(TRUE);
  127. }
  128. }
  129. template<class T> void CHttpServerT<T>::ReleaseDyingConnection()
  130. {
  131. TDyingConnection* pDyingConn = nullptr;
  132. while(m_lsDyingQueue.UnsafePopFront(&pDyingConn))
  133. TDyingConnection::Destruct(pDyingConn);
  134. VERIFY(m_lsDyingQueue.IsEmpty());
  135. }
  136. template<class T> BOOL CHttpServerT<T>::IsUpgrade(CONNID dwConnID)
  137. {
  138. THttpObj* pHttpObj = FindHttpObj(dwConnID);
  139. if(pHttpObj == nullptr)
  140. return FALSE;
  141. return pHttpObj->IsUpgrade();
  142. }
  143. template<class T> BOOL CHttpServerT<T>::IsKeepAlive(CONNID dwConnID)
  144. {
  145. THttpObj* pHttpObj = FindHttpObj(dwConnID);
  146. if(pHttpObj == nullptr)
  147. return FALSE;
  148. return pHttpObj->IsKeepAlive();
  149. }
  150. template<class T> USHORT CHttpServerT<T>::GetVersion(CONNID dwConnID)
  151. {
  152. THttpObj* pHttpObj = FindHttpObj(dwConnID);
  153. if(pHttpObj == nullptr)
  154. return 0;
  155. return pHttpObj->GetVersion();
  156. }
  157. template<class T> ULONGLONG CHttpServerT<T>::GetContentLength(CONNID dwConnID)
  158. {
  159. THttpObj* pHttpObj = FindHttpObj(dwConnID);
  160. if(pHttpObj == nullptr)
  161. return 0;
  162. return pHttpObj->GetContentLength();
  163. }
  164. template<class T> LPCSTR CHttpServerT<T>::GetContentType(CONNID dwConnID)
  165. {
  166. THttpObj* pHttpObj = FindHttpObj(dwConnID);
  167. if(pHttpObj == nullptr)
  168. return 0;
  169. return pHttpObj->GetContentType();
  170. }
  171. template<class T> EnHttpUpgradeType CHttpServerT<T>::GetUpgradeType(CONNID dwConnID)
  172. {
  173. THttpObj* pHttpObj = FindHttpObj(dwConnID);
  174. if(pHttpObj == nullptr)
  175. return HUT_NONE;
  176. return pHttpObj->GetUpgradeType();
  177. }
  178. template<class T> USHORT CHttpServerT<T>::GetParseErrorCode(CONNID dwConnID, LPCSTR* lpszErrorDesc)
  179. {
  180. THttpObj* pHttpObj = FindHttpObj(dwConnID);
  181. if(pHttpObj == nullptr)
  182. return 0;
  183. return pHttpObj->GetParseErrorCode(lpszErrorDesc);
  184. }
  185. template<class T> BOOL CHttpServerT<T>::GetHeader(CONNID dwConnID, LPCSTR lpszName, LPCSTR* lpszValue)
  186. {
  187. THttpObj* pHttpObj = FindHttpObj(dwConnID);
  188. if(pHttpObj == nullptr)
  189. return 0;
  190. return pHttpObj->GetHeader(lpszName, lpszValue);
  191. }
  192. template<class T> BOOL CHttpServerT<T>::GetHeaders(CONNID dwConnID, LPCSTR lpszName, LPCSTR lpszValue[], DWORD& dwCount)
  193. {
  194. THttpObj* pHttpObj = FindHttpObj(dwConnID);
  195. if(pHttpObj == nullptr)
  196. return 0;
  197. return pHttpObj->GetHeaders(lpszName, lpszValue, dwCount);
  198. }
  199. template<class T> BOOL CHttpServerT<T>::GetAllHeaders(CONNID dwConnID, THeader lpHeaders[], DWORD& dwCount)
  200. {
  201. THttpObj* pHttpObj = FindHttpObj(dwConnID);
  202. if(pHttpObj == nullptr)
  203. return 0;
  204. return pHttpObj->GetAllHeaders(lpHeaders, dwCount);
  205. }
  206. template<class T> BOOL CHttpServerT<T>::GetAllHeaderNames(CONNID dwConnID, LPCSTR lpszName[], DWORD& dwCount)
  207. {
  208. THttpObj* pHttpObj = FindHttpObj(dwConnID);
  209. if(pHttpObj == nullptr)
  210. return 0;
  211. return pHttpObj->GetAllHeaderNames(lpszName, dwCount);
  212. }
  213. template<class T> BOOL CHttpServerT<T>::GetCookie(CONNID dwConnID, LPCSTR lpszName, LPCSTR* lpszValue)
  214. {
  215. THttpObj* pHttpObj = FindHttpObj(dwConnID);
  216. if(pHttpObj == nullptr)
  217. return FALSE;
  218. return pHttpObj->GetCookie(lpszName, lpszValue);
  219. }
  220. template<class T> BOOL CHttpServerT<T>::GetAllCookies(CONNID dwConnID, TCookie lpCookies[], DWORD& dwCount)
  221. {
  222. THttpObj* pHttpObj = FindHttpObj(dwConnID);
  223. if(pHttpObj == nullptr)
  224. return FALSE;
  225. return pHttpObj->GetAllCookies(lpCookies, dwCount);
  226. }
  227. template<class T> USHORT CHttpServerT<T>::GetUrlFieldSet(CONNID dwConnID)
  228. {
  229. THttpObj* pHttpObj = FindHttpObj(dwConnID);
  230. if(pHttpObj == nullptr)
  231. return 0;
  232. return pHttpObj->GetUrlFieldSet();
  233. }
  234. template<class T> LPCSTR CHttpServerT<T>::GetUrlField(CONNID dwConnID, EnHttpUrlField enField)
  235. {
  236. THttpObj* pHttpObj = FindHttpObj(dwConnID);
  237. if(pHttpObj == nullptr)
  238. return 0;
  239. return pHttpObj->GetUrlField(enField);
  240. }
  241. template<class T> LPCSTR CHttpServerT<T>::GetMethod(CONNID dwConnID)
  242. {
  243. THttpObj* pHttpObj = FindHttpObj(dwConnID);
  244. if(pHttpObj == nullptr)
  245. return 0;
  246. return pHttpObj->GetMethod();
  247. }
  248. template<class T> inline typename CHttpServerT<T>::THttpObj* CHttpServerT<T>::FindHttpObj(CONNID dwConnID)
  249. {
  250. THttpObj* pHttpObj = nullptr;
  251. GetConnectionReserved(dwConnID, (PVOID*)&pHttpObj);
  252. return pHttpObj;
  253. }
  254. template<class T> inline typename CHttpServerT<T>::THttpObj* CHttpServerT<T>::FindHttpObj(TSocketObj* pSocketObj)
  255. {
  256. THttpObj* pHttpObj = nullptr;
  257. GetConnectionReserved(pSocketObj, (PVOID*)&pHttpObj);
  258. return pHttpObj;
  259. }
  260. template class CHttpServerT<CTcpServer>;
  261. #ifdef _SSL_SUPPORT
  262. #include "SSLServer.h"
  263. template class CHttpServerT<CSSLServer>;
  264. #endif