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();
}
|