Skip to content

Commit

Permalink
1.0.5
Browse files Browse the repository at this point in the history
- Added natives for changing client connect timeout, follow location setting
- Added feature for receiving error string
- Now callback fires anyway.
- IChangeableForward replaced: now using IPluginFunction
  • Loading branch information
CrazyHackGUT committed Dec 21, 2017
1 parent 7f04d2f commit f0841ac
Show file tree
Hide file tree
Showing 7 changed files with 115 additions and 8 deletions.
67 changes: 66 additions & 1 deletion curl_natives.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -227,6 +227,36 @@ static cell_t GetClientTimeout(IPluginContext *pContext, const cell_t *params)
return client->timeout;
}

static cell_t GetClientConnectTimeout(IPluginContext *pContext, const cell_t *params)
{
HandleError err;
HandleSecurity sec(pContext->GetIdentity(), myself->GetIdentity());

struct HTTPClient *client;
Handle_t hndlClient = static_cast<Handle_t>(params[1]);
if ((err=handlesys->ReadHandle(hndlClient, htHTTPClientObject, &sec, (void **)&client)) != HandleError_None)
{
return pContext->ThrowNativeError("Invalid HTTP client handle %x (error %d)", hndlClient, err);
}

return client->connect_timeout;
}

static cell_t GetClientFollowLocation(IPluginContext *pContext, const cell_t *params)
{
HandleError err;
HandleSecurity sec(pContext->GetIdentity(), myself->GetIdentity());

struct HTTPClient *client;
Handle_t hndlClient = static_cast<Handle_t>(params[1]);
if ((err=handlesys->ReadHandle(hndlClient, htHTTPClientObject, &sec, (void **)&client)) != HandleError_None)
{
return pContext->ThrowNativeError("Invalid HTTP client handle %x (error %d)", hndlClient, err);
}

return client->follow_location;
}

static cell_t SetClientTimeout(IPluginContext *pContext, const cell_t *params)
{
HandleError err;
Expand All @@ -243,11 +273,42 @@ static cell_t SetClientTimeout(IPluginContext *pContext, const cell_t *params)
return 1;
}

static cell_t GetResponseData(IPluginContext *pContext, const cell_t *params)
static cell_t SetClientConnectTimeout(IPluginContext *pContext, const cell_t *params)
{
HandleError err;
HandleSecurity sec(pContext->GetIdentity(), myself->GetIdentity());

struct HTTPClient *client;
Handle_t hndlClient = static_cast<Handle_t>(params[1]);
if ((err=handlesys->ReadHandle(hndlClient, htHTTPClientObject, &sec, (void **)&client)) != HandleError_None)
{
return pContext->ThrowNativeError("Invalid HTTP client handle %x (error %d)", hndlClient, err);
}

client->connect_timeout = params[2];
return 1;
}

static cell_t SetClientFollowLocation(IPluginContext *pContext, const cell_t *params)
{
HandleError err;
HandleSecurity sec(pContext->GetIdentity(), myself->GetIdentity());

struct HTTPClient *client;
Handle_t hndlClient = static_cast<Handle_t>(params[1]);
if ((err=handlesys->ReadHandle(hndlClient, htHTTPClientObject, &sec, (void **)&client)) != HandleError_None)
{
return pContext->ThrowNativeError("Invalid HTTP client handle %x (error %d)", hndlClient, err);
}

client->follow_location = (params[2] == 0 ? 0L : 1L);
return 1;
}

static cell_t GetResponseData(IPluginContext *pContext, const cell_t *params) {
HandleError err;
HandleSecurity sec(pContext->GetIdentity(), myself->GetIdentity());

struct HTTPResponse *response;
Handle_t hndlResponse = static_cast<Handle_t>(params[1]);
if ((err=handlesys->ReadHandle(hndlResponse, htHTTPResponseObject, &sec, (void **)&response)) != HandleError_None)
Expand Down Expand Up @@ -302,6 +363,10 @@ const sp_nativeinfo_t curl_natives[] =

{"HTTPClient.Timeout.set", SetClientTimeout},
{"HTTPClient.Timeout.get", GetClientTimeout},
{"HTTPClient.ConnectTimeout.set", SetClientConnectTimeout},
{"HTTPClient.ConnectTimeout.get", GetClientConnectTimeout},
{"HTTPClient.FollowLocation.set", SetClientFollowLocation},
{"HTTPClient.FollowLocation.get", GetClientFollowLocation},

{"HTTPClient.Delete", DeleteRequest},
{"HTTPResponse.Data.get", GetResponseData},
Expand Down
2 changes: 2 additions & 0 deletions curlapi.h
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,8 @@ class HTTPClient
void SetHeader(const char *name, const char *value);

long timeout = 30L;
long follow_location = 1L;
long connect_timeout = 10L;
private:
const ke::AString baseURL;
HTTPHeaderMap headers;
Expand Down
14 changes: 10 additions & 4 deletions curlthread.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -54,10 +54,13 @@ static size_t WriteResponseBody(void *body, size_t size, size_t nmemb, void *use

void HTTPRequestThread::RunThread(IThreadHandle *pHandle)
{
char* szError = new char[256];
CURL *curl = curl_easy_init();
if (curl == NULL)
{
smutils->LogError(myself, "Could not initialize cURL session.");
// smutils->LogError(myself, "Could not initialize cURL session.");
smutils->Format(szError, 256, "Could not initialize cURL session.");
g_RipExt.AddCallbackToQueue(HTTPRequestCallback(this->function, this->value, szError));
return;
}

Expand Down Expand Up @@ -90,9 +93,9 @@ void HTTPRequestThread::RunThread(IThreadHandle *pHandle)

curl_easy_setopt(curl, CURLOPT_ACCEPT_ENCODING, "");
curl_easy_setopt(curl, CURLOPT_CAINFO, caBundlePath);
curl_easy_setopt(curl, CURLOPT_CONNECTTIMEOUT, 10L);
curl_easy_setopt(curl, CURLOPT_CONNECTTIMEOUT, this->client->connect_timeout);
curl_easy_setopt(curl, CURLOPT_ERRORBUFFER, error);
curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1L);
curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, this->client->follow_location);
curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers);
curl_easy_setopt(curl, CURLOPT_NOSIGNAL, 1L);
curl_easy_setopt(curl, CURLOPT_READDATA, &this->request);
Expand All @@ -109,7 +112,9 @@ void HTTPRequestThread::RunThread(IThreadHandle *pHandle)
curl_slist_free_all(headers);
free(this->request.body);

