logging-general mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From sde...@apache.org
Subject svn commit: r924176 - in /logging/chainsaw/trunk: ./ src/main/java/org/apache/log4j/chainsaw/zeroconf/ src/main/resources/org/apache/log4j/chainsaw/help/ src/main/resources/org/apache/log4j/chainsaw/zeroconf/ src/site/apt/
Date Wed, 17 Mar 2010 07:16:07 GMT
Author: sdeboy
Date: Wed Mar 17 07:16:06 2010
New Revision: 924176

URL: http://svn.apache.org/viewvc?rev=924176&view=rev
Log:
Added ZeroConf support to most of the network-based appenders and receivers.

To enable ZeroConf advertising of an appender or receiver, a user can now:
 - add jmdns jar to their classpath 
 - set the 'advertiseViaMulticastDNS' param to 'true'

Also added support for discovery of appenders in Chainsaw (Chainsaw will automatically configure
a matching receiver when connected).
Supported appenders:
    SocketAppender
    SocketHubAppender (ZeroConfSocketHubAppender is still functional)
    UDPAppender
    MulticastAppender
Supported receivers:
    SocketReceiver
    SocketHubReceiver (also receives events from ZeroConfSocketHubAppender)
    XMLSocketReceiver (can receive events sent over TCP by other logging frameworks)
    UDPReceiver
    MulticastReceiver

Implementation details:
 - removed Zeroconf4log4j class, jmdns access is now through the ZeroConfSupport class (class
provides support of JmDNS and ServiceInfo creation via reflection, and supports both jmdns
1.0 and jmdns 3.1 apis)
 - ZeroConfSupport class is now used by ZeroConfSocketHubAppender, Chainsaw and all appenders
& receivers that can advertise their configuration via ZeroConf
 - added new 'advertiseViaMulticastDNS' param to the appenders and receivers that support
ZeroConf
 - updated the ZeroConf site documentation
 - updated release notes
 - updated the ZeroConfPlugin html file
 - tested appenders with 1.0 and 3.1 jmdns jars
 - updated log4j references in poms to log4j 1.2.16-snapshot where necessary 

For those wanting to add ZeroConf support to third-party appenders and have Chainsaw discover
the appenders, the service info naming convention is described here: https://issues.apache.org/bugzilla/show_bug.cgi?id=48907

Modified:
    logging/chainsaw/trunk/pom.xml
    logging/chainsaw/trunk/src/main/java/org/apache/log4j/chainsaw/zeroconf/ZeroConfPlugin.java
    logging/chainsaw/trunk/src/main/resources/org/apache/log4j/chainsaw/help/release-notes.html
    logging/chainsaw/trunk/src/main/resources/org/apache/log4j/chainsaw/zeroconf/ZeroConfPlugin.html
    logging/chainsaw/trunk/src/site/apt/zeroconf.apt

Modified: logging/chainsaw/trunk/pom.xml
URL: http://svn.apache.org/viewvc/logging/chainsaw/trunk/pom.xml?rev=924176&r1=924175&r2=924176&view=diff
==============================================================================
--- logging/chainsaw/trunk/pom.xml (original)
+++ logging/chainsaw/trunk/pom.xml Wed Mar 17 07:16:06 2010
@@ -349,7 +349,7 @@
     <dependency>
       <groupId>log4j</groupId>
       <artifactId>log4j</artifactId>
-      <version>1.2.16</version>
+      <version>1.2.16-SNAPSHOT</version>
     </dependency>
     <dependency>
       <groupId>xstream</groupId>

Modified: logging/chainsaw/trunk/src/main/java/org/apache/log4j/chainsaw/zeroconf/ZeroConfPlugin.java
URL: http://svn.apache.org/viewvc/logging/chainsaw/trunk/src/main/java/org/apache/log4j/chainsaw/zeroconf/ZeroConfPlugin.java?rev=924176&r1=924175&r2=924176&view=diff
==============================================================================
--- logging/chainsaw/trunk/src/main/java/org/apache/log4j/chainsaw/zeroconf/ZeroConfPlugin.java
(original)
+++ logging/chainsaw/trunk/src/main/java/org/apache/log4j/chainsaw/zeroconf/ZeroConfPlugin.java
Wed Mar 17 07:16:06 2010
@@ -10,8 +10,10 @@ import java.io.File;
 import java.io.FileReader;
 import java.io.FileWriter;
 import java.util.HashMap;
