PP_Resource
ppb_image_data_create(PP_Instance instance, PP_ImageDataFormat format,
                      const struct PP_Size *size, PP_Bool init_to_zero)
{
    (void)instance;
    PP_Resource image_data = pp_resource_allocate(PP_RESOURCE_IMAGE_DATA, instance);
    struct pp_image_data_s *id = pp_resource_acquire(image_data, PP_RESOURCE_IMAGE_DATA);
    if (!id) {
        trace_warning("%s, failed to create image data resource\n", __func__);
        return 0;
    }

    id->format = format;
    id->width = size->width;
    id->height = size->height;
    id->stride = id->width * 4;

    (void)init_to_zero; // ignore flag, always clear memory
    id->data = calloc(id->stride * id->height, 1);
    if (!id->data) {
        pp_resource_release(image_data);
        ppb_core_release_resource(image_data);
        trace_warning("%s, can't allocate memory for image\n", __func__);
        return 0;
    }

    id->cairo_surf = cairo_image_surface_create_for_data((void *)id->data, CAIRO_FORMAT_ARGB32,
                                                         id->width, id->height, id->stride);
    pp_resource_release(image_data);
    return image_data;
}
NPError
NPP_New(NPMIMEType pluginType, NPP npp, uint16_t mode, int16_t argc, char *argn[],
        char *argv[], NPSavedData *saved)
{
    trace_info_f("%s\n", __func__);

    NPObject *np_plugin_element_obj;

    int err = npn.getvalue(npp, NPNVPluginElementNPObject, &np_plugin_element_obj);
    if (err != NPERR_NO_ERROR) {
        trace_warning("%s, NPN_GetValue returned %d\n", __func__, err);
        goto done;
    }

    NPVariant result;
    NPString script = {
        .UTF8Characters = resource_text_libpdf_frontend_js,
        .UTF8Length = strlen(resource_text_libpdf_frontend_js),
    };

    if (!npn.evaluate(npp, np_plugin_element_obj, &script, &result)) {
        trace_warning("%s, NPN_Evaluate failed\n", __func__);
    }

done:
    return NPERR_NO_ERROR;
}
示例#3
0
struct PP_Var
ppb_url_util_dev_resolve_relative_to_url(struct PP_Var base_url, struct PP_Var relative_string,
                                         struct PP_URLComponents_Dev *components)
{
    reset_components(components);
    struct PP_Var var = PP_MakeNull();

    if (base_url.type != PP_VARTYPE_STRING) {
        trace_warning("%s, base_url is not a string\n", __func__);
        return PP_MakeNull();
    }

    if (relative_string.type != PP_VARTYPE_STRING) {
        trace_warning("%s, relative_string is not a string\n", __func__);
        return PP_MakeNull();
    }

    const char *s_base_url = ppb_var_var_to_utf8(base_url, NULL);
    const char *s_relative_string = ppb_var_var_to_utf8(relative_string, NULL);

    UriParserStateA ups;
    UriUriA uri_base, uri_rel, uri_result;

    ups.uri = &uri_base;
    if (uriParseUriA(&ups, s_base_url) != URI_SUCCESS) {
        trace_warning("%s, can't parse s_base_url\n", __func__);
        goto err_1;
    }

    ups.uri = &uri_rel;
    if (uriParseUriA(&ups, s_relative_string) != URI_SUCCESS) {
        trace_warning("%s, can't parse s_relative_string\n", __func__);
        goto err_2;
    }

    if (uriAddBaseUriA(&uri_result, &uri_rel, &uri_base) != URI_SUCCESS) {
        trace_warning("%s, can't merge base and rel\n", __func__);
        goto err_3;
    }

    int len;
    uriToStringCharsRequiredA(&uri_result, &len);
    len++;
    char *str = malloc(len);
    uriToStringA(str, &uri_result, len, NULL);
    var = ppb_var_var_from_utf8_z(str);
    free(str);

    if (components)
        parse_url_string(str, components);

err_3:  uriFreeUriMembersA(&uri_result);
err_2:  uriFreeUriMembersA(&uri_rel);
err_1:  uriFreeUriMembersA(&uri_base);
    return var;
}
示例#4
0
/**
 *  \brief Send single buffer data through DMA
 */
static void _usart_dma_tx(const uint8_t* buffer, uint32_t len )
{

	struct _buffer tx = {
		.data = (unsigned char*)buffer,
		.size = len
	};
	usartd_transfert(&usart_desc, 0, &tx,
				_us_dma_tx_callback, 0);

}

/**
 * Callback invoked when data has been received on the USB.
 */
static void _usb_data_received(void *read, uint8_t status,
		uint32_t received, uint32_t remaining)
{
	/* Check that data has been received successfully */
	if (status == USBD_STATUS_SUCCESS) {
		*(uint8_t *)read = 1;
		/* Send back CDC data */
		if (is_cdc_echo_on){

			cdcd_serial_driver_write(usb_buffer, received, 0, 0);
		}
		/* Send data through USART */
		if (is_cdc_serial_on) {

			_usart_dma_tx( usb_buffer, received );
		}

		/* Check if bytes have been discarded */
		if ((received == DATAPACKETSIZE) && (remaining > 0)) {

			trace_warning(
				"_usb_data_received: %u bytes discarded\n\r",
					(unsigned int)remaining);
		}
	} else {

		trace_warning( "_usb_data_received: Transfer error\n\r");
	}
}



/**
 * console help dump
 */
static void _debug_help(void)
{
	printf("-- ESC to Enable/Disable ECHO on cdc serial --\n\r");
	printf("-- Press 't' to test trasfer --\n\r");
}
示例#5
0
static
void
handle_tcp_connect_stage1(struct async_network_task_s *task)
{
    struct evdns_request *req;
    struct sockaddr_in sai;

    memset(&sai, 0, sizeof(sai));
    if (inet_pton(AF_INET, task->host, &sai.sin_addr) == 1) {
        // already a valid IP address
        handle_tcp_connect_stage2(DNS_ERR_NONE, DNS_IPv4_A, 1, 300, &sai.sin_addr, task);
        return;
    }

    // queue DNS request
    req = evdns_base_resolve_ipv4(evdns_b, task->host, DNS_QUERY_NO_SEARCH,
                                  handle_tcp_connect_stage2, task);
    // TODO: what about ipv6?

    if (!req) {
        trace_warning("%s, early dns resolution failure (%s:%u)\n", __func__, task->host,
                      (unsigned int)task->port);
        ppb_message_loop_post_work_with_result(task->callback_ml, task->callback, 0,
                                               PP_ERROR_NAME_NOT_RESOLVED, 0, __func__);
        task_destroy(task);
        return;
    }
}
/**
 * Handles composite-specific USB requests sent by the host, and forwards
 * standard ones to the USB device driver.
 * \param request Pointer to a USBGenericRequest instance.
 */
