[dvblast-devel] [PATCH 1/6] comm: Allow command answer to be split in multiple packets
Georgi Chorbadzhiyski
gf at unixsol.org
Mon Aug 29 23:15:18 CEST 2011
On 8/29/11 11:36 AM, Georgi Chorbadzhiyski wrote:
> diff --git a/comm.h b/comm.h
> index 017a96d..67ba003 100644
> --- a/comm.h
> +++ b/comm.h
> @@ -19,10 +19,12 @@
> #include<linux/dvb/frontend.h>
> #include<linux/dvb/ca.h>
>
> -#define COMM_BUFFER_SIZE 4096
> #define COMM_HEADER_SIZE 4
The above should be 8 :( I've lost the correct hunk somewhere.
> +#define COMM_BUFFER_SIZE (COMM_HEADER_SIZE + ((PSI_PRIVATE_MAX_SIZE + PSI_HEADER_SIZE) * (PSI_TABLE_MAX_SECTIONS / 2)))
> #define COMM_HEADER_MAGIC 0x48
>
> +#define COMM_MAX_MSG_CHUNK 65535
> +
> #define CMD_RELOAD 1
> #define CMD_SHUTDOWN 2
> #define CMD_FRONTEND_STATUS 3
Correct patch is attached and in order to avoid later
patch conflict (trivial to resolve) I'm attaching the
fixed second patch of the series as well.
--
Georgi Chorbadzhiyski
http://georgi.unixsol.org/
-------------- next part --------------
>From e5e9ee6629ac81b1f74e9fdabc2ec543454ff835 Mon Sep 17 00:00:00 2001
From: Georgi Chorbadzhiyski <gf at unixsol.org>
Date: Fri, 26 Aug 2011 15:17:49 +0300
Subject: [PATCH 1/6] comm: Allow command answer to be split in multiple
packets
---
comm.c | 25 +++++++++++++++++++++----
comm.h | 6 ++++--
dvblastctl.c | 18 ++++++++++++++++--
3 files changed, 41 insertions(+), 8 deletions(-)
diff --git a/comm.c b/comm.c
index 171aead..a0f1a2c 100644
--- a/comm.c
+++ b/comm.c
@@ -41,7 +41,7 @@ int i_comm_fd = -1;
*****************************************************************************/
void comm_Open( void )
{
- int i_size = 65535;
+ int i_size = COMM_MAX_MSG_CHUNK;
struct sockaddr_un sun_server;
if ( (i_comm_fd = socket( AF_UNIX, SOCK_DGRAM, 0 )) == -1 )
@@ -164,10 +164,27 @@ void comm_Read( void )
p_answer[1] = i_answer;
p_answer[2] = 0;
p_answer[3] = 0;
+ uint32_t *p_size = (uint32_t *)&p_answer[4];
+ *p_size = i_answer_size + COMM_HEADER_SIZE;
+
msg_Dbg( NULL, "answering %d to %d with size %zd", i_answer, i_command,
i_answer_size );
- if ( sendto( i_comm_fd, p_answer, i_answer_size + COMM_HEADER_SIZE, 0,
- (struct sockaddr *)&sun_client, sun_length ) < 0 )
- msg_Err( NULL, "cannot send comm socket (%s)", strerror(errno) );
+#define min(a, b) (a < b ? a : b)
+ ssize_t i_sended = 0;
+ ssize_t i_to_send = i_answer_size + COMM_HEADER_SIZE;
+ do {
+ ssize_t i_sent = sendto( i_comm_fd, p_answer + i_sended,
+ min(i_to_send, COMM_MAX_MSG_CHUNK), 0,
+ (struct sockaddr *)&sun_client, sun_length );
+
+ if ( i_sent < 0 ) {
+ msg_Err( NULL, "cannot send comm socket (%s)", strerror(errno) );
+ break;
+ }
+
+ i_sended += i_sent;
+ i_to_send -= i_sent;
+ } while ( i_to_send > 0 );
+#undef min
}
diff --git a/comm.h b/comm.h
index 017a96d..8092d46 100644
--- a/comm.h
+++ b/comm.h
@@ -19,10 +19,12 @@
#include <linux/dvb/frontend.h>
#include <linux/dvb/ca.h>
-#define COMM_BUFFER_SIZE 4096
-#define COMM_HEADER_SIZE 4
+#define COMM_HEADER_SIZE 8
+#define COMM_BUFFER_SIZE (COMM_HEADER_SIZE + ((PSI_PRIVATE_MAX_SIZE + PSI_HEADER_SIZE) * (PSI_TABLE_MAX_SECTIONS / 2)))
#define COMM_HEADER_MAGIC 0x48
+#define COMM_MAX_MSG_CHUNK 65535
+
#define CMD_RELOAD 1
#define CMD_SHUTDOWN 2
#define CMD_FRONTEND_STATUS 3
diff --git a/dvblastctl.c b/dvblastctl.c
index 2d5099e..1ecef0b 100644
--- a/dvblastctl.c
+++ b/dvblastctl.c
@@ -59,7 +59,7 @@ int main( int i_argc, char **ppsz_argv )
char *client_socket_tmpl = "dvblastctl.clientsock.XXXXXX";
char *psz_srv_socket = NULL;
int i_fd;
- int i = 65535;
+ int i = COMM_MAX_MSG_CHUNK;
ssize_t i_size;
struct sockaddr_un sun_client, sun_server;
uint8_t p_buffer[COMM_BUFFER_SIZE];
@@ -239,7 +239,21 @@ int main( int i_argc, char **ppsz_argv )
exit(255);
}
- i_size = recv( i_fd, p_buffer, COMM_BUFFER_SIZE, 0 );
+ uint32_t i_packet_size = 0, i_received = 0;
+ do {
+ i_size = recv( i_fd, p_buffer + i_received, COMM_MAX_MSG_CHUNK, 0 );
+ if ( i_size == -1 )
+ break;
+ if ( !i_packet_size ) {
+ i_packet_size = *((uint32_t *)&p_buffer[4]);
+ if ( i_packet_size > COMM_BUFFER_SIZE ) {
+ i_size = -1;
+ break;
+ }
+ }
+ i_received += i_size;
+ } while ( i_received < i_packet_size );
+
close( i_fd );
unlink( psz_client_socket );
if ( i_size < COMM_HEADER_SIZE )
--
1.7.5.1
-------------- next part --------------
>From 868614281d3be03b191b3ca8246922028328c510 Mon Sep 17 00:00:00 2001
From: Georgi Chorbadzhiyski <gf at unixsol.org>
Date: Thu, 25 Aug 2011 13:12:37 +0300
Subject: [PATCH 2/6] dvblastctl: Add get_pat, get_cat, get_nit and get_sdt
commands.
---
NEWS | 1 +
comm.c | 40 ++++++++++++++++++++++++
comm.h | 11 +++++++
demux.c | 19 ++++++++++++
dvblast.h | 7 ++++
dvblastctl.c | 94 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++-
util.c | 68 ++++++++++++++++++++++++++++++++++++++++++
7 files changed, 238 insertions(+), 2 deletions(-)
diff --git a/NEWS b/NEWS
index a31fb80..7de4d63 100644
--- a/NEWS
+++ b/NEWS
@@ -18,6 +18,7 @@ Changes between 1.2 and 2.0:
* Add basic support for ATSC
* Add support for MRTG statistics
* Add detailed information for TS errors
+ * Add support for getting PAT/CAT/NIT/SDT tables in dvblastctl
Changes between 1.1 and 1.2:
----------------------------
diff --git a/comm.c b/comm.c
index a0f1a2c..c3f658d 100644
--- a/comm.c
+++ b/comm.c
@@ -77,6 +77,8 @@ void comm_Read( void )
ssize_t i_size, i_answer_size = 0;
uint8_t p_buffer[COMM_BUFFER_SIZE], p_answer[COMM_BUFFER_SIZE];
uint8_t i_command, i_answer;
+ uint8_t *p_packed_section;
+ unsigned int i_packed_section_size;
i_size = recvfrom( i_comm_fd, p_buffer, COMM_BUFFER_SIZE, 0,
(struct sockaddr *)&sun_client, &sun_length );
@@ -153,6 +155,44 @@ void comm_Read( void )
i_answer_size = 0;
break;
+ case CMD_GET_PAT:
+ case CMD_GET_CAT:
+ case CMD_GET_NIT:
+ case CMD_GET_SDT:
+ {
+#define CASE_TABLE(x) \
+ case CMD_GET_##x: \
+ { \
+ i_answer = RET_##x; \
+ p_packed_section = demux_get_current_packed_##x(&i_packed_section_size); \
+ break; \
+ }
+ switch ( i_command )
+ {
+ CASE_TABLE(PAT)
+ CASE_TABLE(CAT)
+ CASE_TABLE(NIT)
+ CASE_TABLE(SDT)
+ }
+#undef CASE_TABLE
+
+ if ( p_packed_section && i_packed_section_size )
+ {
+ if ( i_packed_section_size <= COMM_BUFFER_SIZE - COMM_HEADER_SIZE )
+ {
+ i_answer_size = i_packed_section_size;
+ memcpy( p_answer + COMM_HEADER_SIZE, p_packed_section, i_packed_section_size );
+ } else {
+ msg_Err( NULL, "section size is too big (%u)\n", i_packed_section_size );
+ i_answer = RET_NODATA;
+ }
+ free( p_packed_section );
+ } else {
+ i_answer = RET_NODATA;
+ }
+
+ break;
+ }
default:
msg_Err( NULL, "wrong command %u", i_command );
i_answer = RET_HUH;
diff --git a/comm.h b/comm.h
index 8092d46..7bfb6df 100644
--- a/comm.h
+++ b/comm.h
@@ -19,6 +19,8 @@
#include <linux/dvb/frontend.h>
#include <linux/dvb/ca.h>
+#include <bitstream/mpeg/psi.h>
+
#define COMM_HEADER_SIZE 8
#define COMM_BUFFER_SIZE (COMM_HEADER_SIZE + ((PSI_PRIVATE_MAX_SIZE + PSI_HEADER_SIZE) * (PSI_TABLE_MAX_SECTIONS / 2)))
#define COMM_HEADER_MAGIC 0x48
@@ -34,6 +36,10 @@
#define CMD_MMI_CLOSE 7 /* arg: slot */
#define CMD_MMI_RECV 8 /* arg: slot */
#define CMD_MMI_SEND 9 /* arg: slot, en50221_mmi_object_t */
+#define CMD_GET_PAT 10
+#define CMD_GET_CAT 11
+#define CMD_GET_NIT 12
+#define CMD_GET_SDT 13
#define RET_OK 0
#define RET_ERR 1
@@ -42,6 +48,11 @@
#define RET_MMI_SLOT_STATUS 4
#define RET_MMI_RECV 5
#define RET_MMI_WAIT 6
+#define RET_NODATA 7
+#define RET_PAT 8
+#define RET_CAT 9
+#define RET_NIT 10
+#define RET_SDT 11
#define RET_HUH 255
struct ret_frontend_status
diff --git a/demux.c b/demux.c
index 327d113..1787593 100644
--- a/demux.c
+++ b/demux.c
@@ -2772,3 +2772,22 @@ static const char *get_pid_desc(uint16_t i_pid, uint16_t *i_sid) {
return "...";
}
+
+/*****************************************************************************
+ * Functions that return packed sections
+ *****************************************************************************/
+uint8_t *demux_get_current_packed_PAT( unsigned int *pi_pack_size ) {
+ return psi_pack_sections( pp_current_pat_sections, pi_pack_size );
+}
+
+uint8_t *demux_get_current_packed_CAT( unsigned int *pi_pack_size ) {
+ return psi_pack_sections( pp_current_cat_sections, pi_pack_size );
+}
+
+uint8_t *demux_get_current_packed_NIT( unsigned int *pi_pack_size ) {
+ return psi_pack_sections( pp_current_nit_sections, pi_pack_size );
+}
+
+uint8_t *demux_get_current_packed_SDT( unsigned int *pi_pack_size ) {
+ return psi_pack_sections( pp_current_sdt_sections, pi_pack_size );
+}
diff --git a/dvblast.h b/dvblast.h
index d1ba6b9..9571eb7 100644
--- a/dvblast.h
+++ b/dvblast.h
@@ -206,6 +206,9 @@ void hexDump( uint8_t *p_data, uint32_t i_len );
struct addrinfo *ParseNodeService( char *_psz_string, char **ppsz_end,
uint16_t i_default_port );
+uint8_t *psi_pack_sections( uint8_t **pp_sections, unsigned int *pi_size );
+uint8_t **psi_unpack_sections( uint8_t *p_flat_sections, unsigned int i_size );
+
void dvb_Open( void );
void dvb_Reset( void );
block_t * dvb_Read( mtime_t i_poll_timeout );
@@ -234,6 +237,10 @@ char *demux_Iconv(void *_unused, const char *psz_encoding,
char *p_string, size_t i_length);
void demux_Close( void );
+uint8_t *demux_get_current_packed_PAT( unsigned int *pi_pack_size );
+uint8_t *demux_get_current_packed_CAT( unsigned int *pi_pack_size );
+uint8_t *demux_get_current_packed_NIT( unsigned int *pi_pack_size );
+uint8_t *demux_get_current_packed_SDT( unsigned int *pi_pack_size );
output_t *output_Create( const output_config_t *p_config );
int output_Init( output_t *p_output, const output_config_t *p_config );
diff --git a/dvblastctl.c b/dvblastctl.c
index 1ecef0b..2fd1a5b 100644
--- a/dvblastctl.c
+++ b/dvblastctl.c
@@ -22,11 +22,13 @@
*****************************************************************************/
#include <stdlib.h>
+#include <stdarg.h>
#include <stdio.h>
#include <unistd.h>
#include <stdint.h>
#include <stdbool.h>
#include <string.h>
+#include <inttypes.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/param.h>
@@ -37,6 +39,11 @@
#include <errno.h>
#include <getopt.h>
+#include <bitstream/mpeg/psi.h>
+#include <bitstream/dvb/si.h>
+#include <bitstream/dvb/si_print.h>
+#include <bitstream/mpeg/psi_print.h>
+
#include "dvblast.h"
#include "en50221.h"
#include "comm.h"
@@ -45,11 +52,42 @@
int i_verbose = 3;
int i_syslog = 0;
+print_type_t i_print_type = PRINT_TEXT;
+
+/*****************************************************************************
+ * The following two functinos are from biTStream's examples and are under the
+ * WTFPL (see LICENSE.WTFPL).
+ ****************************************************************************/
+__attribute__ ((format(printf, 2, 3)))
+static void psi_print(void *_unused, const char *psz_format, ...)
+{
+ char psz_fmt[strlen(psz_format) + 2];
+ va_list args;
+ va_start(args, psz_format);
+ strcpy(psz_fmt, psz_format);
+ strcat(psz_fmt, "\n");
+ vprintf(psz_fmt, args);
+}
+
+static char *iconv_append_null(const char *p_string, size_t i_length)
+{
+ char *psz_string = malloc(i_length + 1);
+ memcpy(psz_string, p_string, i_length);
+ psz_string[i_length] = '\0';
+ return psz_string;
+}
+
+char *psi_iconv(void *_unused, const char *psz_encoding,
+ char *p_string, size_t i_length)
+{
+ return iconv_append_null(p_string, i_length);
+}
+
void usage()
{
msg_Raw( NULL, "DVBlastctl %d.%d.%d%s", VERSION_MAJOR, VERSION_MINOR,
VERSION_REVISION, VERSION_EXTRA );
- msg_Raw( NULL, "Usage: dvblastctl -r <remote socket> reload|shutdown|fe_status|mmi_status|mmi_open|mmi_close|mmi_get|mmi_send_text|mmi_send_choice [<CAM slot>] [<text/choice>]" );
+ msg_Raw( NULL, "Usage: dvblastctl -r <remote socket> reload|shutdown|fe_status|mmi_status|mmi_open|mmi_close|mmi_get|mmi_send_text|mmi_send_choice|get_pat|get_cat|get_nit|get_sdt [<CAM slot>] [-x <text|xml>] [<text/choice>]" );
exit(1);
}
@@ -71,11 +109,12 @@ int main( int i_argc, char **ppsz_argv )
static const struct option long_options[] =
{
{"remote-socket", required_argument, NULL, 'r'},
+ {"print", required_argument, NULL, 'x'},
{"help", no_argument, NULL, 'h'},
{0, 0, 0, 0}
};
- if ( (c = getopt_long(i_argc, ppsz_argv, "r:h", long_options, NULL)) == -1 )
+ if ( (c = getopt_long(i_argc, ppsz_argv, "r:x:h", long_options, NULL)) == -1 )
break;
switch ( c )
@@ -84,6 +123,17 @@ int main( int i_argc, char **ppsz_argv )
psz_srv_socket = optarg;
break;
+ case 'x':
+ if ( !strcmp(optarg, "text") )
+ i_print_type = PRINT_TEXT;
+ else if ( !strcmp(optarg, "xml") )
+ i_print_type = PRINT_XML;
+ else
+ msg_Warn( NULL, "unrecognized print type %s", optarg );
+ /* Make stdout line-buffered */
+ setvbuf(stdout, NULL, _IOLBF, 0);
+ break;
+
case 'h':
default:
usage();
@@ -96,6 +146,10 @@ int main( int i_argc, char **ppsz_argv )
if ( strcmp(ppsz_argv[optind], "reload")
&& strcmp(ppsz_argv[optind], "shutdown")
&& strcmp(ppsz_argv[optind], "fe_status")
+ && strcmp(ppsz_argv[optind], "get_pat")
+ && strcmp(ppsz_argv[optind], "get_cat")
+ && strcmp(ppsz_argv[optind], "get_nit")
+ && strcmp(ppsz_argv[optind], "get_sdt")
&& strcmp(ppsz_argv[optind], "mmi_status")
&& strcmp(ppsz_argv[optind], "mmi_slot_status")
&& strcmp(ppsz_argv[optind], "mmi_open")
@@ -171,6 +225,14 @@ int main( int i_argc, char **ppsz_argv )
p_buffer[1] = CMD_SHUTDOWN;
else if ( !strcmp(ppsz_argv[optind], "fe_status") )
p_buffer[1] = CMD_FRONTEND_STATUS;
+ else if ( !strcmp(ppsz_argv[optind], "get_pat") )
+ p_buffer[1] = CMD_GET_PAT;
+ else if ( !strcmp(ppsz_argv[optind], "get_cat") )
+ p_buffer[1] = CMD_GET_CAT;
+ else if ( !strcmp(ppsz_argv[optind], "get_nit") )
+ p_buffer[1] = CMD_GET_NIT;
+ else if ( !strcmp(ppsz_argv[optind], "get_sdt") )
+ p_buffer[1] = CMD_GET_SDT;
else if ( !strcmp(ppsz_argv[optind], "mmi_status") )
p_buffer[1] = CMD_MMI_STATUS;
else
@@ -289,6 +351,34 @@ int main( int i_argc, char **ppsz_argv )
exit(255);
break;
+ case RET_NODATA:
+ msg_Err( NULL, "no data" );
+ exit(255);
+ break;
+
+ case RET_PAT:
+ case RET_CAT:
+ case RET_NIT:
+ case RET_SDT:
+ {
+ uint8_t *p_flat_data = p_buffer + COMM_HEADER_SIZE;
+ unsigned int i_flat_data_size = i_size - COMM_HEADER_SIZE;
+ uint8_t **pp_sections = psi_unpack_sections( p_flat_data, i_flat_data_size );
+
+ switch( p_buffer[1] )
+ {
+ case RET_PAT: pat_table_print( pp_sections, psi_print, NULL, i_print_type ); break;
+ case RET_CAT: cat_table_print( pp_sections, psi_print, NULL, i_print_type ); break;
+ case RET_NIT: nit_table_print( pp_sections, psi_print, NULL, psi_iconv, NULL, i_print_type ); break;
+ case RET_SDT: sdt_table_print( pp_sections, psi_print, NULL, psi_iconv, NULL, i_print_type ); break;
+ }
+
+ psi_table_free( pp_sections );
+ free( pp_sections );
+ exit(0);
+ break;
+ }
+
case RET_FRONTEND_STATUS:
{
struct ret_frontend_status *p_ret =
diff --git a/util.c b/util.c
index 1408772..de141ab 100644
--- a/util.c
+++ b/util.c
@@ -37,6 +37,8 @@
#include <errno.h>
#include <syslog.h>
+#include <bitstream/mpeg/psi.h>
+
#include "dvblast.h"
/*****************************************************************************
@@ -333,3 +335,69 @@ struct addrinfo *ParseNodeService( char *_psz_string, char **ppsz_end,
return p_res;
}
+/*****************************************************************************
+ * psi_pack_sections: return psi sections as array
+ * Note: Allocates the return value. The caller must free it.
+ *****************************************************************************/
+uint8_t *psi_pack_sections( uint8_t **pp_sections, unsigned int *pi_size ) {
+ uint8_t i_last_section;
+ uint8_t *p_flat_section;
+ unsigned int i, i_pos = 0;
+
+ if ( !psi_table_validate( pp_sections ) )
+ return NULL;
+
+ i_last_section = psi_table_get_lastsection( pp_sections );
+
+ /* Calculate total size */
+ *pi_size = 0;
+ for ( i = 0; i <= i_last_section; i++ )
+ {
+ uint8_t *p_section = psi_table_get_section( pp_sections, i );
+ *pi_size += psi_get_length( p_section ) + PSI_HEADER_SIZE;
+ }
+
+ p_flat_section = malloc( *pi_size );
+ if ( !p_flat_section )
+ return NULL;
+
+ for ( i = 0; i <= i_last_section; i++ )
+ {
+ uint8_t *p_section = psi_table_get_section( pp_sections, i );
+ uint16_t psi_length = psi_get_length( p_section ) + PSI_HEADER_SIZE;
+
+ memcpy( p_flat_section + i_pos, p_section, psi_length );
+ i_pos += psi_length;
+ }
+
+ return p_flat_section;
+
+}
+
+/*****************************************************************************
+ * psi_unpack_sections: return psi sections
+ * Note: Allocates psi_table, the result must be psi_table_free()'ed
+ *****************************************************************************/
+uint8_t **psi_unpack_sections( uint8_t *p_flat_sections, unsigned int i_size ) {
+ uint8_t **pp_sections;
+ unsigned int i, i_offset = 0;
+
+ pp_sections = psi_table_allocate();
+ psi_table_init( pp_sections );
+
+ for ( i = 0; i < PSI_TABLE_MAX_SECTIONS; i++ ) {
+ uint8_t *p_section = p_flat_sections + i_offset;
+ uint16_t i_section_len = psi_get_length( p_section ) + PSI_HEADER_SIZE;
+
+ /* Must use allocated section not p_flat_section + offset directly! */
+ uint8_t *p_section_local = psi_private_allocate();
+ memcpy( p_section_local, p_section, i_section_len );
+ psi_table_section( pp_sections, p_section_local );
+
+ i_offset += i_section_len;
+ if ( i_offset >= i_size - 1 )
+ break;
+ }
+
+ return pp_sections;
+}
--
1.7.5.1
More information about the dvblast-devel
mailing list