smutils->LogError(myself, "HTTP request failed: %s", error);
// smutils->LogError(myself, "HTTP request failed: %s", error);
smutils->Format(szError, 256, "%s", error);
g_RipExt.AddCallbackToQueue(HTTPRequestCallback(this->function, this->value, szError));
return;
}

Expand All @@ -121,4 +126,5 @@ void HTTPRequestThread::RunThread(IThreadHandle *pHandle)
free(this->request.body);

g_RipExt.AddCallbackToQueue(HTTPRequestCallback(this->function, response, this->value));
delete []szError;
}
17 changes: 17 additions & 0 deletions extension.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -110,21 +110,37 @@ void RipExt::RunFrame()
IPluginFunction *function = callback.function;
struct HTTPResponse response = callback.response;
cell_t value = callback.value;
char* szError = callback.error;

/* Function can be a null or not callable after processed request. */
if (function == NULL || !function->IsRunnable())
{
smutils->LogError(myself, "Invalid function after processed request.");
json_decref(response.data);
if (szError != nullptr) delete []szError;
this->callbackMutex->Unlock();

return;
}

/* Error handling from cURL Thread */
if (szError != nullptr) {
function->PushCell(BAD_HANDLE);
function->PushCell(value);
function->PushString(szError);
function->Execute(NULL);

json_decref(response.data);
delete []szError;
this->callbackMutex->Unlock();
return;
}

HandleSecurity sec(NULL, myself->GetIdentity());
Handle_t hndlResponse = handlesys->CreateHandleEx(htHTTPResponseObject, &response, &sec, NULL, NULL);
if (hndlResponse == BAD_HANDLE)
{
json_decref(response.data);
this->callbackMutex->Unlock();

smutils->LogError(myself, "Could not create HTTP response handle.");
Expand All @@ -133,6 +149,7 @@ void RipExt::RunFrame()

function->PushCell(hndlResponse);
function->PushCell(value);
function->PushString("");
function->Execute(NULL);

handlesys->FreeHandle(hndlResponse, &sec);
Expand Down
6 changes: 5 additions & 1 deletion extension.h
Original file line number Diff line number Diff line change
Expand Up @@ -67,11 +67,15 @@ struct HTTPResponse {

struct HTTPRequestCallback {
HTTPRequestCallback(IPluginFunction *function, struct HTTPResponse response, cell_t value)
: function(function), response(response), value(value) {}
: function(function), response(response), value(value), error(nullptr) {}

HTTPRequestCallback(IPluginFunction *function, cell_t value, char* error)
: function(function), response(), value(value), error(error) {}

IPluginFunction *function;
struct HTTPResponse response;
cell_t value;
char* error;
};


Expand Down
15 changes: 14 additions & 1 deletion pawn/scripting/include/ripext/http.inc
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@ enum HTTPStatus
typeset HTTPRequestCallback
{
function void (HTTPResponse response, any value);
function void (HTTPResponse response, any value, const char[] szError);
};

methodmap HTTPResponse
Expand Down Expand Up @@ -122,9 +123,21 @@ methodmap HTTPClient < Handle
// @param value Optional value to pass to the callback function.
public native void Delete(const char[] endpoint, HTTPRequestCallback callback, any value = 0);

// Connection timeout in seconds.
// Timeout in seconds.
property int Timeout {
public native get();
public native set(int iTimeout);
}

// Connection timeout in seconds.
property int ConnectTimeout {
public native get();
public native set(int iConnectTimeout);
}

// Follow location? (HTTP response code 30X)
property bool FollowLocation {
public native get();
public native set(bool bFollowLocation);
}
};
2 changes: 1 addition & 1 deletion smsdk_config.h
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@
/* Basic information exposed publicly */
#define SMEXT_CONF_NAME "REST in Pawn"
#define SMEXT_CONF_DESCRIPTION "Provides HTTP and JSON natives for plugins"
#define SMEXT_CONF_VERSION "1.0.4"
#define SMEXT_CONF_VERSION "1.0.5"
#define SMEXT_CONF_AUTHOR "Tsunami, CrazyHackGUT aka Kruzya"
#define SMEXT_CONF_URL "https://kruzefag.ru/"
#define SMEXT_CONF_LOGTAG "RIPEXT"
Expand Down

0 comments on commit f0841ac

Please sign in to comment.