void dual_cdcd_driver_request_handler(const USBGenericRequest *request)
{
	CDCDSerialPort *p_cdcd = 0;
	uint32_t rc, i;

	LIBUSB_TRACE("NewReq ");

	for (i = 0; i < NUM_PORTS; i ++) {
		p_cdcd = &dual_cdcd_driver.cdcd_serial_port[i];
		rc = cdcd_serial_port_request_handler(p_cdcd, request);
		if (rc == USBRC_SUCCESS)
			break;
	}

	/* Not handled by CDC Serial */
	if (rc != USBRC_SUCCESS) {
		if (usb_generic_request_get_type(request) == USBGenericRequest_STANDARD) {
			usbd_driver_request_handler(request);
		}
		else {
			trace_warning("dual_cdcd_driver_request_handler: Unsupported request (%d,%d)\n\r",
			  usb_generic_request_get_type(request),
			  usb_generic_request_get_request(request));
			usbd_stall(0);
		}
	}

}
示例#7
0
static
void
handle_tcp_connect_stage4(int sock, short event_flags, void *arg)
{
    struct async_network_task_s *task = arg;
    struct pp_tcp_socket_s *ts = pp_resource_acquire(task->resource, PP_RESOURCE_TCP_SOCKET);
    if (!ts) {
        trace_warning("%s, tcp socket resource was closed during request (%s:%u)\n", __func__,
                      task->host, (unsigned int)task->port);
        free(task->addr);
        task_destroy(task);
        return;
    }
    char buf[200];
    socklen_t len = sizeof(buf);

    if (event_flags & EV_TIMEOUT)
        ts->is_connected = 0;
    else
        ts->is_connected = (getpeername(ts->sock, (struct sockaddr *)buf, &len) == 0);

    if (ts->is_connected) {
        ppb_message_loop_post_work_with_result(task->callback_ml, task->callback, 0, PP_OK, 0,
                                               __func__);
        pp_resource_release(task->resource);
        free(task->addr);
        task_destroy(task);
        return;
    }

    // try other addresses, one by one
    task->addr_ptr++;
    if (task->addr_ptr < task->addr_count) {
        pp_resource_release(task->resource);
        handle_tcp_connect_stage3(task);
        return;
    }

    // no addresses left, fail gracefully
    trace_warning("%s, connection failed to all addresses (%s:%u)\n", __func__, task->host,
                  (unsigned int)task->port);
    ppb_message_loop_post_work_with_result(task->callback_ml, task->callback, 0, get_pp_errno(), 0,
                                           __func__);
    pp_resource_release(task->resource);
    free(task->addr);
    task_destroy(task);
}
PP_Resource
ppb_graphics2d_create(PP_Instance instance, const struct PP_Size *size, PP_Bool is_always_opaque)
{
    struct pp_instance_s *pp_i = tables_get_pp_instance(instance);
    if (!pp_i) {
        trace_error("%s, bad instance\n", __func__);
        return 0;
    }
    PP_Resource graphics_2d = pp_resource_allocate(PP_RESOURCE_GRAPHICS2D, pp_i);
    struct pp_graphics2d_s *g2d = pp_resource_acquire(graphics_2d, PP_RESOURCE_GRAPHICS2D);
    if (!g2d) {
        trace_error("%s, can't create graphics2d resource\n", __func__);
        return 0;
    }

    g2d->is_always_opaque = is_always_opaque;
    g2d->scale = config.device_scale;
    g2d->width =  size->width;
    g2d->height = size->height;
    g2d->stride = 4 * size->width;

    g2d->scaled_width = g2d->width * g2d->scale + 0.5;
    g2d->scaled_height = g2d->height * g2d->scale + 0.5;
    g2d->scaled_stride = 4 * g2d->scaled_width;

    g2d->data = calloc(g2d->stride * g2d->height, 1);
    g2d->second_buffer = calloc(g2d->scaled_stride * g2d->scaled_height, 1);
    if (!g2d->data || !g2d->second_buffer) {
        trace_warning("%s, can't allocate memory\n", __func__);
        free_and_nullify(g2d->data);
        free_and_nullify(g2d->second_buffer);
        pp_resource_release(graphics_2d);
        ppb_core_release_resource(graphics_2d);
        return 0;
    }
    g2d->cairo_surf = cairo_image_surface_create_for_data((unsigned char *)g2d->data,
                            CAIRO_FORMAT_ARGB32, g2d->width, g2d->height, g2d->stride);
    g2d->task_list = NULL;

    if (pp_i->is_transparent) {
        // we need XRender picture (which in turn requires X Pixmap) to alpha blend
        // our images with existing pixmap provided by the browser. This is only needed
        // is instance is transparent, therefore depth is always 32-bit.
        pthread_mutex_lock(&display.lock);
        g2d->pixmap = XCreatePixmap(display.x, DefaultRootWindow(display.x), g2d->scaled_width,
                                    g2d->scaled_height, 32);
        XFlush(display.x);
        g2d->xr_pict = XRenderCreatePicture(display.x, g2d->pixmap, display.pictfmt_argb32, 0, 0);
        g2d->gc = XCreateGC(display.x, g2d->pixmap, 0, 0);
        XFlush(display.x);
        pthread_mutex_unlock(&display.lock);
    }

    pp_resource_release(graphics_2d);
    return graphics_2d;
}
int32_t
ppb_tcp_socket_read(PP_Resource tcp_socket, char *buffer, int32_t bytes_to_read,
                    struct PP_CompletionCallback callback)
{
    if (bytes_to_read <= 0) {
        trace_error("%s, bytes_to_read <= 0\n", __func__);
        return PP_ERROR_BADARGUMENT;
    }

    struct pp_tcp_socket_s *ts = pp_resource_acquire(tcp_socket, PP_RESOURCE_TCP_SOCKET);
    if (!ts) {
        trace_error("%s, bad resource\n", __func__);
        return PP_ERROR_BADRESOURCE;
    }

    if (!ts->is_connected) {
        trace_warning("%s, not connected\n", __func__);
        pp_resource_release(tcp_socket);
        return PP_ERROR_FAILED;
    }

    if (ts->seen_eof) {
        trace_warning("%s, seen eof\n", __func__);
        pp_resource_release(tcp_socket);
        return PP_ERROR_FAILED;
    }

    if (bytes_to_read > 1024 * 1024)
        bytes_to_read = 1024 * 1024;

    struct async_network_task_s *task = async_network_task_create();

    task->type = ASYNC_NETWORK_TCP_READ;
    task->resource = tcp_socket;
    task->buffer = buffer;
    task->bufsize = bytes_to_read;
    task->callback = callback;
    pp_resource_release(tcp_socket);

    async_network_task_push(task);
    return PP_OK_COMPLETIONPENDING;
}
示例#10
0
PP_Bool
ppb_instance_bind_graphics(PP_Instance instance, PP_Resource device)
{
    PP_Bool retval;
    struct pp_instance_s *pp_i = tables_get_pp_instance(instance);
    if (!pp_i) {
        trace_error("%s, bad instance\n", __func__);
        return PP_FALSE;
    }

    if (device == 0) {
        // unbind
        pthread_mutex_lock(&pp_i->lock);
        pp_i->graphics = 0;
        pthread_mutex_unlock(&pp_i->lock);
        return PP_TRUE;
    }

    struct pp_graphics2d_s *g2d = pp_resource_acquire(device, PP_RESOURCE_GRAPHICS2D);
    struct pp_graphics3d_s *g3d = pp_resource_acquire(device, PP_RESOURCE_GRAPHICS3D);

    if (g2d) {
        if (pp_i != g2d->instance) {
            retval = PP_FALSE;
            goto done;
        }

        pthread_mutex_lock(&pp_i->lock);
        pp_i->graphics = device;
        pthread_mutex_unlock(&pp_i->lock);
        retval = PP_TRUE;
    } else if (g3d) {
        if (pp_i != g3d->instance) {
            retval = PP_FALSE;
            goto done;
        }

        pthread_mutex_lock(&pp_i->lock);
        pp_i->graphics = device;
        pthread_mutex_unlock(&pp_i->lock);
        pp_resource_release(device);
        retval = PP_TRUE;
    } else {
        trace_warning("%s, unsupported graphics resource %d on instance %d\n", __func__,
                      device, instance);
        retval = PP_FALSE;
    }

done:
    pp_resource_release(device);
    return retval;
}
示例#11
0
PP_Resource
pp_resource_ref(PP_Resource resource)
{
    pthread_mutex_lock(&res_tbl_lock);
    struct pp_resource_generic_s *ptr = g_hash_table_lookup(res_tbl, GINT_TO_POINTER(resource));
    if (ptr) {
        ptr->ref_cnt ++;
    } else {
        trace_warning("%s, no such resource %d\n", __func__, resource);
    }
    pthread_mutex_unlock(&res_tbl_lock);
    return resource;
}
static
void
deactivate_xscreensaver(Display *dpy)
{
    Window xssw = find_xscreensaver_window(dpy);

    if (!xssw) {
        trace_warning("%s, no XScreenSaver's window found\n", __func__);
        return;
    }

    if (is_xscreensaver_active(dpy)) {
        // XScreenSaver already active, deactivating timer makes no sense
        return;
    }

    XEvent  ev;
    Status  status;
    Atom    XA_SCREENSAVER =    XInternAtom(dpy, "SCREENSAVER", False);
    Atom    XA_DEACTIVATE =     XInternAtom(dpy, "DEACTIVATE", False);

    ev.xany.type =              ClientMessage;
    ev.xclient.display =        dpy;
    ev.xclient.window =         xssw;
    ev.xclient.message_type =   XA_SCREENSAVER;
    ev.xclient.format =         32;

    memset(&ev.xclient.data, 0, sizeof(ev.xclient.data));
    ev.xclient.data.l[0] =      XA_DEACTIVATE;
    ev.xclient.data.l[1] =      0;
    ev.xclient.data.l[2] =      0;

    status = XSendEvent(dpy, xssw, False, 0, &ev);
    if (status == 0) {
        trace_warning("%s, can't send event to XScreenSaver's window\n", __func__);
        return;
    }
}
示例#13
0
/**
 * Callback invoked when data has been received on the USB.
 * For USB CDC Serial Port 1
 */
