1999-12-09 23:15:14 +00:00
|
|
|
/*
|
|
|
|
|
|
|
|
|
|
clients.c
|
|
|
|
|
|
|
|
|
|
Inits/shuts down client system,
|
|
|
|
|
creates/destroys individual clients,
|
|
|
|
|
enqueues/dequeues messages from clients,
|
|
|
|
|
and searches for clients in the list.
|
|
|
|
|
|
|
|
|
|
:)
|
|
|
|
|
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
#include <stdio.h>
|
|
|
|
|
#include <stdlib.h>
|
|
|
|
|
#include <unistd.h>
|
|
|
|
|
#include <string.h>
|
|
|
|
|
|
|
|
|
|
#include "clients.h"
|
|
|
|
|
#include "client_data.h"
|
|
|
|
|
#include "../shared/debug.h"
|
|
|
|
|
|
2000-03-30 20:20:41 +00:00
|
|
|
LL *clients;
|
1999-12-09 23:15:14 +00:00
|
|
|
|
|
|
|
|
// Initialize and kill client list...
|
2000-03-30 20:20:41 +00:00
|
|
|
int
|
|
|
|
|
client_init ()
|
1999-12-09 23:15:14 +00:00
|
|
|
{
|
2000-04-03 22:13:57 +00:00
|
|
|
debug ("client_init()\n");
|
2000-03-30 20:20:41 +00:00
|
|
|
|
2000-04-03 22:13:57 +00:00
|
|
|
clients = LL_new ();
|
|
|
|
|
if (!clients) {
|
|
|
|
|
fprintf (stderr, "client_init: Unable to create client list\n");
|
|
|
|
|
return -1;
|
|
|
|
|
}
|
1999-12-09 23:15:14 +00:00
|
|
|
|
2000-04-03 22:13:57 +00:00
|
|
|
return 0;
|
1999-12-09 23:15:14 +00:00
|
|
|
}
|
|
|
|
|
|
2000-03-30 20:20:41 +00:00
|
|
|
int
|
|
|
|
|
client_shutdown ()
|
1999-12-09 23:15:14 +00:00
|
|
|
{
|
2000-04-03 22:13:57 +00:00
|
|
|
// TODO: Close all connections first...
|
|
|
|
|
client *c;
|
1999-12-09 23:15:14 +00:00
|
|
|
|
2000-04-03 22:13:57 +00:00
|
|
|
debug ("client_shutdown()\n");
|
2000-03-30 20:20:41 +00:00
|
|
|
|
2000-04-03 22:13:57 +00:00
|
|
|
// Free all client structures...
|
|
|
|
|
// Note that the regular list loop doesn't work here, because
|
|
|
|
|
// client_destroy() calls LL_Remove()
|
|
|
|
|
for (c = LL_Pop (clients); c; c = LL_Pop (clients)) {
|
|
|
|
|
debug ("client_shutdown: ...\n");
|
|
|
|
|
if (c) {
|
|
|
|
|
debug ("client_shutdown: ... %i ...\n", c->sock);
|
|
|
|
|
if (0 != client_destroy (c)) {
|
|
|
|
|
fprintf (stderr, "client_shutdown: Error freeing client\n");
|
|
|
|
|
} else {
|
|
|
|
|
debug ("client_shutdown: Freed client...\n");
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
debug ("client_shutdown: No client!\n");
|
|
|
|
|
}
|
|
|
|
|
}
|
1999-12-09 23:15:14 +00:00
|
|
|
|
2000-04-03 22:13:57 +00:00
|
|
|
// Then, free the list...
|
|
|
|
|
LL_Destroy (clients);
|
2000-03-30 20:20:41 +00:00
|
|
|
|
2000-04-03 22:13:57 +00:00
|
|
|
debug ("client_shutdown: done\n");
|
1999-12-09 23:15:14 +00:00
|
|
|
|
2000-04-03 22:13:57 +00:00
|
|
|
return 0;
|
1999-12-09 23:15:14 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Create and destroy clients....
|
2000-03-30 20:20:41 +00:00
|
|
|
client *
|
|
|
|
|
client_create (int sock)
|
1999-12-09 23:15:14 +00:00
|
|
|
{
|
2000-04-03 22:13:57 +00:00
|
|
|
client *c;
|
1999-12-09 23:15:14 +00:00
|
|
|
|
2000-04-03 22:13:57 +00:00
|
|
|
debug ("client_create(%i)\n", sock);
|
1999-12-09 23:15:14 +00:00
|
|
|
|
2000-04-03 22:13:57 +00:00
|
|
|
// Allocate new client...
|
|
|
|
|
c = malloc (sizeof (client));
|
|
|
|
|
if (!c) {
|
|
|
|
|
fprintf (stderr, "client_create: error allocating new client\n");
|
|
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
// Init struct members
|
|
|
|
|
c->sock = 0;
|
|
|
|
|
c->data = NULL;
|
|
|
|
|
c->messages = NULL;
|
1999-12-09 23:15:14 +00:00
|
|
|
|
2000-04-03 22:13:57 +00:00
|
|
|
c->sock = sock;
|
1999-12-09 23:15:14 +00:00
|
|
|
|
2000-04-03 22:13:57 +00:00
|
|
|
// Set up message list...
|
|
|
|
|
c->messages = LL_new ();
|
|
|
|
|
if (!c->messages) {
|
|
|
|
|
fprintf (stderr, "client_create: error allocating message list\n");
|
|
|
|
|
free (c);
|
|
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
// TODO: allocate and init client data...
|
|
|
|
|
c->data = malloc (sizeof (client_data));
|
|
|
|
|
if (!c->data) {
|
|
|
|
|
fprintf (stderr, "client_create: error allocating client data\n");
|
|
|
|
|
free (c->messages);
|
|
|
|
|
free (c);
|
|
|
|
|
return NULL;
|
|
|
|
|
} else if (client_data_init (c->data) < 0) {
|
|
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
// TODO: Check for errors while adding the client to the list?
|
|
|
|
|
LL_Push (clients, (void *) c);
|
2000-03-30 20:20:41 +00:00
|
|
|
|
2000-04-03 22:13:57 +00:00
|
|
|
return c;
|
1999-12-09 23:15:14 +00:00
|
|
|
}
|
2000-03-30 20:20:41 +00:00
|
|
|
|
|
|
|
|
int
|
|
|
|
|
client_destroy (client * c)
|
1999-12-09 23:15:14 +00:00
|
|
|
{
|
2000-04-03 22:13:57 +00:00
|
|
|
// TODO: Close the socket connection here?
|
|
|
|
|
int err;
|
2000-03-30 20:20:41 +00:00
|
|
|
|
2000-04-03 22:13:57 +00:00
|
|
|
char *str;
|
1999-12-09 23:15:14 +00:00
|
|
|
|
2000-04-03 22:13:57 +00:00
|
|
|
debug ("client_destroy()\n");
|
2000-03-30 20:20:41 +00:00
|
|
|
|
2000-04-03 22:13:57 +00:00
|
|
|
if (!c)
|
|
|
|
|
return -1;
|
1999-12-09 23:15:14 +00:00
|
|
|
|
2000-04-03 22:13:57 +00:00
|
|
|
// Eat the rest of the incoming requests...
|
|
|
|
|
debug ("client_destroy: get_messages\n");
|
|
|
|
|
while ((str = client_get_message (c))) {
|
|
|
|
|
if (str) {
|
|
|
|
|
debug ("client_destroy: kill message %s\n", str);
|
|
|
|
|
free (str);
|
|
|
|
|
}
|
|
|
|
|
}
|
1999-12-09 23:15:14 +00:00
|
|
|
|
2000-04-03 22:13:57 +00:00
|
|
|
err = LL_Destroy (c->messages);
|
1999-12-09 23:15:14 +00:00
|
|
|
|
2000-04-03 22:13:57 +00:00
|
|
|
// Free client's other data
|
|
|
|
|
client_data_destroy (c->data);
|
2000-03-30 20:20:41 +00:00
|
|
|
|
1999-12-09 23:15:14 +00:00
|
|
|
/*
|
|
|
|
|
// FIXME? Should the connection get closed here or elsewhere?
|
|
|
|
|
if(c->sock) close(c->sock);
|
|
|
|
|
c->sock = 0;
|
|
|
|
|
*/
|
2000-03-30 20:20:41 +00:00
|
|
|
|
2000-04-03 22:13:57 +00:00
|
|
|
// Remove the client from the clients list...
|
|
|
|
|
LL_Remove (clients, c);
|
2000-03-30 20:20:41 +00:00
|
|
|
|
2000-04-03 22:13:57 +00:00
|
|
|
free (c);
|
1999-12-09 23:15:14 +00:00
|
|
|
|
2000-04-03 22:13:57 +00:00
|
|
|
return 0;
|
1999-12-09 23:15:14 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Add and remove messages from the client's queue...
|
2000-03-30 20:20:41 +00:00
|
|
|
int
|
|
|
|
|
client_add_message (client * c, char *message)
|
1999-12-09 23:15:14 +00:00
|
|
|
{
|
2000-04-03 22:13:57 +00:00
|
|
|
int err = 0;
|
|
|
|
|
char *dup;
|
|
|
|
|
char *str, *cp;
|
|
|
|
|
char delimiters[] = "\n\r\0";
|
1999-12-09 23:15:14 +00:00
|
|
|
// int len;
|
|
|
|
|
|
2000-04-03 22:13:57 +00:00
|
|
|
//debug("client_add_message(%s)\n", message);
|
2000-03-30 20:20:41 +00:00
|
|
|
|
2000-04-03 22:13:57 +00:00
|
|
|
if (!c)
|
|
|
|
|
return -1;
|
|
|
|
|
if (!message)
|
|
|
|
|
return -1;
|
1999-12-09 23:15:14 +00:00
|
|
|
|
|
|
|
|
// len = strlen(message);
|
|
|
|
|
// if(len < 1) return 0;
|
2000-03-30 20:20:41 +00:00
|
|
|
|
2000-04-03 22:13:57 +00:00
|
|
|
// Copy the string to avoid overwriting the original...
|
|
|
|
|
dup = strdup (message);
|
|
|
|
|
if (!dup) {
|
|
|
|
|
fprintf (stderr, "client_add_message: Error allocating new string\n");
|
|
|
|
|
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 ("client_add_message: %s\n", cp);
|
|
|
|
|
err += LL_Enqueue (c->messages, (void *) cp);
|
|
|
|
|
}
|
1999-12-09 23:15:14 +00:00
|
|
|
|
2000-04-03 22:13:57 +00:00
|
|
|
//debug("client_add_message(%s): %i errors\n", message, err);
|
|
|
|
|
free (dup); // Fixed memory leak...
|
2000-03-30 20:20:41 +00:00
|
|
|
|
2000-04-03 22:13:57 +00:00
|
|
|
// Err is the number of errors encountered...
|
|
|
|
|
return err;
|
2000-03-30 20:20:41 +00:00
|
|
|
|
1999-12-09 23:15:14 +00:00
|
|
|
}
|
2000-03-30 20:20:41 +00:00
|
|
|
|
1999-12-09 23:15:14 +00:00
|
|
|
// Woo-hoo! A simple function. :)
|
2000-03-30 20:20:41 +00:00
|
|
|
char *
|
|
|
|
|
client_get_message (client * c)
|
1999-12-09 23:15:14 +00:00
|
|
|
{
|
2000-04-03 22:13:57 +00:00
|
|
|
char *str;
|
1999-12-09 23:15:14 +00:00
|
|
|
|
2000-04-03 22:13:57 +00:00
|
|
|
//debug("client_get_message()\n");
|
1999-12-09 23:15:14 +00:00
|
|
|
|
2000-04-03 22:13:57 +00:00
|
|
|
if (!c)
|
|
|
|
|
return NULL;
|
2000-03-30 20:20:41 +00:00
|
|
|
|
2000-04-03 22:13:57 +00:00
|
|
|
str = (char *) LL_Dequeue (c->messages);
|
1999-12-09 23:15:14 +00:00
|
|
|
|
2000-04-03 22:13:57 +00:00
|
|
|
//debug("client_get_message: \"%s\"\n", str);
|
2000-03-30 20:20:41 +00:00
|
|
|
|
2000-04-03 22:13:57 +00:00
|
|
|
return str;
|
1999-12-09 23:15:14 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Get and set the client's data...
|
2000-03-30 20:20:41 +00:00
|
|
|
int
|
|
|
|
|
client_set (client * c, void *data)
|
1999-12-09 23:15:14 +00:00
|
|
|
{
|
2000-04-03 22:13:57 +00:00
|
|
|
// You know, I really doubt this function will be useful...
|
|
|
|
|
return 0;
|
1999-12-09 23:15:14 +00:00
|
|
|
}
|
2000-03-30 20:20:41 +00:00
|
|
|
|
|
|
|
|
void *
|
|
|
|
|
client_get (client * c)
|
1999-12-09 23:15:14 +00:00
|
|
|
{
|
2000-04-03 22:13:57 +00:00
|
|
|
// But this one might be handy...
|
1999-12-09 23:15:14 +00:00
|
|
|
|
2000-04-03 22:13:57 +00:00
|
|
|
return NULL;
|
1999-12-09 23:15:14 +00:00
|
|
|
}
|
|
|
|
|
|
2000-03-30 20:20:41 +00:00
|
|
|
client *
|
|
|
|
|
client_find_sock (int sock)
|
1999-12-09 23:15:14 +00:00
|
|
|
{
|
2000-04-03 22:13:57 +00:00
|
|
|
client *c;
|
1999-12-09 23:15:14 +00:00
|
|
|
|
|
|
|
|
// debug("client_find_sock(%i)\n", sock);
|
|
|
|
|
|
2000-04-03 22:13:57 +00:00
|
|
|
LL_Rewind (clients);
|
|
|
|
|
do {
|
|
|
|
|
c = (client *) LL_Get (clients);
|
1999-12-09 23:15:14 +00:00
|
|
|
// debug("client_find_sock: ... %i ...\n", c->sock);
|
2000-04-03 22:13:57 +00:00
|
|
|
if (c->sock == sock) {
|
2000-03-30 20:20:41 +00:00
|
|
|
// debug("client_find_sock: ..! %i !..\n", c->sock);
|
2000-04-03 22:13:57 +00:00
|
|
|
return c;
|
|
|
|
|
}
|
|
|
|
|
} while (LL_Next (clients) == 0);
|
2000-03-30 20:20:41 +00:00
|
|
|
|
2000-04-03 22:13:57 +00:00
|
|
|
debug ("client_find_sock: failed\n");
|
1999-12-09 23:15:14 +00:00
|
|
|
|
2000-04-03 22:13:57 +00:00
|
|
|
return NULL;
|
1999-12-09 23:15:14 +00:00
|
|
|
}
|