util.c 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606
  1. /*
  2. * AirConnect: Chromecast & UPnP to AirPlay
  3. *
  4. * (c) Philippe 2016-2017, philippe_44@outlook.com
  5. *
  6. * This software is released under the MIT License.
  7. * https://opensource.org/licenses/MIT
  8. *
  9. */
  10. #include "platform.h"
  11. #ifdef WIN32
  12. #include <iphlpapi.h>
  13. #else
  14. #include "esp_netif.h"
  15. // IDF-V4++ #include "esp_netif.h"
  16. #include <ctype.h>
  17. #endif
  18. #include <stdarg.h>
  19. #include "pthread.h"
  20. #include "util.h"
  21. #include "log_util.h"
  22. /*----------------------------------------------------------------------------*/
  23. /* globals */
  24. /*----------------------------------------------------------------------------*/
  25. extern log_level util_loglevel;
  26. /*----------------------------------------------------------------------------*/
  27. /* locals */
  28. /*----------------------------------------------------------------------------*/
  29. static log_level *loglevel = &util_loglevel;
  30. static char *ltrim(char *s);
  31. static int read_line(int fd, char *line, int maxlen, int timeout);
  32. /*----------------------------------------------------------------------------*/
  33. /* */
  34. /* NETWORKING utils */
  35. /* */
  36. /*----------------------------------------------------------------------------*/
  37. /*---------------------------------------------------------------------------*/
  38. #define MAX_INTERFACES 256
  39. #define DEFAULT_INTERFACE 1
  40. #if !defined(WIN32)
  41. #define INVALID_SOCKET (-1)
  42. #endif
  43. in_addr_t get_localhost(char **name)
  44. {
  45. #ifdef WIN32
  46. char buf[256];
  47. struct hostent *h = NULL;
  48. struct sockaddr_in LocalAddr;
  49. memset(&LocalAddr, 0, sizeof(LocalAddr));
  50. gethostname(buf, 256);
  51. h = gethostbyname(buf);
  52. if (name) *name = strdup(buf);
  53. if (h != NULL) {
  54. memcpy(&LocalAddr.sin_addr, h->h_addr_list[0], 4);
  55. return LocalAddr.sin_addr.s_addr;
  56. }
  57. else return INADDR_ANY;
  58. #else
  59. tcpip_adapter_ip_info_t ipInfo;
  60. tcpip_adapter_if_t if_type = TCPIP_ADAPTER_IF_STA;
  61. // then get IP address
  62. tcpip_adapter_get_ip_info(if_type, &ipInfo);
  63. // we might be in AP mode
  64. if (ipInfo.ip.addr == INADDR_ANY) {
  65. if_type = TCPIP_ADAPTER_IF_AP;
  66. tcpip_adapter_get_ip_info(TCPIP_ADAPTER_IF_AP, &ipInfo);
  67. }
  68. // get hostname if required
  69. if (name) {
  70. const char *hostname;
  71. tcpip_adapter_get_hostname(if_type, &hostname);
  72. *name = strdup(hostname);
  73. }
  74. return ipInfo.ip.addr;
  75. #endif
  76. }
  77. /*----------------------------------------------------------------------------*/
  78. #ifdef WIN32
  79. void winsock_init(void) {
  80. WSADATA wsaData;
  81. WORD wVersionRequested = MAKEWORD(2, 2);
  82. int WSerr = WSAStartup(wVersionRequested, &wsaData);
  83. if (WSerr != 0) {
  84. LOG_ERROR("Bad winsock version", NULL);
  85. exit(1);
  86. }
  87. }
  88. /*----------------------------------------------------------------------------*/
  89. void winsock_close(void) {
  90. WSACleanup();
  91. }
  92. #endif
  93. /*----------------------------------------------------------------------------*/
  94. int shutdown_socket(int sd)
  95. {
  96. if (sd <= 0) return -1;
  97. #ifdef WIN32
  98. shutdown(sd, SD_BOTH);
  99. #else
  100. shutdown(sd, SHUT_RDWR);
  101. #endif
  102. LOG_DEBUG("closed socket %d", sd);
  103. return closesocket(sd);
  104. }
  105. /*----------------------------------------------------------------------------*/
  106. int bind_socket(unsigned short *port, int mode)
  107. {
  108. int sock;
  109. socklen_t len = sizeof(struct sockaddr);
  110. struct sockaddr_in addr;
  111. if ((sock = socket(AF_INET, mode, 0)) < 0) {
  112. LOG_ERROR("cannot create socket %d", sock);
  113. return sock;
  114. }
  115. /* Populate socket address structure */
  116. memset(&addr, 0, sizeof(addr));
  117. addr.sin_family = AF_INET;
  118. addr.sin_addr.s_addr = htonl(INADDR_ANY);
  119. addr.sin_port = htons(*port);
  120. #ifdef SIN_LEN
  121. si.sin_len = sizeof(si);
  122. #endif
  123. if (bind(sock, (struct sockaddr*) &addr, sizeof(addr)) < 0) {
  124. closesocket(sock);
  125. LOG_ERROR("cannot bind socket %d", sock);
  126. return -1;
  127. }
  128. if (!*port) {
  129. getsockname(sock, (struct sockaddr *) &addr, &len);
  130. *port = ntohs(addr.sin_port);
  131. }
  132. LOG_DEBUG("socket binding %d on port %d", sock, *port);
  133. return sock;
  134. }
  135. /*----------------------------------------------------------------------------*/
  136. int conn_socket(unsigned short port)
  137. {
  138. struct sockaddr_in addr;
  139. int sd;
  140. sd = socket(AF_INET, SOCK_STREAM, 0);
  141. addr.sin_family = AF_INET;
  142. addr.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
  143. addr.sin_port = htons(port);
  144. if (sd < 0 || connect(sd, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
  145. close(sd);
  146. return -1;
  147. }
  148. LOG_DEBUG("created socket %d", sd);
  149. return sd;
  150. }
  151. /*----------------------------------------------------------------------------*/
  152. /* */
  153. /* SYSTEM utils */
  154. /* */
  155. /*----------------------------------------------------------------------------*/
  156. #ifdef WIN32
  157. /*----------------------------------------------------------------------------*/
  158. void *dlopen(const char *filename, int flag) {
  159. SetLastError(0);
  160. return LoadLibrary((LPCTSTR)filename);
  161. }
  162. /*----------------------------------------------------------------------------*/
  163. void *dlsym(void *handle, const char *symbol) {
  164. SetLastError(0);
  165. return (void *)GetProcAddress(handle, symbol);
  166. }
  167. /*----------------------------------------------------------------------------*/
  168. char *dlerror(void) {
  169. static char ret[32];
  170. int last = GetLastError();
  171. if (last) {
  172. sprintf(ret, "code: %i", last);
  173. SetLastError(0);
  174. return ret;
  175. }
  176. return NULL;
  177. }
  178. #endif
  179. /*----------------------------------------------------------------------------*/
  180. /* */
  181. /* STDLIB extensions */
  182. /* */
  183. /*----------------------------------------------------------------------------*/
  184. #ifdef WIN32
  185. /*---------------------------------------------------------------------------*/
  186. char *strcasestr(const char *haystack, const char *needle) {
  187. size_t length_needle;
  188. size_t length_haystack;
  189. size_t i;
  190. if (!haystack || !needle)
  191. return NULL;
  192. length_needle = strlen(needle);
  193. length_haystack = strlen(haystack);
  194. if (length_haystack < length_needle) return NULL;
  195. length_haystack -= length_needle - 1;
  196. for (i = 0; i < length_haystack; i++)
  197. {
  198. size_t j;
  199. for (j = 0; j < length_needle; j++)
  200. {
  201. unsigned char c1;
  202. unsigned char c2;
  203. c1 = haystack[i+j];
  204. c2 = needle[j];
  205. if (toupper(c1) != toupper(c2))
  206. goto next;
  207. }
  208. return (char *) haystack + i;
  209. next:
  210. ;
  211. }
  212. return NULL;
  213. }
  214. /*---------------------------------------------------------------------------*/
  215. char* strsep(char** stringp, const char* delim)
  216. {
  217. char* start = *stringp;
  218. char* p;
  219. p = (start != NULL) ? strpbrk(start, delim) : NULL;
  220. if (p == NULL) {
  221. *stringp = NULL;
  222. } else {
  223. *p = '\0';
  224. *stringp = p + 1;
  225. }
  226. return start;
  227. }
  228. /*---------------------------------------------------------------------------*/
  229. char *strndup(const char *s, size_t n) {
  230. char *p = malloc(n + 1);
  231. strncpy(p, s, n);
  232. p[n] = '\0';
  233. return p;
  234. }
  235. #endif
  236. /*----------------------------------------------------------------------------*/
  237. char* strextract(char *s1, char *beg, char *end)
  238. {
  239. char *p1, *p2, *res;
  240. p1 = strcasestr(s1, beg);
  241. if (!p1) return NULL;
  242. p1 += strlen(beg);
  243. p2 = strcasestr(p1, end);
  244. if (!p2) return strdup(p1);
  245. res = malloc(p2 - p1 + 1);
  246. memcpy(res, p1, p2 - p1);
  247. res[p2 - p1] = '\0';
  248. return res;
  249. }
  250. #ifdef WIN32
  251. /*----------------------------------------------------------------------------*/
  252. int asprintf(char **strp, const char *fmt, ...)
  253. {
  254. va_list args, cp;
  255. int len, ret = 0;
  256. va_start(args, fmt);
  257. len = vsnprintf(NULL, 0, fmt, args);
  258. *strp = malloc(len + 1);
  259. if (*strp) ret = vsprintf(*strp, fmt, args);
  260. va_end(args);
  261. return ret;
  262. }
  263. #endif
  264. /*---------------------------------------------------------------------------*/
  265. static char *ltrim(char *s)
  266. {
  267. while(isspace((int) *s)) s++;
  268. return s;
  269. }
  270. /*----------------------------------------------------------------------------*/
  271. /* */
  272. /* HTTP management */
  273. /* */
  274. /*----------------------------------------------------------------------------*/
  275. /*----------------------------------------------------------------------------*/
  276. bool http_parse(int sock, char *method, key_data_t *rkd, char **body, int *len)
  277. {
  278. char line[256], *dp;
  279. unsigned j;
  280. int i, timeout = 100;
  281. rkd[0].key = NULL;
  282. if ((i = read_line(sock, line, sizeof(line), timeout)) <= 0) {
  283. if (i < 0) {
  284. LOG_ERROR("cannot read method", NULL);
  285. }
  286. return false;
  287. }
  288. if (!sscanf(line, "%s", method)) {
  289. LOG_ERROR("missing method", NULL);
  290. return false;
  291. }
  292. i = *len = 0;
  293. while (read_line(sock, line, sizeof(line), timeout) > 0) {
  294. LOG_SDEBUG("sock: %u, received %s", line);
  295. // line folding should be deprecated
  296. if (i && rkd[i].key && (line[0] == ' ' || line[0] == '\t')) {
  297. for(j = 0; j < strlen(line); j++) if (line[j] != ' ' && line[j] != '\t') break;
  298. rkd[i].data = realloc(rkd[i].data, strlen(rkd[i].data) + strlen(line + j) + 1);
  299. strcat(rkd[i].data, line + j);
  300. continue;
  301. }
  302. dp = strstr(line,":");
  303. if (!dp){
  304. LOG_ERROR("Request failed, bad header", NULL);
  305. kd_free(rkd);
  306. return false;
  307. }
  308. *dp = 0;
  309. rkd[i].key = strdup(line);
  310. rkd[i].data = strdup(ltrim(dp + 1));
  311. if (!strcasecmp(rkd[i].key, "Content-Length")) *len = atol(rkd[i].data);
  312. i++;
  313. rkd[i].key = NULL;
  314. }
  315. if (*len) {
  316. int size = 0;
  317. *body = malloc(*len + 1);
  318. while (*body && size < *len) {
  319. int bytes = recv(sock, *body + size, *len - size, 0);
  320. if (bytes <= 0) break;
  321. size += bytes;
  322. }
  323. (*body)[*len] = '\0';
  324. if (!*body || size != *len) {
  325. LOG_ERROR("content length receive error %d %d", *len, size);
  326. }
  327. }
  328. return true;
  329. }
  330. /*----------------------------------------------------------------------------*/
  331. static int read_line(int fd, char *line, int maxlen, int timeout)
  332. {
  333. int i,rval;
  334. int count=0;
  335. struct pollfd pfds;
  336. char ch;
  337. *line = 0;
  338. pfds.fd = fd;
  339. pfds.events = POLLIN;
  340. for(i = 0; i < maxlen; i++){
  341. if (poll(&pfds, 1, timeout)) rval=recv(fd, &ch, 1, 0);
  342. else return 0;
  343. if (rval == -1) {
  344. if (errno == EAGAIN) return 0;
  345. LOG_ERROR("fd: %d read error: %s", fd, strerror(errno));
  346. return -1;
  347. }
  348. if (rval == 0) {
  349. LOG_INFO("disconnected on the other end %u", fd);
  350. return 0;
  351. }
  352. if (ch == '\n') {
  353. *line=0;
  354. return count;
  355. }
  356. if (ch=='\r') continue;
  357. *line++=ch;
  358. count++;
  359. if (count >= maxlen-1) break;
  360. }
  361. *line = 0;
  362. return count;
  363. }
  364. /*----------------------------------------------------------------------------*/
  365. char *http_send(int sock, char *method, key_data_t *rkd)
  366. {
  367. unsigned sent, len;
  368. char *resp = kd_dump(rkd);
  369. char *data = malloc(strlen(method) + 2 + strlen(resp) + 2 + 1);
  370. len = sprintf(data, "%s\r\n%s\r\n", method, resp);
  371. NFREE(resp);
  372. sent = send(sock, data, len, 0);
  373. if (sent != len) {
  374. LOG_ERROR("HTTP send() error:%s %u (strlen=%u)", data, sent, len);
  375. NFREE(data);
  376. }
  377. return data;
  378. }
  379. /*----------------------------------------------------------------------------*/
  380. char *kd_lookup(key_data_t *kd, char *key)
  381. {
  382. int i = 0;
  383. while (kd && kd[i].key){
  384. if (!strcasecmp(kd[i].key, key)) return kd[i].data;
  385. i++;
  386. }
  387. return NULL;
  388. }
  389. /*----------------------------------------------------------------------------*/
  390. bool kd_add(key_data_t *kd, char *key, char *data)
  391. {
  392. int i = 0;
  393. while (kd && kd[i].key) i++;
  394. kd[i].key = strdup(key);
  395. kd[i].data = strdup(data);
  396. kd[i+1].key = NULL;
  397. return NULL;
  398. }
  399. /*----------------------------------------------------------------------------*/
  400. void kd_free(key_data_t *kd)
  401. {
  402. int i = 0;
  403. while (kd && kd[i].key){
  404. free(kd[i].key);
  405. if (kd[i].data) free(kd[i].data);
  406. i++;
  407. }
  408. kd[0].key = NULL;
  409. }
  410. /*----------------------------------------------------------------------------*/
  411. char *kd_dump(key_data_t *kd)
  412. {
  413. int i = 0;
  414. int pos = 0, size = 0;
  415. char *str = NULL;
  416. if (!kd || !kd[0].key) return strdup("\r\n");
  417. while (kd && kd[i].key) {
  418. char *buf;
  419. int len;
  420. len = asprintf(&buf, "%s: %s\r\n", kd[i].key, kd[i].data);
  421. while (pos + len >= size) {
  422. void *p = realloc(str, size + 1024);
  423. size += 1024;
  424. if (!p) {
  425. free(str);
  426. return NULL;
  427. }
  428. str = p;
  429. }
  430. memcpy(str + pos, buf, len);
  431. pos += len;
  432. free(buf);
  433. i++;
  434. }
  435. str[pos] = '\0';
  436. return str;
  437. }
  438. /*--------------------------------------------------------------------------*/
  439. void free_metadata(struct metadata_s *metadata)
  440. {
  441. NFREE(metadata->artist);
  442. NFREE(metadata->album);
  443. NFREE(metadata->title);
  444. NFREE(metadata->genre);
  445. NFREE(metadata->path);
  446. NFREE(metadata->artwork);
  447. NFREE(metadata->remote_title);
  448. }
  449. /*----------------------------------------------------------------------------*/
  450. int _fprintf(FILE *file, ...)
  451. {
  452. va_list args;
  453. char *fmt;
  454. int n;
  455. va_start(args, file);
  456. fmt = va_arg(args, char*);
  457. n = vfprintf(file, fmt, args);
  458. va_end(args);
  459. return n;
  460. }