HttpdClient.hxx 3.94 KB
Newer Older
1
/*
Max Kellermann's avatar
Max Kellermann committed
2
 * Copyright (C) 2003-2014 The Music Player Daemon Project
3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
 * http://www.musicpd.org
 *
 * This program 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; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program 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.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License along
 * with this program; if not, write to the Free Software Foundation, Inc.,
 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
 */

#ifndef MPD_OUTPUT_HTTPD_CLIENT_HXX
#define MPD_OUTPUT_HTTPD_CLIENT_HXX

23
#include "event/BufferedSocket.hxx"
24
#include "Compiler.h"
25

26
#include <queue>
27 28 29 30
#include <list>

#include <stddef.h>

31
class HttpdOutput;
Max Kellermann's avatar
Max Kellermann committed
32
class Page;
33

34
class HttpdClient final : BufferedSocket {
35 36 37
	/**
	 * The httpd output object this client is connected to.
	 */
38
	HttpdOutput &httpd;
39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54

	/**
	 * The current state of the client.
	 */
	enum {
		/** reading the request line */
		REQUEST,

		/** reading the request headers */
		HEADERS,

		/** sending the HTTP response */
		RESPONSE,
	} state;

	/**
Max Kellermann's avatar
Max Kellermann committed
55
	 * A queue of #Page objects to be sent to the client.
56
	 */
57
	std::queue<Page *, std::list<Page *>> pages;
58

59 60 61 62 63
	/**
	 * The sum of all page sizes in #pages.
	 */
	size_t queue_size;

64 65 66
	/**
	 * The #page which is currently being sent to the client.
	 */
Max Kellermann's avatar
Max Kellermann committed
67
	Page *current_page;
68 69 70 71 72 73 74

	/**
	 * The amount of bytes which were already sent from
	 * #current_page.
	 */
	size_t current_position;

75 76 77 78 79
	/**
	 * Is this a HEAD request?
	 */
	bool head_method;

80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105
	/**
         * If DLNA streaming was an option.
         */
	bool dlna_streaming_requested;

	/* ICY */

	/**
	 * Do we support sending Icy-Metadata to the client?  This is
	 * disabled if the httpd audio output uses encoder tags.
	 */
	bool metadata_supported;

	/**
	 * If we should sent icy metadata.
	 */
	bool metadata_requested;

	/**
	 * If the current metadata was already sent to the client.
	 */
	bool metadata_sent;

	/**
	 * The amount of streaming data between each metadata block
	 */
106
	unsigned metaint;
107 108

	/**
Max Kellermann's avatar
Max Kellermann committed
109
	 * The metadata as #Page which is currently being sent to the client.
110
	 */
Max Kellermann's avatar
Max Kellermann committed
111
	Page *metadata;
112 113 114 115 116 117 118 119 120 121

	/*
	 * The amount of bytes which were already sent from the metadata.
	 */
	size_t metadata_current_position;

	/**
	 * The amount of streaming data sent to the client
	 * since the last icy information was sent.
	 */
122
	unsigned metadata_fill;
123 124 125 126 127 128

public:
	/**
	 * @param httpd the HTTP output device
	 * @param fd the socket file descriptor
	 */
129
	HttpdClient(HttpdOutput &httpd, int _fd, EventLoop &_loop,
130
		    bool _metadata_supported);
131 132 133

	/**
	 * Note: this does not remove the client from the
134
	 * #HttpdOutput object.
135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165
	 */
	~HttpdClient();

	/**
	 * Frees the client and removes it from the server's client list.
	 */
	void Close();

	void LockClose();

	/**
	 * Clears the page queue.
	 */
	void CancelQueue();

	/**
	 * Handle a line of the HTTP request.
	 */
	bool HandleLine(const char *line);

	/**
	 * Switch the client to the "RESPONSE" state.
	 */
	void BeginResponse();

	/**
	 * Sends the status line and response headers to the client.
	 */
	bool SendResponse();

	gcc_pure
166
	ssize_t GetBytesTillMetaData() const;
167

168 169 170 171
	ssize_t TryWritePage(const Page &page, size_t position);
	ssize_t TryWritePageN(const Page &page, size_t position, ssize_t n);

	bool TryWrite();
172 173 174 175

	/**
	 * Appends a page to the client's queue.
	 */
Max Kellermann's avatar
Max Kellermann committed
176
	void PushPage(Page *page);
177 178 179 180

	/**
	 * Sends the passed metadata.
	 */
181 182
	void PushMetaData(Page *page);

183 184 185
private:
	void ClearQueue();

186 187
protected:
	virtual bool OnSocketReady(unsigned flags) override;
188
	virtual InputResult OnSocketInput(void *data, size_t length) override;
189
	virtual void OnSocketError(Error &&error) override;
190
	virtual void OnSocketClosed() override;
191 192 193
};

#endif