ApResolve.cpp 2.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113
  1. #include "ApResolve.h"
  2. #include <memory>
  3. #include <vector>
  4. #include <string>
  5. #include <iostream>
  6. #include <ctype.h>
  7. #include <cstring>
  8. #include <stdlib.h>
  9. #include <sys/types.h>
  10. #ifdef _WIN32
  11. #include <winsock2.h>
  12. #include <ws2tcpip.h>
  13. #include "win32shim.h"
  14. #else
  15. #include <sys/socket.h>
  16. #include <netdb.h>
  17. #include <netinet/in.h>
  18. #include <unistd.h>
  19. #endif
  20. #include <sstream>
  21. #include <fstream>
  22. #include "Logger.h"
  23. #include <cJSON.h>
  24. #include <ConfigJSON.h>
  25. #include <random>
  26. ApResolve::ApResolve() {}
  27. std::string ApResolve::getApList()
  28. {
  29. // hostname lookup
  30. struct hostent *host = gethostbyname("apresolve.spotify.com");
  31. struct sockaddr_in client;
  32. if ((host == NULL) || (host->h_addr == NULL))
  33. {
  34. CSPOT_LOG(error, "apresolve: DNS lookup error");
  35. throw std::runtime_error("Resolve failed");
  36. }
  37. // Prepare socket
  38. bzero(&client, sizeof(client));
  39. client.sin_family = AF_INET;
  40. client.sin_port = htons(80);
  41. memcpy(&client.sin_addr, host->h_addr, host->h_length);
  42. int sockFd = socket(AF_INET, SOCK_STREAM, 0);
  43. // Connect to spotify's server
  44. if (connect(sockFd, (struct sockaddr *)&client, sizeof(client)) < 0)
  45. {
  46. close(sockFd);
  47. CSPOT_LOG(error, "Could not connect to apresolve");
  48. throw std::runtime_error("Resolve failed");
  49. }
  50. // Prepare HTTP get header
  51. std::stringstream ss;
  52. ss << "GET / HTTP/1.1\r\n"
  53. << "Host: apresolve.spotify.com\r\n"
  54. << "Accept: application/json\r\n"
  55. << "Connection: close\r\n"
  56. << "\r\n\r\n";
  57. std::string request = ss.str();
  58. // Send the request
  59. if (send(sockFd, request.c_str(), request.length(), 0) != (int)request.length())
  60. {
  61. CSPOT_LOG(error, "apresolve: can't send request");
  62. throw std::runtime_error("Resolve failed");
  63. }
  64. char cur;
  65. // skip read till json data
  66. while (read(sockFd, &cur, 1) > 0 && cur != '{');
  67. auto jsonData = std::string("{");
  68. // Read json structure
  69. while (read(sockFd, &cur, 1) > 0)
  70. {
  71. jsonData += cur;
  72. }
  73. close(sockFd);
  74. return jsonData;
  75. }
  76. std::string ApResolve::fetchFirstApAddress()
  77. {
  78. if (configMan->apOverride != "")
  79. {
  80. return configMan->apOverride;
  81. }
  82. // Fetch json body
  83. auto jsonData = getApList();
  84. // Use cJSON to get first ap address
  85. auto root = cJSON_Parse(jsonData.c_str());
  86. auto apList = cJSON_GetObjectItemCaseSensitive(root, "ap_list");
  87. auto firstAp = cJSON_GetArrayItem(apList, 0);
  88. auto data = std::string(firstAp->valuestring);
  89. // release cjson memory
  90. cJSON_Delete(root);
  91. return data;
  92. }