/* 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()) ; }
/* 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); }