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 #ifdef LIBNETAPI_DEPRECATED 113 status_t 114 BUrlRequest::Pause() 115 { 116 return B_ERROR; 117 } 118 119 120 status_t 121 BUrlRequest::Resume() 122 { 123 return B_ERROR; 124 } 125 #endif 126 127 128 // #pragma mark URL protocol parameters modification 129 130 131 status_t 132 BUrlRequest::SetUrl(const BUrl& url) 133 { 134 // We should avoid to change URL while the thread is running ... 135 if (IsRunning()) 136 return B_ERROR; 137 138 fUrl = url; 139 return B_OK; 140 } 141 142 143 status_t 144 BUrlRequest::SetContext(BUrlContext* context) 145 { 146 if (IsRunning()) 147 return B_ERROR; 148 149 if (context == NULL) 150 fContext = gDefaultContext; 151 else 152 fContext = context; 153 154 return B_OK; 155 } 156 157 158 status_t 159 BUrlRequest::SetListener(BUrlProtocolListener* listener) 160 { 161 if (IsRunning()) 162 return B_ERROR; 163 164 fListener = listener; 165 return B_OK; 166 } 167 168 169 #ifndef LIBNETAPI_DEPRECATED 170 status_t 171 BUrlRequest::SetOutput(BDataIO* output) 172 { 173 if (IsRunning()) 174 return B_ERROR; 175 176 fOutput = output; 177 return B_OK; 178 } 179 #endif 180 181 182 // #pragma mark URL protocol parameters access 183 184 185 const BUrl& 186 BUrlRequest::Url() const 187 { 188 return fUrl; 189 } 190 191 192 BUrlContext* 193 BUrlRequest::Context() const 194 { 195 return fContext; 196 } 197 198 199 BUrlProtocolListener* 200 BUrlRequest::Listener() const 201 { 202 return fListener; 203 } 204 205 206 const BString& 207 BUrlRequest::Protocol() const 208 { 209 return fProtocol; 210 } 211 212 213 #ifndef LIBNETAPI_DEPRECATED 214 BDataIO* 215 BUrlRequest::Output() const 216 { 217 return fOutput; 218 } 219 #endif 220 221 // #pragma mark URL protocol informations 222 223 224 bool 225 BUrlRequest::IsRunning() const 226 { 227 return fRunning; 228 } 229 230 231 status_t 232 BUrlRequest::Status() const 233 { 234 return fThreadStatus; 235 } 236 237 238 // #pragma mark Thread management 239 240 241 /*static*/ int32 242 BUrlRequest::_ThreadEntry(void* arg) 243 { 244 BUrlRequest* request = reinterpret_cast<BUrlRequest*>(arg); 245 request->fThreadStatus = B_BUSY; 246 request->_ProtocolSetup(); 247 248 status_t protocolLoopExitStatus = request->_ProtocolLoop(); 249 250 request->fRunning = false; 251 request->fThreadStatus = protocolLoopExitStatus; 252 253 if (request->fListener != NULL) { 254 request->fListener->RequestCompleted(request, 255 protocolLoopExitStatus == B_OK); 256 } 257 258 return B_OK; 259 } 260 261 262 void 263 BUrlRequest::_EmitDebug(BUrlProtocolDebugMessage type, 264 const char* format, ...) 265 { 266 if (fListener == NULL) 267 return; 268 269 va_list arguments; 270 va_start(arguments, format); 271 272 char debugMsg[1024]; 273 vsnprintf(debugMsg, sizeof(debugMsg), format, arguments); 274 fListener->DebugMessage(this, type, debugMsg); 275 va_end(arguments); 276 } 277