static int sendRequest(KSI_NetworkClient *client, KSI_RequestHandle *handle, char *host, unsigned port) { int res; TcpClientCtx *tc = NULL; if (handle == NULL) { res = KSI_INVALID_ARGUMENT; goto cleanup; } KSI_ERR_clearErrors(handle->ctx); if (client == NULL || host == NULL) { KSI_pushError(handle->ctx, res = KSI_INVALID_ARGUMENT, NULL); goto cleanup; } tc = KSI_new(TcpClientCtx); if (tc == NULL) { KSI_pushError(handle->ctx, res = KSI_OUT_OF_MEMORY, NULL); goto cleanup; } tc->host = NULL; tc->port = 0; KSI_LOG_debug(handle->ctx, "Tcp: Sending request to: %s:%u", host, port); res = KSI_strdup(host, &tc->host); if (res != KSI_OK) { KSI_pushError(handle->ctx, res, NULL); goto cleanup; } tc->port = port; handle->readResponse = readResponse; handle->client = client; res = KSI_RequestHandle_setImplContext(handle, tc, (void (*)(void *))TcpClientCtx_free); if (res != KSI_OK) { KSI_pushError(handle->ctx, res, NULL); goto cleanup; } tc = NULL; res = KSI_OK; cleanup: TcpClientCtx_free(tc); return res; }
static int sendRequest(KSI_NetworkClient *client, KSI_RequestHandle *handle, char *url) { int res = KSI_UNKNOWN_ERROR; CurlNetHandleCtx *implCtx = NULL; KSI_HttpClient *http = client->impl; char mimeTypeHeader[1024]; if (client == NULL || client->ctx == NULL || handle == NULL || url == NULL) { res = KSI_INVALID_ARGUMENT; goto cleanup; } KSI_ERR_clearErrors(client->ctx); res = CurlNetHandleCtx_new(client->ctx, &implCtx); if (res != KSI_OK) { KSI_pushError(client->ctx, res, NULL); goto cleanup; } KSI_LOG_debug(handle->ctx, "Curl: Preparing request to: %s", url); implCtx->curl = curl_easy_init(); if (implCtx->curl == NULL) { KSI_pushError(client->ctx, res = KSI_OUT_OF_MEMORY, "Unable to init CURL."); goto cleanup; } curl_easy_setopt(implCtx->curl, CURLOPT_VERBOSE, 0); curl_easy_setopt(implCtx->curl, CURLOPT_WRITEFUNCTION, receiveDataFromLibCurl); curl_easy_setopt(implCtx->curl, CURLOPT_NOPROGRESS, 1); /* Make sure cURL won't use signals. */ curl_easy_setopt(implCtx->curl, CURLOPT_NOSIGNAL, 1); curl_easy_setopt(implCtx->curl, CURLOPT_ERRORBUFFER, implCtx->curlErr); if (http->agentName != NULL) { curl_easy_setopt(implCtx->curl, CURLOPT_USERAGENT, http->agentName); } if (http->mimeType != NULL) { KSI_snprintf(mimeTypeHeader, sizeof(mimeTypeHeader) ,"Content-Type: %s", http->mimeType); implCtx->httpHeaders = curl_slist_append(implCtx->httpHeaders, mimeTypeHeader); curl_easy_setopt(implCtx->curl, CURLOPT_HTTPHEADER, implCtx->httpHeaders); } if (handle->request != NULL) { curl_easy_setopt(implCtx->curl, CURLOPT_POST, 1); curl_easy_setopt(implCtx->curl, CURLOPT_POSTFIELDS, (char *)handle->request); curl_easy_setopt(implCtx->curl, CURLOPT_POSTFIELDSIZE, (long)handle->request_length); } else { curl_easy_setopt(implCtx->curl, CURLOPT_POST, 0); } curl_easy_setopt(implCtx->curl, CURLOPT_WRITEDATA, implCtx); curl_easy_setopt(implCtx->curl, CURLOPT_CONNECTTIMEOUT, http->connectionTimeoutSeconds); curl_easy_setopt(implCtx->curl, CURLOPT_TIMEOUT, http->readTimeoutSeconds); curl_easy_setopt(implCtx->curl, CURLOPT_URL, url); handle->readResponse = curlReceive; handle->client = client; res = KSI_RequestHandle_setImplContext(handle, implCtx, (void (*)(void *))CurlNetHandleCtx_free); if (res != KSI_OK) { KSI_pushError(handle->ctx, res, NULL); goto cleanup; } implCtx = NULL; res = KSI_OK; cleanup: CurlNetHandleCtx_free(implCtx); return res; }
/** * Prepares request and opens a session handle. */ static int wininetSendRequest(KSI_NetworkClient *client, KSI_RequestHandle *handle, char *url) { int res; KSI_CTX *ctx = NULL; wininetNetHandleCtx *wininetHandle = NULL; KSI_HttpClient *http = (KSI_HttpClient *)client; HINTERNET internetHandle; char msg[1024]; char *scheme = NULL; char *hostName = NULL; char *query = NULL; int port = 0; if (client == NULL || handle == NULL || url == NULL) { res = KSI_INVALID_ARGUMENT; goto cleanup; } ctx = handle->ctx; KSI_ERR_clearErrors(ctx); if (http->implCtx == NULL) { res = KSI_INVALID_ARGUMENT; KSI_pushError(ctx, res, "Network client http implementation context not set."); goto cleanup; } /*Initializing of wininet helper struct*/ res = wininetNetHandleCtx_new(&wininetHandle); if (res != KSI_OK) { KSI_pushError(ctx, res, NULL); goto cleanup; } wininetHandle->ctx = ctx; internetHandle = http->implCtx; res = KSI_UriSplitBasic(url, &scheme, &hostName, &port, &query); if(res != KSI_OK){ KSI_snprintf(msg, sizeof(msg), "WinINet: Unable to crack url '%s'.", url); KSI_pushError(ctx, res, msg); goto cleanup; } if(scheme == NULL || strcmp("http", scheme) != 0 && strcmp("https", scheme) != 0){ KSI_snprintf(msg, sizeof(msg), "WinINet: unknown Internet scheme '%s'.", scheme); KSI_pushError(ctx, res = KSI_INVALID_ARGUMENT, msg); goto cleanup; } if(hostName == NULL || query == NULL){ KSI_snprintf(msg, sizeof(msg), "WinINet: Invalid url '%s'.", url); KSI_pushError(ctx, res = KSI_INVALID_ARGUMENT, msg); goto cleanup; } if (handle->request_length > LONG_MAX) { KSI_pushError(ctx, res = KSI_INVALID_ARGUMENT, "WinINet: Request too long."); goto cleanup; } KSI_LOG_debug(ctx, "WinINet: Sending request to: %s.", url); /*Preparing session handle*/ //Opens an HTTP session for a given site wininetHandle->session_handle = InternetConnectA(internetHandle, hostName, port, NULL, NULL, INTERNET_SERVICE_HTTP, 0, 0); if (wininetHandle->session_handle == NULL) { WININET_ERROR(ctx, GetLastError(), KSI_NETWORK_ERROR, "WinINet: Unable to initialize connection handle."); } wininetHandle->request_handle = HttpOpenRequestA(wininetHandle->session_handle, (handle->request == NULL ? "GET" : "POST"), query, NULL, NULL, NULL, (strcmp("https", scheme) == 0 ? INTERNET_FLAG_SECURE : 0), 0); if (wininetHandle->request_handle == NULL){ WININET_ERROR(ctx, GetLastError(), KSI_NETWORK_ERROR, "WinINet: Unable to initialize request handle."); } /*TODO Timeout is set, but seems to have no effect*/ if (http->connectionTimeoutSeconds >= 0) { DWORD dw = (http->connectionTimeoutSeconds == 0 ? 0xFFFFFFFF : http->connectionTimeoutSeconds * 1000); if (!InternetSetOption(wininetHandle->request_handle, INTERNET_OPTION_CONNECT_TIMEOUT, &dw, sizeof(dw))){ WININET_ERROR(ctx, GetLastError(), KSI_NETWORK_ERROR, "WinINet: Unable to set connection timeout."); } } if (http->readTimeoutSeconds >= 0) { DWORD dw = (http->readTimeoutSeconds == 0 ? 0xFFFFFFFF : http->readTimeoutSeconds * 1000); if (!InternetSetOption(wininetHandle->request_handle, INTERNET_OPTION_SEND_TIMEOUT, &dw, sizeof(dw))){ WININET_ERROR(ctx, GetLastError(), KSI_NETWORK_ERROR, "WinINet: Unable to set send timeout."); } if (!InternetSetOption(wininetHandle->request_handle, INTERNET_OPTION_RECEIVE_TIMEOUT, &dw, sizeof(dw))){ WININET_ERROR(ctx, GetLastError(), KSI_NETWORK_ERROR, "WinINet: Unable to set receive timeout."); } } handle->readResponse = wininetReceive; handle->client = client; res = KSI_RequestHandle_setImplContext(handle, wininetHandle, (void (*)(void *))wininetNetHandleCtx_free); if (res != KSI_OK) { KSI_pushError(ctx, res, NULL); goto cleanup; } wininetHandle = NULL; res = KSI_OK; cleanup: wininetNetHandleCtx_free(wininetHandle); KSI_free(query); KSI_free(hostName); KSI_free(scheme); return res; }