1 /*
2  * This file is part of OpenTTD.
3  * OpenTTD is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 2.
4  * OpenTTD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
5  * See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with OpenTTD. If not, see <http://www.gnu.org/licenses/>.
6  */
7 
8 /**
9  * @file tcp_http.h Basic functions to receive and send HTTP TCP packets.
10  */
11 
12 #ifndef NETWORK_CORE_TCP_HTTP_H
13 #define NETWORK_CORE_TCP_HTTP_H
14 
15 #include "tcp.h"
16 
17 /** Callback for when the HTTP handler has something to tell us. */
18 struct HTTPCallback {
19 	/**
20 	 * An error has occurred and the connection has been closed.
21 	 * @note HTTP socket handler is closed/freed.
22 	 */
23 	virtual void OnFailure() = 0;
24 
25 	/**
26 	 * We're receiving data.
27 	 * @param data   the received data, nullptr when all data has been received.
28 	 * @param length the amount of received data, 0 when all data has been received.
29 	 * @note When nullptr is sent the HTTP socket handler is closed/freed.
30 	 */
31 	virtual void OnReceiveData(const char *data, size_t length) = 0;
32 
33 	/** Silentium */
~HTTPCallbackHTTPCallback34 	virtual ~HTTPCallback() {}
35 };
36 
37 /** Base socket handler for HTTP traffic. */
38 class NetworkHTTPSocketHandler : public NetworkSocketHandler {
39 private:
40 	char recv_buffer[4096];   ///< Partially received message.
41 	int recv_pos;             ///< Current position in buffer.
42 	int recv_length;          ///< Length of the data still retrieving.
43 	HTTPCallback *callback;   ///< The callback to call for the incoming data.
44 	const char *data;         ///< The (POST) data we might want to forward (to a redirect).
45 	int redirect_depth;       ///< The depth of the redirection.
46 
47 	int HandleHeader();
48 	int Receive();
49 public:
50 	SOCKET sock;              ///< The socket currently connected to
51 
52 	/**
53 	 * Whether this socket is currently bound to a socket.
54 	 * @return true when the socket is bound, false otherwise
55 	 */
IsConnected()56 	bool IsConnected() const
57 	{
58 		return this->sock != INVALID_SOCKET;
59 	}
60 
61 	void CloseSocket();
62 
63 	NetworkHTTPSocketHandler(SOCKET sock, HTTPCallback *callback,
64 			const std::string &host, const char *url, const char *data, int depth);
65 
66 	~NetworkHTTPSocketHandler();
67 
68 	static int Connect(char *uri, HTTPCallback *callback,
69 			const char *data = nullptr, int depth = 0);
70 
71 	static void HTTPReceive();
72 };
73 
74 /** Connect with a HTTP server and do ONE query. */
75 class NetworkHTTPContentConnecter : TCPConnecter {
76 	std::string hostname;   ///< Hostname we are connecting to.
77 	HTTPCallback *callback; ///< Callback to tell that we received some data (or won't).
78 	const char *url;        ///< The URL we want to get at the server.
79 	const char *data;       ///< The data to send
80 	int depth;              ///< How far we have recursed
81 
82 public:
83 	/**
84 	 * Start the connecting.
85 	 * @param hostname The hostname to connect to.
86 	 * @param callback The callback for HTTP retrieval.
87 	 * @param url The url at the server.
88 	 * @param data The data to send.
89 	 * @param depth The depth (redirect recursion) of the queries.
90 	 */
91 	NetworkHTTPContentConnecter(const std::string &hostname, HTTPCallback *callback, const char *url, const char *data = nullptr, int depth = 0) :
92 		TCPConnecter(hostname, 80),
93 		hostname(hostname),
94 		callback(callback),
95 		url(stredup(url)),
96 		data(data),
97 		depth(depth)
98 	{
99 	}
100 
101 	/** Free all our allocated data. */
~NetworkHTTPContentConnecter()102 	~NetworkHTTPContentConnecter()
103 	{
104 		free(this->url);
105 	}
106 
OnFailure()107 	void OnFailure() override
108 	{
109 		this->callback->OnFailure();
110 		free(this->data);
111 	}
112 
OnConnect(SOCKET s)113 	void OnConnect(SOCKET s) override
114 	{
115 		new NetworkHTTPSocketHandler(s, this->callback, this->hostname, this->url, this->data, this->depth);
116 		/* We've relinquished control of data now. */
117 		this->data = nullptr;
118 	}
119 };
120 
121 #endif /* NETWORK_CORE_TCP_HTTP_H */
122