+ char *servername = var_GetNonEmptyString (p_session, "tls-server-name");
+ if (servername == NULL )
+ msg_Err (p_session, "server name missing for TLS session");
+
+ p_sys->session.psz_hostname = servername;
+ gnutls_server_name_set (p_sys->session.session, GNUTLS_NAME_DNS,
+ servername, strlen (servername));
+
+ return VLC_SUCCESS;
+
+s_error:
+ gnutls_deinit (p_sys->session.session);
+ gnutls_certificate_free_credentials (p_sys->x509_cred);
+error:
+ gnutls_Deinit (obj);
+ free (p_sys);
+ return VLC_EGENERIC;
+}
+
+
+static void CloseClient (vlc_object_t *obj)
+{
+ tls_session_t *client = (tls_session_t *)obj;
+ tls_client_sys_t *p_sys = (tls_client_sys_t *)(client->p_sys);
+
+ if (p_sys->session.b_handshaked == VLC_TRUE)
+ gnutls_bye (p_sys->session.session, GNUTLS_SHUT_WR);
+ gnutls_deinit (p_sys->session.session);
+ /* credentials must be free'd *after* gnutls_deinit() */
+ gnutls_certificate_free_credentials (p_sys->x509_cred);
+
+ gnutls_Deinit (obj);
+ free (p_sys->session.psz_hostname);
+ free (p_sys);
+}
+
+
+/**
+ * Server-side TLS
+ */
+struct tls_server_sys_t
+{
+ gnutls_certificate_credentials_t x509_cred;
+ gnutls_dh_params_t dh_params;
+
+ struct saved_session_t *p_cache;
+ struct saved_session_t *p_store;
+ int i_cache_size;
+ vlc_mutex_t cache_lock;
+
+ int (*pf_handshake) (tls_session_t *);
+};
+
+
+/**
+ * TLS session resumption callbacks (server-side)
+ */
+#define MAX_SESSION_ID 32
+#define MAX_SESSION_DATA 1024
+
+typedef struct saved_session_t
+{
+ char id[MAX_SESSION_ID];
+ char data[MAX_SESSION_DATA];
+
+ unsigned i_idlen;
+ unsigned i_datalen;
+} saved_session_t;
+
+
+static int cb_store( void *p_server, gnutls_datum key, gnutls_datum data )
+{
+ tls_server_sys_t *p_sys = ((tls_server_t *)p_server)->p_sys;
+
+ if( ( p_sys->i_cache_size == 0 )
+ || ( key.size > MAX_SESSION_ID )
+ || ( data.size > MAX_SESSION_DATA ) )
+ return -1;
+
+ vlc_mutex_lock( &p_sys->cache_lock );
+
+ memcpy( p_sys->p_store->id, key.data, key.size);
+ memcpy( p_sys->p_store->data, data.data, data.size );
+ p_sys->p_store->i_idlen = key.size;
+ p_sys->p_store->i_datalen = data.size;
+
+ p_sys->p_store++;
+ if( ( p_sys->p_store - p_sys->p_cache ) == p_sys->i_cache_size )
+ p_sys->p_store = p_sys->p_cache;
+
+ vlc_mutex_unlock( &p_sys->cache_lock );
+
+ return 0;
+}
+
+
+static gnutls_datum cb_fetch( void *p_server, gnutls_datum key )
+{
+ static const gnutls_datum_t err_datum = { NULL, 0 };
+ tls_server_sys_t *p_sys = ((tls_server_t *)p_server)->p_sys;
+ saved_session_t *p_session, *p_end;
+
+ p_session = p_sys->p_cache;
+ p_end = p_session + p_sys->i_cache_size;
+
+ vlc_mutex_lock( &p_sys->cache_lock );
+
+ while( p_session < p_end )