// Common, group Communication
// Copyright 2003 Alexander Liss

//     	Declaration of classes
//	ASocketConnector

#ifndef __ASOCKETCONNECTOR_H__
#define __ASOCKETCONNECTOR_H__

#include <string.h>
#include "array.h"
#include "ASocket.h"
#include "AMutex.h"
#include "strbuf.h"


	// ASocketConnector
	// addresses of higher priority are tried first
	// addresses of same priority are reordered pseudo-randomly
	// random_seed defines the chain of pseudo-random orderings
	// watch that it is different for different instances of a process

class ASocketConnector
{
public:
	StrBuffer id; // service id, internal id

ASocketConnector();

int set_timeout(unsigned z){timeout=z; return 0;}
int adjust_priority(){adjust=true; return 0;}

int bind_to_address(const IPAddress& address, unsigned short port=0)
{ bind_address=address; bind_port=port; bound=true; return 0; }

int bind_to_card(unsigned card_number=0, unsigned short port=0);

int add(const char * address,const char * port, int priority=0);
int add(const IPAddress& address,const char * port, int priority=0);
int add(const IPAddress& address,unsigned port, int priority=0);
int add(const IPSocketAddress& address_port, int priority=0);

int add_name(const char * name,const char * port, int priority=0,unsigned name_size_limit=255);

int reset_list(unsigned Random_seed=0);
unsigned list_size(){return addresses.in_object();}

int connect(ASocket&);

private:

	struct InputNodeAddress
	{
		IPSocketAddress address; 
		int priority;
	 InputNodeAddress():priority(0){}
	 InputNodeAddress(const IPSocketAddress& Address,int Priority):
	 address(Address),priority(Priority){}	
	};
	
	struct InputNodeName
	{
		char* name;
		unsigned port;
		int priority;
		// results of a lookup - cache
		SimpleCollector< IPAddress, SimpleArray<IPAddress> > addresses;
		
	 InputNodeName():name(0),port(0),priority(0){}
	 InputNodeName(const char* Name, unsigned Port,int Priority):
	 port(Port),priority(Priority){set_name(Name);}	
	 ~InputNodeName(){delete name;}
	 int set_name(const char* Name)
	 { delete name; int size=strlen(Name); name = new char[size+1]; 
	   name[size]=0; memcpy(name,Name,size); return 0;
	 }
	};
	
	struct Node
	{ 
		IPSocketAddress address; 
		int priority;
		unsigned failure_count; // first success restores to zero
		unsigned index; 
		
	 Node():priority(0),failure_count(0),index(0){}
	 Node(const IPSocketAddress& Address,int Priority):
	 address(Address),priority(Priority),failure_count(0),index(0){}
	};
	
	unsigned timeout;
	SimpleCollector< InputNodeAddress, SimpleArray<InputNodeAddress> > input_addresses;
	SimpleCollector< InputNodeName, SimpleArray<InputNodeName> > input_names;
	SimpleCollector< Node, SimpleArray<Node> > addresses;
	unsigned random_seed, current;
	int max_priority, min_priority;
	bool adjust;
	IPAddress bind_address;
	unsigned short bind_port;
	bool bound;
	AMutex mutex; 		// for multithereaded use
	//DNSCall dns_call;
};


#endif