summaryrefslogtreecommitdiff
path: root/Bus/Ivy/IvyWatcher.cxx
blob: 4cbf604b44cd35e09b8bfba5227757de59802e22 (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
// IvyWatcher.cpp : implementation file
//

#include "IvyStdAfx.h"


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

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


#define VERSION 3

IvyWatcher::IvyWatcher(Ivy * bus)
{
	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 !!!
	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() );
	}
}
void IvyWatcher::stop()
{
	Close();
}