mirror of
https://github.com/SuperBFG7/ympd
synced 2024-06-27 23:23:15 +00:00
Fix: cleanup mpd_client for thread safety
Fix: remove all possible global states
This commit is contained in:
parent
a7d07fbcc9
commit
3c214baa16
40
src/global.c
40
src/global.c
|
@ -27,35 +27,51 @@
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
|
#include <dirent.h>
|
||||||
|
|
||||||
#include "tiny_queue.h"
|
#include "tiny_queue.h"
|
||||||
|
#include "list.h"
|
||||||
#include "global.h"
|
#include "global.h"
|
||||||
|
|
||||||
|
bool testdir(char *name, char *dirname) {
|
||||||
|
DIR* dir = opendir(dirname);
|
||||||
|
if (dir) {
|
||||||
|
closedir(dir);
|
||||||
|
LOG_INFO() printf("%s: \"%s\"\n", name, dirname);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
printf("%s: \"%s\" don't exists\n", name, dirname);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
int randrange(int n) {
|
int randrange(int n) {
|
||||||
return rand() / (RAND_MAX / (n + 1) + 1);
|
return rand() / (RAND_MAX / (n + 1) + 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
void sanitize_string(const char *data) {
|
|
||||||
static char ok_chars[] = "abcdefghijklmnopqrstuvwxyz"
|
|
||||||
"ABCDEFGHIJKLMNOPQRSTUVWXYZ"
|
|
||||||
"1234567890_-. ";
|
|
||||||
char *cp = data;
|
|
||||||
const char *end = data + strlen(data);
|
|
||||||
for (cp += strspn(cp, ok_chars); cp != end; cp += strspn(cp, ok_chars))
|
|
||||||
*cp = '_';
|
|
||||||
}
|
|
||||||
|
|
||||||
bool validate_string(const char *data) {
|
bool validate_string(const char *data) {
|
||||||
static char ok_chars[] = "abcdefghijklmnopqrstuvwxyz"
|
static char ok_chars[] = "abcdefghijklmnopqrstuvwxyz"
|
||||||
"ABCDEFGHIJKLMNOPQRSTUVWXYZ"
|
"ABCDEFGHIJKLMNOPQRSTUVWXYZ"
|
||||||
"1234567890_-. ";
|
"1234567890_-. ";
|
||||||
const char *cp = data;
|
const char *cp = data;
|
||||||
const char *end = data + strlen(data);
|
const char *end = data + strlen(data);
|
||||||
for (cp += strspn(cp, ok_chars); cp != end; cp += strspn(cp, ok_chars))
|
for (cp += strspn(cp, ok_chars); cp != end; cp += strspn(cp, ok_chars)) {
|
||||||
|
printf("ERROR: Invalid character in string\n");
|
||||||
return false;
|
return false;
|
||||||
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int replacechar(char *str, const char orig, const char rep) {
|
||||||
|
char *ix = str;
|
||||||
|
int n = 0;
|
||||||
|
while ((ix = strchr(ix, orig)) != NULL) {
|
||||||
|
*ix++ = rep;
|
||||||
|
n++;
|
||||||
|
}
|
||||||
|
return n;
|
||||||
|
}
|
||||||
|
|
||||||
int copy_string(char * const dest, char const * const src, size_t const dst_len, size_t const src_len) {
|
int copy_string(char * const dest, char const * const src, size_t const dst_len, size_t const src_len) {
|
||||||
if (dst_len == 0 || src_len == 0)
|
if (dst_len == 0 || src_len == 0)
|
||||||
|
@ -66,7 +82,7 @@ int copy_string(char * const dest, char const * const src, size_t const dst_len,
|
||||||
return max;
|
return max;
|
||||||
}
|
}
|
||||||
|
|
||||||
enum mypd_cmd_ids get_cmd_id(const char *cmd) {
|
enum mympd_cmd_ids get_cmd_id(const char *cmd) {
|
||||||
const char * mympd_cmd_strs[] = { MYMPD_CMDS(GEN_STR) };
|
const char * mympd_cmd_strs[] = { MYMPD_CMDS(GEN_STR) };
|
||||||
|
|
||||||
for (unsigned i = 0; i < sizeof(mympd_cmd_strs) / sizeof(mympd_cmd_strs[0]); i++)
|
for (unsigned i = 0; i < sizeof(mympd_cmd_strs) / sizeof(mympd_cmd_strs[0]); i++)
|
||||||
|
|
|
@ -45,13 +45,9 @@
|
||||||
|
|
||||||
//central logging definition
|
//central logging definition
|
||||||
#cmakedefine DEBUG
|
#cmakedefine DEBUG
|
||||||
#define LOG_INFO() if (config.loglevel >= 1)
|
#define LOG_INFO() if (loglevel >= 1)
|
||||||
#define LOG_VERBOSE() if (config.loglevel >= 2)
|
#define LOG_VERBOSE() if (loglevel >= 2)
|
||||||
#define LOG_DEBUG() if (config.loglevel == 3)
|
#define LOG_DEBUG() if (loglevel == 3)
|
||||||
|
|
||||||
#define LOG_INFO2() if (config->loglevel >= 1)
|
|
||||||
#define LOG_VERBOSE2() if (config->loglevel >= 2)
|
|
||||||
#define LOG_DEBUG2() if (config->loglevel == 3)
|
|
||||||
|
|
||||||
//check and return buffer size
|
//check and return buffer size
|
||||||
#define CHECK_RETURN_LEN() do { \
|
#define CHECK_RETURN_LEN() do { \
|
||||||
|
@ -122,7 +118,14 @@
|
||||||
#define GEN_ENUM(X) X,
|
#define GEN_ENUM(X) X,
|
||||||
#define GEN_STR(X) #X,
|
#define GEN_STR(X) #X,
|
||||||
|
|
||||||
enum mypd_cmd_ids {
|
//Global variables
|
||||||
|
|
||||||
|
int loglevel;
|
||||||
|
|
||||||
|
//signal handler
|
||||||
|
sig_atomic_t s_signal_received;
|
||||||
|
|
||||||
|
enum mympd_cmd_ids {
|
||||||
MYMPD_CMDS(GEN_ENUM)
|
MYMPD_CMDS(GEN_ENUM)
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -131,25 +134,21 @@ tiny_queue_t *web_server_queue;
|
||||||
tiny_queue_t *mpd_client_queue;
|
tiny_queue_t *mpd_client_queue;
|
||||||
tiny_queue_t *mympd_api_queue;
|
tiny_queue_t *mympd_api_queue;
|
||||||
|
|
||||||
struct work_request_t {
|
typedef struct t_work_request {
|
||||||
long conn_id; // needed to identify the connection where to send the reply
|
long conn_id; // needed to identify the connection where to send the reply
|
||||||
char data[1000];
|
char data[1000];
|
||||||
int length;
|
int length;
|
||||||
enum mypd_cmd_ids cmd_id;
|
enum mympd_cmd_ids cmd_id;
|
||||||
} work_request_t;
|
} t_work_request;
|
||||||
|
|
||||||
struct work_result_t {
|
typedef struct t_work_result {
|
||||||
long conn_id; // needed to identify the connection where to send the reply
|
long conn_id; // needed to identify the connection where to send the reply
|
||||||
char data[MAX_SIZE];
|
char data[MAX_SIZE];
|
||||||
int length;
|
int length;
|
||||||
} work_result_t;
|
} t_work_result;
|
||||||
|
|
||||||
|
|
||||||
//signal handler
|
|
||||||
sig_atomic_t s_signal_received;
|
|
||||||
|
|
||||||
//myMPD configuration
|
//myMPD configuration
|
||||||
typedef struct {
|
typedef struct t_config {
|
||||||
long mpdport;
|
long mpdport;
|
||||||
const char *mpdhost;
|
const char *mpdhost;
|
||||||
const char *mpdpass;
|
const char *mpdpass;
|
||||||
|
@ -177,15 +176,14 @@ typedef struct {
|
||||||
const char *streamurl;
|
const char *streamurl;
|
||||||
unsigned long last_played_count;
|
unsigned long last_played_count;
|
||||||
long loglevel;
|
long loglevel;
|
||||||
void *syscmd_list;
|
struct list syscmd_list;
|
||||||
} t_config;
|
} t_config;
|
||||||
|
|
||||||
t_config config;
|
|
||||||
|
|
||||||
//global functions
|
//global functions
|
||||||
|
bool testdir(char *name, char *dirname);
|
||||||
int randrange(int n);
|
int randrange(int n);
|
||||||
void sanitize_string(const char *data);
|
|
||||||
bool validate_string(const char *data);
|
bool validate_string(const char *data);
|
||||||
int copy_string(char * const dest, char const * const src, size_t const dst_len, size_t const src_len);
|
int copy_string(char * const dest, char const * const src, size_t const dst_len, size_t const src_len);
|
||||||
enum mypd_cmd_ids get_cmd_id(const char *cmd);
|
int replacechar(char *str, const char orig, const char rep);
|
||||||
|
enum mympd_cmd_ids get_cmd_id(const char *cmd);
|
||||||
#endif
|
#endif
|
||||||
|
|
210
src/main.c
210
src/main.c
|
@ -39,17 +39,18 @@
|
||||||
#include "tiny_queue.h"
|
#include "tiny_queue.h"
|
||||||
#include "global.h"
|
#include "global.h"
|
||||||
#include "mpd_client.h"
|
#include "mpd_client.h"
|
||||||
|
#include "../dist/src/mongoose/mongoose.h"
|
||||||
#include "web_server.h"
|
#include "web_server.h"
|
||||||
#include "mympd_api.h"
|
#include "mympd_api.h"
|
||||||
#include "../dist/src/inih/ini.h"
|
#include "../dist/src/inih/ini.h"
|
||||||
#include "../dist/src/mongoose/mongoose.h"
|
|
||||||
|
|
||||||
static void signal_handler(int sig_num) {
|
static void signal_handler(int sig_num) {
|
||||||
signal(sig_num, signal_handler); // Reinstantiate signal handler
|
signal(sig_num, signal_handler); // Reinstantiate signal handler
|
||||||
s_signal_received = sig_num;
|
s_signal_received = sig_num;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int inihandler(void* user, const char* section, const char* name, const char* value) {
|
static int inihandler(void *user, const char *section, const char *name, const char* value) {
|
||||||
t_config* p_config = (t_config*)user;
|
t_config* p_config = (t_config*)user;
|
||||||
char *crap;
|
char *crap;
|
||||||
|
|
||||||
|
@ -141,178 +142,32 @@ static int inihandler(void* user, const char* section, const char* name, const c
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
void read_syscmds(void *arg_config) {
|
void read_syscmds(t_config *config) {
|
||||||
DIR *dir;
|
DIR *dir;
|
||||||
struct dirent *ent;
|
struct dirent *ent;
|
||||||
char dirname[400];
|
char dirname[400];
|
||||||
char *cmd;
|
char *cmd;
|
||||||
long order;
|
long order;
|
||||||
t_config *config = (t_config *) arg_config;
|
|
||||||
|
|
||||||
if (config->syscmds == true) {
|
if (config->syscmds == true) {
|
||||||
snprintf(dirname, 400, "%s/syscmds", config->etcdir);
|
snprintf(dirname, 400, "%s/syscmds", config->etcdir);
|
||||||
LOG_INFO2() printf("Reading syscmds: %s\n", dirname);
|
printf("Reading syscmds: %s\n", dirname);
|
||||||
if ((dir = opendir (dirname)) != NULL) {
|
if ((dir = opendir (dirname)) != NULL) {
|
||||||
while ((ent = readdir(dir)) != NULL) {
|
while ((ent = readdir(dir)) != NULL) {
|
||||||
if (strncmp(ent->d_name, ".", 1) == 0)
|
if (strncmp(ent->d_name, ".", 1) == 0)
|
||||||
continue;
|
continue;
|
||||||
order = strtol(ent->d_name, &cmd, 10);
|
order = strtol(ent->d_name, &cmd, 10);
|
||||||
if (strcmp(cmd, "") != 0)
|
if (strcmp(cmd, "") != 0)
|
||||||
list_push(config->syscmd_list, strdup(cmd), order);
|
list_push(&config->syscmd_list, strdup(cmd), order);
|
||||||
}
|
}
|
||||||
closedir(dir);
|
closedir(dir);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
LOG_INFO2() printf("Syscmds are disabled\n");
|
printf("Syscmds are disabled\n");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void read_statefiles() {
|
|
||||||
char *crap;
|
|
||||||
char value[400];
|
|
||||||
|
|
||||||
LOG_INFO() printf("Reading states\n");
|
|
||||||
if (mpd_client_state_get("notificationWeb", value)) {
|
|
||||||
if (strcmp(value, "true") == 0)
|
|
||||||
mympd_state.notificationWeb = true;
|
|
||||||
else
|
|
||||||
mympd_state.notificationWeb = false;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
mympd_state.notificationWeb = false;
|
|
||||||
mpd_client_state_set("notificationWeb", "false");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (mpd_client_state_get("notificationPage", value)) {
|
|
||||||
if (strcmp(value, "true") == 0)
|
|
||||||
mympd_state.notificationPage = true;
|
|
||||||
else
|
|
||||||
mympd_state.notificationPage = false;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
mympd_state.notificationPage = true;
|
|
||||||
mpd_client_state_set("notificationPage", "true");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (mpd_client_state_get("jukeboxMode", value))
|
|
||||||
mympd_state.jukeboxMode = strtol(value, &crap, 10);
|
|
||||||
else {
|
|
||||||
mympd_state.jukeboxMode = 0;
|
|
||||||
mpd_client_state_set("jukeboxMode", "0");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (mpd_client_state_get("jukeboxPlaylist", value))
|
|
||||||
mympd_state.jukeboxPlaylist = strdup(value);
|
|
||||||
else {
|
|
||||||
mympd_state.jukeboxPlaylist = strdup("Database");
|
|
||||||
mpd_client_state_set("jukeboxPlaylist", "Database");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (mpd_client_state_get("jukeboxQueueLength", value))
|
|
||||||
mympd_state.jukeboxQueueLength = strtol(value, &crap, 10);
|
|
||||||
else {
|
|
||||||
mympd_state.jukeboxQueueLength = 1;
|
|
||||||
mpd_client_state_set("jukeboxQueueLength", "1");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (mpd_client_state_get("colsQueueCurrent", value))
|
|
||||||
mympd_state.colsQueueCurrent = strdup(value);
|
|
||||||
else {
|
|
||||||
mympd_state.colsQueueCurrent = strdup("[\"Pos\",\"Title\",\"Artist\",\"Album\",\"Duration\"]");
|
|
||||||
mpd_client_state_set("colsQueueCurrent", mympd_state.colsQueueCurrent);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (mpd_client_state_get("colsSearch", value))
|
|
||||||
mympd_state.colsSearch = strdup(value);
|
|
||||||
else {
|
|
||||||
mympd_state.colsSearch = strdup("[\"Title\",\"Artist\",\"Album\",\"Duration\"]");
|
|
||||||
mpd_client_state_set("colsSearch", mympd_state.colsSearch);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (mpd_client_state_get("colsBrowseDatabase", value))
|
|
||||||
mympd_state.colsBrowseDatabase = strdup(value);
|
|
||||||
else {
|
|
||||||
mympd_state.colsBrowseDatabase = strdup("[\"Track\",\"Title\",\"Duration\"]");
|
|
||||||
mpd_client_state_set("colsBrowseDatabase", mympd_state.colsBrowseDatabase);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (mpd_client_state_get("colsBrowsePlaylistsDetail", value))
|
|
||||||
mympd_state.colsBrowsePlaylistsDetail = strdup(value);
|
|
||||||
else {
|
|
||||||
mympd_state.colsBrowsePlaylistsDetail = strdup("[\"Pos\",\"Title\",\"Artist\",\"Album\",\"Duration\"]");
|
|
||||||
mpd_client_state_set("colsBrowsePlaylistsDetail", mympd_state.colsBrowsePlaylistsDetail);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (mpd_client_state_get("colsBrowseFilesystem", value))
|
|
||||||
mympd_state.colsBrowseFilesystem = strdup(value);
|
|
||||||
else {
|
|
||||||
mympd_state.colsBrowseFilesystem = strdup("[\"Type\",\"Title\",\"Artist\",\"Album\",\"Duration\"]");
|
|
||||||
mpd_client_state_set("colsBrowseFilesystem", mympd_state.colsBrowseFilesystem);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (mpd_client_state_get("colsPlayback", value))
|
|
||||||
mympd_state.colsPlayback = strdup(value);
|
|
||||||
else {
|
|
||||||
mympd_state.colsPlayback = strdup("[\"Artist\",\"Album\",\"Genre\"]");
|
|
||||||
mpd_client_state_set("colsPlayback", mympd_state.colsPlayback);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (mpd_client_state_get("colsQueueLastPlayed", value))
|
|
||||||
mympd_state.colsQueueLastPlayed = strdup(value);
|
|
||||||
else {
|
|
||||||
mympd_state.colsQueueLastPlayed = strdup("[\"Pos\",\"Title\",\"Artist\",\"Album\",\"LastPlayed\"]");
|
|
||||||
mpd_client_state_set("colsQueueLastPlayed", mympd_state.colsQueueLastPlayed);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
int read_last_played() {
|
|
||||||
char cfgfile[400];
|
|
||||||
char *line;
|
|
||||||
char *data;
|
|
||||||
char *crap;
|
|
||||||
size_t n = 0;
|
|
||||||
ssize_t read;
|
|
||||||
long value;
|
|
||||||
|
|
||||||
snprintf(cfgfile, 400, "%s/state/last_played", config.varlibdir);
|
|
||||||
FILE *fp = fopen(cfgfile, "r");
|
|
||||||
if (fp == NULL) {
|
|
||||||
printf("Error opening %s\n", cfgfile);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
while ((read = getline(&line, &n, fp)) > 0) {
|
|
||||||
value = strtol(line, &data, 10);
|
|
||||||
if (strlen(data) > 2)
|
|
||||||
data = data + 2;
|
|
||||||
strtok_r(data, "\n", &crap);
|
|
||||||
list_push(&last_played, data, value);
|
|
||||||
}
|
|
||||||
fclose(fp);
|
|
||||||
return last_played.length;;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool testdir(char *name, char *dirname) {
|
|
||||||
DIR* dir = opendir(dirname);
|
|
||||||
if (dir) {
|
|
||||||
closedir(dir);
|
|
||||||
LOG_INFO() printf("%s: \"%s\"\n", name, dirname);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
printf("%s: \"%s\" don't exists\n", name, dirname);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void *mpd_client_loop() {
|
|
||||||
while (s_signal_received == 0) {
|
|
||||||
mpd_client_idle(100);
|
|
||||||
}
|
|
||||||
mpd_client_disconnect();
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
int main(int argc, char **argv) {
|
int main(int argc, char **argv) {
|
||||||
s_signal_received = 0;
|
s_signal_received = 0;
|
||||||
char testdirname[400];
|
char testdirname[400];
|
||||||
|
@ -322,7 +177,8 @@ int main(int argc, char **argv) {
|
||||||
|
|
||||||
srand((unsigned int)time(NULL));
|
srand((unsigned int)time(NULL));
|
||||||
|
|
||||||
//defaults
|
//mympd config defaults
|
||||||
|
t_config config;
|
||||||
config.mpdhost = "127.0.0.1";
|
config.mpdhost = "127.0.0.1";
|
||||||
config.mpdport = 6600;
|
config.mpdport = 6600;
|
||||||
config.mpdpass = NULL;
|
config.mpdpass = NULL;
|
||||||
|
@ -353,16 +209,10 @@ int main(int argc, char **argv) {
|
||||||
config.localplayer = true;
|
config.localplayer = true;
|
||||||
config.loglevel = 1;
|
config.loglevel = 1;
|
||||||
|
|
||||||
mpd.timeout = 3000;
|
|
||||||
mpd.last_update_sticker_song_id = -1;
|
|
||||||
mpd.last_song_id = -1;
|
|
||||||
mpd.last_last_played_id = -1;
|
|
||||||
mpd.feat_library = false;
|
|
||||||
|
|
||||||
if (argc == 2) {
|
if (argc == 2) {
|
||||||
LOG_INFO() printf("Starting myMPD %s\n", MYMPD_VERSION);
|
printf("Starting myMPD %s\n", MYMPD_VERSION);
|
||||||
LOG_INFO() printf("Libmpdclient %i.%i.%i\n", LIBMPDCLIENT_MAJOR_VERSION, LIBMPDCLIENT_MINOR_VERSION, LIBMPDCLIENT_PATCH_VERSION);
|
printf("Libmpdclient %i.%i.%i\n", LIBMPDCLIENT_MAJOR_VERSION, LIBMPDCLIENT_MINOR_VERSION, LIBMPDCLIENT_PATCH_VERSION);
|
||||||
LOG_INFO() printf("Parsing config file: %s\n", argv[1]);
|
printf("Parsing config file: %s\n", argv[1]);
|
||||||
if (ini_parse(argv[1], inihandler, &config) < 0) {
|
if (ini_parse(argv[1], inihandler, &config) < 0) {
|
||||||
printf("Can't load config file \"%s\"\n", argv[1]);
|
printf("Can't load config file \"%s\"\n", argv[1]);
|
||||||
return EXIT_FAILURE;
|
return EXIT_FAILURE;
|
||||||
|
@ -383,6 +233,7 @@ int main(int argc, char **argv) {
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
printf("Debug flag enabled, setting loglevel to debug\n");
|
printf("Debug flag enabled, setting loglevel to debug\n");
|
||||||
config.loglevel = 3;
|
config.loglevel = 3;
|
||||||
|
loglevel = config.loglevel;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
signal(SIGTERM, signal_handler);
|
signal(SIGTERM, signal_handler);
|
||||||
|
@ -398,7 +249,7 @@ int main(int argc, char **argv) {
|
||||||
|
|
||||||
//drop privileges
|
//drop privileges
|
||||||
if (config.user != NULL) {
|
if (config.user != NULL) {
|
||||||
LOG_INFO() printf("Droping privileges to %s\n", config.user);
|
printf("Droping privileges to %s\n", config.user);
|
||||||
struct passwd *pw;
|
struct passwd *pw;
|
||||||
if ((pw = getpwnam(config.user)) == NULL) {
|
if ((pw = getpwnam(config.user)) == NULL) {
|
||||||
printf("getpwnam() failed, unknown user\n");
|
printf("getpwnam() failed, unknown user\n");
|
||||||
|
@ -430,12 +281,8 @@ int main(int argc, char **argv) {
|
||||||
return EXIT_FAILURE;
|
return EXIT_FAILURE;
|
||||||
|
|
||||||
snprintf(testdirname, 400, "%s/library", DOC_ROOT);
|
snprintf(testdirname, 400, "%s/library", DOC_ROOT);
|
||||||
if (testdir("Link to mpd music_directory", testdirname)) {
|
if (!testdir("Link to mpd music_directory", testdirname)) {
|
||||||
LOG_INFO() printf("Enabling featLibrary support\n");
|
printf("Disabling coverimage support\n");
|
||||||
mpd.feat_library = true;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
LOG_INFO() printf("Disabling coverimage support\n");
|
|
||||||
config.coverimage = false;
|
config.coverimage = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -451,41 +298,26 @@ int main(int argc, char **argv) {
|
||||||
if (!testdir("State dir", testdirname))
|
if (!testdir("State dir", testdirname))
|
||||||
return EXIT_FAILURE;
|
return EXIT_FAILURE;
|
||||||
|
|
||||||
//read myMPD states under config.varlibdir
|
|
||||||
read_statefiles();
|
|
||||||
|
|
||||||
//read system command files
|
//read system command files
|
||||||
config.syscmd_list = malloc(sizeof(struct list));
|
list_init(&config.syscmd_list);
|
||||||
list_init(config.syscmd_list);
|
|
||||||
read_syscmds(&config);
|
read_syscmds(&config);
|
||||||
list_sort_by_value(config.syscmd_list, true);
|
list_sort_by_value(&config.syscmd_list, true);
|
||||||
|
|
||||||
//init lists for tag handling
|
|
||||||
list_init(&mpd_tags);
|
|
||||||
list_init(&mympd_tags);
|
|
||||||
|
|
||||||
//read last played songs history file
|
|
||||||
list_init(&last_played);
|
|
||||||
LOG_INFO() printf("Reading last played songs: %d\n", read_last_played());
|
|
||||||
|
|
||||||
//Create working threads
|
//Create working threads
|
||||||
pthread_t mpd_client_thread, web_server_thread, mympd_api_thread;
|
pthread_t mpd_client_thread, web_server_thread, mympd_api_thread;
|
||||||
//mpd connection
|
//mpd connection
|
||||||
pthread_create(&mpd_client_thread, NULL, mpd_client_loop, NULL);
|
pthread_create(&mpd_client_thread, NULL, mpd_client_loop, &config);
|
||||||
//webserver
|
//webserver
|
||||||
pthread_create(&web_server_thread, NULL, web_server_loop, &mgr);
|
pthread_create(&web_server_thread, NULL, web_server_loop, &mgr);
|
||||||
//mympd api
|
//mympd api
|
||||||
pthread_create(&mympd_api_thread, NULL, mympd_api_loop, &config);
|
pthread_create(&mympd_api_thread, NULL, mympd_api_loop, &config);
|
||||||
|
|
||||||
//Do nothing...
|
//Outsourced all work to separate threads, do nothing...
|
||||||
|
|
||||||
|
|
||||||
//clean up
|
//clean up
|
||||||
pthread_join(mpd_client_thread, NULL);
|
pthread_join(mpd_client_thread, NULL);
|
||||||
pthread_join(web_server_thread, NULL);
|
pthread_join(web_server_thread, NULL);
|
||||||
list_free(&mpd_tags);
|
list_free(&config.syscmd_list);
|
||||||
list_free(&mympd_tags);
|
|
||||||
list_free(config.syscmd_list);
|
|
||||||
tiny_queue_free(web_server_queue);
|
tiny_queue_free(web_server_queue);
|
||||||
tiny_queue_free(mpd_client_queue);
|
tiny_queue_free(mpd_client_queue);
|
||||||
tiny_queue_free(mympd_api_queue);
|
tiny_queue_free(mympd_api_queue);
|
||||||
|
|
1760
src/mpd_client.c
1760
src/mpd_client.c
File diff suppressed because it is too large
Load Diff
140
src/mpd_client.h
140
src/mpd_client.h
|
@ -24,144 +24,6 @@
|
||||||
|
|
||||||
#ifndef __MPD_CLIENT_H__
|
#ifndef __MPD_CLIENT_H__
|
||||||
#define __MPD_CLIENT_H__
|
#define __MPD_CLIENT_H__
|
||||||
|
void *mpd_client_loop(void *arg_config);
|
||||||
|
|
||||||
#define RETURN_ERROR_AND_RECOVER(X) do { \
|
|
||||||
printf("MPD %s: %s\n", X, mpd_connection_get_error_message(mpd.conn)); \
|
|
||||||
len = json_printf(&out, "{type: error, data: %Q}", mpd_connection_get_error_message(mpd.conn)); \
|
|
||||||
if (!mpd_connection_clear_error(mpd.conn)) \
|
|
||||||
mpd.conn_state = MPD_FAILURE; \
|
|
||||||
return len; \
|
|
||||||
} while (0)
|
|
||||||
|
|
||||||
#define LOG_ERROR_AND_RECOVER(X) do { \
|
|
||||||
printf("MPD %s: %s\n", X, mpd_connection_get_error_message(mpd.conn)); \
|
|
||||||
if (!mpd_connection_clear_error(mpd.conn)) \
|
|
||||||
mpd.conn_state = MPD_FAILURE; \
|
|
||||||
} while (0)
|
|
||||||
|
|
||||||
#define PUT_SONG_TAGS() do { \
|
|
||||||
struct node *current = mympd_tags.list; \
|
|
||||||
int tagnr = 0; \
|
|
||||||
while (current != NULL) { \
|
|
||||||
if (tagnr ++) \
|
|
||||||
len += json_printf(&out, ","); \
|
|
||||||
len += json_printf(&out, "%Q: %Q", current->data, mpd_client_get_tag(song, mpd_tag_name_parse(current->data))); \
|
|
||||||
current = current->next; \
|
|
||||||
} \
|
|
||||||
len += json_printf(&out, ", Duration: %d, uri: %Q", mpd_song_get_duration(song), mpd_song_get_uri(song)); \
|
|
||||||
} while (0)
|
|
||||||
|
|
||||||
#define PUT_MIN_SONG_TAGS() do { \
|
|
||||||
len += json_printf(&out, "Title: %Q, Duration: %d, uri: %Q", mpd_client_get_tag(song, MPD_TAG_TITLE), mpd_song_get_duration(song), mpd_song_get_uri(song)); \
|
|
||||||
} while (0)
|
|
||||||
|
|
||||||
|
|
||||||
enum mpd_conn_states {
|
|
||||||
MPD_DISCONNECTED,
|
|
||||||
MPD_FAILURE,
|
|
||||||
MPD_CONNECTED,
|
|
||||||
MPD_RECONNECT,
|
|
||||||
MPD_DISCONNECT
|
|
||||||
};
|
|
||||||
|
|
||||||
struct t_mpd {
|
|
||||||
// Connection
|
|
||||||
struct mpd_connection *conn;
|
|
||||||
enum mpd_conn_states conn_state;
|
|
||||||
int timeout;
|
|
||||||
|
|
||||||
// Reponse Buffer
|
|
||||||
char buf[MAX_SIZE];
|
|
||||||
|
|
||||||
// States
|
|
||||||
int song_id;
|
|
||||||
int next_song_id;
|
|
||||||
int last_song_id;
|
|
||||||
unsigned queue_version;
|
|
||||||
unsigned queue_length;
|
|
||||||
int last_update_sticker_song_id;
|
|
||||||
int last_last_played_id;
|
|
||||||
|
|
||||||
// Features
|
|
||||||
const unsigned* protocol;
|
|
||||||
// Supported tags
|
|
||||||
bool feat_sticker;
|
|
||||||
bool feat_playlists;
|
|
||||||
bool feat_tags;
|
|
||||||
bool feat_library;
|
|
||||||
bool feat_advsearch;
|
|
||||||
} mpd;
|
|
||||||
|
|
||||||
struct list mpd_tags;
|
|
||||||
struct list mympd_tags;
|
|
||||||
struct list mympd_searchtags;
|
|
||||||
struct list mympd_browsetags;
|
|
||||||
struct list last_played;
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
long playCount;
|
|
||||||
long skipCount;
|
|
||||||
long lastPlayed;
|
|
||||||
long like;
|
|
||||||
} t_sticker;
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
bool notificationWeb;
|
|
||||||
bool notificationPage;
|
|
||||||
int jukeboxMode;
|
|
||||||
const char *jukeboxPlaylist;
|
|
||||||
int jukeboxQueueLength;
|
|
||||||
char *colsQueueCurrent;
|
|
||||||
char *colsSearch;
|
|
||||||
char *colsBrowseDatabase;
|
|
||||||
char *colsBrowsePlaylistsDetail;
|
|
||||||
char *colsBrowseFilesystem;
|
|
||||||
char *colsPlayback;
|
|
||||||
char *colsQueueLastPlayed;
|
|
||||||
} t_mympd_state;
|
|
||||||
|
|
||||||
t_mympd_state mympd_state;
|
|
||||||
|
|
||||||
void mpd_client_idle(int timeout);
|
|
||||||
void mpd_client_parse_idle(int idle_bitmask);
|
|
||||||
void mpd_client_api(void *arg_request);
|
|
||||||
void mpd_client_notify(size_t n);
|
|
||||||
bool mpd_client_count_song_id(int song_id, char *name, int value);
|
|
||||||
bool mpd_client_count_song_uri(const char *uri, char *name, int value);
|
|
||||||
bool mpd_client_like_song_uri(const char *uri, int value);
|
|
||||||
bool mpd_client_last_played_song_uri(const char *uri);
|
|
||||||
bool mpd_client_last_played_song_id(int song_id);
|
|
||||||
bool mpd_client_get_sticker(const char *uri, t_sticker *sticker);
|
|
||||||
bool mpd_client_last_played_list(int song_id);
|
|
||||||
bool mpd_client_jukebox();
|
|
||||||
bool mpd_client_state_get(char *name, char *value);
|
|
||||||
bool mpd_client_state_set(const char *name, const char *value);
|
|
||||||
int mpd_client_smartpls_save(char *smartpltype, char *playlist, char *tag, char *searchstr, int maxentries, int timerange);
|
|
||||||
int mpd_client_smartpls_put(char *buffer, char *playlist);
|
|
||||||
int mpd_client_smartpls_update_all();
|
|
||||||
int mpd_client_smartpls_clear(char *playlist);
|
|
||||||
int mpd_client_smartpls_update_sticker(char *playlist, char *sticker, int maxentries);
|
|
||||||
int mpd_client_smartpls_update_newest(char *playlist, int timerange);
|
|
||||||
int mpd_client_smartpls_update_search(char *playlist, char *tag, char *searchstr);
|
|
||||||
int mpd_client_get_updatedb_state(char *buffer);
|
|
||||||
int mpd_client_put_state(char *buffer, int *current_song_id, int *next_song_id, int *last_song_id, unsigned *queue_version, unsigned *queue_length);
|
|
||||||
int mpd_client_put_outputs(char *buffer);
|
|
||||||
int mpd_client_put_current_song(char *buffer);
|
|
||||||
int mpd_client_put_queue(char *buffer, unsigned int offset, unsigned *queue_version, unsigned *queue_length);
|
|
||||||
int mpd_client_put_browse(char *buffer, char *path, unsigned int offset, char *filter);
|
|
||||||
int mpd_client_search(char *buffer, char *searchstr, char *filter, char *plist, unsigned int offset);
|
|
||||||
int mpd_client_search_adv(char *buffer, char *expression, char *sort, bool sortdesc, char *grouptag, char *plist, unsigned int offset);
|
|
||||||
int mpd_client_search_queue(char *buffer, char *mpdtagtype, unsigned int offset, char *searchstr);
|
|
||||||
int mpd_client_put_welcome(char *buffer);
|
|
||||||
int mpd_client_put_volume(char *buffer);
|
|
||||||
int mpd_client_put_stats(char *buffer);
|
|
||||||
int mpd_client_put_settings(char *buffer, void *arg_config);
|
|
||||||
int mpd_client_put_db_tag(char *buffer, unsigned int offset, char *mpdtagtype, char *mpdsearchtagtype, char *searchstr, char *filter);
|
|
||||||
int mpd_client_put_songs_in_album(char *buffer, char *album, char *search, char *tag);
|
|
||||||
int mpd_client_put_playlists(char *buffer, unsigned int offset, char *filter);
|
|
||||||
int mpd_client_put_playlist_list(char *buffer, char *uri, unsigned int offset, char *filter);
|
|
||||||
int mpd_client_put_songdetails(char *buffer, char *uri);
|
|
||||||
int mpd_client_put_last_played_songs(char *buffer, unsigned int offset);
|
|
||||||
int mpd_client_queue_crop(char *buffer);
|
|
||||||
void mpd_client_disconnect();
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -39,21 +39,22 @@
|
||||||
#include "../dist/src/frozen/frozen.h"
|
#include "../dist/src/frozen/frozen.h"
|
||||||
|
|
||||||
//private definitions
|
//private definitions
|
||||||
static void mympd_api(void *arg_request, void *arg_config);
|
//static void mympd_api(void *arg_request, void *arg_config);
|
||||||
static int mympd_api_syscmd(char *buffer, const char *cmd, void *arg_config);
|
static void mympd_api(t_work_request *request, t_config *config);
|
||||||
|
static int mympd_api_syscmd(char *buffer, const char *cmd, t_config *config);
|
||||||
|
|
||||||
//public functions
|
//public functions
|
||||||
void *mympd_api_loop(void *arg_config) {
|
void *mympd_api_loop(void *arg_config) {
|
||||||
while (s_signal_received == 0) {
|
while (s_signal_received == 0) {
|
||||||
struct work_request_t *req = tiny_queue_shift(mympd_api_queue);
|
struct t_work_request *request = tiny_queue_shift(mympd_api_queue);
|
||||||
mympd_api(req, arg_config);
|
mympd_api(request, arg_config);
|
||||||
}
|
}
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
//private functions
|
//private functions
|
||||||
static void mympd_api(void *arg_request, void *arg_config) {
|
static void mympd_api(t_work_request *request, t_config *config) {
|
||||||
struct work_request_t *request = (struct work_request_t*) arg_request;
|
//t_work_request *request = (t_work_request *) arg_request;
|
||||||
size_t len = 0;
|
size_t len = 0;
|
||||||
char buffer[MAX_SIZE];
|
char buffer[MAX_SIZE];
|
||||||
int je;
|
int je;
|
||||||
|
@ -61,10 +62,10 @@ static void mympd_api(void *arg_request, void *arg_config) {
|
||||||
LOG_VERBOSE() printf("MYMPD API request: %.*s\n", request->length, request->data);
|
LOG_VERBOSE() printf("MYMPD API request: %.*s\n", request->length, request->data);
|
||||||
|
|
||||||
if (request->cmd_id == MYMPD_API_SYSCMD) {
|
if (request->cmd_id == MYMPD_API_SYSCMD) {
|
||||||
if (config.syscmds == true) {
|
if (config->syscmds == true) {
|
||||||
je = json_scanf(request->data, request->length, "{data: {cmd: %Q}}", &p_charbuf1);
|
je = json_scanf(request->data, request->length, "{data: {cmd: %Q}}", &p_charbuf1);
|
||||||
if (je == 1) {
|
if (je == 1) {
|
||||||
len = mympd_api_syscmd(buffer, p_charbuf1, arg_config);
|
len = mympd_api_syscmd(buffer, p_charbuf1, config);
|
||||||
free(p_charbuf1);
|
free(p_charbuf1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -83,7 +84,7 @@ static void mympd_api(void *arg_request, void *arg_config) {
|
||||||
}
|
}
|
||||||
LOG_DEBUG() fprintf(stderr, "DEBUG: Send http response to connection %lu (first 800 chars):\n%*.*s\n", request->conn_id, 0, 800, buffer);
|
LOG_DEBUG() fprintf(stderr, "DEBUG: Send http response to connection %lu (first 800 chars):\n%*.*s\n", request->conn_id, 0, 800, buffer);
|
||||||
|
|
||||||
struct work_result_t *response = (struct work_result_t*)malloc(sizeof(struct work_result_t));
|
t_work_result *response = (t_work_result *)malloc(sizeof(t_work_result));
|
||||||
response->conn_id = request->conn_id;
|
response->conn_id = request->conn_id;
|
||||||
response->length = copy_string(response->data, buffer, MAX_SIZE, len);
|
response->length = copy_string(response->data, buffer, MAX_SIZE, len);
|
||||||
tiny_queue_push(web_server_queue, response);
|
tiny_queue_push(web_server_queue, response);
|
||||||
|
@ -91,16 +92,15 @@ static void mympd_api(void *arg_request, void *arg_config) {
|
||||||
free(request);
|
free(request);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int mympd_api_syscmd(char *buffer, const char *cmd, void *arg_config) {
|
static int mympd_api_syscmd(char *buffer, const char *cmd, t_config *config) {
|
||||||
int len;
|
int len;
|
||||||
char filename[400];
|
char filename[400];
|
||||||
char *line;
|
char *line;
|
||||||
char *crap;
|
char *crap;
|
||||||
size_t n = 0;
|
size_t n = 0;
|
||||||
ssize_t read;
|
ssize_t read;
|
||||||
t_config *config = (t_config *) arg_config;
|
|
||||||
|
|
||||||
const int order = list_get_value(config->syscmd_list, cmd);
|
const int order = list_get_value(&config->syscmd_list, cmd);
|
||||||
if (order == -1) {
|
if (order == -1) {
|
||||||
printf("ERROR: Syscmd not defined: %s\n", cmd);
|
printf("ERROR: Syscmd not defined: %s\n", cmd);
|
||||||
len = snprintf(buffer, MAX_SIZE, "{\"type\": \"error\", \"data\": \"System command not defined\"}");
|
len = snprintf(buffer, MAX_SIZE, "{\"type\": \"error\", \"data\": \"System command not defined\"}");
|
||||||
|
@ -118,9 +118,10 @@ static int mympd_api_syscmd(char *buffer, const char *cmd, void *arg_config) {
|
||||||
fclose(fp);
|
fclose(fp);
|
||||||
if (read > 0) {
|
if (read > 0) {
|
||||||
strtok_r(line, "\n", &crap);
|
strtok_r(line, "\n", &crap);
|
||||||
if (system(line) == 0) {
|
const int rc = system(line);
|
||||||
|
if ( rc == 0) {
|
||||||
len = snprintf(buffer, MAX_SIZE, "{\"type\": \"result\", \"data\": \"Executed cmd %s.\"}", cmd);
|
len = snprintf(buffer, MAX_SIZE, "{\"type\": \"result\", \"data\": \"Executed cmd %s.\"}", cmd);
|
||||||
LOG_VERBOSE2() printf("Executed syscmd: \"%s\"\n", line);
|
LOG_VERBOSE() printf("Executed syscmd: \"%s\"\n", line);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
len = snprintf(buffer, MAX_SIZE, "{\"type\": \"error\", \"data\": \"Executing cmd %s failed.\"}", cmd);
|
len = snprintf(buffer, MAX_SIZE, "{\"type\": \"error\", \"data\": \"Executing cmd %s failed.\"}", cmd);
|
||||||
|
|
|
@ -38,8 +38,8 @@
|
||||||
static int is_websocket(const struct mg_connection *nc);
|
static int is_websocket(const struct mg_connection *nc);
|
||||||
static void ev_handler(struct mg_connection *nc, int ev, void *ev_data);
|
static void ev_handler(struct mg_connection *nc, int ev, void *ev_data);
|
||||||
static void ev_handler_redirect(struct mg_connection *nc_http, int ev, void *ev_data);
|
static void ev_handler_redirect(struct mg_connection *nc_http, int ev, void *ev_data);
|
||||||
static void send_ws_notify(struct mg_mgr *mgr, struct work_result_t *response);
|
static void send_ws_notify(struct mg_mgr *mgr, t_work_result *response);
|
||||||
static void send_api_response(struct mg_mgr *mgr, struct work_result_t *response);
|
static void send_api_response(struct mg_mgr *mgr, t_work_result *response);
|
||||||
static bool handle_api(long conn_id, const char *request, int request_len);
|
static bool handle_api(long conn_id, const char *request, int request_len);
|
||||||
|
|
||||||
typedef struct t_user_data {
|
typedef struct t_user_data {
|
||||||
|
@ -48,9 +48,8 @@ typedef struct t_user_data {
|
||||||
} t_user_data;
|
} t_user_data;
|
||||||
|
|
||||||
//public functions
|
//public functions
|
||||||
bool web_server_init(void *arg_mgr, void *arg_config) {
|
bool web_server_init(void *arg_mgr, t_config *config) {
|
||||||
struct mg_mgr *mgr = (struct mg_mgr *) arg_mgr;
|
struct mg_mgr *mgr = (struct mg_mgr *) arg_mgr;
|
||||||
t_config *config = (t_config *) arg_config;
|
|
||||||
struct mg_connection *nc_https;
|
struct mg_connection *nc_https;
|
||||||
struct mg_connection *nc_http;
|
struct mg_connection *nc_http;
|
||||||
struct mg_bind_opts bind_opts_https;
|
struct mg_bind_opts bind_opts_https;
|
||||||
|
@ -78,7 +77,7 @@ bool web_server_init(void *arg_mgr, void *arg_config) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
mg_set_protocol_http_websocket(nc_http);
|
mg_set_protocol_http_websocket(nc_http);
|
||||||
LOG_INFO2() printf("Listening on http port %s.\n", config->webport);
|
LOG_INFO() printf("Listening on http port %s.\n", config->webport);
|
||||||
|
|
||||||
//bind to sslport
|
//bind to sslport
|
||||||
if (config->ssl == true) {
|
if (config->ssl == true) {
|
||||||
|
@ -93,7 +92,7 @@ bool web_server_init(void *arg_mgr, void *arg_config) {
|
||||||
mg_mgr_free(mgr);
|
mg_mgr_free(mgr);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
LOG_INFO2() printf("Listening on ssl port %s\n", config->sslport);
|
LOG_INFO() printf("Listening on ssl port %s\n", config->sslport);
|
||||||
mg_set_protocol_http_websocket(nc_https);
|
mg_set_protocol_http_websocket(nc_https);
|
||||||
}
|
}
|
||||||
return mgr;
|
return mgr;
|
||||||
|
@ -110,7 +109,7 @@ void *web_server_loop(void *arg_mgr) {
|
||||||
mg_mgr_poll(mgr, 100);
|
mg_mgr_poll(mgr, 100);
|
||||||
unsigned web_server_queue_length = tiny_queue_length(web_server_queue);
|
unsigned web_server_queue_length = tiny_queue_length(web_server_queue);
|
||||||
if (web_server_queue_length > 0) {
|
if (web_server_queue_length > 0) {
|
||||||
struct work_result_t *response = tiny_queue_shift(web_server_queue);
|
t_work_result *response = tiny_queue_shift(web_server_queue);
|
||||||
if (response->conn_id == 0) {
|
if (response->conn_id == 0) {
|
||||||
//Websocket notify from mpd idle
|
//Websocket notify from mpd idle
|
||||||
send_ws_notify(mgr, response);
|
send_ws_notify(mgr, response);
|
||||||
|
@ -130,7 +129,7 @@ static int is_websocket(const struct mg_connection *nc) {
|
||||||
return nc->flags & MG_F_IS_WEBSOCKET;
|
return nc->flags & MG_F_IS_WEBSOCKET;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void send_ws_notify(struct mg_mgr *mgr, struct work_result_t *response) {
|
static void send_ws_notify(struct mg_mgr *mgr, t_work_result *response) {
|
||||||
struct mg_connection *nc;
|
struct mg_connection *nc;
|
||||||
for (nc = mg_next(mgr, NULL); nc != NULL; nc = mg_next(mgr, nc)) {
|
for (nc = mg_next(mgr, NULL); nc != NULL; nc = mg_next(mgr, nc)) {
|
||||||
if (!is_websocket(nc))
|
if (!is_websocket(nc))
|
||||||
|
@ -140,7 +139,7 @@ static void send_ws_notify(struct mg_mgr *mgr, struct work_result_t *response) {
|
||||||
free(response);
|
free(response);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void send_api_response(struct mg_mgr *mgr, struct work_result_t *response) {
|
static void send_api_response(struct mg_mgr *mgr, t_work_result *response) {
|
||||||
struct mg_connection *nc;
|
struct mg_connection *nc;
|
||||||
for (nc = mg_next(mgr, NULL); nc != NULL; nc = mg_next(mgr, nc)) {
|
for (nc = mg_next(mgr, NULL); nc != NULL; nc = mg_next(mgr, nc)) {
|
||||||
if (nc->user_data != NULL) {
|
if (nc->user_data != NULL) {
|
||||||
|
@ -171,12 +170,12 @@ static void ev_handler(struct mg_connection *nc, int ev, void *ev_data) {
|
||||||
nc_user_data->config = config;
|
nc_user_data->config = config;
|
||||||
nc_user_data->conn_id = user_data->conn_id;
|
nc_user_data->conn_id = user_data->conn_id;
|
||||||
nc->user_data = nc_user_data;
|
nc->user_data = nc_user_data;
|
||||||
LOG_DEBUG2() fprintf(stderr, "DEBUG: New connection id %ld.\n", user_data->conn_id);
|
LOG_DEBUG() fprintf(stderr, "DEBUG: New connection id %ld.\n", user_data->conn_id);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case MG_EV_WEBSOCKET_HANDSHAKE_REQUEST: {
|
case MG_EV_WEBSOCKET_HANDSHAKE_REQUEST: {
|
||||||
struct http_message *hm = (struct http_message *) ev_data;
|
struct http_message *hm = (struct http_message *) ev_data;
|
||||||
LOG_VERBOSE2() printf("New websocket request (%ld): %.*s\n", user_data->conn_id, hm->uri.len, hm->uri.p);
|
LOG_VERBOSE() printf("New websocket request (%ld): %.*s\n", user_data->conn_id, hm->uri.len, hm->uri.p);
|
||||||
if (mg_vcmp(&hm->uri, "/ws") != 0) {
|
if (mg_vcmp(&hm->uri, "/ws") != 0) {
|
||||||
printf("ERROR: Websocket request not to /ws, closing connection\n");
|
printf("ERROR: Websocket request not to /ws, closing connection\n");
|
||||||
mg_printf(nc, "%s", "HTTP/1.1 403 FORBIDDEN\r\n\r\n");
|
mg_printf(nc, "%s", "HTTP/1.1 403 FORBIDDEN\r\n\r\n");
|
||||||
|
@ -185,14 +184,14 @@ static void ev_handler(struct mg_connection *nc, int ev, void *ev_data) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case MG_EV_WEBSOCKET_HANDSHAKE_DONE: {
|
case MG_EV_WEBSOCKET_HANDSHAKE_DONE: {
|
||||||
LOG_VERBOSE2() printf("New Websocket connection established (%ld).\n", user_data->conn_id);
|
LOG_VERBOSE() printf("New Websocket connection established (%ld).\n", user_data->conn_id);
|
||||||
char response[] = "{\"type\": \"welcome\", \"data\": {\"mympdVersion\": \"" MYMPD_VERSION "\"}}";
|
char response[] = "{\"type\": \"welcome\", \"data\": {\"mympdVersion\": \"" MYMPD_VERSION "\"}}";
|
||||||
mg_send_websocket_frame(nc, WEBSOCKET_OP_TEXT, response, strlen(response));
|
mg_send_websocket_frame(nc, WEBSOCKET_OP_TEXT, response, strlen(response));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case MG_EV_HTTP_REQUEST: {
|
case MG_EV_HTTP_REQUEST: {
|
||||||
struct http_message *hm = (struct http_message *) ev_data;
|
struct http_message *hm = (struct http_message *) ev_data;
|
||||||
LOG_VERBOSE2() printf("HTTP request (%ld): %.*s\n", user_data->conn_id, hm->uri.len, hm->uri.p);
|
LOG_VERBOSE() printf("HTTP request (%ld): %.*s\n", user_data->conn_id, hm->uri.len, hm->uri.p);
|
||||||
if (mg_vcmp(&hm->uri, "/api") == 0) {
|
if (mg_vcmp(&hm->uri, "/api") == 0) {
|
||||||
bool rc = handle_api(user_data->conn_id, hm->body.p, hm->body.len);
|
bool rc = handle_api(user_data->conn_id, hm->body.p, hm->body.len);
|
||||||
if (rc == false) {
|
if (rc == false) {
|
||||||
|
@ -211,7 +210,7 @@ static void ev_handler(struct mg_connection *nc, int ev, void *ev_data) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case MG_EV_CLOSE: {
|
case MG_EV_CLOSE: {
|
||||||
LOG_VERBOSE2() fprintf(stderr, "HTTP connection %ld closed.\n", user_data->conn_id);
|
LOG_VERBOSE() fprintf(stderr, "HTTP connection %ld closed.\n", user_data->conn_id);
|
||||||
free(nc->user_data);
|
free(nc->user_data);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -239,7 +238,7 @@ static void ev_handler_redirect(struct mg_connection *nc, int ev, void *ev_data)
|
||||||
snprintf(s_redirect, 250, "https://%s/", host);
|
snprintf(s_redirect, 250, "https://%s/", host);
|
||||||
else
|
else
|
||||||
snprintf(s_redirect, 250, "https://%s:%s/", host, config->sslport);
|
snprintf(s_redirect, 250, "https://%s:%s/", host, config->sslport);
|
||||||
LOG_VERBOSE2() printf("Redirecting to %s\n", s_redirect);
|
LOG_VERBOSE() printf("Redirecting to %s\n", s_redirect);
|
||||||
mg_http_send_redirect(nc, 301, mg_mk_str(s_redirect), mg_mk_str(NULL));
|
mg_http_send_redirect(nc, 301, mg_mk_str(s_redirect), mg_mk_str(NULL));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -257,11 +256,11 @@ static bool handle_api(long conn_id, const char *request_body, int request_len)
|
||||||
if (je < 1)
|
if (je < 1)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
enum mypd_cmd_ids cmd_id = get_cmd_id(cmd);
|
enum mympd_cmd_ids cmd_id = get_cmd_id(cmd);
|
||||||
if (cmd_id == 0)
|
if (cmd_id == 0)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
struct work_request_t *request = (struct work_request_t*)malloc(sizeof(struct work_request_t));
|
t_work_request *request = (t_work_request*)malloc(sizeof(t_work_request));
|
||||||
request->conn_id = conn_id;
|
request->conn_id = conn_id;
|
||||||
request->cmd_id = cmd_id;
|
request->cmd_id = cmd_id;
|
||||||
request->length = copy_string(request->data, request_body, 1000, request_len);
|
request->length = copy_string(request->data, request_body, 1000, request_len);
|
||||||
|
|
|
@ -26,7 +26,7 @@
|
||||||
#define __WEB_SERVER_H__
|
#define __WEB_SERVER_H__
|
||||||
|
|
||||||
void *web_server_loop(void *arg_mgr);
|
void *web_server_loop(void *arg_mgr);
|
||||||
bool web_server_init(void *arg_mgr, void *arg_config);
|
bool web_server_init(void *arg_mgr, t_config *config);
|
||||||
void web_server_free(void *arg_mgr);
|
void web_server_free(void *arg_mgr);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
Loading…
Reference in New Issue
Block a user