]> git.sesse.net Git - cubemap/blob - httpinput.h
Better HOWTO in the README.
[cubemap] / httpinput.h
1 #ifndef _HTTPINPUT_H
2 #define _HTTPINPUT_H 1
3
4 #include <stddef.h>
5 #include <sys/types.h>
6 #include <mutex>
7 #include <string>
8 #include <vector>
9
10 #include "input.h"
11 #include "metacube2.h"
12 #include "stream.h"
13
14 class InputProto;
15
16 // Despite the name, covers input over both HTTP and pipes, both typically
17 // wrapped in Metacube.
18 class HTTPInput : public Input {
19 public:
20         HTTPInput(const std::string &url, Input::Encoding encoding);
21
22         // Serialization/deserialization.
23         HTTPInput(const InputProto &serialized);
24         virtual InputProto serialize() const;
25         
26         virtual void close_socket();
27
28         virtual std::string get_url() const { return url; }
29
30         virtual void add_destination(int stream_index);
31
32         virtual InputStats get_stats() const;
33
34 private:
35         // Actually does the download.
36         virtual void do_work();
37         
38         // Open a socket that connects to the given host and port. Does DNS resolving.
39         int lookup_and_connect(const std::string &host, const std::string &port);
40
41         // Open a child process with the given command line (given to /bin/sh).
42         // Returns a pipe to its standard output.
43         int open_child_process(const std::string &cmdline);
44
45         // Parses a HTTP response. Returns false if it not a 200.
46         bool parse_response(const std::string &response);
47
48         // Stores the given data, looks for Metacube blocks (skipping data if needed),
49         // and calls process_block() for each one.
50         void process_data(char *ptr, size_t bytes);
51
52         // Drops <num_bytes> bytes from the head of <pending_data>,
53         // and outputs a warning.
54         void drop_pending_data(size_t num_bytes);
55
56         void process_metacube_metadata_block(const metacube2_block_header &hdr, const char *payload, uint32_t payload_size);
57
58         enum State {
59                 NOT_CONNECTED,
60                 SENDING_REQUEST,
61                 RECEIVING_HEADER,
62                 RECEIVING_DATA,
63                 CLOSING_SOCKET,  // Due to error.
64         };
65         State state;
66
67         std::vector<int> stream_indices;
68
69         // The URL and its parsed components.
70         std::string url;
71         std::string host, port, path;
72
73         // What the input stream is to be interpreted as (normally Metacube).
74         Input::Encoding encoding;
75
76         // The HTTP request, with headers and all.
77         // Only relevant for SENDING_REQUEST.
78         std::string request;
79
80         // How many bytes we've sent of the request so far.
81         // Only relevant for SENDING_REQUEST.
82         size_t request_bytes_sent;
83
84         // The HTTP response we've received so far. Only relevant for RECEIVING_HEADER.
85         std::string response;
86
87         // The HTTP response headers we want to give clients for this input.
88         std::string http_header;
89
90         // The stream heder we want to give clients for this input.
91         std::string stream_header;
92
93         // Data we have received but not fully processed yet.
94         std::vector<char> pending_data;
95
96         // If <pending_data> starts with a Metacube header,
97         // this is true.
98         bool has_metacube_header = false;
99
100         // The socket we are downloading on (or -1).
101         int sock = -1;
102
103         // pid of the child process (or -1).
104         pid_t child_pid = -1;
105
106         // Mutex protecting <stats>.
107         mutable std::mutex stats_mutex;
108
109         // The current statistics for this connection. Protected by <stats_mutex>.
110         InputStats stats;
111
112         // Number of (started) connection attempts since last data byte was successfully read.
113         unsigned num_connection_attempts = 0;
114
115         // If set, don't log anything related to connections.
116         // (Only set if we've had enough unsuccessful connection attempts.)
117         bool suppress_logging = false;
118
119         // Last time we made a connection with logging enabled.
120         // (Initially at some point before the epoch.)
121         timespec last_verbose_connection { -3600, 0 };
122
123         // If we've received a Metacube2 PTS metadata block, it belongs to the
124         // next regular block we receive, and is stored here in the meantime.
125         // If we haven't received one yet (or we've already received the
126         // corresponding data block), this is empty, ie., timebase_num == 0.
127         RationalPTS next_block_pts;
128 };
129
130 #endif  // !defined(_HTTPINPUT_H)