1 /*
2  *  Tvheadend - structures
3  *  Copyright (C) 2007 Andreas Öman
4  *
5  *  This program is free software: you can redistribute it and/or modify
6  *  it under the terms of the GNU General Public License as published by
7  *  the Free Software Foundation, either version 3 of the License, or
8  *  (at your option) any later version.
9  *
10  *  This program is distributed in the hope that it will be useful,
11  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
12  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  *  GNU General Public License for more details.
14  *
15  *  You should have received a copy of the GNU General Public License
16  *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
17  */
18 #ifndef TVHEADEND_H
19 #define TVHEADEND_H
20 
21 #include "build.h"
22 
23 #define _GNU_SOURCE
24 #include <pthread.h>
25 #include <stdlib.h>
26 #include <stdio.h>
27 #include <errno.h>
28 #include <netinet/in.h>
29 #include <sys/socket.h>
30 #include <sys/time.h>
31 #include <libgen.h>
32 #include <string.h>
33 #include <assert.h>
34 #include <unistd.h>
35 #include <limits.h>
36 #if ENABLE_LOCKOWNER || ENABLE_ANDROID
37 #include <sys/syscall.h>
38 #endif
39 #include "queue.h"
40 #include "tvh_string.h"
41 #include "hts_strtab.h"
42 #include "htsmsg.h"
43 #include "tvhlog.h"
44 
45 #include "redblack.h"
46 
47 #include "tvh_locale.h"
48 
49 #define STRINGIFY(s) # s
50 #define SRCLINEID() SRCLINEID2(__FILE__, __LINE__)
51 #define SRCLINEID2(f,l) f ":" STRINGIFY(l)
52 
53 #define ERRNO_AGAIN(e) ((e) == EAGAIN || (e) == EINTR || (e) == EWOULDBLOCK)
54 
55 #include "compat.h"
56 
57 typedef struct {
58   const char     *name;
59   const uint32_t *enabled;
60 } tvh_caps_t;
61 
62 extern int              tvheadend_running;
63 extern const char      *tvheadend_version;
64 extern const char      *tvheadend_cwd;
65 extern const char      *tvheadend_webroot;
66 extern const tvh_caps_t tvheadend_capabilities[];
67 
tvheadend_is_running(void)68 static inline int tvheadend_is_running(void)
69 {
70   return atomic_get(&tvheadend_running);
71 }
72 
73 htsmsg_t *tvheadend_capabilities_list(int check);
74 
75 typedef struct str_list
76 {
77   int max;
78   int num;
79   char **str;
80 } str_list_t;
81 
82 #define PTS_UNSET INT64_C(0x8000000000000000)
83 #define PTS_MASK  INT64_C(0x00000001ffffffff)
84 
85 extern pthread_mutex_t global_lock;
86 extern pthread_mutex_t tasklet_lock;
87 extern pthread_mutex_t fork_lock;
88 
89 extern int tvheadend_webui_port;
90 extern int tvheadend_webui_debug;
91 extern int tvheadend_htsp_port;
92 
93 static inline void
lock_assert0(pthread_mutex_t * l,const char * file,int line)94 lock_assert0(pthread_mutex_t *l, const char *file, int line)
95 {
96 #if 0 && ENABLE_LOCKOWNER
97   assert(l->__data.__owner == syscall(SYS_gettid));
98 #else
99   if(pthread_mutex_trylock(l) == EBUSY)
100     return;
101 
102   fprintf(stderr, "Mutex not held at %s:%d\n", file, line);
103   abort();
104 #endif
105 }
106 
107 #define lock_assert(l) lock_assert0(l, __FILE__, __LINE__)
108 
109 #if defined(__has_feature)
110 #if __has_feature(address_sanitizer) || __has_feature(thread_sanitizer)
111 #define CLANG_SANITIZER 1
112 #endif
113 #endif
114 
115 /*
116  *
117  */
118 
119 typedef struct {
120   pthread_cond_t cond;
121 } tvh_cond_t;
122 
123 
124 /*
125  * Commercial status
126  */
127 typedef enum {
128   COMMERCIAL_UNKNOWN,
129   COMMERCIAL_YES,
130   COMMERCIAL_NO,
131 } th_commercial_advice_t;
132 
133 
134 /*
135  *
136  */
137 #define UILEVEL_DEFAULT  (-1)
138 #define UILEVEL_BASIC    0
139 #define UILEVEL_ADVANCED 1
140 #define UILEVEL_EXPERT   2
141 
142 /*
143  *
144  */
145 #define CHICON_NONE      0
146 #define CHICON_LOWERCASE 1
147 #define CHICON_SVCNAME   2
148 
149 /*
150  *
151  */
152 #define PICON_STANDARD   0
153 #define PICON_ISVCTYPE   1
154 
155 /*
156  * timer support functions
157  */
158 
159 #if ENABLE_GTIMER_CHECK
160 #define GTIMER_TRACEID_ const char *id, const char *fcn,
161 #define GTIMER_FCN(n) check_##n
162 #else
163 #define GTIMER_TRACEID_
164 #define GTIMER_FCN(n) n
165 #endif
166 
167 /*
168  * global timer - monotonic
169  */
170 
171 typedef void (mti_callback_t)(void *opaque);
172 
173 typedef struct mtimer {
174   LIST_ENTRY(mtimer) mti_link;
175   mti_callback_t *mti_callback;
176   void *mti_opaque;
177   int64_t mti_expire;
178 #if ENABLE_GTIMER_CHECK
179   const char *mti_id;
180   const char *mti_fcn;
181 #endif
182 } mtimer_t;
183 
184 void GTIMER_FCN(mtimer_arm_rel)
185   (GTIMER_TRACEID_ mtimer_t *mti, mti_callback_t *callback, void *opaque, int64_t delta);
186 void GTIMER_FCN(mtimer_arm_abs)
187   (GTIMER_TRACEID_ mtimer_t *mti, mti_callback_t *callback, void *opaque, int64_t when);
188 
189 #if ENABLE_GTIMER_CHECK
190 #define mtimer_arm_rel(a, b, c, d) GTIMER_FCN(mtimer_arm_rel)(SRCLINEID(), __func__, a, b, c, d)
191 #define mtimer_arm_abs(a, b, c, d) GTIMER_FCN(mtimer_arm_abs)(SRCLINEID(), __func__, a, b, c, d)
192 #endif
193 
194 void mtimer_disarm(mtimer_t *mti);
195 
196 
197 
198 /*
199  * global timer (based on the current system time - time())
200  */
201 
202 typedef void (gti_callback_t)(void *opaque);
203 
204 typedef struct gtimer {
205   LIST_ENTRY(gtimer) gti_link;
206   gti_callback_t *gti_callback;
207   void *gti_opaque;
208   time_t gti_expire;
209 #if ENABLE_GTIMER_CHECK
210   const char *gti_id;
211   const char *gti_fcn;
212 #endif
213 } gtimer_t;
214 
215 void GTIMER_FCN(gtimer_arm_rel)
216   (GTIMER_TRACEID_ gtimer_t *gti, gti_callback_t *callback, void *opaque, time_t delta);
217 void GTIMER_FCN(gtimer_arm_absn)
218   (GTIMER_TRACEID_ gtimer_t *gti, gti_callback_t *callback, void *opaque, time_t when);
219 
220 #if ENABLE_GTIMER_CHECK
221 #define gtimer_arm_rel(a, b, c, d) GTIMER_FCN(gtimer_arm_rel)(SRCLINEID(), __func__, a, b, c, d)
222 #define gtimer_arm_absn(a, b, c, d) GTIMER_FCN(gtimer_arm_absn)(SRCLINEID(), __func__, a, b, c, d)
223 #endif
224 
225 void gtimer_disarm(gtimer_t *gti);
226 
227 
228 /*
229  * tasklet
230  */
231 
232 typedef void (tsk_callback_t)(void *opaque, int disarmed);
233 
234 typedef struct tasklet {
235   TAILQ_ENTRY(tasklet) tsk_link;
236   tsk_callback_t *tsk_callback;
237   void *tsk_opaque;
238   void (*tsk_free)(void *);
239 } tasklet_t;
240 
241 tasklet_t *tasklet_arm_alloc(tsk_callback_t *callback, void *opaque);
242 void tasklet_arm(tasklet_t *tsk, tsk_callback_t *callback, void *opaque);
243 void tasklet_disarm(tasklet_t *gti);
244 
245 
246 /*
247  * List / Queue header declarations
248  */
249 LIST_HEAD(memoryinfo_list, memoryinfo);
250 LIST_HEAD(access_entry_list, access_entry);
251 LIST_HEAD(th_subscription_list, th_subscription);
252 LIST_HEAD(dvr_vfs_list, dvr_vfs);
253 LIST_HEAD(dvr_config_list, dvr_config);
254 LIST_HEAD(dvr_entry_list, dvr_entry);
255 TAILQ_HEAD(ref_update_queue, ref_update);
256 LIST_HEAD(service_list, service);
257 RB_HEAD(service_tree, service);
258 TAILQ_HEAD(service_queue, service);
259 LIST_HEAD(elementary_stream_list, elementary_stream);
260 TAILQ_HEAD(elementary_stream_queue, elementary_stream);
261 LIST_HEAD(th_muxer_list, th_muxer);
262 LIST_HEAD(th_muxstream_list, th_muxstream);
263 LIST_HEAD(th_descrambler_list, th_descrambler);
264 TAILQ_HEAD(th_refpkt_queue, th_refpkt);
265 TAILQ_HEAD(th_muxpkt_queue, th_muxpkt);
266 LIST_HEAD(dvr_autorec_entry_list, dvr_autorec_entry);
267 LIST_HEAD(dvr_timerec_entry_list, dvr_timerec_entry);
268 TAILQ_HEAD(th_pktref_queue, th_pktref);
269 LIST_HEAD(streaming_target_list, streaming_target);
270 
271 /**
272  * Stream component types
273  */
274 typedef enum {
275   SCT_NONE = -1,
276   SCT_UNKNOWN = 0,
277   SCT_RAW = 1,
278   SCT_MPEG2VIDEO,
279   SCT_MPEG2AUDIO,
280   SCT_H264,
281   SCT_AC3,
282   SCT_TELETEXT,
283   SCT_DVBSUB,
284   SCT_CA,
285   SCT_AAC,     /* AAC-LATM in MPEG-TS, ADTS + AAC in packet form */
286   SCT_MPEGTS,
287   SCT_TEXTSUB,
288   SCT_EAC3,
289   SCT_MP4A,    /* ADTS + AAC in MPEG-TS and packet form */
290   SCT_VP8,
291   SCT_VORBIS,
292   SCT_HEVC,
293   SCT_VP9,
294   SCT_LAST = SCT_VP9
295 } streaming_component_type_t;
296 
297 #define SCT_MASK(t) (1 << (t))
298 
299 #define SCT_ISVIDEO(t) ((t) == SCT_MPEG2VIDEO || (t) == SCT_H264 ||	\
300 			(t) == SCT_VP8 || (t) == SCT_HEVC || (t) == SCT_VP9)
301 
302 #define SCT_ISAUDIO(t) ((t) == SCT_MPEG2AUDIO || (t) == SCT_AC3 || \
303                         (t) == SCT_AAC  || (t) == SCT_MP4A ||	   \
304 			(t) == SCT_EAC3 || (t) == SCT_VORBIS)
305 
306 #define SCT_ISAV(t) (SCT_ISVIDEO(t) || SCT_ISAUDIO(t))
307 
308 #define SCT_ISSUBTITLE(t) ((t) == SCT_TEXTSUB || (t) == SCT_DVBSUB)
309 
310 /*
311  * Scales for signal status values
312  */
313 typedef enum {
314   SIGNAL_STATUS_SCALE_UNKNOWN = 0,
315   SIGNAL_STATUS_SCALE_RELATIVE, // value is unsigned, where 0 means 0% and 65535 means 100%
316   SIGNAL_STATUS_SCALE_DECIBEL   // value is measured in dB * 1000
317 } signal_status_scale_t;
318 
319 /**
320  * The signal status of a tuner
321  */
322 typedef struct signal_status {
323   const char *status_text; /* adapter status text */
324   int snr;      /* signal/noise ratio */
325   signal_status_scale_t snr_scale;
326   int signal;   /* signal strength */
327   signal_status_scale_t signal_scale;
328   int ber;      /* bit error rate */
329   int unc;      /* uncorrected blocks */
330   int ec_bit;   /* error bit count */
331   int tc_bit;   /* total bit count */
332   int ec_block; /* error block count */
333   int tc_block; /* total block count */
334 } signal_status_t;
335 
336 /**
337  * Descramble info
338  */
339 typedef struct descramble_info {
340   uint16_t pid;
341   uint16_t caid;
342   uint32_t provid;
343   uint32_t ecmtime;
344   uint16_t hops;
345   char cardsystem[128];
346   char reader    [128];
347   char from      [128];
348   char protocol  [128];
349 } descramble_info_t;
350 
351 /**
352  *
353  */
354 typedef struct timeshift_status
355 {
356   int     full;
357   int64_t shift;
358   int64_t pts_start;
359   int64_t pts_end;
360 } timeshift_status_t;
361 
362 /**
363  * Streaming skip
364  */
365 typedef struct streaming_skip
366 {
367   enum {
368     SMT_SKIP_ERROR,
369     SMT_SKIP_REL_TIME,
370     SMT_SKIP_ABS_TIME,
371     SMT_SKIP_REL_SIZE,
372     SMT_SKIP_ABS_SIZE,
373     SMT_SKIP_LIVE
374   } type;
375   union {
376     off_t   size;
377     int64_t time;
378   };
379 #if ENABLE_TIMESHIFT
380   timeshift_status_t timeshift;
381 #endif
382 } streaming_skip_t;
383 
384 
385 /**
386  * A streaming pad generates data.
387  * It has one or more streaming targets attached to it.
388  *
389  * We support two different streaming target types:
390  * One is callback driven and the other uses a queue + thread.
391  *
392  * Targets which already has a queueing intrastructure in place (such
393  * as HTSP) does not need any interim queues so it would be a waste. That
394  * is why we have the callback target.
395  *
396  */
397 typedef struct streaming_pad {
398   struct streaming_target_list sp_targets;
399   int sp_ntargets;
400   int sp_reject_filter;
401 } streaming_pad_t;
402 
403 
404 TAILQ_HEAD(streaming_message_queue, streaming_message);
405 
406 /**
407  * Streaming messages types
408  */
409 typedef enum {
410 
411   /**
412    * Packet with data.
413    *
414    * sm_data points to a th_pkt. th_pkt will be unref'ed when
415    * the message is destroyed
416    */
417   SMT_PACKET,
418 
419   /**
420    * Stream grace period
421    *
422    * sm_code contains number of seconds to settle things down
423    */
424 
425   SMT_GRACE,
426 
427   /**
428    * Stream start
429    *
430    * sm_data points to a stream_start struct.
431    * See transport_build_stream_start()
432    */
433 
434   SMT_START,
435 
436   /**
437    * Service status
438    *
439    * Notification about status of source, see TSS_ flags
440    */
441   SMT_SERVICE_STATUS,
442 
443   /**
444    * Signal status
445    *
446    * Notification about frontend signal status
447    */
448   SMT_SIGNAL_STATUS,
449 
450   /**
451    * Descrambler info message
452    *
453    * Notification about descrambler
454    */
455   SMT_DESCRAMBLE_INFO,
456 
457   /**
458    * Streaming stop.
459    *
460    * End of streaming. If sm_code is 0 this was a result to an
461    * unsubscription. Otherwise the reason was external and the
462    * subscription scheduler will attempt to start a new streaming
463    * session.
464    */
465   SMT_STOP,
466 
467   /**
468    * Streaming unable to start.
469    *
470    * sm_code indicates reason. Scheduler will try to restart
471    */
472   SMT_NOSTART,
473 
474   /**
475    * Streaming unable to start (non-fatal).
476    *
477    * sm_code indicates reason. Scheduler will try to restart
478    */
479   SMT_NOSTART_WARN,
480 
481   /**
482    * Raw MPEG TS data
483    */
484   SMT_MPEGTS,
485 
486   /**
487    * Internal message to exit receiver
488    */
489   SMT_EXIT,
490 
491   /**
492    * Set stream speed
493    */
494   SMT_SPEED,
495 
496   /**
497    * Skip the stream
498    */
499   SMT_SKIP,
500 
501   /**
502    * Timeshift status
503    */
504   SMT_TIMESHIFT_STATUS,
505 
506 } streaming_message_type_t;
507 
508 #define SMT_TO_MASK(x) (1 << ((unsigned int)x))
509 
510 
511 #define SM_CODE_OK                        0
512 
513 #define SM_CODE_UNDEFINED_ERROR           1
514 
515 #define SM_CODE_FORCE_OK                  10
516 
517 #define SM_CODE_SOURCE_RECONFIGURED       100
518 #define SM_CODE_BAD_SOURCE                101
519 #define SM_CODE_SOURCE_DELETED            102
520 #define SM_CODE_SUBSCRIPTION_OVERRIDDEN   103
521 #define SM_CODE_INVALID_TARGET            104
522 #define SM_CODE_USER_ACCESS               105
523 #define SM_CODE_USER_LIMIT                106
524 #define SM_CODE_WEAK_STREAM               107
525 #define SM_CODE_USER_REQUEST              108
526 
527 #define SM_CODE_NO_FREE_ADAPTER           200
528 #define SM_CODE_MUX_NOT_ENABLED           201
529 #define SM_CODE_NOT_FREE                  202
530 #define SM_CODE_TUNING_FAILED             203
531 #define SM_CODE_SVC_NOT_ENABLED           204
532 #define SM_CODE_BAD_SIGNAL                205
533 #define SM_CODE_NO_SOURCE                 206
534 #define SM_CODE_NO_SERVICE                207
535 #define SM_CODE_NO_VALID_ADAPTER          208
536 #define SM_CODE_NO_ADAPTERS               209
537 #define SM_CODE_INVALID_SERVICE           210
538 
539 #define SM_CODE_ABORTED                   300
540 
541 #define SM_CODE_NO_DESCRAMBLER            400
542 #define SM_CODE_NO_ACCESS                 401
543 #define SM_CODE_NO_INPUT                  402
544 #define SM_CODE_NO_SPACE                  403
545 
546 typedef enum
547 {
548   SIGNAL_UNKNOWN,
549   SIGNAL_GOOD,
550   SIGNAL_BAD,
551   SIGNAL_FAINT,
552   SIGNAL_NONE
553 } signal_state_t;
554 
555 static struct strtab signal_statetab[] = {
556   { "GOOD",       SIGNAL_GOOD    },
557   { "BAD",        SIGNAL_BAD     },
558   { "FAINT",      SIGNAL_FAINT   },
559   { "NONE",       SIGNAL_NONE    },
560 };
561 
signal2str(signal_state_t st)562 static inline const char * signal2str ( signal_state_t st )
563 {
564   const char *r = val2str(st, signal_statetab);
565   if (!r) r = "UNKNOWN";
566   return r;
567 }
568 
569 /**
570  * Streaming messages are sent from the pad to its receivers
571  */
572 typedef struct streaming_message {
573   TAILQ_ENTRY(streaming_message) sm_link;
574   streaming_message_type_t sm_type;
575 #if ENABLE_TIMESHIFT
576   int64_t sm_time;
577 #endif
578   union {
579     void *sm_data;
580     int sm_code;
581   };
582 } streaming_message_t;
583 
584 /**
585  * A streaming target receives data.
586  */
587 
588 typedef void (st_callback_t)(void *opaque, streaming_message_t *sm);
589 
590 typedef struct {
591   st_callback_t *st_cb;
592   htsmsg_t *(*st_info)(void *opaque, htsmsg_t *list);
593 } streaming_ops_t;
594 
595 typedef struct streaming_target {
596   LIST_ENTRY(streaming_target) st_link;
597   streaming_pad_t *st_pad;               /* Source we are linked to */
598 
599  streaming_ops_t st_ops;
600   void *st_opaque;
601   int st_reject_filter;
602 } streaming_target_t;
603 
604 
605 /**
606  *
607  */
608 typedef struct streaming_queue {
609 
610   streaming_target_t sq_st;
611 
612   pthread_mutex_t sq_mutex;    /* Protects sp_queue */
613   tvh_cond_t  sq_cond;         /* Condvar for signalling new packets */
614 
615   size_t          sq_maxsize;  /* Max queue size (bytes) */
616   size_t          sq_size;     /* Actual queue size (bytes) - only data */
617 
618   struct streaming_message_queue sq_queue;
619 
620 } streaming_queue_t;
621 
622 
623 /**
624  * Simple dynamically growing buffer
625  */
626 typedef struct sbuf {
627   uint8_t *sb_data;
628   int      sb_ptr;
629   int      sb_size;
630   uint16_t sb_err;
631   uint8_t  sb_bswap;
632 } sbuf_t;
633 
634 
635 streaming_component_type_t streaming_component_txt2type(const char *str);
636 const char *streaming_component_type2txt(streaming_component_type_t s);
637 streaming_component_type_t streaming_component_txt2type(const char *s);
638 const char *streaming_component_audio_type2desc(int audio_type);
639 
640 #define MIN(a,b) ((a) < (b) ? (a) : (b))
641 #define MAX(a,b) ((a) > (b) ? (a) : (b))
642 #define MINMAX(a,mi,ma) MAX(mi, MIN(ma, a))
643 #define ARRAY_SIZE(a) (sizeof(a) / sizeof(a[0]))
644 
645 int sri_to_rate(int sri);
646 int rate_to_sri(int rate);
647 
648 extern struct service_list all_transports;
649 
650 extern void scopedunlock(pthread_mutex_t **mtxp);
651 
652 #define scopedlock(mtx) \
653  pthread_mutex_t *scopedlock ## __LINE__ \
654  __attribute__((cleanup(scopedunlock))) = mtx; \
655  pthread_mutex_lock(scopedlock ## __LINE__);
656 
657 #define scopedgloballock() scopedlock(&global_lock)
658 
659 typedef struct th_pipe
660 {
661   int rd;
662   int wr;
663 } th_pipe_t;
664 
665 void doexit(int x);
666 
667 int tvhthread_create
668   (pthread_t *thread, const pthread_attr_t *attr,
669    void *(*start_routine) (void *), void *arg,
670    const char *name);
671 
672 int tvhthread_renice(int value);
673 
674 int tvh_mutex_timedlock(pthread_mutex_t *mutex, int64_t usec);
675 
676 int tvh_cond_init(tvh_cond_t *cond);
677 
678 int tvh_cond_destroy(tvh_cond_t *cond);
679 
680 int tvh_cond_signal(tvh_cond_t *cond, int broadcast);
681 
682 int tvh_cond_wait(tvh_cond_t *cond, pthread_mutex_t *mutex);
683 
684 int tvh_cond_timedwait(tvh_cond_t *cond, pthread_mutex_t *mutex, int64_t monoclock);
685 
686 int tvh_open(const char *pathname, int flags, mode_t mode);
687 
688 int tvh_socket(int domain, int type, int protocol);
689 
690 int tvh_pipe(int flags, th_pipe_t *pipe);
691 
692 void tvh_pipe_close(th_pipe_t *pipe);
693 
694 int tvh_write(int fd, const void *buf, size_t len);
695 
696 FILE *tvh_fopen(const char *filename, const char *mode);
697 
698 void hexdump(const char *pfx, const uint8_t *data, int len);
699 
700 uint32_t tvh_crc32(const uint8_t *data, size_t datalen, uint32_t crc);
701 
702 int base64_decode(uint8_t *out, const char *in, int out_size);
703 
704 char *base64_encode(char *out, int out_size, const uint8_t *in, int in_size);
705 
706 /* Calculate the output size needed to base64-encode x bytes. */
707 #define BASE64_SIZE(x) (((x)+2) / 3 * 4 + 1)
708 
ts_rescale(int64_t ts,int tb)709 static inline int64_t ts_rescale(int64_t ts, int tb)
710 {
711   //  return (ts * tb + (tb / 2)) / 90000LL;
712   return (ts * tb ) / 90000LL;
713 }
714 
ts_rescale_inv(int64_t ts,int tb)715 static inline int64_t ts_rescale_inv(int64_t ts, int tb)
716 {
717   return (ts * 90000LL) / tb;
718 }
719 
720 void sbuf_init(sbuf_t *sb);
721 
722 void sbuf_init_fixed(sbuf_t *sb, int len);
723 
724 void sbuf_free(sbuf_t *sb);
725 
726 void sbuf_reset(sbuf_t *sb, int max_len);
727 
728 void sbuf_reset_and_alloc(sbuf_t *sb, int len);
729 
sbuf_steal_data(sbuf_t * sb)730 static inline void sbuf_steal_data(sbuf_t *sb)
731 {
732   sb->sb_data = NULL;
733   sb->sb_ptr = sb->sb_size = sb->sb_err = 0;
734 }
735 
sbuf_err(sbuf_t * sb,int errors)736 static inline void sbuf_err(sbuf_t *sb, int errors)
737 {
738   sb->sb_err += errors;
739 }
740 
741 void sbuf_alloc_(sbuf_t *sb, int len);
742 
sbuf_alloc(sbuf_t * sb,int len)743 static inline void sbuf_alloc(sbuf_t *sb, int len)
744 {
745   if (sb->sb_ptr + len >= sb->sb_size)
746     sbuf_alloc_(sb, len);
747 }
748 
749 void sbuf_realloc(sbuf_t *sb, int len);
750 
751 void sbuf_append(sbuf_t *sb, const void *data, int len);
752 
753 void sbuf_cut(sbuf_t *sb, int off);
754 
755 void sbuf_put_be32(sbuf_t *sb, uint32_t u32);
756 
757 void sbuf_put_be16(sbuf_t *sb, uint16_t u16);
758 
759 void sbuf_put_byte(sbuf_t *sb, uint8_t u8);
760 
761 ssize_t sbuf_read(sbuf_t *sb, int fd);
762 
sbuf_peek_u8(sbuf_t * sb,int off)763 static inline uint8_t sbuf_peek_u8(sbuf_t *sb, int off) { return sb->sb_data[off]; }
sbuf_peek_s8(sbuf_t * sb,int off)764 static inline  int8_t sbuf_peek_s8(sbuf_t *sb, int off) { return sb->sb_data[off]; }
765 uint16_t sbuf_peek_u16(sbuf_t *sb, int off);
sbuf_peek_s16(sbuf_t * sb,int off)766 static inline int16_t sbuf_peek_s16(sbuf_t *sb, int off) { return sbuf_peek_u16(sb, off); }
767 uint16_t sbuf_peek_u16le(sbuf_t *sb, int off);
sbuf_peek_s16le(sbuf_t * sb,int off)768 static inline int16_t sbuf_peek_s16le(sbuf_t *sb, int off) { return sbuf_peek_u16le(sb, off); }
769 uint16_t sbuf_peek_u16be(sbuf_t *sb, int off);
sbuf_peek_s16be(sbuf_t * sb,int off)770 static inline int16_t sbuf_peek_s16be(sbuf_t *sb, int off) { return sbuf_peek_u16be(sb, off); }
771 uint32_t sbuf_peek_u32(sbuf_t *sb, int off);
sbuf_peek_s32(sbuf_t * sb,int off)772 static inline int32_t sbuf_peek_s32(sbuf_t *sb, int off) { return sbuf_peek_u32(sb, off); }
773 uint32_t sbuf_peek_u32le(sbuf_t *sb, int off);
sbuf_peek_s32le(sbuf_t * sb,int off)774 static inline int32_t sbuf_peek_s32le(sbuf_t *sb, int off) { return sbuf_peek_u32le(sb, off); }
775 uint32_t sbuf_peek_u32be(sbuf_t *sb, int off);
sbuf_peek_s32be(sbuf_t * sb,int off)776 static inline  int32_t sbuf_peek_s32be(sbuf_t *sb, int off) { return sbuf_peek_u32be(sb, off); }
sbuf_peek(sbuf_t * sb,int off)777 static inline uint8_t *sbuf_peek(sbuf_t *sb, int off) { return sb->sb_data + off; }
778 
779 char *md5sum ( const char *str, int lowercase );
780 
781 int makedirs ( int subsys, const char *path, int mode, int mstrict, gid_t gid, uid_t uid );
782 
783 int rmtree ( const char *path );
784 
785 char *regexp_escape ( const char *str );
786 
787 #if ENABLE_ZLIB
788 uint8_t *tvh_gzip_inflate ( const uint8_t *data, size_t size, size_t orig );
789 uint8_t *tvh_gzip_deflate ( const uint8_t *data, size_t orig, size_t *size );
790 int      tvh_gzip_deflate_fd ( int fd, const uint8_t *data, size_t orig, size_t *size, int speed );
791 int      tvh_gzip_deflate_fd_header ( int fd, const uint8_t *data, size_t orig, size_t *size, int speed );
792 #endif
793 
794 /* URL decoding */
795 char to_hex(char code);
796 char *url_encode(const char *str);
797 void http_deescape(char *str);
798 
799 int mpegts_word_count(const uint8_t *tsb, int len, uint32_t mask);
800 
801 int deferred_unlink(const char *filename, const char *rootdir);
802 
803 void sha1_calc(uint8_t *dst, const uint8_t *d1, size_t d1_len, const uint8_t *d2, size_t d2_len);
804 
805 uint32_t gcdU32(uint32_t a, uint32_t b);
deltaI32(int32_t a,int32_t b)806 static inline int32_t deltaI32(int32_t a, int32_t b) { return (a > b) ? (a - b) : (b - a); }
deltaU32(uint32_t a,uint32_t b)807 static inline uint32_t deltaU32(uint32_t a, uint32_t b) { return (a > b) ? (a - b) : (b - a); }
808 
809 #define SKEL_DECLARE(name, type) type *name;
810 #define SKEL_ALLOC(name) do { if (!name) name = calloc(1, sizeof(*name)); } while (0)
811 #define SKEL_USED(name) do { name = NULL; } while (0)
812 #define SKEL_FREE(name) do { free(name); name = NULL; } while (0)
813 
814 htsmsg_t *network_interfaces_enum(void *obj, const char *lang);
815 
816 const char *gmtime2local(time_t gmt, char *buf, size_t buflen);
817 
818 /* glibc wrapper */
819 #if ! ENABLE_QSORT_R
820 void
821 qsort_r(void *base, size_t nmemb, size_t size,
822        int (*cmp)(const void *, const void *, void *), void *aux);
823 #endif /* ENABLE_QSORT_R */
824 
825 void tvh_qsort_r(void *base, size_t nmemb, size_t size, int (*compar)(const void *, const void *, void *), void *arg);
826 
827 /* printing */
828 #ifndef __WORDSIZE
829 # if ULONG_MAX == 0xffffffffffffffff
830 #  define __WORDSIZE 64
831 # elif ULONG_MAX == 0xffffffff
832 #  define __WORDSIZE 32
833 # endif /* ULONG_MAX */
834 #endif /* __WORDSIZE */
835 
836 #if __WORDSIZE == 32 && defined(PLATFORM_FREEBSD)
837 #define PRItime_t       "d"
838 #else
839 #define PRItime_t       "ld"
840 #endif
841 
842 #endif /* TVHEADEND_H */
843