//
// 
//	Copyright (C) 2003 Hirohisa MORI <joshua@nichibun.ac.jp>
// 
//	This program is free software; you can redistribute it 
//	and/or modify it under the terms of the GLOBALBASE 
//	Library General Public License (G-LGPL) as published by 
//
//	http://www.globalbase.org/
// 
//	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.
//
//

extern "C" {

#include	<LInternetAddress.h>
#include	"memory_debug.h"
#include	"task.h"
#include	"netutils.h"
#include	"blacklist.h"
int get_xltime();
int bl_do(void * cmd);
extern SEM netutils_lock;
struct hostent * get_new_hostent();
struct hostent * search_hostent_hash(int len, char *address);
void add_to_hostent_hash(struct hostent *he);
void _ExStop(void);
void _ExRevert(void);

typedef struct gethostbyname_cmd {
	BL_CMD			cmd;
	struct hostent *	h;
} GETHOSTBYNAME_CMD;

struct hostent * _gethostbyname_rr(char * name);
int gethostbyname_rr_proc(BLACKLIST * bl,GETHOSTBYNAME_CMD * cmd);
int gethostbyname_rr_retry(BLACKLIST * bl);


struct hostent *
_gethostbyname_rr(char * name)
{
	LInternetAddress ia;
	struct hostent * ret;
	int address;
	unsigned char buf[256];
	_ExStop();
	try
	{
		c2pstrcpy(buf, name);
		ia.SetDNSAddress(buf);
		address = ia.GetIPAddress();
	}
	catch(...)
	{
		_ExRevert();
		return 0;
		goto end;
	}
	_ExRevert();

	if ( (ret = search_hostent_hash(4, (char*)&address)) )
		return ret;
		
	ret = get_new_hostent();
 	strncpy(ret->h_name, name, 256);
	*(int*)ret->h_addr = address;
	add_to_hostent_hash(ret);
end:
	return ret;
}

int
gethostbyname_rr_proc(BLACKLIST * bl,GETHOSTBYNAME_CMD * cmd)
{
unsigned int t;
	t = get_xltime();

	cmd->h = _gethostbyname_rr((char*)cmd->cmd.name);
	bl->polling_initial = 2*(get_xltime() - t);
	if ( cmd->h )
		return BLS_OK;
	return BLS_ERROR;
}

int
gethostbyname_rr_retry(BLACKLIST * bl)
{
struct hostent * h;
int ret;
unsigned int t;

	t = get_xltime();
	lock_task(netutils_lock);
	sethostent_rr(0);
	h = _gethostbyname_rr((char*)bl->name);
	if ( h )
		ret = BLS_OK;
	else	ret = BLS_ERROR;
	endhostent_rr();
	unlock_task(netutils_lock,"new_connect");
	return ret;
}

HOST_ENTRY *
intr_gethostbyname_rr(char * name)
{
GETHOSTBYNAME_CMD c;
HOST_ENTRY * machine2he_v4(struct hostent*);
	c.cmd.name = name;
	c.cmd.name_len = strlen(name)+1;
	c.cmd.retry = (int(*)())gethostbyname_rr_retry;
	c.cmd.proc = (int(*)())gethostbyname_rr_proc;
	c.cmd.type = BLT_RESOLVE;
	c.h = 0;
	bl_do(&c);
	return machine2he_v4(c.h);
}

} // extern "C"