static void _usb_data_received1(void *read,
							uint8_t status,
							uint32_t received,
							uint32_t remaining)
{
	/* Check that data has been received successfully */
	if (status == USBD_STATUS_SUCCESS) {
		*(uint8_t *)read = 1;
		/* Send data through USBSerial 0 */
		while (cdcd_serial_port_write(dual_cdcd_driver_get_serialport(0),
							usb_serial_buffer1,
							received, 0, 0) != USBD_STATUS_SUCCESS);

		/* Check if bytes have been discarded */
		if ((received == DATABUFFERSIZE) && (remaining > 0)) {
			trace_warning(
						"_usb_data_received1: %u bytes discarded\n\r",
						(unsigned int)remaining);
		}
	} else {
		trace_warning( "_usb_data_received1: Transfer error\n\r");
	}
}
int32_t
ppb_video_decoder_decode(PP_Resource video_decoder,
                         const struct PP_VideoBitstreamBuffer_Dev *bitstream_buffer,
                         struct PP_CompletionCallback callback)
{
    struct pp_video_decoder_s *vd = pp_resource_acquire(video_decoder, PP_RESOURCE_VIDEO_DECODER);
    if (!vd) {
        trace_error("%s, bad resource\n", __func__);
        return PP_ERROR_BADRESOURCE;
    }

    if (vd->failed_state) {
        trace_warning("%s, there were errors before, giving up\n", __func__);
        pp_resource_release(video_decoder);
        return PP_ERROR_FAILED;
    }

    void *rawdata = ppb_buffer_map(bitstream_buffer->data);
    if (!rawdata) {
        trace_error("%s, bad bitstream buffer\n", __func__);
        pp_resource_release(video_decoder);
        return PP_ERROR_FAILED;
    }

    uint8_t *inbuf = rawdata;
    size_t   inbuf_sz = bitstream_buffer->size;

    while (inbuf_sz > 0) {
        uint8_t *outbuf = NULL;
        int      outbuf_sz = 0;
        int len = av_parser_parse2(vd->avparser, vd->avctx, &outbuf, &outbuf_sz,
                                   inbuf, inbuf_sz, 0, 0, AV_NOPTS_VALUE);
        if (outbuf_sz > 0)
            decode_frame(vd, outbuf, outbuf_sz, vd->last_consumed_bitstream_buffer_id);
        inbuf += len;
        inbuf_sz -= len;
    }

    vd->last_consumed_bitstream_buffer_id = bitstream_buffer->id;
    ppb_buffer_unmap(bitstream_buffer->data);

