summaryrefslogtreecommitdiff
path: root/Ivy/IvyWatcher.cxx
blob: ab7251146f16b6dad82e0b9e6d304b76e09c74ee (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
// IvyWatcher.cpp : implementation file
//

#include "IvyStdAfx.h"


#include "IvyWatcher.h"
#include "IvyApplication.h"

/////////////////////////////////////////////////////////////////////////////
// IvyWatcher


#define VERSION 3

IvyWatcher::IvyWatcher(Ivy * bus)
{
	running = false;
	this->bus = bus;
}
IvyWatcher::~IvyWatcher()
{
}



/////////////////////////////////////////////////////////////////////////////
// IvyWatcher member functions

void IvyWatcher::OnReceive(int nErrorCode) 
{
	size_t err;
	int version;
	char buffer[2048];
	ivy::string remotehost;
	UINT remoteport;
	UINT serviceport;
	char appid[2048];
    char appname[2048];

	memset( appid, 0, sizeof( appid ) );
    memset( appname, 0, sizeof( appname ) );
        
	err = ReceiveFrom( buffer, sizeof(buffer), remotehost, remoteport );
	if ( err == SOCKET_ERROR )
		{
		TRACE("Receive Broadcast error %d\n",this->GetLastError());
		return;
		}
	if ( err < 255 ) buffer[err] ='\0';
	err = sscanf_s(buffer,"%d %u %s %[^\n]",&version, &serviceport,appid, sizeof(appid), appname,sizeof(appname));
	if ( err < 2 )
		{
		/* ignore the message */
		TRACE(" Bad Supervision message expected 'version port'\n");
		return;
		}
	if ( version != VERSION )
		{
		/* ignore the message */
		TRACE(" Bad Ivy verion number expected %d receive %d from %s:%d\n", VERSION,version, remotehost.c_str(), remoteport);
		return;
		}
	/* check if we received our own message. SHOULD ALSO TEST THE HOST */
    if ( strcmp( appid , bus->ApplicationID.c_str()) ==0 ) return;

	/* check if we receive our own message 	should test also the host */
	if ( serviceport == bus->GetApplicationPort() /*&&  remotehost == "localhost"*/) return;
	TRACE(" Broadcast de %s:%u port %u\n", remotehost.c_str(), remoteport, serviceport );
	
	/* connect to the service and send the regexp */
	IvyApplication *newapp = new IvyApplication(bus);
	// exception to catch
	newapp->Create(remotehost.c_str(), serviceport, appname );
	//	delete newapp;
	//	return;

	bus->AddApplication( newapp );
	TRACE(" Connecting to  %s:%u\n", remotehost.c_str(),  serviceport );
	
}

void IvyWatcher::start(const char *domainlist)
{
	BOOL reuse = TRUE;
	ivy::string domain;
	UINT port=0;
	// determine domain to use
	domain = bus->GetDomain( domainlist );
	
	// first find our UDP port
	size_t sep_index = domain.rfind( ':' );
	if ( sep_index != -1 )
		{
		port = atoi ( domain.substr( sep_index +1 ).c_str() );
		// supress port number from end of domain list
		domain.erase( sep_index, domain.length() - sep_index );
		}
	// create UDP receiver
	// catch exception !!!
	// if already open then CLOSE
	if ( running )
	{
		Close();
	}
	Socket(SOCK_DGRAM);
	SetSockOpt( SO_REUSEADDR, &reuse, sizeof(BOOL)  );
	Bind(port);
	StartListener();
	
	ivy::string addr;
	char hello[2048];
	int len = _snprintf_s( hello, sizeof(hello), sizeof(hello)-1, "%d %u %s %s\n", VERSION, bus->GetApplicationPort(), bus->ApplicationID.c_str(), bus->ApplicationName.c_str() );

	// send broadcast to domain list
	while ( !domain.empty() ) 
	{
	// find addr up to separator
	size_t index  = domain.find_first_of( ", \t" );
	addr = domain.substr( 0, index );
	domain.erase( 0, addr.length() +1 );
	TRACE("Ivy Broadcasting on %s:%d\n", addr.c_str(), port );
	AddMember( addr.c_str() );
	SendTo( hello, len, port, addr.c_str() );
	}
	running = true;
}
void IvyWatcher::stop()
{
	Close();
	running = false;
}