1 /* -*- c-basic-offset: 8; -*- */
2 /* shout.h: Private libshout data structures and declarations
3  *
4  *  Copyright (C) 2002-2004 the Icecast team <team@icecast.org>,
5  *  Copyright (C) 2012-2019 Philipp "ph3-der-loewe" Schafft <lion@lion.leolix.org>
6  *
7  *  This library is free software; you can redistribute it and/or
8  *  modify it under the terms of the GNU Library General Public
9  *  License as published by the Free Software Foundation; either
10  *  version 2 of the License, or (at your option) any later version.
11  *
12  *  This library is distributed in the hope that it will be useful,
13  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
14  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15  *  Library General Public License for more details.
16  *
17  *  You should have received a copy of the GNU Library General Public
18  *  License along with this library; if not, write to the Free
19  *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
20  *
21  * $Id$
22  */
23 
24 #ifndef __LIBSHOUT_SHOUT_PRIVATE_H__
25 #define __LIBSHOUT_SHOUT_PRIVATE_H__
26 
27 #ifdef HAVE_CONFIG_H
28 #   include "config.h"
29 #endif
30 
31 #include <shout/shout.h>
32 #include <common/net/sock.h>
33 #include <common/timing/timing.h>
34 #include "util.h"
35 
36 #include <sys/types.h>
37 
38 #ifdef HAVE_STDINT_H
39 #   include <stdint.h>
40 #elif defined (HAVE_INTTYPES_H)
41 #   include <inttypes.h>
42 #endif
43 
44 #ifdef HAVE_OPENSSL
45 #   include <openssl/ssl.h>
46 #endif
47 
48 #define LIBSHOUT_DEFAULT_HOST       "localhost"
49 #define LIBSHOUT_DEFAULT_PORT       8000
50 #define LIBSHOUT_DEFAULT_FORMAT     SHOUT_FORMAT_OGG
51 #define LIBSHOUT_DEFAULT_USAGE      SHOUT_USAGE_UNKNOWN
52 #define LIBSHOUT_DEFAULT_PROTOCOL   SHOUT_PROTOCOL_HTTP
53 #define LIBSHOUT_DEFAULT_USER       "source"
54 #define LIBSHOUT_DEFAULT_USERAGENT  "libshout/" VERSION
55 #define LIBSHOUT_DEFAULT_ALLOWED_CIPHERS "ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:DHE-DSS-AES128-GCM-SHA256:kEDH+AESGCM:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA:ECDHE-ECDSA-AES256-SHA:DHE-RSA-AES128-SHA256:DHE-RSA-AES128-SHA:DHE-DSS-AES128-SHA256:DHE-RSA-AES256-SHA256:DHE-DSS-AES256-SHA:DHE-RSA-AES256-SHA:AES128-GCM-SHA256:AES256-GCM-SHA384:AES128-SHA256:AES256-SHA256:AES128-SHA:AES256-SHA:AES:CAMELLIA:DES-CBC3-SHA:!aNULL:!eNULL:!EXPORT:!DES:!RC4:!MD5:!PSK:!aECDH:!EDH-DSS-DES-CBC3-SHA:!EDH-RSA-DES-CBC3-SHA:!KRB5-DES-CBC3-SHA" /* Mozilla's 'Intermediate' list as of 2015-04-19 */
56 
57 /* server capabilities.
58    0x000000XXUL -> Methods.
59    0x0000XX00UL -> HTTP Options
60    0x000X0000UL -> TLS Related
61    0xX0000000UL -> State related
62    0x0XX00000UL -> Reserved
63  */
64 #define LIBSHOUT_CAP_SOURCE      0x00000001UL
65 #define LIBSHOUT_CAP_PUT         0x00000002UL
66 #define LIBSHOUT_CAP_GET         0x00000004UL
67 #define LIBSHOUT_CAP_POST        0x00000008UL
68 #define LIBSHOUT_CAP_OPTIONS     0x00000010UL
69 #define LIBSHOUT_CAP_CHUNKED     0x00000100UL
70 #define LIBSHOUT_CAP_100CONTINUE 0x00000200UL
71 #define LIBSHOUT_CAP_UPGRADETLS  0x00010000UL
72 #define LIBSHOUT_CAP_REQAUTH     0x20000000UL /* requires authentication */
73 #define LIBSHOUT_CAP_CHALLENGED  0x40000000UL
74 #define LIBSHOUT_CAP_GOTCAPS     0x80000000UL
75 
76 #define LIBSHOUT_MAX_RETRY       3
77 
78 #define SHOUT_BUFSIZE 4096
79 
80 typedef struct _shout_tls shout_tls_t;
81 
82 typedef struct _shout_buf {
83     unsigned char   data[SHOUT_BUFSIZE];
84     unsigned int    len;
85     unsigned int    pos;
86 
87     struct  _shout_buf *prev;
88     struct  _shout_buf *next;
89 } shout_buf_t;
90 
91 typedef struct {
92     shout_buf_t     *head;
93     size_t           len;
94 } shout_queue_t;
95 
96 typedef enum {
97     SHOUT_SOCKSTATE_UNCONNECTED = 0,
98     SHOUT_SOCKSTATE_CONNECTING,
99     SHOUT_SOCKSTATE_CONNECTED,
100     SHOUT_SOCKSTATE_TLS_CONNECTING,
101     SHOUT_SOCKSTATE_TLS_CONNECTED,
102     SHOUT_SOCKSTATE_TLS_VERIFIED
103 } shout_connect_socket_state_t;
104 
105 typedef enum {
106     SHOUT_MSGSTATE_IDLE = 0,
107     SHOUT_MSGSTATE_CREATING0,
108     SHOUT_MSGSTATE_SENDING0,
109     SHOUT_MSGSTATE_WAITING0,
110     SHOUT_MSGSTATE_RECEIVING0,
111     SHOUT_MSGSTATE_RECEIVED0,
112     SHOUT_MSGSTATE_PARSED_INFORMATIONAL0,
113     SHOUT_MSGSTATE_CREATING1,
114     SHOUT_MSGSTATE_SENDING1,
115     SHOUT_MSGSTATE_WAITING1,
116     SHOUT_MSGSTATE_RECEIVING1,
117     SHOUT_MSGSTATE_RECEIVED1,
118     SHOUT_MSGSTATE_PARSED_INFORMATIONAL1,
119     SHOUT_MSGSTATE_PARSED_FINAL
120 } shout_connect_message_state_t;
121 
122 typedef enum {
123     SHOUT_RS_DONE,
124     SHOUT_RS_TIMEOUT,
125     SHOUT_RS_NOTNOW,
126     SHOUT_RS_ERROR
127 } shout_connection_return_state_t;
128 
129 typedef union shout_protocol_extra_tag {
130     int si;
131     void *vp;
132 } shout_protocol_extra_t;
133 
134 typedef struct {
135     int is_source;
136     int fake_ua;
137     int auth;
138     const char *method;
139     const char *resource;
140     const char *param;
141 } shout_http_plan_t;
142 
143 typedef struct shout_connection_tag shout_connection_t;
144 
145 typedef struct {
146     shout_connection_return_state_t (*msg_create)(shout_t *self, shout_connection_t *connection);
147     shout_connection_return_state_t (*msg_get)(shout_t *self, shout_connection_t *connection);
148     shout_connection_return_state_t (*msg_parse)(shout_t *self, shout_connection_t *connection);
149     shout_connection_return_state_t (*protocol_iter)(shout_t *self, shout_connection_t *connection);
150 } shout_protocol_impl_t;
151 
152 typedef int (*shout_connection_callback_t)(shout_connection_t *con, shout_event_t event, void *userdata, va_list ap);
153 
154 struct shout_connection_tag {
155     size_t                          refc;
156 
157     int                             selected_tls_mode;
158     shout_connect_socket_state_t    target_socket_state;
159     shout_connect_socket_state_t    current_socket_state;
160     shout_connect_message_state_t   target_message_state;
161     shout_connect_message_state_t   current_message_state;
162     int                             target_protocol_state;
163     int                             current_protocol_state;
164     shout_protocol_extra_t          protocol_extra;
165 
166     const shout_protocol_impl_t *impl;
167     const void *plan;
168 
169     int (*any_timeout)(shout_t *self, shout_connection_t *connection);
170     int (*destory)(shout_connection_t *connection);
171 
172     int                             nonblocking;
173 
174     shout_connection_callback_t callback;
175     void        *callback_userdata;
176 
177 #ifdef HAVE_OPENSSL
178     shout_tls_t   *tls;
179 #endif
180     sock_t         socket;
181     shout_queue_t  rqueue;
182     shout_queue_t  wqueue;
183 
184     uint64_t       wait_timeout;
185     /* maybe we want to convert this to general flag vector later */
186     int            wait_timeout_happened;
187 
188     /* server capabilities (LIBSHOUT_CAP_*) */
189     uint32_t server_caps;
190 
191     int error;
192 };
193 
194 struct shout {
195     /* hostname or IP of icecast server */
196     char *host;
197     /* port of the icecast server */
198     int port;
199     /* login password for the server */
200     char *password;
201     /* server protocol to use */
202     unsigned int protocol;
203     /* type of data being sent */
204     unsigned int format;
205     unsigned int usage;
206     /* audio encoding parameters */
207     util_dict *audio_info;
208     /* content-language */
209     char *content_language;
210 
211     /* user-agent to use when doing HTTP login */
212     char *useragent;
213     /* mountpoint for this stream */
214     char *mount;
215     /* all the meta data about the stream */
216     util_dict *meta;
217     /* icecast 1.x dumpfile */
218     char *dumpfile;
219     /* username to use for HTTP auth. */
220     char *user;
221     /* is this stream private? */
222     int public;
223 
224     shout_callback_t callback;
225     void *callback_userdata;
226 
227     /* TLS options */
228 #ifdef HAVE_OPENSSL
229     int          tls_mode;
230     char        *ca_directory;
231     char        *ca_file;
232     char        *allowed_ciphers;
233     char        *client_certificate;
234 #endif
235 
236     union {
237         shout_http_plan_t http;
238     } source_plan;
239 
240     /* socket the connection is on */
241     shout_connection_t *connection;
242     int             nonblocking;
243 
244     void *format_data;
245     int (*send)(shout_t* self, const unsigned char* buff, size_t len);
246     void (*close)(shout_t* self);
247 
248     /* start of this period's timeclock */
249     uint64_t starttime;
250     /* amount of data we've sent (in microseconds) */
251     uint64_t senttime;
252 
253     int error;
254 };
255 
256 /* helper functions */
257 const char *shout_get_mimetype_from_self(shout_t *self);
258 
259 int     shout_queue_data(shout_queue_t *queue, const unsigned char *data, size_t len);
260 int     shout_queue_str(shout_connection_t *self, const char *str);
261 int     shout_queue_printf(shout_connection_t *self, const char *fmt, ...);
262 void    shout_queue_free(shout_queue_t *queue);
263 ssize_t shout_queue_collect(shout_buf_t *queue, char **buf);
264 
265 /* transports */
266 ssize_t shout_conn_read(shout_t *self, void *buf, size_t len);
267 ssize_t shout_conn_write(shout_t *self, const void *buf, size_t len);
268 int     shout_conn_recoverable(shout_t *self);
269 
270 /* connection */
271 ssize_t shout_connection__read(shout_connection_t *con, shout_t *shout, void *buf, size_t len);
272 int shout_connection__recoverable(shout_connection_t *con, shout_t *shout);
273 shout_connection_t *shout_connection_new(shout_t *self, const shout_protocol_impl_t *impl, const void *plan);
274 int                 shout_connection_ref(shout_connection_t *con);
275 int                 shout_connection_unref(shout_connection_t *con);
276 int                 shout_connection_iter(shout_connection_t *con, shout_t *shout);
277 int                 shout_connection_select_tlsmode(shout_connection_t *con, int tlsmode);
278 int                 shout_connection_set_nonblocking(shout_connection_t *con, unsigned int nonblocking);
279 int                 shout_connection_set_wait_timeout(shout_connection_t *con, shout_t *shout, uint64_t timeout /* [ms] */);
280 int                 shout_connection_get_wait_timeout_happened(shout_connection_t *con, shout_t *shout); /* returns SHOUTERR_* or > 0 for true */
281 int                 shout_connection_connect(shout_connection_t *con, shout_t *shout);
282 int                 shout_connection_disconnect(shout_connection_t *con);
283 ssize_t             shout_connection_send(shout_connection_t *con, shout_t *shout, const void *buf, size_t len);
284 ssize_t             shout_connection_get_sendq(shout_connection_t *con, shout_t *shout);
285 int                 shout_connection_starttls(shout_connection_t *con, shout_t *shout);
286 int                 shout_connection_set_error(shout_connection_t *con, int error);
287 int                 shout_connection_get_error(shout_connection_t *con);
288 int                 shout_connection_transfer_error(shout_connection_t *con, shout_t *shout);
289 int                 shout_connection_control(shout_connection_t *con, shout_control_t control, ...);
290 int                 shout_connection_set_callback(shout_connection_t *con, shout_connection_callback_t callback, void *userdata);
291 
292 #ifdef HAVE_OPENSSL
293 typedef int (*shout_tls_callback_t)(shout_tls_t *tls, shout_event_t event, void *userdata, va_list ap);
294 
295 shout_tls_t *shout_tls_new(shout_t *self, sock_t socket);
296 int          shout_tls_try_connect(shout_tls_t *tls);
297 int          shout_tls_close(shout_tls_t *tls);
298 ssize_t      shout_tls_read(shout_tls_t *tls, void *buf, size_t len);
299 ssize_t      shout_tls_write(shout_tls_t *tls, const void *buf, size_t len);
300 int          shout_tls_recoverable(shout_tls_t *tls);
301 int          shout_tls_get_peer_certificate(shout_tls_t *tls, char **buf);
302 int          shout_tls_get_peer_certificate_chain(shout_tls_t *tls, char **buf);
303 int          shout_tls_set_callback(shout_tls_t *tls, shout_tls_callback_t callback, void *userdata);
304 #endif
305 
306 /* protocols */
307 extern const shout_protocol_impl_t *shout_http_impl;
308 extern const shout_protocol_impl_t *shout_xaudiocast_impl;
309 extern const shout_protocol_impl_t *shout_icy_impl;
310 extern const shout_protocol_impl_t *shout_roaraudio_impl;
311 
312 shout_connection_return_state_t shout_get_xaudiocast_response(shout_t *self, shout_connection_t *connection);
313 shout_connection_return_state_t shout_parse_xaudiocast_response(shout_t *self, shout_connection_t *connection);
314 
315 /* containers */
316 int shout_open_ogg(shout_t *self);
317 int shout_open_mp3(shout_t *self);
318 int shout_open_webm(shout_t *self);
319 
320 #endif /* __LIBSHOUT_SHOUT_PRIVATE_H__ */
321