/*
* client.c
* This file is part of LCDd, the lcdproc server.
*
* This file is released under the GNU General Public License. Refer to the
* COPYING file distributed with this package.
*
* Copyright (c) 1999, William Ferrell, Scott Scriven
* 2002, Joris Robijn
*
*/
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include "config.h"
#include "client.h"
#include "screenlist.h"
#include "render.h"
#include "input.h"
#include "menuscreens.h"
#include "menuitem.h"
#include "shared/report.h"
#include "shared/LL.h"
Client *client_create(int sock)
{
Client *c;
debug(RPT_DEBUG, "%s(sock=%i)", __FUNCTION__, sock);
/* Allocate new client...*/
c = malloc(sizeof(Client));
if (!c) {
report(RPT_ERR, "%s: Error allocating", __FUNCTION__);
return NULL;
}
/* Init struct members*/
c->sock = sock;
c->messages = NULL;
c->backlight = BACKLIGHT_OPEN;
c->heartbeat = HEARTBEAT_OPEN;
/*Set up message list...*/
c->messages = LL_new();
if (!c->messages) {
report(RPT_ERR, "%s: Error allocating", __FUNCTION__);
free(c);
return NULL;
}
c->ack = 0;
c->name = NULL;
c->menu = NULL;
c->screenlist = LL_new();
if (!c->screenlist) {
report(RPT_ERR, "%s: Error allocating", __FUNCTION__);
return NULL;
}
return c;
}
int
client_destroy(Client *c)
{
Screen *s;
char *str;
if (!c)
return -1;
debug(RPT_DEBUG, "%s(c=[%d])", __FUNCTION__, c->sock);
/* Close the socket */
close(c->sock);
/* Eat messages */
while ((str = client_get_message(c))) {
free(str);
}
LL_Destroy(c->messages);
/* Clean up the screenlist...*/
debug(RPT_DEBUG, "%s: Cleaning screenlist", __FUNCTION__);
for (s = LL_GetFirst(c->screenlist); s; s = LL_GetNext(c->screenlist)) {
/* Free its memory...*/
screen_destroy(s);
/* Note that the screen is not removed from the list because
* the list will be destroyed anyway...
*/
}
LL_Destroy(c->screenlist);
/* Destroy the client's menu, if it exists */
if (c->menu) {
menuscreen_inform_item_destruction(c->menu);
menu_remove_item(c->menu->parent, c->menu);
menuscreen_inform_item_modified(c->menu->parent);
menuitem_destroy(c->menu);
}
/* Forget client's key reservations */
input_release_client_keys(c);
/* Free client's other data */
c->ack = 0;
/* Clean up the name...*/
if (c->name)
free(c->name);
/* Remove structure */
free(c);
debug(RPT_DEBUG, "%s: Client data removed", __FUNCTION__);
return 0;
}
/*Add and remove messages from the client's queue...*/
int
client_add_message(Client *c, char *message)
{
int err = 0;
char *dup;
char *str, *cp;
char delimiters[] = "\n\r\0";
debug(RPT_DEBUG, "%s(c=[%d], message=\"%s\")", __FUNCTION__, c->sock, message);
if (!c)
return -1;
if (!message)
return -1;
/* Copy the string to avoid overwriting the original...*/
dup = strdup(message);
if (!dup) {
report(RPT_ERR, "%s: Error allocating", __FUNCTION__);
return -1;
}
/* Now split the string into lines and enqueue each one...*/
for (str = strtok(dup, delimiters); str; str = strtok(NULL, delimiters)) {
cp = strdup(str);
debug(RPT_DEBUG, "%s: Queued message: \"%s\"", __FUNCTION__, cp);
err += LL_Enqueue(c->messages, (void *) cp);
}
free(dup);
/* Err is the number of errors encountered...*/
return err;
}
/* Woo-hoo! A simple function. :)*/
char *
client_get_message(Client *c)
{
char *str;
debug(RPT_DEBUG, "%s(c=[%d])", __FUNCTION__, c->sock);
if (!c)
return NULL;
str = (char *) LL_Dequeue(c->messages);
return str;
}
Screen *
client_find_screen(Client *c, char *id)
{
Screen *s;
if (!c)
return NULL;
if (!id)
return NULL;
debug(RPT_DEBUG, "%s(c=[%d], id=\"%s\")", __FUNCTION__, c->sock, id);
LL_Rewind(c->screenlist);
do {
s = LL_Get(c->screenlist);
if ((s) && (0 == strcmp(s->id, id))) {
debug(RPT_DEBUG, "%s: Found %s", __FUNCTION__, id);
return s;
}
} while (LL_Next(c->screenlist) == 0);
return NULL;
}
int
client_add_screen(Client *c, Screen *s)
{
if (!c)
return -1;
if (!s)
return -1;
debug(RPT_DEBUG, "%s(c=[%d], s=[%s])", __FUNCTION__, c->sock, s->id);
LL_Push(c->screenlist, (void *) s);
/* Now, add it to the screenlist...*/
screenlist_add(s);
return 0;
}
int
client_remove_screen(Client *c, Screen *s)
{
if (!c)
return -1;
if (!s)
return -1;
debug(RPT_DEBUG, "%s(c=[%d], s=[%s])", __FUNCTION__, c->sock, s->id);
/* TODO: Check for errors here?*/
LL_Remove(c->screenlist, (void *) s);
/* Now, remove it from the screenlist...*/
screenlist_remove(s);
return 0;
}
int client_screen_count(Client *c)
{
return LL_Length(c->screenlist);
}
syntax highlighted by Code2HTML, v. 0.9.1