    pp_resource_release(video_decoder);
    ppb_core_call_on_main_thread(0, callback, PP_OK);
    return PP_OK_COMPLETIONPENDING;
}
PP_Resource
ppb_ime_input_event_create(PP_Instance instance, PP_InputEvent_Type type, PP_TimeTicks time_stamp,
                           struct PP_Var text, uint32_t segment_number,
                           const uint32_t segment_offsets[], int32_t target_segment,
                           uint32_t selection_start, uint32_t selection_end)
{
    struct pp_instance_s *pp_i = tables_get_pp_instance(instance);
    if (!pp_i) {
        trace_error("%s, bad instance\n", __func__);
        return 0;
    }

    if (type != PP_INPUTEVENT_TYPE_IME_COMPOSITION_START &&
        type != PP_INPUTEVENT_TYPE_IME_COMPOSITION_UPDATE &&
        type != PP_INPUTEVENT_TYPE_IME_COMPOSITION_END &&
        type != PP_INPUTEVENT_TYPE_IME_TEXT)
    {
        trace_warning("%s, wrong type=%d\n", __func__, type);
        return 0;
    }

    PP_Resource input_event = pp_resource_allocate(PP_RESOURCE_INPUT_EVENT, pp_i);
    struct pp_input_event_s *ie = pp_resource_acquire(input_event, PP_RESOURCE_INPUT_EVENT);
    if (!ie) {
        trace_error("%s, can't allocate memory\n", __func__);
        return 0;
    }
    ie->event_class =     PP_INPUTEVENT_CLASS_IME;
    ie->type =            type;
    ie->time_stamp =      time_stamp;
    ie->text =            ppb_var_add_ref2(text);
    ie->segment_number =  segment_number;
    ie->segment_offsets = NULL;
    if (segment_number > 0) {
        ie->segment_offsets = malloc((segment_number + 1) * sizeof(uint32_t));
        memcpy(ie->segment_offsets, segment_offsets, (segment_number + 1) * sizeof(uint32_t));
    }
    ie->target_segment =  target_segment;
    ie->selection_start = selection_start;
    ie->selection_end =   selection_end;

    pp_resource_release(input_event);
    return input_event;
}
示例#16
0
PP_Resource
ppb_graphics2d_create(PP_Instance instance, const struct PP_Size *size, PP_Bool is_always_opaque)
{
    struct pp_instance_s *pp_i = tables_get_pp_instance(instance);
    if (!pp_i) {
        trace_error("%s, bad instance\n", __func__);
        return 0;
    }
    PP_Resource graphics_2d = pp_resource_allocate(PP_RESOURCE_GRAPHICS2D, pp_i);
    struct pp_graphics2d_s *g2d = pp_resource_acquire(graphics_2d, PP_RESOURCE_GRAPHICS2D);
    if (!g2d) {
        trace_error("%s, can't create graphics2d resource\n", __func__);
        return 0;
    }

    g2d->is_always_opaque = is_always_opaque;
    g2d->scale = 1.0;
    g2d->width =  size->width;
    g2d->height = size->height;
    g2d->stride = 4 * size->width;

    g2d->scaled_width =  g2d->width;
    g2d->scaled_height = g2d->height;
    g2d->scaled_stride = g2d->stride;

    g2d->data = calloc(g2d->stride * g2d->height, 1);
    g2d->second_buffer = calloc(g2d->scaled_stride * g2d->scaled_height, 1);
    if (!g2d->data || !g2d->second_buffer) {
        trace_warning("%s, can't allocate memory\n", __func__);
        free_and_nullify(g2d, data);
        free_and_nullify(g2d, second_buffer);
        pp_resource_release(graphics_2d);
        ppb_core_release_resource(graphics_2d);
        return 0;
    }
    g2d->cairo_surf = cairo_image_surface_create_for_data((unsigned char *)g2d->data,
                            CAIRO_FORMAT_ARGB32, g2d->width, g2d->height, g2d->stride);
    g2d->task_list = NULL;

    pp_resource_release(graphics_2d);
    return graphics_2d;
}
PP_Bool
ppb_tcp_socket_get_remote_address(PP_Resource tcp_socket, struct PP_NetAddress_Private *remote_addr)
{
    struct pp_tcp_socket_s *ts = pp_resource_acquire(tcp_socket, PP_RESOURCE_TCP_SOCKET);
    if (!ts) {
        trace_error("%s, bad resource\n", __func__);
        return PP_FALSE;
    }

    if (!ts->is_connected) {
        trace_warning("%s, not connected\n", __func__);
        pp_resource_release(tcp_socket);
        return PP_FALSE;
    }

    socklen_t len = sizeof(remote_addr->data);
    int ret = getpeername(ts->sock, (struct sockaddr *)remote_addr->data, &len);
    remote_addr->size = len;

    pp_resource_release(tcp_socket);
    return ret == 0 ? PP_TRUE : PP_FALSE;
}
示例#18
0
static
void
handle_tcp_connect_stage2(int result, char type, int count, int ttl, void *addresses, void *arg)
{
    struct async_network_task_s *task = arg;

    if (result != DNS_ERR_NONE || count < 1) {
        trace_warning("%s, evdns returned code %d, count = %d (%s:%u)\n", __func__, result, count,
                      task->host, (unsigned int)task->port);
        ppb_message_loop_post_work_with_result(task->callback_ml, task->callback, 0,
                                               PP_ERROR_NAME_NOT_RESOLVED, 0, __func__);
        task_destroy(task);
        return;
    }

    evutil_make_socket_nonblocking(task->sock);

    task->addr_count = count;
    task->addr_ptr = 0;
    task->addr_type = type;

    if (type == DNS_IPv4_A) {
        task->addr = malloc(4 * count);
        memcpy(task->addr, addresses, 4 * count);
    } else if (type == DNS_IPv6_AAAA) {
        task->addr = malloc(16 * count);
        memcpy(task->addr, addresses, 16 * count);
    } else {
        trace_error("%s, bad evdns type %d (%s:%u)\n", __func__, type, task->host,
                    (unsigned int)task->port);
        ppb_message_loop_post_work_with_result(task->callback_ml, task->callback, 0,
                                               PP_ERROR_FAILED, 0, __func__);
        task_destroy(task);
        return;
    }

    handle_tcp_connect_stage3(task);
}
static
Cursor
create_cursor_from_image_data_resource(Display *dpy, Window wnd, PP_Resource image_data,
                                       int hotspot_x, int hotspot_y)
{
    struct pp_image_data_s *id = pp_resource_acquire(image_data, PP_RESOURCE_IMAGE_DATA);
    if (!id) {
        trace_warning("%s, bad resource\n", __func__);
        return None;
    }

    XcursorImage *cursor_image = XcursorImageCreate(id->width, id->height);
    cursor_image->xhot = hotspot_x;
    cursor_image->yhot = hotspot_y;

    memcpy(cursor_image->pixels, id->data, id->stride * id->height);

    Cursor cursor = XcursorImageLoadCursor(dpy, cursor_image);
    XcursorImageDestroy(cursor_image);

    pp_resource_release(image_data);
    return cursor;
}
示例#20
0
PP_Resource
ppb_graphics3d_create(PP_Instance instance, PP_Resource share_context, const int32_t attrib_list[])
{
    struct pp_instance_s *pp_i = tables_get_pp_instance(instance);
    if (!pp_i) {
        trace_error("%s, bad instance\n", __func__);
        return 0;
    }

    GLXContext share_glc = (share_context == 0) ? NULL
                                                : peek_gl_context(share_context);
    // check for required GLX extensions
#if HAVE_GLES2
    if (!display.glx_arb_create_context || !display.glx_arb_create_context_profile ||
        !display.glx_ext_create_context_es2_profile)
    {
        trace_warning("%s, some of GLX_ARB_create_context, GLX_ARB_create_context_profile, "
                      "GLX_EXT_create_context_es2_profile missing\n", __func__);
        return 0;
    }

    if (!display.glXCreateContextAttribsARB) {
        trace_warning("%s, no glXCreateContextAttribsARB found\n", __func__);
        return 0;
    }
#endif

    PP_Resource context = pp_resource_allocate(PP_RESOURCE_GRAPHICS3D, pp_i);
    struct pp_graphics3d_s *g3d = pp_resource_acquire(context, PP_RESOURCE_GRAPHICS3D);
    if (!g3d) {
        trace_error("%s, can't create context\n", __func__);
        return 0;
    }

    int attrib_len = 0;
    while (attrib_list[attrib_len] != PP_GRAPHICS3DATTRIB_NONE) {
        attrib_len += 2;
    }
    attrib_len ++;

    int *cfg_attrs = calloc(attrib_len + 3 * 2, sizeof(int));
    int k2 = 0;
    cfg_attrs[k2++] = GLX_X_RENDERABLE;
    cfg_attrs[k2++] = True;
    cfg_attrs[k2++] = GLX_DRAWABLE_TYPE;
    cfg_attrs[k2++] = GLX_WINDOW_BIT | GLX_PIXMAP_BIT;

    int done = 0;
    int k1 = 0;
    while (!done) {
        switch (attrib_list[k1]) {
        case PP_GRAPHICS3DATTRIB_HEIGHT:
            g3d->height = attrib_list[k1 + 1];
            k1 += 2;
            break;
        case PP_GRAPHICS3DATTRIB_WIDTH:
            g3d->width = attrib_list[k1 + 1];
            k1 += 2;
            break;
        case PP_GRAPHICS3DATTRIB_GPU_PREFERENCE:
        case PP_GRAPHICS3DATTRIB_SWAP_BEHAVIOR:
            // TODO: save these values
            k1 += 2;
            break;
        case PP_GRAPHICS3DATTRIB_NONE:
            cfg_attrs[k2++] = None;
            done = 1;
            break;
        case PP_GRAPHICS3DATTRIB_ALPHA_SIZE:
            cfg_attrs[k2++] = GLX_ALPHA_SIZE;
            cfg_attrs[k2++] = attrib_list[k1 + 1];
            k1 += 2;
            break;
        case PP_GRAPHICS3DATTRIB_BLUE_SIZE:
            cfg_attrs[k2++] = GLX_BLUE_SIZE;
            cfg_attrs[k2++] = attrib_list[k1 + 1];
            k1 += 2;
            break;
        case PP_GRAPHICS3DATTRIB_GREEN_SIZE:
            cfg_attrs[k2++] = GLX_GREEN_SIZE;
            cfg_attrs[k2++] = attrib_list[k1 + 1];
            k1 += 2;
            break;
        case PP_GRAPHICS3DATTRIB_RED_SIZE:
            cfg_attrs[k2++] = GLX_RED_SIZE;
            cfg_attrs[k2++] = attrib_list[k1 + 1];
            k1 += 2;
            break;
        case PP_GRAPHICS3DATTRIB_DEPTH_SIZE:
            cfg_attrs[k2++] = GLX_DEPTH_SIZE;
            cfg_attrs[k2++] = attrib_list[k1 + 1];
            k1 += 2;
            break;
        case PP_GRAPHICS3DATTRIB_STENCIL_SIZE:
            cfg_attrs[k2++] = GLX_STENCIL_SIZE;
            cfg_attrs[k2++] = attrib_list[k1 + 1];
            k1 += 2;
            break;
        case PP_GRAPHICS3DATTRIB_SAMPLES:
            cfg_attrs[k2++] = GLX_SAMPLES;
            cfg_attrs[k2++] = attrib_list[k1 + 1];
            k1 += 2;
            break;
        case PP_GRAPHICS3DATTRIB_SAMPLE_BUFFERS:
            cfg_attrs[k2++] = GLX_SAMPLE_BUFFERS;
            cfg_attrs[k2++] = attrib_list[k1 + 1];
            k1 += 2;
            break;
        case GLX_Y_INVERTED_EXT:
            cfg_attrs[k2++] = GLX_Y_INVERTED_EXT;
            cfg_attrs[k2++] = attrib_list[k1 + 1];
            k1 += 2;
            break;
        case GLX_BIND_TO_TEXTURE_RGBA_EXT:
            cfg_attrs[k2++] = GLX_BIND_TO_TEXTURE_RGBA_EXT;
            cfg_attrs[k2++] = attrib_list[k1 + 1];
            k1 += 2;
            break;
        default:
            // skip unknown attribute
            trace_error("%s, unknown attribute 0x%x\n", __func__, attrib_list[k1]);
            k1 += 1;
            break;
        }
    }

    pthread_mutex_lock(&display.lock);
    int screen = DefaultScreen(display.x);
    int nconfigs = 0;
    GLXFBConfig *fb_cfgs = glXChooseFBConfig(display.x, screen, cfg_attrs, &nconfigs);
    free(cfg_attrs);

    if (!fb_cfgs) {
        trace_error("%s, glXChooseFBConfig returned NULL\n", __func__);
        goto err;
    }

    trace_info_f("%s, glXChooseFBConfig returned %d configs, choosing first one\n", __func__,
                 nconfigs);
    g3d->fb_config = fb_cfgs[0];
    XFree(fb_cfgs);

#if HAVE_GLES2
    // create context implementing OpenGL ES 2.0
    const int ctx_attrs[] = {
        GLX_RENDER_TYPE,                GLX_RGBA_TYPE,
        GLX_CONTEXT_MAJOR_VERSION_ARB,  2,
        GLX_CONTEXT_MINOR_VERSION_ARB,  0,
        GLX_CONTEXT_PROFILE_MASK_ARB,   GLX_CONTEXT_ES2_PROFILE_BIT_EXT,
        None,
    };
#else
    // create context implementing OpenGL 2.0
    // OpenGL ES 2.0 will be emulated with help of shader translator
    const int ctx_attrs[] = {
        GLX_RENDER_TYPE,                GLX_RGBA_TYPE,
        GLX_CONTEXT_MAJOR_VERSION_ARB,  2,
        GLX_CONTEXT_MINOR_VERSION_ARB,  0,
        None,
    };
#endif

    if (display.glXCreateContextAttribsARB) {
        g3d->glc = display.glXCreateContextAttribsARB(display.x, g3d->fb_config, share_glc, True,
                                                      ctx_attrs);
        if (!g3d->glc)
            trace_warning("%s, glXCreateContextAttribsARB returned NULL\n", __func__);

    } else {
        g3d->glc = NULL;
    }

    if (!g3d->glc) {
        // if glXCreateContextAttribsARB is not present or returned NULL,
        // request any GL context
        g3d->glc = glXCreateNewContext(display.x, g3d->fb_config, GLX_RGBA_TYPE, share_glc, True);
        if (!g3d->glc) {
            trace_error("%s, glXCreateNewContext returned NULL\n", __func__);
            goto err;
        }
    }

    g3d->depth = pp_i->is_transparent ? 32 : DefaultDepth(display.x, screen);
    switch (g3d->depth) {
    case 24:
        g3d->xr_pictfmt = display.pictfmt_rgb24;
        break;
    case 32:
        g3d->xr_pictfmt = display.pictfmt_argb32;
        break;
    default:
        trace_error("%s, unsupported g3d->depth (%d)\n", __func__, g3d->depth);
        goto err;
    }

    g3d->pixmap = XCreatePixmap(display.x, DefaultRootWindow(display.x), g3d->width, g3d->height,
                                g3d->depth);
    g3d->glx_pixmap = glXCreatePixmap(display.x, g3d->fb_config, g3d->pixmap, NULL);
    if (g3d->glx_pixmap == None) {
        trace_error("%s, failed to create GLX pixmap\n", __func__);
        goto err;
    }

    XFlush(display.x);
    g3d->xr_pict = XRenderCreatePicture(display.x, g3d->pixmap, g3d->xr_pictfmt, 0, 0);

    int ret = glXMakeCurrent(display.x, g3d->glx_pixmap, g3d->glc);
    if (!ret) {
        trace_error("%s, glXMakeCurrent failed\n", __func__);
        goto err;
    }

    // clear surface
    glClearColor(0.0, 0.0, 0.0, 1.0);
    glClear(GL_COLOR_BUFFER_BIT);

    glXMakeCurrent(display.x, None, NULL);

    g3d->sub_maps = g_hash_table_new(g_direct_hash, g_direct_equal);
    pthread_mutex_unlock(&display.lock);

    pp_resource_release(context);
    return context;
err:
    pthread_mutex_unlock(&display.lock);
    pp_resource_release(context);
    pp_resource_expunge(context);
    return 0;
}
static
void
parse_url_string(const char *s, struct PP_URLComponents_Dev *components)
{
    UriParserStateA ups;
    UriUriA uri;

    ups.uri = &uri;
    if (uriParseUriA(&ups, s) != URI_SUCCESS) {
        uriFreeUriMembersA(&uri);
        trace_warning("failure at %s\n", __func__);
        return;
    }

    components->scheme.begin =   0;     components->scheme.len =   -1;
    components->username.begin = 0;     components->username.len = -1;
    components->password.begin = 0;     components->password.len = -1;
    components->host.begin =     0;     components->host.len =     -1;
    components->port.begin =     0;     components->port.len =     -1;
    components->path.begin =     0;     components->path.len =     -1;
    components->query.begin =    0;     components->query.len =    -1;
    components->ref.begin =      0;     components->ref.len =      -1;

#define C_PARSE(c1, c2) \
    components->c1.begin = uri.c2.first ? uri.c2.first - s + 1 : 0; \
    components->c1.len = uri.c2.first ? uri.c2.afterLast - uri.c2.first : -1;

    C_PARSE(scheme, scheme);
    C_PARSE(username, userInfo);
    C_PARSE(password, userInfo);
    if (components->username.begin > 0) {
        const char *first = s + components->username.begin - 1;
        const char *last = first + components->username.len;
        const char *ptr = first;
        while (ptr < last) {
            if (*ptr == ':') {
                components->username.len = ptr - first;
                components->password.begin += ptr - first + 1;
                components->password.len -= ptr - first + 1;
                if (components->username.len == 0) {
                    components->username.begin = 0;
                    components->username.len = -1;
                }
                if (components->password.len == 0) {
                    components->password.begin = 0;
                    components->password.len = -1;
                }
                break;
            }
            ptr ++;
        }
    }
    C_PARSE(host, hostText);
    C_PARSE(port, portText);
    components->path.begin = uri.pathHead ? uri.pathHead->text.first - s + 1 : 0;
    components->path.len = uri.pathHead ? uri.pathTail->text.afterLast - uri.pathHead->text.first
                                        : -1;
    if (components->path.begin > 0) {
        components->path.begin -= 1;
        components->path.len += 1;
    }
    C_PARSE(query, query);
    C_PARSE(ref, fragment);

#undef C_PARSE

    uriFreeUriMembersA(&uri);
}
static
void
request_buffers(struct pp_video_decoder_s *vd)
{
    const PP_Instance instance = vd->instance->id;
    const struct PP_Size dimensions = { .width = vd->avctx->width,
                                        .height = vd->avctx->height };

    pp_resource_release(vd->self_id);
    // TODO: how many surfaces do we need?
    vd->ppp_video_decoder_dev->ProvidePictureBuffers(instance, vd->self_id, 21, &dimensions,
                                                     GL_TEXTURE_2D);
    pp_resource_acquire(vd->self_id, PP_RESOURCE_VIDEO_DECODER);
}