+import java.util.HashSet;
 import java.util.Iterator;
 import java.util.Map;
+import java.util.Set;
 
 import javax.jmdns.JmDNS;
 import javax.jmdns.ServiceEvent;
@@ -41,12 +43,17 @@ import org.apache.log4j.chainsaw.help.He
 import org.apache.log4j.chainsaw.icons.ChainsawIcons;
 import org.apache.log4j.chainsaw.plugins.GUIPluginSkeleton;
 import org.apache.log4j.chainsaw.prefs.SettingsManager;
+import org.apache.log4j.helpers.LogLog;
+import org.apache.log4j.net.MulticastReceiver;
 import org.apache.log4j.net.SocketHubReceiver;
-import org.apache.log4j.net.ZeroConfSocketHubAppender;
-import org.apache.log4j.net.Zeroconf4log4j;
+import org.apache.log4j.net.SocketReceiver;
+import org.apache.log4j.net.UDPReceiver;
+import org.apache.log4j.net.XMLSocketReceiver;
+import org.apache.log4j.net.ZeroConfSupport;
 import org.apache.log4j.plugins.Plugin;
 import org.apache.log4j.plugins.PluginEvent;
 import org.apache.log4j.plugins.PluginListener;
+import org.apache.log4j.plugins.Receiver;
 import org.apache.log4j.spi.LoggerRepositoryEx;
 
 import com.thoughtworks.xstream.XStream;
@@ -62,9 +69,6 @@ import com.thoughtworks.xstream.io.xml.D
  * TODO add the
  * default Zone, and the list of user-specified zones to a preferenceModel
  * 
- * To run this in trial mode, first run {@link ZeroConfSocketHubAppenderTestBed}, then
- * run this class' main(..) method.
- * 
  * @author psmith
  * 
  */
@@ -80,8 +84,6 @@ public class ZeroConfPlugin extends GUIP
     
     private final JScrollPane scrollPane = new JScrollPane(deviceTable);
 
-    private JmDNS jmDNS;
-
     private ZeroConfPreferenceModel preferenceModel;
     
     private Map serviceInfoToReceiveMap = new HashMap();
@@ -97,13 +99,19 @@ public class ZeroConfPlugin extends GUIP
     });  
     
     private JMenuItem nothingToConnectTo = new JMenuItem("No devices discovered");
-    
+    private static final String MULTICAST_APPENDER_SERVICE_NAME = "_log4j_xml_mcast_appender.local.";
+    private static final String UDP_APPENDER_SERVICE_NAME = "_log4j_xml_udp_appender.local.";
+    private static final String XML_SOCKET_APPENDER_SERVICE_NAME = "_log4j_xml_tcpconnect_appender.local.";
+    private static final String SOCKET_APPENDER_SERVICE_NAME = "_log4j_obj_tcpconnect_appender.local.";
+    private static final String SOCKETHUB_APPENDER_SERVICE_NAME = "_log4j_obj_tcpaccept_appender.local.";
+    private JmDNS jmDNS;
+
     public ZeroConfPlugin() {
         setName("Zeroconf");
     }
 
     public void shutdown() {
-        Zeroconf4log4j.shutdown();
+        jmDNS.close();
         save();
     }
 
@@ -123,14 +131,10 @@ public class ZeroConfPlugin extends GUIP
 
     public void activateOptions() {
         setLayout(new BorderLayout());
-        jmDNS = Zeroconf4log4j.getInstance();
+        jmDNS = (JmDNS) ZeroConfSupport.getJMDNSInstance();
 
-        jmDNS.addServiceListener(
-                ZeroConfSocketHubAppender.DEFAULT_ZEROCONF_ZONE,
-                new ZeroConfServiceListener());
+        registerServiceListenersForAppenders();
 
-        jmDNS.addServiceListener(ZeroConfSocketHubAppender.DEFAULT_ZEROCONF_ZONE, discoveredDevices);
-        
         deviceTable.addMouseListener(new ConnectorMouseListener());
 
         
@@ -179,7 +183,28 @@ public class ZeroConfPlugin extends GUIP
         discoveredDevices.setZeroConfPreferenceModel(preferenceModel);
         discoveredDevices.setZeroConfPluginParent(this);
     }
