//#
//# Corba Time Server
//# $Revision: 1.1 $
//# Copyright 2004 by Eric Y. Theriault
//# All Rights Reserved.
//# http://www.eyt.ca/CORBA
//#
using System;
using System.Runtime.Remoting;
using System.Runtime.Remoting.Services;
using System.Runtime.Remoting.Channels;
using Ch.Elca.Iiop;
using Ch.Elca.Iiop.Services;
using omg.org.CosNaming;
namespace ca.eyt.corba
{
///
/// Multicast Service.
///
///
/// For more information on Multicasting, please see Chapter 21 [549]
/// of W. Richard Stevens, Bill Fenner, and Andrew M. Rudoff's UNIX
/// Network Programming: Volume 1: The Sockets Networking API--Third
/// Edition, Addison-Wesley, 2004.
///
class MulticastIORServer
{
///
/// Port to multicast on. This number is random.
///
public const int MulticastPort = 7007;
///
/// Address to multicast to. The default is link-local, which is
/// generally OK, but in the presence of a segmented network with
/// routers, this address and the TTL will have to be changed.
///
public const String MulticastAddress = "224.0.0.1";
///
/// This is the message that is multicasted to discover the new
/// server.
///
public const String MulticastDiscoverServer = "DiscoverIOR";
///
/// IOR to Multicast
///
private string ior;
///
/// Multicast Socket
///
private MulticastSocket mcast;
///
/// Thread Reference.
///
System.Threading.Thread thread;
///
/// Create the service to answer to inbound Multicasts
///
/// IOR of NameService
public MulticastIORServer( String ior )
{
this.ior = ior;
// Please note that a real implementation would provide options
// to set the bind address, Time To Live, etc., but this is
// simply to demonstrate the functionality.
mcast = new MulticastSocket( MulticastPort );
mcast.bind();
mcast.joinGroup( MulticastAddress );
}
///
/// Executes the thread.
///
protected void run()
{
while ( true ) {
try {
// Create a received String
System.Net.IPEndPoint address = null;
string receivedString = mcast.receive( ref address );
// If the packet is good, reply
//
// In a real application, a checksum or something could
// be used to validate the message, and the reply should
// contain a more verbose message.
if ( receivedString.StartsWith( MulticastDiscoverServer ) ) {
// Unicast back to the sender the ior string.
mcast.send( address, ior );
}
}
catch ( Exception e ) {
// Log the message.
System.Console.WriteLine( "Exception: " + e.Message );
System.Console.WriteLine( e.StackTrace.ToString() );
}
}
}
///
/// Starts a thread.
///
public void start()
{
thread = new System.Threading.Thread( new System.Threading.ThreadStart( run ) );
thread.Start();
}
}
///
/// Implements a CORBA server to provide the local time.
///
public class TimeServer
{
///
/// Server Port
///
const int ServerPort = 7832;
///
/// Main.
///
[System.STAThread]
public static void Main( string[] args )
{
try {
String iorFile = "time.ior";
// Create and Initialize the ORB
CorbaInit orb = CorbaInit.GetInit();
// Register server channel
IiopChannel channel = new IiopChannel( ServerPort );
ChannelServices.RegisterChannel( channel );
// Create the time Servant and register it.
ca.eyt.corba.TimeImpl timeImpl = new ca.eyt.corba.TimeImpl();
// Create the object reference.
string objectURI = "Time";
ObjRef objrefWellKnown = RemotingServices.Marshal( timeImpl, objectURI );
// Acquire the IOR for the object reference.
//TODO: There is probably a nicer way to do this.
omg.org.CORBA.OrbServices srv = omg.org.CORBA.OrbServices.GetSingleton();
String[] url = channel.GetUrlsForUri( objrefWellKnown.URI );
if ( url.Length != 1 ) {
throw new Exception( "Unexpected input: " + url.Length );
}
object obj = srv.string_to_object( url[0] );
String ior = srv.object_to_string( obj );
// Write out the file
try {
using ( System.IO.StreamWriter writer = new System.IO.StreamWriter( iorFile ) ) {
writer.WriteLine( ior );
}
} catch ( Exception e ) {
System.Console.Error.WriteLine( iorFile + " raised an exception: " + e.Message );
System.Environment.Exit( 1 );
}
// Let's get the root naming context.
NamingContext nameService = ORBHelper.resolveNameserviceReference( orb, args );
// Bind the Time object to the reference.
String Time = "Time";
NameComponent[] path = new NameComponent[] { new NameComponent( Time, "" ) };
nameService.rebind( path, timeImpl );
// Start the Multicast Server
MulticastIORServer mcast = new MulticastIORServer( srv.object_to_string( nameService ) );
mcast.start();
// Server is now up and running
System.Console.Out.WriteLine( "TimeServer is ready and waiting..." );
} catch ( System.Exception e ) {
System.Console.WriteLine( "Exception: " + e.Message );
System.Console.WriteLine( e.StackTrace.ToString() );
System.Environment.Exit( 1 );
}
}
}
}