Browse Source

pianod: Add Pandora Radio player daemon

   * Integrate as OpenWrt daemon
   * Build with PolarSSL (replaces GNUTLS)
   * Add optional client WebUI
   * Fix some socket failure handling and segfaults

Signed-off-by: Ted Hess <thess@kitschensync.net>
Ted Hess 10 years ago
parent
commit
1ba6028cc1

+ 110
- 0
sound/pianod/Makefile View File

@@ -0,0 +1,110 @@
1
+#
2
+# Copyright (C) 2015 OpenWrt.org
3
+#
4
+# This is free software, licensed under the GNU General Public License v2.
5
+# See /LICENSE for more information.
6
+#
7
+
8
+include $(TOPDIR)/rules.mk
9
+
10
+PKG_NAME:=pianod
11
+PKG_VERSION:=173
12
+PKG_RELEASE:=2
13
+
14
+PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz
15
+PKG_SOURCE_URL:=http://deviousfish.com/Downloads/pianod/
16
+PKG_MD5SUM:=be0cec19ea6df1c4bc6c1cac8e253445
17
+
18
+PKG_MAINTAINER:=Ted Hess <thess@kitschensync.net>
19
+
20
+PKG_LICENSE:=MIT VARIOUS
21
+PKG_LICENSE_FILES:=COPYING
22
+
23
+PKG_FIXUP:=autoreconf
24
+PKG_INSTALL:=1
25
+
26
+include $(INCLUDE_DIR)/package.mk
27
+
28
+define Package/pianod
29
+  SECTION:=sound
30
+  CATEGORY:=Sound
31
+  DEPENDS:=+libao +libfaad2 +libmad +libpolarssl +libjson-c +libgcrypt +libpthread
32
+  TITLE:=Pandora radio daemon
33
+  USERID:=pianod=88:pianod=88
34
+  URL:=http://deviousfish.com/pianod/
35
+endef
36
+
37
+define Package/pianod/description
38
+  pianod is a Pandora music player client with line-oriented and Websocket control interfaces.
39
+  A simple protocol makes for easy clients, mix scripting, integration with a
40
+  home automation system, use as multiple-user music system for home or office.
41
+  Documentation and configuration information can be found at:
42
+      http://deviousfish.com/pianod/
43
+endef
44
+
45
+define Package/pianod-client
46
+  SECTION:=sound
47
+  CATEGORY:=Sound
48
+  DEPENDS:=+pianod
49
+  TITLE:=Pandora radio daemon WebUI
50
+  URL:=http://deviousfish.com/pianod/
51
+endef
52
+
53
+define Package/pianod-client/description
54
+  Web client UI and remote player viewer for pianod
55
+  Examples --- (Note: The viewer.* files need not be on the pianod host)
56
+  Main interface: http://pianod-host:4446/pianod
57
+  Remote viewer: file:///<path>/viewer.html?server=pianod-host:4446  --or--
58
+                 http://pianod-host:4446/pianod/viewer.html?server=pianod-host:4446
59
+endef
60
+
61
+CONFIGURE_ARGS+= --with-polarssl
62
+
63
+PIANOD_CLIENT:=pianod-client-compiled-51.tar.gz
64
+
65
+define Download/pianod-client
66
+  URL:=$(PKG_SOURCE_URL)/Devel
67
+  FILE:=$(PIANOD_CLIENT)
68
+  MD5SUM:=abbdee5627bcee6a00c8304da8b4e2e7
69
+endef
70
+
71
+define Package/pianod/conffiles
72
+/etc/pianod/startscript
73
+/etc/pianod/users
74
+endef
75
+
76
+define Build/Prepare
77
+    $(call Build/Prepare/Default)
78
+    ifeq ($(CONFIG_PACKAGE_pianod-client),y)
79
+	$(eval $(call Download,pianod-client))
80
+	mkdir -p $(PKG_BUILD_DIR)/pianod-client
81
+	$(TAR) -xf $(DL_DIR)/$(PIANOD_CLIENT) --strip=1 -C $(PKG_BUILD_DIR)/pianod-client
82
+    endif
83
+endef
84
+
85
+define Package/pianod-client/Configure
86
+endef
87
+
88
+define Package/pianod-client/Compile
89
+endef
90
+
91
+define Package/pianod/install
92
+	$(INSTALL_DIR) $(1)/usr/bin
93
+	$(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/bin/pianod $(1)/usr/bin/
94
+# These scripts need ksh (install mksh and link)
95
+#	$(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/bin/piano $(1)/usr/bin/
96
+#	$(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/bin/runmix $(1)/usr/bin/
97
+
98
+	$(INSTALL_DIR) $(1)/etc/pianod
99
+	$(INSTALL_DATA) $(PKG_BUILD_DIR)/contrib/startscript-example $(1)/etc/pianod/startscript
100
+	$(INSTALL_DIR) $(1)/etc/init.d
101
+	$(INSTALL_BIN) ./files/pianod.init $(1)/etc/init.d/pianod
102
+endef
103
+
104
+define Package/pianod-client/install
105
+	$(INSTALL_DIR) $(1)/www/pianod
106
+	$(INSTALL_DATA) $(PKG_BUILD_DIR)/pianod-client/*.{html,js,gif,jpeg,css} $(1)/www/pianod/
107
+endef
108
+
109
+$(eval $(call BuildPackage,pianod))
110
+$(eval $(call BuildPackage,pianod-client))

+ 42
- 0
sound/pianod/files/pianod.init View File

@@ -0,0 +1,42 @@
1
+#!/bin/sh /etc/rc.common
2
+# Copyright (C) 2015 OpenWrt.org
3
+
4
+NAME=pianod
5
+START=95
6
+
7
+USE_PROCD=1
8
+
9
+PD_USER=$NAME
10
+PD_STARTSCRIPT=/etc/$NAME/startscript
11
+PD_PASSWDFILE=/etc/$NAME/users
12
+PD_WEBUI=/www/$NAME
13
+
14
+start_service() {
15
+	# Take group ownership of audio devices
16
+	chown root:$NAME /dev/snd/* /dev/mixer /dev/dsp
17
+	chmod 664 /dev/snd/* /dev/mixer /dev/dsp
18
+
19
+	procd_open_instance
20
+
21
+	procd_set_param command "/usr/bin/$NAME"
22
+
23
+	procd_append_param command -n $PD_USER
24
+	procd_append_param command -i "$PD_STARTSCRIPT"
25
+	procd_append_param command -u "$PD_PASSWDFILE"
26
+	[ -d "$PD_WEBUI" ] && procd_append_param command -c "$PD_WEBUI"
27
+	# No HTTPS support without certificates
28
+	procd_append_param command -s 0
29
+
30
+	procd_close_instance
31
+}
32
+
33
+# Wait for service to exit and release sockets
34
+reload_service() {
35
+	stop
36
+	sleep 2
37
+	start
38
+}
39
+
40
+restart() {
41
+	reload_service
42
+}

+ 29
- 0
sound/pianod/patches/005-Fix_IPV6_socket_handling.patch View File

@@ -0,0 +1,29 @@
1
+--- a/src/libwaitress/waitress.c
2
++++ b/src/libwaitress/waitress.c
3
+@@ -813,7 +813,14 @@ static WaitressReturn_t WaitressConnect
4
+ 					sizeof (sockopt));
5
+ 
6
+ 			/* non-blocking connect will return immediately */
7
+-			connect (sock, gacurr->ai_addr, gacurr->ai_addrlen);
8
++			if (connect (sock, gacurr->ai_addr, gacurr->ai_addrlen) == -1) {
9
++				// Error if not in-progress or immediate success
10
++				if (errno != EINPROGRESS) {
11
++					// Close socket and try alternatives
12
++					close (sock);
13
++					continue;
14
++				}
15
++			}
16
+ 
17
+ 			pollres = WaitressPollLoop (sock, POLLOUT, waith->timeout);
18
+ 			if (pollres == 0) {
19
+--- a/src/libfootball/fb_service.c
20
++++ b/src/libfootball/fb_service.c
21
+@@ -111,6 +111,8 @@ static bool fb_setup_socket (FB_SERVICE
22
+ 		service->socket [which] = 0;
23
+ 	} else {
24
+         fb_perror ("socket");
25
++        // Element must be zero (not -1)
26
++        service->socket [which] = 0;
27
+ 	};
28
+ 	return false;
29
+ }

+ 42
- 0
sound/pianod/patches/010-Configure_add_SSL_options.patch View File

@@ -0,0 +1,42 @@
1
+--- a/configure.ac
2
++++ b/configure.ac
3
+@@ -31,8 +31,6 @@ AC_CHECK_LIB([pthread], [pthread_create]
4
+ # with it, but don't consider it an error.
5
+ # PKG_CHECK_MODULES only validates that pkg-config returns stuff; it doesn't
6
+ # validate that these are correct, so check lib to make sure they're right.
7
+-PKG_CHECK_MODULES([gnutls], [gnutls],,
8
+-	[AC_MSG_WARN([No pkg-config for libgnutls])])
9
+ PKG_CHECK_MODULES([ao], [ao],,
10
+ 	[AC_MSG_WARN([No pkg-config for libao])])
11
+ PKG_CHECK_MODULES([mad], [mad],,
12
+@@ -42,12 +40,28 @@ PKG_CHECK_MODULES([json], [json-c],,
13
+ 		[PKG_CHECK_MODULES([json], [json0],,
14
+ 			[AC_MSG_WARN([No pkg-config for json-c (aka libjson0, libjson)])])])])
15
+ 
16
++
17
+ # Network communication stuff:
18
+ AC_CHECK_LIB([gcrypt], [gcry_cipher_open],,
19
+ 	[AC_MSG_ERROR([Cannot find required library: libgcrypt],1)])
20
+-AC_CHECK_LIB([gnutls], [gnutls_record_recv],,
21
++# Check for SSL option
22
++AC_ARG_WITH(polarssl, [  --with-polarssl	Build waitress with PolarSSL (default GNUTLS)], [
23
++  AC_MSG_RESULT(>>Using PolarSSL)
24
++  HAS_POLARSSL=1
25
++  AC_DEFINE([USE_POLARSSL], 1, [Build for PolarSSL])
26
++  PKG_CHECK_MODULES([polarssl], [polarssl],,
27
++		[AC_MSG_WARN([No pkg-config for libpolarssl])])
28
++  AC_CHECK_LIB([polarssl], [ssl_set_session],,
29
++		[AC_MSG_ERROR([Cannot find required library: libpolarssl (aka polarssl)],1)])] )
30
++AM_CONDITIONAL([USE_POLARSSL],[test "x$HAS_POLARSSL" = "x1"])
31
++
32
++if test "x$HAS_POLARSSL" != x1 ; then
33
++  PKG_CHECK_MODULES([gnutls], [gnutls],,
34
++	[AC_MSG_WARN([No pkg-config for libgnutls])])
35
++  AC_CHECK_LIB([gnutls], [gnutls_record_recv],,
36
+ 	[AC_MSG_ERROR([Cannot find required library: libgnutls (aka gnutls)],1)])
37
+-AC_CHECK_FUNCS(gnutls_transport_set_int2 gnutls_sec_param_to_pk_bits)
38
++  AC_CHECK_FUNCS(gnutls_transport_set_int2 gnutls_sec_param_to_pk_bits)
39
++fi
40
+ 
41
+ # Bloody json library may be linked via -ljson, or -ljson-c depending on
42
+ # the platform.  Try both.

+ 59
- 0
sound/pianod/patches/020-Use_package_config_h_for_all_modules.patch View File

@@ -0,0 +1,59 @@
1
+--- a/src/libpiano/config.h
2
++++ /dev/null
3
+@@ -1 +0,0 @@
4
+-#define PACKAGE "libpiano"
5
+--- a/src/libwaitress/config.h
6
++++ /dev/null
7
+@@ -1 +0,0 @@
8
+-#define PACKAGE "libwaitress"
9
+--- a/src/libpiano/piano.h
10
++++ b/src/libpiano/piano.h
11
+@@ -39,6 +39,8 @@ THE SOFTWARE.
12
+  * http://pan-do-ra-api.wikia.com
13
+  */
14
+ 
15
++#define LIBPIANO_NAME "libpiano"
16
++
17
+ #define PIANO_RPC_HOST "tuner.pandora.com"
18
+ #define PIANO_RPC_PATH "/services/json/?"
19
+ 
20
+--- a/src/libwaitress/waitress.c
21
++++ b/src/libwaitress/waitress.c
22
+@@ -922,14 +922,14 @@ static WaitressReturn_t WaitressSendRequ
23
+ 	if (WaitressProxyEnabled (waith) && !waith->url.tls) {
24
+ 		snprintf (buf, WAITRESS_BUFFER_SIZE,
25
+ 			"%s http://%s:%s/%s HTTP/" WAITRESS_HTTP_VERSION "\r\n"
26
+-			"Host: %s\r\nUser-Agent: " PACKAGE "\r\nConnection: Close\r\n",
27
++			"Host: %s\r\nUser-Agent: " LIBWAITRESS_NAME "\r\nConnection: Close\r\n",
28
+ 			(waith->method == WAITRESS_METHOD_GET ? "GET" : "POST"),
29
+ 			waith->url.host,
30
+ 			WaitressDefaultPort (&waith->url), path, waith->url.host);
31
+ 	} else {
32
+ 		snprintf (buf, WAITRESS_BUFFER_SIZE,
33
+ 			"%s /%s HTTP/" WAITRESS_HTTP_VERSION "\r\n"
34
+-			"Host: %s\r\nUser-Agent: " PACKAGE "\r\nConnection: Close\r\n",
35
++			"Host: %s\r\nUser-Agent: " LIBWAITRESS_NAME "\r\nConnection: Close\r\n",
36
+ 			(waith->method == WAITRESS_METHOD_GET ? "GET" : "POST"),
37
+ 			path, waith->url.host);
38
+ 	}
39
+--- a/src/libwaitress/waitress.h
40
++++ b/src/libwaitress/waitress.h
41
+@@ -29,6 +29,8 @@ THE SOFTWARE.
42
+ #include <stdbool.h>
43
+ #include <gnutls/gnutls.h>
44
+ 
45
++#define LIBWAITRESS_NAME "libwaitress"
46
++
47
+ #define WAITRESS_BUFFER_SIZE 10*1024
48
+ 
49
+ typedef enum {
50
+--- a/src/libpiano/request.c
51
++++ b/src/libpiano/request.c
52
+@@ -40,6 +40,7 @@ THE SOFTWARE.
53
+ #include <stdio.h>
54
+ #include <string.h>
55
+ /* needed for urlencode */
56
++#include <config.h>
57
+ #include <waitress.h>
58
+ 
59
+ #include "piano.h"

+ 344
- 0
sound/pianod/patches/030-Waitress_add_polarssl_variant.patch View File

@@ -0,0 +1,344 @@
1
+--- a/src/libwaitress/waitress.h
2
++++ b/src/libwaitress/waitress.h
3
+@@ -27,7 +27,12 @@ THE SOFTWARE.
4
+ #include <stdlib.h>
5
+ #include <unistd.h>
6
+ #include <stdbool.h>
7
++
8
++#if defined(USE_POLARSSL)
9
++typedef struct _polarssl_ctx polarssl_ctx;
10
++#else
11
+ #include <gnutls/gnutls.h>
12
++#endif
13
+ 
14
+ #define LIBWAITRESS_NAME "libwaitress"
15
+ 
16
+@@ -102,8 +107,9 @@ typedef struct {
17
+ 	WaitressUrl_t url;
18
+ 	WaitressUrl_t proxy;
19
+ 
20
++#if !defined(USE_POLARSSL)
21
+ 	gnutls_certificate_credentials_t tlsCred;
22
+-
23
++#endif
24
+ 	/* per-request data */
25
+ 	struct {
26
+ 		int sockfd;
27
+@@ -121,7 +127,11 @@ typedef struct {
28
+ 		WaitressReturn_t (*read) (void *, char *, const size_t, size_t *);
29
+ 		WaitressReturn_t (*write) (void *, const char *, const size_t);
30
+ 
31
++#if defined(USE_POLARSSL)
32
++		polarssl_ctx* sslCtx;
33
++#else
34
+ 		gnutls_session_t tlsSession;
35
++#endif
36
+ 	} request;
37
+ } WaitressHandle_t;
38
+ 
39
+--- a/src/pianod.c
40
++++ b/src/pianod.c
41
+@@ -531,8 +531,11 @@ static bool initialize_libraries (APPSTA
42
+ 	gcry_check_version (NULL);
43
+ 	gcry_control (GCRYCTL_DISABLE_SECMEM, 0);
44
+ 	gcry_control (GCRYCTL_INITIALIZATION_FINISHED, 0);
45
++
46
++#if !defined(USE_POLARSSL)
47
+ 	int crystatus = gnutls_global_init ();
48
+ 	if (crystatus == GNUTLS_E_SUCCESS) {
49
++#endif
50
+ 		PianoReturn_t status = PianoInit (&app->ph, app->settings.partnerUser, app->settings.partnerPassword,
51
+ 										  app->settings.device, app->settings.inkey, app->settings.outkey);
52
+ 		if (status == PIANO_RET_OK) {
53
+@@ -545,11 +548,13 @@ static bool initialize_libraries (APPSTA
54
+ 		} else {
55
+ 			flog (LOG_ERROR, "initialize_libraries: PianoInit: %s", PianoErrorToStr (status));
56
+ 		}
57
++#if !defined(USE_POLARSSL)
58
+ 		gnutls_global_deinit ();
59
+ 	} else {
60
+ 		flog (LOG_ERROR, "initialize_libraries: gnutls_global_init: %s", gcry_strerror (crystatus));
61
+ 
62
+ 	}
63
++#endif
64
+ 	return false;
65
+ }
66
+ 
67
+@@ -728,7 +733,9 @@ int main (int argc, char **argv) {
68
+ 		PianoDestroyPlaylist (app.song_history);
69
+ 		PianoDestroyPlaylist (app.playlist);
70
+ 		WaitressFree (&app.waith);
71
++#if !defined(USE_POLARSSL)
72
+ 		gnutls_global_deinit ();
73
++#endif
74
+ 		settings_destroy (&app.settings);
75
+ 	}
76
+ 	
77
+--- a/src/libwaitress/waitress.c
78
++++ b/src/libwaitress/waitress.c
79
+@@ -41,11 +41,33 @@ THE SOFTWARE.
80
+ #include <assert.h>
81
+ #include <stdint.h>
82
+ 
83
+-#include <gnutls/x509.h>
84
+ 
85
+ #include "config.h"
86
+ #include "waitress.h"
87
+ 
88
++#if defined(USE_POLARSSL)
89
++
90
++#include <polarssl/ssl.h>
91
++#include <polarssl/entropy.h>
92
++#include <polarssl/ctr_drbg.h>
93
++#include <polarssl/x509.h>
94
++#include <polarssl/sha1.h>
95
++
96
++struct _polarssl_ctx
97
++{
98
++	ssl_context		ssl;
99
++	ssl_session		session;
100
++	entropy_context		entrophy;
101
++	ctr_drbg_context	rnd;
102
++};
103
++
104
++#else
105
++
106
++// Use gnutls by default (USE_POLARSSL not defined)
107
++#include <gnutls/x509.h>
108
++
109
++#endif
110
++
111
+ #define strcaseeq(a,b) (strcasecmp(a,b) == 0)
112
+ #define WAITRESS_HTTP_VERSION "1.1"
113
+ 
114
+@@ -56,6 +78,13 @@ typedef struct {
115
+ 
116
+ static WaitressReturn_t WaitressReceiveHeaders (WaitressHandle_t *, size_t *);
117
+ 
118
++// gnutls wants (void *) and polarssl want (unsigned char *)
119
++#if defined(USE_POLARSSL)
120
++#define BUFFER_CAST unsigned char
121
++#else
122
++#define BUFFER_CAST void
123
++#endif
124
++
125
+ #define READ_RET(buf, count, size) \
126
+ 		if ((wRet = waith->request.read (waith, buf, count, size)) != \
127
+ 				WAITRESS_RET_OK) { \
128
+@@ -444,7 +473,7 @@ static int WaitressPollLoop (int fd, sho
129
+  *	@param write count bytes
130
+  *	@return number of written bytes or -1 on error
131
+  */
132
+-static ssize_t WaitressPollWrite (void *data, const void *buf, size_t count) {
133
++static ssize_t WaitressPollWrite (void *data, const BUFFER_CAST *buf, size_t count) {
134
+ 	int pollres = -1;
135
+ 	ssize_t retSize;
136
+ 	WaitressHandle_t *waith = data;
137
+@@ -478,13 +507,20 @@ static WaitressReturn_t WaitressOrdinary
138
+ 	return waith->request.readWriteRet;
139
+ }
140
+ 
141
+-static WaitressReturn_t WaitressGnutlsWrite (void *data, const char *buf,
142
++static WaitressReturn_t WaitressTlsWrite (void *data, const char *buf,
143
+ 		const size_t size) {
144
+ 	WaitressHandle_t *waith = data;
145
++#if defined(USE_POLARSSL)
146
++
147
++	if (ssl_write (&waith->request.sslCtx->ssl, buf, size) < 0) {
148
++		return WAITRESS_RET_TLS_WRITE_ERR;
149
++	}
150
++#else
151
+ 
152
+ 	if (gnutls_record_send (waith->request.tlsSession, buf, size) < 0) {
153
+ 		return WAITRESS_RET_TLS_WRITE_ERR;
154
+ 	}
155
++#endif
156
+ 	return waith->request.readWriteRet;
157
+ }
158
+ 
159
+@@ -494,7 +530,7 @@ static WaitressReturn_t WaitressGnutlsWr
160
+  *	@param buffer size
161
+  *	@return number of read bytes or -1 on error
162
+  */
163
+-static ssize_t WaitressPollRead (void *data, void *buf, size_t count) {
164
++static ssize_t WaitressPollRead (void *data, BUFFER_CAST *buf, size_t count) {
165
+ 	int pollres = -1;
166
+ 	ssize_t retSize;
167
+ 	WaitressHandle_t *waith = data;
168
+@@ -531,16 +567,34 @@ static WaitressReturn_t WaitressOrdinary
169
+ 	return waith->request.readWriteRet;
170
+ }
171
+ 
172
+-static WaitressReturn_t WaitressGnutlsRead (void *data, char *buf,
173
++static WaitressReturn_t WaitressTlsRead (void *data, char *buf,
174
+ 		const size_t size, size_t *retSize) {
175
+ 	WaitressHandle_t *waith = data;
176
+ 
177
++#if defined(USE_POLARSSL)
178
++	int ret;
179
++
180
++	*retSize = 0;
181
++	waith->request.readWriteRet = WAITRESS_RET_OK;
182
++	ret = ssl_read (&waith->request.sslCtx->ssl, buf, size);
183
++
184
++	if (ret < 0) {
185
++		if (ret != POLARSSL_ERR_SSL_PEER_CLOSE_NOTIFY) {
186
++			waith->request.readWriteRet = WAITRESS_RET_TLS_READ_ERR;
187
++		}
188
++
189
++		return waith->request.readWriteRet;
190
++	}
191
++
192
++	*retSize = ret;
193
++#else
194
+ 	ssize_t ret = gnutls_record_recv (waith->request.tlsSession, buf, size);
195
+ 	if (ret < 0) {
196
+ 		return WAITRESS_RET_TLS_READ_ERR;
197
+ 	} else {
198
+ 		*retSize = ret;
199
+ 	}
200
++#endif
201
+ 	return waith->request.readWriteRet;
202
+ }
203
+ 
204
+@@ -727,10 +781,28 @@ static int WaitressParseStatusline (cons
205
+ /*	verify server certificate
206
+  */
207
+ static WaitressReturn_t WaitressTlsVerify (const WaitressHandle_t *waith) {
208
++
209
++#if defined(USE_POLARSSL)
210
++	unsigned char fingerprint[20];
211
++
212
++	const x509_crt* cert = ssl_get_peer_cert (&waith->request.sslCtx->ssl);
213
++
214
++	if (NULL == cert) {
215
++		return WAITRESS_RET_TLS_HANDSHAKE_ERR;
216
++	}
217
++
218
++	sha1 (cert->raw.p, cert->raw.len, fingerprint);
219
++
220
++	if (memcmp (fingerprint, waith->tlsFingerprint, sizeof (fingerprint)) != 0) {
221
++		return WAITRESS_RET_TLS_FINGERPRINT_MISMATCH;
222
++	}
223
++
224
++#else
225
+ 	gnutls_session_t session = waith->request.tlsSession;
226
+ 	unsigned int certListSize;
227
+ 	const gnutls_datum_t *certList;
228
+ 	gnutls_x509_crt_t cert;
229
++	char fingerprint[20];
230
+ 
231
+ 	if (gnutls_certificate_type_get (session) != GNUTLS_CRT_X509) {
232
+ 		return WAITRESS_RET_TLS_HANDSHAKE_ERR;
233
+@@ -750,7 +822,6 @@ static WaitressReturn_t WaitressTlsVerif
234
+ 		return WAITRESS_RET_TLS_HANDSHAKE_ERR;
235
+ 	}
236
+ 
237
+-	char fingerprint[20];
238
+ 	size_t fingerprintSize = sizeof (fingerprint);
239
+ 	if (gnutls_x509_crt_get_fingerprint (cert, GNUTLS_DIG_SHA1, fingerprint,
240
+ 			&fingerprintSize) != 0) {
241
+@@ -763,7 +834,7 @@ static WaitressReturn_t WaitressTlsVerif
242
+ 	}
243
+ 
244
+ 	gnutls_x509_crt_deinit (cert);
245
+-
246
++#endif
247
+ 	return WAITRESS_RET_OK;
248
+ }
249
+ 
250
+@@ -807,11 +878,6 @@ static WaitressReturn_t WaitressConnect
251
+ 			/* we need shorter timeouts for connect() */
252
+ 			fcntl (sock, F_SETFL, O_NONBLOCK);
253
+ 
254
+-			/* increase socket receive buffer */
255
+-			const int sockopt = 256*1024;
256
+-			setsockopt (sock, SOL_SOCKET, SO_RCVBUF, &sockopt,
257
+-					sizeof (sockopt));
258
+-
259
+ 			/* non-blocking connect will return immediately */
260
+ 			if (connect (sock, gacurr->ai_addr, gacurr->ai_addrlen) == -1) {
261
+ 				// Error if not in-progress or immediate success
262
+@@ -880,6 +946,11 @@ static WaitressReturn_t WaitressConnect
263
+ 			}
264
+ 		}
265
+ 
266
++#if defined(USE_POLARSSL)
267
++		if (ssl_handshake (&waith->request.sslCtx->ssl) != 0) {
268
++			return WAITRESS_RET_TLS_HANDSHAKE_ERR;
269
++		}
270
++#else
271
+ 		/* Ignore return code as connection will likely still succeed */
272
+ 		gnutls_server_name_set (waith->request.tlsSession, GNUTLS_NAME_DNS,
273
+ 				waith->url.host, strlen (waith->url.host));
274
+@@ -887,14 +958,15 @@ static WaitressReturn_t WaitressConnect
275
+ 		if (gnutls_handshake (waith->request.tlsSession) != GNUTLS_E_SUCCESS) {
276
+ 			return WAITRESS_RET_TLS_HANDSHAKE_ERR;
277
+ 		}
278
++#endif
279
+ 
280
+ 		if ((wRet = WaitressTlsVerify (waith)) != WAITRESS_RET_OK) {
281
+ 			return wRet;
282
+ 		}
283
+ 
284
+ 		/* now we can talk encrypted */
285
+-		waith->request.read = WaitressGnutlsRead;
286
+-		waith->request.write = WaitressGnutlsWrite;
287
++		waith->request.read = WaitressTlsRead;
288
++		waith->request.write = WaitressTlsWrite;
289
+ 	}
290
+ 
291
+ 	return WAITRESS_RET_OK;
292
+@@ -1120,6 +1192,21 @@ WaitressReturn_t WaitressFetchCall (Wait
293
+ 	waith->request.contentLengthKnown = false;
294
+ 
295
+ 	if (waith->url.tls) {
296
++#if defined(USE_POLARSSL)
297
++		waith->request.sslCtx = calloc (1, sizeof(polarssl_ctx));
298
++
299
++		entropy_init (&waith->request.sslCtx->entrophy);
300
++		ctr_drbg_init (&waith->request.sslCtx->rnd, entropy_func, &waith->request.sslCtx->entrophy, "libwaitress", 11);
301
++		ssl_init (&waith->request.sslCtx->ssl);
302
++
303
++		ssl_set_endpoint (&waith->request.sslCtx->ssl, SSL_IS_CLIENT);
304
++		ssl_set_authmode (&waith->request.sslCtx->ssl, SSL_VERIFY_NONE);
305
++		ssl_set_rng (&waith->request.sslCtx->ssl, ctr_drbg_random, &waith->request.sslCtx->rnd);
306
++		ssl_set_session (&waith->request.sslCtx->ssl, &waith->request.sslCtx->session);
307
++		ssl_set_bio (&waith->request.sslCtx->ssl,
308
++			     WaitressPollRead, waith,
309
++			     WaitressPollWrite, waith);
310
++#else
311
+ 		gnutls_init (&waith->request.tlsSession, GNUTLS_CLIENT);
312
+ 		gnutls_set_default_priority (waith->request.tlsSession);
313
+ 
314
+@@ -1137,6 +1224,7 @@ WaitressReturn_t WaitressFetchCall (Wait
315
+ 				WaitressPollRead);
316
+ 		gnutls_transport_set_push_function (waith->request.tlsSession,
317
+ 				WaitressPollWrite);
318
++#endif
319
+ 	}
320
+ 
321
+ 	/* buffer is required for connect already */
322
+@@ -1148,15 +1236,22 @@ WaitressReturn_t WaitressFetchCall (Wait
323
+ 		if ((wRet = WaitressSendRequest (waith)) == WAITRESS_RET_OK) {
324
+ 			wRet = WaitressReceiveResponse (waith);
325
+ 		}
326
++#if !defined(USE_POLARSSL)
327
+ 		if (waith->url.tls) {
328
+ 			gnutls_bye (waith->request.tlsSession, GNUTLS_SHUT_RDWR);
329
+ 		}
330
++#endif
331
+ 	}
332
+ 
333
+ 	/* cleanup */
334
+ 	if (waith->url.tls) {
335
++#if defined(USE_POLARSSL)
336
++		ssl_free (&waith->request.sslCtx->ssl);
337
++		free (waith->request.sslCtx);
338
++#else
339
+ 		gnutls_deinit (waith->request.tlsSession);
340
+ 		gnutls_certificate_free_credentials (waith->tlsCred);
341
++#endif
342
+ 	}
343
+ 	if (waith->request.sockfd != -1) {
344
+ 		close (waith->request.sockfd);