static
uint32_t
find_free_buffer(struct pp_video_decoder_s *vd)
{
    for (uint32_t idx = 0; idx < vd->buffer_count; idx ++) {
        if (!vd->buffers[idx].used) {
            vd->buffers[idx].used = 1;
            return idx;
        }
    }

    return (uint32_t)-1;
}

static
void
issue_frame(struct pp_video_decoder_s *vd)
{
    AVFrame *frame = vd->avframe;
    uint32_t idx = find_free_buffer(vd);
    int32_t  bitstream_buffer_id = (int32_t)frame->pkt_pts;

    if (idx == (uint32_t)-1) {
        trace_warning("%s, no free buffer available\n", __func__);
        return;
    }

    struct pp_graphics3d_s *g3d = pp_resource_acquire(vd->graphics3d, PP_RESOURCE_GRAPHICS3D);
    if (!g3d) {
        trace_error("%s, bad resource\n", __func__);
        return;
    }

    VASurfaceID va_surf = GPOINTER_TO_SIZE(frame->data[3]);

    pthread_mutex_lock(&display.lock);
    glXMakeCurrent(display.x, g3d->glx_pixmap, g3d->glc);
    glBindTexture(GL_TEXTURE_2D, vd->buffers[idx].texture_id);
    display.glXBindTexImageEXT(display.x, vd->buffers[idx].glx_pixmap, GLX_FRONT_EXT, NULL);
    XFlush(display.x);
    vaPutSurface(display.va, va_surf, vd->buffers[idx].pixmap,
                 0, 0, frame->width, frame->height,
                 0, 0, frame->width, frame->height,
                 NULL, 0, VA_FRAME_PICTURE);
    XFlush(display.x);
    glXMakeCurrent(display.x, None, NULL);
    pthread_mutex_unlock(&display.lock);

    pp_resource_release(vd->graphics3d);

    const PP_Instance instance = vd->instance->id;
    const struct PP_Picture_Dev picture = {
        .picture_buffer_id = vd->buffers[idx].id,
        .bitstream_buffer_id = bitstream_buffer_id,
    };

    pp_resource_release(vd->self_id);
    vd->ppp_video_decoder_dev->PictureReady(instance, vd->self_id, &picture);
    pp_resource_acquire(vd->self_id, PP_RESOURCE_VIDEO_DECODER);
}

