From 013f8cd1dfcb7d7291f7c0a1f973d27b9288a435 Mon Sep 17 00:00:00 2001 From: chatty Date: Tue, 28 Nov 2000 17:07:44 +0000 Subject: New bus address scheme --- comm/BusAccess.cc | 102 +++++++++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 94 insertions(+), 8 deletions(-) (limited to 'comm/BusAccess.cc') 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 #include #include +#include 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); -- cgit v1.1