util.c 13 KB

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