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