Init
This commit is contained in:
279
DependentExtensions/Rackspace/Rackspace2.cpp
Normal file
279
DependentExtensions/Rackspace/Rackspace2.cpp
Normal file
@ -0,0 +1,279 @@
|
||||
/*
|
||||
* Original work: Copyright (c) 2014, Oculus VR, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This source code is licensed under the BSD-style license found in the
|
||||
* RakNet License.txt file in the licenses directory of this source tree. An additional grant
|
||||
* of patent rights can be found in the RakNet Patents.txt file in the same directory.
|
||||
*
|
||||
*
|
||||
* Modified work: Copyright (c) 2016-2020, SLikeSoft UG (haftungsbeschränkt)
|
||||
*
|
||||
* This source code was modified by SLikeSoft. Modifications are licensed under the MIT-style
|
||||
* license found in the license.txt file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
#include "Rackspace2.h"
|
||||
#include "slikenet/TCPInterface.h"
|
||||
#include "slikenet/HTTPConnection2.h"
|
||||
#include "slikenet/linux_adapter.h"
|
||||
#include "slikenet/osx_adapter.h"
|
||||
|
||||
using namespace SLNet;
|
||||
|
||||
Rackspace2::Rackspace2()
|
||||
{
|
||||
X_Auth_Token[0]=0;
|
||||
eventCallback=0;
|
||||
tcp=0;
|
||||
cloudAccountNumber=0;
|
||||
reexecuteLastRequestOnAuth=false;
|
||||
}
|
||||
Rackspace2::~Rackspace2()
|
||||
{
|
||||
|
||||
}
|
||||
void Rackspace2::Update(void)
|
||||
{
|
||||
RakString stringTransmitted;
|
||||
RakString hostTransmitted;
|
||||
RakString responseReceived;
|
||||
Packet *packet;
|
||||
SystemAddress sa;
|
||||
// This is kind of crappy, but for TCP plugins, always do HasCompletedConnectionAttempt, then Receive(), then HasFailedConnectionAttempt(),HasLostConnection()
|
||||
sa = tcp->HasCompletedConnectionAttempt();
|
||||
if (sa!=UNASSIGNED_SYSTEM_ADDRESS)
|
||||
{
|
||||
//printf("Rackspace2 TCP: Connected to %s\n", sa.ToString());
|
||||
// serverAddress = sa;
|
||||
}
|
||||
for (packet = tcp->Receive(); packet; tcp->DeallocatePacket(packet), packet = tcp->Receive())
|
||||
;
|
||||
sa = tcp->HasFailedConnectionAttempt();
|
||||
//if (sa!=UNASSIGNED_SYSTEM_ADDRESS)
|
||||
// printf("Rackspace2 TCP: Failed connection attempt to %s\n", sa.ToString());
|
||||
sa = tcp->HasLostConnection();
|
||||
if (sa!=UNASSIGNED_SYSTEM_ADDRESS)
|
||||
{
|
||||
//printf("Rackspace2 TCP: Lost connection to %s\n", sa.ToString());
|
||||
// serverAddress=UNASSIGNED_SYSTEM_ADDRESS;
|
||||
}
|
||||
|
||||
SystemAddress hostReceived;
|
||||
ptrdiff_t contentOffset;
|
||||
if (httpConnection2->GetResponse(stringTransmitted, hostTransmitted, responseReceived, hostReceived, contentOffset))
|
||||
{
|
||||
if (responseReceived.IsEmpty()==false)
|
||||
{
|
||||
static FILE *fp = nullptr;
|
||||
if (fp == nullptr)
|
||||
fopen_s(&fp, "responses.txt", "wt");
|
||||
// #low - add nullptr-check (incl. error logging) for fp
|
||||
fprintf(fp, responseReceived.C_String());
|
||||
fprintf(fp, "\n");
|
||||
if (contentOffset==-1)
|
||||
{
|
||||
if (eventCallback)
|
||||
eventCallback->OnResponse(R2RC_NO_CONTENT, responseReceived, contentOffset);
|
||||
}
|
||||
else
|
||||
{
|
||||
json_error_t error;
|
||||
|
||||
json_t *root = json_loads(strstr(responseReceived.C_String() + contentOffset, "{"), JSON_REJECT_DUPLICATES | JSON_DISABLE_EOF_CHECK, &error);
|
||||
if (!root)
|
||||
{
|
||||
if (eventCallback)
|
||||
eventCallback->OnResponse(R2RC_BAD_JSON, responseReceived, contentOffset);
|
||||
}
|
||||
else
|
||||
{
|
||||
void *iter = json_object_iter(root);
|
||||
const char *firstKey = json_object_iter_key(iter);
|
||||
if (_stricmp(firstKey, "unauthorized")==0)
|
||||
{
|
||||
if (eventCallback)
|
||||
eventCallback->OnResponse(R2RC_UNAUTHORIZED, responseReceived, contentOffset);
|
||||
}
|
||||
else if (_stricmp(firstKey, "itemNotFound")==0)
|
||||
{
|
||||
if (eventCallback)
|
||||
eventCallback->OnResponse(R2RC_404_NOT_FOUND, responseReceived, contentOffset);
|
||||
}
|
||||
else if (_stricmp(firstKey, "access")==0)
|
||||
{
|
||||
json_t *valAuthToken = json_object_get(json_object_get(json_object_get(root, "access"), "token"), "id");
|
||||
strcpy_s(X_Auth_Token, json_string_value(valAuthToken));
|
||||
|
||||
json_t *valAccountNumber = json_object_get(json_object_get(json_object_get(json_object_get(root, "access"), "token"), "tenant"), "id");
|
||||
cloudAccountNumber = atoi(json_string_value(valAccountNumber));
|
||||
|
||||
if (reexecuteLastRequestOnAuth)
|
||||
{
|
||||
reexecuteLastRequestOnAuth=false;
|
||||
|
||||
json_t *root2 = json_loads(__addOpLast_dataAsStr.C_String(), 0, &error);
|
||||
AddOperation(__addOpLast_URL, __addOpLast_isPost, root2, true);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (eventCallback)
|
||||
eventCallback->OnResponse(R2RC_AUTHENTICATED, responseReceived, contentOffset);
|
||||
}
|
||||
|
||||
}
|
||||
else if (_stricmp(firstKey, "domains")==0)
|
||||
{
|
||||
if (eventCallback)
|
||||
eventCallback->OnResponse(R2RC_GOT_DOMAINS, responseReceived, contentOffset);
|
||||
}
|
||||
else if (_stricmp(firstKey, "records")==0)
|
||||
{
|
||||
if (eventCallback)
|
||||
eventCallback->OnResponse(R2RC_GOT_RECORDS, responseReceived, contentOffset);
|
||||
}
|
||||
else if (_stricmp(firstKey, "servers")==0)
|
||||
{
|
||||
if (eventCallback)
|
||||
eventCallback->OnResponse(R2RC_GOT_SERVERS, responseReceived, contentOffset);
|
||||
}
|
||||
else if (_stricmp(firstKey, "images")==0)
|
||||
{
|
||||
if (eventCallback)
|
||||
eventCallback->OnResponse(R2RC_GOT_IMAGES, responseReceived, contentOffset);
|
||||
}
|
||||
else if (_stricmp(firstKey, "message")==0)
|
||||
{
|
||||
const char *message = json_string_value(json_object_iter_value(iter));
|
||||
|
||||
if (strcmp(message, "Invalid authentication token. Please renew.")==0)
|
||||
{
|
||||
// Sets reexecuteLastRequestOnAuth to true
|
||||
// After authenticate completes, will rerun the last run command
|
||||
Reauthenticate();
|
||||
}
|
||||
else
|
||||
{
|
||||
if (eventCallback)
|
||||
eventCallback->OnMessage(message, responseReceived, stringTransmitted, contentOffset);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (eventCallback)
|
||||
eventCallback->OnResponse(R2RC_UNKNOWN, responseReceived, contentOffset);
|
||||
}
|
||||
}
|
||||
|
||||
json_decref(root);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (eventCallback)
|
||||
eventCallback->OnEmptyResponse(stringTransmitted);
|
||||
}
|
||||
}
|
||||
}
|
||||
void Rackspace2::SetEventCallback(Rackspace2EventCallback *callback)
|
||||
{
|
||||
eventCallback=callback;
|
||||
}
|
||||
int Rackspace2::GetCloudAccountNumber(void) const
|
||||
{
|
||||
return cloudAccountNumber;
|
||||
}
|
||||
const char *Rackspace2::GetAuthToken(void) const
|
||||
{
|
||||
return (const char*) &X_Auth_Token;
|
||||
}
|
||||
void Rackspace2::Reauthenticate(void)
|
||||
{
|
||||
reexecuteLastRequestOnAuth=true;
|
||||
AuthenticateInt(lastAuthenticationURL.C_String(), lastRackspaceCloudUsername.C_String(), lastApiAccessKey.C_String());
|
||||
}
|
||||
void Rackspace2::AuthenticateInt(const char *authenticationURL, const char *rackspaceCloudUsername, const char *apiAccessKey)
|
||||
{
|
||||
json_t *json_credentials = json_object();
|
||||
json_object_set(json_credentials, "username", json_string(rackspaceCloudUsername));
|
||||
json_object_set(json_credentials, "apiKey", json_string(apiAccessKey));
|
||||
json_t *json_auth = json_object();
|
||||
json_object_set(json_auth, "RAX-KSKEY:apiKeyCredentials", json_credentials);
|
||||
json_t *json_root = json_object();
|
||||
json_object_set(json_root, "auth", json_auth);
|
||||
|
||||
RakString URL = authenticationURL;
|
||||
RakString command = "/tokens";
|
||||
URL += command;
|
||||
|
||||
AddOperation(URL, OT_POST, json_root, false);
|
||||
}
|
||||
void Rackspace2::Authenticate(const char *authenticationURL, const char *rackspaceCloudUsername, const char *apiAccessKey)
|
||||
{
|
||||
lastAuthenticationURL=authenticationURL;
|
||||
lastRackspaceCloudUsername=rackspaceCloudUsername;
|
||||
lastApiAccessKey=apiAccessKey;
|
||||
AuthenticateInt(authenticationURL, rackspaceCloudUsername,apiAccessKey);
|
||||
}
|
||||
void Rackspace2::AddOperation(SLNet::RakString URL, OpType opType, json_t *data, bool setAuthToken)
|
||||
{
|
||||
if (tcp==0)
|
||||
{
|
||||
tcp = SLNet::OP_NEW<TCPInterface>(_FILE_AND_LINE_);
|
||||
|
||||
if (tcp->Start(0, 0, 8)==false)
|
||||
{
|
||||
if (eventCallback)
|
||||
eventCallback->OnTCPFailure();
|
||||
}
|
||||
|
||||
httpConnection2 = SLNet::OP_NEW<HTTPConnection2>(_FILE_AND_LINE_);
|
||||
|
||||
tcp->AttachPlugin(httpConnection2);
|
||||
}
|
||||
|
||||
RakString authURLHeader, authURLDomain, authURLPath;
|
||||
URL.SplitURI(authURLHeader,authURLDomain,authURLPath);
|
||||
char *jsonStr = "";
|
||||
if (data)
|
||||
jsonStr = json_dumps(data, 0);
|
||||
RakString requestStr;
|
||||
RakString extraBody;
|
||||
if (setAuthToken)
|
||||
{
|
||||
RakAssert(X_Auth_Token[0]);
|
||||
// Test expired token
|
||||
//strcpy_s(X_Auth_Token, "fd6ad67c-fbd3-4b35-94e2-059b6090998e");
|
||||
extraBody.Set("Accept: application/json\r\nX-Auth-Token: %s", X_Auth_Token);
|
||||
|
||||
__addOpLast_URL = URL;
|
||||
__addOpLast_isPost = opType;
|
||||
__addOpLast_dataAsStr = jsonStr;
|
||||
}
|
||||
else
|
||||
{
|
||||
extraBody = "Accept: application/json";
|
||||
}
|
||||
|
||||
if (opType==OT_POST)
|
||||
requestStr = RakString::FormatForPOST(URL, "application/json", jsonStr, extraBody);
|
||||
else if (opType==OT_GET)
|
||||
requestStr = RakString::FormatForGET(URL, extraBody);
|
||||
else if (opType==OT_DELETE)
|
||||
requestStr = RakString::FormatForDELETE(URL, extraBody);
|
||||
else
|
||||
requestStr = RakString::FormatForPUT(URL, "application/json", jsonStr, extraBody);
|
||||
|
||||
bool b = httpConnection2->TransmitRequest(requestStr,authURLDomain, 443, true);
|
||||
if (!b)
|
||||
{
|
||||
if (eventCallback)
|
||||
eventCallback->OnTransmissionFailed(httpConnection2, requestStr, authURLDomain);
|
||||
}
|
||||
if (data)
|
||||
{
|
||||
free(jsonStr);
|
||||
json_decref(data);
|
||||
}
|
||||
}
|
||||
|
||||
138
DependentExtensions/Rackspace/Rackspace2.h
Normal file
138
DependentExtensions/Rackspace/Rackspace2.h
Normal file
@ -0,0 +1,138 @@
|
||||
/*
|
||||
* Original work: Copyright (c) 2014, Oculus VR, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This source code is licensed under the BSD-style license found in the
|
||||
* RakNet License.txt file in the licenses directory of this source tree. An additional grant
|
||||
* of patent rights can be found in the RakNet Patents.txt file in the same directory.
|
||||
*
|
||||
*
|
||||
* Modified work: Copyright (c) 2016-2017, SLikeSoft UG (haftungsbeschränkt)
|
||||
*
|
||||
* This source code was modified by SLikeSoft. Modifications are licensed under the MIT-style
|
||||
* license found in the license.txt file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
/// \file Rackspace.h
|
||||
/// \brief Helper to class to manage Rackspace servers
|
||||
|
||||
#include "slikenet/NativeFeatureIncludes.h"
|
||||
|
||||
#if _RAKNET_SUPPORT_TCPInterface==1
|
||||
|
||||
#include "slikenet/Export.h"
|
||||
#include "slikenet/types.h"
|
||||
#include "slikenet/DS_Queue.h"
|
||||
#include "slikenet/string.h"
|
||||
#include "jansson.h"
|
||||
|
||||
#ifndef __RACKSPACE_2_H
|
||||
#define __RACKSPACE_2_H
|
||||
|
||||
namespace SLNet
|
||||
{
|
||||
class TCPInterface;
|
||||
class HTTPConnection2;
|
||||
struct Packet;
|
||||
|
||||
enum Rackspace2ResponseCode
|
||||
{
|
||||
R2RC_AUTHENTICATED,
|
||||
R2RC_GOT_DOMAINS,
|
||||
R2RC_GOT_RECORDS,
|
||||
R2RC_GOT_SERVERS,
|
||||
R2RC_GOT_IMAGES,
|
||||
R2RC_NO_CONTENT,
|
||||
R2RC_BAD_JSON,
|
||||
R2RC_UNAUTHORIZED,
|
||||
R2RC_404_NOT_FOUND,
|
||||
R2RC_UNKNOWN,
|
||||
};
|
||||
|
||||
/// \brief Callback interface to receive the results of operations
|
||||
class RAK_DLL_EXPORT Rackspace2EventCallback
|
||||
{
|
||||
public:
|
||||
virtual void OnTCPFailure(void)=0;
|
||||
virtual void OnTransmissionFailed(HTTPConnection2 *httpConnection2, RakString postStr, RakString authURLDomain)=0;
|
||||
virtual void OnResponse(Rackspace2ResponseCode r2rc, RakString responseReceived, ptrdiff_t contentOffset)=0;
|
||||
virtual void OnEmptyResponse(RakString stringTransmitted)=0;
|
||||
virtual void OnMessage(const char *message, RakString responseReceived, RakString stringTransmitted, ptrdiff_t contentOffset)=0;
|
||||
};
|
||||
|
||||
/// \brief Version 2 of the code that uses the TCPInterface class to communicate with the Rackspace API servers
|
||||
/// Works with their "next-gen" API as of 2012
|
||||
/// API operations are hidden at http://docs.rackspace.com/servers/api/v2/cs-devguide/content/ch_api_operations.html
|
||||
/// \pre Compile RakNet with OPEN_SSL_CLIENT_SUPPORT set to 1
|
||||
/// Maintains its own TCPInterface class
|
||||
class RAK_DLL_EXPORT Rackspace2
|
||||
{
|
||||
public:
|
||||
Rackspace2();
|
||||
~Rackspace2();
|
||||
|
||||
// Call periodically
|
||||
void Update(void);
|
||||
|
||||
/// Sets the callback to be used when an operation completes
|
||||
void SetEventCallback(Rackspace2EventCallback *callback);
|
||||
|
||||
int GetCloudAccountNumber(void) const;
|
||||
const char *GetAuthToken(void) const;
|
||||
|
||||
/// \brief Authenticate with Rackspace servers, required before executing any commands.
|
||||
/// \details All requests to authenticate and operate against Cloud Servers are performed using SSL over HTTP (HTTPS) on TCP port 443.
|
||||
/// TODO - Will reauthenticate automatically as needed
|
||||
/// \param[in] authenticationURL See http://docs.rackspace.com/cdns/api/v1.0/cdns-devguide/content/Authentication-d1e647.html
|
||||
/// \param[in] rackspaceCloudUsername Username you registered with Rackspace on their website
|
||||
/// \param[in] apiAccessKey Obtain your API access key from the Rackspace Cloud Control Panel in the Your Account API Access section.
|
||||
void Authenticate(const char *authenticationURL, const char *rackspaceCloudUsername, const char *apiAccessKey);
|
||||
|
||||
enum OpType
|
||||
{
|
||||
OT_POST,
|
||||
OT_PUT,
|
||||
OT_GET,
|
||||
OT_DELETE,
|
||||
};
|
||||
|
||||
/// \param[in] URL Path to command, for example https://identity.api.rackspacecloud.com/v2.0/tokens
|
||||
/// \param[in] opType Type of operation to perform
|
||||
/// \param[in] data If the operation requires data, put it here
|
||||
/// \param[in] setAuthToken true to automatically set the auth token for the operation. I believe this should be true for everything except authentication itself
|
||||
void AddOperation(SLNet::RakString URL, OpType opType, json_t *data, bool setAuthToken);
|
||||
|
||||
struct Operation
|
||||
{
|
||||
SLNet::RakString URL;
|
||||
bool isPost;
|
||||
json_t *data;
|
||||
};
|
||||
|
||||
protected:
|
||||
void AuthenticateInt(const char *authenticationURL, const char *rackspaceCloudUsername, const char *apiAccessKey);
|
||||
void Reauthenticate(void);
|
||||
|
||||
char X_Auth_Token[128];
|
||||
Rackspace2EventCallback *eventCallback;
|
||||
DataStructures::Queue<Operation> operations;
|
||||
TCPInterface *tcp;
|
||||
HTTPConnection2 *httpConnection2;
|
||||
int cloudAccountNumber;
|
||||
RakString lastAuthenticationURL;
|
||||
RakString lastRackspaceCloudUsername;
|
||||
RakString lastApiAccessKey;
|
||||
bool reexecuteLastRequestOnAuth;
|
||||
|
||||
//SystemAddress serverAddress;
|
||||
RakString __addOpLast_URL;
|
||||
OpType __addOpLast_isPost;
|
||||
RakString __addOpLast_dataAsStr;
|
||||
|
||||
};
|
||||
|
||||
} // namespace SLNet
|
||||
|
||||
#endif // __RACKSPACE_API_H
|
||||
|
||||
#endif // _RAKNET_SUPPORT_Rackspace
|
||||
Reference in New Issue
Block a user