Exemplo n.º 1
0
struct vector *
set_manipulate_array(struct vector *arr1, struct vector *arr2, int op)
{
    struct mapping *m;
    struct vector *r;
    struct svalue tmp, *v;
    char *flags;
    int cnt, res;
    
    if (arr1->size < 1 || arr2->size < 1)
    {
	switch (op)
	{
	case SETARR_SUBTRACT:
	    INCREF(arr1->ref);
	    return arr1;

        case SETARR_INTERSECT:
	    return allocate_array(0);
	}
    }

    m = make_mapping(arr2, 0);
    tmp.type = T_NUMBER;
    tmp.u.number = 1;
    assign_svalue_no_free(get_map_lvalue(m, &arr2->item[0], 1), &tmp);

    res = 0;

    flags = alloca((size_t)arr1->size + 1); 
    for (cnt = 0; cnt < arr1->size; cnt++) 
    {
	flags[cnt] = 0;
	v = get_map_lvalue(m, &(arr1->item[cnt]), 0);
	if (op == SETARR_INTERSECT && v != &const0)
	{
	    flags[cnt] = 1; 
	    res++; 
	}
	else if (op == SETARR_SUBTRACT && v == &const0)
	{
	    flags[cnt] = 1; 
	    res++; 
	}
    }
    r = allocate_array(res);
    if (res) 
    {
	for (cnt = res = 0; cnt < arr1->size; cnt++) 
	{
	    if (flags[cnt]) 
		assign_svalue_no_free(&r->item[res++], &arr1->item[cnt]);
	}
    }
    free_mapping(m);
    return r;
}
Exemplo n.º 2
0
struct svalue 
get_variables(struct object *ob)
{
    int i, j;
    struct vector *names;
    struct vector *values;
    struct svalue res;
    int num_var;
    
    if (ob->flags & O_DESTRUCTED)
	return const0;


    if (!ob->variables)
	return const0;
    
    num_var = ob->prog->num_variables + ob->prog->inherit[ob->prog->num_inherited - 1]
	.variable_index_offset;

    names = allocate_array(num_var);
    values = allocate_array(num_var);
    
    for (j = ob->prog->num_inherited - 1; j >= 0; j--)
	if (!(ob->prog->inherit[j].type & TYPE_MOD_SECOND) &&
	    ob->prog->inherit[j].prog->num_variables > 0)
	{
	    for (i = 0; i < (int)ob->prog->inherit[j].prog->num_variables; i++)
	    {
		if (num_var == 0)
		    error("Wrong number of variables in object.\n");
		names->item[--num_var].type = T_STRING;
		names->item[num_var].string_type = STRING_SSTRING;
		names->item[num_var].u.string =
		    reference_sstring(ob->prog->inherit[j].prog->
				      variable_names[i].name);
		assign_svalue_no_free(&values->item[num_var],
				      &ob->variables[ob->prog->inherit[j]
						     .variable_index_offset + i]);
	    }
	}
    res.type = T_MAPPING;
    res.u.map = make_mapping(names, values);
    free_vector(names);
    free_vector(values);
    return res;
}
Exemplo n.º 3
0
void OTNRTSPStreamer::open_stream_for_client (int client_id)
{
    OTNClient * client = new OTNClient (client_id);
    make_mapping (client_id, client);
    client -> start_stream ();
}
static ngx_int_t ngx_http_mp4frag_handler(ngx_http_request_t *r)
{
    ngx_int_t    rc;
    ngx_chain_t  out;
    u_char *resp_body;
    ngx_buf_t   *resp;
    char *lastslash;
    char *mediafilename;
    u_char *last;
    size_t root;
    ngx_str_t path;
    ngx_str_t index_map = ngx_null_string;
    const u_char *indexptr;
    ngx_str_t mediafile_map = ngx_null_string;
    unsigned medianum, fragnum;
    uint16_t nmedia;
    ngx_str_t videocodecdata, audiocodecdata;
    uint32_t mediaoffset, fragments_offset;
    uint16_t mediafilenamelen;
    uint16_t nsamples, nfragments;
    uint32_t totalsize;
    unsigned int iii;

    if (!(r->method & (NGX_HTTP_GET|NGX_HTTP_HEAD))) {
        return NGX_HTTP_NOT_ALLOWED;
    }
 
    /* discard request body, since we don't need it here */
    rc = ngx_http_discard_request_body(r);
 
    if (rc != NGX_OK) {
        return rc;
    }
 
#if 0
    /* set the 'Content-type' header */
    r->headers_out.content_type.len = sizeof("text/html") - 1;
    r->headers_out.content_type.data = (u_char *) "text/html";
#endif
 
    last = ngx_http_map_uri_to_path(r, &path, &root, 0);
    lastslash = strrchr((char*)path.data, '/');
    if ( lastslash ) {
        path.len = lastslash - (char*)path.data;
    }

    /* определить путь к файлу индекса и номер фрагмента: */
    *lastslash++ = 0;
    // uri - dirname, lastslash - basename
    if ( memcmp(lastslash, "Seg1-Frag", 9) != 0 ) {
        return NGX_HTTP_NOT_FOUND;
    }
    fragnum = atoi(lastslash + 9);

    lastslash = strrchr((char*)path.data, '/');
    if ( !lastslash ) {
        return NGX_HTTP_NOT_FOUND;
    }
    medianum = atoi(lastslash + 1);

    memcpy(lastslash + 1, "index", 6);
    
    if ( (rc = make_mapping((const char *)path.data, &index_map, r)) != NGX_OK ) {
        return rc;
    }
    indexptr = index_map.data;

#define CHECKMAP(nbytes) do { if (indexptr + nbytes >= index_map.data + index_map.len) { ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "index underrun, offset 0x%0x", nbytes); goto GENERAL_ERROR;}  } while(0)

    CHECKMAP(10); /* 8 for signature and 2 for media count */
    if ( memcmp(index_map.data, "mp4frag", 7) != 0 || index_map.data[7] /* version */ > 2 ) {
        free_mapping(&index_map);
        ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "Bad index format in %s", path.data);
        goto GENERAL_ERROR;
    }
    indexptr += 8;

    nmedia = get16(indexptr);
    if ( medianum >= nmedia ) {
        ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "No media #%d in %s, total %d media", medianum, path.data, nmedia);
        goto GENERAL_ERROR;
    }
    indexptr += 2;
    CHECKMAP(nmedia * 4);

    mediaoffset = get32(indexptr + medianum * 4);
    if ( mediaoffset >= index_map.len ) {
        ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "short index in %s", path.data);
        goto GENERAL_ERROR;
    }
    indexptr = index_map.data;
    CHECKMAP(mediaoffset);
    indexptr = index_map.data + mediaoffset;

    CHECKMAP(2);
    mediafilenamelen = get16(indexptr);
    indexptr += 2;
    CHECKMAP(mediafilenamelen);
    if ( index_map.data[7] == 1 ) {
        if ( (mediafilename = ngx_pcalloc(r->pool, mediafilenamelen + 1)) == NULL ) {
            ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "Insufficient memory");
            goto GENERAL_ERROR;
        }
        memcpy(mediafilename, (const char *)indexptr, mediafilenamelen);
        mediafilename[mediafilenamelen] = 0;
    }
    else /* index_map.data[7] == 2 */ {
        mediafilename = (char *)indexptr;
    }

    indexptr += mediafilenamelen;
 
    CHECKMAP(2);
    videocodecdata.len = get16(indexptr);
    indexptr += 2;
    CHECKMAP(videocodecdata.len);
    videocodecdata.data = (u_char*)indexptr;
    indexptr += videocodecdata.len;
    CHECKMAP(2);
    audiocodecdata.len = get16(indexptr);
    indexptr += 2;
    CHECKMAP(audiocodecdata.len);
    audiocodecdata.data = (u_char*)indexptr;
    indexptr += audiocodecdata.len;

    /* number of fragments in the media */
    CHECKMAP(2);
    nfragments = get16(indexptr);
    if ( fragnum > nfragments || fragnum < 1 ) {
        ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "No fragment #%d in media #%d in file %s", fragnum, medianum, path.data);
        goto NOT_FOUND;
    }
    indexptr += 2;

    CHECKMAP(nfragments * 4);

    fragments_offset = get32(indexptr + (fragnum - 1) * 4);
    indexptr = index_map.data;
    CHECKMAP(fragments_offset);
    indexptr += fragments_offset;

    CHECKMAP(6);  /* first entry should present anyway */
    nsamples = get16(indexptr);
    if ( nsamples < 1 ) {
        ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "Number of samples is 0 for media #%d, fragment #%d, index %s",
                      medianum, fragnum, path.data);
        goto GENERAL_ERROR;
    }

    /* total fragment size in bytes: */
    totalsize = get32(indexptr + 2);

    ngx_log_error(NGX_LOG_DEBUG, r->connection->log, 0, "nsamples=%d, totalsize=%d", nsamples, totalsize);

    indexptr += 6;

    /* allocate memory for response */
    if ( (resp_body = ngx_pcalloc(r->pool, totalsize)) == NULL ) {
        ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "Insufficient memory");
        goto GENERAL_ERROR;
    }

    if ( (resp = ngx_pcalloc(r->pool, sizeof(ngx_buf_t))) == NULL ) {
        ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "Insufficient memory");
        goto GENERAL_ERROR;
    }
 
    out.buf = resp;
    out.next = NULL;

    resp->pos = resp_body;
    resp->last = resp_body + totalsize;
    resp->memory = 1; 
    resp->last_buf = 1;
 
    if ( make_mapping(mediafilename, &mediafile_map, r) != NGX_OK ) goto GENERAL_ERROR;
 
    /* generate the fragment */
    write32(resp_body, totalsize);
    memcpy(resp_body + 4, "mdat", 4);

    CHECKMAP(16 * nsamples - 1); /* check if the last byte still inside the index */

    /* fragment timestamp is equal to first sample timestamp */
    resp_body = write_fragment_prefix(resp_body + 8, &videocodecdata, &audiocodecdata, get32(indexptr + 8));

    for ( iii = 0; iii < nsamples; ++iii ) {
        uint32_t offset = get32(indexptr);
        uint32_t size = get32(indexptr + 4);
        uint32_t timestamp = get32(indexptr + 8);
        uint32_t composition_offset = get24(indexptr + 12);
        uint8_t flags = indexptr[15];
        indexptr += 16;
        if ( flags ) {
            resp_body = write_video_packet(resp_body, flags & 2, 0, composition_offset, timestamp,
                                     mediafile_map.data + offset, size);
        }
        else {
            resp_body = write_audio_packet(resp_body, 0, timestamp, mediafile_map.data + offset, size);
        }
    }

    free_mapping(&index_map);
    free_mapping(&mediafile_map);

    if ( resp_body != resp->last ) {
        ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "response buffer overrun");
        return NGX_HTTP_INTERNAL_SERVER_ERROR;
    }

    r->headers_out.status = NGX_HTTP_OK;
    r->headers_out.content_length_n = totalsize;

    rc = ngx_http_send_header(r);
    if (rc == NGX_ERROR || rc > NGX_OK || r->header_only || r->method == NGX_HTTP_HEAD) {
        return rc;
    }

    /* send the buffer chain of your response */
    return ngx_http_output_filter(r, &out);

