Remove excessive debug, extend search for start
[dvblastpn.git] / util.c
blob97b4b79c53f610616b9393202bf103d373e32848
1 /*****************************************************************************
2 * util.c
3 *****************************************************************************
4 * Copyright (C) 2004, 2015 VideoLAN
6 * Authors: Christophe Massiot <massiot@via.ecp.fr>
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
21 *****************************************************************************/
23 #include <stdlib.h>
24 #include <stdio.h>
25 #include <stdint.h>
26 #include <stdbool.h>
27 #include <string.h>
28 #include <stdarg.h>
29 #include <sys/time.h>
30 #include <time.h>
31 #include <sys/types.h>
32 #include <sys/socket.h>
33 #include <netdb.h>
34 #include <netinet/in.h>
35 #include <arpa/inet.h>
36 #include <errno.h>
37 #include <syslog.h>
39 #include <bitstream/mpeg/psi.h>
41 #include "dvblast.h"
43 /*****************************************************************************
44 * Local declarations
45 *****************************************************************************/
46 #define MAX_BLOCKS 500
47 #define MAX_MSG 1024
48 #define VERB_DBG 4
49 #define VERB_INFO 3
50 #define VERB_WARN 2
51 #define VERB_ERR 1
53 static block_t *p_block_lifo = NULL;
54 static unsigned int i_block_count = 0;
56 /*****************************************************************************
57 * block_New
58 *****************************************************************************/
59 block_t *block_New( void )
61 block_t *p_block;
63 if (i_block_count)
65 p_block = p_block_lifo;
66 p_block_lifo = p_block->p_next;
67 i_block_count--;
69 else
71 p_block = malloc(sizeof(block_t));
74 p_block->p_next = NULL;
75 p_block->i_refcount = 1;
76 return p_block;
79 /*****************************************************************************
80 * block_Delete
81 *****************************************************************************/
82 void block_Delete( block_t *p_block )
84 if (i_block_count >= MAX_BLOCKS )
86 free( p_block );
87 return;
90 p_block->p_next = p_block_lifo;
91 p_block_lifo = p_block;
92 i_block_count++;
95 /*****************************************************************************
96 * block_Vacuum
97 *****************************************************************************/
98 void block_Vacuum( void )
100 while (i_block_count)
102 block_t *p_block = p_block_lifo;
103 p_block_lifo = p_block->p_next;
104 free(p_block);
105 i_block_count--;
109 /*****************************************************************************
110 * msg_Connect
111 *****************************************************************************/
112 void msg_Connect( const char *ident )
114 i_syslog = 1;
115 openlog( ident, LOG_NDELAY | LOG_PID, LOG_USER );
118 /*****************************************************************************
119 * msg_Disconnect
120 *****************************************************************************/
121 void msg_Disconnect( void )
123 i_syslog = 0;
124 closelog();
127 /*****************************************************************************
128 * msg_Info
129 *****************************************************************************/
130 void msg_Info( void *_unused, const char *psz_format, ... )
132 if ( i_verbose < VERB_INFO )
133 return;
135 va_list args;
136 va_start( args, psz_format );
138 if ( !i_syslog )
140 char psz_fmt[MAX_MSG];
141 snprintf( psz_fmt, MAX_MSG, "info: %s\n", psz_format );
142 vfprintf( stderr, psz_fmt, args );
144 else
146 vsyslog( LOG_INFO, psz_format, args );
149 va_end(args);
152 /*****************************************************************************
153 * msg_Err
154 *****************************************************************************/
155 void msg_Err( void *_unused, const char *psz_format, ... )
157 if ( i_verbose < VERB_ERR )
158 return;
160 va_list args;
161 va_start( args, psz_format );
163 if ( !i_syslog )
165 char psz_fmt[MAX_MSG];
166 snprintf( psz_fmt, MAX_MSG, "error: %s\n", psz_format );
167 vfprintf( stderr, psz_fmt, args );
169 else
171 vsyslog( LOG_ERR, psz_format, args );
174 va_end(args);
177 /*****************************************************************************
178 * msg_Warn
179 *****************************************************************************/
180 void msg_Warn( void *_unused, const char *psz_format, ... )
182 if ( i_verbose < VERB_WARN )
183 return;
185 va_list args;
186 va_start( args, psz_format );
188 if ( !i_syslog )
190 char psz_fmt[MAX_MSG];
191 snprintf( psz_fmt, MAX_MSG, "warning: %s\n", psz_format );
192 vfprintf( stderr, psz_fmt, args );
194 else
196 vsyslog( LOG_WARNING, psz_format, args );
199 va_end(args);
202 /*****************************************************************************
203 * msg_Dbg
204 *****************************************************************************/
205 void msg_Dbg( void *_unused, const char *psz_format, ... )
207 if ( i_verbose < VERB_DBG )
208 return;
210 va_list args;
211 va_start( args, psz_format );
213 if ( !i_syslog )
215 char psz_fmt[MAX_MSG];
216 snprintf( psz_fmt, MAX_MSG, "debug: %s\n", psz_format );
217 vfprintf( stderr, psz_fmt, args );
219 else
221 vsyslog( LOG_DEBUG, psz_format, args );
224 va_end(args);
227 /*****************************************************************************
228 * msg_Raw
229 *****************************************************************************/
230 void msg_Raw( void *_unused, const char *psz_format, ... )
232 va_list args;
233 char psz_fmt[MAX_MSG];
234 va_start( args, psz_format );
236 snprintf( psz_fmt, MAX_MSG, "%s\n", psz_format );
237 vfprintf( stderr, psz_fmt, args );
238 va_end(args);
241 /*****************************************************************************
242 * streq
243 *****************************************************************************/
244 inline bool streq(char *a, char *b) {
245 if (!a && b) return false;
246 if (!b && a) return false;
247 if (a == b) return true;
248 return strcmp(a, b) == 0 ? true : false;
251 /*****************************************************************************
252 * xstrdup
253 *****************************************************************************/
254 inline char * xstrdup(char *str) {
255 return str ? strdup(str) : NULL;
258 /*****************************************************************************
259 * dvb_string_init
260 *****************************************************************************/
261 void dvb_string_init(dvb_string_t *p_dvb_string)
263 p_dvb_string->p = NULL;
264 p_dvb_string->i = 0;
267 /*****************************************************************************
268 * dvb_string_clean
269 *****************************************************************************/
270 void dvb_string_clean(dvb_string_t *p_dvb_string)
272 free(p_dvb_string->p);
275 /*****************************************************************************
276 * dvb_string_copy
277 *****************************************************************************/
278 void dvb_string_copy(dvb_string_t *p_dst, const dvb_string_t *p_src)
280 p_dst->p = malloc(p_src->i);
281 memcpy(p_dst->p, p_src->p, p_src->i);
282 p_dst->i = p_src->i;
285 /*****************************************************************************
286 * dvb_string_cmp
287 *****************************************************************************/
288 int dvb_string_cmp(const dvb_string_t *p_1, const dvb_string_t *p_2)
290 if (p_1->i != p_2->i)
291 return p_1->i - p_2->i;
292 return memcmp(p_1->p, p_2->p, p_1->i);
295 /*****************************************************************************
296 * mdate
297 *****************************************************************************/
298 mtime_t mdate( void )
300 #if defined (HAVE_CLOCK_NANOSLEEP)
301 struct timespec ts;
303 /* Try to use POSIX monotonic clock if available */
304 if( clock_gettime( CLOCK_MONOTONIC, &ts ) == EINVAL )
305 /* Run-time fallback to real-time clock (always available) */
306 (void)clock_gettime( CLOCK_REALTIME, &ts );
308 return ((mtime_t)ts.tv_sec * (mtime_t)1000000)
309 + (mtime_t)(ts.tv_nsec / 1000);
310 #else
311 struct timeval tv_date;
313 /* gettimeofday() could return an error, and should be tested. However, the
314 * only possible error, according to 'man', is EFAULT, which can not happen
315 * here, since tv is a local variable. */
316 gettimeofday( &tv_date, NULL );
317 return( (mtime_t) tv_date.tv_sec * 1000000 + (mtime_t) tv_date.tv_usec );
318 #endif
321 /*****************************************************************************
322 * msleep
323 *****************************************************************************/
324 void msleep( mtime_t delay )
326 struct timespec ts;
327 ts.tv_sec = delay / 1000000;
328 ts.tv_nsec = (delay % 1000000) * 1000;
330 #if defined( HAVE_CLOCK_NANOSLEEP )
331 int val;
332 while ( ( val = clock_nanosleep( CLOCK_MONOTONIC, 0, &ts, &ts ) ) == EINTR );
333 if( val == EINVAL )
335 ts.tv_sec = delay / 1000000;
336 ts.tv_nsec = (delay % 1000000) * 1000;
337 while ( clock_nanosleep( CLOCK_REALTIME, 0, &ts, &ts ) == EINTR );
339 #else
340 while ( nanosleep( &ts, &ts ) && errno == EINTR );
341 #endif
344 /*****************************************************************************
345 * hexDump
346 *****************************************************************************/
347 void hexDump( uint8_t *p_data, uint32_t i_len )
349 uint16_t i, j;
351 char *p_outline;
352 char *p_hrdata;
354 p_outline = malloc(70);
355 p_hrdata = malloc(18);
357 for( i = 0; i < i_len; i += 16 )
360 sprintf( p_outline, "%03x: ", i );
362 for( j = 0; j < 16; j++ )
364 if( i + j < i_len )
366 sprintf( &p_outline[5 + (3 * j)], "%02x ", p_data[i + j] );
368 if( p_data[i + j] >= 32 && p_data[i + j] <= 136 )
370 sprintf( &p_hrdata[j], "%c", p_data[i + j] );
373 else {
374 sprintf( &p_hrdata[j], "." );
378 else
380 sprintf( &p_outline[5 + (3 * j)], " " );
381 sprintf( &p_hrdata[j], " " );
385 sprintf( &p_outline[53], "%16s", p_hrdata );
386 msg_Dbg( NULL, "%s", p_outline );
389 free( p_hrdata );
390 free( p_outline );
393 /*****************************************************************************
394 * ParseNodeService: parse a host:port string
395 *****************************************************************************/
396 struct addrinfo *ParseNodeService( char *_psz_string, char **ppsz_end,
397 uint16_t i_default_port )
399 int i_family = AF_INET;
400 char psz_port_buffer[6];
401 char *psz_string = strdup( _psz_string );
402 char *psz_node, *psz_port = NULL, *psz_end;
403 struct addrinfo *p_res;
404 struct addrinfo hint;
405 int i_ret;
407 if ( psz_string[0] == '[' )
409 i_family = AF_INET6;
410 psz_node = psz_string + 1;
411 psz_end = strchr( psz_node, ']' );
412 if ( psz_end == NULL )
414 msg_Warn( NULL, "invalid IPv6 address %s", _psz_string );
415 free( psz_string );
416 return NULL;
418 *psz_end++ = '\0';
420 else
422 psz_node = psz_string;
423 psz_end = strpbrk( psz_string, "@:,/" );
426 if ( psz_end != NULL && psz_end[0] == ':' )
428 *psz_end++ = '\0';
429 psz_port = psz_end;
430 psz_end = strpbrk( psz_port, "@:,/" );
433 if ( psz_end != NULL )
435 *psz_end = '\0';
436 if ( ppsz_end != NULL )
437 *ppsz_end = _psz_string + (psz_end - psz_string);
439 else if ( ppsz_end != NULL )
440 *ppsz_end = _psz_string + strlen(_psz_string);
442 if ( i_default_port != 0 && (psz_port == NULL || !*psz_port) )
444 sprintf( psz_port_buffer, "%u", i_default_port );
445 psz_port = psz_port_buffer;
448 if ( psz_node[0] == '\0' )
450 free( psz_string );
451 return NULL;
454 memset( &hint, 0, sizeof(hint) );
455 hint.ai_family = i_family;
456 hint.ai_socktype = SOCK_DGRAM;
457 hint.ai_protocol = 0;
458 hint.ai_flags = AI_PASSIVE | AI_NUMERICHOST | AI_NUMERICSERV | AI_ADDRCONFIG;
459 if ( (i_ret = getaddrinfo( psz_node, psz_port, NULL, &p_res )) != 0 )
461 msg_Warn( NULL, "getaddrinfo(host=%s, port=%s) error: %s",
462 psz_node, psz_port ? psz_port : "", gai_strerror(i_ret) );
463 free( psz_string );
464 return NULL;
467 free( psz_string );
468 return p_res;
471 /*****************************************************************************
472 * psi_pack_section: return psi section
473 * Note: Allocates the return value. The caller must free it.
474 *****************************************************************************/
475 uint8_t *psi_pack_section( uint8_t *p_section, unsigned int *pi_size ) {
476 uint8_t *p_flat_section;
477 uint16_t psi_length = psi_get_length( p_section ) + PSI_HEADER_SIZE;
478 *pi_size = 0;
480 p_flat_section = malloc( psi_length );
481 if ( !p_flat_section )
482 return NULL;
484 *pi_size = psi_length;
485 memcpy( p_flat_section, p_section, psi_length );
487 return p_flat_section;
490 /*****************************************************************************
491 * psi_pack_sections: return psi sections as array
492 * Note: Allocates the return value. The caller must free it.
493 *****************************************************************************/
494 uint8_t *psi_pack_sections( uint8_t **pp_sections, unsigned int *pi_size ) {
495 uint8_t i_last_section;
496 uint8_t *p_flat_section;
497 unsigned int i, i_pos = 0;
499 if ( !psi_table_validate( pp_sections ) )
500 return NULL;
502 i_last_section = psi_table_get_lastsection( pp_sections );
504 /* Calculate total size */
505 *pi_size = 0;
506 for ( i = 0; i <= i_last_section; i++ )
508 uint8_t *p_section = psi_table_get_section( pp_sections, i );
509 *pi_size += psi_get_length( p_section ) + PSI_HEADER_SIZE;
512 p_flat_section = malloc( *pi_size );
513 if ( !p_flat_section )
514 return NULL;
516 for ( i = 0; i <= i_last_section; i++ )
518 uint8_t *p_section = psi_table_get_section( pp_sections, i );
519 uint16_t psi_length = psi_get_length( p_section ) + PSI_HEADER_SIZE;
521 memcpy( p_flat_section + i_pos, p_section, psi_length );
522 i_pos += psi_length;
525 return p_flat_section;
529 /*****************************************************************************
530 * psi_unpack_sections: return psi sections
531 * Note: Allocates psi_table, the result must be psi_table_free()'ed
532 *****************************************************************************/
533 uint8_t **psi_unpack_sections( uint8_t *p_flat_sections, unsigned int i_size ) {
534 uint8_t **pp_sections;
535 unsigned int i, i_offset = 0;
537 pp_sections = psi_table_allocate();
538 if ( !pp_sections )
540 msg_Err( NULL, "%s: cannot allocate PSI table\n", __func__ );
541 return NULL;
544 psi_table_init( pp_sections );
546 for ( i = 0; i < PSI_TABLE_MAX_SECTIONS; i++ ) {
547 uint8_t *p_section = p_flat_sections + i_offset;
548 uint16_t i_section_len = psi_get_length( p_section ) + PSI_HEADER_SIZE;
550 if ( !psi_validate( p_section ) )
552 msg_Err( NULL, "%s: Invalid section %d\n", __func__, i );
553 psi_table_free( pp_sections );
554 return NULL;
557 /* Must use allocated section not p_flat_section + offset directly! */
558 uint8_t *p_section_local = psi_private_allocate();
559 if ( !p_section_local )
561 msg_Err( NULL, "%s: cannot allocate PSI private\n", __func__ );
562 psi_table_free( pp_sections );
563 return NULL;
565 memcpy( p_section_local, p_section, i_section_len );
567 /* We ignore the return value of psi_table_section(), because it is useless
568 in this case. We are building the table section by section and when we have
569 more than one section in a table, psi_table_section() returns false when section
570 0 is added. */
571 psi_table_section( pp_sections, p_section_local );
573 i_offset += i_section_len;
574 if ( i_offset >= i_size - 1 )
575 break;
578 return pp_sections;