Finished writing the code to generate Subsonic LinkTable
- Also refactored various bits and pieces
This commit is contained in:
parent
b7c63f4418
commit
5062f511bd
5
Makefile
5
Makefile
|
@ -1,7 +1,8 @@
|
|||
VERSION=1.1.10
|
||||
|
||||
CFLAGS+= -O2 -Wall -Wextra -Wshadow -rdynamic\
|
||||
-D_FILE_OFFSET_BITS=64 -DVERSION=\"$(VERSION)\" \
|
||||
CFLAGS+= -O2 -Wall -Wextra -Wshadow\
|
||||
-rdynamic -D_XOPEN_SOURCE=700 -D_DEFAULT_SOURCE\
|
||||
-D_FILE_OFFSET_BITS=64 -DVERSION=\"$(VERSION)\"\
|
||||
`pkg-config --cflags-only-I gumbo libcurl fuse uuid expat`
|
||||
LIBS = -pthread -lgumbo -lcurl -lfuse -lcrypto -luuid -lexpat
|
||||
COBJS = network.o fuse_local.o link.o cache.o util.o main.o
|
||||
|
|
30
src/cache.c
30
src/cache.c
|
@ -9,21 +9,6 @@
|
|||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
|
||||
/**
|
||||
* \brief Data file block size
|
||||
* \details We set it to 1024*1024*8 = 8MiB
|
||||
*/
|
||||
|
||||
#define DEFAULT_DATA_BLK_SZ 8*1024*1024
|
||||
|
||||
/**
|
||||
* \brief Maximum segment block count
|
||||
* \details This is set to 128*1024 blocks, which uses 128KB. By default,
|
||||
* this allows the user to store (128*1024)*(8*1024*1024) = 1TB of data
|
||||
*/
|
||||
|
||||
#define DEFAULT_MAX_SEGBC 128*1024
|
||||
|
||||
/**
|
||||
* \brief error associated with metadata
|
||||
*/
|
||||
|
@ -36,10 +21,7 @@ typedef enum {
|
|||
} MetaError;
|
||||
|
||||
/* ---------------- External variables -----------------------*/
|
||||
|
||||
int CACHE_SYSTEM_INIT = 0;
|
||||
int DATA_BLK_SZ = 0;
|
||||
int MAX_SEGBC = DEFAULT_MAX_SEGBC;
|
||||
char *META_DIR;
|
||||
|
||||
/* ----------------- Static variables ----------------------- */
|
||||
|
@ -156,10 +138,6 @@ void CacheSystem_init(const char *path, int url_supplied)
|
|||
strerror(errno));
|
||||
}
|
||||
|
||||
if (!DATA_BLK_SZ) {
|
||||
DATA_BLK_SZ = DEFAULT_DATA_BLK_SZ;
|
||||
}
|
||||
|
||||
CACHE_SYSTEM_INIT = 1;
|
||||
}
|
||||
|
||||
|
@ -202,12 +180,12 @@ blksz: %d, segbc: %ld\n", cf->path, cf->content_length, cf->blksz, cf->segbc);
|
|||
return EZERO;
|
||||
}
|
||||
|
||||
if (cf->blksz != DATA_BLK_SZ) {
|
||||
fprintf(stderr, "Meta_read(): Warning: cf->blksz != DATA_BLK_SZ\n");
|
||||
if (cf->blksz != CONFIG.data_blksz) {
|
||||
fprintf(stderr, "Meta_read(): Warning: cf->blksz != CONFIG.data_blksz\n");
|
||||
}
|
||||
|
||||
/* Allocate some memory for the segment */
|
||||
if (cf->segbc > MAX_SEGBC) {
|
||||
if (cf->segbc > CONFIG.max_segbc) {
|
||||
fprintf(stderr, "Meta_read(): Error: segbc: %ld\n", cf->segbc);
|
||||
return EMEM;
|
||||
}
|
||||
|
@ -671,7 +649,7 @@ int Cache_create(Link *this_link)
|
|||
cf->path = strndup(fn, MAX_PATH_LEN);
|
||||
cf->time = this_link->time;
|
||||
cf->content_length = this_link->content_length;
|
||||
cf->blksz = DATA_BLK_SZ;
|
||||
cf->blksz = CONFIG.data_blksz;
|
||||
cf->segbc = (cf->content_length / cf->blksz) + 1;
|
||||
cf->seg = CALLOC(cf->segbc, sizeof(Seg));
|
||||
|
||||
|
|
10
src/cache.h
10
src/cache.h
|
@ -70,16 +70,6 @@ struct Cache {
|
|||
*/
|
||||
extern int CACHE_SYSTEM_INIT;
|
||||
|
||||
/**
|
||||
* \brief The size of each download segment
|
||||
*/
|
||||
extern int DATA_BLK_SZ;
|
||||
|
||||
/**
|
||||
* \brief The maximum segment count for a single cache file
|
||||
*/
|
||||
extern int MAX_SEGBC;
|
||||
|
||||
/**
|
||||
* \brief The metadata directory
|
||||
*/
|
||||
|
|
32
src/link.c
32
src/link.c
|
@ -49,9 +49,9 @@ LinkTable *LinkSystem_init(const char *url)
|
|||
}
|
||||
|
||||
/* ----------- Enable cache system --------------------*/
|
||||
if (NETWORK_CONFIG.cache_enabled) {
|
||||
if (NETWORK_CONFIG.cache_dir) {
|
||||
CacheSystem_init(NETWORK_CONFIG.cache_dir, 0);
|
||||
if (CONFIG.cache_enabled) {
|
||||
if (CONFIG.cache_dir) {
|
||||
CacheSystem_init(CONFIG.cache_dir, 0);
|
||||
} else {
|
||||
CacheSystem_init(url, 1);
|
||||
}
|
||||
|
@ -62,7 +62,7 @@ LinkTable *LinkSystem_init(const char *url)
|
|||
return ROOT_LINK_TBL;
|
||||
}
|
||||
|
||||
static void LinkTable_add(LinkTable *linktbl, Link *link)
|
||||
void LinkTable_add(LinkTable *linktbl, Link *link)
|
||||
{
|
||||
linktbl->num++;
|
||||
linktbl->links = realloc(linktbl->links, linktbl->num * sizeof(Link *));
|
||||
|
@ -139,7 +139,7 @@ static CURL *Link_to_curl(Link *link)
|
|||
fprintf(stderr, "Link_to_curl(): curl_easy_init() failed!\n");
|
||||
}
|
||||
/* set up some basic curl stuff */
|
||||
curl_easy_setopt(curl, CURLOPT_USERAGENT, NETWORK_CONFIG.user_agent);
|
||||
curl_easy_setopt(curl, CURLOPT_USERAGENT, CONFIG.user_agent);
|
||||
curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1);
|
||||
/* for following directories without the '/' */
|
||||
curl_easy_setopt(curl, CURLOPT_MAXREDIRS, 2);
|
||||
|
@ -151,26 +151,26 @@ static CURL *Link_to_curl(Link *link)
|
|||
|
||||
// curl_easy_setopt(curl, CURLOPT_VERBOSE, 1L);
|
||||
|
||||
if (NETWORK_CONFIG.username) {
|
||||
curl_easy_setopt(curl, CURLOPT_USERNAME, NETWORK_CONFIG.username);
|
||||
if (CONFIG.http_username) {
|
||||
curl_easy_setopt(curl, CURLOPT_USERNAME, CONFIG.http_username);
|
||||
}
|
||||
|
||||
if (NETWORK_CONFIG.password) {
|
||||
curl_easy_setopt(curl, CURLOPT_PASSWORD, NETWORK_CONFIG.password);
|
||||
if (CONFIG.http_password) {
|
||||
curl_easy_setopt(curl, CURLOPT_PASSWORD, CONFIG.http_password);
|
||||
}
|
||||
|
||||
if (NETWORK_CONFIG.proxy) {
|
||||
curl_easy_setopt(curl, CURLOPT_PROXY, NETWORK_CONFIG.proxy);
|
||||
if (CONFIG.proxy) {
|
||||
curl_easy_setopt(curl, CURLOPT_PROXY, CONFIG.proxy);
|
||||
}
|
||||
|
||||
if (NETWORK_CONFIG.proxy_user) {
|
||||
if (CONFIG.proxy_username) {
|
||||
curl_easy_setopt(curl, CURLOPT_PROXYUSERNAME,
|
||||
NETWORK_CONFIG.proxy_user);
|
||||
CONFIG.proxy_username);
|
||||
}
|
||||
|
||||
if (NETWORK_CONFIG.proxy_pass) {
|
||||
if (CONFIG.proxy_password) {
|
||||
curl_easy_setopt(curl, CURLOPT_PROXYPASSWORD,
|
||||
NETWORK_CONFIG.proxy_pass);
|
||||
CONFIG.proxy_password);
|
||||
}
|
||||
|
||||
return curl;
|
||||
|
@ -355,7 +355,7 @@ DataStruct Link_to_DataStruct(Link *head_link)
|
|||
fprintf(stderr,
|
||||
"LinkTable_new(): URL: %s, HTTP %ld, retrying later.\n",
|
||||
url, http_resp);
|
||||
sleep(HTTP_WAIT_SEC);
|
||||
sleep(CONFIG.http_wait_sec);
|
||||
} else if (http_resp != HTTP_OK) {
|
||||
fprintf(stderr,
|
||||
"LinkTable_new(): cannot retrieve URL: %s, HTTP %ld\n",
|
||||
|
|
|
@ -159,4 +159,8 @@ void LinkTable_free(LinkTable *linktbl);
|
|||
*/
|
||||
void LinkTable_print(LinkTable *linktbl);
|
||||
|
||||
/**
|
||||
* \brief add a Link to a LinkTable
|
||||
*/
|
||||
void LinkTable_add(LinkTable *linktbl, Link *link);
|
||||
#endif
|
||||
|
|
40
src/main.c
40
src/main.c
|
@ -36,7 +36,7 @@ int main(int argc, char **argv)
|
|||
add_arg(&fuse_argv, &fuse_argc, argv[0]);
|
||||
|
||||
/* initialise network configuration struct */
|
||||
NetworkConfig_init();
|
||||
Config_init();
|
||||
|
||||
/* initialise network subsystem */
|
||||
NetworkSystem_init();
|
||||
|
@ -140,7 +140,10 @@ parse_arg_list(int argc, char **argv, char ***fuse_argv, int *fuse_argc)
|
|||
{"max-conns", required_argument, NULL, 'L'}, /* 11 */
|
||||
{"user-agent", required_argument, NULL, 'L'}, /* 12 */
|
||||
{"retry-wait", required_argument, NULL, 'L'}, /* 13 */
|
||||
{"cache-location", required_argument, NULL, 'L'}, /* 14 */
|
||||
{"cache-location", required_argument, NULL, 'L'}, /* 14 */
|
||||
{"sonic-username", required_argument, NULL, 'L'}, /* 15 */
|
||||
{"sonic-password", required_argument, NULL, 'L'}, /* 16 */
|
||||
{"sonic", no_argument, NULL, 'L'}, /* 17 */
|
||||
{0, 0, 0, 0}
|
||||
};
|
||||
while ((c =
|
||||
|
@ -170,43 +173,52 @@ parse_arg_list(int argc, char **argv, char ***fuse_argv, int *fuse_argc)
|
|||
add_arg(fuse_argv, fuse_argc, "-s");
|
||||
break;
|
||||
case 'u':
|
||||
NETWORK_CONFIG.username = strdup(optarg);
|
||||
CONFIG.http_username = strdup(optarg);
|
||||
break;
|
||||
case 'p':
|
||||
NETWORK_CONFIG.password = strdup(optarg);
|
||||
CONFIG.http_password = strdup(optarg);
|
||||
break;
|
||||
case 'P':
|
||||
NETWORK_CONFIG.proxy = strdup(optarg);
|
||||
CONFIG.proxy = strdup(optarg);
|
||||
break;
|
||||
case 'L':
|
||||
/* Long options */
|
||||
switch (long_index) {
|
||||
case 6:
|
||||
NETWORK_CONFIG.proxy_user = strdup(optarg);
|
||||
CONFIG.proxy_username = strdup(optarg);
|
||||
break;
|
||||
case 7:
|
||||
NETWORK_CONFIG.proxy_pass = strdup(optarg);
|
||||
CONFIG.proxy_password = strdup(optarg);
|
||||
break;
|
||||
case 8:
|
||||
NETWORK_CONFIG.cache_enabled = 1;
|
||||
CONFIG.cache_enabled = 1;
|
||||
break;
|
||||
case 9:
|
||||
DATA_BLK_SZ = atoi(optarg) * 1024 * 1024;
|
||||
CONFIG.data_blksz = atoi(optarg) * 1024 * 1024;
|
||||
break;
|
||||
case 10:
|
||||
MAX_SEGBC = atoi(optarg);
|
||||
CONFIG.max_segbc = atoi(optarg);
|
||||
break;
|
||||
case 11:
|
||||
NETWORK_CONFIG.max_conns = atoi(optarg);
|
||||
CONFIG.max_conns = atoi(optarg);
|
||||
break;
|
||||
case 12:
|
||||
NETWORK_CONFIG.user_agent = strdup(optarg);
|
||||
CONFIG.user_agent = strdup(optarg);
|
||||
break;
|
||||
case 13:
|
||||
HTTP_WAIT_SEC = atoi(optarg);
|
||||
CONFIG.http_wait_sec = atoi(optarg);
|
||||
break;
|
||||
case 14:
|
||||
NETWORK_CONFIG.cache_dir = strdup(optarg);
|
||||
CONFIG.cache_dir = strdup(optarg);
|
||||
break;
|
||||
case 15:
|
||||
CONFIG.sonic_username = strdup(optarg);
|
||||
break;
|
||||
case 16:
|
||||
CONFIG.sonic_password = strdup(optarg);
|
||||
break;
|
||||
case 17:
|
||||
CONFIG.sonic_mode = 1;
|
||||
break;
|
||||
default:
|
||||
fprintf(stderr, "see httpdirfs -h for usage\n");
|
||||
|
|
|
@ -9,13 +9,9 @@
|
|||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#define DEFAULT_NETWORK_MAX_CONNS 10
|
||||
#define DEFAULT_HTTP_WAIT_SEC 5
|
||||
|
||||
/* ----------------- External variables ---------------------- */
|
||||
CURLSH *CURL_SHARE;
|
||||
NetworkConfigStruct NETWORK_CONFIG;
|
||||
int HTTP_WAIT_SEC = DEFAULT_HTTP_WAIT_SEC;
|
||||
|
||||
/* ----------------- Static variable ----------------------- */
|
||||
/** \brief curl multi interface handle */
|
||||
|
@ -123,8 +119,8 @@ static void curl_process_msgs(CURLMsg *curl_msg, int n_running_curl,
|
|||
if (!slept) {
|
||||
fprintf(stderr,
|
||||
"curl_process_msgs(): HTTP %ld, sleeping for %d sec\n",
|
||||
http_resp, HTTP_WAIT_SEC);
|
||||
sleep(HTTP_WAIT_SEC);
|
||||
http_resp, CONFIG.http_wait_sec);
|
||||
sleep(CONFIG.http_wait_sec);
|
||||
slept = 1;
|
||||
}
|
||||
} else {
|
||||
|
@ -231,19 +227,6 @@ int curl_multi_perform_once(void)
|
|||
return n_running_curl;
|
||||
}
|
||||
|
||||
void NetworkConfig_init(void)
|
||||
{
|
||||
NETWORK_CONFIG.username = NULL;
|
||||
NETWORK_CONFIG.password = NULL;
|
||||
NETWORK_CONFIG.proxy = NULL;
|
||||
NETWORK_CONFIG.proxy_user = NULL;
|
||||
NETWORK_CONFIG.proxy_pass = NULL;
|
||||
NETWORK_CONFIG.max_conns = DEFAULT_NETWORK_MAX_CONNS;
|
||||
NETWORK_CONFIG.user_agent = DEFAULT_USER_AGENT;
|
||||
NETWORK_CONFIG.cache_enabled = 0;
|
||||
NETWORK_CONFIG.cache_dir = NULL;
|
||||
}
|
||||
|
||||
void NetworkSystem_init(void)
|
||||
{
|
||||
/* ------- Global related ----------*/
|
||||
|
@ -277,9 +260,9 @@ void NetworkSystem_init(void)
|
|||
exit_failure();
|
||||
}
|
||||
curl_multi_setopt(curl_multi, CURLMOPT_MAX_TOTAL_CONNECTIONS,
|
||||
NETWORK_CONFIG.max_conns);
|
||||
CONFIG.max_conns);
|
||||
curl_multi_setopt(curl_multi, CURLMOPT_MAX_HOST_CONNECTIONS,
|
||||
NETWORK_CONFIG.max_conns);
|
||||
CONFIG.max_conns);
|
||||
|
||||
/* ------------ Initialise locks ---------*/
|
||||
if (pthread_mutex_init(&transfer_lock, NULL)) {
|
||||
|
|
|
@ -8,24 +8,6 @@
|
|||
|
||||
#include "link.h"
|
||||
|
||||
/**
|
||||
* \brief the default user agent string
|
||||
*/
|
||||
#define DEFAULT_USER_AGENT "HTTPDirFS-" VERSION
|
||||
|
||||
typedef struct {
|
||||
char *username;
|
||||
char *password;
|
||||
char *proxy;
|
||||
char *proxy_user;
|
||||
char *proxy_pass;
|
||||
long max_conns;
|
||||
char *user_agent;
|
||||
int http_429_wait;
|
||||
char *cache_dir;
|
||||
int cache_enabled;
|
||||
} NetworkConfigStruct;
|
||||
|
||||
/** \brief HTTP response codes */
|
||||
typedef enum {
|
||||
HTTP_OK = 200,
|
||||
|
@ -36,21 +18,12 @@ typedef enum {
|
|||
HTTP_CLOUDFLARE_TIMEOUT = 524
|
||||
} HTTPResponseCode;
|
||||
|
||||
/** \brief The waiting time after getting HTTP 429 */
|
||||
extern int HTTP_WAIT_SEC;
|
||||
|
||||
/** \brief CURL configuration */
|
||||
extern NetworkConfigStruct NETWORK_CONFIG;
|
||||
|
||||
/** \brief curl shared interface */
|
||||
extern CURLSH *CURL_SHARE;
|
||||
|
||||
/** \brief perform one transfer cycle */
|
||||
int curl_multi_perform_once(void);
|
||||
|
||||
/** \brief initialise network config struct */
|
||||
void NetworkConfig_init(void);
|
||||
|
||||
/** \brief initialise the network module */
|
||||
void NetworkSystem_init(void);
|
||||
|
||||
|
|
130
src/sonic.c
130
src/sonic.c
|
@ -8,6 +8,8 @@
|
|||
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
|
||||
|
||||
typedef struct {
|
||||
char *server;
|
||||
|
@ -31,8 +33,8 @@ void sonic_config_init(const char *server, const char *username,
|
|||
if (SONIC_CONFIG.server[server_url_len] == '/') {
|
||||
SONIC_CONFIG.server[server_url_len] = '\0';
|
||||
}
|
||||
SONIC_CONFIG.username = strndup(username, MAX_FILENAME_LEN);
|
||||
SONIC_CONFIG.password = strndup(password, MAX_FILENAME_LEN);
|
||||
SONIC_CONFIG.http_username = strndup(username, MAX_FILENAME_LEN);
|
||||
SONIC_CONFIG.http_password = strndup(password, MAX_FILENAME_LEN);
|
||||
SONIC_CONFIG.client = DEFAULT_USER_AGENT;
|
||||
/*
|
||||
* API 1.13.0 is the minimum version that supports
|
||||
|
@ -47,16 +49,16 @@ void sonic_config_init(const char *server, const char *username,
|
|||
static char *sonic_gen_auth_str()
|
||||
{
|
||||
char *salt = generate_salt();
|
||||
size_t password_len = strnlen(SONIC_CONFIG.password, MAX_FILENAME_LEN);
|
||||
size_t password_len = strnlen(SONIC_CONFIG.http_password, MAX_FILENAME_LEN);
|
||||
size_t password_salt_len = password_len + strnlen(salt, MAX_FILENAME_LEN);
|
||||
char *password_salt = CALLOC(password_salt_len + 1, sizeof(char));
|
||||
strncat(password_salt, SONIC_CONFIG.password, MAX_FILENAME_LEN);
|
||||
strncat(password_salt, SONIC_CONFIG.http_password, MAX_FILENAME_LEN);
|
||||
strncat(password_salt + password_len, salt, MAX_FILENAME_LEN);
|
||||
char *token = generate_md5sum(password_salt);
|
||||
char *auth_str = CALLOC(MAX_PATH_LEN + 1, sizeof(char));
|
||||
snprintf(auth_str, MAX_PATH_LEN,
|
||||
".view?u=%s&t=%s&s=%s&v=%s&c=%s",
|
||||
SONIC_CONFIG.username, token, salt,
|
||||
SONIC_CONFIG.http_username, token, salt,
|
||||
SONIC_CONFIG.api_version, SONIC_CONFIG.client);
|
||||
free(salt);
|
||||
free(token);
|
||||
|
@ -76,27 +78,54 @@ static char *sonic_gen_url_first_part(char *method)
|
|||
return url;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief generate a getMusicDirectory request URL
|
||||
*/
|
||||
static char *sonic_getMusicDirectory_link(const int id)
|
||||
{
|
||||
char *first_part = sonic_gen_url_first_part("getMusicDirectory");
|
||||
char *url = CALLOC(MAX_PATH_LEN + 1, sizeof(char));
|
||||
snprintf(url, MAX_PATH_LEN, "%s&id=%d", first_part, id);
|
||||
free(first_part);
|
||||
return url;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief generate a download request URL
|
||||
*/
|
||||
static char *sonic_download_link(const int id)
|
||||
{
|
||||
char *first_part = sonic_gen_url_first_part("download");
|
||||
char *url = CALLOC(MAX_PATH_LEN + 1, sizeof(char));
|
||||
snprintf(url, MAX_PATH_LEN, "%s&id=%d", first_part, id);
|
||||
free(first_part);
|
||||
return url;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Process a single element output by the parser
|
||||
* \details This is the callback function called by the the XML parser.
|
||||
* \param[in] data user supplied data, in this case it is the pointer to the
|
||||
* LinkTable.
|
||||
* \param[in] element the name of this element, it should be either "child" or
|
||||
* \param[in] elem the name of this element, it should be either "child" or
|
||||
* "artist"
|
||||
* \param[in] attributes Each attribute seen in a start (or empty) tag occupies
|
||||
* \param[in] attr Each attribute seen in a start (or empty) tag occupies
|
||||
* 2 consecutive places in this vector: the attribute name followed by the
|
||||
* attribute value. These pairs are terminated by a null pointer.
|
||||
* \note we are using strcmp rather than strncmp, because we are assuming the
|
||||
* parser terminates the strings properly, which is a fair assumption,
|
||||
* considering how mature expat is.
|
||||
*/
|
||||
static void XMLCALL XML_process_single_element(void *data, const char *element,
|
||||
const char **attributes)
|
||||
static void XMLCALL XML_process_single_element(void *data, const char *elem,
|
||||
const char **attr)
|
||||
{
|
||||
LinkTable *linktbl = (LinkTable *) data;
|
||||
Link *link;
|
||||
if (!strncmp(element, "child", 5)) {
|
||||
if (!strcmp(elem, "child")) {
|
||||
/* Return from getMusicDirectory */
|
||||
link = CALLOC(1, sizeof(Link));
|
||||
link->type = LINK_INVALID;
|
||||
} else if (!strncmp(element, "artist", 6)){
|
||||
} else if (!strcmp(elem, "artist")){
|
||||
/* Return from getIndexes */
|
||||
link = CALLOC(1, sizeof(Link));
|
||||
link->type = LINK_DIR;
|
||||
|
@ -105,9 +134,78 @@ static void XMLCALL XML_process_single_element(void *data, const char *element,
|
|||
return;
|
||||
}
|
||||
|
||||
for (int i = 0; attributes[i]; i += 2) {
|
||||
int id_set = 0;
|
||||
int linkname_set = 0;
|
||||
|
||||
for (int i = 0; attr[i]; i += 2) {
|
||||
if (!strcmp("id", attr[i])) {
|
||||
link->sonic_id = atoi(attr[i+1]);
|
||||
id_set = 1;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!strcmp("name", attr[i]) || !strcmp("title", attr[i])) {
|
||||
strncpy(link->linkname, attr[i+1], MAX_FILENAME_LEN);
|
||||
linkname_set = 1;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!strcmp("isDir", attr[i])) {
|
||||
if (!strcmp("true", attr[i+1])) {
|
||||
link->type = LINK_DIR;
|
||||
} else if (!strcmp("false", attr[i+1])) {
|
||||
link->type = LINK_FILE;
|
||||
} else {
|
||||
link->type = LINK_DIR;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!strcmp("created", attr[i])) {
|
||||
struct tm *tm = calloc(1, sizeof(struct tm));
|
||||
strptime(attr[i+1], "%Y-%m-%dT%H:%M:%S.000Z", tm);
|
||||
link->time = mktime(tm);
|
||||
free(tm);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!strcmp("size", attr[i])) {
|
||||
link->content_length = atoll(attr[i+1]);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
/* Clean up if linkname is not set */
|
||||
if (!linkname_set) {
|
||||
free(link);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Clean up if id is not set */
|
||||
if (!id_set) {
|
||||
if (linkname_set) {
|
||||
free(link->linkname);
|
||||
}
|
||||
free(link);
|
||||
return;
|
||||
}
|
||||
|
||||
if (link->type == LINK_DIR) {
|
||||
char *url = sonic_getMusicDirectory_link(link->sonic_id);
|
||||
strncpy(link->f_url, url, MAX_PATH_LEN);
|
||||
free(url);
|
||||
} else if (link->type == LINK_FILE) {
|
||||
char *url = sonic_download_link(link->sonic_id);
|
||||
strncpy(link->f_url, url, MAX_PATH_LEN);
|
||||
free(url);
|
||||
} else {
|
||||
/* Invalid link */
|
||||
free(link->linkname);
|
||||
free(link);
|
||||
return;
|
||||
}
|
||||
|
||||
LinkTable_add(linktbl, link);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -127,14 +225,12 @@ static void sonic_XML_to_LinkTable(DataStruct ds, LinkTable *linktbl)
|
|||
XML_ParserFree(parser);
|
||||
}
|
||||
|
||||
|
||||
LinkTable *sonic_LinkTable_new(const int id)
|
||||
{
|
||||
char *url;
|
||||
if (id > 0) {
|
||||
char *first_part = sonic_gen_url_first_part("getMusicDirectory");
|
||||
url = CALLOC(MAX_PATH_LEN + 1, sizeof(char));
|
||||
snprintf(url, MAX_PATH_LEN, "%s&id=%d", first_part, id);
|
||||
free(first_part);
|
||||
url = sonic_getMusicDirectory_link(id);
|
||||
} else {
|
||||
url = sonic_gen_url_first_part("getIndexes");
|
||||
}
|
||||
|
@ -166,7 +262,7 @@ int main(int argc, char **argv)
|
|||
|
||||
sonic_config_init(argv[1], argv[2], argv[3]);
|
||||
|
||||
NetworkConfig_init();
|
||||
Config_init();
|
||||
NetworkSystem_init();
|
||||
|
||||
sonic_LinkTable_new(0);
|
||||
|
|
77
src/util.c
77
src/util.c
|
@ -9,10 +9,86 @@
|
|||
#include <string.h>
|
||||
#include <errno.h>
|
||||
|
||||
/**
|
||||
* \brief Backtrace buffer size
|
||||
*/
|
||||
#define BT_BUF_SIZE 100
|
||||
|
||||
/**
|
||||
* \brief The length of a MD5SUM string
|
||||
*/
|
||||
#define MD5_HASH_LEN 32
|
||||
|
||||
/**
|
||||
* \brief The length of the salt
|
||||
* \details This is basically the length of a UUID
|
||||
*/
|
||||
#define SALT_LEN 36
|
||||
|
||||
/**
|
||||
* \brief The default maximum number of network connections
|
||||
*/
|
||||
#define DEFAULT_NETWORK_MAX_CONNS 10
|
||||
|
||||
/**
|
||||
* \brief The default HTTP 429 (too many requests) wait time
|
||||
*/
|
||||
#define DEFAULT_HTTP_WAIT_SEC 5
|
||||
/**
|
||||
* \brief Data file block size
|
||||
* \details We set it to 1024*1024*8 = 8MiB
|
||||
*/
|
||||
#define DEFAULT_DATA_BLKSZ 8*1024*1024
|
||||
|
||||
/**
|
||||
* \brief Maximum segment block count
|
||||
* \details This is set to 128*1024 blocks, which uses 128KB. By default,
|
||||
* this allows the user to store (128*1024)*(8*1024*1024) = 1TB of data
|
||||
*/
|
||||
#define DEFAULT_MAX_SEGBC 128*1024
|
||||
|
||||
ConfigStruct CONFIG;
|
||||
|
||||
/**
|
||||
* \note The opening curly bracket should be at line 39, so the code lines up
|
||||
* with the definition code in util.h.
|
||||
*/
|
||||
void Config_init(void)
|
||||
{
|
||||
/*---------------- Network related --------------*/
|
||||
CONFIG.http_username = NULL;
|
||||
|
||||
CONFIG.http_password = NULL;
|
||||
|
||||
CONFIG.proxy = NULL;
|
||||
|
||||
CONFIG.proxy_username = NULL;
|
||||
|
||||
CONFIG.proxy_password = NULL;
|
||||
|
||||
CONFIG.max_conns = DEFAULT_NETWORK_MAX_CONNS;
|
||||
|
||||
CONFIG.user_agent = DEFAULT_USER_AGENT;
|
||||
|
||||
CONFIG.http_wait_sec = DEFAULT_HTTP_WAIT_SEC;
|
||||
|
||||
/*--------------- Cache related ---------------*/
|
||||
CONFIG.cache_enabled = 0;
|
||||
|
||||
CONFIG.cache_dir = NULL;
|
||||
|
||||
CONFIG.data_blksz = DEFAULT_DATA_BLKSZ;
|
||||
|
||||
CONFIG.max_segbc = DEFAULT_MAX_SEGBC;
|
||||
|
||||
/*-------------- Subsonic related -------------*/
|
||||
CONFIG.sonic_mode = 0;
|
||||
|
||||
CONFIG.sonic_username = NULL;
|
||||
|
||||
CONFIG.sonic_password = NULL;
|
||||
}
|
||||
|
||||
char *path_append(const char *path, const char *filename)
|
||||
{
|
||||
int needs_separator = 0;
|
||||
|
@ -123,3 +199,4 @@ void *CALLOC(size_t nmemb, size_t size)
|
|||
}
|
||||
return ptr;
|
||||
}
|
||||
|
||||
|
|
60
src/util.h
60
src/util.h
|
@ -21,6 +21,61 @@
|
|||
*/
|
||||
#define MAX_FILENAME_LEN 255
|
||||
|
||||
/**
|
||||
* \brief the default user agent string
|
||||
*/
|
||||
#define DEFAULT_USER_AGENT "HTTPDirFS-" VERSION
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* \brief configuration data structure
|
||||
* \note The opening curly bracket should be at line 39, so the code belong
|
||||
* lines up with the initialisation code in util.c
|
||||
*/
|
||||
typedef struct {
|
||||
/** \brief HTTP username */
|
||||
char *http_username;
|
||||
/** \brief HTTP password */
|
||||
char *http_password;
|
||||
/** \brief HTTP proxy URL */
|
||||
char *proxy;
|
||||
/** \brief HTTP proxy username */
|
||||
char *proxy_username;
|
||||
/** \brief HTTP proxy password */
|
||||
char *proxy_password;
|
||||
/** \brief HTTP maximum connection count */
|
||||
long max_conns;
|
||||
/** \brief HTTP user agent*/
|
||||
char *user_agent;
|
||||
/** \brief The waiting time after getting HTTP 429 (too many requests) */
|
||||
int http_wait_sec;
|
||||
|
||||
/** \brief Whether cache mode is enabled */
|
||||
int cache_enabled;
|
||||
/** \brief The cache location*/
|
||||
char *cache_dir;
|
||||
/** \brief The size of each download segment for cache mode */
|
||||
int data_blksz;
|
||||
/** \brief The maximum segment count for a single cache file */
|
||||
int max_segbc;
|
||||
|
||||
/** \brief Whether we are using the Subsonic mode */
|
||||
int sonic_mode;
|
||||
/** \brief The Subsonic server username */
|
||||
char *sonic_username;
|
||||
/** \brief The Subsonic server password */
|
||||
char *sonic_password;
|
||||
} ConfigStruct;
|
||||
|
||||
/**
|
||||
* \brief The Configuration data structure
|
||||
*/
|
||||
extern ConfigStruct CONFIG;
|
||||
|
||||
/**
|
||||
* \brief append a path
|
||||
* \details This function appends a path with the next level, while taking the
|
||||
|
@ -74,4 +129,9 @@ char *generate_md5sum(const char *str);
|
|||
*/
|
||||
void *CALLOC(size_t nmemb, size_t size);
|
||||
|
||||
/**
|
||||
* \brief initialise the configuration data structure
|
||||
*/
|
||||
void Config_init(void);
|
||||
|
||||
#endif
|
||||
|
|
Loading…
Reference in New Issue