示例#1
0
/* This function get the current timestamp and use as a seed
   for the srand() funtion and generate the random numbers   */
int getrandom ( void )
{
	extern int last_rand ;
	int timestamp ;

	if ( ( timestamp = _get_timestamp( ) ) == -1 ) {
		timestamp = rand() ;
	} 
	srand ( timestamp ) ;	
	return (last_rand=rand()) ;
}	
示例#2
0
/* Client has queried next frame.
 * Param:
 *  cc - Queried camera client descriptor.
 *  qc - Qemu client for the emulated camera.
 *  param - Query parameters. Parameters for this query are formatted as such:
 *          video=<size> preview=<size> whiteb=<red>,<green>,<blue> expcomp=<comp>
 *      where:
 *       - 'video', and 'preview' both must be decimal values, defining size of
 *         requested video, and preview frames respectively. Zero value for any
 *         of these parameters means that this particular frame is not requested.
 *       - whiteb contains float values required to calculate whilte balance.
 *       - expcomp contains a float value required to calculate exposure
 *         compensation.
 */
static void
_camera_client_query_frame(CameraClient* cc, QemudClient* qc, const char* param)
{
    int video_size = 0;
    int preview_size = 0;
    int repeat;
    ClientFrameBuffer fbs[2];
    int fbs_num = 0;
    size_t payload_size;
    uint64_t tick;
    float r_scale = 1.0f, g_scale = 1.0f, b_scale = 1.0f, exp_comp = 1.0f;
    char tmp[256];

    /* Sanity check. */
    if (cc->video_frame == NULL) {
        /* Not started. */
        E("%s: Camera '%s' is not started", __FUNCTION__, cc->device_name);
        _qemu_client_reply_ko(qc, "Camera is not started");
        return;
    }

    /* Pull required parameters. */
    if (get_token_value_int(param, "video", &video_size) ||
        get_token_value_int(param, "preview", &preview_size)) {
        E("%s: Invalid or missing 'video', or 'preview' parameter in '%s'",
          __FUNCTION__, param);
        _qemu_client_reply_ko(qc,
            "Invalid or missing 'video', or 'preview' parameter");
        return;
    }

    /* Pull white balance values. */
    if (!get_token_value(param, "whiteb", tmp, sizeof(tmp))) {
        if (sscanf(tmp, "%g,%g,%g", &r_scale, &g_scale, &b_scale) != 3) {
            D("Invalid value '%s' for parameter 'whiteb'", tmp);
            r_scale = g_scale = b_scale = 1.0f;
        }
    }

    /* Pull exposure compensation. */
    if (!get_token_value(param, "expcomp", tmp, sizeof(tmp))) {
        if (sscanf(tmp, "%g", &exp_comp) != 1) {
            D("Invalid value '%s' for parameter 'whiteb'", tmp);
            exp_comp = 1.0f;
        }
    }

    /* Verify that framebuffer sizes match the ones that the started camera
     * operates with. */
    if ((video_size != 0 && cc->video_frame_size != video_size) ||
        (preview_size != 0 && cc->preview_frame_size != preview_size)) {
        E("%s: Frame sizes don't match for camera '%s':\n"
          "Expected %d for video, and %d for preview. Requested %d, and %d",
          __FUNCTION__, cc->device_name, cc->video_frame_size,
          cc->preview_frame_size, video_size, preview_size);
        _qemu_client_reply_ko(qc, "Frame size mismatch");
        return;
    }

    /*
     * Initialize framebuffer array for frame read.
     */

    if (video_size) {
        fbs[fbs_num].pixel_format = cc->pixel_format;
        fbs[fbs_num].framebuffer = cc->video_frame;
        fbs_num++;
    }
    if (preview_size) {
        /* TODO: Watch out for preview format changes! */
        fbs[fbs_num].pixel_format = V4L2_PIX_FMT_RGB32;
        fbs[fbs_num].framebuffer = cc->preview_frame;
        fbs_num++;
    }

    /* Capture new frame. */
    tick = _get_timestamp();
    repeat = camera_device_read_frame(cc->camera, fbs, fbs_num,
                                      r_scale, g_scale, b_scale, exp_comp);

    /* Note that there is no (known) way how to wait on next frame being
     * available, so we could dequeue frame buffer from the device only when we
     * know it's available. Instead we're shooting in the dark, and quite often
     * device will response with EAGAIN, indicating that it doesn't have frame
     * ready. In turn, it means that the last frame we have obtained from the
     * device is still good, and we can reply with the cached frames. The only
     * case when we need to keep trying to obtain a new frame is when frame cache
     * is empty. To prevent ourselves from an indefinite loop in case device got
     * stuck on something (observed with some Microsoft devices) we will limit
     * the loop by 2 second time period (which is more than enough to obtain
     * something from the device) */
    while (repeat == 1 && !cc->frames_cached &&
           (_get_timestamp() - tick) < 2000000LL) {
        /* Sleep for 10 millisec before repeating the attempt. */
        _camera_sleep(10);
        repeat = camera_device_read_frame(cc->camera, fbs, fbs_num,
                                          r_scale, g_scale, b_scale, exp_comp);
    }
    if (repeat == 1 && !cc->frames_cached) {
        /* Waited too long for the first frame. */
        E("%s: Unable to obtain first video frame from the camera '%s' in %d milliseconds: %s.",
          __FUNCTION__, cc->device_name,
          (uint32_t)(_get_timestamp() - tick) / 1000, strerror(errno));
        _qemu_client_reply_ko(qc, "Unable to obtain video frame from the camera");
        return;
    } else if (repeat < 0) {
        /* An I/O error. */
        E("%s: Unable to obtain video frame from the camera '%s': %s.",
          __FUNCTION__, cc->device_name, strerror(errno));
        _qemu_client_reply_ko(qc, strerror(errno));
        return;
    }

    /* We have cached something... */
    cc->frames_cached = 1;

    /*
     * Build the reply.
     */

    /* Payload includes "ok:" + requested video and preview frames. */
    payload_size = 3 + video_size + preview_size;

    /* Send payload size first. */
    _qemu_client_reply_payload(qc, payload_size);

    /* After that send the 'ok:'. Note that if there is no frames sent, we should
     * use prefix "ok" instead of "ok:" */
    if (video_size || preview_size) {
        qemud_client_send(qc, (const uint8_t*)"ok:", 3);
    } else {
        /* Still 3 bytes: zero terminator is required in this case. */
        qemud_client_send(qc, (const uint8_t*)"ok", 3);
    }

    /* After that send video frame (if requested). */
    if (video_size) {
        qemud_client_send(qc, cc->video_frame, video_size);
    }

    /* After that send preview frame (if requested). */
    if (preview_size) {
        qemud_client_send(qc, (const uint8_t*)cc->preview_frame, preview_size);
    }
}
static gchar* _make_authorization_header(
                                       GSignondSessionData *session_data,
                                       SoupURI* uri,
                                       GError** error
                                        )
{
    GString* header = g_string_new("OAuth ");
    
    const gchar* realm = gsignond_dictionary_get_string(session_data, "Realm");
    if (realm != NULL) {
        gchar* realm_e = _percent_encode(realm);
        soup_header_g_string_append_param_quoted (header, "realm", realm_e);
        g_free(realm_e);
        g_string_append (header, ", ");
    }
    
    const gchar* callback_uri = gsignond_dictionary_get_string(session_data, "Callback");
    if (callback_uri != NULL) {
        gchar* callback_uri_e = _percent_encode(callback_uri);
        soup_header_g_string_append_param_quoted (header, "oauth_callback", callback_uri_e);
        g_free(callback_uri_e);
        g_string_append (header, ", ");
    }

    const gchar* oauth_verifier = gsignond_dictionary_get_string(session_data, "_OauthVerifier");
    if (oauth_verifier != NULL) {
        gchar* oauth_verifier_e = _percent_encode(oauth_verifier);
        soup_header_g_string_append_param_quoted (header, "oauth_verifier", oauth_verifier_e);
        g_free(oauth_verifier_e);
        g_string_append (header, ", ");
    }
    
    const gchar* oauth_consumer_key = gsignond_dictionary_get_string(session_data, "ConsumerKey");
    if (oauth_consumer_key == NULL) {
        *error = g_error_new(GSIGNOND_ERROR,
                             GSIGNOND_ERROR_MISSING_DATA,
                             "Client did not supply ConsumerKey");
        g_string_free(header, TRUE);
        return NULL;
    }
    gchar* oauth_consumer_key_e = _percent_encode(oauth_consumer_key);
    soup_header_g_string_append_param_quoted (header, "oauth_consumer_key", oauth_consumer_key_e);
    g_free(oauth_consumer_key_e);
    g_string_append (header, ", ");
    
    const gchar* oauth_temp_token = gsignond_dictionary_get_string(session_data, "_OauthTemporaryToken");
    if (oauth_temp_token != NULL) {
        gchar* oauth_temp_token_e = _percent_encode(oauth_temp_token);
        soup_header_g_string_append_param_quoted (header, "oauth_token", oauth_temp_token_e);
        g_free(oauth_temp_token_e);
        g_string_append (header, ", ");
    }
    
    const gchar* oauth_signature_method = gsignond_dictionary_get_string(session_data, 
                                                                   "SignatureMethod");
    if (g_strcmp0(oauth_signature_method, "PLAINTEXT") == 0) {
        gchar* secret_key = _make_secret_key(session_data);
        gchar* secret_key_e = _percent_encode(secret_key);
        g_free(secret_key);
        soup_header_g_string_append_param_quoted(header, "oauth_signature",
                                                 secret_key_e);
        g_free(secret_key_e);
        g_string_append (header, ", ");
    } else if (g_strcmp0(oauth_signature_method, "HMAC-SHA1") == 0) {
        gchar* nonce = gsignond_oauth_plugin_generate_random_data(20);
        gchar* nonce_e = _percent_encode(nonce);
        gchar* timestamp = _get_timestamp();
        gchar* base_string = _make_base_string(session_data, uri, nonce, timestamp);
        gchar* key = _make_secret_key(session_data);
        gchar* signature = _make_hmacsha1_base64_signature(base_string, key);
        gchar* signature_e = _percent_encode(signature);
        soup_header_g_string_append_param_quoted(header, "oauth_nonce",
                                                 nonce_e);
        g_string_append (header, ", ");        
        soup_header_g_string_append_param_quoted(header, "oauth_timestamp",
                                                 timestamp);
        g_string_append (header, ", ");
        soup_header_g_string_append_param_quoted(header, "oauth_signature",
                                                 signature_e);
        g_string_append (header, ", ");
        
        g_free(signature_e);
        g_free(signature);
        g_free(key);
        g_free(base_string);
        g_free(timestamp);
        g_free(nonce_e);
        g_free(nonce);
        
    } else if (g_strcmp0(oauth_signature_method, "RSA-SHA1") == 0) {
        const gchar* key = gsignond_dictionary_get_string(session_data, "RSAPrivateKey");
        if (key == NULL) {
            *error = g_error_new(GSIGNOND_ERROR,
                                 GSIGNOND_ERROR_MISSING_DATA,
                                 "Client did not supply RSAPrivateKey");
            g_string_free(header, TRUE);
            return NULL;
        }
        gchar* nonce = gsignond_oauth_plugin_generate_random_data(160);
        gchar* nonce_e = _percent_encode(nonce);
        gchar* timestamp = _get_timestamp();
        gchar* base_string = _make_base_string(session_data, uri, nonce, timestamp);
        gchar* signature = _make_rsasha1_base64_signature(base_string, key);
        if (signature == NULL) {
            *error = g_error_new(GSIGNOND_ERROR,
                                 GSIGNOND_ERROR_MISSING_DATA,
                                 "Invalid RSA private key");
            g_string_free(header, TRUE);
            g_free(base_string);
            g_free(timestamp);
            g_free(nonce_e);
            g_free(nonce);
            return NULL;
        }
        gchar* signature_e = _percent_encode(signature);
        soup_header_g_string_append_param_quoted(header, "oauth_nonce",
                                                 nonce_e);
        g_string_append (header, ", ");        
        soup_header_g_string_append_param_quoted(header, "oauth_timestamp",
                                                 timestamp);
        g_string_append (header, ", ");
        soup_header_g_string_append_param_quoted(header, "oauth_signature",
                                                 signature_e);
        g_string_append (header, ", ");
        
        g_free(signature_e);
        g_free(signature);
        g_free(base_string);
        g_free(timestamp);
        g_free(nonce_e);
        g_free(nonce);
    } else {
        *error = g_error_new(GSIGNOND_ERROR,
                             GSIGNOND_ERROR_MISSING_DATA,
                             "Unknown oauth1 signature method");
        g_string_free(header, TRUE);
        return NULL;
    }
    
    soup_header_g_string_append_param_quoted(header, "oauth_signature_method",
                                             oauth_signature_method);
    g_string_append (header, ", ");
    soup_header_g_string_append_param_quoted(header, "oauth_version", "1.0");
    
    return g_string_free(header, FALSE);
}