GENERAL_ERROR:
    free_mapping(&index_map);
    free_mapping(&mediafile_map);
    return NGX_HTTP_INTERNAL_SERVER_ERROR;

NOT_FOUND:
    free_mapping(&index_map);
    free_mapping(&mediafile_map);
    return NGX_HTTP_NOT_FOUND;

}
Exemplo n.º 5
0
static ngx_int_t ngx_http_f4fhds_handler(ngx_http_request_t *r)
{
    ngx_int_t    rc;
    ngx_chain_t  out;
    u_char *resp_body;
    ngx_buf_t   *resp;
    char *lastslash;
    char *segsuffix;
    size_t root;
    ngx_str_t path;
    ngx_str_t index_map = ngx_null_string;
    ngx_str_t mediafile_map = ngx_null_string;
    unsigned fragnum;
    uint32_t totalsize;
    ngx_table_elt_t *self;

    unsigned afraentries;
    unsigned g_afraentries, g_entry_size = 0;
    unsigned globaltable_offset;
    unsigned long long afraoffset = 0, offsetfromafra = 0;
    unsigned entryindex = 0;

    if (!(r->method & (NGX_HTTP_GET|NGX_HTTP_HEAD))) {
        return NGX_HTTP_NOT_ALLOWED;
    }
 
    if ( (rc = ngx_http_discard_request_body(r)) != NGX_OK ) {
        return rc;
    }

    if ( (self = ngx_list_push(&r->headers_out.headers)) == NULL ) {
        ngx_log_error(NGX_LOG_DEBUG, r->connection->log, 0, "Insufficient memory for ngx_list_push");
        return NGX_ERROR;
    }
    self->hash = 1;
    ngx_str_set(&self->key, "X-Inventos-F4FHDS-Version");
    ngx_str_set(&self->value, VERSION);
 
    ngx_http_map_uri_to_path(r, &path, &root, 0);

    ngx_log_error(NGX_LOG_DEBUG, r->connection->log, 0, "path=%s", path.data);

    lastslash = strrchr((char*)path.data, '/');
    ++lastslash;
    segsuffix = (char *)memmem(lastslash, path.len - (lastslash - (char *)path.data), "Seg1-Frag", 9);
    if ( segsuffix == NULL ) {
        return NGX_HTTP_NOT_FOUND;
    }
    segsuffix += 4; /* "Seg1" */

    fragnum = atoi(segsuffix + /* "-Frag" */ 5);
    if ( fragnum < 1 ) {
        return NGX_HTTP_NOT_FOUND;
    }

    memcpy(segsuffix, ".f4x", 4);
    path.len = segsuffix - (char*)path.data + 4;
    segsuffix[4] = 0;

    ngx_log_error(NGX_LOG_DEBUG, r->connection->log, 0, "f4x_path=%s", path.data);
    if ( (rc = make_mapping((const char *)path.data, &index_map, r)) != NGX_OK ) {
        return rc;
    }

    if ( index_map.len < 8 ) {
        ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "Wrong f4x afra size: %d in %s", index_map.len, path.data);
        goto GENERAL_ERROR;
    }
    if ( memcmp(index_map.data + 4, "afra", 4) != 0 ) {
        ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "Wrong f4x format: %s", path.data);
        goto GENERAL_ERROR;
    }
    if ( getboxlen(index_map.data) != index_map.len ) {
        ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "Wrong f4x prefix size: %d in %s", get32(index_map.data), path.data);
        goto GENERAL_ERROR;
    }

    if ( (index_map.data[12] & 0x20) == 0 ) {
        ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "Global entries are not present in %s", path.data);
        goto GENERAL_ERROR;
    }

    afraentries = get32(index_map.data + 17);
    globaltable_offset = 17 + 4 + afraentries * (8 /* time */ + ((index_map.data[12] & 0x40) ? 8 : 4)) + 4;
    if ( index_map.len < globaltable_offset ) {
        ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "Index file too short: %s", path.data);
        goto GENERAL_ERROR;
    }
    g_afraentries = get32(index_map.data + globaltable_offset - 4);

    switch ( index_map.data[12] & 0xc0 ) {
    case 0xc0: 
        g_entry_size = 32; 
        break;
    case 0x80: 
        g_entry_size = 24; 
        break;
    case 0x40: 
        g_entry_size = 28; 
        break;
    case 0:    
        g_entry_size = 20; 
        break;
    }

    ngx_log_error(NGX_LOG_DEBUG, r->connection->log, 0, "globaltable_offset=%d, afraentries=%d, g_afraentries=%d, entrysize=%d", 
                      globaltable_offset, afraentries, g_afraentries, g_entry_size
                     );

    if ( index_map.len < globaltable_offset + g_afraentries * g_entry_size ) {
        ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "Index file too short: %s, len=%d, need=%d, globaltable_offset=%d, afraentries=%d, g_afraentries=%d, entrysize=%d", 
                      path.data, index_map.len, globaltable_offset + g_afraentries * g_entry_size,
                      globaltable_offset, afraentries, g_afraentries, g_entry_size
                     );
        goto GENERAL_ERROR;
    }

