mirror of
https://github.com/sle118/squeezelite-esp32.git
synced 2025-12-12 22:47:15 +03:00
more ota work-ota cmd line implemented-not tested
This commit is contained in:
@@ -1,4 +1,4 @@
|
||||
/*
|
||||
/*
|
||||
* AirConnect: Chromecast & UPnP to AirPlay
|
||||
*
|
||||
* (c) Philippe 2016-2017, philippe_44@outlook.com
|
||||
@@ -16,11 +16,11 @@
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "platform.h"
|
||||
|
||||
#ifdef WIN32
|
||||
*/
|
||||
|
||||
#include "platform.h"
|
||||
|
||||
#ifdef WIN32
|
||||
#include <iphlpapi.h>
|
||||
#else
|
||||
/*
|
||||
@@ -34,63 +34,63 @@
|
||||
|
||||
#include <stdarg.h>
|
||||
|
||||
#include "pthread.h"
|
||||
#include "util.h"
|
||||
#include "log_util.h"
|
||||
|
||||
/*----------------------------------------------------------------------------*/
|
||||
/* globals */
|
||||
/*----------------------------------------------------------------------------*/
|
||||
|
||||
extern log_level util_loglevel;
|
||||
|
||||
/*----------------------------------------------------------------------------*/
|
||||
/* locals */
|
||||
/*----------------------------------------------------------------------------*/
|
||||
static log_level *loglevel = &util_loglevel;
|
||||
|
||||
static char *ltrim(char *s);
|
||||
static int read_line(int fd, char *line, int maxlen, int timeout);
|
||||
|
||||
/*----------------------------------------------------------------------------*/
|
||||
/* */
|
||||
/* NETWORKING utils */
|
||||
/* */
|
||||
/*----------------------------------------------------------------------------*/
|
||||
#include "pthread.h"
|
||||
#include "util.h"
|
||||
#include "log_util.h"
|
||||
|
||||
/*---------------------------------------------------------------------------*/
|
||||
#define MAX_INTERFACES 256
|
||||
#define DEFAULT_INTERFACE 1
|
||||
#if !defined(WIN32)
|
||||
#define INVALID_SOCKET (-1)
|
||||
#endif
|
||||
in_addr_t get_localhost(char **name)
|
||||
{
|
||||
#ifdef WIN32
|
||||
char buf[256];
|
||||
struct hostent *h = NULL;
|
||||
struct sockaddr_in LocalAddr;
|
||||
|
||||
memset(&LocalAddr, 0, sizeof(LocalAddr));
|
||||
|
||||
gethostname(buf, 256);
|
||||
h = gethostbyname(buf);
|
||||
|
||||
if (name) *name = strdup(buf);
|
||||
|
||||
if (h != NULL) {
|
||||
memcpy(&LocalAddr.sin_addr, h->h_addr_list[0], 4);
|
||||
return LocalAddr.sin_addr.s_addr;
|
||||
}
|
||||
else return INADDR_ANY;
|
||||
#else
|
||||
// missing platform here ...
|
||||
return INADDR_ANY;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
/*----------------------------------------------------------------------------*/
|
||||
/*----------------------------------------------------------------------------*/
|
||||
/* globals */
|
||||
/*----------------------------------------------------------------------------*/
|
||||
|
||||
extern log_level util_loglevel;
|
||||
|
||||
/*----------------------------------------------------------------------------*/
|
||||
/* locals */
|
||||
/*----------------------------------------------------------------------------*/
|
||||
static log_level *loglevel = &util_loglevel;
|
||||
|
||||
static char *ltrim(char *s);
|
||||
static int read_line(int fd, char *line, int maxlen, int timeout);
|
||||
|
||||
/*----------------------------------------------------------------------------*/
|
||||
/* */
|
||||
/* NETWORKING utils */
|
||||
/* */
|
||||
/*----------------------------------------------------------------------------*/
|
||||
|
||||
/*---------------------------------------------------------------------------*/
|
||||
#define MAX_INTERFACES 256
|
||||
#define DEFAULT_INTERFACE 1
|
||||
#if !defined(WIN32)
|
||||
#define INVALID_SOCKET (-1)
|
||||
#endif
|
||||
in_addr_t get_localhost(char **name)
|
||||
{
|
||||
#ifdef WIN32
|
||||
char buf[256];
|
||||
struct hostent *h = NULL;
|
||||
struct sockaddr_in LocalAddr;
|
||||
|
||||
memset(&LocalAddr, 0, sizeof(LocalAddr));
|
||||
|
||||
gethostname(buf, 256);
|
||||
h = gethostbyname(buf);
|
||||
|
||||
if (name) *name = strdup(buf);
|
||||
|
||||
if (h != NULL) {
|
||||
memcpy(&LocalAddr.sin_addr, h->h_addr_list[0], 4);
|
||||
return LocalAddr.sin_addr.s_addr;
|
||||
}
|
||||
else return INADDR_ANY;
|
||||
#else
|
||||
// missing platform here ...
|
||||
return INADDR_ANY;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
/*----------------------------------------------------------------------------*/
|
||||
#ifdef WIN32
|
||||
void winsock_init(void) {
|
||||
WSADATA wsaData;
|
||||
@@ -108,92 +108,92 @@ void winsock_close(void) {
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
/*----------------------------------------------------------------------------*/
|
||||
int shutdown_socket(int sd)
|
||||
{
|
||||
if (sd <= 0) return -1;
|
||||
|
||||
#ifdef WIN32
|
||||
shutdown(sd, SD_BOTH);
|
||||
#else
|
||||
shutdown(sd, SHUT_RDWR);
|
||||
#endif
|
||||
|
||||
LOG_DEBUG("closed socket %d", sd);
|
||||
|
||||
return closesocket(sd);
|
||||
}
|
||||
|
||||
|
||||
/*----------------------------------------------------------------------------*/
|
||||
int bind_socket(unsigned short *port, int mode)
|
||||
{
|
||||
int sock;
|
||||
socklen_t len = sizeof(struct sockaddr);
|
||||
struct sockaddr_in addr;
|
||||
|
||||
if ((sock = socket(AF_INET, mode, 0)) < 0) {
|
||||
LOG_ERROR("cannot create socket %d", sock);
|
||||
return sock;
|
||||
}
|
||||
|
||||
/* Populate socket address structure */
|
||||
memset(&addr, 0, sizeof(addr));
|
||||
addr.sin_family = AF_INET;
|
||||
addr.sin_addr.s_addr = htonl(INADDR_ANY);
|
||||
addr.sin_port = htons(*port);
|
||||
#ifdef SIN_LEN
|
||||
si.sin_len = sizeof(si);
|
||||
#endif
|
||||
|
||||
if (bind(sock, (struct sockaddr*) &addr, sizeof(addr)) < 0) {
|
||||
closesocket(sock);
|
||||
LOG_ERROR("cannot bind socket %d", sock);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (!*port) {
|
||||
getsockname(sock, (struct sockaddr *) &addr, &len);
|
||||
*port = ntohs(addr.sin_port);
|
||||
}
|
||||
|
||||
LOG_DEBUG("socket binding %d on port %d", sock, *port);
|
||||
|
||||
return sock;
|
||||
}
|
||||
|
||||
|
||||
/*----------------------------------------------------------------------------*/
|
||||
int conn_socket(unsigned short port)
|
||||
{
|
||||
struct sockaddr_in addr;
|
||||
int sd;
|
||||
|
||||
sd = socket(AF_INET, SOCK_STREAM, 0);
|
||||
|
||||
addr.sin_family = AF_INET;
|
||||
addr.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
|
||||
addr.sin_port = htons(port);
|
||||
|
||||
if (sd < 0 || connect(sd, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
|
||||
close(sd);
|
||||
return -1;
|
||||
}
|
||||
|
||||
LOG_DEBUG("created socket %d", sd);
|
||||
|
||||
return sd;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*----------------------------------------------------------------------------*/
|
||||
/* */
|
||||
/* SYSTEM utils */
|
||||
/* */
|
||||
/*----------------------------------------------------------------------------*/
|
||||
|
||||
int shutdown_socket(int sd)
|
||||
{
|
||||
if (sd <= 0) return -1;
|
||||
|
||||
#ifdef WIN32
|
||||
shutdown(sd, SD_BOTH);
|
||||
#else
|
||||
shutdown(sd, SHUT_RDWR);
|
||||
#endif
|
||||
|
||||
LOG_DEBUG("closed socket %d", sd);
|
||||
|
||||
return closesocket(sd);
|
||||
}
|
||||
|
||||
|
||||
/*----------------------------------------------------------------------------*/
|
||||
int bind_socket(unsigned short *port, int mode)
|
||||
{
|
||||
int sock;
|
||||
socklen_t len = sizeof(struct sockaddr);
|
||||
struct sockaddr_in addr;
|
||||
|
||||
if ((sock = socket(AF_INET, mode, 0)) < 0) {
|
||||
LOG_ERROR("cannot create socket %d", sock);
|
||||
return sock;
|
||||
}
|
||||
|
||||
/* Populate socket address structure */
|
||||
memset(&addr, 0, sizeof(addr));
|
||||
addr.sin_family = AF_INET;
|
||||
addr.sin_addr.s_addr = htonl(INADDR_ANY);
|
||||
addr.sin_port = htons(*port);
|
||||
#ifdef SIN_LEN
|
||||
si.sin_len = sizeof(si);
|
||||
#endif
|
||||
|
||||
if (bind(sock, (struct sockaddr*) &addr, sizeof(addr)) < 0) {
|
||||
closesocket(sock);
|
||||
LOG_ERROR("cannot bind socket %d", sock);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (!*port) {
|
||||
getsockname(sock, (struct sockaddr *) &addr, &len);
|
||||
*port = ntohs(addr.sin_port);
|
||||
}
|
||||
|
||||
LOG_DEBUG("socket binding %d on port %d", sock, *port);
|
||||
|
||||
return sock;
|
||||
}
|
||||
|
||||
|
||||
/*----------------------------------------------------------------------------*/
|
||||
int conn_socket(unsigned short port)
|
||||
{
|
||||
struct sockaddr_in addr;
|
||||
int sd;
|
||||
|
||||
sd = socket(AF_INET, SOCK_STREAM, 0);
|
||||
|
||||
addr.sin_family = AF_INET;
|
||||
addr.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
|
||||
addr.sin_port = htons(port);
|
||||
|
||||
if (sd < 0 || connect(sd, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
|
||||
close(sd);
|
||||
return -1;
|
||||
}
|
||||
|
||||
LOG_DEBUG("created socket %d", sd);
|
||||
|
||||
return sd;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*----------------------------------------------------------------------------*/
|
||||
/* */
|
||||
/* SYSTEM utils */
|
||||
/* */
|
||||
/*----------------------------------------------------------------------------*/
|
||||
|
||||
#ifdef WIN32
|
||||
/*----------------------------------------------------------------------------*/
|
||||
void *dlopen(const char *filename, int flag) {
|
||||
@@ -222,14 +222,14 @@ char *dlerror(void) {
|
||||
|
||||
|
||||
/*----------------------------------------------------------------------------*/
|
||||
/* */
|
||||
/* STDLIB extensions */
|
||||
/* */
|
||||
/*----------------------------------------------------------------------------*/
|
||||
|
||||
#ifdef WIN32
|
||||
/*---------------------------------------------------------------------------*/
|
||||
char *strcasestr(const char *haystack, const char *needle) {
|
||||
/* */
|
||||
/* STDLIB extensions */
|
||||
/* */
|
||||
/*----------------------------------------------------------------------------*/
|
||||
|
||||
#ifdef WIN32
|
||||
/*---------------------------------------------------------------------------*/
|
||||
char *strcasestr(const char *haystack, const char *needle) {
|
||||
size_t length_needle;
|
||||
size_t length_haystack;
|
||||
size_t i;
|
||||
@@ -242,7 +242,7 @@ char *strcasestr(const char *haystack, const char *needle) {
|
||||
|
||||
if (length_haystack < length_needle) return NULL;
|
||||
|
||||
length_haystack -= length_needle - 1;
|
||||
length_haystack -= length_needle - 1;
|
||||
|
||||
for (i = 0; i < length_haystack; i++)
|
||||
{
|
||||
@@ -264,92 +264,92 @@ char *strcasestr(const char *haystack, const char *needle) {
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*---------------------------------------------------------------------------*/
|
||||
char* strsep(char** stringp, const char* delim)
|
||||
{
|
||||
char* start = *stringp;
|
||||
char* p;
|
||||
|
||||
p = (start != NULL) ? strpbrk(start, delim) : NULL;
|
||||
|
||||
if (p == NULL) {
|
||||
*stringp = NULL;
|
||||
} else {
|
||||
*p = '\0';
|
||||
*stringp = p + 1;
|
||||
}
|
||||
|
||||
return start;
|
||||
}
|
||||
|
||||
/*---------------------------------------------------------------------------*/
|
||||
char *strndup(const char *s, size_t n) {
|
||||
char *p = malloc(n + 1);
|
||||
strncpy(p, s, n);
|
||||
p[n] = '\0';
|
||||
|
||||
return p;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
/*----------------------------------------------------------------------------*/
|
||||
char* strextract(char *s1, char *beg, char *end)
|
||||
{
|
||||
char *p1, *p2, *res;
|
||||
|
||||
p1 = strcasestr(s1, beg);
|
||||
if (!p1) return NULL;
|
||||
|
||||
p1 += strlen(beg);
|
||||
p2 = strcasestr(p1, end);
|
||||
if (!p2) return strdup(p1);
|
||||
|
||||
res = malloc(p2 - p1 + 1);
|
||||
memcpy(res, p1, p2 - p1);
|
||||
res[p2 - p1] = '\0';
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
#ifdef WIN32
|
||||
/*----------------------------------------------------------------------------*/
|
||||
int asprintf(char **strp, const char *fmt, ...)
|
||||
{
|
||||
va_list args, cp;
|
||||
int len, ret = 0;
|
||||
|
||||
va_start(args, fmt);
|
||||
len = vsnprintf(NULL, 0, fmt, args);
|
||||
*strp = malloc(len + 1);
|
||||
|
||||
if (*strp) ret = vsprintf(*strp, fmt, args);
|
||||
|
||||
va_end(args);
|
||||
|
||||
return ret;
|
||||
}
|
||||
#endif
|
||||
|
||||
/*---------------------------------------------------------------------------*/
|
||||
static char *ltrim(char *s)
|
||||
}
|
||||
|
||||
/*---------------------------------------------------------------------------*/
|
||||
char* strsep(char** stringp, const char* delim)
|
||||
{
|
||||
char* start = *stringp;
|
||||
char* p;
|
||||
|
||||
p = (start != NULL) ? strpbrk(start, delim) : NULL;
|
||||
|
||||
if (p == NULL) {
|
||||
*stringp = NULL;
|
||||
} else {
|
||||
*p = '\0';
|
||||
*stringp = p + 1;
|
||||
}
|
||||
|
||||
return start;
|
||||
}
|
||||
|
||||
/*---------------------------------------------------------------------------*/
|
||||
char *strndup(const char *s, size_t n) {
|
||||
char *p = malloc(n + 1);
|
||||
strncpy(p, s, n);
|
||||
p[n] = '\0';
|
||||
|
||||
return p;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
/*----------------------------------------------------------------------------*/
|
||||
char* strextract(char *s1, char *beg, char *end)
|
||||
{
|
||||
char *p1, *p2, *res;
|
||||
|
||||
p1 = strcasestr(s1, beg);
|
||||
if (!p1) return NULL;
|
||||
|
||||
p1 += strlen(beg);
|
||||
p2 = strcasestr(p1, end);
|
||||
if (!p2) return strdup(p1);
|
||||
|
||||
res = malloc(p2 - p1 + 1);
|
||||
memcpy(res, p1, p2 - p1);
|
||||
res[p2 - p1] = '\0';
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
#ifdef WIN32
|
||||
/*----------------------------------------------------------------------------*/
|
||||
int asprintf(char **strp, const char *fmt, ...)
|
||||
{
|
||||
va_list args, cp;
|
||||
int len, ret = 0;
|
||||
|
||||
va_start(args, fmt);
|
||||
len = vsnprintf(NULL, 0, fmt, args);
|
||||
*strp = malloc(len + 1);
|
||||
|
||||
if (*strp) ret = vsprintf(*strp, fmt, args);
|
||||
|
||||
va_end(args);
|
||||
|
||||
return ret;
|
||||
}
|
||||
#endif
|
||||
|
||||
/*---------------------------------------------------------------------------*/
|
||||
static char *ltrim(char *s)
|
||||
{
|
||||
while(isspace((int) *s)) s++;
|
||||
return s;
|
||||
}
|
||||
|
||||
/*----------------------------------------------------------------------------*/
|
||||
/* */
|
||||
/* HTTP management */
|
||||
/* */
|
||||
/*----------------------------------------------------------------------------*/
|
||||
|
||||
/*----------------------------------------------------------------------------*/
|
||||
bool http_parse(int sock, char *method, key_data_t *rkd, char **body, int *len)
|
||||
{
|
||||
/* */
|
||||
/* HTTP management */
|
||||
/* */
|
||||
/*----------------------------------------------------------------------------*/
|
||||
|
||||
/*----------------------------------------------------------------------------*/
|
||||
bool http_parse(int sock, char *method, key_data_t *rkd, char **body, int *len)
|
||||
{
|
||||
char line[256], *dp;
|
||||
unsigned j;
|
||||
int i, timeout = 100;
|
||||
@@ -357,14 +357,14 @@ bool http_parse(int sock, char *method, key_data_t *rkd, char **body, int *len)
|
||||
rkd[0].key = NULL;
|
||||
|
||||
if ((i = read_line(sock, line, sizeof(line), timeout)) <= 0) {
|
||||
if (i < 0) {
|
||||
LOG_ERROR("cannot read method", NULL);
|
||||
}
|
||||
if (i < 0) {
|
||||
LOG_ERROR("cannot read method", NULL);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!sscanf(line, "%s", method)) {
|
||||
LOG_ERROR("missing method", NULL);
|
||||
LOG_ERROR("missing method", NULL);
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -377,7 +377,7 @@ bool http_parse(int sock, char *method, key_data_t *rkd, char **body, int *len)
|
||||
// line folding should be deprecated
|
||||
if (i && rkd[i].key && (line[0] == ' ' || line[0] == '\t')) {
|
||||
for(j = 0; j < strlen(line); j++) if (line[j] != ' ' && line[j] != '\t') break;
|
||||
rkd[i].data = realloc(rkd[i].data, strlen(rkd[i].data) + strlen(line + j) + 1);
|
||||
rkd[i].data = realloc(rkd[i].data, strlen(rkd[i].data) + strlen(line + j) + 1);
|
||||
strcat(rkd[i].data, line + j);
|
||||
continue;
|
||||
}
|
||||
@@ -403,7 +403,7 @@ bool http_parse(int sock, char *method, key_data_t *rkd, char **body, int *len)
|
||||
if (*len) {
|
||||
int size = 0;
|
||||
|
||||
*body = malloc(*len + 1);
|
||||
*body = malloc(*len + 1);
|
||||
while (*body && size < *len) {
|
||||
int bytes = recv(sock, *body + size, *len - size, 0);
|
||||
if (bytes <= 0) break;
|
||||
@@ -467,23 +467,23 @@ static int read_line(int fd, char *line, int maxlen, int timeout)
|
||||
|
||||
/*----------------------------------------------------------------------------*/
|
||||
char *http_send(int sock, char *method, key_data_t *rkd)
|
||||
{
|
||||
unsigned sent, len;
|
||||
char *resp = kd_dump(rkd);
|
||||
char *data = malloc(strlen(method) + 2 + strlen(resp) + 2 + 1);
|
||||
|
||||
len = sprintf(data, "%s\r\n%s\r\n", method, resp);
|
||||
NFREE(resp);
|
||||
|
||||
sent = send(sock, data, len, 0);
|
||||
|
||||
if (sent != len) {
|
||||
LOG_ERROR("HTTP send() error:%s %u (strlen=%u)", data, sent, len);
|
||||
NFREE(data);
|
||||
}
|
||||
|
||||
return data;
|
||||
}
|
||||
{
|
||||
unsigned sent, len;
|
||||
char *resp = kd_dump(rkd);
|
||||
char *data = malloc(strlen(method) + 2 + strlen(resp) + 2 + 1);
|
||||
|
||||
len = sprintf(data, "%s\r\n%s\r\n", method, resp);
|
||||
NFREE(resp);
|
||||
|
||||
sent = send(sock, data, len, 0);
|
||||
|
||||
if (sent != len) {
|
||||
LOG_ERROR("HTTP send() error:%s %u (strlen=%u)", data, sent, len);
|
||||
NFREE(data);
|
||||
}
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
|
||||
/*----------------------------------------------------------------------------*/
|
||||
@@ -534,7 +534,7 @@ char *kd_dump(key_data_t *kd)
|
||||
char *str = NULL;
|
||||
|
||||
if (!kd || !kd[0].key) return strdup("\r\n");
|
||||
|
||||
|
||||
while (kd && kd[i].key) {
|
||||
char *buf;
|
||||
int len;
|
||||
@@ -545,8 +545,8 @@ char *kd_dump(key_data_t *kd)
|
||||
void *p = realloc(str, size + 1024);
|
||||
size += 1024;
|
||||
if (!p) {
|
||||
free(str);
|
||||
return NULL;
|
||||
free(str);
|
||||
return NULL;
|
||||
}
|
||||
str = p;
|
||||
}
|
||||
@@ -574,28 +574,28 @@ void free_metadata(struct metadata_s *metadata)
|
||||
NFREE(metadata->artwork);
|
||||
NFREE(metadata->remote_title);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*----------------------------------------------------------------------------*/
|
||||
|
||||
|
||||
int _fprintf(FILE *file, ...)
|
||||
{
|
||||
va_list args;
|
||||
/*----------------------------------------------------------------------------*/
|
||||
int n;
|
||||
|
||||
|
||||
int _fprintf(FILE *file, ...)
|
||||
{
|
||||
va_list args;
|
||||
char *fmt;
|
||||
int n;
|
||||
|
||||
va_start(args, file);
|
||||
fmt = va_arg(args, char*);
|
||||
|
||||
n = vfprintf(file, fmt, args);
|
||||
va_end(args);
|
||||
return n;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
fmt = va_arg(args, char*);
|
||||
|
||||
n = vfprintf(file, fmt, args);
|
||||
va_end(args);
|
||||
return n;
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user