static int open_input(struct variant *var) { AVDictionary *opts = NULL; int ret; struct segment *seg = var->segments[var->cur_seq_no - var->start_seq_no]; av_dict_set(&opts, "seekable", "0", 0); if (seg->key_type == KEY_NONE) { ret = ffurl_open(&var->input, seg->url, AVIO_FLAG_READ, &var->parent->interrupt_callback, &opts); goto cleanup; } else if (seg->key_type == KEY_AES_128) { char iv[33], key[33], url[MAX_URL_SIZE]; if (strcmp(seg->key, var->key_url)) { URLContext *uc; if (ffurl_open(&uc, seg->key, AVIO_FLAG_READ, &var->parent->interrupt_callback, &opts) == 0) { if (ffurl_read_complete(uc, var->key, sizeof(var->key)) != sizeof(var->key)) { av_log(NULL, AV_LOG_ERROR, "Unable to read key file %s\n", seg->key); } ffurl_close(uc); } else { av_log(NULL, AV_LOG_ERROR, "Unable to open key file %s\n", seg->key); } av_strlcpy(var->key_url, seg->key, sizeof(var->key_url)); } ff_data_to_hex(iv, seg->iv, sizeof(seg->iv), 0); ff_data_to_hex(key, var->key, sizeof(var->key), 0); iv[32] = key[32] = '\0'; if (strstr(seg->url, "://")) snprintf(url, sizeof(url), "crypto+%s", seg->url); else snprintf(url, sizeof(url), "crypto:%s", seg->url); if ((ret = ffurl_alloc(&var->input, url, AVIO_FLAG_READ, &var->parent->interrupt_callback)) < 0) goto cleanup; av_opt_set(var->input->priv_data, "key", key, 0); av_opt_set(var->input->priv_data, "iv", iv, 0); /* Need to repopulate options */ av_dict_free(&opts); av_dict_set(&opts, "seekable", "0", 0); if ((ret = ffurl_connect(var->input, &opts)) < 0) { ffurl_close(var->input); var->input = NULL; goto cleanup; } ret = 0; } else ret = AVERROR(ENOSYS); cleanup: av_dict_free(&opts); return ret; }
static int open_input(struct variant *var) { struct segment *seg = var->segments[var->cur_seq_no - var->start_seq_no]; if (seg->key_type == KEY_NONE) { return ffurl_open(&var->input, seg->url, AVIO_FLAG_READ); } else if (seg->key_type == KEY_AES_128) { char iv[33], key[33], url[MAX_URL_SIZE]; int ret; if (strcmp(seg->key, var->key_url)) { URLContext *uc; if (ffurl_open(&uc, seg->key, AVIO_FLAG_READ) == 0) { if (ffurl_read_complete(uc, var->key, sizeof(var->key)) != sizeof(var->key)) { av_log(NULL, AV_LOG_ERROR, "Unable to read key file %s\n", seg->key); } ffurl_close(uc); } else { av_log(NULL, AV_LOG_ERROR, "Unable to open key file %s\n", seg->key); } av_strlcpy(var->key_url, seg->key, sizeof(var->key_url)); } ff_data_to_hex(iv, seg->iv, sizeof(seg->iv), 0); ff_data_to_hex(key, var->key, sizeof(var->key), 0); iv[32] = key[32] = '\0'; if (strstr(seg->url, "://")) snprintf(url, sizeof(url), "crypto+%s", seg->url); else snprintf(url, sizeof(url), "crypto:%s", seg->url); if ((ret = ffurl_alloc(&var->input, url, AVIO_FLAG_READ)) < 0) return ret; av_set_string3(var->input->priv_data, "key", key, 0, NULL); av_set_string3(var->input->priv_data, "iv", iv, 0, NULL); if ((ret = ffurl_connect(var->input)) < 0) { ffurl_close(var->input); var->input = NULL; return ret; } return 0; } return AVERROR(ENOSYS); }
static char *extradata2config(AVCodecContext *c) { char *config; if (c->extradata_size > MAX_EXTRADATA_SIZE) { av_log(c, AV_LOG_ERROR, "Too much extradata!\n"); return NULL; } config = av_malloc(10 + c->extradata_size * 2); if (config == NULL) { av_log(c, AV_LOG_ERROR, "Cannot allocate memory for the config info.\n"); return NULL; } memcpy(config, "; config=", 9); ff_data_to_hex(config + 9, c->extradata, c->extradata_size, 0); config[9 + c->extradata_size * 2] = 0; return config; }
void ff_rdt_calc_response_and_checksum(char response[41], char chksum[9], const char *challenge) { int ch_len = strlen (challenge), i; unsigned char zres[16], buf[64] = { 0xa1, 0xe9, 0x14, 0x9d, 0x0e, 0x6b, 0x3b, 0x59 }; #define XOR_TABLE_SIZE 37 const unsigned char xor_table[XOR_TABLE_SIZE] = { 0x05, 0x18, 0x74, 0xd0, 0x0d, 0x09, 0x02, 0x53, 0xc0, 0x01, 0x05, 0x05, 0x67, 0x03, 0x19, 0x70, 0x08, 0x27, 0x66, 0x10, 0x10, 0x72, 0x08, 0x09, 0x63, 0x11, 0x03, 0x71, 0x08, 0x08, 0x70, 0x02, 0x10, 0x57, 0x05, 0x18, 0x54 }; /* some (length) checks */ if (ch_len == 40) /* what a hack... */ ch_len = 32; else if (ch_len > 56) ch_len = 56; memcpy(buf + 8, challenge, ch_len); /* xor challenge bytewise with xor_table */ for (i = 0; i < XOR_TABLE_SIZE; i++) buf[8 + i] ^= xor_table[i]; av_md5_sum(zres, buf, 64); ff_data_to_hex(response, zres, 16, 1); /* add tail */ strcpy (response + 32, "01d0a8e3"); /* calculate checksum */ for (i = 0; i < 8; i++) chksum[i] = response[i * 4]; chksum[8] = 0; }
static void *circular_buffer_task( void *_handle) { CacheHttpContext * s = (CacheHttpContext *)_handle; URLContext *h = NULL; float config_value = 0.0; void * fp = NULL; int config_ret = 0; while(!s->EXIT) { av_log(h, AV_LOG_ERROR, "----------circular_buffer_task item "); s->reset_flag = 1; if (url_interrupt_cb()) { s->circular_buffer_error = EINTR; goto FAIL; } if(h) { CacheHttp_ffurl_close(h); config_ret = am_getconfig_float("libplayer.hls.dump",&config_value); if(config_ret >= 0 && (int)config_value == 2) CacheHttp_dump_close(fp); h = NULL; } list_item_t * item = getCurrentSegment(NULL); if(!item||(!item->file&&!item->flags&ENDLIST_FLAG)) { usleep(WAIT_TIME); continue; } s->reset_flag = 0; s->item_starttime = item->start_time; s->item_duration = item->duration; s->have_list_end = item->have_list_end; s->ktype = item->ktype; if(item->key_ctx!=NULL&& s->ktype==KEY_AES_128) { ff_data_to_hex(s->iv, item->key_ctx->iv, sizeof(item->key_ctx->iv), 0); ff_data_to_hex(s->key, item->key_ctx->key, sizeof(item->key_ctx->key), 0); s->iv[32] = s->key[32] = '\0'; } if(item&&item->flags&ENDLIST_FLAG) { s->finish_flag =1; } else { s->finish_flag =0; } if(s->finish_flag) { av_log(NULL, AV_LOG_INFO, "ENDLIST_FLAG, return 0\n"); //break; usleep(500*1000); continue; } int err, http_code; char* filename = NULL; if(s->ktype == KEY_NONE) { filename = av_strdup(item->file); } else { char url[MAX_URL_SIZE]; if (strstr(item->file, "://")) snprintf(url, sizeof(url), "crypto+%s", item->file); else snprintf(url, sizeof(url), "crypto:%s", item->file); filename = av_strdup(url); } int retry_num = 0; OPEN_RETRY: if(s->RESET) goto SKIP; err = CacheHttp_advanced_ffurl_open_h(&h, filename,AVIO_FLAG_READ|AVIO_FLAG_NONBLOCK, s->headers, &http_code,s); if (err) { if(url_interrupt_cb()) { if(filename) { av_free(filename); filename = NULL; } break; } if(1 == http_code && !s->have_list_end) { av_log(h, AV_LOG_ERROR, "----------CacheHttpContext : ffurl_open_h 404\n"); if(retry_num++ < LIVE_HTTP_RETRY_TIMES) { usleep(WAIT_TIME); goto OPEN_RETRY; } else { goto SKIP; } } else if(s->have_list_end || ((2 == http_code || 3 == http_code)&& !s->have_list_end)) { usleep(1000*20); goto OPEN_RETRY; } else if(!s->have_list_end&&err ==AVERROR(EIO)) { if(retry_num++ < LIVE_HTTP_RETRY_TIMES) {//if live streaming,just keep on 2s. usleep(WAIT_TIME); goto OPEN_RETRY; } else { av_log(h, AV_LOG_ERROR, "----------CacheHttpContext : ffurl_open_h failed ,%d\n",err); if(filename) { av_free(filename); filename = NULL; } break; } } else { av_log(h, AV_LOG_ERROR, "----------CacheHttpContext : ffurl_open_h failed ,%d\n",err); if(filename) { av_free(filename); filename = NULL; } break; } } if(h && s->seek_flag) { int64_t cur_pos = CacheHttp_ffurl_seek(h, 0, SEEK_CUR); int64_t pos_ret = CacheHttp_ffurl_seek(h, s->seek_pos-cur_pos, SEEK_CUR); av_log(NULL,AV_LOG_INFO,"--------------> cachehttp_seek seek_pos=%lld, pos_ret=%lld", s->seek_pos, pos_ret); s->seek_flag = 0; } s->hd = h; s->item_pos = 0; s->item_size = CacheHttp_ffurl_seek(s->hd, 0, AVSEEK_SIZE); item->item_size = s->item_size; char tmpbuf[TMP_BUFFER_SIZE]; int left = 0; int tmpdatasize = 0; config_ret = am_getconfig_float("libplayer.hls.dump",&config_value); if(config_ret >= 0 && config_value > 0) CacheHttp_dump_open(&fp, filename, (int)config_value); while(!s->EXIT) { if(s->RESET) break; if (url_interrupt_cb()) { s->circular_buffer_error = EINTR; break; } if(!s->hd) break; if(s->hd && tmpdatasize <= 0) { bandwidth_measure_start_read(s->bandwidth_measure); tmpdatasize = CacheHttp_ffurl_read(s->hd, tmpbuf, TMP_BUFFER_SIZE); bandwidth_measure_finish_read(s->bandwidth_measure,tmpdatasize); } //if(tmpdatasize > 0) { pthread_mutex_lock(&s->read_mutex); left = av_fifo_space(s->fifo); left = FFMIN(left, s->fifo->end - s->fifo->wptr); if( !left) { pthread_mutex_unlock(&s->read_mutex); usleep(WAIT_TIME); continue; } left = FFMIN(left, tmpdatasize); if(left >0) { memcpy(s->fifo->wptr, tmpbuf , left); tmpdatasize-=left; } if(tmpdatasize>0) { memmove(tmpbuf, tmpbuf+left , tmpdatasize); } if (left > 0) { config_ret = am_getconfig_float("libplayer.hls.dump",&config_value); if(config_ret >= 0 && config_value > 0) CacheHttp_dump_write(fp, s->fifo->wptr, left); s->fifo->wptr += left; if (s->fifo->wptr >= s->fifo->end) s->fifo->wptr = s->fifo->buffer; s->fifo->wndx += left; s->item_pos += left; } else if(left == AVERROR(EAGAIN) || (left < 0 && s->have_list_end&& left != AVERROR_EOF)) { pthread_mutex_unlock(&s->read_mutex); continue; } else { pthread_mutex_unlock(&s->read_mutex); av_log(h, AV_LOG_ERROR, "---------- circular_buffer_task read left = %d\n", left); break; } pthread_mutex_unlock(&s->read_mutex); //} //usleep(WAIT_TIME); } SKIP: if(filename) { av_free(filename); filename = NULL; } if(!s->RESET) switchNextSegment(NULL); } FAIL: if(h) CacheHttp_ffurl_close(h); s->hd = NULL; s->EXITED = 1; config_ret = am_getconfig_float("libplayer.hls.dump",&config_value); if(config_ret >= 0 && config_value > 0) CacheHttp_dump_close(fp); av_log(NULL, AV_LOG_ERROR, "---------> CacheHttp thread quit !"); return NULL; }
/* Generate a digest reply, according to RFC 2617. */ static char *make_digest_auth(HTTPAuthState *state, const char *username, const char *password, const char *uri, const char *method) { DigestParams *digest = &state->digest_params; int len; uint32_t cnonce_buf[2]; char cnonce[17]; char nc[9]; int i; char A1hash[33], A2hash[33], response[33]; struct AVMD5 *md5ctx; uint8_t hash[16]; char *authstr; digest->nc++; snprintf(nc, sizeof(nc), "%08x", digest->nc); /* Generate a client nonce. */ for (i = 0; i < 2; i++) cnonce_buf[i] = av_get_random_seed(); ff_data_to_hex(cnonce, (const uint8_t*) cnonce_buf, sizeof(cnonce_buf), 1); cnonce[2*sizeof(cnonce_buf)] = 0; md5ctx = av_md5_alloc(); if (!md5ctx) return NULL; av_md5_init(md5ctx); update_md5_strings(md5ctx, username, ":", state->realm, ":", password, NULL); av_md5_final(md5ctx, hash); ff_data_to_hex(A1hash, hash, 16, 1); A1hash[32] = 0; if (!strcmp(digest->algorithm, "") || !strcmp(digest->algorithm, "MD5")) { } else if (!strcmp(digest->algorithm, "MD5-sess")) { av_md5_init(md5ctx); update_md5_strings(md5ctx, A1hash, ":", digest->nonce, ":", cnonce, NULL); av_md5_final(md5ctx, hash); ff_data_to_hex(A1hash, hash, 16, 1); A1hash[32] = 0; } else { /* Unsupported algorithm */ av_free(md5ctx); return NULL; } av_md5_init(md5ctx); update_md5_strings(md5ctx, method, ":", uri, NULL); av_md5_final(md5ctx, hash); ff_data_to_hex(A2hash, hash, 16, 1); A2hash[32] = 0; av_md5_init(md5ctx); update_md5_strings(md5ctx, A1hash, ":", digest->nonce, NULL); if (!strcmp(digest->qop, "auth") || !strcmp(digest->qop, "auth-int")) { update_md5_strings(md5ctx, ":", nc, ":", cnonce, ":", digest->qop, NULL); } update_md5_strings(md5ctx, ":", A2hash, NULL); av_md5_final(md5ctx, hash); ff_data_to_hex(response, hash, 16, 1); response[32] = 0; av_free(md5ctx); if (!strcmp(digest->qop, "") || !strcmp(digest->qop, "auth")) { } else if (!strcmp(digest->qop, "auth-int")) { /* qop=auth-int not supported */ return NULL; } else { /* Unsupported qop value. */ return NULL; } len = strlen(username) + strlen(state->realm) + strlen(digest->nonce) + strlen(uri) + strlen(response) + strlen(digest->algorithm) + strlen(digest->opaque) + strlen(digest->qop) + strlen(cnonce) + strlen(nc) + 150; authstr = av_malloc(len); if (!authstr) return NULL; snprintf(authstr, len, "Authorization: Digest "); /* TODO: Escape the quoted strings properly. */ av_strlcatf(authstr, len, "username=\"%s\"", username); av_strlcatf(authstr, len, ", realm=\"%s\"", state->realm); av_strlcatf(authstr, len, ", nonce=\"%s\"", digest->nonce); av_strlcatf(authstr, len, ", uri=\"%s\"", uri); av_strlcatf(authstr, len, ", response=\"%s\"", response); if (digest->algorithm[0]) av_strlcatf(authstr, len, ", algorithm=%s", digest->algorithm); if (digest->opaque[0]) av_strlcatf(authstr, len, ", opaque=\"%s\"", digest->opaque); if (digest->qop[0]) { av_strlcatf(authstr, len, ", qop=\"%s\"", digest->qop); av_strlcatf(authstr, len, ", cnonce=\"%s\"", cnonce); av_strlcatf(authstr, len, ", nc=%s", nc); } av_strlcatf(authstr, len, "\r\n"); return authstr; }
static int open_input(HLSContext *c, struct playlist *pls) { AVDictionary *opts = NULL; AVDictionary *opts2 = NULL; int ret; struct segment *seg = pls->segments[pls->cur_seq_no - pls->start_seq_no]; // broker prior HTTP options that should be consistent across requests av_dict_set(&opts, "user-agent", c->user_agent, 0); av_dict_set(&opts, "cookies", c->cookies, 0); av_dict_set(&opts, "headers", c->headers, 0); av_dict_set(&opts, "seekable", "0", 0); // Same opts for key request (ffurl_open mutilates the opts so it cannot be used twice) av_dict_copy(&opts2, opts, 0); if (seg->key_type == KEY_NONE) { ret = ffurl_open(&pls->input, seg->url, AVIO_FLAG_READ, &pls->parent->interrupt_callback, &opts); goto cleanup; } else if (seg->key_type == KEY_AES_128) { char iv[33], key[33], url[MAX_URL_SIZE]; if (strcmp(seg->key, pls->key_url)) { URLContext *uc; if (ffurl_open(&uc, seg->key, AVIO_FLAG_READ, &pls->parent->interrupt_callback, &opts2) == 0) { if (ffurl_read_complete(uc, pls->key, sizeof(pls->key)) != sizeof(pls->key)) { av_log(NULL, AV_LOG_ERROR, "Unable to read key file %s\n", seg->key); } ffurl_close(uc); } else { av_log(NULL, AV_LOG_ERROR, "Unable to open key file %s\n", seg->key); } av_strlcpy(pls->key_url, seg->key, sizeof(pls->key_url)); } ff_data_to_hex(iv, seg->iv, sizeof(seg->iv), 0); ff_data_to_hex(key, pls->key, sizeof(pls->key), 0); iv[32] = key[32] = '\0'; if (strstr(seg->url, "://")) snprintf(url, sizeof(url), "crypto+%s", seg->url); else snprintf(url, sizeof(url), "crypto:%s", seg->url); if ((ret = ffurl_alloc(&pls->input, url, AVIO_FLAG_READ, &pls->parent->interrupt_callback)) < 0) goto cleanup; av_opt_set(pls->input->priv_data, "key", key, 0); av_opt_set(pls->input->priv_data, "iv", iv, 0); if ((ret = ffurl_connect(pls->input, &opts)) < 0) { ffurl_close(pls->input); pls->input = NULL; goto cleanup; } ret = 0; } else ret = AVERROR(ENOSYS); cleanup: av_dict_free(&opts); av_dict_free(&opts2); return ret; }