static
void
decode_frame(struct pp_video_decoder_s *vd, uint8_t *data, size_t data_len,
             int32_t bitstream_buffer_id)
{
    AVPacket packet;
    av_init_packet(&packet);
    packet.data = data;
    packet.size = data_len;
    packet.pts = bitstream_buffer_id;

    // libavcodec can call hw functions, which in turn can call Xlib functions,
    // therefore we need to lock
    pthread_mutex_lock(&display.lock);
    int got_frame = 0;
    int len = avcodec_decode_video2(vd->avctx, vd->avframe, &got_frame, &packet);
    pthread_mutex_unlock(&display.lock);
    if (len < 0) {
        trace_error("%s, error %d while decoding frame\n", __func__, len);
        return;
    }

    if (got_frame) {
        if (!vd->buffers_were_requested) {
            request_buffers(vd);
            vd->buffers_were_requested = 1;
        }

        issue_frame(vd);
    }
}
PP_Bool
ppb_url_request_info_set_property(PP_Resource request, PP_URLRequestProperty property,
                                  struct PP_Var value)
{
    const char *tmp, *tmp2;
    PP_Bool retval = PP_TRUE;
    struct pp_url_request_info_s *ri = pp_resource_acquire(request, PP_RESOURCE_URL_REQUEST_INFO);
    if (!ri) {
        trace_error("%s, bad resource\n", __func__);
        return PP_FALSE;
    }

#define ENSURE_TYPE(vartype) if (value.type != vartype) { retval = PP_FALSE; break; }

    switch (property) {
    case PP_URLREQUESTPROPERTY_URL:
        ENSURE_TYPE(PP_VARTYPE_STRING);
        free_and_nullify(ri->url);
        tmp = ppb_var_var_to_utf8(value, NULL);
        tmp2 = ltrim(tmp);
        ri->url = strdup(tmp2);
        ri->is_immediate_javascript = (strncasecmp(tmp2, "javascript:", strlen("javascript:"))==0);
        break;
    case PP_URLREQUESTPROPERTY_METHOD:
        ENSURE_TYPE(PP_VARTYPE_STRING);
        tmp = ppb_var_var_to_utf8(value, NULL);
        if (strcmp(tmp, "GET") == 0) {
            ri->method = PP_METHOD_GET;
        } else if (strcmp(tmp, "POST") == 0) {
            ri->method = PP_METHOD_POST;
        } else {
            trace_warning("%s, unknown method %s\n", __func__, tmp);
            ri->method = PP_METHOD_UNKNOWN;
        }
        break;
    case PP_URLREQUESTPROPERTY_HEADERS:
        ENSURE_TYPE(PP_VARTYPE_STRING);
        free_and_nullify(ri->headers);
        ri->headers = strdup(ppb_var_var_to_utf8(value, NULL));
        break;
    case PP_URLREQUESTPROPERTY_STREAMTOFILE:
        ENSURE_TYPE(PP_VARTYPE_BOOL);
        ri->stream_to_file = value.value.as_bool;
        break;
    case PP_URLREQUESTPROPERTY_FOLLOWREDIRECTS:
        ENSURE_TYPE(PP_VARTYPE_BOOL);
        ri->follow_redirects = value.value.as_bool;
        break;
    case PP_URLREQUESTPROPERTY_RECORDDOWNLOADPROGRESS:
        ENSURE_TYPE(PP_VARTYPE_BOOL);
        ri->record_download_progress = value.value.as_bool;
        break;
    case PP_URLREQUESTPROPERTY_RECORDUPLOADPROGRESS:
        ENSURE_TYPE(PP_VARTYPE_BOOL);
        ri->record_upload_progress = value.value.as_bool;
        break;
    case PP_URLREQUESTPROPERTY_CUSTOMREFERRERURL:
        ENSURE_TYPE(PP_VARTYPE_STRING);
        free_and_nullify(ri->custom_referrer_url);
        ri->custom_referrer_url = strdup(ppb_var_var_to_utf8(value, NULL));
        break;
    case PP_URLREQUESTPROPERTY_ALLOWCROSSORIGINREQUESTS:
        ENSURE_TYPE(PP_VARTYPE_BOOL);
        ri->allow_cross_origin_requests = value.value.as_bool;
        break;
    case PP_URLREQUESTPROPERTY_ALLOWCREDENTIALS:
        ENSURE_TYPE(PP_VARTYPE_BOOL);
        ri->allow_credentials = value.value.as_bool;
        break;
    case PP_URLREQUESTPROPERTY_CUSTOMCONTENTTRANSFERENCODING:
        ENSURE_TYPE(PP_VARTYPE_STRING);
        free_and_nullify(ri->custom_content_transfer_encoding);
        ri->custom_content_transfer_encoding = strdup(ppb_var_var_to_utf8(value, NULL));
        break;
    case PP_URLREQUESTPROPERTY_PREFETCHBUFFERUPPERTHRESHOLD:
        ENSURE_TYPE(PP_VARTYPE_INT32);
        ri->prefetch_buffer_upper_threshold = value.value.as_int;
        break;
    case PP_URLREQUESTPROPERTY_PREFETCHBUFFERLOWERTHRESHOLD:
        ENSURE_TYPE(PP_VARTYPE_INT32);
        ri->prefetch_buffer_lower_threshold = value.value.as_int;
        break;
    case PP_URLREQUESTPROPERTY_CUSTOMUSERAGENT:
        ENSURE_TYPE(PP_VARTYPE_STRING);
        free_and_nullify(ri->custom_user_agent);
        ri->custom_user_agent = strdup(ppb_var_var_to_utf8(value, NULL));
        break;
    default:
        trace_error("%s, unknown url request property %d\n", __func__, property);
        retval = PP_FALSE;
        break;
    }

