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 using namespace BPrivate::Network; 15 16 17 static BReference<BUrlContext> gDefaultContext = new(std::nothrow) BUrlContext(); 18 19 20 BUrlRequest::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 40 BUrlRequest::~BUrlRequest() 41 { 42 Stop(); 43 } 44 45 46 // #pragma mark URL protocol thread management 47 48 49 thread_id 50 BUrlRequest::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 78 status_t 79 BUrlRequest::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 92 status_t 93 BUrlRequest::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 104 status_t 105 BUrlRequest::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 119 status_t 120 BUrlRequest::SetListener(BUrlProtocolListener* listener) 121 { 122 if (IsRunning()) 123 return B_ERROR; 124 125 fListener = listener; 126 return B_OK; 127 } 128 129 130 status_t 131 BUrlRequest::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 144 const BUrl& 145 BUrlRequest::Url() const 146 { 147 return fUrl; 148 } 149 150 151 BUrlContext* 152 BUrlRequest::Context() const 153 { 154 return fContext; 155 } 156 157 158 BUrlProtocolListener* 159 BUrlRequest::Listener() const 160 { 161 return fListener; 162 } 163 164 165 const BString& 166 BUrlRequest::Protocol() const 167 { 168 return fProtocol; 169 } 170 171 172 #ifndef LIBNETAPI_DEPRECATED 173 BDataIO* 174 BUrlRequest::Output() const 175 { 176 return fOutput; 177 } 178 #endif 179 180 // #pragma mark URL protocol informations 181 182 183 bool 184 BUrlRequest::IsRunning() const 185 { 186 return fRunning; 187 } 188 189 190 status_t 191 BUrlRequest::Status() const 192 { 193 return fThreadStatus; 194 } 195 196 197 // #pragma mark Thread management 198 199 200 /*static*/ int32 201 BUrlRequest::_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 221 void 222 BUrlRequest::_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