/******************************************************************************!
* \file resources.c
* \author Sebastien Beaugrand
* \sa http://beaugrand.chez.com/
* \copyright CeCILL 2.1 Free Software license
******************************************************************************/
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <sys/socket.h>
#include <unistd.h>
#include <signal.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include "resources.h"
#include "mp3server.h"
#include "player.h"
#include "log.h"
#include "html.h"
#include "common.h"
/******************************************************************************!
* \fn sendPage
******************************************************************************/
void sendPage(int sock, struct Buffer* buffer)
{
char http_length[HTTP_LENGTH_SIZE];
char* buffPtr;
unsigned int len;
memset(http_length, ' ', HTTP_LENGTH_SIZE - 1);
http_length[HTTP_LENGTH_SIZE - 1] = '\0';
fprintf(buffer->file, http_length);
buffPtr = bufferGet(buffer);
strcpy(buffPtr, httpGetHttpOk());
if (snprintf(http_length, HTTP_LENGTH_SIZE, "%zu",
strlen(buffPtr + httpGetHttpOkSize())) >= HTTP_LENGTH_SIZE) {
ERROR("http_length = %s", http_length);
}
DEBUG("http_length = %s", http_length);
strcat(buffPtr, http_length);
strcat(buffPtr, "\r\n\r\n");
len = strlen(buffPtr);
if (len < httpGetHttpOkSize()) {
memset(buffPtr + len, ' ', httpGetHttpOkSize() - len);
buffPtr[httpGetHttpOkSize() - 1] = '\n';
}
len = strlen(buffPtr);
if (send(sock, buffPtr, len, 0) != (ssize_t) len) {
ERROR("send");
}
}
/******************************************************************************!
* \fn sendMessage
******************************************************************************/
void sendMessage(int sock, struct Buffer* buffer)
{
const char* buffPtr = bufferGet(buffer);
unsigned int buffLen = buffer->size;
if (buffLen == 0) {
if (send(sock, " ", 1, 0) != (ssize_t) 1) {
ERROR("send");
}
} else {
if (send(sock, buffPtr, buffLen, 0) != (ssize_t) buffLen) {
ERROR("send");
}
}
}
/******************************************************************************!
* \fn sendResourceRoot
******************************************************************************/
unsigned int
sendResourceRoot(int sockClient, struct Buffer* buffer,
enum tFormat __attribute__((__unused__)) format)
{
FILE* buffFile = bufferInit(buffer);
//if (format == HTML) {
fseek(buffFile, httpGetHttpOkSize(), SEEK_SET);
fprintf(buffFile, "%s%s", htmlGetBegin(), htmlGetEnd());
sendPage(sockClient, buffer);
//} else {
// sendMessage(sockClient, buffer);
//}
return 1;
}
/******************************************************************************!
* \fn sendResourceList
******************************************************************************/
unsigned int
sendResourceList(int sockClient, struct Buffer* buffer, enum tFormat format)
{
if (format == HTML) {
sendPage(sockClient, playerTitleList(buffer, HTML));
} else {
sendMessage(sockClient, playerTitleList(buffer, RAW));
}
return 1;
}
/******************************************************************************!
* \fn sendResourceRand
******************************************************************************/
unsigned int
sendResourceRand(int sockClient,
struct Buffer __attribute__((__unused__))* buffer,
enum tFormat format)
{
if (format == HTML) {
sendPage(sockClient, mp3serverMp3rand(HTML));
mp3serverSignalToClient(SIGUSR1);
} else {
sendMessage(sockClient, mp3serverMp3rand(RAW));
}
return 1;
}
/******************************************************************************!
* \fn sendResourceOk
******************************************************************************/
unsigned int
sendResourceOk(int sockClient, struct Buffer* buffer,
enum tFormat __attribute__((__unused__)) format)
{
if (mp3serverStopTempo()) {
mp3serverReadAlbum();
sendMessage(sockClient, mp3serverMp3info(NULL, RAW));
} else {
playerPause();
sendMessage(sockClient, playerCurrentTitle(buffer));
}
return 1;
}
/******************************************************************************!
* \fn sendResourceInfo
******************************************************************************/
unsigned int
sendResourceInfo(int sockClient,
struct Buffer __attribute__((__unused__))* buffer,
enum tFormat format)
{
if (format == HTML) {
sendPage(sockClient, mp3serverMp3info(NULL, HTML));
} else {
sendMessage(sockClient, mp3serverMp3info(NULL, RAW));
}
return 1;
}
/******************************************************************************!
* \fn sendResourcePlay
******************************************************************************/
unsigned int
sendResourcePlay(int sockClient,
struct Buffer __attribute__((__unused__))* buffer,
enum tFormat format)
{
playerStart();
if (format == HTML) {
sendPage(sockClient, playerTitleList(buffer, HTML));
} else {
sendMessage(sockClient, playerTitleList(buffer, RAW));
}
return 1;
}
/******************************************************************************!
* \fn sendResourcePause
******************************************************************************/
unsigned int
sendResourcePause(int sockClient,
struct Buffer __attribute__((__unused__))* buffer,
enum tFormat format)
{
playerPause();
if (format == HTML) {
sendPage(sockClient, playerTitleList(buffer, HTML));
} else {
sendMessage(sockClient, playerTitleList(buffer, RAW));
}
return 1;
}
/******************************************************************************!
* \fn sendResourceStop
******************************************************************************/
unsigned int
sendResourceStop(int sockClient, struct Buffer* buffer, enum tFormat format)
{
FILE* buffFile = bufferInit(buffer);
mp3serverSavePlaytime(playerGetPlaytime());
playerStop();
if (format == HTML) {
fseek(buffFile, httpGetHttpOkSize(), SEEK_SET);
fprintf(buffFile, "%s%s", htmlGetEmpty(), htmlGetEnd());
sendPage(sockClient, buffer);
} else {
fprintf(buffFile, "ok");
sendMessage(sockClient, buffer);
}
return 1;
}
/******************************************************************************!
* \fn sendResourceResume
******************************************************************************/
unsigned int
sendResourceResume(int sockClient,
struct Buffer __attribute__((__unused__))* buffer,
enum tFormat format)
{
playerResume();
if (format == HTML) {
sendPage(sockClient, playerTitleList(buffer, HTML));
} else {
sendMessage(sockClient, playerTitleList(buffer, RAW));
}
return 1;
}
/******************************************************************************!
* \fn sendResourcePrev
******************************************************************************/
unsigned int
sendResourcePrev(int sockClient,
struct Buffer __attribute__((__unused__))* buffer,
enum tFormat __attribute__((__unused__)) format)
{
playerStartRel(-1);
# if defined(__arm__) || defined(__aarch64__)
nanoSleep(500000000);
# endif
sendMessage(sockClient, playerCurrentTitle(buffer));
return 1;
}
/******************************************************************************!
* \fn sendResourceNext
******************************************************************************/
unsigned int
sendResourceNext(int sockClient,
struct Buffer __attribute__((__unused__))* buffer,
enum tFormat __attribute__((__unused__)) format)
{
playerStartRel(1);
# if defined(__arm__) || defined(__aarch64__)
nanoSleep(500000000);
# endif
sendMessage(sockClient, playerCurrentTitle(buffer));
return 1;
}
/******************************************************************************!
* \fn sendResourceDir
******************************************************************************/
unsigned int
sendResourceDir(int sockClient,
struct Buffer* buffer,
enum tFormat __attribute__((__unused__)) format)
{
char dir[32];
unsigned int pos;
unsigned int i;
char* buffPtr = bufferGet(buffer);
pos = 5 + strlen(RESOURCE_NAME_DIR) + 1;
for (i = 0; i < 32; ++i) {
if (buffPtr[pos] == ' ' ||
buffPtr[pos] == '?') {
dir[i] = '\0';
break;
}
if (buffPtr[pos] == '%' &&
buffPtr[pos + 1] == '2' &&
buffPtr[pos + 2] == '0') {
dir[i] = ' ';
pos += 3;
} else {
dir[i] = buffPtr[pos];
++pos;
}
}
DEBUG("dir = %s", dir);
sendPage(sockClient, mp3serverGetHtmlDir(dir));
return 1;
}
/******************************************************************************!
* \fn sendResourcePos
******************************************************************************/
unsigned int
sendResourcePos(int sockClient, struct Buffer* buffer,
enum tFormat __attribute__((__unused__)) format)
{
unsigned int pos;
char* buffPtr = bufferGet(buffer);
sscanf(buffPtr + 5 + strlen(RESOURCE_NAME_POS) + 1, "%3u", &pos);
DEBUG("id = %u", pos);
playerStartId(pos);
sendPage(sockClient, playerTitleList(buffer, HTML));
return 1;
}
/******************************************************************************!
* \fn sendResourceAlbum
******************************************************************************/
unsigned int
sendResourceAlbum(int sockClient, struct Buffer* buffer, enum tFormat format)
{
char album[LINE_SIZE];
unsigned int pos;
unsigned int i;
char* buffPtr = bufferGet(buffer);
pos = 5 + strlen(RESOURCE_NAME_ALBUM) + 1;
for (i = 0; i < LINE_SIZE - 1; ++i) {
if (buffPtr[pos] == '/' &&
(buffPtr[pos + 1] == ' ' ||
buffPtr[pos + 1] == '?')) {
album[i] = '\0';
break;
}
if (buffPtr[pos] == '%' &&
buffPtr[pos + 1] == '2' &&
buffPtr[pos + 2] == '0') {
album[i] = ' ';
pos += 3;
} else if (buffPtr[pos] == '%' &&
buffPtr[pos + 1] == '2' &&
buffPtr[pos + 2] == '7') {
album[i] = '\'';
pos += 3;
} else {
album[i] = buffPtr[pos];
++pos;
}
}
DEBUG("album = %s", album);
mp3serverStartAlbum(album);
if (format == HTML) {
sendPage(sockClient, mp3serverMp3info(NULL, HTML));
mp3serverSignalToClient(SIGUSR1);
} else {
sendMessage(sockClient, mp3serverMp3info(NULL, RAW));
}
return 1;
}
/******************************************************************************!
* \fn sendResourceArtist
******************************************************************************/
unsigned int
sendResourceArtist(int sockClient, struct Buffer* buffer,
enum tFormat __attribute__((__unused__)) format)
{
char artist[LINE_SIZE];
unsigned int pos;
unsigned int i;
FILE* buffFile;
char* buffPtr = bufferGet(buffer);
pos = 5 + strlen(RESOURCE_NAME_ARTIST) + 1;
for (i = 0; i < LINE_SIZE - 1; ++i) {
if (buffPtr[pos] == '/' &&
(buffPtr[pos + 1] == ' ' ||
buffPtr[pos + 1] == '?')) {
artist[i] = '\0';
break;
}
if (buffPtr[pos] == '%' &&
buffPtr[pos + 1] == '2' &&
buffPtr[pos + 2] == '0') {
artist[i] = ' ';
pos += 3;
} else if (buffPtr[pos] == '%' &&
buffPtr[pos + 1] == '2' &&
buffPtr[pos + 2] == '7') {
artist[i] = '\'';
pos += 3;
} else {
artist[i] = buffPtr[pos];
++pos;
}
}
strcpy(buffPtr, mp3serverGetArtist(artist));
DEBUG("artist = %s ==> %s", artist, buffPtr);
if (*buffPtr != '\0') {
sendMessage(sockClient, mp3serverMp3info(buffPtr, RAW));
} else {
buffFile = bufferInit(buffer);
fprintf(buffFile, " ");
sendMessage(sockClient, buffer);
}
return 1;
}
/******************************************************************************!
* \fn sendResourceKill
******************************************************************************/
unsigned int
sendResourceKill(int sockClient, struct Buffer* buffer, enum tFormat format)
{
FILE* buffFile = bufferInit(buffer);
if (format == HTML) {
fseek(buffFile, httpGetHttpOkSize(), SEEK_SET);
fprintf(buffFile, "%s", htmlGetEmpty());
fprintf(buffFile, "%s", htmlGetEnd());
sendPage(sockClient, buffer);
} else {
fprintf(buffFile, "ok");
sendMessage(sockClient, buffer);
}
if (close(sockClient) == -1) {
ERROR("close");
}
mp3serverSavePlaytime(playerGetPlaytime());
mp3serverQuit(EXIT_SUCCESS);
return 1;
}
/******************************************************************************!
* \fn sendResourceHalt
******************************************************************************/
unsigned int
sendResourceHalt(int sockClient, struct Buffer* buffer, enum tFormat format)
{
FILE* buffFile = bufferInit(buffer);
if (format == HTML) {
fseek(buffFile, httpGetHttpOkSize(), SEEK_SET);
fprintf(buffFile, "%s%s", htmlGetEmpty(), htmlGetEnd());
sendPage(sockClient, buffer);
} else {
fprintf(buffFile, "ok");
sendMessage(sockClient, buffer);
}
if (close(sockClient) == -1) {
ERROR("close");
}
mp3serverSavePlaytime(playerGetPlaytime());
# if defined(__arm__) || defined(__aarch64__)
if (system("sudo /sbin/halt") != EXIT_SUCCESS) {
ERROR("halt");
}
# endif
mp3serverQuit(EXIT_SUCCESS);
return 1;
}
/******************************************************************************!
* \fn sendResourcePid
******************************************************************************/
unsigned int
sendResourcePid(int sockClient, struct Buffer* buffer,
enum tFormat __attribute__((__unused__)) format)
{
pid_t pid;
FILE* buffFile;
char* buffPtr = bufferGet(buffer);
sscanf(buffPtr + 5 + strlen(RESOURCE_NAME_PID) + 1, "%5u", &pid);
mp3serverSetClientPid(pid);
DEBUG("pid = %u", pid);
buffFile = bufferInit(buffer);
fprintf(buffFile, "pid=%u", pid);
sendMessage(sockClient, buffer);
return 1;
}
/******************************************************************************!
* \fn sendResourceDate
******************************************************************************/
unsigned int
sendResourceDate(int sockClient, struct Buffer* buffer, enum tFormat format)
{
char dateOfTheDay[20];
FILE* buffFile = bufferInit(buffer);
strftime(dateOfTheDay,
sizeof(dateOfTheDay), "%F %T", mp3serverTmOfTheDay());
if (format == HTML) {
fseek(buffFile, httpGetHttpOkSize(), SEEK_SET);
fprintf(buffFile, "%s%s%s", htmlGetBegin(), dateOfTheDay, htmlGetEnd());
sendPage(sockClient, buffer);
} else {
fprintf(buffFile, "%s", dateOfTheDay);
sendMessage(sockClient, buffer);
}
return 1;
}
/******************************************************************************!
* \fn bufferPrintFile
******************************************************************************/
void bufferPrintFile(FILE* buffFile, const char* filename)
{
char buf[BUFSIZ];
int source;
ssize_t size;
source = open(filename, O_RDONLY, 0);
if (source == -1) {
return;
}
while ((size = read(source, buf, BUFSIZ - 1)) > 0) {
buf[size] = '\0';
fprintf(buffFile, "%s", buf);
}
close(source);
}
/******************************************************************************!
* \fn sendResourceLast
******************************************************************************/
unsigned int
sendResourceLast(int sockClient, struct Buffer* buffer, enum tFormat format)
{
char filename[LINE_SIZE];
FILE* buffFile = bufferInit(buffer);
if (format == HTML) {
fseek(buffFile, httpGetHttpOkSize(), SEEK_SET);
fprintf(buffFile, "%s", htmlGetBegin());
}
strcpy(filename, mp3serverGetMp3rootDir());
strcat(filename, "/.mp3log");
bufferPrintFile(buffFile, filename);
strcpy(filename, mp3serverGetMp3rootDir());
strcat(filename, "/.mp3last");
bufferPrintFile(buffFile, filename);
if (format == HTML) {
fprintf(buffFile, "%s", htmlGetEnd());
sendPage(sockClient, buffer);
} else {
sendMessage(sockClient, buffer);
}
return 1;
}
/******************************************************************************!
* \fn sendResourceLog
******************************************************************************/
unsigned int
sendResourceLog(int sockClient, struct Buffer* buffer, enum tFormat format)
{
char filename[LINE_SIZE];
FILE* buffFile = bufferInit(buffer);
if (format == HTML) {
fseek(buffFile, httpGetHttpOkSize(), SEEK_SET);
fprintf(buffFile, "%s", htmlGetBegin());
}
fprintf(buffFile, "Server\n\n");
strcpy(filename, mp3serverGetMp3rootDir());
strcat(filename, "/.mp3server.log.5");
bufferPrintFile(buffFile, filename);
fprintf(buffFile, "\n");
strcpy(filename, mp3serverGetMp3rootDir());
strcat(filename, "/.mp3server.log.4");
bufferPrintFile(buffFile, filename);
fprintf(buffFile, "\n");
strcpy(filename, mp3serverGetMp3rootDir());
strcat(filename, "/.mp3server.log.3");
bufferPrintFile(buffFile, filename);
fprintf(buffFile, "\n");
strcpy(filename, mp3serverGetMp3rootDir());
strcat(filename, "/.mp3server.log.2");
bufferPrintFile(buffFile, filename);
fprintf(buffFile, "\n");
strcpy(filename, mp3serverGetMp3rootDir());
strcat(filename, "/.mp3server.log.1");
bufferPrintFile(buffFile, filename);
fprintf(buffFile, "\n");
strcpy(filename, mp3serverGetMp3rootDir());
strcat(filename, "/.mp3server.log");
bufferPrintFile(buffFile, filename);
fprintf(buffFile, "\n");
fprintf(buffFile, "Client\n\n");
strcpy(filename, mp3serverGetMp3rootDir());
strcat(filename, "/.mp3client.log.5");
bufferPrintFile(buffFile, filename);
fprintf(buffFile, "\n");
strcpy(filename, mp3serverGetMp3rootDir());
strcat(filename, "/.mp3client.log.4");
bufferPrintFile(buffFile, filename);
fprintf(buffFile, "\n");
strcpy(filename, mp3serverGetMp3rootDir());
strcat(filename, "/.mp3client.log.3");
bufferPrintFile(buffFile, filename);
fprintf(buffFile, "\n");
strcpy(filename, mp3serverGetMp3rootDir());
strcat(filename, "/.mp3client.log.2");
bufferPrintFile(buffFile, filename);
fprintf(buffFile, "\n");
strcpy(filename, mp3serverGetMp3rootDir());
strcat(filename, "/.mp3client.log.1");
bufferPrintFile(buffFile, filename);
fprintf(buffFile, "\n");
strcpy(filename, mp3serverGetMp3rootDir());
strcat(filename, "/.mp3client.log");
bufferPrintFile(buffFile, filename);
fprintf(buffFile, "\n");
if (format == HTML) {
fprintf(buffFile, "%s", htmlGetEnd());
sendPage(sockClient, buffer);
} else {
sendMessage(sockClient, buffer);
}
return 1;
}
/******************************************************************************!
* \fn createResources
******************************************************************************/
void createResources()
{
httpInit();
httpAddResource(RESOURCE_NAME_ROOT, sendResourceRoot);
httpAddResource(RESOURCE_NAME_LIST, sendResourceList);
httpAddResource(RESOURCE_NAME_RAND, sendResourceRand);
httpAddResource(RESOURCE_NAME_OK, sendResourceOk);
httpAddResource(RESOURCE_NAME_INFO, sendResourceInfo);
httpAddResource(RESOURCE_NAME_PLAY, sendResourcePlay);
httpAddResource(RESOURCE_NAME_PAUSE, sendResourcePause);
httpAddResource(RESOURCE_NAME_STOP, sendResourceStop);
httpAddResource(RESOURCE_NAME_RESUME, sendResourceResume);
httpAddResource(RESOURCE_NAME_DIR, sendResourceDir);
httpAddResource(RESOURCE_NAME_POS, sendResourcePos);
httpAddResource(RESOURCE_NAME_PREV, sendResourcePrev);
httpAddResource(RESOURCE_NAME_NEXT, sendResourceNext);
httpAddResource(RESOURCE_NAME_ALBUM, sendResourceAlbum);
httpAddResource(RESOURCE_NAME_ARTIST, sendResourceArtist);
httpAddResource(RESOURCE_NAME_KILL, sendResourceKill);
httpAddResource(RESOURCE_NAME_HALT, sendResourceHalt);
httpAddResource(RESOURCE_NAME_PID, sendResourcePid);
httpAddResource(RESOURCE_NAME_DATE, sendResourceDate);
httpAddResource(RESOURCE_NAME_LAST, sendResourceLast);
httpAddResource(RESOURCE_NAME_LOG, sendResourceLog);
}