#define FIND_SEGMENT(SEGSIZE, FRAGSIZE, AOSIZE, OFASIZE) \
        for ( entryindex = 0; entryindex < g_afraentries; ++entryindex ) { \
            u_char *pentry = index_map.data + globaltable_offset + entryindex * g_entry_size; \
            unsigned segment = get##SEGSIZE (pentry + 8); \
            unsigned fragment = get##FRAGSIZE (pentry + 8 + SEGSIZE/8); \
            if ( segment == 1 && fragment == fragnum ) { \
                afraoffset = get##AOSIZE (pentry + 8 + SEGSIZE/8 + FRAGSIZE/8); \
                offsetfromafra = get##OFASIZE (pentry + 8 + SEGSIZE/8 + FRAGSIZE/8 + AOSIZE/8); \
                break; \
            } \
        }


    switch ( index_map.data[12] & 0xc0 ) {
    case 0xc0: 
        FIND_SEGMENT(32, 32, 64, 64);
        break;
    case 0x80: 
        FIND_SEGMENT(32, 32, 32, 32);
        break;
    case 0x40: 
        FIND_SEGMENT(16, 16, 64, 64);
        break;
    case 0:    
        FIND_SEGMENT(16, 16, 32, 32);
        break;
    }
    if ( entryindex == g_afraentries ) {
        ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "Fragment #%d not found in %s, g_afraentries=%d", fragnum, path.data, g_afraentries);
        goto NOT_FOUND;
    }
    if ( offsetfromafra != 0 ) {
        ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "OffsetFromAfra=%llu not supported, %s", offsetfromafra, path.data);
        goto GENERAL_ERROR;
    }


    memcpy(segsuffix, ".f4f", 4);
    if ( (rc = make_mapping((const char *)path.data, &mediafile_map, r)) != NGX_OK ) {
        return rc;
    }

    if ( mediafile_map.len < afraoffset + 8 ) {
        ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "Mediafile is too short: %s", path.data);
        goto GENERAL_ERROR;
    }

    {
    const u_char *afra = mediafile_map.data + afraoffset;
    unsigned long long afralen = getboxlen(afra);
    const u_char *abst = afra + afralen;
    unsigned long long abstlen = getboxlen(abst);
    const u_char *moof = abst + abstlen;
    unsigned long long mooflen = getboxlen(moof);
    const u_char *mdat = moof + mooflen;
    unsigned long long mdatlen = getboxlen(mdat);
    totalsize = afralen + abstlen + mooflen + mdatlen;
    if ( (resp_body = ngx_pcalloc(r->pool, totalsize)) == NULL ) {
        ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "Insufficient memory");
        goto GENERAL_ERROR;
    }
    memcpy(resp_body, afra, totalsize);
    }

    if ( (resp = ngx_pcalloc(r->pool, sizeof(ngx_buf_t))) == NULL ) {
        ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "Insufficient memory");
        goto GENERAL_ERROR;
    }
 
    out.buf = resp;
    out.next = NULL;

    resp->pos = resp_body;
    resp->last = resp_body + totalsize;
    resp->memory = 1; 
    resp->last_buf = 1;
 
    free_mapping(&index_map);
    free_mapping(&mediafile_map);

    r->headers_out.status = NGX_HTTP_OK;
    r->headers_out.content_length_n = totalsize;

    rc = ngx_http_send_header(r);
    if (rc == NGX_ERROR || rc > NGX_OK || r->header_only || r->method == NGX_HTTP_HEAD) {
        return rc;
    }

    return ngx_http_output_filter(r, &out);

GENERAL_ERROR:
    free_mapping(&index_map);
    free_mapping(&mediafile_map);
    return NGX_HTTP_INTERNAL_SERVER_ERROR;

NOT_FOUND:
    free_mapping(&index_map);
    free_mapping(&mediafile_map);
    return NGX_HTTP_NOT_FOUND;

}