diff -updwrN LFSLib-0.11b/AbstractLfsPacketReader.cs LFSLib/AbstractLfsPacketReader.cs --- LFSLib-0.11b/AbstractLfsPacketReader.cs 2006-05-19 17:09:32.000000000 +1000 +++ LFSLib/AbstractLfsPacketReader.cs 2006-06-19 17:47:42.000000000 +1000 @@ -43,6 +43,7 @@ namespace FullMotion.LiveForSpeed Thread listenerThread; Socket listener; int port; + UdpClient connection; #endregion #region Constructors ########################################################################## @@ -66,6 +67,22 @@ namespace FullMotion.LiveForSpeed listenerThread.Abort(); } } + + public AbstractLfsPacketReader(UdpClient c) { + connection = c; + try + { + //Starting the UDP Server thread. + listenerThread = new Thread(new ThreadStart(Listen)); + listenerThread.Start(); + log.Debug("Started Listener Thread on port "+this.port); + } + catch (Exception e) + { + log.Debug("Listener Thread unable to start",e); + listenerThread.Abort(); + } + } #endregion #region Properties ############################################################################ @@ -76,11 +93,15 @@ namespace FullMotion.LiveForSpeed { try { + if (connection == null) { IPEndPoint ipep = new IPEndPoint(IPAddress.Any, this.port); listener = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp); - + //listener.ExclusiveAddressUse = false; listener.Bind(ipep); + } else { + listener = connection.Client; + } log.Debug("Listening..."); @@ -260,10 +281,13 @@ namespace FullMotion.LiveForSpeed public void Stop() { log.Debug("shutting down"); + try { listener.Shutdown(SocketShutdown.Both); listener.Close(); + } catch (Exception) { } listenerThread.Abort(); listenerThread.Join(); + log.Debug("shut down"); } #endregion Binary files LFSLib-0.11b/bin/Debug/LFSLib.dll and LFSLib/bin/Debug/LFSLib.dll differ Binary files LFSLib-0.11b/bin/Debug/LFSLib.pdb and LFSLib/bin/Debug/LFSLib.pdb differ diff -updwrN LFSLib-0.11b/InSim/Configuration.cs LFSLib/InSim/Configuration.cs --- LFSLib-0.11b/InSim/Configuration.cs 2006-05-18 09:40:56.000000000 +1000 +++ LFSLib/InSim/Configuration.cs 2006-06-19 17:39:25.000000000 +1000 @@ -41,6 +41,8 @@ namespace FullMotion.LiveForSpeed.InSim #region Constants ############################################################################# private const string DEFAULT_HOST = "127.0.0.1"; + private const string RELAY_HOST = "isrelay.liveforspeed.net"; + private const int RELAY_PORT = 47474; private const int DEFAULT_HOST_PORT = 30000; private const int DEFAULT_REPLY_PORT = 29999; private const int DEFAULT_NODE_INTERVAL = 0; @@ -60,6 +62,9 @@ namespace FullMotion.LiveForSpeed.InSim data.InSim.Port = DEFAULT_REPLY_PORT; data.InSim.TrackingInterval = DEFAULT_NODE_INTERVAL; data.InSim.RaceTrackType = RaceTrackType.NoTracking; + data.InSim.UseRelay = false; + data.InSim.RelayHost = RELAY_HOST; + data.InSim.RelayHostPort = RELAY_PORT; } #endregion @@ -107,6 +112,28 @@ namespace FullMotion.LiveForSpeed.InSim set { data.Host.Address = value; } } + + public string LFSRelayHost + { + get { return data.InSim.RelayHost; } + set { data.InSim.RelayHost = value; } + } + + public int LFSRelayHostPort + { + get { return data.InSim.RelayHostPort; } + set { data.InSim.RelayHostPort = value; } + } + + /// + /// Whether to use the insim relay to connect to the host + /// + public bool UseRelay + { + get { return data.InSim.UseRelay; } + set { data.InSim.UseRelay = value; } + } + /// /// The port to hit on the LFS host /// @@ -201,6 +228,15 @@ namespace FullMotion.LiveForSpeed.InSim } /// + /// The hostname to connect to for the insim relay + /// + public string Hostname + { + get { return data.InSim.RelayHostName; } + set { data.InSim.RelayHostName = value; } + } + + /// /// The number of hundredths between OutSim messages sent by the host. If 0, OutSim is not /// initialized. OutSim messages arrive via the same port as InSim and are accessible via events on /// @@ -436,6 +472,26 @@ namespace FullMotion.LiveForSpeed.InSim /// [XmlAttribute("warnings")] public bool WarningsOff; + /// + /// Don't access directly to set configuration + /// + [XmlAttribute("relay")] + public bool UseRelay; + /// + /// Don't access directly to set configuration + /// + [XmlAttribute("relayhost")] + public string RelayHost; + /// + /// Don't access directly to set configuration + /// + [XmlAttribute("relayhostport")] + public int RelayHostPort; + /// + /// Don't access directly to set configuration + /// + [XmlAttribute("relayhostport")] + public string RelayHostName; } /// diff -updwrN LFSLib-0.11b/InSim/Events/Message.cs LFSLib/InSim/Events/Message.cs --- LFSLib-0.11b/InSim/Events/Message.cs 2006-05-16 21:24:58.000000000 +1000 +++ LFSLib/InSim/Events/Message.cs 2006-06-19 17:39:25.000000000 +1000 @@ -23,6 +23,7 @@ using log4net; using FullMotion.LiveForSpeed.InSim.Messages; using FullMotion.LiveForSpeed.InSim.PacketInfo; using FullMotion.LiveForSpeed.Util; +using System.Text.RegularExpressions; namespace FullMotion.LiveForSpeed.InSim.Events { diff -updwrN LFSLib-0.11b/InSim/InSimHandler.cs LFSLib/InSim/InSimHandler.cs --- LFSLib-0.11b/InSim/InSimHandler.cs 2006-05-18 09:16:18.000000000 +1000 +++ LFSLib/InSim/InSimHandler.cs 2006-06-19 17:39:25.000000000 +1000 @@ -20,6 +20,7 @@ using System; using System.Threading; using System.Xml; +using System.Net.Sockets; using log4net; using FullMotion.LiveForSpeed.InSim.Exceptions; using FullMotion.LiveForSpeed.InSim.Messages; @@ -78,6 +79,7 @@ namespace FullMotion.LiveForSpeed.InSim private HandlerState state = HandlerState.New; private bool asyncEventHandling; private int initWait; + private Thread relayAlive; #endregion #region Constructors ########################################################################## @@ -337,19 +339,36 @@ namespace FullMotion.LiveForSpeed.InSim Initialize(10); } + public void KeepRelayAlive() { + while (true) { + Thread.Sleep(19000); + writer.Send(new MsgKeepAlive()); + } + } /// /// Initialize the connection to the LFS Host. May throw one of the following exceptions: , , or /// /// Maximum seconds to wait for initialization to complete. A value of 0 waits indefinitely. public void Initialize(int wait) { + UdpClient c; if( state == HandlerState.Connected ) { throw new InSimHandlerException.AlreadyInitialized(); } log.Debug("Initializing"); + if (configuration.UseRelay) { + writer = new InSimWriter(configuration.LFSRelayHost, configuration.LFSRelayHostPort); + writer.RelayConnect(); + writer.RelayConnectHost(configuration.Hostname, configuration.AdminPass); + c = writer.getConnection(); + reader = InSimReader.GetReader(c); + relayAlive = new Thread(new ThreadStart(KeepRelayAlive)); + relayAlive.Start(); + } else { writer = new InSimWriter(configuration.LFSHost, configuration.LFSHostPort); reader = InSimReader.GetReader(configuration.ReplyPort); + } SubscribeToReaderEvents(); writer.Send(configuration.GetInitMessage()); if( wait == 0 ) @@ -360,7 +379,16 @@ namespace FullMotion.LiveForSpeed.InSim { initWait = wait*1000; } + try { CheckVersion(); + } catch (InSimHandlerException.NoVersion) { + if (relayAlive != null) { + relayAlive.Abort(); + relayAlive.Join(); + } + reader.Stop(); //this is the wrong way to fix this, but this non connection kind of error really should have happened a long time ago. + throw new InSimHandlerException.NotConnected(); + } CheckState(); CheckForKeepAlive(); CheckForRaceTracking(); @@ -683,6 +711,10 @@ namespace FullMotion.LiveForSpeed.InSim public void Close() { CheckConnection(); + if (relayAlive != null) { + relayAlive.Abort(); + relayAlive.Join(); + } writer.SendClose(); state = HandlerState.Closed; reader.Stop(); diff -updwrN LFSLib-0.11b/InSim/InSimReader.cs LFSLib/InSim/InSimReader.cs --- LFSLib-0.11b/InSim/InSimReader.cs 2006-05-16 21:25:00.000000000 +1000 +++ LFSLib/InSim/InSimReader.cs 2006-06-19 17:39:25.000000000 +1000 @@ -45,6 +45,10 @@ namespace FullMotion.LiveForSpeed.InSim { return (IInSimReader)new InSimReader(port); } + static public IInSimReader GetReader(UdpClient c) + { + return (IInSimReader)new InSimReader(c); + } #endregion #region Member Variables ###################################################################### @@ -56,6 +60,11 @@ namespace FullMotion.LiveForSpeed.InSim { log.Debug("InSimReader started"); } + private InSimReader(UdpClient c) + : base(c) + { + log.Debug("InSimReader started"); + } #endregion #region Properties ############################################################################ diff -updwrN LFSLib-0.11b/InSim/InSimWriter.cs LFSLib/InSim/InSimWriter.cs --- LFSLib-0.11b/InSim/InSimWriter.cs 2006-05-16 21:25:00.000000000 +1000 +++ LFSLib/InSim/InSimWriter.cs 2006-06-19 17:39:25.000000000 +1000 @@ -44,6 +44,7 @@ namespace FullMotion.LiveForSpeed.InSim /// /// /// + public InSimWriter(string server, int port) { try @@ -55,6 +56,7 @@ namespace FullMotion.LiveForSpeed.InSim throw new InSim.Exceptions.InSimHandlerException.ConnectionFailed(e); } } + #endregion #region Properties ############################################################################ @@ -71,6 +73,10 @@ namespace FullMotion.LiveForSpeed.InSim message.Send(this.connection); } + public UdpClient getConnection() { + return connection; + } + /// /// Send a MsgClose /// @@ -111,6 +117,29 @@ namespace FullMotion.LiveForSpeed.InSim this.Send(textMsg); } + /// + /// Connects to the insim relay system + /// + public void RelayConnect() + { + MsgRelayConnect relayMsg = new MsgRelayConnect(); + relayMsg.Connect = true; + relayMsg.GuaranteedDelivery = true; + relayMsg.GetHostList = false; + relayMsg.NoMci = true; + this.Send(relayMsg); + } + /// + /// Send a MsgRelayConnectHost. Connects to a host via relay. + /// + public void RelayConnectHost(string host, string adminPass) + { + MsgRelayConnectHost relayMsg = new MsgRelayConnectHost(); + relayMsg.HostName = host; + relayMsg.AdminPass = adminPass; + this.Send(relayMsg); + } + #endregion } } diff -updwrN LFSLib-0.11b/InSim/Messages/MsgRelayConnect.cs LFSLib/InSim/Messages/MsgRelayConnect.cs --- LFSLib-0.11b/InSim/Messages/MsgRelayConnect.cs 1970-01-01 10:00:00.000000000 +1000 +++ LFSLib/InSim/Messages/MsgRelayConnect.cs 2006-06-19 17:39:25.000000000 +1000 @@ -0,0 +1,88 @@ +/* ------------------------------------------------------------------------- * + * Copyright (C) 2005,2006 Arne Claassen + * + * Arne Claassen + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * ------------------------------------------------------------------------- */ +using System; +using System.Text; +using System.Net; +using System.Net.Sockets; +using log4net; +using FullMotion.LiveForSpeed.InSim.PacketInfo; +using FullMotion.LiveForSpeed.Util; + +namespace FullMotion.LiveForSpeed.InSim.Messages +{ + /// + /// Summary description for Init. + /// + internal class MsgRelayConnect : IClientMessage + { + #region Static Members ######################################################################## + private static readonly ILog log = LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); + #endregion + + #region Member Variables ###################################################################### + RelayInit packet; + #endregion + + #region Constructors ########################################################################## + internal MsgRelayConnect() + { + packet = new RelayInit(); + packet.Id = PacketId.RelayInit; + } + #endregion + + public bool Connect + { + get { return (packet.Flags&RelayInitFlags.Connect)== RelayInitFlags.Connect; } + set { packet.Flags = (value)?packet.Flags|RelayInitFlags.Connect:packet.Flags&~RelayInitFlags.Connect; } + } + + public bool GuaranteedDelivery + { + get { return (packet.Flags&RelayInitFlags.Guarantee)== RelayInitFlags.Guarantee; } + set { packet.Flags = (value)?packet.Flags|RelayInitFlags.Guarantee:packet.Flags&~RelayInitFlags.Guarantee; } + } + + public bool GetHostList + { + get { return (packet.Flags&RelayInitFlags.HostList)==RelayInitFlags.HostList; } + set { packet.Flags = (value)?packet.Flags|RelayInitFlags.HostList:packet.Flags&~RelayInitFlags.HostList; } + } + + public bool NoMci + { + get { return (packet.Flags&RelayInitFlags.NoMci)==RelayInitFlags.NoMci; } + set { packet.Flags = (value)?packet.Flags|RelayInitFlags.NoMci:packet.Flags&~RelayInitFlags.NoMci; } + } + + #region IClientMessage Members + public void Send(UdpClient lfsConnection) + { + byte[] lfsPacket = packet.GetBytes(); + lfsConnection.Send(lfsPacket,lfsPacket.Length); + } + + public InSimId GetId() + { + return packet.Id; + } + #endregion + } +} diff -updwrN LFSLib-0.11b/InSim/Messages/MsgRelayConnectHost.cs LFSLib/InSim/Messages/MsgRelayConnectHost.cs --- LFSLib-0.11b/InSim/Messages/MsgRelayConnectHost.cs 1970-01-01 10:00:00.000000000 +1000 +++ LFSLib/InSim/Messages/MsgRelayConnectHost.cs 2006-06-19 17:39:25.000000000 +1000 @@ -0,0 +1,140 @@ +/* ------------------------------------------------------------------------- * + * Copyright (C) 2005,2006 Arne Claassen + * + * Arne Claassen + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * ------------------------------------------------------------------------- */ +using System; +using System.Text; +using System.Net; +using System.Net.Sockets; +using log4net; +using FullMotion.LiveForSpeed.InSim.PacketInfo; +using FullMotion.LiveForSpeed.Util; + +namespace FullMotion.LiveForSpeed.InSim.Messages +{ + /// + /// Summary description for Init. + /// + internal class MsgRelayConnectHost : IClientMessage + { + #region Static Members ######################################################################## + private static readonly ILog log = LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); + #endregion + + #region Member Variables ###################################################################### + RelayConnectHost packet; + #endregion + + #region Constructors ########################################################################## + internal MsgRelayConnectHost() + { + packet = new RelayConnectHost(); + packet.Id = PacketId.RelayConnectHost; + } + #endregion + + + public string AdminPass + { + get + { + return Byte2String.GetString( packet.AdminPass ); + } + set + { + if( value == null ) + { + packet.AdminPass = new byte[16]; + } + else if( value.Length > 16 ) + { + throw new ArgumentException("Admin Password can not be longer than 16 characters"); + } + else + { + packet.AdminPass = new byte[16]; + byte[] bytes = Encoding.ASCII.GetBytes(value); + bytes.CopyTo(packet.AdminPass,0); + } + } + } + + public string SpectatorPass + { + get + { + return Byte2String.GetString( packet.SpecPass ); + } + set + { + if( value == null ) + { + packet.SpecPass = new byte[24]; + } + else if( value.Length > 24 ) + { + throw new ArgumentException("Spectator Password can not be longer than 16 characters"); + } + else + { + packet.SpecPass = new byte[24]; + byte[] bytes = Encoding.ASCII.GetBytes(value); + bytes.CopyTo(packet.SpecPass,0); + } + } + } + + public string HostName + { + get + { + return Byte2String.GetString( packet.Hostname ); + } + set + { + if( value == null ) + { + packet.Hostname = new byte[32]; + } + else if( value.Length > 32 ) + { + throw new ArgumentException("Hostname can not be longer than 16 characters"); + } + else + { + packet.Hostname = new byte[32]; + byte[] bytes = Encoding.ASCII.GetBytes(value); + bytes.CopyTo(packet.Hostname,0); + } + } + } + + #region IClientMessage Members + public void Send(UdpClient lfsConnection) + { + byte[] lfsPacket = packet.GetBytes(); + lfsConnection.Send(lfsPacket,lfsPacket.Length); + } + + public InSimId GetId() + { + return packet.Id; + } + #endregion + } +} diff -updwrN LFSLib-0.11b/InSim/PacketInfo/PacketId.cs LFSLib/InSim/PacketInfo/PacketId.cs --- LFSLib-0.11b/InSim/PacketInfo/PacketId.cs 2006-05-06 11:37:32.000000000 +1000 +++ LFSLib/InSim/PacketInfo/PacketId.cs 2006-06-19 17:39:25.000000000 +1000 @@ -28,6 +28,10 @@ namespace FullMotion.LiveForSpeed.InSim. { public const string IN_SIM_INIT = "ISI"; public static InSimId InSimInit = new InSimId(IN_SIM_INIT); + public const string RELAY_INIT = "CCN"; + public static InSimId RelayInit = new InSimId(RELAY_INIT); + public const string RELAY_CONNECT_HOST = "HOS"; + public static InSimId RelayConnectHost = new InSimId(RELAY_CONNECT_HOST); public const string IN_SIM_VERSION = "VER"; public static InSimId InSimVersion = new InSimId(IN_SIM_VERSION); public const string IN_SIM_CLOSE = "ISC"; diff -updwrN LFSLib-0.11b/InSim/PacketInfo/RelayConnectHost.cs LFSLib/InSim/PacketInfo/RelayConnectHost.cs --- LFSLib-0.11b/InSim/PacketInfo/RelayConnectHost.cs 1970-01-01 10:00:00.000000000 +1000 +++ LFSLib/InSim/PacketInfo/RelayConnectHost.cs 2006-06-19 17:39:25.000000000 +1000 @@ -0,0 +1,73 @@ +/* ------------------------------------------------------------------------- * + * Copyright (C) 2005,2006 Arne Claassen + * + * Arne Claassen + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * ------------------------------------------------------------------------- */ +using System; + +namespace FullMotion.LiveForSpeed.InSim.PacketInfo +{ + /// + /// UDP packet to initialise the InSim system + /// + internal struct RelayConnectHost : IlfsSendPacket + { + public InSimId Id; // CCN + zero + public byte[] Hostname; //32 + public byte[] AdminPass; //16 + public byte[] SpecPass; //24 + + #region IlfsPacket Members + public byte[] GetBytes() + { + byte[] bytes = new byte[76]; + + int position = 0; + byte[] buffer = this.Id.GetBytes(); + int length = buffer.Length; + Array.Copy(buffer,0,bytes,position,length); + + position += length; + + if( Hostname != null ) + { + buffer = Hostname; + length = buffer.Length; + Array.Copy(buffer,0,bytes,position,length); + } + position += 32; + + if( SpecPass != null ) + { + buffer = SpecPass; + length = buffer.Length; + Array.Copy(buffer,0,bytes,position,length); + } + position += 24; + + if( AdminPass != null ) + { + buffer = AdminPass; + length = buffer.Length; + Array.Copy(buffer,0,bytes,position,length); + } + + return bytes; + } + #endregion + } +} diff -updwrN LFSLib-0.11b/InSim/PacketInfo/RelayInit.cs LFSLib/InSim/PacketInfo/RelayInit.cs --- LFSLib-0.11b/InSim/PacketInfo/RelayInit.cs 1970-01-01 10:00:00.000000000 +1000 +++ LFSLib/InSim/PacketInfo/RelayInit.cs 2006-06-19 17:39:25.000000000 +1000 @@ -0,0 +1,72 @@ +/* ------------------------------------------------------------------------- * + * Copyright (C) 2005,2006 Arne Claassen + * + * Arne Claassen + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * ------------------------------------------------------------------------- */ +using System; + +namespace FullMotion.LiveForSpeed.InSim.PacketInfo +{ + /// + /// UDP packet to initialise the InSim system + /// + internal struct RelayInit : IlfsSendPacket + { + public InSimId Id; // CCN + zero + public RelayInitFlags Flags; // Bit flags for options - see below + + #region IlfsPacket Members + public byte[] GetBytes() + { + byte[] bytes = new byte[8]; + + int position = 0; + byte[] buffer = this.Id.GetBytes(); + int length = buffer.Length; + Array.Copy(buffer,0,bytes,position,length); + position += length; + bytes[position++] = (byte)Flags; + return bytes; + } + #endregion + } + + /// + /// Flags in InSimInit packet : set the relevant bits to turn on the option + /// + [Flags()] internal enum RelayInitFlags : byte + { + /// + /// turns on race tracking + /// + Connect = 1, // bit 0 : connect + /// + /// turns on guaranteed delivery + /// + HostList = 2, // bit 1 : if set, receives a host list on connect + /// + /// use MSS, not MSO for user messages + /// + NoMci = 4, // bit 2 : if set, won't receive MCI packets + /// + /// turns off packet warnings + /// + Guarantee = 8, // bit 3 : turns on guaranteed delivery + } + + +}