-    
+
+    private void registerServiceListenersForAppenders()
+    {
+        Set serviceNames = new HashSet();
+        serviceNames.add(MULTICAST_APPENDER_SERVICE_NAME);
+        serviceNames.add(SOCKET_APPENDER_SERVICE_NAME);
+        serviceNames.add(SOCKETHUB_APPENDER_SERVICE_NAME);
+        serviceNames.add(UDP_APPENDER_SERVICE_NAME);
+        serviceNames.add(XML_SOCKET_APPENDER_SERVICE_NAME);
+
+        for (Iterator iter = serviceNames.iterator(); iter.hasNext();) {
+            String serviceName = iter.next().toString();
+            jmDNS.addServiceListener(
+                    serviceName,
+                    new ZeroConfServiceListener());
+
+            jmDNS.addServiceListener(serviceName, discoveredDevices);
+        }
+
+        //now add each appender constant
+    }
+
     /**
      * Sets the icon of this parent container (a JTabbedPane, we hope
      *
@@ -286,7 +311,7 @@ public class ZeroConfPlugin extends GUIP
             connectToMenu.insert(connectToDeviceMenuItem,0);
         }
 //         if the device name is one of the autoconnect devices, then connect immediately
-        if (preferenceModel.getAutoConnectDevices().contains(name)) {
+        if (preferenceModel != null && preferenceModel.getAutoConnectDevices() !=
null && preferenceModel.getAutoConnectDevices().contains(name)) {
             new Thread(new Runnable() {
 
                 public void run() {
@@ -432,15 +457,12 @@ public class ZeroConfPlugin extends GUIP
      */
     private void connectTo(ServiceInfo info) {
         LOG.info("Connection request for " + info);
-        int port = info.getPort();
-        String hostAddress = info.getHostAddress();
-       
-//        TODO handle different receivers than just SocketHubReceiver
-        SocketHubReceiver receiver = new SocketHubReceiver();
-        receiver.setHost(hostAddress);
-        receiver.setPort(port);
-        receiver.setName(info.getName());
-        
+        //Chainsaw can construct receivers from discovered appenders
+        Receiver receiver = getReceiver(info);
+        //if null, unable to resolve the service name..no-op
+        if (receiver == null) {
+            return;
+        }
         ((LoggerRepositoryEx)LogManager.getLoggerRepository()).getPluginRegistry().addPlugin(receiver);
         receiver.activateOptions();
         LOG.info("Receiver '" + receiver.getName() + "' has been started");
@@ -460,6 +482,69 @@ public class ZeroConfPlugin extends GUIP
 //        discoveredDevices.fireContentsChanged();
     }
 
