mirror-http-reader.cpp
上传用户:market2
上传日期:2018-11-18
资源大小:18786k
文件大小:5k
源码类别:

外挂编程

开发平台:

Windows_Unix

  1. /*  Asynchronous HTTP client
  2.  *  Copyright (C) 2006   Written by VCL
  3.  *
  4.  *  This program is free software; you can redistribute it and/or modify
  5.  *  it under the terms of the GNU General Public License as published by
  6.  *  the Free Software Foundation; either version 2 of the License, or
  7.  *  (at your option) any later version.
  8.  *
  9.  *  This program is distributed in the hope that it will be useful,
  10.  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
  11.  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  12.  *  GNU General Public License for more details.
  13.  *
  14.  *  You should have received a copy of the GNU General Public License
  15.  *  along with this program; if not, write to the Free Software
  16.  *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  17.  */
  18. #include "mirror-http-reader.h"
  19. #include "std-http-reader.h"
  20. #include <stdlib.h>
  21. #include <string.h>
  22. #include <assert.h>
  23. // Platform abstraction layer.
  24. #ifdef WIN32
  25. #include "win32/platform.h"
  26. #else
  27. #include "unix/platform.h"
  28. #endif
  29. using namespace std;
  30. namespace OpenKore {
  31. /**
  32.  * A private class which implements the threading details.
  33.  * This class is used to hide the dependency on
  34.  * platform-specific threading mechanisms from the public
  35.  * header files.
  36.  */
  37. class _MirrorHttpReaderPrivate {
  38. private:
  39. MirrorHttpReader *parent;
  40. Thread thread;
  41. Mutex mutex;
  42. bool stop;
  43. static ThreadValue ThreadCallConvention threadEntry(void *arg) {
  44. _MirrorHttpReaderPrivate *priv = (_MirrorHttpReaderPrivate *) arg;
  45. MirrorHttpReader *self = priv->parent;
  46. HttpReader *http;
  47. bool found = false;
  48. list<char *> &urls = self->urls;
  49. // Find a mirror to use.
  50. while (!urls.empty() && !found) {
  51. DWORD beginTime;
  52. bool timeout = false;
  53. http = StdHttpReader::create(urls.front(),
  54.      self->userAgent);
  55. beginTime = GetTickCount();
  56. while (http->getStatus() == HTTP_READER_CONNECTING
  57.     && !priv->stop && !timeout) {
  58. Sleep(10);
  59. timeout = self->timeout != 0 && GetTickCount() >= beginTime + self->timeout;
  60. }
  61. if (priv->stop) {
  62. delete http;
  63. return 0;
  64. } else if (http->getStatus() == HTTP_READER_ERROR || timeout) {
  65. // Failed; try next mirror.
  66. delete http;
  67. free(urls.front());
  68. urls.pop_front();
  69. } else {
  70. // Connected; use this mirror for downloading.
  71. found = true;
  72. priv->lock();
  73. self->http = http;
  74. priv->unlock();
  75. }
  76. }
  77. if (!found) {
  78. priv->lock();
  79. self->status = HTTP_READER_ERROR;
  80. self->error = "Unable to connect to any mirror.";
  81. priv->unlock();
  82. }
  83. return THREAD_DEFAULT_RETURN_VALUE;
  84. }
  85. public:
  86. _MirrorHttpReaderPrivate(MirrorHttpReader *http) {
  87. parent = http;
  88. stop = false;
  89. NewMutex(mutex);
  90. NewThread(thread, threadEntry, this);
  91. }
  92. ~_MirrorHttpReaderPrivate() {
  93. stop = true;
  94. WaitThread(thread);
  95. FreeMutex(mutex);
  96. }
  97. void lock() {
  98. LockMutex(mutex);
  99. }
  100. void unlock() {
  101. UnlockMutex(mutex);
  102. }
  103. };
  104. /*****************************
  105.  * MirrorHttpReader
  106.  *****************************/
  107. MirrorHttpReader::MirrorHttpReader(const list<const char *> &urls,
  108. unsigned int timeout, const char *userAgent) {
  109. assert(!urls.empty());
  110. // Create a private copy of the URLs.
  111. list<const char *>::const_iterator it;
  112. for (it = urls.begin(); it != urls.end(); it++) {
  113. this->urls.push_back(strdup(*it));
  114. }
  115. this->timeout = timeout;
  116. this->userAgent = strdup(userAgent);
  117. status = HTTP_READER_CONNECTING;
  118. error = NULL;
  119. http = NULL;
  120. priv = new _MirrorHttpReaderPrivate(this);
  121. }
  122. MirrorHttpReader::~MirrorHttpReader() {
  123. delete priv;
  124. list<char *>::iterator it;
  125. for (it = urls.begin(); it != urls.end(); it++) {
  126. free(*it);
  127. }
  128. free(userAgent);
  129. if (http != NULL) {
  130. delete http;
  131. }
  132. }
  133. HttpReaderStatus
  134. MirrorHttpReader::getStatus() const {
  135. HttpReaderStatus result;
  136. priv->lock();
  137. if (http != NULL) {
  138. result = http->getStatus();
  139. } else {
  140. result = status;
  141. }
  142. priv->unlock();
  143. return result;
  144. }
  145. const char *
  146. MirrorHttpReader::getError() const {
  147. assert(getStatus() == HTTP_READER_ERROR);
  148. const char *result;
  149. priv->lock();
  150. if (http != NULL) {
  151. result = http->getError();
  152. } else {
  153. result = error;
  154. }
  155. priv->unlock();
  156. return result;
  157. }
  158. int
  159. MirrorHttpReader::pullData(void *buf, unsigned int size) {
  160. assert(getStatus() != HTTP_READER_CONNECTING);
  161. assert(buf != NULL);
  162. assert(size > 0);
  163. int result;
  164. priv->lock();
  165. if (http != NULL) {
  166. result = http->pullData(buf, size);
  167. } else {
  168. assert(status != HTTP_READER_CONNECTING);
  169. assert(status == HTTP_READER_ERROR);
  170. result = -2;
  171. }
  172. priv->unlock();
  173. return result;
  174. }
  175. const char *
  176. MirrorHttpReader::getData(unsigned int &len) const {
  177. assert(getStatus() == HTTP_READER_DONE);
  178. assert(http != NULL);
  179. return http->getData(len);
  180. }
  181. int
  182. MirrorHttpReader::getSize() const {
  183. assert(getStatus() != HTTP_READER_CONNECTING);
  184. int result;
  185. priv->lock();
  186. if (http != NULL) {
  187. result = http->getSize();
  188. } else {
  189. result = -2;
  190. assert(status == HTTP_READER_ERROR);
  191. }
  192. priv->unlock();
  193. return result;
  194. }
  195. }