SLikeNet  0.1.3
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
Rackspace.cpp
Go to the documentation of this file.
1 /*
2  * Original work: Copyright (c) 2014, Oculus VR, Inc.
3  * All rights reserved.
4  *
5  * This source code is licensed under the BSD-style license found in the
6  * RakNet License.txt file in the licenses directory of this source tree. An additional grant
7  * of patent rights can be found in the RakNet Patents.txt file in the same directory.
8  *
9  *
10  * Modified work: Copyright (c) 2017, SLikeSoft UG (haftungsbeschränkt)
11  *
12  * This source code was modified by SLikeSoft. Modifications are licensed under the MIT-style
13  * license found in the license.txt file in the root directory of this source tree.
14  */
15 
17 #if _RAKNET_SUPPORT_Rackspace==1 && _RAKNET_SUPPORT_TCPInterface==1
18 
19 #include "slikenet/Rackspace.h"
20 #include "slikenet/string.h"
21 #include "slikenet/TCPInterface.h"
22 
23 using namespace SLNet;
24 
26 {
27  tcpInterface=0;
28 }
29 
31 {
32 
33 }
34 
36 {
37  unsigned int idx = eventCallbacks.GetIndexOf(callback);
38  if (idx == (unsigned int)-1)
40 }
42 {
43  unsigned int idx = eventCallbacks.GetIndexOf(callback);
44  if (idx != (unsigned int)-1)
46 }
48 {
50 }
51 SystemAddress Rackspace::Authenticate(TCPInterface *_tcpInterface, const char *_authenticationURL, const char *_rackspaceCloudUsername, const char *_apiAccessKey)
52 {
54  if (index!=(unsigned int)-1)
55  {
56  // In progress
57  return operations[index].connectionAddress;
58  }
59 
60  tcpInterface=_tcpInterface;
61 
62  rackspaceCloudUsername=_rackspaceCloudUsername;
63  apiAccessKey=_apiAccessKey;
64 
65  unsigned int i;
66 
67  RackspaceOperation ro;
69  ro.isPendingAuthentication=false;
70 
72  ro.connectionAddress=tcpInterface->Connect(_authenticationURL,443,true);
73  if (ro.connectionAddress==UNASSIGNED_SYSTEM_ADDRESS)
74  {
75  for (i=0; i < eventCallbacks.Size(); i++)
76  eventCallbacks[i]->OnConnectionAttemptFailure(RO_CONNECT_AND_AUTHENTICATE, _authenticationURL);
77 
79  }
80 
81 #if OPEN_SSL_CLIENT_SUPPORT==1
82  tcpInterface->StartSSLClient(ro.connectionAddress);
83 #endif
84 
85  SLNet::RakString command(
86  "GET /v1.0 HTTP/1.1\n"
87  "Host: %s\n"
88  "X-Auth-User: %s\n"
89  "X-Auth-Key: %s\n\n"
90  ,_authenticationURL, _rackspaceCloudUsername, _apiAccessKey);
91  tcpInterface->Send(command.C_String(), (unsigned int) command.GetLength(), ro.connectionAddress, false);
92 
94  return ro.connectionAddress;
95 }
96 
98 {
99  switch (eventType)
100  {
101  case RET_Success_200:
102  return "Success_200";
103  case RET_Success_201:
104  return "Success_201";
105  case RET_Success_202:
106  return "Success_202";
107  case RET_Success_203:
108  return "Success_203";
109  case RET_Success_204:
110  return "Success_204";
112  return "Cloud_Servers_Fault_500";
114  return "Service_Unavailable_503";
116  return "Unauthorized_401";
117  case RET_Bad_Request_400:
118  return "Bad_Request_400";
119  case RET_Over_Limit_413:
120  return "Over_Limit_413";
122  return "Bad_Media_Type_415";
124  return "Item_Not_Found_404";
126  return "Build_In_Progress_409";
128  return "Resize_Not_Allowed_403";
130  return "Connection_Closed_Without_Reponse";
131  case RET_Unknown_Failure:
132  return "Unknown_Failure";
133  }
134  return "Unknown event type (bug)";
135 }
137 {
138  RackspaceOperation ro;
139  ro.type=type;
140  ro.httpCommand=httpCommand;
141  ro.operation=operation;
142  ro.xml=xml;
143  ro.isPendingAuthentication=HasOperationOfType(RO_CONNECT_AND_AUTHENTICATE);
144  if (ro.isPendingAuthentication==false)
145  {
146  if (ExecuteOperation(ro))
148  }
149  else
151 }
152 void Rackspace::ListServers(void)
153 {
154  AddOperation(RO_LIST_SERVERS, "GET", "servers", "");
155 }
157 {
158  AddOperation(RO_LIST_SERVERS_WITH_DETAILS, "GET", "servers/detail", "");
159 }
161 {
162  SLNet::RakString xml(
163  "<?xml version=\"1.0\" encoding=\"UTF-8\"?>"
164  "<server xmlns=\"http://docs.rackspacecloud.com/servers/api/v1.0\" name=\"%s\" imageId=\"%s\" flavorId=\"%s\">"
165  "</server>"
166  ,name.C_String() ,imageId.C_String(), flavorId.C_String());
167  AddOperation(RO_CREATE_SERVER, "POST", "servers", xml);
168 }
170 {
171  AddOperation(RO_GET_SERVER_DETAILS, "GET", SLNet::RakString("servers/%s", serverId.C_String()), "");
172 }
174 {
175  if (newName.IsEmpty() && newPassword.IsEmpty())
176  return;
177  SLNet::RakString xml(
178  "<?xml version=\"1.0\" encoding=\"UTF-8\"?>"
179  "<server xmlns=\"http://docs.rackspacecloud.com/servers/api/v1.0\""
180  );
181  if (newName.IsEmpty()==false)
182  xml += SLNet::RakString(" name=\"%s\"", newName.C_String());
183  if (newPassword.IsEmpty()==false)
184  xml += SLNet::RakString(" adminPass=\"%s\"", newPassword.C_String());
185  xml += " />";
186  AddOperation(RO_UPDATE_SERVER_NAME_OR_PASSWORD, "PUT", SLNet::RakString("servers/%s", serverId.C_String()), xml);
187 }
189 {
190  AddOperation(RO_DELETE_SERVER, "DELETE", SLNet::RakString("servers/%s", serverId.C_String()), "");
191 }
193 {
194  AddOperation(RO_LIST_SERVER_ADDRESSES, "GET", SLNet::RakString("servers/%s/ips", serverId.C_String()), "");
195 }
197 {
198  AddOperation(RO_SHARE_SERVER_ADDRESS, "PUT", SLNet::RakString("servers/%s/ips/public/%s", serverId.C_String(), ipAddress.C_String()), "");
199 }
201 {
202  AddOperation(RO_DELETE_SERVER_ADDRESS, "DELETE", SLNet::RakString("servers/%s/ips/public/%s", serverId.C_String(), ipAddress.C_String()), "");
203 }
205 {
206  SLNet::RakString xml(
207  "<?xml version=\"1.0\" encoding=\"UTF-8\"?>"
208  "<reboot xmlns=\"http://docs.rackspacecloud.com/servers/api/v1.0\" type=\"%s\""
209  "/>",
210  rebootType.C_String());
211 
212  AddOperation(RO_REBOOT_SERVER, "POST", SLNet::RakString("servers/%s/action", serverId.C_String()), xml);
213 }
215 {
216  SLNet::RakString xml(
217  "<?xml version=\"1.0\" encoding=\"UTF-8\"?>"
218  "<rebuild xmlns=\"http://docs.rackspacecloud.com/servers/api/v1.0\" imageId=\"%s\""
219  "/>",
220  imageId.C_String());
221 
222  AddOperation(RO_REBUILD_SERVER, "POST", SLNet::RakString("servers/%s/action", serverId.C_String()), xml);
223 }
225 {
226  SLNet::RakString xml(
227  "<?xml version=\"1.0\" encoding=\"UTF-8\"?>"
228  "<resize xmlns=\"http://docs.rackspacecloud.com/servers/api/v1.0\" flavorId=\"%s\""
229  "/>",
230  flavorId.C_String());
231 
232  AddOperation(RO_RESIZE_SERVER, "POST", SLNet::RakString("servers/%s/action", serverId.C_String()), xml);
233 }
235 {
236  SLNet::RakString xml(
237  "<?xml version=\"1.0\" encoding=\"UTF-8\"?>"
238  "<confirmResize xmlns=\"http://docs.rackspacecloud.com/servers/api/v1.0\" "
239  "/>");
240  AddOperation(RO_CONFIRM_RESIZED_SERVER, "POST", SLNet::RakString("servers/%s/action", serverId.C_String()), xml);
241 }
243 {
244  SLNet::RakString xml(
245  "<?xml version=\"1.0\" encoding=\"UTF-8\"?>"
246  "<revertResize xmlns=\"http://docs.rackspacecloud.com/servers/api/v1.0\" "
247  "/>");
248  AddOperation(RO_REVERT_RESIZED_SERVER, "POST", SLNet::RakString("servers/%s/action", serverId.C_String()), xml);
249 }
250 void Rackspace::ListFlavors(void)
251 {
252  AddOperation(RO_LIST_FLAVORS, "GET", "flavors", "");
253 }
255 {
256  AddOperation(RO_GET_FLAVOR_DETAILS, "GET", SLNet::RakString("flavors/%s", flavorId.C_String()), "");
257 }
258 void Rackspace::ListImages(void)
259 {
260  AddOperation(RO_LIST_IMAGES, "GET", "images", "");
261 }
263 {
264  SLNet::RakString xml(
265  "<?xml version=\"1.0\" encoding=\"UTF-8\"?>"
266  "<image xmlns=\"http://docs.rackspacecloud.com/servers/api/v1.0\" name=\"%s\" serverId=\"%s\""
267  "/>",
268  imageName.C_String(),serverId.C_String());
269 
270  AddOperation(RO_CREATE_IMAGE, "POST", "images", xml);
271 }
273 {
274  AddOperation(RO_GET_IMAGE_DETAILS, "GET", SLNet::RakString("images/%s", imageId.C_String()), "");
275 }
277 {
278  AddOperation(RO_DELETE_IMAGE, "DELETE", SLNet::RakString("images/%s", imageId.C_String()), "");
279 }
281 {
282  AddOperation(RO_LIST_SHARED_IP_GROUPS, "GET", "shared_ip_groups", "");
283 }
285 {
286  AddOperation(RO_LIST_SHARED_IP_GROUPS_WITH_DETAILS, "GET", "shared_ip_groups/detail", "");
287 }
289 {
290  SLNet::RakString xml(
291  "<?xml version=\"1.0\" encoding=\"UTF-8\"?>"
292  "<sharedIpGroup xmlns=\"http://docs.rackspacecloud.com/servers/api/v1.0\" name=\"%s\">", name.C_String());
293  if (optionalServerId.IsEmpty()==false)
294  xml+= SLNet::RakString("<server id=\"%s\"/>", optionalServerId.C_String());
295  xml+="</sharedIpGroup>";
296 
297  AddOperation(RO_CREATE_SHARED_IP_GROUP, "POST", "shared_ip_groups", xml);
298 }
300 {
301  AddOperation(RO_GET_SHARED_IP_GROUP_DETAILS, "GET", SLNet::RakString("shared_ip_groups/%s", groupId.C_String()), "");
302 }
304 {
305  AddOperation(RO_DELETE_SHARED_IP_GROUP, "DELETE", SLNet::RakString("shared_ip_groups/%s", groupId.C_String()), "");
306 }
308 {
309  if (systemAddress==UNASSIGNED_SYSTEM_ADDRESS)
310  return;
311 
312  unsigned int i, operationsIndex;
313  operationsIndex=0;
314  while (operationsIndex < operations.Size())
315  {
316  if (operations[operationsIndex].isPendingAuthentication==false && operations[operationsIndex].connectionAddress==systemAddress)
317  {
318  RackspaceOperation ro = operations[operationsIndex];
319  operations.RemoveAtIndex(operationsIndex);
320 
321  SLNet::RakString packetDataString = ro.incomingStream;
322  const char *packetData = packetDataString.C_String();
323 
324  char resultCodeStr[32];
325  int resultCodeInt;
326 
327  RackspaceEventType rackspaceEventType;
328  char *result;
329  result=strstr((char*) packetData, "HTTP/1.1 ");
330  if (result!=0)
331  {
332  result+=strlen("HTTP/1.1 ");
333  for (i=0; i < sizeof(resultCodeStr)-1 && result[i] && result[i]>='0' && result[i]<='9'; i++)
334  resultCodeStr[i]=result[i];
335  resultCodeStr[i]=0;
336  resultCodeInt=atoi(resultCodeStr);
337 
338  switch (resultCodeInt)
339  {
340  case 200: rackspaceEventType=RET_Success_200; break;
341  case 201: rackspaceEventType=RET_Success_201; break;
342  case 202: rackspaceEventType=RET_Success_202; break;
343  case 203: rackspaceEventType=RET_Success_203; break;
344  case 204: rackspaceEventType=RET_Success_204; break;
345  case 500: rackspaceEventType=RET_Cloud_Servers_Fault_500; break;
346  case 503: rackspaceEventType=RET_Service_Unavailable_503; break;
347  case 401: rackspaceEventType=RET_Unauthorized_401; break;
348  case 400: rackspaceEventType=RET_Bad_Request_400; break;
349  case 413: rackspaceEventType=RET_Over_Limit_413; break;
350  case 415: rackspaceEventType=RET_Bad_Media_Type_415; break;
351  case 404: rackspaceEventType=RET_Item_Not_Found_404; break;
352  case 409: rackspaceEventType=RET_Build_In_Progress_409; break;
353  case 403: rackspaceEventType=RET_Resize_Not_Allowed_403; break;
354  default: rackspaceEventType=RET_Unknown_Failure; break;
355  }
356  }
357  else
358  {
359  rackspaceEventType=RET_Connection_Closed_Without_Reponse;
360  }
361 
362  switch (ro.type)
363  {
365  {
366  if (rackspaceEventType==RET_Success_204)
367  {
368  SLNet::RakString header;
369  ReadLine(packetData, "X-Server-Management-Url: ", serverManagementURL);
371  ReadLine(packetData, "X-Storage-Url: ", storageURL);
373  ReadLine(packetData, "X-CDN-Management-Url: ", cdnManagementURL);
375  ReadLine(packetData, "X-Auth-Token: ", authToken);
376  ReadLine(packetData, "X-Storage-Token: ", storageToken);
377 
378  operationsIndex=0;
379  while (operationsIndex < operations.Size())
380  {
381  if (operations[operationsIndex].isPendingAuthentication==true)
382  {
383  operations[operationsIndex].isPendingAuthentication=false;
384  if (ExecuteOperation(operations[operationsIndex])==false)
385  {
386  operations.RemoveAtIndex(operationsIndex);
387  }
388  else
389  operationsIndex++;
390  }
391  else
392  operationsIndex++;
393  }
394 
395  // Restart in list
396  operationsIndex=0;
397  }
398 
399  for (i=0; i < eventCallbacks.Size(); i++)
400  eventCallbacks[i]->OnAuthenticationResult(rackspaceEventType, (const char*) packetData);
401 
402  break;
403  }
404  case RO_LIST_SERVERS:
405  {
406  for (i=0; i < eventCallbacks.Size(); i++)
407  eventCallbacks[i]->OnListServersResult(rackspaceEventType, (const char*) packetData);
408  break;
409  }
411  {
412  for (i=0; i < eventCallbacks.Size(); i++)
413  eventCallbacks[i]->OnListServersWithDetailsResult(rackspaceEventType, (const char*) packetData);
414  break;
415  }
416  case RO_CREATE_SERVER:
417  {
418  for (i=0; i < eventCallbacks.Size(); i++)
419  eventCallbacks[i]->OnCreateServerResult(rackspaceEventType, (const char*) packetData);
420  break;
421  }
422 
424  {
425  for (i=0; i < eventCallbacks.Size(); i++)
426  eventCallbacks[i]->OnGetServerDetails(rackspaceEventType, (const char*) packetData);
427  break;
428  }
430  {
431  for (i=0; i < eventCallbacks.Size(); i++)
432  eventCallbacks[i]->OnUpdateServerNameOrPassword(rackspaceEventType, (const char*) packetData);
433  break;
434  }
435  case RO_DELETE_SERVER:
436  {
437  for (i=0; i < eventCallbacks.Size(); i++)
438  eventCallbacks[i]->OnDeleteServer(rackspaceEventType, (const char*) packetData);
439  break;
440  }
442  {
443  for (i=0; i < eventCallbacks.Size(); i++)
444  eventCallbacks[i]->OnListServerAddresses(rackspaceEventType, (const char*) packetData);
445  break;
446  }
448  {
449  for (i=0; i < eventCallbacks.Size(); i++)
450  eventCallbacks[i]->OnShareServerAddress(rackspaceEventType, (const char*) packetData);
451  break;
452  }
454  {
455  for (i=0; i < eventCallbacks.Size(); i++)
456  eventCallbacks[i]->OnDeleteServerAddress(rackspaceEventType, (const char*) packetData);
457  break;
458  }
459  case RO_REBOOT_SERVER:
460  {
461  for (i=0; i < eventCallbacks.Size(); i++)
462  eventCallbacks[i]->OnRebootServer(rackspaceEventType, (const char*) packetData);
463  break;
464  }
465  case RO_REBUILD_SERVER:
466  {
467  for (i=0; i < eventCallbacks.Size(); i++)
468  eventCallbacks[i]->OnRebuildServer(rackspaceEventType, (const char*) packetData);
469  break;
470  }
471  case RO_RESIZE_SERVER:
472  {
473  for (i=0; i < eventCallbacks.Size(); i++)
474  eventCallbacks[i]->OnResizeServer(rackspaceEventType, (const char*) packetData);
475  break;
476  }
478  {
479  for (i=0; i < eventCallbacks.Size(); i++)
480  eventCallbacks[i]->OnConfirmResizedServer(rackspaceEventType, (const char*) packetData);
481  break;
482  }
484  {
485  for (i=0; i < eventCallbacks.Size(); i++)
486  eventCallbacks[i]->OnRevertResizedServer(rackspaceEventType, (const char*) packetData);
487  break;
488  }
489 
490 
491  case RO_LIST_FLAVORS:
492  {
493  for (i=0; i < eventCallbacks.Size(); i++)
494  eventCallbacks[i]->OnListFlavorsResult(rackspaceEventType, (const char*) packetData);
495  break;
496  }
498  {
499  for (i=0; i < eventCallbacks.Size(); i++)
500  eventCallbacks[i]->OnGetFlavorDetailsResult(rackspaceEventType, (const char*) packetData);
501  break;
502  }
503  case RO_LIST_IMAGES:
504  {
505  for (i=0; i < eventCallbacks.Size(); i++)
506  eventCallbacks[i]->OnListImagesResult(rackspaceEventType, (const char*) packetData);
507  break;
508  }
509  case RO_CREATE_IMAGE:
510  {
511  for (i=0; i < eventCallbacks.Size(); i++)
512  eventCallbacks[i]->OnCreateImageResult(rackspaceEventType, (const char*) packetData);
513  break;
514  }
516  {
517  for (i=0; i < eventCallbacks.Size(); i++)
518  eventCallbacks[i]->OnGetImageDetailsResult(rackspaceEventType, (const char*) packetData);
519  break;
520  }
521  case RO_DELETE_IMAGE:
522  {
523  for (i=0; i < eventCallbacks.Size(); i++)
524  eventCallbacks[i]->OnDeleteImageResult(rackspaceEventType, (const char*) packetData);
525  break;
526  }
528  {
529  for (i=0; i < eventCallbacks.Size(); i++)
530  eventCallbacks[i]->OnListSharedIPGroups(rackspaceEventType, (const char*) packetData);
531  break;
532  }
534  {
535  for (i=0; i < eventCallbacks.Size(); i++)
536  eventCallbacks[i]->OnListSharedIPGroupsWithDetails(rackspaceEventType, (const char*) packetData);
537  break;
538  }
540  {
541  for (i=0; i < eventCallbacks.Size(); i++)
542  eventCallbacks[i]->OnCreateSharedIPGroup(rackspaceEventType, (const char*) packetData);
543  break;
544  }
546  {
547  for (i=0; i < eventCallbacks.Size(); i++)
548  eventCallbacks[i]->OnGetSharedIPGroupDetails(rackspaceEventType, (const char*) packetData);
549  break;
550  }
552  {
553  for (i=0; i < eventCallbacks.Size(); i++)
554  eventCallbacks[i]->OnDeleteSharedIPGroup(rackspaceEventType, (const char*) packetData);
555  break;
556  }
557  default:
558  break;
559 
560  }
561  }
562  else
563  {
564  operationsIndex++;
565  }
566  }
567 }
568 void Rackspace::OnReceive(Packet *packet)
569 {
570  unsigned int operationsIndex;
571  for (operationsIndex=0; operationsIndex < operations.Size(); operationsIndex++)
572  {
573  if (operations[operationsIndex].isPendingAuthentication==false && operations[operationsIndex].connectionAddress==packet->systemAddress)
574  {
575  operations[operationsIndex].incomingStream+=packet->data;
576  }
577  }
578 }
579 bool Rackspace::ExecuteOperation(RackspaceOperation &ro)
580 {
581  if (ConnectToServerManagementDomain(ro)==false)
582  return false;
583 
584  SLNet::RakString command(
585  "%s %s/%s HTTP/1.1\n"
586  "Host: %s\n"
587  "Content-Type: application/xml\n"
588  "Content-Length: %i\n"
589  "Accept: application/xml\n"
590  "X-Auth-Token: %s\n",
591  ro.httpCommand.C_String(), serverManagementPath.C_String(), ro.operation.C_String(), serverManagementDomain.C_String(),
592  ro.xml.GetLength(),
593  authToken.C_String());
594 
595  if (ro.xml.IsEmpty()==false)
596  {
597  command+="\n";
598  command+=ro.xml;
599  command+="\n";
600  }
601 
602  command+="\n";
603 
604  //printf(command.C_String());
605 
606  tcpInterface->Send(command.C_String(), (unsigned int) command.GetLength(), ro.connectionAddress, false);
607  return true;
608 }
609 void Rackspace::ReadLine(const char *data, const char *stringStart, SLNet::RakString &output)
610 {
611  output.Clear();
612 
613  char *result, *resultEnd;
614 
615  result=strstr((char*) data, stringStart);
616  if (result==0)
617  {
618  RakAssert(0);
619  return;
620  }
621 
622  result+=strlen(stringStart);
623  if (result==0)
624  {
625  RakAssert(0);
626  return;
627  }
628 
629  output=result;
630  resultEnd=result;
631  while (*resultEnd && (*resultEnd!='\r') && (*resultEnd!='\n') )
632  resultEnd++;
633  output.Truncate((unsigned int) (resultEnd-result));
634 }
635 
636 
637 bool Rackspace::ConnectToServerManagementDomain(RackspaceOperation &ro)
638 {
639  unsigned int i;
640 
641  ro.connectionAddress=tcpInterface->Connect(serverManagementDomain.C_String(),443,true);
642  if (ro.connectionAddress==UNASSIGNED_SYSTEM_ADDRESS)
643  {
644  for (i=0; i < eventCallbacks.Size(); i++)
645  eventCallbacks[i]->OnConnectionAttemptFailure(ro.type, serverManagementURL);
646  return false;
647  }
648 
649 #if OPEN_SSL_CLIENT_SUPPORT==1
650  tcpInterface->StartSSLClient(ro.connectionAddress);
651 #endif
652 
653  return true;
654 }
656 {
657  unsigned int i;
658  for (i=0; i < operations.Size(); i++)
659  {
660  if (operations[i].type==t)
661  return true;
662  }
663  return false;
664 }
666 {
667  unsigned int i;
668  for (i=0; i < operations.Size(); i++)
669  {
670  if (operations[i].type==t)
671  return i;
672  }
673  return (unsigned int) -1;
674 }
675 
676 #endif