//------------------------------------------------------------- // // Shutdown() - called when execution is stopped or the // plugin instance is no longer going to be // referenced // //------------------------------------------------------------- public void Shutdown() { // keep track of interface ids we have shutdown var idList = new SortedList <string, int>(); // iterate through universetable foreach (var uE in _universeTable) { // assume multicast var id = uE.Multicast; // if unicast use psuedo id if (uE.Unicast != null) { id = "unicast"; } // if active if (!uE.Active) { continue; } // and a usable socket if (uE.Socket == null) { continue; } // if not already done if (idList.ContainsKey(id)) { continue; } // record it & shut it down idList.Add(id, 1); uE.Socket.Shutdown(SocketShutdown.Both); uE.Socket.Close(); } if (!_statisticsOption) { return; } if (_messageTexts.Length > 0) { _messageTexts.AppendLine(); } _messageTexts.AppendLine("Events: " + _eventCnt); _messageTexts.AppendLine("Total Time: " + _totalTicks + " Ticks; " + TimeSpan.FromTicks(_totalTicks).Milliseconds + " ms"); foreach (var uE in _universeTable.Where(uE => uE.Active)) { _messageTexts.AppendLine(); _messageTexts.Append((string)uE.StatsToText); } J1MsgBox.ShowMsg("Plugin Statistics:", _messageTexts.ToString(), "J1Sys E1.31 Vixen Plugin", MessageBoxButtons.OK, MessageBoxIcon.Information); }
//------------------------------------------------------------- // // Startup() - called when a sequence is executed // // // todo: // // 1) probably add error checking on all 'new' operations // and system calls // // 2) better error reporting and logging // //------------------------------------------------------------- public void Startup() { // a single socket to use for unicast (if needed) Socket unicastSocket = null; // a sortedlist containing the multicast sockets we've already done var nicSockets = new SortedList <string, Socket>(); // reload all of our xml into working objects LoadSetupNodeInfo(); // initialize plugin wide stats _eventCnt = 0; _totalTicks = 0; // initialize sequence # for E1.31 packet (should it be per universe?) _seqNum = 0; // initialize messageTexts stringbuilder to hold all warnings/errors _messageTexts = new StringBuilder(); // check for configured from/to if (_pluginChannelsFrom == 0 && _pluginChannelsTo == 0) { foreach (var uE in _universeTable) { uE.Active = false; } _messageTexts.AppendLine("Plugin Channels From/To Configuration Error!!"); } // now we need to scan the universeTable foreach (var uE in _universeTable) { // active? - check universeentry start and size if (uE.Active) { // is start out of range? if (_pluginChannelsFrom + uE.Start > _pluginChannelsTo) { _messageTexts.AppendLine("Start Error - " + uE.InfoToText); uE.Active = false; } // is size (end) out of range? if (_pluginChannelsFrom + uE.Start + uE.Size - 1 > _pluginChannelsTo) { _messageTexts.AppendLine("Start/Size Error - " + uE.InfoToText); uE.Active = false; } } // if it's still active we'll look into making a socket for it if (!uE.Active) { continue; } // if it's unicast it's fairly easy to do IPAddress ipAddress; if (uE.Unicast != null) { // is this the first unicast universe? if (unicastSocket == null) { // yes - make a new socket to use for ALL unicasts unicastSocket = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp); } // use the common unicastsocket uE.Socket = unicastSocket; // try to parse our ip address if (!IPAddress.TryParse(uE.Unicast, out ipAddress)) { // oops - bad ip, fuss and deactivate uE.Active = false; uE.Socket = null; _messageTexts.AppendLine("Invalid Unicast IP: " + uE.Unicast + " - " + uE.RowUnivToText); } else { // if good, make our destination endpoint uE.DestIPEndPoint = new IPEndPoint(ipAddress, 5568); } } // if it's multicast roll up your sleeves we've got work to do if (uE.Multicast != null) { // create an ipaddress object based on multicast universe ip rules var multicastIPAddress = new IPAddress(new byte[] { 239, 255, (byte)(uE.Universe >> 8), (byte)(uE.Universe & 0xff) }); // create an ipendpoint object based on multicast universe ip/port rules var multicastIPEndPoint = new IPEndPoint(multicastIPAddress, 5568); // first check for multicast id in nictable if (!_nicTable.ContainsKey(uE.Multicast)) { // no - deactivate and scream & yell!! uE.Active = false; _messageTexts.AppendLine("Invalid Multicast NIC ID: " + uE.Multicast + " - " + uE.RowUnivToText); } else { // yes - let's get a working networkinterface object var networkInterface = _nicTable[uE.Multicast]; // have we done this multicast id before? if (nicSockets.ContainsKey(uE.Multicast)) { // yes - easy to do - use existing socket uE.Socket = nicSockets[uE.Multicast]; // setup destipendpoint based on multicast universe ip rules uE.DestIPEndPoint = multicastIPEndPoint; } // is the interface up? else if (networkInterface.OperationalStatus != OperationalStatus.Up) { // no - deactivate and scream & yell!! uE.Active = false; _messageTexts.AppendLine("Multicast Interface Down: " + networkInterface.Name + " - " + uE.RowUnivToText); } else { // new interface in 'up' status - let's make a new udp socket uE.Socket = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp); // get a working copy of ipproperties var ipProperties = networkInterface.GetIPProperties(); // get a working copy of the ipv4interfaceproperties ipProperties.GetIPv4Properties(); // get a working copy of all unicasts var unicasts = ipProperties.UnicastAddresses; ipAddress = null; foreach (var unicast in unicasts.Where(unicast => unicast.Address.AddressFamily == AddressFamily.InterNetwork)) { ipAddress = unicast.Address; } if (ipAddress == null) { _messageTexts.AppendLine("No IP On Multicast Interface: " + networkInterface.Name + " - " + uE.InfoToText); } else { // set the multicastinterface option uE.Socket.SetSocketOption(SocketOptionLevel.IP, SocketOptionName.MulticastInterface, ipAddress.GetAddressBytes()); // set the multicasttimetolive option uE.Socket.SetSocketOption(SocketOptionLevel.IP, SocketOptionName.MulticastTimeToLive, uE.Ttl); // setup destipendpoint based on multicast universe ip rules uE.DestIPEndPoint = multicastIPEndPoint; // add this socket to the socket table for reuse nicSockets.Add(uE.Multicast, uE.Socket); } } } } // if still active we need to create an empty packet if (!uE.Active) { continue; } var zeroBfr = new byte[uE.Size]; var e131Pkt = new E131Pkt(_guid, "", 0, (ushort)uE.Universe, zeroBfr, 0, uE.Size); uE.PhyBuffer = e131Pkt.PhyBuffer; } // any warnings/errors recorded? if (_messageTexts.Length > 0) { // should we display them if (_warningsOption) { // show our warnings/errors J1MsgBox.ShowMsg("The following warnings and errors were detected during startup:", _messageTexts.ToString(), "Startup Warnings/Errors", MessageBoxButtons.OK, MessageBoxIcon.Exclamation); // discard warning/errors after reporting them _messageTexts = new StringBuilder(); } } }
// ------------------------------------------------------------- // // Startup() - called when the plugin is loaded // // // todo: // // 1) probably add error checking on all 'new' operations // and system calls // // 2) better error reporting and logging // // 3) Sequence # should be per universe // // ------------------------------------------------------------- public override void Start() { bool cleanStart = true; base.Start(); if (!PluginInstances.Contains(this)) { PluginInstances.Add(this); } // working copy of networkinterface object NetworkInterface networkInterface; // a single socket to use for unicast (if needed) Socket unicastSocket = null; // working ipaddress object IPAddress ipAddress = null; // a sortedlist containing the multicast sockets we've already done var nicSockets = new SortedList <string, Socket>(); // load all of our xml into working objects this.LoadSetupNodeInfo(); // initialize plugin wide stats this._eventCnt = 0; this._totalTicks = 0; if (_data.Unicast == null && _data.Multicast == null) { if (_data.Universes[0] != null && (_data.Universes[0].Multicast != null || _data.Universes[0].Unicast != null)) { _data.Unicast = _data.Universes[0].Unicast; _data.Multicast = _data.Universes[0].Multicast; if (!_updateWarn) { //messageBox Arguments are (Text, Title, No Button Visible, Cancel Button Visible) MessageBoxForm.msgIcon = SystemIcons.Information; //this is used if you want to add a system icon to the message form. var messageBox = new MessageBoxForm( "The E1.31 plugin is importing data from an older version of the plugin. Please verify the new Streaming ACN (E1.31) configuration.", "Vixen 3 Streaming ACN (E1.31) plugin", false, false); messageBox.ShowDialog(); _updateWarn = true; } } } // find all of the network interfaces & build a sorted list indexed by Id this._nicTable = new SortedList <string, NetworkInterface>(); NetworkInterface[] nics = NetworkInterface.GetAllNetworkInterfaces(); foreach (var nic in nics) { if (nic.NetworkInterfaceType != NetworkInterfaceType.Tunnel && nic.NetworkInterfaceType != NetworkInterfaceType.Loopback) { this._nicTable.Add(nic.Id, nic); } } if (_data.Unicast != null) { if (!unicasts.ContainsKey(_data.Unicast)) { unicasts.Add(_data.Unicast, 0); } } // initialize messageTexts stringbuilder to hold all warnings/errors this._messageTexts = new StringBuilder(); // now we need to scan the universeTable foreach (var uE in _data.Universes) { // if it's still active we'll look into making a socket for it if (cleanStart && uE.Active) { // if it's unicast it's fairly easy to do if (_data.Unicast != null) { // is this the first unicast universe? if (unicastSocket == null) { // yes - make a new socket to use for ALL unicasts unicastSocket = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp); } // use the common unicastsocket uE.Socket = unicastSocket; IPAddress[] ips = null; try { ips = Dns.GetHostAddresses(_data.Unicast); } catch { //Probably couldn't find the host name NLog.LogManager.GetCurrentClassLogger().Warn("Couldn't connect to host " + _data.Unicast + "."); cleanStart = false; } if (ips != null) { IPAddress ip = null; foreach (IPAddress i in ips) { if (i.AddressFamily == AddressFamily.InterNetwork) { ip = i; } } // try to parse our ip address if (ip == null) { // oops - bad ip, fuss and deactivate NLog.LogManager.GetCurrentClassLogger().Warn("Couldn't connect to host " + _data.Unicast + "."); cleanStart = false; uE.Socket = null; } else { // if good, make our destination endpoint uE.DestIpEndPoint = new IPEndPoint(ip, 5568); } } } // if it's multicast roll up your sleeves we've got work to do else if (_data.Multicast != null) { // create an ipaddress object based on multicast universe ip rules var multicastIpAddress = new IPAddress(new byte[] { 239, 255, (byte)(uE.Universe >> 8), (byte)(uE.Universe & 0xff) }); // create an ipendpoint object based on multicast universe ip/port rules var multicastIpEndPoint = new IPEndPoint(multicastIpAddress, 5568); // first check for multicast id in nictable if (!this._nicTable.ContainsKey(_data.Multicast)) { // no - deactivate and scream & yell!! NLog.LogManager.GetCurrentClassLogger() .Warn("Couldn't connect to use nic " + _data.Multicast + " for multicasting."); if (!_missingInterfaceWarning) { //messageBox Arguments are (Text, Title, No Button Visible, Cancel Button Visible) MessageBoxForm.msgIcon = SystemIcons.Warning; //this is used if you want to add a system icon to the message form. var messageBox = new MessageBoxForm( "The Streaming ACN (E1.31) plugin could not find one or more of the multicast interfaces specified. Please verify your network and plugin configuration.", "Vixen 3 Streaming ACN (E1.31) plugin", false, false); messageBox.ShowDialog(); _missingInterfaceWarning = true; } cleanStart = false; } else { // yes - let's get a working networkinterface object networkInterface = this._nicTable[_data.Multicast]; // have we done this multicast id before? if (nicSockets.ContainsKey(_data.Multicast)) { // yes - easy to do - use existing socket uE.Socket = nicSockets[_data.Multicast]; // setup destipendpoint based on multicast universe ip rules uE.DestIpEndPoint = multicastIpEndPoint; } // is the interface up? else if (networkInterface.OperationalStatus != OperationalStatus.Up) { // no - deactivate and scream & yell!! NLog.LogManager.GetCurrentClassLogger() .Warn("Nic " + _data.Multicast + " is available for multicasting bur currently down."); cleanStart = false; } else { // new interface in 'up' status - let's make a new udp socket uE.Socket = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp); // get a working copy of ipproperties IPInterfaceProperties ipProperties = networkInterface.GetIPProperties(); // get a working copy of all unicasts UnicastIPAddressInformationCollection unicasts = ipProperties.UnicastAddresses; ipAddress = null; foreach (var unicast in unicasts) { if (unicast.Address.AddressFamily == AddressFamily.InterNetwork) { ipAddress = unicast.Address; } } if (ipAddress == null) { this._messageTexts.AppendLine(string.Format("No IP On Multicast Interface: {0} - {1}", networkInterface.Name, uE.InfoToText)); } else { // set the multicastinterface option uE.Socket.SetSocketOption( SocketOptionLevel.IP, SocketOptionName.MulticastInterface, ipAddress.GetAddressBytes()); // set the multicasttimetolive option uE.Socket.SetSocketOption( SocketOptionLevel.IP, SocketOptionName.MulticastTimeToLive, 64); // setup destipendpoint based on multicast universe ip rules uE.DestIpEndPoint = multicastIpEndPoint; // add this socket to the socket table for reuse nicSockets.Add(_data.Multicast, uE.Socket); } } } } else { NLog.LogManager.GetCurrentClassLogger() .Warn( "E1.31 plugin failed to start due to unassigned destinations. This can happen with newly created plugin instances that have yet to be configured."); cleanStart = false; } // if still active we need to create an empty packet if (cleanStart) { var zeroBfr = new byte[uE.Size]; var e131Packet = new E131Packet(_data.ModuleInstanceId, "Vixen 3", 0, (ushort)uE.Universe, zeroBfr, 0, uE.Size, _data.Priority, _data.Blind); uE.PhyBuffer = e131Packet.PhyBuffer; } } if (cleanStart) { running = true; } } // any warnings/errors recorded? if (this._messageTexts.Length > 0) { // should we display them if (_data.Warnings) { // show our warnings/errors J1MsgBox.ShowMsg( "The following warnings and errors were detected during startup:", this._messageTexts.ToString(), "Startup Warnings/Errors", MessageBoxButtons.OK, MessageBoxIcon.Exclamation); // discard warning/errors after reporting them this._messageTexts = new StringBuilder(); } } #if VIXEN21 return(new List <Form> { }); #endif }
private void OkButtonClick(object sender, EventArgs e) { var valid = true; var errorList = new StringBuilder(); var universeDestinations = new SortedList <string, int>(); // first buid a table of active universe/destination combos foreach (DataGridViewRow row in this.univDGVN.Rows) { if (row.IsNewRow) { continue; } if (row.Cells[ACTIVE_COLUMN].Value != null) { if ((bool)row.Cells[ACTIVE_COLUMN].Value) { if (row.Cells[DESTINATION_COLUMN].Value != null) { var universeDestination = (string)row.Cells[UNIVERSE_COLUMN].Value + ":" + (string)row.Cells[DESTINATION_COLUMN].Value; if (universeDestinations.ContainsKey(universeDestination)) { universeDestinations[universeDestination] = 1; } else { universeDestinations.Add(universeDestination, 0); } } } } } // now scan for empty destinations, duplicate universe/destination combos, channels errors, etc. foreach (DataGridViewRow row in this.univDGVN.Rows) { if (row.IsNewRow) { continue; } // only test if row is active if (row.Cells[ACTIVE_COLUMN].Value != null) { if ((bool)row.Cells[ACTIVE_COLUMN].Value) { // test for null destinations if (row.Cells[DESTINATION_COLUMN].Value == null) { if (!valid) { errorList.Append("\r\n"); } errorList.Append("Row "); errorList.Append((row.Index + 1).ToString()); errorList.Append(": No Destination Selected"); valid = false; } else { // otherwise, test for duplicate universe/destination combos var universeDestination = (string)row.Cells[UNIVERSE_COLUMN].Value + ":" + (string)row.Cells[DESTINATION_COLUMN].Value; if (universeDestinations[universeDestination] != 0) { if (!valid) { errorList.Append("\r\n"); } errorList.Append("Row "); errorList.Append((row.Index + 1).ToString()); errorList.Append(": Duplicate Universe/Destination Combination"); valid = false; } } // only test for range if more than 0 channels, otherwise wait for runtime if (this.pluginChannelCount > 0) { // now test for valid channel start if (((string)row.Cells[START_COLUMN].Value).TryParseInt32(1) > this.pluginChannelCount) { if (!valid) { errorList.Append("\r\n"); } errorList.Append("Row "); errorList.Append((row.Index + 1).ToString()); errorList.Append(": Start Channel Out Of Range"); valid = false; } // now test for valid channel size if (((string)row.Cells[START_COLUMN].Value).TryParseInt32(1) + ((string)row.Cells[SIZE_COLUMN].Value).TryParseInt32(1) - 1 > this.pluginChannelCount) { if (!valid) { errorList.Append("\r\n"); } errorList.Append("Row "); errorList.Append((row.Index + 1).ToString()); errorList.Append(": Start Channel + Size Out Of Range"); valid = false; } } // now test for ttl value if (((string)row.Cells[TTL_COLUMN].Value).TryParseInt32(1) == 0) { if (!valid) { errorList.Append("\r\n"); } errorList.Append("Row "); errorList.Append((row.Index + 1).ToString()); errorList.Append(": Warning - Zero TTL"); valid = false; } } } } if (!valid) { if ( J1MsgBox.ShowMsg( "Your configurations contains active entries that may cause run time errors.\r\n\r\nHit OK to continue and save your configuration. Hit Cancel to re-edit before saving.", errorList.ToString(), "Configuration Validation", MessageBoxButtons.OKCancel, MessageBoxIcon.Error) == DialogResult.OK) { valid = true; } } if (valid) { this.DialogResult = DialogResult.OK; this.Close(); } }
// ------------------------------------------------------------- // // Stop() - called when execution is stopped or the // plugin instance is no longer going to be // referenced // // ------------------------------------------------------------- public override void Stop() { base.Stop(); PluginInstances.Remove(this); running = false; //Close open sockets //If unicast then all universes are sharing a socket //so just close the first/only one. if (_data.Unicast != null) { if (_data.Universes != null && _data.Universes.Count > 0 && _data.Universes[0].Socket != null) { _data.Universes[0].Socket.Shutdown(SocketShutdown.Both); _data.Universes[0].Socket.Close(); _data.Universes[0].Socket = null; } } else if (_data.Multicast != null) { // keep track of interface ids we have shutdown var idList = new SortedList <string, int>(); // iterate through universetable foreach (var uE in _data.Universes) { // assume multicast string id = _data.Multicast; // if active if (uE.Active) { // and a usable socket if (uE.Socket != null) { // if not already done if (!idList.ContainsKey(id)) { // record it & shut it down idList.Add(id, 1); uE.Socket.Shutdown(SocketShutdown.Both); uE.Socket.Close(); uE.Socket = null; } } } } } if (_data.Statistics) { if (this._messageTexts.Length > 0) { this._messageTexts.AppendLine(); } this._messageTexts.AppendLine(string.Format("Events: {0}", this._eventCnt)); this._messageTexts.AppendLine(string.Format("Total Time: {0} Ticks; {1} ms", this._totalTicks, TimeSpan.FromTicks(this._totalTicks).Milliseconds)); foreach (var uE in _data.Universes) { if (uE.Active) { this._messageTexts.AppendLine(); this._messageTexts.Append(uE.StatsToText); } } J1MsgBox.ShowMsg( "Plugin Statistics:", this._messageTexts.ToString(), "J1Sys E1.31 Vixen Plugin", MessageBoxButtons.OK, MessageBoxIcon.Information); } // this._universeTable.Clear(); if (this._nicTable != null) { this._nicTable.Clear(); } this._nicTable = new SortedList <string, NetworkInterface>(); }
// -------------------------------------------------------------------- // ShowSysClick() - command to show system info // -------------------------------------------------------------------- public static void ShowSysClick(object sender, EventArgs e) { var txt = new StringBuilder(); var p = Process.GetCurrentProcess(); txt.AppendLine("Process: " + p.ProcessName); txt.Append("Threads: " + p.Threads.Count); txt.AppendLine(" Handles: " + p.HandleCount); if (Environment.OSVersion.Platform == PlatformID.Win32NT) { txt.Append("PMemory: " + p.PrivateMemorySize64); txt.AppendLine(" WMemory: " + p.WorkingSet64); } txt.AppendLine(); var computerProperties = IPGlobalProperties.GetIPGlobalProperties(); txt.Append("HostName: " + computerProperties.HostName); txt.AppendLine(" DomainName: " + computerProperties.DomainName); var nics = NetworkInterface.GetAllNetworkInterfaces(); if (nics.Length > 0) { foreach (var nic in nics) { if (nic.NetworkInterfaceType.CompareTo(NetworkInterfaceType.Tunnel) != 0) { txt.AppendLine(); txt.AppendLine(nic.Description + ":"); txt.AppendLine(" ID: " + nic.Id); txt.AppendLine(" Name: " + nic.Name); txt.Append(" Interface Type: " + nic.NetworkInterfaceType); txt.Append(" Physical Address: " + nic.GetPhysicalAddress()); txt.AppendLine(); txt.Append(" Operational Status: " + nic.OperationalStatus); txt.Append(" Supports Multicast: " + nic.SupportsMulticast); txt.AppendLine(); var uniCasts = nic.GetIPProperties().UnicastAddresses; bool prefix = false; foreach (var uniCast in uniCasts) { if (uniCast.Address.AddressFamily.CompareTo(AddressFamily.InterNetwork) == 0) { if (!prefix) { txt.Append(" IP Address: "); prefix = true; } txt.Append(" " + uniCast.Address); } } if (prefix) { txt.AppendLine(); } } } } txt.AppendLine(); txt.AppendLine("That's All Folks!!!"); J1MsgBox.ShowMsg(string.Empty, txt.ToString(), "Show System Info", MessageBoxButtons.OK, MessageBoxIcon.None); }
//------------------------------------------------------------- // // okButton_Click() - validate the data consistency // //------------------------------------------------------------- private void okButton_Click(object sender, EventArgs e) { var valid = true; var errorList = new StringBuilder(); var universeDestinations = new SortedList <string, int>(); // first buid a table of active universe/destination combos foreach (var universeDestination in from DataGridViewRow row in univDGVN.Rows where !row.IsNewRow where row.Cells[ActiveColumn].Value != null where (bool)row.Cells[ActiveColumn].Value where row.Cells[DestinationColumn].Value != null select(string) row.Cells[UniverseColumn].Value + ":" + (string)row.Cells[DestinationColumn].Value) { if (universeDestinations.ContainsKey(universeDestination)) { universeDestinations[universeDestination] = 1; } else { universeDestinations.Add(universeDestination, 0); } } // now scan for empty destinations, duplicate universe/destination combos, channels errors, etc. foreach (var row in from DataGridViewRow row in univDGVN.Rows where !row.IsNewRow where row.Cells[ActiveColumn].Value != null where (bool)row.Cells[ActiveColumn].Value select row) { // test for null destinations if (row.Cells[DestinationColumn].Value == null) { if (!valid) { errorList.Append("\r\n"); } errorList.Append("Row "); errorList.Append((row.Index + 1).ToString(CultureInfo.InvariantCulture)); errorList.Append(": No Destination Selected"); valid = false; } else { // otherwise, test for duplicate universe/destination combos var universeDestination = (string)row.Cells[UniverseColumn].Value + ":" + (string)row.Cells[DestinationColumn].Value; if (universeDestinations[universeDestination] != 0) { if (!valid) { errorList.Append("\r\n"); } errorList.Append("Row "); errorList.Append((row.Index + 1).ToString(CultureInfo.InvariantCulture)); errorList.Append(": Duplicate Universe/Destination Combination"); valid = false; } } // only test for range if more than 0 channels, otherwise wait for runtime if (_pluginChannelCount > 0) { // now test for valid channel start if (OutputPlugin.TryParseInt32((string)row.Cells[StartColumn].Value, 1) > _pluginChannelCount) { if (!valid) { errorList.Append("\r\n"); } errorList.Append("Row "); errorList.Append((row.Index + 1).ToString(CultureInfo.InvariantCulture)); errorList.Append(": Start Channel Out Of Range"); valid = false; } // now test for valid channel size if (OutputPlugin.TryParseInt32((string)row.Cells[StartColumn].Value, 1) + OutputPlugin.TryParseInt32((string)row.Cells[SizeColumn].Value, 1) - 1 > _pluginChannelCount) { if (!valid) { errorList.Append("\r\n"); } errorList.Append("Row "); errorList.Append((row.Index + 1).ToString(CultureInfo.InvariantCulture)); errorList.Append(": Start Channel + Size Out Of Range"); valid = false; } } // now test for ttl value if (OutputPlugin.TryParseInt32((string)row.Cells[TtlColumn].Value, 1) != 0) { continue; } if (!valid) { errorList.Append("\r\n"); } errorList.Append("Row "); errorList.Append((row.Index + 1).ToString(CultureInfo.InvariantCulture)); errorList.Append(": Warning - Zero TTL"); valid = false; } if (!valid) { J1MsgBox.ShowMsg("Your configurations contains active entries that may cause run time errors.", errorList.ToString(), "Configuration Validation", MessageBoxButtons.OK, MessageBoxIcon.Error); } else { J1MsgBox.ShowMsg("Your configuration appears to be valid.", "Configuration Validation", MessageBoxButtons.OK, MessageBoxIcon.Information); } }
// ------------------------------------------------------------- // // Startup() - called when the plugin is loaded // // // todo: // // 1) probably add error checking on all 'new' operations // and system calls // // 2) better error reporting and logging // // 3) Sequence # should be per universe // // ------------------------------------------------------------- public override void Start() { // working copy of networkinterface object NetworkInterface networkInterface; // a single socket to use for unicast (if needed) Socket unicastSocket = null; // working ipaddress object IPAddress ipAddress = null; // a sortedlist containing the multicast sockets we've already done var nicSockets = new SortedList <string, Socket>(); // Load the NICs and XML file this.Initialize(); // initialize plugin wide stats this._eventCnt = 0; this._totalTicks = 0; // initialize messageTexts stringbuilder to hold all warnings/errors this._messageTexts = new StringBuilder(); // now we need to scan the universeTable foreach (var uE in _data.Universes) { // if it's still active we'll look into making a socket for it if (uE.Active) { // if it's unicast it's fairly easy to do if (uE.Unicast != null) { // is this the first unicast universe? if (unicastSocket == null) { // yes - make a new socket to use for ALL unicasts unicastSocket = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp); } // use the common unicastsocket uE.Socket = unicastSocket; // try to parse our ip address if (!IPAddress.TryParse(uE.Unicast, out ipAddress)) { // oops - bad ip, fuss and deactivate uE.Active = false; uE.Socket = null; this._messageTexts.AppendLine(string.Format("Invalid Unicast IP: {0} - {1}", uE.Unicast, uE.RowUnivToText)); } else { // if good, make our destination endpoint uE.DestIpEndPoint = new IPEndPoint(ipAddress, 5568); } } // if it's multicast roll up your sleeves we've got work to do else if (uE.Multicast != null) { // create an ipaddress object based on multicast universe ip rules var multicastIpAddress = new IPAddress(new byte[] { 239, 255, (byte)(uE.Universe >> 8), (byte)(uE.Universe & 0xff) }); // create an ipendpoint object based on multicast universe ip/port rules var multicastIpEndPoint = new IPEndPoint(multicastIpAddress, 5568); // first check for multicast id in nictable if (!this._nicTable.ContainsKey(uE.Multicast)) { // no - deactivate and scream & yell!! uE.Active = false; this._messageTexts.AppendLine(string.Format("Invalid Multicast NIC ID: {0} - {1}", uE.Multicast, uE.RowUnivToText)); } else { // yes - let's get a working networkinterface object networkInterface = this._nicTable[uE.Multicast]; // have we done this multicast id before? if (nicSockets.ContainsKey(uE.Multicast)) { // yes - easy to do - use existing socket uE.Socket = nicSockets[uE.Multicast]; // setup destipendpoint based on multicast universe ip rules uE.DestIpEndPoint = multicastIpEndPoint; } // is the interface up? else if (networkInterface.OperationalStatus != OperationalStatus.Up) { // no - deactivate and scream & yell!! uE.Active = false; this._messageTexts.AppendLine(string.Format("Multicast Interface Down: {0} - {1}", networkInterface.Name, uE.RowUnivToText)); } else { // new interface in 'up' status - let's make a new udp socket uE.Socket = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp); // get a working copy of ipproperties IPInterfaceProperties ipProperties = networkInterface.GetIPProperties(); // get a working copy of all unicasts UnicastIPAddressInformationCollection unicasts = ipProperties.UnicastAddresses; ipAddress = null; foreach (var unicast in unicasts) { if (unicast.Address.AddressFamily == AddressFamily.InterNetwork) { ipAddress = unicast.Address; } } if (ipAddress == null) { this._messageTexts.AppendLine(string.Format("No IP On Multicast Interface: {0} - {1}", networkInterface.Name, uE.InfoToText)); } else { // set the multicastinterface option uE.Socket.SetSocketOption( SocketOptionLevel.IP, SocketOptionName.MulticastInterface, ipAddress.GetAddressBytes()); // set the multicasttimetolive option uE.Socket.SetSocketOption( SocketOptionLevel.IP, SocketOptionName.MulticastTimeToLive, uE.Ttl); // setup destipendpoint based on multicast universe ip rules uE.DestIpEndPoint = multicastIpEndPoint; // add this socket to the socket table for reuse nicSockets.Add(uE.Multicast, uE.Socket); } } } } else { throw new System.Exception("no uni or multi cast"); } // if still active we need to create an empty packet if (uE.Active) { var zeroBfr = new byte[uE.Size]; for (int i = 0; i < uE.Size; i++) // init to unlikely value for later compares { zeroBfr[i] = (byte)i; } var e131Packet = new E131Packet(_data.ModuleInstanceId, string.Empty, 0, (ushort)uE.Universe, zeroBfr, 0, uE.Size); uE.PhyBuffer = e131Packet.PhyBuffer; } } hasStarted = true; } // any warnings/errors recorded? if (this._messageTexts.Length > 0) { // should we display them if (_data.Warnings) { // show our warnings/errors J1MsgBox.ShowMsg( "The following warnings and errors were detected during startup:", this._messageTexts.ToString(), "Startup Warnings/Errors", MessageBoxButtons.OK, MessageBoxIcon.Exclamation); // discard warning/errors after reporting them this._messageTexts = new StringBuilder(); } } #if VIXEN21 return(new List <Form> { }); #endif }
// ------------------------------------------------------------- // // Shutdown() - called when execution is stopped or the // plugin instance is no longer going to be // referenced // // ------------------------------------------------------------- public void Shutdown() { // keep track of interface ids we have shutdown var idList = new SortedList <string, int>(); // iterate through universetable foreach (var uE in _data.Universes) { // assume multicast string id = uE.Multicast; // if unicast use psuedo id if (uE.Unicast != null) { id = "unicast"; } // if active if (uE.Active) { // and a usable socket if (uE.Socket != null) { // if not already done if (!idList.ContainsKey(id)) { // record it & shut it down idList.Add(id, 1); uE.Socket.Shutdown(SocketShutdown.Both); uE.Socket.Close(); } } } } if (_data.Statistics) { if (this._messageTexts.Length > 0) { this._messageTexts.AppendLine(); } this._messageTexts.AppendLine(string.Format("Events: {0}", this._eventCnt)); this._messageTexts.AppendLine(string.Format("Total Time: {0} Ticks; {1} ms", this._totalTicks, TimeSpan.FromTicks(this._totalTicks).Milliseconds)); foreach (var uE in _data.Universes) { if (uE.Active) { this._messageTexts.AppendLine(); this._messageTexts.Append(uE.StatsToText); } } J1MsgBox.ShowMsg( "Plugin Statistics:", this._messageTexts.ToString(), "J1Sys E1.31 Vixen Plugin", MessageBoxButtons.OK, MessageBoxIcon.Information); } // this._universeTable.Clear(); if (this._nicTable != null) { this._nicTable.Clear(); } this._nicTable = new SortedList <string, NetworkInterface>(); }