/*-*-linux-c-*-*/

/*
 *  gnewtellium - Newtella for Unix
 *  Copyright (C) 2001 Elias Athanasopoulos
 *
 *  This program 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.
 *
 *  This program 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 this program; if not, write to the Free Software
 *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 */

#include <string.h>

#include "route.h"
#include "memory.h"
#include "connection.h"
#include "gnutella.h"

int route_msg_add(struct message *rmsg, gchar *dataload)
{
	struct message *msg;
	gchar *data;

	if (g_slist_length(rmessages) == ROUTE_CACHE_SIZE) {
		msg = (struct message *) rmessages->data;

		rmessages = g_slist_remove(rmessages, msg);

		newtella_free(msg->head);
		newtella_free(msg);
	}


	rmsg->head->ttl--;
	rmsg->head->hops++;

	/* attach header to msg */
	data = newtella_malloc(rmsg->length);
	GNUTELLA_HDR_ATTACH(data, rmsg->head);

	if (dataload)
		memcpy(data+GN_HEADER_SIZE, dataload, rmsg->head->length);

	switch (rmsg->policy) {
	case RP_ALL:
		con_send_to_all(data, rmsg->length, 1);
		break;
	case RP_ONLY_TO:
		con_send_packet(rmsg->con,
				data, rmsg->length, 1);
		break;
	case RP_ALL_EXC:
		con_send_ex_one(rmsg->con,
				data, rmsg->length, 1);
		break;
	default:
		break;
	}

	rmessages = g_slist_append(rmessages, rmsg);

	newtella_free(data);

	return 1;
}

struct message *route_msg_find(gchar *mguid, gnutella_function f, gint len)
{
	GSList *l;
	struct message *msg;

	for (l = rmessages; l; l = l->next) {
		msg = (struct message *) l->data;

		if (guidcmp(msg->head->guid, mguid) && (msg->head->f == f)) {
			if (!len || (msg->head->length == len))
				return msg;
		}
	}

	return NULL;
}

struct message *route_msg_rs_find(gchar *pguid)
{
	/* finds a result set type of message
	   based on the guid used for push.
	*/
	GSList *l;
	struct message *msg;

	for (l = rmessages; l; l = l->next) {
		msg = (struct message *) l->data;

		if (msg->head->f != GNUTELLA_INITRESPONSE)
			continue;
		else {
			if (guidcmp(pguid, msg->guid))
				return msg;
		}
	}

	return NULL;
}


/* debug */
int route_msg_dump(struct message *msg)
{
	g_print("Route: f: %d ttl: %d hops: %d length: %d\n",
		msg->head->f,
		msg->head->ttl,
		msg->head->hops,
		msg->head->length);

	return 1;
}

int route_table_dump(void)
{
	GSList *l;
	struct message *msg;

	for (l = rmessages; l; l = l->next) {
		msg = (struct message *) l->data;
		g_print("----\n");
		guiddump(msg->head->guid);
		g_print("----\n");
	}

	return 1;
}
