diff --git a/src/xbmsp.c b/src/xbmsp.c
deleted file mode 100644
index a121dd91..00000000
--- a/src/xbmsp.c
+++ /dev/null
@@ -1,1139 +0,0 @@
-/*
- * tvheadend, XBMSP interface
- * Copyright (C) 2008 Andreas Öman
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see .
- */
-
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-
-#include "tvhead.h"
-#include "channels.h"
-#include "subscriptions.h"
-#include "dispatch.h"
-#include "xbmsp.h"
-#include "tcp.h"
-#include "access.h"
-
-#define XBMSP_FILEFORMAT "ts"
-
-static LIST_HEAD(, xbmsp) xbmsp_sessions;
-
-extern AVOutputFormat mpegts_muxer;
-
-
-/**
- * Function for delivery of data.
- * We try to respond to any pending read
- */
-static void
-xbmsp_output_file(void *opaque)
-{
- xbmsp_subscrption_t *xs = opaque;
- tffm_fifo_t *tf = xs->xs_fifo;
- xbmsp_t *xbmsp = xs->xs_xbmsp;
- uint32_t msgid = xs->xs_pending_read_msgid;
- htsbuf_queue_t hq;
- int rem, tlen, len = xs->xs_pending_read_size;
- uint8_t buf[13];
- tffm_fifo_pkt_t *pkt, *n;
-
- if(len == 0 || tf->tf_pktq_len < len)
- return;
-
- tlen = len + 4 + 4 + 1;
-
- buf[0] = tlen >> 24;
- buf[1] = tlen >> 16;
- buf[2] = tlen >> 8;
- buf[3] = tlen;
- buf[4] = XBMSP_PACKET_FILE_CONTENTS;
- buf[5] = msgid >> 24;
- buf[6] = msgid >> 16;
- buf[7] = msgid >> 8;
- buf[8] = msgid;
- buf[9] = len >> 24;
- buf[10] = len >> 16;
- buf[11] = len >> 8;
- buf[12] = len;
-
- htsbuf_queue_init(&hq, 0);
- htsbuf_append(&hq, buf, 13);
-
- while(len > 0) {
- pkt = TAILQ_FIRST(&tf->tf_pktq);
- assert(pkt != NULL);
-
- if(len >= pkt->tfp_pktsize) {
- /* Consume entire packet */
- htsbuf_append(&hq, pkt->tfp_buf, pkt->tfp_pktsize);
- } else {
- /* Partial, create new packet at front with remaining data */
- htsbuf_append(&hq, pkt->tfp_buf, len);
- rem = pkt->tfp_pktsize - len;
- n = malloc(sizeof(tffm_fifo_pkt_t) + rem);
- n->tfp_pktsize = rem;
- memcpy(n->tfp_buf, pkt->tfp_buf + len, rem);
- TAILQ_INSERT_HEAD(&tf->tf_pktq, n, tfp_link);
-
- tf->tf_pktq_len += rem;
- }
- len -= pkt->tfp_pktsize;
- tf->tf_pktq_len -= pkt->tfp_pktsize;
- TAILQ_REMOVE(&tf->tf_pktq, pkt, tfp_link);
- free(pkt);
- }
-
- xs->xs_pending_read_size = 0;
- xs->xs_pending_read_msgid = 0;
- tcp_output_queue(&xbmsp->xbmsp_tcp_session, 0, &hq);
-}
-
-
-
-
-/**
- * Called when a subscription gets/loses access to a transport
- */
-static void
-xbmsp_subscription_callback(struct th_subscription *s,
- subscription_event_t event, void *opaque)
-{
- th_transport_t *t = s->ths_transport;
- xbmsp_subscrption_t *xs = opaque;
- xbmsp_t *xbmsp = xs->xs_xbmsp;
- th_ffmuxer_t *tffm = &xs->xs_tffm;
- th_muxer_t *tm = &tffm->tffm_muxer;
- th_muxstream_t *tms;
- AVFormatContext *fctx;
- int err;
-
- switch(event) {
- case TRANSPORT_AVAILABLE:
- tm->tm_opaque = tffm;
- tm->tm_new_pkt = tffm_packet_input;
-
- xs->xs_fifo = tffm_fifo_create(xbmsp_output_file, xs);
-
- fctx = av_alloc_format_context();
- fctx->oformat = &mpegts_muxer;
-
- err = url_fopen(&fctx->pb, tffm_filename(xs->xs_fifo), URL_WRONLY);
- if(err < 0)
- abort(); /* Should not happen, we've just created the fifo */
-
- tffm_open(tffm, t, fctx, xbmsp->xbmsp_logname);
- LIST_INSERT_HEAD(&t->tht_muxers, tm, tm_transport_link);
- tffm_set_state(tffm, TFFM_WAIT_AUDIO_LOCK);
- break;
-
- case TRANSPORT_UNAVAILABLE:
- LIST_REMOVE(tm, tm_transport_link);
- tffm_close(tffm);
-
- /* Destroy muxstreams, XXX: Should be in tffm_close() */
-
- while((tms = LIST_FIRST(&tm->tm_streams)) != NULL) {
- LIST_REMOVE(tms, tms_muxer_link0);
- free(tms);
- }
- tffm_fifo_destroy(xs->xs_fifo);
- break;
- }
-}
-
-/**
- * Close subscription given by 'handle', free all data
- * If handle == 0, close all.
- * return -1 if we fail to locate it.
- */
-static int
-xbmsp_close_subscription(xbmsp_t *xbmsp, uint32_t handle)
-{
- xbmsp_subscrption_t *xs, *next;
-
- for(xs = LIST_FIRST(&xbmsp->xbmsp_subscriptions); xs != NULL; xs = next) {
- next = LIST_NEXT(xs, xs_link);
-
- if(xs->xs_handle == handle || handle == 0) {
- subscription_unsubscribe(xs->xs_subscription);
- LIST_REMOVE(xs, xs_link);
- free(xs);
-
- if(handle != 0)
- return 0;
- }
- }
-
- return handle == 0 ? 0 : -1;
-}
-
-
-
-/**
- * Add an entry to a dirhandle
- */
-static void
-xbmsp_dir_add_entry(xbmsp_dirhandle_t *xdh, const char *name,
- const char *displayname, const char *type)
-{
- xbmsp_direntry_t *xde;
- char xmlbuf[1000];
-
- xde = malloc(sizeof(xbmsp_direntry_t));
- xde->xde_filename = strdup(name);
-
- snprintf(xmlbuf, sizeof(xmlbuf),
- ""
- "%s"
- "%s"
- "", displayname, type);
-
- xde->xde_xmlmeta = strdup(xmlbuf);
- TAILQ_INSERT_TAIL(&xdh->xdh_entries, xde, xde_link);
-}
-
-/**
- *
- */
-static channel_group_t *
-xbmsp_cur_channel_group(xbmsp_t *xbmsp)
-{
- channel_group_t *tcg;
-
- TAILQ_FOREACH(tcg, &all_channel_groups, tcg_global_link) {
- if(tcg->tcg_hidden)
- continue;
- if(!strcmp(tcg->tcg_name, xbmsp->xbmsp_wd))
- return tcg;
- }
- return NULL;
-}
-
-
-/**
- * Populate a dirhandle with direntries based on the current
- * working directory
- */
-static int
-xbmsp_dir_populate(xbmsp_t *xbmsp, xbmsp_dirhandle_t *xdh, const char *filter)
-{
- channel_group_t *tcg;
- channel_t *ch;
- char name[100];
-
- if(xbmsp->xbmsp_wd[0] == 0) {
- /* root dir */
-
- TAILQ_FOREACH(tcg, &all_channel_groups, tcg_global_link) {
- if(tcg->tcg_hidden)
- continue;
-
- if(filter != NULL && strcmp(tcg->tcg_name, filter))
- continue;
-
- xbmsp_dir_add_entry(xdh, tcg->tcg_name, tcg->tcg_name, "directory");
- }
- } else {
-
- if((tcg = xbmsp_cur_channel_group(xbmsp)) == NULL)
- return -1;
-
- TAILQ_FOREACH(ch, &tcg->tcg_channels, ch_group_link) {
- if(LIST_FIRST(&ch->ch_transports) == NULL)
- continue;
-
- if(filter != NULL && strcmp(ch->ch_name, filter))
- continue;
-
- snprintf(name, sizeof(name), "%s." XBMSP_FILEFORMAT, ch->ch_name);
-
- xbmsp_dir_add_entry(xdh, name, ch->ch_name, "stream");
- }
- }
- return 0;
-}
-
-/**
- * Close dirhandle given by 'handle', free all data
- * If handle == 0, close all.
- * Return -1 if we fail to locate it.
- */
-static int
-xbmsp_close_dirhandle(xbmsp_t *xbmsp, uint32_t handle)
-{
- xbmsp_dirhandle_t *xdh, *next;
- xbmsp_direntry_t *xde;
-
- for(xdh = LIST_FIRST(&xbmsp->xbmsp_dirhandles); xdh != NULL; xdh = next) {
- next = LIST_NEXT(xdh, xdh_link);
- if(xdh->xdh_handle == handle || handle == 0) {
-
- while((xde = TAILQ_FIRST(&xdh->xdh_entries)) != NULL) {
- TAILQ_REMOVE(&xdh->xdh_entries, xde, xde_link);
- free((void *)xde->xde_filename);
- free((void *)xde->xde_xmlmeta);
- free(xde);
- }
- LIST_REMOVE(xdh, xdh_link);
- free(xdh);
-
- if(handle != 0)
- return 0;
- }
- }
-
- return handle == 0 ? 0 : -1;
-}
-
-
-
-
-/**
- * xbmsp_cdup() - Change to one directory up (cd ..)
- */
-static const char *
-xbmsp_cdup(xbmsp_t *xbmsp)
-{
- char *wd = xbmsp->xbmsp_wd;
- char *r;
-
- r = strrchr(wd, '/');
- if(r == NULL) {
- *wd = 0;
- } else {
- *r = 0;
- }
- return NULL;
-}
-
-/**
- * xbmsp_cdroot() - Change to root (cd /)
- */
-static const char *
-xbmsp_cdroot(xbmsp_t *xbmsp)
-{
- free(xbmsp->xbmsp_wd);
- xbmsp->xbmsp_wd = strdup("");
- return NULL;
-}
-
-/**
- * xbmsp_cddown() - Change to root (cd dir)
- */
-static const char *
-xbmsp_cddown(xbmsp_t *xbmsp, const char *dir)
-{
- channel_group_t *tcg;
-
- if(xbmsp->xbmsp_wd[0] == 0) {
- /* root dir */
-
- TAILQ_FOREACH(tcg, &all_channel_groups, tcg_global_link) {
- if(tcg->tcg_hidden)
- continue;
-
- if(!strcmp(dir, tcg->tcg_name))
- break;
- }
-
- if(tcg == NULL)
- return "%s -- No such file or directory";
-
- free(xbmsp->xbmsp_wd);
- xbmsp->xbmsp_wd = strdup(tcg->tcg_name);
- return NULL;
- }
- return "%s -- No such file or directory";
-}
-
-
-
-/**
- * Send a message back
- */
-static void
-xbmsp_send_msg(xbmsp_t *xbmsp, uint8_t type, uint32_t msgid,
- uint8_t *payload, int payloadlen)
-{
- uint8_t buf[9];
- htsbuf_queue_t hq;
-
- int tlen = payloadlen + 5;
-
- buf[0] = tlen >> 24;
- buf[1] = tlen >> 16;
- buf[2] = tlen >> 8;
- buf[3] = tlen;
- buf[4] = type;
- buf[5] = msgid >> 24;
- buf[6] = msgid >> 16;
- buf[7] = msgid >> 8;
- buf[8] = msgid;
-
- htsbuf_queue_init(&hq, 0);
- htsbuf_append(&hq, buf, 9);
- if(payloadlen > 0) {
- if(payload == NULL) {
- payload = alloca(payloadlen);
- memset(payload, 0, payloadlen);
- }
- htsbuf_append(&hq, payload, payloadlen);
- }
- tcp_output_queue(&xbmsp->xbmsp_tcp_session, 0, &hq);
-}
-
-
-/**
- * Send an error code back
- */
-static void
-xbmsp_send_err(xbmsp_t *xbmsp, uint32_t msgid, uint8_t errcode,
- const char *errfmt, ...)
-{
- int slen;
- uint8_t *buf;
- char errbuf[200];
- va_list ap;
-
- va_start(ap, errfmt);
- vsnprintf(errbuf, sizeof(errbuf), errfmt, ap);
- va_end(ap);
-
- tvhlog(LOG_INFO, "xbmsp", "%s: %s", xbmsp->xbmsp_logname, errbuf);
-
- slen = strlen(errbuf);
-
- buf = alloca(slen + 5);
- buf[0] = errcode;
- buf[1] = slen >> 24;
- buf[2] = slen >> 16;
- buf[3] = slen >> 8;
- buf[4] = slen;
- memcpy(buf + 5, errbuf, slen);
-
- xbmsp_send_msg(xbmsp, XBMSP_PACKET_ERROR, msgid, buf, slen + 5);
-}
-
-/**
- * Send a handle id back
- */
-static void
-xbmsp_send_handle(xbmsp_t *xbmsp, uint32_t msgid, uint32_t handle)
-{
- uint8_t buf[4];
-
- buf[0] = handle >> 24;
- buf[1] = handle >> 16;
- buf[2] = handle >> 8;
- buf[3] = handle;
-
- xbmsp_send_msg(xbmsp, XBMSP_PACKET_HANDLE, msgid, buf, 4);
-}
-
-
-/**
- * Extract a string from the current buffer adjusting the pointers
- * sent in
- */
-static char *
-xbmsp_extract_string(xbmsp_t *xbmsp, uint8_t **bufp, int *lenp)
-{
- uint8_t *buf = *bufp;
- uint32_t slen;
- char *str;
- if(*lenp < 4)
- return NULL;
-
- slen = (buf[0] << 24) | (buf[1] << 16) | (buf[2] << 8) | buf[3];
-
- if(slen == 0)
- return strdup(""); /* empty string */
-
- *lenp -= 4;
- buf += 4;
-
- if(slen > *lenp)
- return NULL; /* String exceeds past end of buffer */
-
- str = malloc(slen + 1);
- memcpy(str, buf, slen);
- str[slen] = 0;
- *bufp = buf + slen;
- return str;
-}
-
-/**
- * Extract an u32 from the current buffer and adjust the pointers
- * sent in
- */
-static int
-xbmsp_extract_u32(xbmsp_t *xbmsp, uint8_t **bufp, int *lenp, uint32_t *res)
-{
- uint8_t *buf = *bufp;
- if(*lenp < 4)
- return -1;
-
- *res = (buf[0] << 24) | (buf[1] << 16) | (buf[2] << 8) | buf[3];
- *lenp -= 4;
- *bufp += 4;
- return 0;
-}
-
-/**
- * Handle XBMSP_PACKET_AUTHENTICATION_INIT
- */
-static int
-xbmsp_input_authentication_init(xbmsp_t *xbmsp, uint32_t msgid,
- uint8_t *buf, int len)
-{
- char *authtype;
-
- authtype = xbmsp_extract_string(xbmsp, &buf, &len);
- if(authtype == NULL)
- return EBADMSG;
-
- if(strcmp(authtype, "password")) {
- xbmsp_send_err(xbmsp, msgid, XBMSP_ERROR_AUTHENTICATION_FAILED,
- "Authentication \"%s\" type not supported", authtype);
- free(authtype);
- return 0;
- }
- free(authtype);
-
- /* Generate handle and send a positive response back. */
- xbmsp->xbmsp_handle_tally++;
- xbmsp_send_handle(xbmsp, msgid, xbmsp->xbmsp_handle_tally);
- return 0;
-}
-
-/**
- * Handle XBMSP_PACKET_AUTHENTICATE
- */
-static int
-xbmsp_input_authenticate(xbmsp_t *xbmsp, uint32_t msgid,
- uint8_t *buf, int len)
-{
- char *username, *password;
- uint32_t handle;
-
- if(xbmsp_extract_u32(xbmsp, &buf, &len, &handle))
- return EBADMSG;
- if((username = xbmsp_extract_string(xbmsp, &buf, &len)) == NULL)
- return EBADMSG;
- if((password = xbmsp_extract_string(xbmsp, &buf, &len)) == NULL) {
- free(username);
- return EBADMSG;
- }
-
- snprintf(xbmsp->xbmsp_logname, sizeof(xbmsp->xbmsp_logname),
- "xbmsp: %s @ %s", username, tcp_logname(&xbmsp->xbmsp_tcp_session));
-
- if(access_verify(username, password,
- (struct sockaddr *)&xbmsp->xbmsp_tcp_session.tcp_peer_addr,
- ACCESS_STREAMING) != 0) {
- xbmsp_send_err(xbmsp, msgid, XBMSP_ERROR_AUTHENTICATION_FAILED,
- "Access denied");
- return 0;
- }
- xbmsp->xbmsp_authenticated = 1;
- /* Auth ok */
- xbmsp_send_msg(xbmsp, XBMSP_PACKET_OK, msgid, NULL, 0);
-
- free(username);
- free(password);
- return 0;
-}
-
-/**
- * Handle XBMSP_PACKET_FILELIST_OPEN
- */
-static int
-xbmsp_input_filelist_open(xbmsp_t *xbmsp, uint32_t msgid,
- uint8_t *buf, int len)
-{
- xbmsp_dirhandle_t *xdh;
-
- xbmsp->xbmsp_handle_tally++;
- xdh = calloc(1, sizeof(xbmsp_dirhandle_t));
- TAILQ_INIT(&xdh->xdh_entries);
- xdh->xdh_handle = xbmsp->xbmsp_handle_tally;
- LIST_INSERT_HEAD(&xbmsp->xbmsp_dirhandles, xdh, xdh_link);
-
- if(xbmsp_dir_populate(xbmsp, xdh, NULL)) {
- xbmsp_send_err(xbmsp, msgid, XBMSP_ERROR_NO_SUCH_FILE,
- "CWD \"%s\" invalid", xbmsp->xbmsp_wd);
- } else {
- xbmsp_send_handle(xbmsp, msgid, xdh->xdh_handle);
- }
- return 0;
-}
-
-/**
- * Send a XBMSP_PACKET_FILE_DATA reply
- */
-static int
-xbmsp_reply_file_data(xbmsp_t *xbmsp, uint32_t msgid, xbmsp_dirhandle_t *xdh,
- const char *single_file)
-{
- xbmsp_direntry_t *xde;
- int len1, len2;
- uint8_t *out;
-
- xde = TAILQ_FIRST(&xdh->xdh_entries);
- if(xde == NULL) {
- if(single_file != NULL) {
- xbmsp_send_err(xbmsp, msgid, XBMSP_ERROR_NO_SUCH_FILE,
- "File \"%s\" not found", single_file);
- } else {
- xbmsp_send_msg(xbmsp, XBMSP_PACKET_FILE_DATA, msgid, NULL, 8);
- }
- return 1;
- }
-
- len1 = strlen(xde->xde_filename);
- len2 = strlen(xde->xde_xmlmeta);
-
- out = alloca(8 + len1 + len2);
-
- out[0] = len1 >> 24;
- out[1] = len1 >> 16;
- out[2] = len1 >> 8;
- out[3] = len1;
-
- memcpy(out + 4, xde->xde_filename, len1);
-
- out[len1 + 4 + 0] = len2 >> 24;
- out[len1 + 4 + 1] = len2 >> 16;
- out[len1 + 4 + 2] = len2 >> 8;
- out[len1 + 4 + 3] = len2;
-
- memcpy(out + 8 + len1, xde->xde_xmlmeta, len2);
-
- xbmsp_send_msg(xbmsp, XBMSP_PACKET_FILE_DATA, msgid, out, 8 + len1 + len2);
-
- TAILQ_REMOVE(&xdh->xdh_entries, xde, xde_link);
- free((void *)xde->xde_filename);
- free((void *)xde->xde_xmlmeta);
- free(xde);
- return 0;
-}
-
-
-
-/**
- * Handle XBMSP_PACKET_FILELIST_READ
- */
-static int
-xbmsp_input_filelist_read(xbmsp_t *xbmsp, uint32_t msgid,
- uint8_t *buf, int len)
-{
- xbmsp_dirhandle_t *xdh;
- uint32_t handle;
-
- if(xbmsp_extract_u32(xbmsp, &buf, &len, &handle))
- return EBADMSG;
-
- LIST_FOREACH(xdh, &xbmsp->xbmsp_dirhandles, xdh_link)
- if(xdh->xdh_handle == handle)
- break;
-
- if(xdh == NULL) {
- xbmsp_send_err(xbmsp, msgid, XBMSP_ERROR_INVALID_HANDLE,
- "Invalid file handle (0x%x)", handle);
- return 0;
- }
-
- if(xbmsp_reply_file_data(xbmsp, msgid, xdh, NULL)) {
- LIST_REMOVE(xdh, xdh_link);
- free(xdh);
- }
- return 0;
-}
-
-/**
- * Handle XBMSP_PACKET_SETCWD
- */
-static int
-xbmsp_input_setcwd(xbmsp_t *xbmsp, uint32_t msgid, uint8_t *buf, int len)
-{
- char *newdir;
- const char *errtxt;
-
- if((newdir = xbmsp_extract_string(xbmsp, &buf, &len)) == NULL)
- return EBADMSG;
-
- if(newdir[0] == 0 || !strcmp(newdir, ".")) {
- /* change to current dir */
- errtxt = NULL;
- } else if(!strcmp(newdir, "..")) {
- /* change to parent dir */
- errtxt = xbmsp_cdup(xbmsp);
- } else if(!strcmp(newdir, "/")) {
- /* change to root */
- errtxt = xbmsp_cdroot(xbmsp);
- } else {
- errtxt = xbmsp_cddown(xbmsp, newdir);
- }
-
- if(errtxt == NULL) {
- xbmsp_send_msg(xbmsp, XBMSP_PACKET_OK, msgid, NULL, 0);
- } else {
- xbmsp_send_err(xbmsp, msgid, XBMSP_ERROR_NO_SUCH_FILE, errtxt, newdir);
- }
-
- free(newdir);
- return 0;
-}
-
-/**
- * Handle XBMSP_PACKET_UPCWD
- */
-static int
-xbmsp_input_upcwd(xbmsp_t *xbmsp, uint32_t msgid, uint8_t *buf, int len)
-{
- const char *errtxt;
- uint32_t levels;
-
- if(xbmsp_extract_u32(xbmsp, &buf, &len, &levels))
- return EBADMSG;
-
- if(levels == 0xffffffff) {
- errtxt = xbmsp_cdroot(xbmsp);
- } else {
- errtxt = NULL;
- while(levels > 0 && errtxt == NULL) {
- levels--;
- errtxt = xbmsp_cdup(xbmsp);
- }
- }
-
- if(errtxt == NULL) {
- xbmsp_send_msg(xbmsp, XBMSP_PACKET_OK, msgid, NULL, 0);
- } else {
- xbmsp_send_err(xbmsp, msgid, XBMSP_ERROR_NO_SUCH_FILE, errtxt);
- }
- return 0;
-}
-
-
-/**
- * Handle XBMSP_PACKET_FILE_INFO
- */
-static int
-xbmsp_input_file_info(xbmsp_t *xbmsp, uint32_t msgid, uint8_t *buf, int len)
-{
- char *fname, *tr;
- xbmsp_dirhandle_t xdh;
-
- if((fname = xbmsp_extract_string(xbmsp, &buf, &len)) == NULL)
- return EBADMSG;
-
- tr = strstr(fname, "." XBMSP_FILEFORMAT);
- if(tr != NULL)
- *tr = 0;
-
- TAILQ_INIT(&xdh.xdh_entries);
- xbmsp_dir_populate(xbmsp, &xdh, fname);
- free(fname);
-
- xbmsp_reply_file_data(xbmsp, msgid, &xdh, fname);
- return 0;
-}
-
-
-
-/**
- * Handle XBMSP_PACKET_FILE_OPEN
- */
-static int
-xbmsp_input_file_open(xbmsp_t *xbmsp, uint32_t msgid, uint8_t *buf, int len)
-{
- char *fname = NULL, *tr;
- channel_group_t *tcg;
- channel_t *ch;
- xbmsp_subscrption_t *xs;
-
- if((fname = xbmsp_extract_string(xbmsp, &buf, &len)) == NULL) {
- return EBADMSG;
- }
-
- tr = strstr(fname, "." XBMSP_FILEFORMAT);
- if(tr != NULL)
- *tr = 0;
-
- if((tcg = xbmsp_cur_channel_group(xbmsp)) == NULL) {
- xbmsp_send_err(xbmsp, msgid, XBMSP_ERROR_NO_SUCH_FILE,
- "Invalid directory \"%s\"", fname);
- free(fname);
- return 0;
- }
-
-
- TAILQ_FOREACH(ch, &tcg->tcg_channels, ch_group_link) {
- if(LIST_FIRST(&ch->ch_transports) == NULL)
- continue;
- if(!strcmp(ch->ch_name, fname))
- break;
- }
-
- if(ch == NULL) {
- xbmsp_send_err(xbmsp, msgid, XBMSP_ERROR_NO_SUCH_FILE,
- "File \"%s\" not found", fname);
- free(fname);
- return 0;
- }
- free(fname);
-
- xs = calloc(1, sizeof(xbmsp_subscrption_t));
-
- xbmsp->xbmsp_handle_tally++;
- xs->xs_handle = xbmsp->xbmsp_handle_tally;
-
- xs->xs_xbmsp = xbmsp;
- xs->xs_subscription = subscription_create(ch, 100, xbmsp->xbmsp_logname,
- xbmsp_subscription_callback, xs, 0);
-
- LIST_INSERT_HEAD(&xbmsp->xbmsp_subscriptions, xs, xs_link);
- xbmsp_send_handle(xbmsp, msgid, xs->xs_handle);
- return 0;
-}
-
-
-/**
- * Handle XBMSP_PACKET_CLOSE
- */
-static int
-xbmsp_input_close(xbmsp_t *xbmsp, uint32_t msgid, uint8_t *buf, int len)
-{
- uint32_t handle;
-
- if(xbmsp_extract_u32(xbmsp, &buf, &len, &handle))
- return EBADMSG;
-
- if(xbmsp_close_dirhandle(xbmsp, handle)) {
- if(xbmsp_close_subscription(xbmsp, handle)) {
- xbmsp_send_err(xbmsp, msgid, XBMSP_ERROR_INVALID_HANDLE,
- "Invalid handle (0x%x)", handle);
- return 0;
- }
- }
- xbmsp_send_msg(xbmsp, XBMSP_PACKET_OK, msgid, NULL, 0);
- return 0;
-}
-
-/**
- * Handle XBMSP_PACKET_CLOSE_ALL
- */
-static int
-xbmsp_input_close_all(xbmsp_t *xbmsp, uint32_t msgid, uint8_t *buf, int len)
-{
- xbmsp_close_dirhandle(xbmsp, 0);
- xbmsp_close_subscription(xbmsp, 0);
-
- xbmsp_send_msg(xbmsp, XBMSP_PACKET_OK, msgid, NULL, 0);
- return 0;
-}
-
-
-/**
- * Handle XBMSP_PACKET_FILE_READ
- */
-static int
-xbmsp_input_file_read(xbmsp_t *xbmsp, uint32_t msgid, uint8_t *buf, int len)
-{
- uint32_t handle, wantlen;
- xbmsp_subscrption_t *xs;
-
- if(xbmsp_extract_u32(xbmsp, &buf, &len, &handle))
- return EBADMSG;
-
- if(xbmsp_extract_u32(xbmsp, &buf, &len, &wantlen))
- return EBADMSG;
-
- LIST_FOREACH(xs, &xbmsp->xbmsp_subscriptions, xs_link)
- if(xs->xs_handle == handle)
- break;
-
- if(xs == NULL) {
- xbmsp_send_err(xbmsp, msgid, XBMSP_ERROR_INVALID_HANDLE,
- "Invalid handle (0x%x)", handle);
- return 0;
- }
-
- if(xs->xs_pending_read_size != 0) {
- xbmsp_send_err(xbmsp, msgid, XBMSP_ERROR_UNSUPPORTED,
- "Read already pending");
- return 0;
- }
-
- xs->xs_pending_read_size = wantlen;
- xs->xs_pending_read_msgid = msgid;
-
- xbmsp_output_file(xs);
- return 0;
-}
-
-
-/**
- * Function for parsing XBMSP 1.0 messages
- */
-static void
-xbmsp_input(xbmsp_t *xbmsp, uint8_t *buf, int len)
-{
- uint8_t msgtype;
- uint32_t msgid;
- int r;
-
- if(len < 5) {
- tcp_disconnect(&xbmsp->xbmsp_tcp_session, EBADMSG);
- return;
- }
-
- msgtype = buf[0];
- msgid = (buf[1] << 24) | (buf[2] << 16) | (buf[3] << 8) | buf[4];
-
- /* Shift to payload */
- buf += 5;
- len -= 5;
-
- if(msgtype != XBMSP_PACKET_AUTHENTICATION_INIT &&
- msgtype != XBMSP_PACKET_AUTHENTICATE &&
- xbmsp->xbmsp_authenticated == 0) {
- xbmsp_send_err(xbmsp, msgid, XBMSP_ERROR_AUTHENTICATION_NEEDED,
- "Authentication needed");
- return;
- }
-
- switch(msgtype) {
- case XBMSP_PACKET_NULL:
- xbmsp_send_msg(xbmsp, XBMSP_PACKET_OK, msgid, NULL, 0);
- r = 0;
- break;
-
- case XBMSP_PACKET_SETCWD:
- r = xbmsp_input_setcwd(xbmsp, msgid, buf, len);
- break;
-
- case XBMSP_PACKET_UPCWD:
- r = xbmsp_input_upcwd(xbmsp, msgid, buf, len);
- break;
-
- case XBMSP_PACKET_FILELIST_OPEN:
- r = xbmsp_input_filelist_open(xbmsp, msgid, buf, len);
- break;
-
- case XBMSP_PACKET_FILELIST_READ:
- r = xbmsp_input_filelist_read(xbmsp, msgid, buf, len);
- break;
-
- case XBMSP_PACKET_FILE_INFO:
- r = xbmsp_input_file_info(xbmsp, msgid, buf, len);
- break;
-
- case XBMSP_PACKET_FILE_OPEN:
- r = xbmsp_input_file_open(xbmsp, msgid, buf, len);
- break;
-
- case XBMSP_PACKET_FILE_READ:
- r = xbmsp_input_file_read(xbmsp, msgid, buf, len);
- break;
-
- case XBMSP_PACKET_CLOSE:
- r = xbmsp_input_close(xbmsp, msgid, buf, len);
- break;
-
- case XBMSP_PACKET_CLOSE_ALL:
- r = xbmsp_input_close_all(xbmsp, msgid, buf, len);
- break;
-
- case XBMSP_PACKET_AUTHENTICATION_INIT:
- r = xbmsp_input_authentication_init(xbmsp, msgid, buf, len);
- break;
-
- case XBMSP_PACKET_AUTHENTICATE:
- r = xbmsp_input_authenticate(xbmsp, msgid, buf, len);
- break;
-
- default:
- xbmsp_send_err(xbmsp, msgid, XBMSP_ERROR_UNSUPPORTED,
- "Unsupported command (%d)", msgtype);
- r = 0;
- break;
- }
-
- if(r)
- tcp_disconnect(&xbmsp->xbmsp_tcp_session, r);
-}
-
-
-
-/*
- *
- */
-static void
-xbmsp_data_input(xbmsp_t *xbmsp)
-{
- tcp_session_t *tcp = &xbmsp->xbmsp_tcp_session;
- int r, l;
-
- switch(xbmsp->xbmsp_state) {
- case XBMSP_STATE_CLIENT_IDENTIFY:
- if(xbmsp->xbmsp_bufptr > 500) {
- tcp_disconnect(tcp, EBADMSG);
- return;
- }
- r = read(tcp->tcp_fd, xbmsp->xbmsp_buf + xbmsp->xbmsp_bufptr, 1);
- if(r < 1) {
- tcp_disconnect(tcp, r == 0 ? ECONNRESET : errno);
- return;
- }
-
- if(xbmsp->xbmsp_buf[xbmsp->xbmsp_bufptr] == 0xa) {
- xbmsp->xbmsp_buf[xbmsp->xbmsp_bufptr] = 0;
- xbmsp->xbmsp_state = XBMSP_STATE_1_0;
- xbmsp->xbmsp_bufptr = 0;
- return;
- }
- xbmsp->xbmsp_bufptr++;
- break;
-
- case XBMSP_STATE_1_0:
-
- if(xbmsp->xbmsp_bufptr < 4) {
- r = read(tcp->tcp_fd, xbmsp->xbmsp_buf + xbmsp->xbmsp_bufptr,
- 4 - xbmsp->xbmsp_bufptr);
- if(r < 1) {
- tcp_disconnect(tcp, r == 0 ? ECONNRESET : errno);
- return;
- }
-
- xbmsp->xbmsp_bufptr += r;
- if(xbmsp->xbmsp_bufptr < 4)
- return;
-
- xbmsp->xbmsp_msglen = (xbmsp->xbmsp_buf[0] << 24) +
- (xbmsp->xbmsp_buf[1] << 16) + (xbmsp->xbmsp_buf[2] << 8) +
- xbmsp->xbmsp_buf[3] + 4;
-
- if(xbmsp->xbmsp_msglen < 9 || xbmsp->xbmsp_msglen > 16 * 1024 * 1024) {
- tcp_disconnect(tcp, EBADMSG);
- return;
- }
-
- if(xbmsp->xbmsp_bufsize < xbmsp->xbmsp_msglen) {
- xbmsp->xbmsp_bufsize = xbmsp->xbmsp_msglen;
- free(xbmsp->xbmsp_buf);
- xbmsp->xbmsp_buf = malloc(xbmsp->xbmsp_bufsize);
- }
- }
-
- l = xbmsp->xbmsp_msglen - xbmsp->xbmsp_bufptr;
-
- r = read(tcp->tcp_fd, xbmsp->xbmsp_buf + xbmsp->xbmsp_bufptr, l);
- if(r < 1) {
- tcp_disconnect(tcp, r == 0 ? ECONNRESET : errno);
- return;
- }
-
- xbmsp->xbmsp_bufptr += r;
-
- if(xbmsp->xbmsp_bufptr == xbmsp->xbmsp_msglen) {
- xbmsp_input(xbmsp, xbmsp->xbmsp_buf + 4, xbmsp->xbmsp_msglen - 4);
- xbmsp->xbmsp_bufptr = 0;
- xbmsp->xbmsp_msglen = 0;
- }
- break;
- }
-}
-
-
-
-/*
- *
- */
-static void
-xbmsp_disconnect(xbmsp_t *xbmsp)
-{
- xbmsp_close_dirhandle(xbmsp, 0);
- xbmsp_close_subscription(xbmsp, 0);
- free(xbmsp->xbmsp_wd);
- free(xbmsp->xbmsp_buf);
- LIST_REMOVE(xbmsp, xbmsp_global_link);
-}
-
-
-/*
- *
- */
-static void
-xbmsp_connect(xbmsp_t *xbmsp)
-{
- LIST_INSERT_HEAD(&xbmsp_sessions, xbmsp, xbmsp_global_link);
-
- xbmsp->xbmsp_wd = strdup(""); /* start in root */
-
- xbmsp->xbmsp_bufsize = 1000;
- xbmsp->xbmsp_buf = malloc(xbmsp->xbmsp_bufsize);
-
- snprintf(xbmsp->xbmsp_logname, sizeof(xbmsp->xbmsp_logname),
- "xbmsp: @ %s", tcp_logname(&xbmsp->xbmsp_tcp_session));
-
- tcp_printf(&xbmsp->xbmsp_tcp_session,
- "XBMSP-1.0 1.0 HTS/Tvheadend\n");
-}
-
-/*
- *
- */
-static void
-xbmsp_tcp_callback(tcpevent_t event, void *tcpsession)
-{
- xbmsp_t *xbmsp = tcpsession;
-
- switch(event) {
- case TCP_CONNECT:
- xbmsp_connect(xbmsp);
- break;
-
- case TCP_DISCONNECT:
- xbmsp_disconnect(xbmsp);
- break;
-
- case TCP_INPUT:
- xbmsp_data_input(xbmsp);
- break;
- }
-}
-
-
-/**
- * Fire up XBMSP server
- */
-void
-xbmsp_start(int port)
-{
- tcp_create_server(port, sizeof(xbmsp_t), "xbmsp", xbmsp_tcp_callback);
-}
diff --git a/src/xbmsp.h b/src/xbmsp.h
deleted file mode 100644
index 19350d20..00000000
--- a/src/xbmsp.h
+++ /dev/null
@@ -1,162 +0,0 @@
-/*
- * tvheadend, XBMSP interface
- * Copyright (C) 2008 Andreas Öman
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see .
- */
-
-#ifndef XBMSP_H_
-#define XBMSP_H_
-
-#include "tcp.h"
-#include "ffmuxer.h"
-
-/**
- * Server source messages
- */
-#define XBMSP_PACKET_OK 1
-#define XBMSP_PACKET_ERROR 2
-#define XBMSP_PACKET_HANDLE 3
-#define XBMSP_PACKET_FILE_DATA 4
-#define XBMSP_PACKET_FILE_CONTENTS 5
-#define XBMSP_PACKET_AUTHENTICATION_CONTINUE 6
-
-
-/**
- * Client source messages
- */
-#define XBMSP_PACKET_NULL 10
-#define XBMSP_PACKET_SETCWD 11
-#define XBMSP_PACKET_FILELIST_OPEN 12
-#define XBMSP_PACKET_FILELIST_READ 13
-#define XBMSP_PACKET_FILE_INFO 14
-#define XBMSP_PACKET_FILE_OPEN 15
-#define XBMSP_PACKET_FILE_READ 16
-#define XBMSP_PACKET_FILE_SEEK 17
-#define XBMSP_PACKET_CLOSE 18
-#define XBMSP_PACKET_CLOSE_ALL 19
-#define XBMSP_PACKET_SET_CONFIGURATION_OPTION 20
-#define XBMSP_PACKET_AUTHENTICATION_INIT 21
-#define XBMSP_PACKET_AUTHENTICATE 22
-#define XBMSP_PACKET_UPCWD 23
-
-
-/**
- * Discovery messages
- */
-#define XBMSP_PACKET_SERVER_DISCOVERY_QUERY 90
-#define XBMSP_PACKET_SERVER_DISCOVERY_REPLY 91
-
-/**
- * Error codes
- */
-#define XBMSP_ERROR_OK 0 /* Reserved */
-#define XBMSP_ERROR_FAILURE 1
-#define XBMSP_ERROR_UNSUPPORTED 2
-#define XBMSP_ERROR_NO_SUCH_FILE 3
-#define XBMSP_ERROR_INVALID_FILE 4
-#define XBMSP_ERROR_INVALID_HANDLE 5
-#define XBMSP_ERROR_OPEN_FAILED 6
-#define XBMSP_ERROR_TOO_MANY_OPEN_FILES 7
-#define XBMSP_ERROR_TOO_LONG_READ 8
-#define XBMSP_ERROR_ILLEGAL_SEEK 9
-#define XBMSP_ERROR_OPTION_IS_READ_ONLY 10
-#define XBMSP_ERROR_INVALID_OPTION_VALUE 11
-#define XBMSP_ERROR_AUTHENTICATION_NEEDED 12
-#define XBMSP_ERROR_AUTHENTICATION_FAILED 13
-
-LIST_HEAD(xbmsp_dirhandle_list, xbmsp_dirhandle);
-LIST_HEAD(xbmsp_subscription_list, xbmsp_subscription);
-TAILQ_HEAD(xbmsp_direntry_queue, xbmsp_direntry);
-
-/**
- * Represents an directory entry (a file or a dir)
- */
-typedef struct xbmsp_direntry {
- TAILQ_ENTRY(xbmsp_direntry) xde_link;
-
- const char *xde_filename;
- const char *xde_xmlmeta;
-
-} xbmsp_direntry_t;
-
-
-/**
- * Represents an opened directory handle.
- *
- * These are created and populated upon XBMSP_PACKET_FILELIST_OPEN and
- * subsequently consumed by XBMSP_PACKET_FILELIST_READ
- */
-typedef struct xbmsp_dirhandle {
- LIST_ENTRY(xbmsp_dirhandle) xdh_link;
- uint32_t xdh_handle;
- struct xbmsp_direntry_queue xdh_entries;
-} xbmsp_dirhandle_t;
-
-/**
- * Represents an file (or stream) entry
- */
-typedef struct xbmsp_subscription {
- LIST_ENTRY(xbmsp_subscription) xs_link;
- uint32_t xs_handle;
- th_subscription_t *xs_subscription;
- struct xbmsp *xs_xbmsp;
-
- th_ffmuxer_t xs_tffm;
- tffm_fifo_t *xs_fifo; /* output fifo */
-
- size_t xs_pending_read_size;
- uint32_t xs_pending_read_msgid;
-
-} xbmsp_subscrption_t;
-
-
-
-/**
- * Context for an XBMSP session
- */
-typedef struct xbmsp {
- tcp_session_t xbmsp_tcp_session; /* Must be first */
-
- LIST_ENTRY(xbmsp) xbmsp_global_link;
-
- enum {
- XBMSP_STATE_CLIENT_IDENTIFY = 0,
- XBMSP_STATE_1_0,
- } xbmsp_state;
-
- uint8_t *xbmsp_buf;
- int xbmsp_bufptr;
- int xbmsp_bufsize;
- int xbmsp_msglen;
-
-
- const char *xbmsp_username;
- struct config_head *xbmsp_user_config;
- int xbmsp_authenticated; /* set if authenticated */
- uint32_t xbmsp_handle_tally;
-
- char *xbmsp_wd; /* Working directory */
-
- struct xbmsp_dirhandle_list xbmsp_dirhandles;
-
- struct xbmsp_subscription_list xbmsp_subscriptions;
-
- char xbmsp_logname[100];
-
-} xbmsp_t;
-
-void xbmsp_start(int port);
-
-#endif /* XBMSP_H_ */