From 2a36140f036b848a33febd99d4ac62595e06f252 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andreas=20=C3=96man?= Date: Tue, 29 Jun 2010 19:50:37 +0000 Subject: [PATCH] Remove ancient code --- src/xbmsp.c | 1139 --------------------------------------------------- src/xbmsp.h | 162 -------- 2 files changed, 1301 deletions(-) delete mode 100644 src/xbmsp.c delete mode 100644 src/xbmsp.h 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_ */