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