summaryrefslogtreecommitdiff
path: root/comm/BusAccess.cc
diff options
context:
space:
mode:
authorchatty2000-11-28 17:07:44 +0000
committerchatty2000-11-28 17:07:44 +0000
commit013f8cd1dfcb7d7291f7c0a1f973d27b9288a435 (patch)
treea680c350a029723b3c850c8a9993efd649fe6772 /comm/BusAccess.cc
parent44d94a1a9e863dea9a2c30349fd723b3b661ded1 (diff)
downloadivy-league-013f8cd1dfcb7d7291f7c0a1f973d27b9288a435.zip
ivy-league-013f8cd1dfcb7d7291f7c0a1f973d27b9288a435.tar.gz
ivy-league-013f8cd1dfcb7d7291f7c0a1f973d27b9288a435.tar.bz2
ivy-league-013f8cd1dfcb7d7291f7c0a1f973d27b9288a435.tar.xz
New bus address scheme
Diffstat (limited to 'comm/BusAccess.cc')
-rw-r--r--comm/BusAccess.cc102
1 files changed, 94 insertions, 8 deletions
diff --git a/comm/BusAccess.cc b/comm/BusAccess.cc
index 826146a..5383e91 100644
--- a/comm/BusAccess.cc
+++ b/comm/BusAccess.cc
@@ -24,8 +24,12 @@
#include <ostream.h>
#include <regex.h>
#include <stdarg.h>
+#include <ctype.h>
int UchBusAccess::Version = 3;
+const char* const UchBusAccess::DefaultBus = "127:2010";
+const sword UchBusAccess::DefaultBusPort = 2010;
+const char* const UchBusAccess::DefaultBusNet = "127";
static int _BusDebug = 0;
@@ -407,19 +411,39 @@ UchBusAgent :: Emit (int id, const char* fmt, ...)
WriteString ("\n");
}
-UchBusAccess :: UchBusAccess (const char* name, sword port)
+UchBusAccess :: UchBusAccess (const char* name, const char* bus)
: UchDatagram (),
UchBaseSignalHandler (*UchMpx, SigInt),
Name (name),
ListenPort (0),
- BroadcastPort (port),
+ BroadcastPort (0),
Server (0),
Agents (),
IdToSubscription (256),
LocalSubscriptions ()
{
- /** set up datagram **/
- UchInetAddress* a = new UchInetAddress (ANYADDR, port);
+
+
+ /** determine network list as well as broadcast port **/
+ /* (we accept addresses such as 123.231,123.123:2000 or 123.231 or :2000) */
+
+ /* first, let's find something to parse */
+ if (!bus || !*bus)
+ bus = getenv ("IVYBUS");
+ if (!bus || !*bus)
+ bus = DefaultBus;
+
+ /* then, let's get a port number. We'll parse network list later.*/
+ sword port;
+ char* q = strchr (bus, ':');
+ if (bus && (port = atoi (q+1)))
+ BroadcastPort = port;
+ else
+ BroadcastPort = DefaultBusPort;
+
+
+ /** set up UDP broadcast socket **/
+ UchInetAddress* a = new UchInetAddress (ANYADDR, BroadcastPort);
BindTo (a);
if (!Open ()) {
perror ("Cannot open socket: ");
@@ -435,7 +459,7 @@ UchBusAccess :: UchBusAccess (const char* name, sword port)
}
if (Bind () < 0) {
- cerr << "cannot bind socket to port " << port << "\n";
+ cerr << "cannot bind socket to port " << BroadcastPort << "\n";
return;
}
// SetMode (IOReadWrite);
@@ -450,11 +474,73 @@ UchBusAccess :: UchBusAccess (const char* name, sword port)
}
ListenPort = a->Port ();
- /** emit handshake on datagram **/
+ /** broadcast handshakes on every network **/
char handshake[32];
sprintf (handshake, "%d %hu\n", Version, ListenPort);
- UchInetAddress ba (BROADCAST, BroadcastPort);
- Send ((byte*)handshake, strlen (handshake), ba);
+
+ /* if we only have a port number, resort to default value for network */
+ if (bus == q)
+ bus = DefaultBusNet;
+
+ /* parse network list and send broadcast handshakes.
+ This is long and painful but inet_aton is sloppy.
+ If someone knows other builtin routines that do that... */
+ unsigned long mask = 0xffffffff;
+ unsigned char elem = 0;
+ int numdigit = 0;
+ int numelem = 0;
+ int error = 0;
+
+ for (;;) {
+ /* address elements are up to 3 digits... */
+ if (!error && isdigit (*bus)) {
+ if (numdigit < 3 && numelem < 4) {
+ elem = 10 * elem + *bus -'0';
+ } else {
+ error = 1;
+ }
+
+ /* ... terminated by a point, a comma or a colon, or the end of string */
+ } else if (!error && (*bus == '.' || *bus == ',' || *bus == ':' || *bus == '\0')) {
+ mask = (mask ^ (0xff << (8*(3-numelem)))) | (elem << (8*(3-numelem)));
+
+ /* after a point, expect next address element */
+ if (*bus == '.') {
+ numelem++;
+
+ /* addresses are terminated by a comma or end of string */
+ } else {
+ printf ("Broadcasting on network %lx, port %d\n", mask, BroadcastPort);
+ UchInetAddress ba (mask, BroadcastPort);
+ Send ((byte*)handshake, strlen (handshake), ba);
+ numelem = 0;
+ mask = 0xffffffff;
+ }
+ numdigit = 0;
+ elem = 0;
+
+ /* recover from bad addresses at next comma or colon or at end of string */
+ } else if (*bus == ',' || *bus == ':' || *bus == '\0') {
+ fprintf (stderr, "bad broadcast address\n");
+ elem = 0;
+ numelem = 0;
+ numdigit = 0;
+ mask = 0xffffffff;
+ error = 0;
+
+ /* ignore spaces */
+ } else if (*bus == ' ') {
+
+ /* everything else is illegal */
+ } else {
+ error = 1;
+ }
+
+ /* end of string or colon */
+ if (*bus == '\0' || *bus == ':')
+ break;
+ ++bus;
+ }
/* add to main loop */
Add (UchMpx);