/* * Receive data */ static int iptv_http_data ( http_client_t *hc, void *buf, size_t len ) { iptv_mux_t *im = hc->hc_aux; if (im == NULL || hc->hc_code != HTTP_STATUS_OK) return 0; if (im->im_m3u_header) { sbuf_append(&im->mm_iptv_buffer, buf, len); return 0; } pthread_mutex_lock(&iptv_lock); sbuf_append(&im->mm_iptv_buffer, buf, len); tsdebug_write((mpegts_mux_t *)im, buf, len); if (len > 0) iptv_input_recv_packets(im, len); pthread_mutex_unlock(&iptv_lock); return 0; }
/* read arguments for .ds and .char */ static void mkargs_ds(struct sbuf *sbuf) { char *s = read_name(n_cp); sbuf_append(sbuf, s); sbuf_add(sbuf, 0); free(s); s = read_string(); if (s) { sbuf_append(sbuf, s); sbuf_add(sbuf, 0); free(s); } jmp_eol(); }
static void tr_coa(char **args) { char *src = args[1]; char *dst = args[2]; if (src && dst && str_get(map(src))) { struct sbuf sb; sbuf_init(&sb); if (str_get(map(dst))) sbuf_append(&sb, str_get(map(dst))); sbuf_append(&sb, str_get(map(src))); str_set(map(dst), sbuf_buf(&sb)); sbuf_done(&sb); } }
static int avc_parse_nal_units(sbuf_t *sb, const uint8_t *buf_in, int size) { const uint8_t *p = buf_in; const uint8_t *end = p + size; const uint8_t *nal_start, *nal_end; //printf("CONVERT SIZE %d\n", size); size = 0; nal_start = avc_find_startcode(p, end); while (nal_start < end) { while(!*(nal_start++)); nal_end = avc_find_startcode(nal_start, end); /*printf("%4d bytes %5d : %d\n", nal_end - nal_start, nal_start - buf_in, nal_end - buf_in);*/ int l = nal_end - nal_start; if (l) { sbuf_put_be32(sb, l); sbuf_append(sb, nal_start, l); size += 4 + l; } nal_start = nal_end; } return size; }
static ssize_t iptv_udp_read ( iptv_input_t *mi, iptv_mux_t *im ) { int i, n; struct iovec *iovec; udp_multirecv_t *um = im->im_data; ssize_t res = 0; n = udp_multirecv_read(um, im->mm_iptv_fd, IPTV_PKTS, &iovec); if (n < 0) return -1; im->mm_iptv_rtp_seq &= ~0xfff; for (i = 0; i < n; i++, iovec++) { if (iovec->iov_len <= 0) continue; if (*(uint8_t *)iovec->iov_base != 0x47) { im->mm_iptv_rtp_seq++; continue; } sbuf_append(&im->mm_iptv_buffer, iovec->iov_base, iovec->iov_len); res += iovec->iov_len; } if (im->mm_iptv_rtp_seq < 0xffff && im->mm_iptv_rtp_seq > 0x3ff) { tvherror(LS_IPTV, "receving non-raw UDP data for %s!", im->mm_nicename); im->mm_iptv_rtp_seq = 0x10000; /* no further logs! */ } return res; }
static void macrobody(struct sbuf *sbuf, char *end) { int first = 1; int c; char *req = NULL; cp_back('\n'); cp_copymode(1); while ((c = cp_next()) >= 0) { if (sbuf && !first) sbuf_add(sbuf, c); first = 0; if (c == '\n') { if ((c = cp_next()) != c_cc) { cp_back(c); continue; } req = read_name(n_cp); if (!strcmp(end, req)) { in_push(end, NULL); cp_back(c_cc); break; } if (sbuf) { sbuf_add(sbuf, c_cc); sbuf_append(sbuf, req); } free(req); req = NULL; } } free(req); cp_copymode(0); }
/* * Complete data */ static int iptv_http_complete ( http_client_t *hc ) { iptv_mux_t *im = hc->hc_aux; char *url; url_t u; int r; if (im->im_m3u_header) { im->im_m3u_header = 0; sbuf_append(&im->mm_iptv_buffer, "", 1); url = iptv_http_m3u((char *)im->mm_iptv_buffer.sb_data); sbuf_reset(&im->mm_iptv_buffer, IPTV_BUF_SIZE); if (url == NULL) { tvherror("iptv", "m3u contents parsing failed"); return 0; } urlinit(&u); if (!urlparse(url, &u)) { hc->hc_keepalive = 0; r = http_client_simple_reconnect(hc, &u); if (r < 0) tvherror("iptv", "cannot reopen http client: %d'", r); } else { tvherror("iptv", "m3u url invalid '%s'", url); } urlreset(&u); free(url); return 0; } return 0; }
/* read arguments for .nr */ static void mkargs_reg1(struct sbuf *sbuf) { char *s = read_name(n_cp); sbuf_append(sbuf, s); sbuf_add(sbuf, 0); free(s); mkargs_req(sbuf); }
/* read arguments for .ochar */ static void mkargs_ochar(struct sbuf *sbuf) { char *s = read_name(0); sbuf_append(sbuf, s); sbuf_add(sbuf, 0); free(s); mkargs_ds(sbuf); }
/* * Complete data */ static int iptv_http_complete ( http_client_t *hc ) { iptv_mux_t *im = hc->hc_aux; char *url, *url2, *s, *p; url_t u; int r; if (im->im_m3u_header) { im->im_m3u_header = 0; sbuf_append(&im->mm_iptv_buffer, "", 1); url = iptv_http_m3u((char *)im->mm_iptv_buffer.sb_data); sbuf_reset(&im->mm_iptv_buffer, IPTV_BUF_SIZE); if (url == NULL) { tvherror("iptv", "m3u contents parsing failed"); return 0; } urlinit(&u); if (url[0] == '/') { s = strdupa(im->mm_iptv_url_raw); if ((p = strchr(s, '/')) != NULL) *p = '\0'; if (!urlparse(s, &u)) goto invalid; url2 = malloc(512); url2[0] = '\0'; if ((p = http_arg_get(&hc->hc_args, "Host")) != NULL) { snprintf(url2, 512, "%s://%s%s", hc->hc_ssl ? "https" : "http", p, url); } else if (im->mm_iptv_url_raw) { snprintf(url2, 512, "%s%s", s, url); } free(url); url = url2; urlinit(&u); } if (!urlparse(url, &u)) { hc->hc_keepalive = 0; r = http_client_simple_reconnect(hc, &u, HTTP_VERSION_1_1); if (r < 0) tvherror("iptv", "cannot reopen http client: %d'", r); } else { invalid: tvherror("iptv", "m3u url invalid '%s'", url); } urlreset(&u); free(url); return 0; } return 0; }
/* * Read thread */ static void * iptv_file_thread ( void *aux ) { iptv_mux_t *im = aux; file_priv_t *fp = im->im_data; ssize_t r; int fd = fp->fd, pause = 0; char buf[32*1024]; off_t off = 0; int64_t mono; int e; #if defined(PLATFORM_DARWIN) fcntl(fd, F_NOCACHE, 1); #endif pthread_mutex_lock(&iptv_lock); while (!fp->shutdown && fd > 0) { while (!fp->shutdown && pause) { mono = mclk() + sec2mono(1); do { e = tvh_cond_timedwait(&fp->cond, &iptv_lock, mono); if (e == ETIMEDOUT) break; } while (ERRNO_AGAIN(e)); } if (fp->shutdown) break; pause = 0; pthread_mutex_unlock(&iptv_lock); r = read(fd, buf, sizeof(buf)); pthread_mutex_lock(&iptv_lock); if (r == 0) break; if (r < 0) { if (ERRNO_AGAIN(errno)) continue; break; } sbuf_append(&im->mm_iptv_buffer, buf, r); if (iptv_input_recv_packets(im, r) == 1) pause = 1; #ifndef PLATFORM_DARWIN #if !ENABLE_ANDROID posix_fadvise(fd, off, r, POSIX_FADV_DONTNEED); #endif #endif off += r; } pthread_mutex_unlock(&iptv_lock); return NULL; }
/* Append RTCP header data to the buffer. Version and padding are set to fixed values, i.e. 2 and 0; */ static void rtcp_append_headers(sbuf_t *buffer, rtcp_t *packet) { packet->common.version = 2; packet->common.p = 0; uint8_t byte = 0; byte |= packet->common.version << 6; byte |= packet->common.p << 5; byte |= packet->common.count; sbuf_put_byte(buffer, byte); byte = packet->common.pt; sbuf_put_byte(buffer, byte); sbuf_append(buffer, &packet->common.length, sizeof(packet->common.length)); }
static void tr_chop(char **args) { struct sbuf sbuf; int id; id = map(args[1]); if (str_get(id)) { sbuf_init(&sbuf); sbuf_append(&sbuf, str_get(id)); if (!sbuf_empty(&sbuf)) { sbuf_cut(&sbuf, sbuf_len(&sbuf) - 1); str_set(id, sbuf_buf(&sbuf)); } sbuf_done(&sbuf); } }
static void tr_de(char **args) { struct sbuf sbuf; int id; if (!args[1]) return; id = map(args[1]); sbuf_init(&sbuf); if (args[0][1] == 'a' && args[0][2] == 'm' && str_get(id)) sbuf_append(&sbuf, str_get(id)); macrobody(&sbuf, args[2] ? args[2] : "."); str_set(id, sbuf_buf(&sbuf)); sbuf_done(&sbuf); if (!n_cp && args[3]) /* parse the arguments as request argv[3] */ str_dset(id, str_dget(map(args[3]))); }
static void tr_coi(char **args) { char *reg = args[1]; char *path = args[2]; char buf[1024]; FILE *fp; if (!reg || !reg[0] || !path || !path[0]) return; if ((fp = fopen(path + 1, "r"))) { struct sbuf sb; sbuf_init(&sb); while (fgets(buf, sizeof(buf), fp)) sbuf_append(&sb, buf); str_set(map(reg), sbuf_buf(&sb)); sbuf_done(&sb); fclose(fp); } }
void testStaticBuffer( Test * pTest) { STATIC_BUFFER sbuffer; char *data1 = "Joshua"; char *data2 = "Anna"; char *data3 = "Christopher"; char *data4 = "Mary"; char data_buffer[480] = ""; char test_data_buffer[480] = ""; char *data; unsigned count; sbuf_init(&sbuffer, NULL, 0); ct_test(pTest, sbuf_empty(&sbuffer) == true); ct_test(pTest, sbuf_data(&sbuffer) == NULL); ct_test(pTest, sbuf_size(&sbuffer) == 0); ct_test(pTest, sbuf_count(&sbuffer) == 0); ct_test(pTest, sbuf_append(&sbuffer, data1, strlen(data1)) == false); sbuf_init(&sbuffer, data_buffer, sizeof(data_buffer)); ct_test(pTest, sbuf_empty(&sbuffer) == true); ct_test(pTest, sbuf_data(&sbuffer) == data_buffer); ct_test(pTest, sbuf_size(&sbuffer) == sizeof(data_buffer)); ct_test(pTest, sbuf_count(&sbuffer) == 0); ct_test(pTest, sbuf_append(&sbuffer, data1, strlen(data1)) == true); ct_test(pTest, sbuf_append(&sbuffer, data2, strlen(data2)) == true); ct_test(pTest, sbuf_append(&sbuffer, data3, strlen(data3)) == true); ct_test(pTest, sbuf_append(&sbuffer, data4, strlen(data4)) == true); strcat(test_data_buffer, data1); strcat(test_data_buffer, data2); strcat(test_data_buffer, data3); strcat(test_data_buffer, data4); ct_test(pTest, sbuf_count(&sbuffer) == strlen(test_data_buffer)); data = sbuf_data(&sbuffer); count = sbuf_count(&sbuffer); ct_test(pTest, memcmp(data, test_data_buffer, count) == 0); ct_test(pTest, count == strlen(test_data_buffer)); ct_test(pTest, sbuf_truncate(&sbuffer, 0) == true); ct_test(pTest, sbuf_count(&sbuffer) == 0); ct_test(pTest, sbuf_size(&sbuffer) == sizeof(data_buffer)); ct_test(pTest, sbuf_append(&sbuffer, data4, strlen(data4)) == true); data = sbuf_data(&sbuffer); count = sbuf_count(&sbuffer); ct_test(pTest, memcmp(data, data4, count) == 0); ct_test(pTest, count == strlen(data4)); return; }
static void download_pipe_read(void *aux) { download_t *dn = aux; ssize_t len; char *s, *p; if (dn->pipe_fd < 0 || dn->pipe_pid == 0) return; while (1) { if (dn->pipe_sbuf.sb_ptr > 50*1024*1024) { errno = EMSGSIZE; goto failed; } sbuf_alloc(&dn->pipe_sbuf, 2048); len = sbuf_read(&dn->pipe_sbuf, dn->pipe_fd); if (len == 0) { s = dn->url ? strdupa(dn->url) : strdupa(""); p = strchr(s, ' '); if (p) *p = '\0'; p = strrchr(s, '/'); if (p) p++; sbuf_append(&dn->pipe_sbuf, "", 1); dn->process(dn->aux, p, NULL, (char *)dn->pipe_sbuf.sb_data, (size_t)dn->pipe_sbuf.sb_ptr); download_pipe_close(dn); return; } else if (len < 0) { if (ERRNO_AGAIN(errno)) break; failed: tvherror(dn->log, "pipe: read failed: %d", errno); download_pipe_close(dn); return; } } gtimer_arm_ms(&dn->pipe_read_timer, download_pipe_read, dn, 250); }
/* read into sbuf until stop; if stop is NULL, stop at whitespace */ static int read_until(struct sbuf *sbuf, char *stop, int (*next)(void), void (*back)(int)) { char cs[GNLEN], cs2[GNLEN]; int c; while ((c = next()) >= 0) { if (c == c_ni) continue; back(c); if (c == '\n') return 1; if (!stop && (c == ' ' || c == '\t')) return 0; charnext(cs, next, back); if (stop && !strcmp(stop, cs)) return 0; charnext_str(cs2, cs); sbuf_append(sbuf, cs2); } return 1; }
static int avc_parse_nal_units(sbuf_t *sb, const uint8_t *buf_in, int size) { const uint8_t *p = buf_in; const uint8_t *end = p + size; const uint8_t *nal_start, *nal_end; size = 0; nal_start = avc_find_startcode(p, end); for (;;) { while (nal_start < end && !*(nal_start++)); if (nal_start == end) break; nal_end = avc_find_startcode(nal_start, end); int l = nal_end - nal_start; sbuf_put_be32(sb, l); sbuf_append(sb, nal_start, l); size += 4 + l; nal_start = nal_end; } return size; }
/* Append RTCP receiver report data to the buffer. */ static void rtcp_append_rr(sbuf_t *buffer, rtcp_t *packet) { uint8_t byte = 0; rtcp_rr_t report = packet->r.rr.rr[0]; sbuf_append(buffer, &packet->r.rr.ssrc, sizeof(packet->r.rr.ssrc)); sbuf_append(buffer, &report.ssrc, sizeof(report.ssrc)); byte = report.fraction; sbuf_put_byte(buffer, byte); // Set the lost number in 3 times byte = (report.lost & 0xff0000) >> 16; sbuf_put_byte(buffer, byte); byte = (report.lost & 0x00ff00) >> 8; sbuf_put_byte(buffer, byte); byte = report.lost & 0x0000ff; sbuf_put_byte(buffer, byte); sbuf_append(buffer, &report.last_seq, sizeof(report.last_seq)); sbuf_append(buffer, &report.jitter, sizeof(report.jitter)); sbuf_append(buffer, &report.lsr, sizeof(report.lsr)); sbuf_append(buffer, &report.dlsr, sizeof(report.dlsr)); }
static int isom_write_avcc(sbuf_t *sb, const uint8_t *data, int len) { if (len > 6) { /* check for h264 start code */ if (RB32(data) == 0x00000001 || RB24(data) == 0x000001) { uint8_t *buf=NULL, *end, *start; uint32_t *sps_size_array=0, *pps_size_array=0; uint32_t pps_count=0,sps_count=0; uint8_t **sps_array=0, **pps_array=0; int i; int ret = avc_parse_nal_units_buf(data, &buf, &len); if (ret < 0) return ret; start = buf; end = buf + len; /* look for sps and pps */ while (buf < end) { unsigned int size; uint8_t nal_type; size = RB32(buf); nal_type = buf[4] & 0x1f; if (nal_type == 7) { /* SPS */ sps_array = realloc(sps_array,sizeof(uint8_t*)*(sps_count+1)); sps_size_array = realloc(sps_size_array,sizeof(uint32_t)*(sps_count+1)); sps_array[sps_count] = buf + 4; sps_size_array[sps_count] = size; sps_count++; } else if (nal_type == 8) { /* PPS */ pps_size_array = realloc(pps_size_array,sizeof(uint32_t)*(pps_count+1)); pps_array = realloc(pps_array,sizeof (uint8_t*)*(pps_count+1)); pps_array[pps_count] = buf + 4; pps_size_array[pps_count] = size; pps_count++; } buf += size + 4; } if(!sps_count || !pps_count) { free(start); if (sps_count) free(sps_array); if (pps_count) free(pps_array); return -1; } sbuf_put_byte(sb, 1); /* version */ sbuf_put_byte(sb, sps_array[0][1]); /* profile */ sbuf_put_byte(sb, sps_array[0][2]); /* profile compat */ sbuf_put_byte(sb, sps_array[0][3]); /* level */ sbuf_put_byte(sb, 0xff); /* 6 bits reserved (111111) + 2 bits nal size length - 1 (11) */ sbuf_put_byte(sb, 0xe0+sps_count); /* 3 bits reserved (111) + 5 bits number of sps (00001) */ for (i=0;i<sps_count;i++) { sbuf_put_be16(sb, sps_size_array[i]); sbuf_append(sb, sps_array[i], sps_size_array[i]); } sbuf_put_byte(sb, pps_count); /* number of pps */ for (i=0;i<pps_count;i++) { sbuf_put_be16(sb, pps_size_array[i]); sbuf_append(sb, pps_array[i], pps_size_array[i]); } free(start); if (sps_count) free(sps_array); if (pps_count) free(pps_array); } else { sbuf_append(sb, data, len); } } return 0; }
ssize_t iptv_rtp_read ( iptv_mux_t *im, udp_multirecv_t *um, void (*pkt_cb)(iptv_mux_t *im, uint8_t *pkt, int len) ) { ssize_t len, hlen; uint8_t *rtp; int i, n; uint32_t seq, nseq, unc = 0; struct iovec *iovec; ssize_t res = 0; n = udp_multirecv_read(um, im->mm_iptv_fd, IPTV_PKTS, &iovec); if (n < 0) return -1; seq = im->mm_iptv_rtp_seq; for (i = 0; i < n; i++, iovec++) { /* Raw packet */ rtp = iovec->iov_base; len = iovec->iov_len; /* Strip RTP header */ if (len < 12) continue; if (pkt_cb) pkt_cb(im, rtp, len); /* Version 2 */ if ((rtp[0] & 0xC0) != 0x80) continue; /* MPEG-TS */ if ((rtp[1] & 0x7F) != 33) continue; /* Header length (4bytes per CSRC) */ hlen = ((rtp[0] & 0xf) * 4) + 12; if (rtp[0] & 0x10) { if (len < hlen+4) continue; hlen += ((rtp[hlen+2] << 8) | rtp[hlen+3]) * 4; hlen += 4; } if (len < hlen || ((len - hlen) % 188) != 0) continue; len -= hlen; /* Use uncorrectable value to notify RTP delivery issues */ nseq = (rtp[2] << 8) | rtp[3]; if (seq == -1) seq = nseq; else if (((seq + 1) & 0xffff) != nseq) { unc += (len / 188) * (uint32_t)((uint16_t)nseq-(uint16_t)(seq+1)); tvhtrace(LS_IPTV, "RTP discontinuity (%i != %i)", seq + 1, nseq); } seq = nseq; /* Move data */ sbuf_append(&im->mm_iptv_buffer, rtp + hlen, len); res += len; } im->mm_iptv_rtp_seq = seq; if (im->mm_active) atomic_add(&im->mm_active->tii_stats.unc, unc); return res; }
int sbuf_append_string(struct sbuf *sbuf, const char *s) { return sbuf_append(sbuf, s, strlen(s)); }