1/*
2 * Copyright 2010-2014 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 *		Niels Sascha Reedijk, niels.reedijk@gmail.com
8 *		Adrien Destugues, pulkomandy@pulkomandy.tk
9 */
10
11
12#include <NetworkRequest.h>
13
14#include <AbstractSocket.h>
15
16using namespace BPrivate::Network;
17
18
19BNetworkRequest::BNetworkRequest(const BUrl& url, BDataIO* output,
20	BUrlProtocolListener* listener, BUrlContext* context,
21	const char* threadName, const char* protocolName)
22	:
23	BUrlRequest(url, output, listener, context, threadName, protocolName),
24	fSocket(NULL)
25{
26}
27
28
29status_t
30BNetworkRequest::Stop()
31{
32	status_t threadStatus = BUrlRequest::Stop();
33
34	if (threadStatus != B_OK)
35		return threadStatus;
36
37	send_signal(fThreadId, SIGUSR1); // unblock blocking syscalls.
38	wait_for_thread(fThreadId, &threadStatus);
39	return threadStatus;
40}
41
42
43void
44BNetworkRequest::SetTimeout(bigtime_t timeout)
45{
46	if (fSocket != NULL)
47		fSocket->SetTimeout(timeout);
48}
49
50
51bool
52BNetworkRequest::_ResolveHostName(BString host, uint16_t port)
53{
54	_EmitDebug(B_URL_PROTOCOL_DEBUG_TEXT, "Resolving %s",
55		fUrl.UrlString().String());
56
57	fRemoteAddr = BNetworkAddress(host, port);
58	if (fRemoteAddr.InitCheck() != B_OK)
59		return false;
60
61	//! ProtocolHook:HostnameResolved
62	if (fListener != NULL)
63		fListener->HostnameResolved(this, fRemoteAddr.ToString().String());
64
65	_EmitDebug(B_URL_PROTOCOL_DEBUG_TEXT, "Hostname resolved to: %s",
66		fRemoteAddr.ToString().String());
67
68	return true;
69}
70
71
72static void
73empty(int)
74{
75}
76
77
78void
79BNetworkRequest::_ProtocolSetup()
80{
81	// Setup an (empty) signal handler so we can be stopped by a signal,
82	// without the whole process being killed.
83	// TODO make connect() properly unlock when close() is called on the
84	// socket, and remove this.
85	struct sigaction action;
86	action.sa_handler = empty;
87	action.sa_mask = 0;
88	action.sa_flags = 0;
89	sigaction(SIGUSR1, &action, NULL);
90}
91
92
93status_t
94BNetworkRequest::_GetLine(BString& destString)
95{
96	// Find a complete line in inputBuffer
97	uint32 characterIndex = 0;
98
99	while ((characterIndex < fInputBuffer.Size())
100		&& ((fInputBuffer.Data())[characterIndex] != '\n'))
101		characterIndex++;
102
103	if (characterIndex == fInputBuffer.Size())
104		return B_ERROR;
105
106	char* temporaryBuffer = new(std::nothrow) char[characterIndex + 1];
107	if (temporaryBuffer == NULL)
108		return B_NO_MEMORY;
109
110	fInputBuffer.RemoveData(temporaryBuffer, characterIndex + 1);
111
112	// Strip end-of-line character(s)
113	if (characterIndex != 0 && temporaryBuffer[characterIndex - 1] == '\r')
114		destString.SetTo(temporaryBuffer, characterIndex - 1);
115	else
116		destString.SetTo(temporaryBuffer, characterIndex);
117
118	delete[] temporaryBuffer;
119	return B_OK;
120}
121
122
123