+    private Receiver getReceiver(ServiceInfo info) {
+        String zone = info.getType();
+        int port = info.getPort();
+        String hostAddress = info.getHostAddress();
+        String name = info.getName();
+        String decoderClass = info.getPropertyString("decoder");
+
+        //MulticastAppender
+        if (MULTICAST_APPENDER_SERVICE_NAME.equals(zone)) {
+            MulticastReceiver receiver = new MulticastReceiver();
+            //this needs to be a multicast address, not the host address, so we need to use
a property
+            receiver.setAddress(info.getPropertyString("multicastAddress"));
+            receiver.setPort(port);
+            receiver.setName(name + "-receiver");
+            if (decoderClass != null && !decoderClass.equals("")) {
+                receiver.setDecoder(decoderClass);
+            }
+
+            return receiver;
+        }
+        //UDPAppender
+        if (UDP_APPENDER_SERVICE_NAME.equals(zone)) {
+            UDPReceiver receiver = new UDPReceiver();
+            receiver.setPort(port);
+            receiver.setName(name + "-receiver");
+            if (decoderClass != null && !decoderClass.equals("")) {
+                receiver.setDecoder(decoderClass);
+            }
+            return receiver;
+        }
+
+        //non-log4j XML-based socketappender
+        if (XML_SOCKET_APPENDER_SERVICE_NAME.equals(zone)) {
+            XMLSocketReceiver receiver = new XMLSocketReceiver();
+            receiver.setPort(port);
+            receiver.setName(name + "-receiver");
+            if (decoderClass != null && !decoderClass.equals("")) {
+                receiver.setDecoder(decoderClass);
+            }
+            return receiver;
+        }
+
+        //SocketAppender
+        if (SOCKET_APPENDER_SERVICE_NAME.equals(zone)) {
+            SocketReceiver receiver = new SocketReceiver();
+            receiver.setPort(port);
+            receiver.setName(name + "-receiver");
+            return receiver;
+        }
+
+        //SocketHubAppender
+        if (SOCKETHUB_APPENDER_SERVICE_NAME.equals(zone)) {
+            SocketHubReceiver receiver = new SocketHubReceiver();
+            receiver.setHost(hostAddress);
+            receiver.setPort(port);
+            receiver.setName(name + "-receiver");
+            return receiver;
+        }
+        //not recognized
+        LogLog.debug("Unable to find receiver for appender with service name: " + zone);
+        return null;
+    }
+
     /**
      * Finds the matching JMenuItem based on name, may return null if there is no match.
      * 

Modified: logging/chainsaw/trunk/src/main/resources/org/apache/log4j/chainsaw/help/release-notes.html
URL: http://svn.apache.org/viewvc/logging/chainsaw/trunk/src/main/resources/org/apache/log4j/chainsaw/help/release-notes.html?rev=924176&r1=924175&r2=924176&view=diff
==============================================================================
--- logging/chainsaw/trunk/src/main/resources/org/apache/log4j/chainsaw/help/release-notes.html
(original)
+++ logging/chainsaw/trunk/src/main/resources/org/apache/log4j/chainsaw/help/release-notes.html
Wed Mar 17 07:16:06 2010
@@ -10,6 +10,23 @@
 <b>NOTE:</b> The mechanism and format used to persist settings in Chainsaw is
subject to change.  If you are experiencing problems displaying events in Chainsaw, please
delete everything in the $user.dir/.chainsaw directory and restart Chainsaw.
 <br>
 <h1>1.99.99</h1>
+<h2>16 Mar 2010</h2>
+<ul>
+<li>
+Added ZeroConf support to most of the network-based appenders and receivers - just add the
jmdns jar to your classpath and set the 'advertiseViaMulticastDNS' param to 'true'.  Also
added
+support for discovery of these appenders in Chainsaw (once you 'connect' to an advertised
appender, Chainsaw will automatically configure a matching receiver).<br>
+Supported appenders:
+    <ul>SocketAppender</ul>
+    <ul>SocketHubAppender (ZeroConfSocketHubAppender is still functional)</ul>
+    <ul>UDPAppender</ul>
+    <ul>MulticastAppender</ul>
+Supported receivers:
+    <ul>SocketReceiver</ul>
+    <ul>SocketHubReceiver (also receives events from ZeroConfSocketHubAppender)</ul>
+    <ul>XMLSocketReceiver (can receive events sent over TCP by other logging frameworks)</ul>
+    <ul>UDPReceiver</ul>
+    <ul>MulticastReceiver</ul>
+</ul>
 <h2>14 Mar 2010</h2>
 <ul>
 <li>

Modified: logging/chainsaw/trunk/src/main/resources/org/apache/log4j/chainsaw/zeroconf/ZeroConfPlugin.html
URL: http://svn.apache.org/viewvc/logging/chainsaw/trunk/src/main/resources/org/apache/log4j/chainsaw/zeroconf/ZeroConfPlugin.html?rev=924176&r1=924175&r2=924176&view=diff
==============================================================================
--- logging/chainsaw/trunk/src/main/resources/org/apache/log4j/chainsaw/zeroconf/ZeroConfPlugin.html
(original)
+++ logging/chainsaw/trunk/src/main/resources/org/apache/log4j/chainsaw/zeroconf/ZeroConfPlugin.html
Wed Mar 17 07:16:06 2010
@@ -20,7 +20,7 @@ devices on your local network such as pr
 Zeroconf is an open-standard that many vendors are using to reduce cost of configuration.
 The <b>JmDNS</b> project
 is an Apache 2.0 licensed library that implements the ZeroConf protocol.  Chainsaw and log4j
use
 JmDNS to broadcast Appender information so that a matching Receiver can be easily created
to connect to each other
-to stream logging messages into Chainsaw.  
+to stream logging messages into Chainsaw.
 </p>
 <p>
 <ul>
@@ -30,19 +30,16 @@ to stream logging messages into Chainsaw
 </p>
 <h2>Interesting... So what do I need to use ZeroConf with Chainsaw & log4j?</h2>
 <p>
-The log4j team has created an additional JAR file that can be added to your existing
-application to enable ZeroConf configuration. You just need to download the <code>log4j-zeroconf.jar</code>
and the JmDNS package (you must use
-at least version 1.0 of JmDNS) and add 
-both JARs to your application's classpath. </p>
-<p> Then change your references from <code>SocketHubAppender</code>
-to <code><b>ZeroConf</b>SocketHubAppender</code>. (We recommend you
change the 'name' propety from it's default to make it easy for you to use, other
-wise it's name will appear as the default 'SocketHubAppender').
-</p>
+Most of the network-based appenders are ZeroConf-capable - all you have to do to use ZeroConf
is to
+download the JmDNS package (at least version 1.0), add the JmDNS jar to your application's
classpath, and set the "advertiseViaMulticastDNS"
+parameter to 'true' for any of the appenders or receivers you want to advertise (most of
the time you will want to advertise appenders, so they can be
+automatically detected by Chainsaw).</p>
 <p>You're log4j.xml configuration file could be as simple as this:</p>
 <pre>
 &lt;log4j:configuration debug="false" threshold="debug"  xmlns:log4j="http://jakarta.apache.org/log4j/&gt;
-    &lt;appender name="zeroconf" class="org.apache.log4j.net.ZeroConfSocketHubAppender"&gt;
+    &lt;appender name="zeroconf" class="org.apache.log4j.net.SocketHubAppender"&gt;
         &lt;param name="Name" value="MyZeroConfSockeHubAppender" /&gt;
+        &lt;param name="advertiseViaMulticastDNS" value="true" /&gt;
     &lt;/appender&gt;
     &lt;!--ROOT Logger--&gt;
     &lt;root&gt;
@@ -52,12 +49,16 @@ wise it's name will appear as the defaul
 &lt;/log4j:configuration&gt;
 </pre>
 <p>
-Once you have started your application using this new appender, then from within Chainsaw,
the ZeroConf tab will show detected
-applications.  You can simply double click on the detected app, and Chainsaw will connect
a Receiver to it.  You can even tick the "Auto-Connect"
+Once you have started your application using this configuration, from within Chainsaw, the
ZeroConf tab will show detected
+applications.  You can simply double click on the detected appender and Chainsaw will connect
a Receiver to it.  You can even tick the "Auto-Connect"
 check box, and next time Chainsaw see's this application, it will automatically connect to
it.
 </p>
+<p>Most of the network-based Receivers are also ZeroConf capable, giving ZeroConf-aware
appenders or applications
+the ability to discover the receivers and configure appenders to connect to those Receivers.
+</p>
 <h2>Cool... But I have some applications that use log4j 1.2.x.  Will it still work?</h2>
-<p>Yes.  We have designed a backward compatible mechanism to expose log4j 1.2.x SocketHubAppender
so that Chainsaw can detect it automatically.  
+<p>Yes.  We have designed a backward compatible mechanism to expose prior versions
of log4j's SocketHubAppender (ZeroConfSocketHubAppender)
+so that Chainsaw can detect it automatically.
 </p>
 
 <h2>But... Surely there's a catch?</h2>

Modified: logging/chainsaw/trunk/src/site/apt/zeroconf.apt
URL: http://svn.apache.org/viewvc/logging/chainsaw/trunk/src/site/apt/zeroconf.apt?rev=924176&r1=924175&r2=924176&view=diff
==============================================================================
--- logging/chainsaw/trunk/src/site/apt/zeroconf.apt (original)
+++ logging/chainsaw/trunk/src/site/apt/zeroconf.apt Wed Mar 17 07:16:06 2010
@@ -14,21 +14,45 @@
 ~~ limitations under the License.
 ZeroConf - Zero Configuration
 
-	Chainsaw has ZeroConf elements embedded within it, but you'll need to add a few things to
your application to enable your application for ZeroConf.
+    Chainsaw can use ZeroConf to discover advertised appenders and automatically configure
a matching receiver, but you must update your configuration in order to advertise your appender
via ZeroConf.
+    
+    If you are using a newer version of log4j (1.2.16 or greater), most of the network-based
appenders are capable of advertising their configurations via ZeroConf, but have this
+capability disabled by default.
+    To advertise an appender via ZeroConf:
+        [[1]] Download {{{http://sourceforge.net/projects/jmdns/}JmDNS}}
 
-	Download:                                            
-	
-		[[1]] {{{http://logging.apache.org/log4j/docs/webstart/chainsaw/log4j-zeroconf.zip}log4j
ZeroConf extension}}
-		
-		[[2]] {{{http://sourceforge.net/projects/jmdns/}JmDNS}}
-		
-		[[3]] Add the <log4j-zeroconf.jar> and the <jmdns.jar> from these bundles and
add them to your application's classpath. 
-		
-		[[4]] Modify your log4j configuration so that it use the ZeroConfSocketHubAppender.  
-		
-	Here is a complete log4j.xml file that you can use as a base:
-	
-+-------------------------------+						
+        [[2]] Add the <jmdns.jar> to your application's classpath
+
+        [[3]] Modify your log4j configuration so that the appender is set to advertise its
configuration via ZeroConf (by setting the 'advertiseViaMulticastDNS' parameter to 'true')
+
+    Here is a complete log4j.xml file that you can use as a base SocketAppender configuration
which advertises the appender via ZeroConf:</p>
+
++-------------------------------+
+<log4j:configuration debug="false" threshold="debug"  xmlns:log4j="http://jakarta.apache.org/log4j/">
+    <appender name="socketAppender" class="org.apache.log4j.net.SocketAppender">
+        <param name="Name" value="MySockeAppender" />
+        <param name="advertiseViaMulticastDNS" value="true" />
+    </appender>
+    <!--ROOT Logger-->
+    <root>
+        <level value="INFO" />
+        <appender-ref ref="socketAppender" />
+    </root>
+</log4j:configuration>
++-------------------------------+
+
+    If you are using an older version of log4j (prior to 1.2.16), ZeroConfSocketHubAppender
is a ZeroConf-capable appender which is backward compatible with the prior versions of SocketHubAppender
and can advertise the appender configuration via ZeroConf:</p>
+        [[1]] Download {{{http://sourceforge.net/projects/jmdns/}JmDNS}}
+
+        [[2]] Add the <i>jmdns.jar</i> to your application's classpath
+
+        [[3]] Download {{{http://logging.apache.org/log4j/docs/webstart/chainsaw/log4j-zeroconf.zip}log4j
ZeroConf extension (provides ZeroConfSocketHubAppender)}}
+
+        [[4]] Add the <log4j-zeroconf.jar> to your application's classpath
+
+    Here is a complete log4j.xml file that you can use as a base ZeroConfSocketAppender configuration
which advertises the appender via ZeroConf:</p>
+
++-------------------------------+
 <log4j:configuration debug="false" threshold="debug"  xmlns:log4j="http://jakarta.apache.org/log4j/">
     <appender name="zeroconf" class="org.apache.log4j.net.ZeroConfSocketHubAppender">
         <param name="Name" value="MyZeroConfSockeHubAppender" />
@@ -41,12 +65,8 @@ ZeroConf - Zero Configuration
 </log4j:configuration>
 +-------------------------------+
 
-	Once configured and your applicatiion started, you should be able to click on the Zeroconf
tab inside Chainsaw, and see the "MyZeroConfSocketHubAppender" listed.  If you double click
on the row, Chainsaw will automatically connect to your application and start receiving events.
 You can tick the 'auto-connect' option to have Chainsaw immediately connect as soon as it
sees your application started.  Great for Dev/QA environment.
-	
-	The Zeroconf-enabled SocketHubAppender broadcasts it's existence via a multicast protocol,
passing enough information for Chainsaw to be able to connect to it.
-	
-Firewalls
+    Once you have enabled ZeroConf in your log4j configuration and started your application,
you should be able to click on the Zeroconf tab inside Chainsaw and see the advertised appenders
listed. If you double click on a row,
+Chainsaw will automatically connect to your application and start receiving events. You can
tick the 'auto-connect' option to have Chainsaw immediately connect as soon as it sees your
application started. Great for Dev/QA environment.</p>
 
-	Multicast protocols generally don't pass through firewall, so in a production environment
Zeroconf won't work.
-	
-	
\ No newline at end of file
+Firewalls
+    Multicast protocols generally don't pass through firewall, so in a production environment
Zeroconf won't work.</p>



Mime
View raw message