ApResolve.cpp 2.5 KB

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