xref: /haiku/src/kits/network/libnetservices/UrlRequest.cpp (revision 4a32f48e70297d9a634646f01e08c2f451ecd6bd)
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