/* $Id: server.c,v 1.5 1999/03/10 07:58:04 boyns Exp $ */
/*
* Copyright (C) 1993-99 Mark R. Boyns <boyns@doit.org>
*
* This file is part of rplay.
*
* rplay is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* rplay is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with rplay; see the file COPYING. If not, write to the
* Free Software Foundation, Inc.,
* 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
*/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include "rplay.h"
#include <sys/param.h>
#include <sys/types.h>
#include <netdb.h>
#include <stdlib.h>
#ifdef HAVE_STRING_H
#include <string.h>
#endif
#include "rplayd.h"
#include "server.h"
#include "connection.h"
#include "buffer.h"
BUFFER *server_list = NULL;
SERVER *servers = NULL;
static time_t server_read_time;
#ifdef __STDC__
void
server_read(char *filename)
#else
void
server_read(filename)
char *filename;
#endif
{
FILE *fp;
char buf[BUFSIZ], *p;
char line[RPTP_MAX_LINE];
struct hostent *hp, *local_hp;
unsigned long addr, local_addr;
struct sockaddr_in sin;
int port, n;
SERVER **s = &servers;
BUFFER *b;
server_read_time = time(0);
fp = fopen(filename, "r");
if (fp == NULL)
{
/*
* I guess it's ok to not have any servers.
*/
report(REPORT_NOTICE, "warning: cannot open %s\n", filename);
return;
}
local_hp = gethostbyname(hostname);
if (local_hp == NULL)
{
report(REPORT_ERROR, "server_read: %s unknown host?!\n", hostname);
done(1);
}
memcpy((char *) &local_addr, (char *) local_hp->h_addr, local_hp->h_length);
b = buffer_create();
strcpy(b->buf, "+message=\"servers\"\r\n");
b->nbytes += strlen(b->buf);
b->status = BUFFER_KEEP;
server_list = b;
while (fgets(buf, sizeof(buf), fp))
{
switch (buf[0])
{
case '#':
case ' ':
case '\t':
case '\n':
continue;
}
p = strchr(buf, '\n');
if (p)
{
*p = '\0';
}
p = strchr(buf, ':');
if (p)
{
*p = '\0';
port = atoi(p + 1);
}
else
{
port = RPTP_PORT;
}
addr = inet_addr(buf);
memset((char *) &sin, 0, sizeof(sin));
if (addr == 0xffffffff)
{
hp = gethostbyname(buf);
if (hp == NULL)
{
report(REPORT_NOTICE, "warning: %s unknown host in %s\n", buf, filename);
continue;
}
memcpy((char *) &sin.sin_addr.s_addr, (char *) hp->h_addr, hp->h_length);
}
else
{
memcpy((char *) &sin.sin_addr.s_addr, (char *) &addr, sizeof(addr));
}
if (memcmp((char *) &sin.sin_addr.s_addr, (char *) &local_addr, sizeof(local_addr)) == 0)
{
/*
* ignore the server if it's the local host
*/
continue;
}
*s = (SERVER *) malloc(sizeof(SERVER));
if (*s == NULL)
{
report(REPORT_ERROR, "server_read: out of memory\n");
done(1);
}
sin.sin_family = AF_INET;
sin.sin_port = htons(port);
SNPRINTF(SIZE(line, sizeof(line)), "host=%s port=%d\r\n", buf, port);
n = strlen(line);
if (b->nbytes + n > BUFFER_SIZE)
{
b->next = buffer_create();
b = b->next;
b->status = BUFFER_KEEP;
}
SNPRINTF(SIZE(b->buf + b->nbytes, BUFFER_SIZE - b->nbytes), line);
b->nbytes += n;
(*s)->sin = sin;
s = &(*s)->next;
report(REPORT_DEBUG, "server %s port %d\n", inet_ntoa(sin.sin_addr), port);
}
*s = NULL;
fclose(fp);
if (b->nbytes + 3 > BUFFER_SIZE)
{
b->next = buffer_create();
b = b->next;
b->status = BUFFER_KEEP;
}
SNPRINTF(SIZE(b->buf + b->nbytes, BUFFER_SIZE - b->nbytes), ".\r\n");
b->nbytes += 3;
}
#ifdef __STDC__
void
server_reread(char *filename)
#else
void
server_reread(filename)
char *filename;
#endif
{
BUFFER *b, *bb;
SERVER *s, *ss;
report(REPORT_DEBUG, "re-reading servers\n");
/*
* Free the server_list buffers.
*/
for (b = server_list; b; bb = b, b = b->next, bb->status = BUFFER_FREE, buffer_destroy(bb)) ;
/*
* Free the servers list.
*/
for (s = servers; s; ss = s, s = s->next, free((char *) ss)) ;
server_list = NULL;
servers = NULL;
server_read(filename);
}
#ifdef __STDC__
void
server_stat(char *filename)
#else
void
server_stat(filename)
char *filename;
#endif
{
if (modified(filename, server_read_time))
{
server_reread(filename);
}
}