// Convert the OsDateTimeBase value to an OsTime value // The OsTime value is relative to when the system was booted. OsStatus OsDateTimeLinux::cvtToTimeSinceBoot(OsTime& rTime) const { unsigned long curTimeAsSecsSinceBoot; time_t curTimeAsTimeT; struct tm thisTime; long thisTimeAsSecsSinceBoot; time_t thisTimeAsTimeT; // convert "this" OsDateTime to a time_t representation thisTime.tm_year = mYear - 1900; thisTime.tm_mon = mMonth; thisTime.tm_mday = mDay; thisTime.tm_hour = mHour; thisTime.tm_min = mMinute; thisTime.tm_sec = mSecond; thisTimeAsTimeT = mktime(&thisTime); assert(thisTimeAsTimeT >= 0); // get the current time as a time_t curTimeAsTimeT = time(NULL); assert(curTimeAsTimeT >= 0); // get the current time as seconds since boot curTimeAsSecsSinceBoot = (unsigned long)secondsSinceBoot(); // convert "this" time to seconds since boot thisTimeAsSecsSinceBoot = (thisTimeAsTimeT - curTimeAsTimeT) + curTimeAsSecsSinceBoot; OsTime deltaOsTime(thisTimeAsSecsSinceBoot, 0); rTime = deltaOsTime; return OS_SUCCESS; }
static int parseProgressInternal(void *clientp, curl_off_t dltotal, curl_off_t dlnow, curl_off_t ultotal, curl_off_t ulnow) { unsigned long startTime = (uintptr_t) clientp; unsigned long nowTime = secondsSinceBoot(); if (nowTime - startTime > PARSE_REQUEST_TIMEOUT_SECONDS) { parseLog(PARSE_LOG_WARN, "Request timeout after %i seconds.\n", nowTime - startTime); return 1; } return 0; }
// Return the current time as an OsTime value // The OsTime value is relative to when the system was booted. void OsDateTimeLinux::getCurTimeSinceBoot(OsTime& rTime) { double seconds; int secs; int usecs; seconds = secondsSinceBoot(); secs = (int)seconds; usecs = (int)((seconds - secs) * MICROSECS_PER_SEC); OsTime timeSinceBoot(secs, usecs); rTime = timeSinceBoot; }
static void parseSendRequestInternal( ParseClient client, const char *httpVerb, const char* httpPath, const char* requestBody, parseRequestCallback callback, int useInstallationIdHeader) { ParseClientInternal *clientInternal = getClient(client); int getRequestBody = 0; CURLcode result = CURLE_OK; CURL *curl = NULL; curl = curl_easy_init(); if (curl == NULL) { if (callback != NULL) callback(client, CURLE_FAILED_INIT, 0, NULL); return; } result = curl_easy_setopt(curl, CURLOPT_CUSTOMREQUEST, httpVerb); if (result != CURLE_OK) { if (callback != NULL) callback(client, result, 0, NULL); return; } if (requestBody != NULL) { if (strncmp(httpVerb, "GET", sizeof("GET"))) { result = curl_easy_setopt(curl, CURLOPT_POSTFIELDS, requestBody); if (result != CURLE_OK) { if (callback != NULL) callback(client, result, 0, NULL); return; } result = curl_easy_setopt(curl, CURLOPT_POSTFIELDSIZE, (long)strlen(requestBody)); if (result != CURLE_OK) { if (callback != NULL) callback(client, result, 0, NULL); return; } } else { getRequestBody = 1; } } int urlSize = strlen("https://api.parse.com"); urlSize += strlen(httpPath) + 1; char* getEncodedBody = NULL; if (getRequestBody) { urlSize += strlen(requestBody) + 1; } char *fullUrl = calloc(1, urlSize + 1); if (fullUrl == NULL) { parseLog(PARSE_LOG_ERROR, "%s:%s generated out of memory.\n", __FUNCTION__, __LINE__); if (callback != NULL) callback(client, ENOMEM, 0, NULL); return; } strncat(fullUrl, "https://api.parse.com", urlSize); strncat(fullUrl, httpPath, urlSize - strlen(fullUrl)); if (getRequestBody) { strncat(fullUrl, "?", urlSize - strlen(fullUrl)); strncat(fullUrl, requestBody, urlSize - strlen(fullUrl)); } result = curl_easy_setopt(curl, CURLOPT_URL, fullUrl); free(fullUrl); if (result != CURLE_OK) { if (callback != NULL) callback(client, result, 0, NULL); return; } struct curl_slist *headers = NULL; char header[128] = {}; snprintf(header, sizeof(header), "X-Parse-Application-Id: %s", clientInternal->applicationId); headers = curl_slist_append(headers, header); snprintf(header, sizeof(header), "X-Parse-Client-Version: c-embedded-%s", VERSION); headers = curl_slist_append(headers, header); snprintf(header, sizeof(header), "X-Parse-OS-Version: %s", clientInternal->osVersion); headers = curl_slist_append(headers, header); snprintf(header, sizeof(header), "X-Parse-Client-Key: %s", clientInternal->clientKey); headers = curl_slist_append(headers, header); if (useInstallationIdHeader && clientInternal->installationId) { snprintf(header, sizeof(header), "X-Parse-Installation-Id: %s", clientInternal->installationId); headers = curl_slist_append(headers, header); } if (clientInternal->sessionToken) { snprintf(header, sizeof(header), "X-Parse-Session-Token: %s", clientInternal->sessionToken); headers = curl_slist_append(headers, header); } headers = curl_slist_append(headers, "Content-Type: application/json; charset=utf-8"); headers = curl_slist_append(headers, "Connection: close"); headers = curl_slist_append(headers, "Accept:"); // This line removes 'Accpet' header. result = curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers); if (result != CURLE_OK) { if (callback != NULL) callback(client, result, 0, NULL); return; } result = curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, curlDataCallback); if (result != CURLE_OK) { if (callback != NULL) callback(client, result, 0, NULL); return; } ParseRequestDataInternal data; data.client = client; data.requestCallback = callback; data.curl = curl; result = curl_easy_setopt(curl, CURLOPT_WRITEDATA, (void *)&data); if (result != CURLE_OK) { if (callback != NULL) callback(client, result, 0, NULL); return; } result = curl_easy_setopt(curl, CURLOPT_NOPROGRESS, 0L); if (result != CURLE_OK) { if (callback != NULL) callback(client, result, 0, NULL); return; } result = curl_easy_setopt(curl, CURLOPT_XFERINFODATA, (void*)((uintptr_t)secondsSinceBoot())); if (result != CURLE_OK) { if (callback != NULL) callback(client, result, 0, NULL); return; } result = curl_easy_setopt(curl, CURLOPT_XFERINFOFUNCTION, parseProgressInternal); if (result != CURLE_OK) { if (callback != NULL) callback(client, result, 0, NULL); return; } result = curl_easy_perform(curl); if (result != CURLE_OK) { // We use callback to implement timeout so let's report the // error as timeout in the case callback aborted the request. if (result == CURLE_ABORTED_BY_CALLBACK) result = CURLE_OPERATION_TIMEDOUT; if (callback != NULL) callback(client, result, 0, NULL); return; } curl_easy_cleanup(curl); curl_slist_free_all(headers); }
int parseProcessNextPushNotification(ParseClient client) { ParseClientInternal *clientInternal = getClient(client); if (clientInternal->pushCurlHandle != NULL) { size_t read = 0;; int length = -1; int start = 0; char* message = NULL; while (length == -1 && parse_push_message_size < sizeof(parse_push_message_buffer)) { CURLcode result = curl_easy_recv(clientInternal->pushCurlHandle, parse_push_message_buffer + parse_push_message_size, sizeof(parse_push_message_buffer) - parse_push_message_size, &read); if (result == CURLE_OK) { parseLog(PARSE_LOG_INFO, "got ok!\n"); parse_push_message_size += read; message = (char *)getPushJson(parse_push_message_buffer, parse_push_message_size, &start, &length); } else if (result == CURLE_AGAIN) { break; } else { parseLog(PARSE_LOG_ERROR, "curl_easy_recv read %i an error %s\n", length, curl_easy_strerror(result)); if (clientInternal->pushCallback != NULL) { clientInternal->pushCallback(client, ECONNRESET, NULL); } return 0; } } if (length == -1 && parse_push_message_size == sizeof(parse_push_message_buffer)) { // this message is bigger than the buffer, we need to drop it :-( parse_push_message_size = 0; return 0; } parseLog(PARSE_LOG_INFO, "message = %p, start = %i, length = %i\n", message, start, length); if (length > 0 && message != NULL) { message[length] = '\0'; // We assume messages are separated by '\n'. parseLog(PARSE_LOG_INFO, "message = '%s'\n", message); char time[32]; if (simpleJsonProcessor(message, "time", time, sizeof(time))) { if (clientInternal->lastPushTime) { free(clientInternal->lastPushTime); } clientInternal->lastPushTime = strdup(time); parseOsStoreKey(clientInternal->applicationId, PARSE_LAST_PUSH_TIME, time); parseLog(PARSE_LOG_INFO, "lastPush = '%s'\n", clientInternal->lastPushTime); } if (strncmp("{}", message, 2) == 0) { // we got a hearbeat back parseLog(PARSE_LOG_DEBUG, "got heartbeat\n"); } else if (clientInternal->pushCallback != NULL) { clientInternal->pushCallback(client, 0, message); } parse_push_message_size -= length + 1; if (parse_push_message_size > 0) { memmove(parse_push_message_buffer, parse_push_message_buffer + length + 1, parse_push_message_size); } return (parse_push_message_size > 0) ? 1 : 0; } unsigned int seconds = secondsSinceBoot(); if (seconds > clientInternal->lastHearbeat + PARSE_HEARTBIT_INTERVAL_SECONDS) { clientInternal->lastHearbeat = seconds; size_t sent; curl_easy_send(clientInternal->pushCurlHandle, "{}\n", 3, &sent); } } return 0; }
int parseStartPushService(ParseClient client) { ParseClientInternal *clientInternal = getClient(client); CURLcode result = CURLE_OK; CURL *curl = NULL; if (clientInternal->pushCurlHandle != NULL) { return 0; } parseCreateInstallationIdIfNeeded(client); parseLog(PARSE_LOG_INFO, "Installation id: %s\n", clientInternal->installationId); curl = curl_easy_init(); if (curl == NULL) { return CURLE_FAILED_INIT; } result = curl_easy_setopt(curl, CURLOPT_CONNECT_ONLY, 1L); if (result != CURLE_OK) { return result; } result = curl_easy_setopt(curl, CURLOPT_USE_SSL, CURLUSESSL_ALL); if (result != CURLE_OK) { return result; } result = curl_easy_setopt(curl, CURLOPT_URL, "https://push.parse.com"); if (result != CURLE_OK) { return result; } result = curl_easy_perform(curl); if (result != CURLE_OK) { return result; } clientInternal->pushCurlHandle = curl; size_t sent; char push[256]; if (clientInternal->lastPushTime) { snprintf(push, sizeof(push), "{\"installation_id\":\"%s\", \"oauth_key\":\"%s\", \"v\":\"e1.0.0\", \"last\":\"%s\"}\n", clientInternal->installationId, clientInternal->applicationId, clientInternal->lastPushTime); } else { snprintf(push, sizeof(push), "{\"installation_id\":\"%s\", \"oauth_key\":\"%s\", \"v\":\"e1.0.0\", \"last\":null}\n", clientInternal->installationId, clientInternal->applicationId); } curl_easy_send(curl, push, strlen(push), &sent); parseLog(PARSE_LOG_INFO, "Sending %i chars in request '%s'\n", sent, push); curl_easy_send(curl, "{}\n", 3, &sent); clientInternal->lastHearbeat = secondsSinceBoot(); return 0; }