    pp_resource_release(request);
    return retval;
}
示例#24
0
/* Check that pointer is either a tag, a global, or a current heap value */
static int
show_field(int show, Field_t fieldType, ptr_t primary, ptr_t replica,
	int i, int ri, Heap_t** legalHeaps, Bitmap_t** legalStarts)
{
	int isNonheapPointer;
	ptr_t primaryField, replicaField;
	double primaryDoubleField, replicaDoubleField;

	if(fieldType==DoubleField){
		primaryDoubleField = ((double *)primary)[i];
		if(replica)
			replicaDoubleField = ((double *)replica)[ri];
	}
	else{
		primaryField = (ptr_t)primary[i];
		if(replica)
			replicaField = (ptr_t)replica[ri];
	}

	isNonheapPointer = (fieldType == PointerField) &&
		(IsTagData(primaryField) ||
		 IsGlobalData(primaryField) ||
		 primaryField == (ptr_t)uninit_val);

	switch(fieldType){
	case PointerField:
	case OldPointerField:
		if(show){
			char* type = fieldType == PointerField ? "P" : "O";
			printf("%s(%5lx)  ", type, (long)primaryField);
		}
		if(isNonheapPointer
		|| fieldType == OldPointerField
		|| inHeaps(primaryField,legalHeaps,legalStarts))
			;
		else{
			if(inHeaps(primaryField,legalHeaps,NULL))
				trace_error("bad pointer (in range) %lx at %lx[%d]",
					(long)primaryField, (long)primary, i);
			else
				trace_error("bad pointer (out of range) %lx at %lx[%d]",
					(long)primaryField, (long)primary, i);
			return 0;
		}
		if(replica){
			if(isNonheapPointer){
				if(primaryField != replicaField){
					trace_error("replica mismatch: %lx[%d] = *%lx*"
						"  and  %lx[%d] = *%lx*",
						(long)primary, i, (long)primaryField,
						(long)replica, ri, (long)replicaField);
					return 0;
				}
			}
			else{
				/*
					Primary and replica may share in a generational
					collector.
				*/
				if(primaryField != replicaField &&
				(ptr_t)primaryField[-1] != replicaField){
					trace_error("ptr replica mismatch: %lx[%d] = %lx -> *%d*"
						"  and  %lx[%d] = *%lx*",
						(long)primary, i, (long)primaryField,
						primaryField[-1],
						(long)replica, ri, (long)replicaField);
					return 0;
				}
			}
		}
		break;

	case IntField:
		if(show)
			printf("I(%5lx)  ", (long)primaryField);
		if(inHeaps(primaryField,legalHeaps,legalStarts))
			trace_warning("suspicious int %ld at %lx[%d]\n",
				(long)primaryField,(long)primary,i);
		if(replica && primaryField != replicaField){
			trace_error("int replica mismatch: %lx[%d] = *%lx*"
				"  and  %lx[%d] = *%lx*",
				(long)primary,i,(long)primaryField,
				(long)replica,ri,(long)replicaField);
			return 0;
		}
		break;

	case DoubleField:
		if(show)
			printf("R(%10g)  ", primaryDoubleField);
		if(replica
		&& !(isnan(primaryDoubleField) && isnan(replicaDoubleField))
		&& primaryDoubleField != replicaDoubleField){
			trace_error("double replica mismatch: %lx[%d] = *%g*"
				"  and  %lx[%d] = *%g*",
				(long)primary,i,primaryDoubleField,
				(long)replica,ri,replicaDoubleField);
			return 0;
		}
		break;

	default:
		DIE("bad field type in show_field");
	}
	return 1;
}
示例#25
0
static
void
handle_disconnect_stage1(struct async_network_task_s *task)
{
    struct event *ev = evtimer_new(event_b, handle_disconnect_stage2, task);
    struct timeval timeout = {.tv_sec = 0};
    add_event_mapping(task, ev);
    event_add(ev, &timeout);
}

static
void
handle_udp_recv_stage2(int sock, short event_flags, void *arg)
{
    struct async_network_task_s *task = arg;

    struct pp_udp_socket_s *us = pp_resource_acquire(task->resource, PP_RESOURCE_UDP_SOCKET);
    if (!us) {
        trace_error("%s, bad resource\n", __func__);
        task_destroy(task);
        return;
    }

    socklen_t len = sizeof(task->addr_from->data);
    int32_t retval = recvfrom(sock, task->buffer, task->bufsize, 0,
                              (struct sockaddr *)task->addr_from->data, &len);
    task->addr_from->size = len;

    if (task->addr_from_resource)
        pp_resource_unref(task->addr_from_resource);

    if (retval < 0)
        retval = get_pp_errno();
    else if (retval == 0) {
        us->seen_eof = 1;   // TODO: is it needed?
    }

    pp_resource_release(task->resource);
    ppb_message_loop_post_work_with_result(task->callback_ml, task->callback, 0, retval, 0,
                                           __func__);
    task_destroy(task);
}

static
void
handle_udp_recv_stage1(struct async_network_task_s *task)
{
    struct pp_udp_socket_s *us = pp_resource_acquire(task->resource, PP_RESOURCE_UDP_SOCKET);
    if (!us) {
        trace_error("%s, bad resource\n", __func__);
        task_destroy(task);
        return;
    }

    memset(task->addr_from, 0, sizeof(*task->addr_from));

    struct event *ev = event_new(event_b, us->sock, EV_READ, handle_udp_recv_stage2, task);
    pp_resource_release(task->resource);
    add_event_mapping(task, ev);
    event_add(ev, NULL);
}

static
void
handle_udp_send_stage2(int sock, short event_flags, void *arg)
{
    struct async_network_task_s *task = arg;

    int retval = sendto(sock, task->buffer, task->bufsize, MSG_NOSIGNAL,
                        (struct sockaddr *)task->netaddr.data, task->netaddr.size);
    if (retval < 0)
        retval = get_pp_errno();

    ppb_message_loop_post_work_with_result(task->callback_ml, task->callback, 0, retval, 0,
                                           __func__);
    task_destroy(task);
}

static
void
handle_udp_send_stage1(struct async_network_task_s *task)
{
    struct pp_udp_socket_s *us = pp_resource_acquire(task->resource, PP_RESOURCE_UDP_SOCKET);
    if (!us) {
        trace_error("%s, bad resource\n", __func__);
        task_destroy(task);
        return;
    }

    // try to send immediately, but don't wait
    int retval = sendto(us->sock, task->buffer, task->bufsize, MSG_DONTWAIT | MSG_NOSIGNAL,
                        (struct sockaddr *)task->netaddr.data, task->netaddr.size);
    pp_resource_release(task->resource);

    if (retval >= 0) {
        // successfully sent
        ppb_message_loop_post_work_with_result(task->callback_ml, task->callback, 0, retval, 0,
                                               __func__);
        task_destroy(task);
        return;
    }

    // need to wait
    struct event *ev = event_new(event_b, us->sock, EV_WRITE, handle_udp_send_stage2, task);
    add_event_mapping(task, ev);
    event_add(ev, NULL);
}

static
void
handle_host_resolve_stage2(int result, char type, int count, int ttl, void *addresses, void *arg)
{
    struct async_network_task_s *task = arg;

    if (result != DNS_ERR_NONE || count < 1) {
        trace_warning("%s, evdns returned code %d, count = %d (%s:%u)\n", __func__, result, count,
                      task->host, (unsigned int)task->port);
        ppb_message_loop_post_work_with_result(task->callback_ml, task->callback, 0,
                                               PP_ERROR_NAME_NOT_RESOLVED, 0, __func__);
        task_destroy(task);
        return;
    }

    struct pp_host_resolver_s *hr = pp_resource_acquire(task->resource, PP_RESOURCE_HOST_RESOLVER);
    if (!hr) {
        trace_error("%s, bad resource\n", __func__);
        task_destroy(task);
        return;
    }

    hr->addr_count = count;
    hr->addrs = calloc(count, sizeof(struct PP_NetAddress_Private));

    if (type == DNS_IPv4_A) {
        struct in_addr *ipv4_addrs = addresses;

        for (int k = 0; k < count; k ++) {
            struct sockaddr_in sai = {
                .sin_family = AF_INET,
                .sin_port =   htons(task->port),
            };

            memcpy(&sai.sin_addr, &ipv4_addrs[k], sizeof(struct in_addr));

            hr->addrs[k].size = sizeof(struct sockaddr_in);
            memcpy(hr->addrs[k].data, &sai, sizeof(sai));
        }

        ppb_message_loop_post_work_with_result(task->callback_ml, task->callback, 0, PP_OK, 0,
                                               __func__);

    } else if (type == DNS_IPv6_AAAA) {
        struct in6_addr *ipv6_addrs = addresses;

        for (int k = 0; k < count; k ++) {
            struct sockaddr_in6 sai6 = {
                .sin6_family = AF_INET6,
                .sin6_port =   htons(task->port),
            };

            memcpy(&sai6.sin6_addr, &ipv6_addrs[k], sizeof(struct in6_addr));

            hr->addrs[k].size = sizeof(struct sockaddr_in6);
            memcpy(hr->addrs[k].data, &sai6, sizeof(sai6));
        }

        ppb_message_loop_post_work_with_result(task->callback_ml, task->callback, 0, PP_OK, 0,
                                               __func__);

    } else {
        trace_error("%s, bad evdns type %d (%s:%u)\n", __func__, type, task->host,
                    (unsigned int)task->port);
        ppb_message_loop_post_work_with_result(task->callback_ml, task->callback, 0,
                                               PP_ERROR_FAILED, 0, __func__);

    }

    pp_resource_release(task->resource);
    task_destroy(task);
}

