diff --git a/sound/pianod/Makefile b/sound/pianod/Makefile new file mode 100644 index 000000000..758805c70 --- /dev/null +++ b/sound/pianod/Makefile @@ -0,0 +1,110 @@ +# +# Copyright (C) 2015 OpenWrt.org +# +# This is free software, licensed under the GNU General Public License v2. +# See /LICENSE for more information. +# + +include $(TOPDIR)/rules.mk + +PKG_NAME:=pianod +PKG_VERSION:=173 +PKG_RELEASE:=2 + +PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz +PKG_SOURCE_URL:=http://deviousfish.com/Downloads/pianod/ +PKG_MD5SUM:=be0cec19ea6df1c4bc6c1cac8e253445 + +PKG_MAINTAINER:=Ted Hess + +PKG_LICENSE:=MIT VARIOUS +PKG_LICENSE_FILES:=COPYING + +PKG_FIXUP:=autoreconf +PKG_INSTALL:=1 + +include $(INCLUDE_DIR)/package.mk + +define Package/pianod + SECTION:=sound + CATEGORY:=Sound + DEPENDS:=+libao +libfaad2 +libmad +libpolarssl +libjson-c +libgcrypt +libpthread + TITLE:=Pandora radio daemon + USERID:=pianod=88:pianod=88 + URL:=http://deviousfish.com/pianod/ +endef + +define Package/pianod/description + pianod is a Pandora music player client with line-oriented and Websocket control interfaces. + A simple protocol makes for easy clients, mix scripting, integration with a + home automation system, use as multiple-user music system for home or office. + Documentation and configuration information can be found at: + http://deviousfish.com/pianod/ +endef + +define Package/pianod-client + SECTION:=sound + CATEGORY:=Sound + DEPENDS:=+pianod + TITLE:=Pandora radio daemon WebUI + URL:=http://deviousfish.com/pianod/ +endef + +define Package/pianod-client/description + Web client UI and remote player viewer for pianod + Examples --- (Note: The viewer.* files need not be on the pianod host) + Main interface: http://pianod-host:4446/pianod + Remote viewer: file:////viewer.html?server=pianod-host:4446 --or-- + http://pianod-host:4446/pianod/viewer.html?server=pianod-host:4446 +endef + +CONFIGURE_ARGS+= --with-polarssl + +PIANOD_CLIENT:=pianod-client-compiled-51.tar.gz + +define Download/pianod-client + URL:=$(PKG_SOURCE_URL)/Devel + FILE:=$(PIANOD_CLIENT) + MD5SUM:=abbdee5627bcee6a00c8304da8b4e2e7 +endef + +define Package/pianod/conffiles +/etc/pianod/startscript +/etc/pianod/users +endef + +define Build/Prepare + $(call Build/Prepare/Default) + ifeq ($(CONFIG_PACKAGE_pianod-client),y) + $(eval $(call Download,pianod-client)) + mkdir -p $(PKG_BUILD_DIR)/pianod-client + $(TAR) -xf $(DL_DIR)/$(PIANOD_CLIENT) --strip=1 -C $(PKG_BUILD_DIR)/pianod-client + endif +endef + +define Package/pianod-client/Configure +endef + +define Package/pianod-client/Compile +endef + +define Package/pianod/install + $(INSTALL_DIR) $(1)/usr/bin + $(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/bin/pianod $(1)/usr/bin/ +# These scripts need ksh (install mksh and link) +# $(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/bin/piano $(1)/usr/bin/ +# $(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/bin/runmix $(1)/usr/bin/ + + $(INSTALL_DIR) $(1)/etc/pianod + $(INSTALL_DATA) $(PKG_BUILD_DIR)/contrib/startscript-example $(1)/etc/pianod/startscript + $(INSTALL_DIR) $(1)/etc/init.d + $(INSTALL_BIN) ./files/pianod.init $(1)/etc/init.d/pianod +endef + +define Package/pianod-client/install + $(INSTALL_DIR) $(1)/www/pianod + $(INSTALL_DATA) $(PKG_BUILD_DIR)/pianod-client/*.{html,js,gif,jpeg,css} $(1)/www/pianod/ +endef + +$(eval $(call BuildPackage,pianod)) +$(eval $(call BuildPackage,pianod-client)) diff --git a/sound/pianod/files/pianod.init b/sound/pianod/files/pianod.init new file mode 100644 index 000000000..b232944e5 --- /dev/null +++ b/sound/pianod/files/pianod.init @@ -0,0 +1,42 @@ +#!/bin/sh /etc/rc.common +# Copyright (C) 2015 OpenWrt.org + +NAME=pianod +START=95 + +USE_PROCD=1 + +PD_USER=$NAME +PD_STARTSCRIPT=/etc/$NAME/startscript +PD_PASSWDFILE=/etc/$NAME/users +PD_WEBUI=/www/$NAME + +start_service() { + # Take group ownership of audio devices + chown root:$NAME /dev/snd/* /dev/mixer /dev/dsp + chmod 664 /dev/snd/* /dev/mixer /dev/dsp + + procd_open_instance + + procd_set_param command "/usr/bin/$NAME" + + procd_append_param command -n $PD_USER + procd_append_param command -i "$PD_STARTSCRIPT" + procd_append_param command -u "$PD_PASSWDFILE" + [ -d "$PD_WEBUI" ] && procd_append_param command -c "$PD_WEBUI" + # No HTTPS support without certificates + procd_append_param command -s 0 + + procd_close_instance +} + +# Wait for service to exit and release sockets +reload_service() { + stop + sleep 2 + start +} + +restart() { + reload_service +} diff --git a/sound/pianod/patches/005-Fix_IPV6_socket_handling.patch b/sound/pianod/patches/005-Fix_IPV6_socket_handling.patch new file mode 100644 index 000000000..68f7c365d --- /dev/null +++ b/sound/pianod/patches/005-Fix_IPV6_socket_handling.patch @@ -0,0 +1,29 @@ +--- a/src/libwaitress/waitress.c ++++ b/src/libwaitress/waitress.c +@@ -813,7 +813,14 @@ static WaitressReturn_t WaitressConnect + sizeof (sockopt)); + + /* non-blocking connect will return immediately */ +- connect (sock, gacurr->ai_addr, gacurr->ai_addrlen); ++ if (connect (sock, gacurr->ai_addr, gacurr->ai_addrlen) == -1) { ++ // Error if not in-progress or immediate success ++ if (errno != EINPROGRESS) { ++ // Close socket and try alternatives ++ close (sock); ++ continue; ++ } ++ } + + pollres = WaitressPollLoop (sock, POLLOUT, waith->timeout); + if (pollres == 0) { +--- a/src/libfootball/fb_service.c ++++ b/src/libfootball/fb_service.c +@@ -111,6 +111,8 @@ static bool fb_setup_socket (FB_SERVICE + service->socket [which] = 0; + } else { + fb_perror ("socket"); ++ // Element must be zero (not -1) ++ service->socket [which] = 0; + }; + return false; + } diff --git a/sound/pianod/patches/010-Configure_add_SSL_options.patch b/sound/pianod/patches/010-Configure_add_SSL_options.patch new file mode 100644 index 000000000..2c2677965 --- /dev/null +++ b/sound/pianod/patches/010-Configure_add_SSL_options.patch @@ -0,0 +1,42 @@ +--- a/configure.ac ++++ b/configure.ac +@@ -31,8 +31,6 @@ AC_CHECK_LIB([pthread], [pthread_create] + # with it, but don't consider it an error. + # PKG_CHECK_MODULES only validates that pkg-config returns stuff; it doesn't + # validate that these are correct, so check lib to make sure they're right. +-PKG_CHECK_MODULES([gnutls], [gnutls],, +- [AC_MSG_WARN([No pkg-config for libgnutls])]) + PKG_CHECK_MODULES([ao], [ao],, + [AC_MSG_WARN([No pkg-config for libao])]) + PKG_CHECK_MODULES([mad], [mad],, +@@ -42,12 +40,28 @@ PKG_CHECK_MODULES([json], [json-c],, + [PKG_CHECK_MODULES([json], [json0],, + [AC_MSG_WARN([No pkg-config for json-c (aka libjson0, libjson)])])])]) + ++ + # Network communication stuff: + AC_CHECK_LIB([gcrypt], [gcry_cipher_open],, + [AC_MSG_ERROR([Cannot find required library: libgcrypt],1)]) +-AC_CHECK_LIB([gnutls], [gnutls_record_recv],, ++# Check for SSL option ++AC_ARG_WITH(polarssl, [ --with-polarssl Build waitress with PolarSSL (default GNUTLS)], [ ++ AC_MSG_RESULT(>>Using PolarSSL) ++ HAS_POLARSSL=1 ++ AC_DEFINE([USE_POLARSSL], 1, [Build for PolarSSL]) ++ PKG_CHECK_MODULES([polarssl], [polarssl],, ++ [AC_MSG_WARN([No pkg-config for libpolarssl])]) ++ AC_CHECK_LIB([polarssl], [ssl_set_session],, ++ [AC_MSG_ERROR([Cannot find required library: libpolarssl (aka polarssl)],1)])] ) ++AM_CONDITIONAL([USE_POLARSSL],[test "x$HAS_POLARSSL" = "x1"]) ++ ++if test "x$HAS_POLARSSL" != x1 ; then ++ PKG_CHECK_MODULES([gnutls], [gnutls],, ++ [AC_MSG_WARN([No pkg-config for libgnutls])]) ++ AC_CHECK_LIB([gnutls], [gnutls_record_recv],, + [AC_MSG_ERROR([Cannot find required library: libgnutls (aka gnutls)],1)]) +-AC_CHECK_FUNCS(gnutls_transport_set_int2 gnutls_sec_param_to_pk_bits) ++ AC_CHECK_FUNCS(gnutls_transport_set_int2 gnutls_sec_param_to_pk_bits) ++fi + + # Bloody json library may be linked via -ljson, or -ljson-c depending on + # the platform. Try both. diff --git a/sound/pianod/patches/020-Use_package_config_h_for_all_modules.patch b/sound/pianod/patches/020-Use_package_config_h_for_all_modules.patch new file mode 100644 index 000000000..25569ccc2 --- /dev/null +++ b/sound/pianod/patches/020-Use_package_config_h_for_all_modules.patch @@ -0,0 +1,59 @@ +--- a/src/libpiano/config.h ++++ /dev/null +@@ -1 +0,0 @@ +-#define PACKAGE "libpiano" +--- a/src/libwaitress/config.h ++++ /dev/null +@@ -1 +0,0 @@ +-#define PACKAGE "libwaitress" +--- a/src/libpiano/piano.h ++++ b/src/libpiano/piano.h +@@ -39,6 +39,8 @@ THE SOFTWARE. + * http://pan-do-ra-api.wikia.com + */ + ++#define LIBPIANO_NAME "libpiano" ++ + #define PIANO_RPC_HOST "tuner.pandora.com" + #define PIANO_RPC_PATH "/services/json/?" + +--- a/src/libwaitress/waitress.c ++++ b/src/libwaitress/waitress.c +@@ -922,14 +922,14 @@ static WaitressReturn_t WaitressSendRequ + if (WaitressProxyEnabled (waith) && !waith->url.tls) { + snprintf (buf, WAITRESS_BUFFER_SIZE, + "%s http://%s:%s/%s HTTP/" WAITRESS_HTTP_VERSION "\r\n" +- "Host: %s\r\nUser-Agent: " PACKAGE "\r\nConnection: Close\r\n", ++ "Host: %s\r\nUser-Agent: " LIBWAITRESS_NAME "\r\nConnection: Close\r\n", + (waith->method == WAITRESS_METHOD_GET ? "GET" : "POST"), + waith->url.host, + WaitressDefaultPort (&waith->url), path, waith->url.host); + } else { + snprintf (buf, WAITRESS_BUFFER_SIZE, + "%s /%s HTTP/" WAITRESS_HTTP_VERSION "\r\n" +- "Host: %s\r\nUser-Agent: " PACKAGE "\r\nConnection: Close\r\n", ++ "Host: %s\r\nUser-Agent: " LIBWAITRESS_NAME "\r\nConnection: Close\r\n", + (waith->method == WAITRESS_METHOD_GET ? "GET" : "POST"), + path, waith->url.host); + } +--- a/src/libwaitress/waitress.h ++++ b/src/libwaitress/waitress.h +@@ -29,6 +29,8 @@ THE SOFTWARE. + #include + #include + ++#define LIBWAITRESS_NAME "libwaitress" ++ + #define WAITRESS_BUFFER_SIZE 10*1024 + + typedef enum { +--- a/src/libpiano/request.c ++++ b/src/libpiano/request.c +@@ -40,6 +40,7 @@ THE SOFTWARE. + #include + #include + /* needed for urlencode */ ++#include + #include + + #include "piano.h" diff --git a/sound/pianod/patches/030-Waitress_add_polarssl_variant.patch b/sound/pianod/patches/030-Waitress_add_polarssl_variant.patch new file mode 100644 index 000000000..de40b35c9 --- /dev/null +++ b/sound/pianod/patches/030-Waitress_add_polarssl_variant.patch @@ -0,0 +1,344 @@ +--- a/src/libwaitress/waitress.h ++++ b/src/libwaitress/waitress.h +@@ -27,7 +27,12 @@ THE SOFTWARE. + #include + #include + #include ++ ++#if defined(USE_POLARSSL) ++typedef struct _polarssl_ctx polarssl_ctx; ++#else + #include ++#endif + + #define LIBWAITRESS_NAME "libwaitress" + +@@ -102,8 +107,9 @@ typedef struct { + WaitressUrl_t url; + WaitressUrl_t proxy; + ++#if !defined(USE_POLARSSL) + gnutls_certificate_credentials_t tlsCred; +- ++#endif + /* per-request data */ + struct { + int sockfd; +@@ -121,7 +127,11 @@ typedef struct { + WaitressReturn_t (*read) (void *, char *, const size_t, size_t *); + WaitressReturn_t (*write) (void *, const char *, const size_t); + ++#if defined(USE_POLARSSL) ++ polarssl_ctx* sslCtx; ++#else + gnutls_session_t tlsSession; ++#endif + } request; + } WaitressHandle_t; + +--- a/src/pianod.c ++++ b/src/pianod.c +@@ -531,8 +531,11 @@ static bool initialize_libraries (APPSTA + gcry_check_version (NULL); + gcry_control (GCRYCTL_DISABLE_SECMEM, 0); + gcry_control (GCRYCTL_INITIALIZATION_FINISHED, 0); ++ ++#if !defined(USE_POLARSSL) + int crystatus = gnutls_global_init (); + if (crystatus == GNUTLS_E_SUCCESS) { ++#endif + PianoReturn_t status = PianoInit (&app->ph, app->settings.partnerUser, app->settings.partnerPassword, + app->settings.device, app->settings.inkey, app->settings.outkey); + if (status == PIANO_RET_OK) { +@@ -545,11 +548,13 @@ static bool initialize_libraries (APPSTA + } else { + flog (LOG_ERROR, "initialize_libraries: PianoInit: %s", PianoErrorToStr (status)); + } ++#if !defined(USE_POLARSSL) + gnutls_global_deinit (); + } else { + flog (LOG_ERROR, "initialize_libraries: gnutls_global_init: %s", gcry_strerror (crystatus)); + + } ++#endif + return false; + } + +@@ -728,7 +733,9 @@ int main (int argc, char **argv) { + PianoDestroyPlaylist (app.song_history); + PianoDestroyPlaylist (app.playlist); + WaitressFree (&app.waith); ++#if !defined(USE_POLARSSL) + gnutls_global_deinit (); ++#endif + settings_destroy (&app.settings); + } + +--- a/src/libwaitress/waitress.c ++++ b/src/libwaitress/waitress.c +@@ -41,11 +41,33 @@ THE SOFTWARE. + #include + #include + +-#include + + #include "config.h" + #include "waitress.h" + ++#if defined(USE_POLARSSL) ++ ++#include ++#include ++#include ++#include ++#include ++ ++struct _polarssl_ctx ++{ ++ ssl_context ssl; ++ ssl_session session; ++ entropy_context entrophy; ++ ctr_drbg_context rnd; ++}; ++ ++#else ++ ++// Use gnutls by default (USE_POLARSSL not defined) ++#include ++ ++#endif ++ + #define strcaseeq(a,b) (strcasecmp(a,b) == 0) + #define WAITRESS_HTTP_VERSION "1.1" + +@@ -56,6 +78,13 @@ typedef struct { + + static WaitressReturn_t WaitressReceiveHeaders (WaitressHandle_t *, size_t *); + ++// gnutls wants (void *) and polarssl want (unsigned char *) ++#if defined(USE_POLARSSL) ++#define BUFFER_CAST unsigned char ++#else ++#define BUFFER_CAST void ++#endif ++ + #define READ_RET(buf, count, size) \ + if ((wRet = waith->request.read (waith, buf, count, size)) != \ + WAITRESS_RET_OK) { \ +@@ -444,7 +473,7 @@ static int WaitressPollLoop (int fd, sho + * @param write count bytes + * @return number of written bytes or -1 on error + */ +-static ssize_t WaitressPollWrite (void *data, const void *buf, size_t count) { ++static ssize_t WaitressPollWrite (void *data, const BUFFER_CAST *buf, size_t count) { + int pollres = -1; + ssize_t retSize; + WaitressHandle_t *waith = data; +@@ -478,13 +507,20 @@ static WaitressReturn_t WaitressOrdinary + return waith->request.readWriteRet; + } + +-static WaitressReturn_t WaitressGnutlsWrite (void *data, const char *buf, ++static WaitressReturn_t WaitressTlsWrite (void *data, const char *buf, + const size_t size) { + WaitressHandle_t *waith = data; ++#if defined(USE_POLARSSL) ++ ++ if (ssl_write (&waith->request.sslCtx->ssl, buf, size) < 0) { ++ return WAITRESS_RET_TLS_WRITE_ERR; ++ } ++#else + + if (gnutls_record_send (waith->request.tlsSession, buf, size) < 0) { + return WAITRESS_RET_TLS_WRITE_ERR; + } ++#endif + return waith->request.readWriteRet; + } + +@@ -494,7 +530,7 @@ static WaitressReturn_t WaitressGnutlsWr + * @param buffer size + * @return number of read bytes or -1 on error + */ +-static ssize_t WaitressPollRead (void *data, void *buf, size_t count) { ++static ssize_t WaitressPollRead (void *data, BUFFER_CAST *buf, size_t count) { + int pollres = -1; + ssize_t retSize; + WaitressHandle_t *waith = data; +@@ -531,16 +567,34 @@ static WaitressReturn_t WaitressOrdinary + return waith->request.readWriteRet; + } + +-static WaitressReturn_t WaitressGnutlsRead (void *data, char *buf, ++static WaitressReturn_t WaitressTlsRead (void *data, char *buf, + const size_t size, size_t *retSize) { + WaitressHandle_t *waith = data; + ++#if defined(USE_POLARSSL) ++ int ret; ++ ++ *retSize = 0; ++ waith->request.readWriteRet = WAITRESS_RET_OK; ++ ret = ssl_read (&waith->request.sslCtx->ssl, buf, size); ++ ++ if (ret < 0) { ++ if (ret != POLARSSL_ERR_SSL_PEER_CLOSE_NOTIFY) { ++ waith->request.readWriteRet = WAITRESS_RET_TLS_READ_ERR; ++ } ++ ++ return waith->request.readWriteRet; ++ } ++ ++ *retSize = ret; ++#else + ssize_t ret = gnutls_record_recv (waith->request.tlsSession, buf, size); + if (ret < 0) { + return WAITRESS_RET_TLS_READ_ERR; + } else { + *retSize = ret; + } ++#endif + return waith->request.readWriteRet; + } + +@@ -727,10 +781,28 @@ static int WaitressParseStatusline (cons + /* verify server certificate + */ + static WaitressReturn_t WaitressTlsVerify (const WaitressHandle_t *waith) { ++ ++#if defined(USE_POLARSSL) ++ unsigned char fingerprint[20]; ++ ++ const x509_crt* cert = ssl_get_peer_cert (&waith->request.sslCtx->ssl); ++ ++ if (NULL == cert) { ++ return WAITRESS_RET_TLS_HANDSHAKE_ERR; ++ } ++ ++ sha1 (cert->raw.p, cert->raw.len, fingerprint); ++ ++ if (memcmp (fingerprint, waith->tlsFingerprint, sizeof (fingerprint)) != 0) { ++ return WAITRESS_RET_TLS_FINGERPRINT_MISMATCH; ++ } ++ ++#else + gnutls_session_t session = waith->request.tlsSession; + unsigned int certListSize; + const gnutls_datum_t *certList; + gnutls_x509_crt_t cert; ++ char fingerprint[20]; + + if (gnutls_certificate_type_get (session) != GNUTLS_CRT_X509) { + return WAITRESS_RET_TLS_HANDSHAKE_ERR; +@@ -750,7 +822,6 @@ static WaitressReturn_t WaitressTlsVerif + return WAITRESS_RET_TLS_HANDSHAKE_ERR; + } + +- char fingerprint[20]; + size_t fingerprintSize = sizeof (fingerprint); + if (gnutls_x509_crt_get_fingerprint (cert, GNUTLS_DIG_SHA1, fingerprint, + &fingerprintSize) != 0) { +@@ -763,7 +834,7 @@ static WaitressReturn_t WaitressTlsVerif + } + + gnutls_x509_crt_deinit (cert); +- ++#endif + return WAITRESS_RET_OK; + } + +@@ -807,11 +878,6 @@ static WaitressReturn_t WaitressConnect + /* we need shorter timeouts for connect() */ + fcntl (sock, F_SETFL, O_NONBLOCK); + +- /* increase socket receive buffer */ +- const int sockopt = 256*1024; +- setsockopt (sock, SOL_SOCKET, SO_RCVBUF, &sockopt, +- sizeof (sockopt)); +- + /* non-blocking connect will return immediately */ + if (connect (sock, gacurr->ai_addr, gacurr->ai_addrlen) == -1) { + // Error if not in-progress or immediate success +@@ -880,6 +946,11 @@ static WaitressReturn_t WaitressConnect + } + } + ++#if defined(USE_POLARSSL) ++ if (ssl_handshake (&waith->request.sslCtx->ssl) != 0) { ++ return WAITRESS_RET_TLS_HANDSHAKE_ERR; ++ } ++#else + /* Ignore return code as connection will likely still succeed */ + gnutls_server_name_set (waith->request.tlsSession, GNUTLS_NAME_DNS, + waith->url.host, strlen (waith->url.host)); +@@ -887,14 +958,15 @@ static WaitressReturn_t WaitressConnect + if (gnutls_handshake (waith->request.tlsSession) != GNUTLS_E_SUCCESS) { + return WAITRESS_RET_TLS_HANDSHAKE_ERR; + } ++#endif + + if ((wRet = WaitressTlsVerify (waith)) != WAITRESS_RET_OK) { + return wRet; + } + + /* now we can talk encrypted */ +- waith->request.read = WaitressGnutlsRead; +- waith->request.write = WaitressGnutlsWrite; ++ waith->request.read = WaitressTlsRead; ++ waith->request.write = WaitressTlsWrite; + } + + return WAITRESS_RET_OK; +@@ -1120,6 +1192,21 @@ WaitressReturn_t WaitressFetchCall (Wait + waith->request.contentLengthKnown = false; + + if (waith->url.tls) { ++#if defined(USE_POLARSSL) ++ waith->request.sslCtx = calloc (1, sizeof(polarssl_ctx)); ++ ++ entropy_init (&waith->request.sslCtx->entrophy); ++ ctr_drbg_init (&waith->request.sslCtx->rnd, entropy_func, &waith->request.sslCtx->entrophy, "libwaitress", 11); ++ ssl_init (&waith->request.sslCtx->ssl); ++ ++ ssl_set_endpoint (&waith->request.sslCtx->ssl, SSL_IS_CLIENT); ++ ssl_set_authmode (&waith->request.sslCtx->ssl, SSL_VERIFY_NONE); ++ ssl_set_rng (&waith->request.sslCtx->ssl, ctr_drbg_random, &waith->request.sslCtx->rnd); ++ ssl_set_session (&waith->request.sslCtx->ssl, &waith->request.sslCtx->session); ++ ssl_set_bio (&waith->request.sslCtx->ssl, ++ WaitressPollRead, waith, ++ WaitressPollWrite, waith); ++#else + gnutls_init (&waith->request.tlsSession, GNUTLS_CLIENT); + gnutls_set_default_priority (waith->request.tlsSession); + +@@ -1137,6 +1224,7 @@ WaitressReturn_t WaitressFetchCall (Wait + WaitressPollRead); + gnutls_transport_set_push_function (waith->request.tlsSession, + WaitressPollWrite); ++#endif + } + + /* buffer is required for connect already */ +@@ -1148,15 +1236,22 @@ WaitressReturn_t WaitressFetchCall (Wait + if ((wRet = WaitressSendRequest (waith)) == WAITRESS_RET_OK) { + wRet = WaitressReceiveResponse (waith); + } ++#if !defined(USE_POLARSSL) + if (waith->url.tls) { + gnutls_bye (waith->request.tlsSession, GNUTLS_SHUT_RDWR); + } ++#endif + } + + /* cleanup */ + if (waith->url.tls) { ++#if defined(USE_POLARSSL) ++ ssl_free (&waith->request.sslCtx->ssl); ++ free (waith->request.sslCtx); ++#else + gnutls_deinit (waith->request.tlsSession); + gnutls_certificate_free_credentials (waith->tlsCred); ++#endif + } + if (waith->request.sockfd != -1) { + close (waith->request.sockfd);