1/* 2 * Copyright 2010 Haiku Inc. All rights reserved. 3 * Distributed under the terms of the MIT License. 4 * 5 * Authors: 6 * Christophe Huriaux, c.huriaux@gmail.com 7 */ 8 9 10#include <UrlRequest.h> 11#include <Debug.h> 12#include <stdio.h> 13 14using namespace BPrivate::Network; 15 16 17static BReference<BUrlContext> gDefaultContext = new(std::nothrow) BUrlContext(); 18 19 20BUrlRequest::BUrlRequest(const BUrl& url, BDataIO* output, 21 BUrlProtocolListener* listener, BUrlContext* context, 22 const char* threadName, const char* protocolName) 23 : 24 fUrl(url), 25 fContext(context), 26 fListener(listener), 27 fOutput(output), 28 fQuit(false), 29 fRunning(false), 30 fThreadStatus(B_NO_INIT), 31 fThreadId(0), 32 fThreadName(threadName), 33 fProtocol(protocolName) 34{ 35 if (fContext == NULL) 36 fContext = gDefaultContext; 37} 38 39 40BUrlRequest::~BUrlRequest() 41{ 42 Stop(); 43} 44 45 46// #pragma mark URL protocol thread management 47 48 49thread_id 50BUrlRequest::Run() 51{ 52 // Thread already running 53 if (fRunning) { 54 PRINT(("BUrlRequest::Run() : Oops, already running ! " 55 "[urlProtocol=%p]!\n", this)); 56 return fThreadId; 57 } 58 59 fThreadId = spawn_thread(BUrlRequest::_ThreadEntry, fThreadName, 60 B_NORMAL_PRIORITY, this); 61 62 if (fThreadId < B_OK) 63 return fThreadId; 64 65 fRunning = true; 66 67 status_t launchErr = resume_thread(fThreadId); 68 if (launchErr < B_OK) { 69 PRINT(("BUrlRequest::Run() : Failed to resume thread %" B_PRId32 "\n", 70 fThreadId)); 71 return launchErr; 72 } 73 74 return fThreadId; 75} 76 77 78status_t 79BUrlRequest::Stop() 80{ 81 if (!fRunning) 82 return B_ERROR; 83 84 fQuit = true; 85 return B_OK; 86} 87 88 89// #pragma mark URL protocol parameters modification 90 91 92status_t 93BUrlRequest::SetUrl(const BUrl& url) 94{ 95 // We should avoid to change URL while the thread is running ... 96 if (IsRunning()) 97 return B_ERROR; 98 99 fUrl = url; 100 return B_OK; 101} 102 103 104status_t 105BUrlRequest::SetContext(BUrlContext* context) 106{ 107 if (IsRunning()) 108 return B_ERROR; 109 110 if (context == NULL) 111 fContext = gDefaultContext; 112 else 113 fContext = context; 114 115 return B_OK; 116} 117 118 119status_t 120BUrlRequest::SetListener(BUrlProtocolListener* listener) 121{ 122 if (IsRunning()) 123 return B_ERROR; 124 125 fListener = listener; 126 return B_OK; 127} 128 129 130status_t 131BUrlRequest::SetOutput(BDataIO* output) 132{ 133 if (IsRunning()) 134 return B_ERROR; 135 136 fOutput = output; 137 return B_OK; 138} 139 140 141// #pragma mark URL protocol parameters access 142 143 144const BUrl& 145BUrlRequest::Url() const 146{ 147 return fUrl; 148} 149 150 151BUrlContext* 152BUrlRequest::Context() const 153{ 154 return fContext; 155} 156 157 158BUrlProtocolListener* 159BUrlRequest::Listener() const 160{ 161 return fListener; 162} 163 164 165const BString& 166BUrlRequest::Protocol() const 167{ 168 return fProtocol; 169} 170 171 172#ifndef LIBNETAPI_DEPRECATED 173BDataIO* 174BUrlRequest::Output() const 175{ 176 return fOutput; 177} 178#endif 179 180// #pragma mark URL protocol informations 181 182 183bool 184BUrlRequest::IsRunning() const 185{ 186 return fRunning; 187} 188 189 190status_t 191BUrlRequest::Status() const 192{ 193 return fThreadStatus; 194} 195 196 197// #pragma mark Thread management 198 199 200/*static*/ int32 201BUrlRequest::_ThreadEntry(void* arg) 202{ 203 BUrlRequest* request = reinterpret_cast<BUrlRequest*>(arg); 204 request->fThreadStatus = B_BUSY; 205 request->_ProtocolSetup(); 206 207 status_t protocolLoopExitStatus = request->_ProtocolLoop(); 208 209 request->fRunning = false; 210 request->fThreadStatus = protocolLoopExitStatus; 211 212 if (request->fListener != NULL) { 213 request->fListener->RequestCompleted(request, 214 protocolLoopExitStatus == B_OK); 215 } 216 217 return B_OK; 218} 219 220 221void 222BUrlRequest::_EmitDebug(BUrlProtocolDebugMessage type, 223 const char* format, ...) 224{ 225 if (fListener == NULL) 226 return; 227 228 va_list arguments; 229 va_start(arguments, format); 230 231 char debugMsg[1024]; 232 vsnprintf(debugMsg, sizeof(debugMsg), format, arguments); 233 fListener->DebugMessage(this, type, debugMsg); 234 va_end(arguments); 235} 236