static
void
handle_host_resolve_stage1(struct async_network_task_s *task)
{
    struct evdns_request *req;

    // queue DNS request
    req = evdns_base_resolve_ipv4(evdns_b, task->host, DNS_QUERY_NO_SEARCH,
                                  handle_host_resolve_stage2, task);
    // TODO: what about ipv6?

    if (!req) {
        trace_warning("%s, early dns resolution failure (%s:%u)\n", __func__, task->host,
                      (unsigned int)task->port);
        ppb_message_loop_post_work_with_result(task->callback_ml, task->callback, 0,
                                               PP_ERROR_NAME_NOT_RESOLVED, 0, __func__);
        task_destroy(task);
        return;
    }
}

static
void *
network_worker_thread(void *param)
{
    event_base_dispatch(event_b);
    event_base_free(event_b);
    trace_error("%s, thread terminated\n", __func__);
    return NULL;
}
static
void *
audio_thread(void *param)
{
    struct pollfd  *fds = NULL;
    nfds_t          nfds = 0;
    static char     buf[16 * 1024];

    ppb_message_loop_mark_thread_unsuitable();

    nfds = do_rebuild_fds(&fds);
    pthread_barrier_wait(&stream_list_update_barrier);
    if (nfds == 0)
        goto quit;

    while (1) {
        if (g_atomic_int_get(&terminate_thread))
            goto quit;

        int res = poll(fds, nfds, 10 * 1000);
        if (res == -1) {
            if (errno == EINTR)
                continue;
            trace_error("%s, poll, errno=%d\n", __func__, errno);
            continue;
        }

        if (res == 0 || fds == NULL)
            continue;

        if (fds[0].revents)
            drain_wakeup_pipe(fds[0].fd);

        if (g_atomic_int_get(&rebuild_fds)) {
            nfds = do_rebuild_fds(&fds);
            pthread_barrier_wait(&stream_list_update_barrier);
            if (nfds == 0)
                goto quit;
        }

        for (uintptr_t k = 1; k < nfds; k ++) {
            unsigned short revents = 0;
            audio_stream *as = g_hash_table_lookup(stream_by_fd_ht, GINT_TO_POINTER(fds[k].fd));

            // check if stream was deleted
            if (!as)
                continue;

            snd_pcm_poll_descriptors_revents(as->pcm, &fds[k], 1, &revents);

            if (revents & (~(POLLIN | POLLOUT))) {
                trace_warning("%s, revents have unexpected flags set (%u)\n", __func__,
                              (unsigned int)revents);
                recover_pcm(as->pcm);
            }

            if (revents & (POLLIN | POLLOUT)) {
                int                 paused = g_atomic_int_get(&as->paused);
                snd_pcm_sframes_t   frame_count = snd_pcm_avail(as->pcm);

                if (revents & POLLIN) {
                    // POLLIN
                    const size_t frame_size = 1 * sizeof(int16_t); // mono 16-bit
                    const size_t max_segment_length = MIN(as->sample_frame_count * frame_size,
                                                          sizeof(buf));
                    size_t       to_process = frame_count * frame_size;

                    while (to_process > 0) {
                        snd_pcm_sframes_t frames_read;
                        const size_t segment_length = MIN(to_process, max_segment_length);

                        frames_read = snd_pcm_readi(as->pcm, buf, segment_length / frame_size);
                        if (frames_read < 0) {
                            trace_warning("%s, snd_pcm_readi error %d\n", __func__,
                                          (int)frames_read);
                            recover_pcm(as->pcm);
                            continue;
                        }

                        if (!paused && as->capture_cb)
                            as->capture_cb(buf, frames_read * frame_size, 0, as->cb_user_data);

                        to_process -= frames_read * frame_size;
                    }

                } else {
                    // POLLOUT
                    const size_t frame_size = 2 * sizeof(int16_t); // stereo 16-bit
                    const size_t max_segment_length = MIN(as->sample_frame_count * frame_size,
                                                          sizeof(buf));
                    size_t       to_process = frame_count * frame_size;

                    while (to_process > 0) {
                        snd_pcm_sframes_t frames_written;
                        const size_t segment_length = MIN(to_process, max_segment_length);

                        if (paused || !as->playback_cb)
                            memset(buf, 0, segment_length);
                        else
                            as->playback_cb(buf, segment_length, 0, as->cb_user_data);

                        frames_written = snd_pcm_writei(as->pcm, buf, segment_length / frame_size);

                        if (frames_written < 0) {
                            trace_warning("%s, snd_pcm_writei error %d\n", __func__,
                                          (int)frames_written);
                            recover_pcm(as->pcm);
                            continue;
                        }

                        to_process -= frames_written * frame_size;
                    }
                }
            }
        }
    }

quit:
    free(fds);
    return NULL;
}
示例#27
0
NPError
NP_Initialize(NPNetscapeFuncs *aNPNFuncs, NPPluginFuncs *aNPPFuncs)
{
    trace_info_f("[NP] %s aNPNFuncs=%p, aNPPFuncs=%p, browser API version = %u\n", __func__,
                 aNPNFuncs, aNPPFuncs, aNPNFuncs->version);

    if (np_initialize_was_called) {
        trace_warning("NP_Initialize was called more than once\n");
        return NPERR_NO_ERROR;
    }

    np_initialize_was_called = 1;

    // set logging-only error handler.
    // Ignore a previous one, we have no plans to restore it
    (void)XSetErrorHandler(x_error_handler);
    (void)XSetIOErrorHandler(x_io_error_hanlder);

    memset(&npn, 0, sizeof(npn));
    memcpy(&npn, aNPNFuncs, sizeof(npn) < aNPNFuncs->size ? sizeof(npn) : aNPNFuncs->size);

    NPPluginFuncs pf;
    memset(&pf, 0, sizeof(NPPluginFuncs));
    pf.size = MIN(aNPPFuncs->size, sizeof(NPPluginFuncs));

    // browser is supposed to fill .size and .version
    pf.newp =               NPP_New;
    pf.destroy =            NPP_Destroy;
    pf.setwindow =          NPP_SetWindow;
    pf.newstream =          NPP_NewStream;
    pf.destroystream =      NPP_DestroyStream;
    pf.asfile =             NPP_StreamAsFile;
    pf.writeready =         NPP_WriteReady;
    pf.write =              NPP_Write;
    pf.print =              NPP_Print;
    pf.event =              NPP_HandleEvent;
    pf.urlnotify =          NPP_URLNotify;
    pf.getvalue =           NPP_GetValue;
    pf.setvalue =           NPP_SetValue;
    pf.gotfocus =           NPP_GotFocus;
    pf.lostfocus =          NPP_LostFocus;
    pf.urlredirectnotify =  NPP_URLRedirectNotify;
    pf.clearsitedata =      NPP_ClearSiteData;
    pf.getsiteswithdata =   NPP_GetSitesWithData;
    pf.didComposite =       NPP_DidComposite;

    memcpy(aNPPFuncs, &pf, pf.size);

    if (aNPNFuncs->version < NPVERS_HAS_PLUGIN_THREAD_ASYNC_CALL) {
        config.quirks.plugin_missing = 1;
        config.quirks.incompatible_npapi_version = 1;
    }

    load_ppp_module();

    if (tables_open_display() != 0)
        return NPERR_GENERIC_ERROR;

    int res = call_plugin_init_module();
    if (res != 0) {
        trace_error("%s, PPP_InitializeModule returned %d\n", __func__, res);
        return NPERR_GENERIC_ERROR;
    }

    return NPERR_NO_ERROR;
}