PageRenderTime 54ms CodeModel.GetById 19ms RepoModel.GetById 0ms app.codeStats 0ms

/src/scripting/flash/net/URLStream.cpp

http://github.com/lightspark/lightspark
C++ | 341 lines | 251 code | 45 blank | 45 comment | 16 complexity | 6c18ae6027182e5079656826f6a2a5d3 MD5 | raw file
Possible License(s): GPL-3.0, LGPL-3.0, MPL-2.0-no-copyleft-exception, BSD-3-Clause
  1. /**************************************************************************
  2. Lightspark, a free flash player implementation
  3. Copyright (C) 2011-2013 Alessandro Pignotti (a.pignotti@sssup.it)
  4. This program is free software: you can redistribute it and/or modify
  5. it under the terms of the GNU Lesser General Public License as published by
  6. the Free Software Foundation, either version 3 of the License, or
  7. (at your option) any later version.
  8. This program is distributed in the hope that it will be useful,
  9. but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  11. GNU Lesser General Public License for more details.
  12. You should have received a copy of the GNU Lesser General Public License
  13. along with this program. If not, see <http://www.gnu.org/licenses/>.
  14. **************************************************************************/
  15. #include <map>
  16. #include "backends/security.h"
  17. #include "scripting/abc.h"
  18. #include "scripting/flash/net/URLStream.h"
  19. #include "scripting/flash/net/flashnet.h"
  20. #include "scripting/flash/utils/ByteArray.h"
  21. #include "scripting/argconv.h"
  22. /**
  23. * TODO: This whole class shares a lot of code with URLLoader - unify!
  24. * TODO: This whole class is quite untested
  25. */
  26. using namespace std;
  27. using namespace lightspark;
  28. URLStreamThread::URLStreamThread(_R<URLRequest> request, _R<URLStream> ldr, _R<ByteArray> bytes)
  29. : DownloaderThreadBase(request, ldr.getPtr()), loader(ldr), data(bytes),streambuffer(NULL),timestamp_last_progress(0),bytes_total(0)
  30. {
  31. }
  32. void URLStreamThread::setBytesTotal(uint32_t b)
  33. {
  34. bytes_total = b;
  35. }
  36. void URLStreamThread::setBytesLoaded(uint32_t b)
  37. {
  38. uint32_t curlen = data->getLength();
  39. if(b>curlen && streambuffer)
  40. {
  41. data->append(streambuffer,b - curlen);
  42. uint64_t cur=compat_get_thread_cputime_us();
  43. if (cur > timestamp_last_progress+ 40*1000)
  44. {
  45. timestamp_last_progress = cur;
  46. loader->incRef();
  47. getVm(loader->getSystemState())->addEvent(loader,_MR(Class<ProgressEvent>::getInstanceS(loader->getSystemState(),b,bytes_total)));
  48. }
  49. }
  50. }
  51. void URLStreamThread::execute()
  52. {
  53. timestamp_last_progress = compat_get_thread_cputime_us();
  54. assert(!downloader);
  55. //TODO: support httpStatus
  56. _R<MemoryStreamCache> cache(_MR(new MemoryStreamCache(loader->getSystemState())));
  57. if(!createDownloader(cache, loader,this))
  58. return;
  59. data->setLength(0);
  60. bool success=false;
  61. if(!downloader->hasFailed())
  62. {
  63. loader->incRef();
  64. getVm(loader->getSystemState())->addEvent(loader,_MR(Class<Event>::getInstanceS(loader->getSystemState(),"open")));
  65. streambuffer = cache->createReader();
  66. loader->incRef();
  67. getVm(loader->getSystemState())->addEvent(loader,_MR(Class<ProgressEvent>::getInstanceS(loader->getSystemState(),0,bytes_total)));
  68. cache->waitForTermination();
  69. if(!downloader->hasFailed() && !threadAborting)
  70. {
  71. /*
  72. std::streambuf *sbuf = cache->createReader();
  73. istream s(sbuf);
  74. uint8_t* buf=new uint8_t[downloader->getLength()];
  75. //TODO: avoid this useless copy
  76. s.read((char*)buf,downloader->getLength());
  77. //TODO: test binary data format
  78. data->acquireBuffer(buf,downloader->getLength());
  79. //The buffers must not be deleted, it's now handled by the ByteArray instance
  80. delete sbuf;
  81. */
  82. success=true;
  83. }
  84. }
  85. // Don't send any events if the thread is aborting
  86. if(success && !threadAborting)
  87. {
  88. loader->incRef();
  89. getVm(loader->getSystemState())->addEvent(loader,_MR(Class<ProgressEvent>::getInstanceS(loader->getSystemState(),downloader->getLength(),downloader->getLength())));
  90. //Send a complete event for this object
  91. loader->incRef();
  92. getVm(loader->getSystemState())->addEvent(loader,_MR(Class<Event>::getInstanceS(loader->getSystemState(),"complete")));
  93. }
  94. else if(!success && !threadAborting)
  95. {
  96. //Notify an error during loading
  97. loader->incRef();
  98. getVm(loader->getSystemState())->addEvent(loader,_MR(Class<IOErrorEvent>::getInstanceS(loader->getSystemState())));
  99. }
  100. {
  101. //Acquire the lock to ensure consistency in threadAbort
  102. SpinlockLocker l(downloaderLock);
  103. getSys()->downloadManager->destroy(downloader);
  104. downloader = NULL;
  105. }
  106. }
  107. void URLStream::sinit(Class_base* c)
  108. {
  109. CLASS_SETUP(c, EventDispatcher, _constructor, CLASS_SEALED);
  110. c->setDeclaredMethodByQName("load","",Class<IFunction>::getFunction(c->getSystemState(),load),NORMAL_METHOD,true);
  111. c->setDeclaredMethodByQName("close","",Class<IFunction>::getFunction(c->getSystemState(),close),NORMAL_METHOD,true);
  112. c->setDeclaredMethodByQName("bytesAvailable","",Class<IFunction>::getFunction(c->getSystemState(),bytesAvailable),GETTER_METHOD,true);
  113. c->setDeclaredMethodByQName("endian","",Class<IFunction>::getFunction(c->getSystemState(),_getEndian),GETTER_METHOD,true);
  114. c->setDeclaredMethodByQName("endian","",Class<IFunction>::getFunction(c->getSystemState(),_setEndian),SETTER_METHOD,true);
  115. c->setDeclaredMethodByQName("objectEncoding","",Class<IFunction>::getFunction(c->getSystemState(),_getObjectEncoding),GETTER_METHOD,true);
  116. c->setDeclaredMethodByQName("objectEncoding","",Class<IFunction>::getFunction(c->getSystemState(),_setObjectEncoding),SETTER_METHOD,true);
  117. c->setDeclaredMethodByQName("readBoolean","",Class<IFunction>::getFunction(c->getSystemState(),readBoolean),NORMAL_METHOD,true);
  118. c->setDeclaredMethodByQName("readByte","",Class<IFunction>::getFunction(c->getSystemState(),readByte),NORMAL_METHOD,true);
  119. c->setDeclaredMethodByQName("readBytes","",Class<IFunction>::getFunction(c->getSystemState(),readBytes),NORMAL_METHOD,true);
  120. c->setDeclaredMethodByQName("readDouble","",Class<IFunction>::getFunction(c->getSystemState(),readDouble),NORMAL_METHOD,true);
  121. c->setDeclaredMethodByQName("readFloat","",Class<IFunction>::getFunction(c->getSystemState(),readFloat),NORMAL_METHOD,true);
  122. c->setDeclaredMethodByQName("readInt","",Class<IFunction>::getFunction(c->getSystemState(),readInt),NORMAL_METHOD,true);
  123. c->setDeclaredMethodByQName("readMultiByte","",Class<IFunction>::getFunction(c->getSystemState(),readMultiByte),NORMAL_METHOD,true);
  124. c->setDeclaredMethodByQName("readObject","",Class<IFunction>::getFunction(c->getSystemState(),readObject),NORMAL_METHOD,true);
  125. c->setDeclaredMethodByQName("readShort","",Class<IFunction>::getFunction(c->getSystemState(),readShort),NORMAL_METHOD,true);
  126. c->setDeclaredMethodByQName("readUnsignedByte","",Class<IFunction>::getFunction(c->getSystemState(),readUnsignedByte),NORMAL_METHOD,true);
  127. c->setDeclaredMethodByQName("readUnsignedInt","",Class<IFunction>::getFunction(c->getSystemState(),readUnsignedInt),NORMAL_METHOD,true);
  128. c->setDeclaredMethodByQName("readUnsignedShort","",Class<IFunction>::getFunction(c->getSystemState(),readUnsignedShort),NORMAL_METHOD,true);
  129. c->setDeclaredMethodByQName("readUTF","",Class<IFunction>::getFunction(c->getSystemState(),readUTF),NORMAL_METHOD,true);
  130. c->setDeclaredMethodByQName("readUTFBytes","",Class<IFunction>::getFunction(c->getSystemState(),readUTFBytes),NORMAL_METHOD,true);
  131. REGISTER_GETTER(c,connected);
  132. c->addImplementedInterface(InterfaceClass<IDataInput>::getClass(c->getSystemState()));
  133. IDataInput::linkTraits(c);
  134. }
  135. ASFUNCTIONBODY_GETTER(URLStream,connected);
  136. void URLStream::buildTraits(ASObject* o)
  137. {
  138. }
  139. void URLStream::threadFinished(IThreadJob* finishedJob)
  140. {
  141. // If this is the current job, we are done. If these are not
  142. // equal, finishedJob is a job that was cancelled when load()
  143. // was called again, and we have to still wait for the correct
  144. // job.
  145. SpinlockLocker l(spinlock);
  146. if(finishedJob==job)
  147. job=NULL;
  148. delete finishedJob;
  149. }
  150. ASFUNCTIONBODY_ATOM(URLStream,_constructor)
  151. {
  152. EventDispatcher::_constructor(ret,sys,obj,NULL,0);
  153. }
  154. ASFUNCTIONBODY_ATOM(URLStream,load)
  155. {
  156. URLStream* th=asAtomHandler::as<URLStream>(obj);
  157. _NR<URLRequest> urlRequest;
  158. ARG_UNPACK_ATOM (urlRequest);
  159. {
  160. SpinlockLocker l(th->spinlock);
  161. if(th->job)
  162. th->job->threadAbort();
  163. }
  164. th->url=urlRequest->getRequestURL();
  165. if(!th->url.isValid())
  166. {
  167. //Notify an error during loading
  168. th->incRef();
  169. sys->currentVm->addEvent(_MR(th),_MR(Class<IOErrorEvent>::getInstanceS(sys)));
  170. return;
  171. }
  172. //TODO: support the right events (like SecurityErrorEvent)
  173. //URLLoader ALWAYS checks for policy files, in contrast to NetStream.play().
  174. SecurityManager::checkURLStaticAndThrow(th->url, ~(SecurityManager::LOCAL_WITH_FILE),
  175. SecurityManager::LOCAL_WITH_FILE | SecurityManager::LOCAL_TRUSTED, true);
  176. th->incRef();
  177. URLStreamThread *job=new URLStreamThread(urlRequest, _MR(th), th->data);
  178. getSys()->addJob(job);
  179. th->job=job;
  180. th->connected = true;
  181. }
  182. ASFUNCTIONBODY_ATOM(URLStream,close)
  183. {
  184. URLStream* th=asAtomHandler::as<URLStream>(obj);
  185. SpinlockLocker l(th->spinlock);
  186. if(th->job)
  187. th->job->threadAbort();
  188. th->connected = false;
  189. }
  190. void URLStream::finalize()
  191. {
  192. EventDispatcher::finalize();
  193. data.reset();
  194. }
  195. URLStream::URLStream(Class_base *c):EventDispatcher(c),data(_MNR(Class<ByteArray>::getInstanceS(c->getSystemState()))),job(NULL),connected(false)
  196. {
  197. }
  198. ASFUNCTIONBODY_ATOM(URLStream,bytesAvailable) {
  199. URLStream* th=asAtomHandler::as<URLStream>(obj);
  200. asAtom v = asAtomHandler::fromObject(th->data.getPtr());
  201. ByteArray::_getBytesAvailable(ret,sys,v, args, argslen);
  202. }
  203. ASFUNCTIONBODY_ATOM(URLStream,_getEndian) {
  204. URLStream* th=asAtomHandler::as<URLStream>(obj);
  205. asAtom v = asAtomHandler::fromObject(th->data.getPtr());
  206. ByteArray::_getEndian(ret,sys,v, args, argslen);
  207. }
  208. ASFUNCTIONBODY_ATOM(URLStream,_setEndian) {
  209. URLStream* th=asAtomHandler::as<URLStream>(obj);
  210. asAtom v = asAtomHandler::fromObject(th->data.getPtr());
  211. ByteArray::_setEndian(ret,sys,v, args, argslen);
  212. }
  213. ASFUNCTIONBODY_ATOM(URLStream,_getObjectEncoding) {
  214. URLStream* th=asAtomHandler::as<URLStream>(obj);
  215. asAtom v = asAtomHandler::fromObject(th->data.getPtr());
  216. ByteArray::_getObjectEncoding(ret,sys,v, args, argslen);
  217. }
  218. ASFUNCTIONBODY_ATOM(URLStream,_setObjectEncoding) {
  219. URLStream* th=asAtomHandler::as<URLStream>(obj);
  220. asAtom v = asAtomHandler::fromObject(th->data.getPtr());
  221. ByteArray::_setObjectEncoding(ret,sys,v, args, argslen);
  222. }
  223. ASFUNCTIONBODY_ATOM(URLStream,readBoolean) {
  224. URLStream* th=asAtomHandler::as<URLStream>(obj);
  225. asAtom v = asAtomHandler::fromObject(th->data.getPtr());
  226. ByteArray::readBoolean(ret,sys,v, args, argslen);
  227. }
  228. ASFUNCTIONBODY_ATOM(URLStream,readByte) {
  229. URLStream* th=asAtomHandler::as<URLStream>(obj);
  230. asAtom v = asAtomHandler::fromObject(th->data.getPtr());
  231. ByteArray::readByte(ret,sys,v, args, argslen);
  232. }
  233. ASFUNCTIONBODY_ATOM(URLStream,readBytes) {
  234. URLStream* th=asAtomHandler::as<URLStream>(obj);
  235. asAtom v = asAtomHandler::fromObject(th->data.getPtr());
  236. ByteArray::readBytes(ret,sys,v, args, argslen);
  237. }
  238. ASFUNCTIONBODY_ATOM(URLStream,readDouble) {
  239. URLStream* th=asAtomHandler::as<URLStream>(obj);
  240. asAtom v = asAtomHandler::fromObject(th->data.getPtr());
  241. ByteArray::readDouble(ret,sys,v, args, argslen);
  242. }
  243. ASFUNCTIONBODY_ATOM(URLStream,readFloat) {
  244. URLStream* th=asAtomHandler::as<URLStream>(obj);
  245. asAtom v = asAtomHandler::fromObject(th->data.getPtr());
  246. ByteArray::readFloat(ret,sys,v, args, argslen);
  247. }
  248. ASFUNCTIONBODY_ATOM(URLStream,readInt) {
  249. URLStream* th=asAtomHandler::as<URLStream>(obj);
  250. asAtom v = asAtomHandler::fromObject(th->data.getPtr());
  251. ByteArray::readInt(ret,sys,v, args, argslen);
  252. }
  253. ASFUNCTIONBODY_ATOM(URLStream,readMultiByte) {
  254. URLStream* th=asAtomHandler::as<URLStream>(obj);
  255. asAtom v = asAtomHandler::fromObject(th->data.getPtr());
  256. ByteArray::readMultiByte(ret,sys,v, args, argslen);
  257. }
  258. ASFUNCTIONBODY_ATOM(URLStream,readObject) {
  259. URLStream* th=asAtomHandler::as<URLStream>(obj);
  260. asAtom v = asAtomHandler::fromObject(th->data.getPtr());
  261. ByteArray::readObject(ret,sys,v, args, argslen);
  262. }
  263. ASFUNCTIONBODY_ATOM(URLStream,readShort) {
  264. URLStream* th=asAtomHandler::as<URLStream>(obj);
  265. asAtom v = asAtomHandler::fromObject(th->data.getPtr());
  266. ByteArray::readShort(ret,sys,v, args, argslen);
  267. }
  268. ASFUNCTIONBODY_ATOM(URLStream,readUnsignedByte) {
  269. URLStream* th=asAtomHandler::as<URLStream>(obj);
  270. asAtom v = asAtomHandler::fromObject(th->data.getPtr());
  271. ByteArray::readUnsignedByte(ret,sys,v, args, argslen);
  272. }
  273. ASFUNCTIONBODY_ATOM(URLStream,readUnsignedInt) {
  274. URLStream* th=asAtomHandler::as<URLStream>(obj);
  275. asAtom v = asAtomHandler::fromObject(th->data.getPtr());
  276. ByteArray::readUnsignedInt(ret,sys,v, args, argslen);
  277. }
  278. ASFUNCTIONBODY_ATOM(URLStream,readUnsignedShort) {
  279. URLStream* th=asAtomHandler::as<URLStream>(obj);
  280. asAtom v = asAtomHandler::fromObject(th->data.getPtr());
  281. ByteArray::readUnsignedShort(ret,sys,v, args, argslen);
  282. }
  283. ASFUNCTIONBODY_ATOM(URLStream,readUTF) {
  284. URLStream* th=asAtomHandler::as<URLStream>(obj);
  285. asAtom v = asAtomHandler::fromObject(th->data.getPtr());
  286. ByteArray::readUTF(ret,sys,v, args, argslen);
  287. }
  288. ASFUNCTIONBODY_ATOM(URLStream,readUTFBytes) {
  289. URLStream* th=asAtomHandler::as<URLStream>(obj);
  290. asAtom v = asAtomHandler::fromObject(th->data.getPtr());
  291. ByteArray::readUTFBytes(ret,sys,v, args, argslen);
  292. }