HttpdClient.hxx 4.08 KB
Newer Older
1
/*
Max Kellermann's avatar
Max Kellermann committed
2
 * Copyright (C) 2003-2015 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 27
#include <boost/intrusive/list.hpp>

28
#include <queue>
29 30 31 32
#include <list>

#include <stddef.h>

33
class HttpdOutput;
Max Kellermann's avatar
Max Kellermann committed
34
class Page;
35

36 37 38
class HttpdClient final
	: BufferedSocket,
	  public boost::intrusive::list_base_hook<boost::intrusive::link_mode<boost::intrusive::normal_link>> {
39 40 41
	/**
	 * The httpd output object this client is connected to.
	 */
42
	HttpdOutput &httpd;
43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58

	/**
	 * 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
59
	 * A queue of #Page objects to be sent to the client.
60
	 */
61
	std::queue<Page *, std::list<Page *>> pages;
62

63 64 65 66 67
	/**
	 * The sum of all page sizes in #pages.
	 */
	size_t queue_size;

68 69 70
	/**
	 * The #page which is currently being sent to the client.
	 */
Max Kellermann's avatar
Max Kellermann committed
71
	Page *current_page;
72 73 74 75 76 77 78

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

79 80 81 82 83
	/**
	 * Is this a HEAD request?
	 */
	bool head_method;

84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109
	/**
         * 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
	 */
110
	unsigned metaint;
111 112

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

	/*
	 * 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.
	 */
126
	unsigned metadata_fill;
127 128 129 130

public:
	/**
	 * @param httpd the HTTP output device
Max Kellermann's avatar
Max Kellermann committed
131
	 * @param _fd the socket file descriptor
132
	 */
133
	HttpdClient(HttpdOutput &httpd, int _fd, EventLoop &_loop,
134
		    bool _metadata_supported);
135 136 137

	/**
	 * Note: this does not remove the client from the
138
	 * #HttpdOutput object.
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 166 167 168 169
	 */
	~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
170
	ssize_t GetBytesTillMetaData() const;
171

172 173 174 175
	ssize_t TryWritePage(const Page &page, size_t position);
	ssize_t TryWritePageN(const Page &page, size_t position, ssize_t n);

	bool TryWrite();
176 177 178 179

	/**
	 * Appends a page to the client's queue.
	 */
Max Kellermann's avatar
Max Kellermann committed
180
	void PushPage(Page *page);
181 182 183 184

	/**
	 * Sends the passed metadata.
	 */
185 186
	void PushMetaData(Page *page);

187 188 189
private:
	void ClearQueue();

190 191
protected:
	virtual bool OnSocketReady(unsigned flags) override;
192
	virtual InputResult OnSocketInput(void *data, size_t length) override;
193
	virtual void OnSocketError(Error &&error) override;
194
	virtual void OnSocketClosed() override;
195 196 197
};

#endif