You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@directory.apache.org by rj...@apache.org on 2009/06/09 14:00:32 UTC

svn commit: r782968 [4/7] - in /directory/sandbox/slp: ./ src/main/java/org/apache/directory/slp/ src/main/java/org/apache/directory/slp/codec/ src/main/java/org/apache/directory/slp/extensions/ src/main/java/org/apache/directory/slp/impl/ src/main/jav...

Added: directory/sandbox/slp/src/main/java/org/apache/directory/slp/impl/PlatformAbstraction.java
URL: http://svn.apache.org/viewvc/directory/sandbox/slp/src/main/java/org/apache/directory/slp/impl/PlatformAbstraction.java?rev=782968&view=auto
==============================================================================
--- directory/sandbox/slp/src/main/java/org/apache/directory/slp/impl/PlatformAbstraction.java (added)
+++ directory/sandbox/slp/src/main/java/org/apache/directory/slp/impl/PlatformAbstraction.java Tue Jun  9 12:00:29 2009
@@ -0,0 +1,118 @@
+/* 
+ *   Licensed to the Apache Software Foundation (ASF) under one
+ *   or more contributor license agreements.  See the NOTICE file
+ *   distributed with this work for additional information
+ *   regarding copyright ownership.  The ASF licenses this file
+ *   to you under the Apache License, Version 2.0 (the
+ *   "License"); you may not use this file except in compliance
+ *   with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *   Unless required by applicable law or agreed to in writing,
+ *   software distributed under the License is distributed on an
+ *   "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *   KIND, either express or implied.  See the License for the
+ *   specific language governing permissions and limitations
+ *   under the License.
+ *   
+ */
+package org.apache.directory.slp.impl;
+
+import org.apache.directory.slp.impl.filter.Filter;
+
+/**
+ * Platform abstraction interface. Used to hide the different implementations
+ * for the OSGi platform and for stand-alone Java.
+ * 
+ * @author Jan S. Rellermeyer
+ */
+public interface PlatformAbstraction {
+
+	/**
+	 * Write a debug message to the log.
+	 * 
+	 * @param message
+	 *            the message.
+	 */
+	void logDebug(String message);
+
+	/**
+	 * Write a debug message to the log.
+	 * 
+	 * @param message
+	 *            the message.
+	 * @param exception
+	 *            an exception.
+	 */
+	void logDebug(String message, Throwable exception);
+
+	/**
+	 * Trace a generic message to the log.
+	 * 
+	 * @param message
+	 *            the message.
+	 */
+	void logTraceMessage(String string);
+
+	/**
+	 * Trace a registration to the log.
+	 * 
+	 * @param message
+	 *            the message.
+	 */
+	void logTraceReg(String string);
+
+	/**
+	 * Trace a drop to the log.
+	 * 
+	 * @param message
+	 *            the message.
+	 */
+	void logTraceDrop(String string);
+
+	/**
+	 * Write a warning message to the log.
+	 * 
+	 * @param message
+	 *            the message.
+	 */
+	void logWarning(String message);
+
+	/**
+	 * Write a warning message to the log.
+	 * 
+	 * @param message
+	 *            the message.
+	 * @param exception
+	 *            an exception.
+	 */
+	void logWarning(String message, Throwable exception);
+
+	/**
+	 * Write an error message to the log.
+	 * 
+	 * @param message
+	 *            the message.
+	 */
+	void logError(String message);
+
+	/**
+	 * Write an error message to the log.
+	 * 
+	 * @param message
+	 *            the message.
+	 * @param exception
+	 *            an exception.
+	 */
+	void logError(String message, Throwable exception);
+
+	/**
+	 * Create an LDAP filter.
+	 * 
+	 * @param filterString
+	 *            the filter string.
+	 * @return an LDAP filter object.
+	 */
+	Filter createFilter(String filterString);
+}

Propchange: directory/sandbox/slp/src/main/java/org/apache/directory/slp/impl/PlatformAbstraction.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Added: directory/sandbox/slp/src/main/java/org/apache/directory/slp/impl/SLPAttributeImpl.java
URL: http://svn.apache.org/viewvc/directory/sandbox/slp/src/main/java/org/apache/directory/slp/impl/SLPAttributeImpl.java?rev=782968&view=auto
==============================================================================
--- directory/sandbox/slp/src/main/java/org/apache/directory/slp/impl/SLPAttributeImpl.java (added)
+++ directory/sandbox/slp/src/main/java/org/apache/directory/slp/impl/SLPAttributeImpl.java Tue Jun  9 12:00:29 2009
@@ -0,0 +1,374 @@
+/* 
+ *   Licensed to the Apache Software Foundation (ASF) under one
+ *   or more contributor license agreements.  See the NOTICE file
+ *   distributed with this work for additional information
+ *   regarding copyright ownership.  The ASF licenses this file
+ *   to you under the Apache License, Version 2.0 (the
+ *   "License"); you may not use this file except in compliance
+ *   with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *   Unless required by applicable law or agreed to in writing,
+ *   software distributed under the License is distributed on an
+ *   "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *   KIND, either express or implied.  See the License for the
+ *   specific language governing permissions and limitations
+ *   under the License.
+ *   
+ */
+package org.apache.directory.slp.impl;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.apache.directory.slp.OpaqueValue;
+import org.apache.directory.slp.SLPAttribute;
+import org.apache.directory.slp.ServiceLocationException;
+
+
+/**
+ * 
+ * @author Lorenz Breu
+ */
+public class SLPAttributeImpl implements SLPAttribute {
+
+	private List values;
+	private String name = "";
+	private int type;
+	private String typeString = "";
+	
+	
+	/**
+	 * Creates a new SLPAttributeImpl with the given name and values: "(name=values)"
+	 * 
+	 * @param name
+	 * 			The attibute name
+	 * @param a_values
+	 * 			The value(s) of the attribute. Types are checked on creation
+	 * @throws ServiceLocationException
+	 * 			If the types of values are not consistent
+	 */
+	public SLPAttributeImpl(String name,List<String> a_values) throws ServiceLocationException{
+		this.name=name;
+		type = checkAndSetType(a_values);
+		
+	}
+	
+	/**
+	 * Creates a new SLPAttributeImpl with the given name and values: "(name=values)"
+	 * 
+	 * @param name
+	 * 			The attibute name
+	 * @param a_values
+	 * 			The value(s) of the attribute. Types are checked on creation
+	 * @throws ServiceLocationException
+	 * 			If the types of values are not consistent
+	 */
+	public SLPAttributeImpl(String name,String[] a_values) throws ServiceLocationException{
+		this.name=name;
+		type = checkAndSetType(a_values);
+		
+	}
+	
+	
+	/**
+	 * Creates a new SLPAttributeImpl as a KEYWORD
+	 * 
+	 * @param name
+	 * 			The attribute/keyword name
+	 */
+	public SLPAttributeImpl(String name){
+		this.name=name;
+		type=KEYWORD_AT;
+	}
+	
+	
+	/* (non-Javadoc)
+	 * @see ch.ethz.iks.slp.SLPAttribute#count()
+	 */
+	public int count() {
+		return values.size();
+	}
+
+	/* (non-Javadoc)
+	 * @see ch.ethz.iks.slp.SLPAttribute#getBooleanValues()
+	 */
+	public Boolean[] getBooleanValues() {
+		if (type==BOOLEAN_AT){
+			return (Boolean[]) values.toArray(new Boolean[values.size()]);
+		}
+		return null;
+	}
+
+	/* (non-Javadoc)
+	 * @see ch.ethz.iks.slp.SLPAttribute#getIntegerValues()
+	 */
+	public Integer[] getIntegerValues() {
+		if (type==INTEGER_AT){
+			return (Integer[]) values.toArray(new Integer[values.size()]);
+		}
+		return null;
+	}
+
+	/* (non-Javadoc)
+	 * @see ch.ethz.iks.slp.SLPAttribute#getName()
+	 */
+	public String getName() {
+		return name;
+	}
+
+	/* (non-Javadoc)
+	 * @see ch.ethz.iks.slp.SLPAttribute#getOpaqueValues()
+	 */
+	public OpaqueValue[] getOpaqueValues() {
+		if (type==OPAQUE_AT){
+			return (OpaqueValue[]) values.toArray(new OpaqueValue[values.size()]);
+		}
+		return null;
+	}
+
+	/* (non-Javadoc)
+	 * @see ch.ethz.iks.slp.SLPAttribute#getStringValues()
+	 */
+	public String[] getStringValues() {
+		String[] res = new String[values.size()];
+		for (int i=0; i<res.length;i++){
+			res[i] = values.get(i).toString();
+		}
+		return res;
+	}
+
+	/* (non-Javadoc)
+	 * @see ch.ethz.iks.slp.SLPAttribute#getType()
+	 */
+	public int getType() {
+		return type;
+	}
+
+	/* (non-Javadoc)
+	 * @see ch.ethz.iks.slp.SLPAttribute#getTypeString()
+	 */
+	public String getTypeString() {
+		return typeString;
+	}
+
+
+	/* (non-Javadoc)
+	 * @see ch.ethz.iks.slp.SLPAttribute#isKeyword()
+	 */
+	public boolean isKeyword() {
+		if (type==KEYWORD_AT){
+			return true;
+		}
+		return false;
+	}
+	
+	/* (non-Javadoc)
+	 * @see java.lang.Object#toString()
+	 */
+	public String toString(){
+		if (isKeyword()){
+			return name;
+		}
+		String res = "("+name+"=";
+		for (Object o:values){
+			res+=o.toString()+", ";
+		}
+		res=res.substring(0,res.length()-2)+")";
+		return res;
+	}
+	
+	/**
+	 * merges the values of another SLPAttribute with the same name and type into the ones of this one.
+	 * Silently discards attributes with different names and/or types
+	 * 
+	 * @param other
+	 * 			The other SLPAttribute to be merged into this one
+	 * 			
+	 */
+	public void merge(SLPAttribute other){
+		if (!other.getName().equals(name) || other.getType()!=type){
+			return;
+		}
+		switch(type){
+		case STRING_AT:
+			String[] ovs = other.getStringValues();
+			for (int i=0;i<ovs.length;i++){
+				if (!values.contains(ovs[i])){
+					values.add(ovs[i]);
+				}
+			}
+			break;
+		case INTEGER_AT:
+			Integer[] ovi = other.getIntegerValues();
+			for (int i=0;i<ovi.length;i++){
+				if (!values.contains(ovi[i])){
+					values.add(ovi[i]);
+				}
+			}
+			break;
+		case BOOLEAN_AT:
+			Boolean[] ovb = other.getBooleanValues();
+			for (int i=0;i<ovb.length;i++){
+				if (!values.contains(ovb[i])){
+					values.add(ovb[i]);
+				}
+			}
+			break;
+		case OPAQUE_AT:
+			OpaqueValue[] ovo = other.getOpaqueValues();
+			for (int i=0;i<ovo.length;i++){
+				if (!values.contains(ovo[i])){
+					values.add(ovo[i]);
+				}
+			}
+			break;
+		}
+		
+	}
+
+	
+	/**
+	 * Ensures the types on a List of Strings are consistent according to SLP RFC2608.
+	 * The values are set if no errors are encountered.
+	 * 
+	 * @param a_values
+	 * 			The values to be checked
+	 * @return
+	 * 			The type of the values
+	 * @throws ServiceLocationException
+	 * 			INTERNAL_SYSTEM_ERROR if inconsistent types are discovered
+	 */
+	private int checkAndSetType(List<String> a_values) throws ServiceLocationException{
+		int t = -1;
+		List v;
+		if (a_values.size()<1){
+			throw new ServiceLocationException(ServiceLocationException.INTERNAL_SYSTEM_ERROR,"no values given for this attribute "+name);
+		}
+		String init = a_values.get(0).trim();
+		if (init.startsWith("\\FF")){
+			t=OPAQUE_AT;
+			v=new ArrayList<OpaqueValue>();
+			v.add(new OpaqueValue(init));
+		} else if (init.toLowerCase().equals("true") || init.toLowerCase().equals("false")){
+			t=BOOLEAN_AT;
+			v=new ArrayList<Boolean>();
+			v.add(Boolean.valueOf(init));
+		} else {
+			try {
+				int vi = Integer.parseInt(init);
+				t=INTEGER_AT;
+				v=new ArrayList<Integer>();
+				v.add(vi);
+			} catch (NumberFormatException nfe){
+				t=STRING_AT;
+				v=new ArrayList<String>();
+				v.add(init);
+			}
+		}
+		
+		for (int i=1;i<a_values.size();i++){
+			init=a_values.get(i).trim();
+			if (init.startsWith("\\FF")){
+				if (t!=OPAQUE_AT){
+					throw new ServiceLocationException(ServiceLocationException.INTERNAL_SYSTEM_ERROR,"inconsistent types for this attribute "+name);
+				}
+				v.add(new OpaqueValue(init));
+				
+			} else if (init.toLowerCase().equals("true") || init.toLowerCase().equals("false")){
+				if (t!=BOOLEAN_AT){
+					throw new ServiceLocationException(ServiceLocationException.INTERNAL_SYSTEM_ERROR,"inconsistent types for this attribute "+name);
+				}
+				v.add(Boolean.valueOf(init));
+			} else {
+				try {
+					int vi = Integer.parseInt(init);
+					if (t!=INTEGER_AT){
+						throw new ServiceLocationException(ServiceLocationException.INTERNAL_SYSTEM_ERROR,"inconsistent types for this attribute "+name);
+					}
+					v.add(vi);
+				} catch (NumberFormatException nfe){
+					if (t!=STRING_AT){
+						throw new ServiceLocationException(ServiceLocationException.INTERNAL_SYSTEM_ERROR,"inconsistent types for this attribute "+name);
+					}
+					v.add(init);
+				}
+			}
+			
+		}
+		values=v;
+		return t;
+		
+	}
+	
+	/**
+	 * Ensures the types on a List of Strings are consistent according to SLP RFC2608.
+	 * The values are set if no errors are encountered.
+	 * 
+	 * @param a_values
+	 * 			The values to be checked
+	 * @return
+	 * 			The type of the values
+	 * @throws ServiceLocationException
+	 * 			INTERNAL_SYSTEM_ERROR if inconsistent types are discovered
+	 */
+	private int checkAndSetType(String[] a_values) throws ServiceLocationException{
+		int t = -1;
+		List v;
+		String init = a_values[0].trim();
+		if (init.startsWith("\\FF")){
+			t=OPAQUE_AT;
+			v=new ArrayList<OpaqueValue>();
+			v.add(new OpaqueValue(init));
+		} else if (init.toLowerCase().equals("true") || init.toLowerCase().equals("false")){
+			t=BOOLEAN_AT;
+			v=new ArrayList<Boolean>();
+			v.add(Boolean.valueOf(init));
+		} else {
+			try {
+				int vi = Integer.parseInt(init);
+				t=INTEGER_AT;
+				v=new ArrayList<Integer>();
+				v.add(vi);
+			} catch (NumberFormatException nfe){
+				t=STRING_AT;
+				v=new ArrayList<String>();
+				v.add(init);
+			}
+		}
+		
+		for (int i=1;i<a_values.length;i++){
+			init=a_values[i];
+			if (init.startsWith("\\FF")){
+				if (t!=OPAQUE_AT){
+					throw new ServiceLocationException(ServiceLocationException.INTERNAL_SYSTEM_ERROR,"inconsistent types for this attribute "+name);
+				}
+				v.add(new OpaqueValue(init));
+				
+			} else if (init.toLowerCase().equals("true") || init.toLowerCase().equals("false")){
+				if (t!=BOOLEAN_AT){
+					throw new ServiceLocationException(ServiceLocationException.INTERNAL_SYSTEM_ERROR,"inconsistent types for this attribute "+name);
+				}
+				v.add(Boolean.valueOf(init));
+			} else {
+				try {
+					int vi = Integer.parseInt(init);
+					if (t!=INTEGER_AT){
+						throw new ServiceLocationException(ServiceLocationException.INTERNAL_SYSTEM_ERROR,"inconsistent types for this attribute "+name);
+					}
+					v.add(vi);
+				} catch (NumberFormatException nfe){
+					if (t!=STRING_AT){
+						throw new ServiceLocationException(ServiceLocationException.INTERNAL_SYSTEM_ERROR,"inconsistent types for this attribute "+name);
+					}
+					v.add(init);
+				}
+			}
+			
+		}
+		
+		return t;
+		
+	}
+}

Propchange: directory/sandbox/slp/src/main/java/org/apache/directory/slp/impl/SLPAttributeImpl.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Added: directory/sandbox/slp/src/main/java/org/apache/directory/slp/impl/SLPConfiguration.java
URL: http://svn.apache.org/viewvc/directory/sandbox/slp/src/main/java/org/apache/directory/slp/impl/SLPConfiguration.java?rev=782968&view=auto
==============================================================================
--- directory/sandbox/slp/src/main/java/org/apache/directory/slp/impl/SLPConfiguration.java (added)
+++ directory/sandbox/slp/src/main/java/org/apache/directory/slp/impl/SLPConfiguration.java Tue Jun  9 12:00:29 2009
@@ -0,0 +1,607 @@
+/* 
+ *   Licensed to the Apache Software Foundation (ASF) under one
+ *   or more contributor license agreements.  See the NOTICE file
+ *   distributed with this work for additional information
+ *   regarding copyright ownership.  The ASF licenses this file
+ *   to you under the Apache License, Version 2.0 (the
+ *   "License"); you may not use this file except in compliance
+ *   with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *   Unless required by applicable law or agreed to in writing,
+ *   software distributed under the License is distributed on an
+ *   "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *   KIND, either express or implied.  See the License for the
+ *   specific language governing permissions and limitations
+ *   under the License.
+ *   
+ */
+package org.apache.directory.slp.impl;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.security.GeneralSecurityException;
+import java.security.KeyFactory;
+import java.security.PrivateKey;
+import java.security.PublicKey;
+import java.security.spec.PKCS8EncodedKeySpec;
+import java.security.spec.X509EncodedKeySpec;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Properties;
+import java.util.StringTokenizer;
+
+
+/**
+ * SLPConfiguration object holds all configurable properties.
+ * 
+ * @author Jan S. Rellermeyer
+ */
+public class SLPConfiguration {
+
+	private static final String USE_SCOPES_PROP = "net.slp.useScopes";
+
+	private static final String USE_SCOPES_DEFAULT = "DEFAULT";
+
+	private static final String DA_ADDRESSES_PROP = "net.slp.DAAddresses";
+
+	private static final String DA_ADDRESSES_DEFAULT = null;
+
+	private static final String WAIT_TIME_PROP = "net.slp.waitTime";
+
+	private static final String WAIT_TIME_DEFAULT = "1000";
+
+	private static final String TRACE_DATRAFFIC_PROP = "net.slp.traceDATraffic";
+
+	private static final String TRACE_DATRAFFIC_DEFAULT = "false";
+
+	private static final String TRACE_MESSAGE_PROP = "net.slp.traceMsg";
+
+	private static final String TRACE_MESSAGE_DEFAULT = "false";
+
+	private static final String TRACE_DROP_PROP = "net.slp.traceDrop";
+
+	private static final String TRACE_DROP_DEFAULT = "false";
+
+	private static final String TRACE_REG_PROP = "net.slp.traceReg";
+
+	private static final String TRACE_REG_DEFAULT = "false";
+
+	private static final String MCAST_TTL_PROP = "net.slp.multicastTTL";
+
+	private static final String MCAST_TTL_DEFAULT = "255";
+
+	private static final String MCAST_MAX_WAIT_PROP = "net.slp.multicastMaximumWait";
+
+	private static final String MCAST_MAX_WAIT_DEFAULT = "15000";
+
+	private static final String MCAST_TIMEOUTS_PROP = "net.slp.multicastTimeouts";
+
+	private static final String MCAST_TIMEOUTS_DEFAULT = "3000,2000,1500,1000,750,500";
+
+	private static final String DATAGRAM_MAX_WAIT_PROP = "net.slp.datagramMaximumWait";
+
+	private static final String DATAGRAM_MAX_WAIT_DEFAULT = "5000";
+
+	private static final String DATAGRAM_TIMEOUTS_PROP = "net.slp.datagramTimeouts";
+
+	private static final String DATAGRAM_TIMEOUTS_DEFAULT = "3000,3000,3000,3000,3000";
+
+	private static final String MTU_PROP = "net.slp.MTU";
+
+	private static final String MTU_DEFAULT = "1400";
+
+	private static final String SECURITY_ENABLED_PROP = "net.slp.securityEnabled";
+
+	private static final String SECURITY_ENABLED_DEFAULT = "false";
+
+	private static final String SPI_PROP = "net.slp.spi";
+
+	private static final String SPI_DEFAULT = "";
+
+	private static final String PRIVATE_KEY_PROP = "net.slp.privateKey.";
+
+	private static final String PUBLIC_KEY_PROP = "net.slp.publicKey.";
+
+	private static final String INTERFACES_PROP = "net.slp.interfaces";
+
+	private static final String INTERFACES_DEFAULT = null;
+
+	private static final String NO_DA_DISCOVERY_PROP = "net.slp.noDADiscovery";
+
+	private static final String PORT_PROP = "net.slp.port";
+
+	private static final String DEFAULT_PORT = "427";
+
+	private static final String DEFAULT_CONVERGENCE_FAILERCOUNT = "2";
+
+	private static final String CONVERGENCE_FAILERCOUNT_PROP = "net.slp.failercount";
+
+	private static final String DEBUG_ENABLED_PROP = "ch.ethz.iks.slp.debug";
+
+	private static final String CONFIG_START_WAIT_PROP = "net.slp.configStartWait";
+
+	private static final String CONFIG_START_WAIT_DEFAULT = "3000";
+
+	private static final String CONFIG_DA_FIND_PROP = "net.slp.configDaFind";
+
+	private static final String CONFIG_DA_FIND_DEFAULT = "900000";
+
+	private static final String CONFIG_REG_ACTIVE_PROP = "net.slp.configRegActive";
+
+	private static final String CONFIG_REG_ACTIVE_DEFAULT = "1000";
+
+	private static final String CONFIG_RETRY_PROP = "net.slp.configRetry";
+
+	private static final String CONFIG_RETRY_DEFAULT = "2000";
+
+	private static final String CONFIG_RETRY_MAX_PROP = "net.slp.configRetryMax";
+
+	private static final String CONFIG_RETRY_MAX_DEFAULT = "15000";
+
+	private static final String CONFIG_DA_BEAT_PROP = "net.slp.DAHeartBeat";
+
+	private static final String CONFIG_DA_BEAT_DEFAULT = "10800000"; // 3h
+
+	private static final String CONFIG_DA_ATTRIBUTES_PROP = "net.slp.DAAttributes";
+
+	private static final String CONFIG_DA_ATTRIBUTES_DEFAULT = "";
+
+	private static String[] INTERFACES;
+
+	private static int PORT;
+
+	private static String SCOPES;
+
+	private static boolean NO_DA_DISCOVERY;
+
+	private static String[] DA_ADDRESSES;
+
+	private static boolean TRACE_DA_TRAFFIC;
+
+	private static boolean TRACE_MESSAGES;
+
+	private static boolean TRACE_DROP;
+
+	private static boolean TRACE_REG;
+
+	private static int MCAST_TTL;
+
+	private static int MCAST_MAX_WAIT;
+
+	private static int[] MCAST_TIMEOUTS;
+
+	private static int DATAGRAM_MAX_WAIT;
+
+	private static int[] DATAGRAM_TIMEOUTS;
+
+	private static int MTU;
+
+	private static boolean SECURITY_ENABLED;
+
+	private static String SPI;
+
+	private static int WAIT_TIME;
+
+	private static Map<String, PublicKey> PUBLIC_KEY_CACHE;
+
+	private static Map<String, PrivateKey> PRIVATE_KEY_CACHE;
+
+	private static int CONVERGENCE_FAILERCOUNT;
+
+	private static boolean DEBUG_ENABLED;
+
+	private static int CONFIG_START_WAIT;
+
+	private static int CONFIG_DA_FIND;
+
+	private static int CONFIG_REG_ACTIVE;
+
+	private static int CONFIG_RETRY;
+
+	private static int CONFIG_RETRY_MAX;
+
+	private static int CONFIG_DA_BEAT;
+
+	private static String CONFIG_DA_ATTRIBUTES;
+
+	/**
+	 * create a new SLPConfiguration from properties.
+	 * 
+	 * @param properties
+	 *            properties.
+	 */
+	SLPConfiguration() {
+		processProperties(System.getProperties());
+	}
+
+	/**
+	 * create a new SLPConfiguration from config file.
+	 * 
+	 * @param file
+	 *            the file.
+	 * @throws IOException
+	 *             in case of IO errors.
+	 */
+	SLPConfiguration(final File file) throws IOException {
+		Properties props = new Properties();
+		props.load(new FileInputStream(file));
+		props.putAll(System.getProperties());
+		processProperties(props);
+	}
+
+	private static void processProperties(final Properties props) {
+		String ifaces = props.getProperty(INTERFACES_PROP, INTERFACES_DEFAULT);
+		if (ifaces == null) {
+			INTERFACES = null;
+		} else {
+			INTERFACES = (String[]) SLPUtils.stringToStringArray(ifaces, ",");
+		}
+		PORT = Integer.parseInt(props.getProperty(PORT_PROP, DEFAULT_PORT));
+		SCOPES = props.getProperty(USE_SCOPES_PROP, USE_SCOPES_DEFAULT);
+		NO_DA_DISCOVERY = new Boolean(props.getProperty(NO_DA_DISCOVERY_PROP,
+				"false")).booleanValue();
+		final String dAs = props.getProperty(DA_ADDRESSES_PROP,
+				DA_ADDRESSES_DEFAULT);
+		if (dAs == null) {
+			DA_ADDRESSES = null;
+		} else {
+			DA_ADDRESSES = SLPUtils.stringToStringArray(dAs, ",");
+		}
+		TRACE_DA_TRAFFIC = new Boolean(props.getProperty(TRACE_DATRAFFIC_PROP,
+				TRACE_DATRAFFIC_DEFAULT)).booleanValue();
+		TRACE_MESSAGES = new Boolean(props.getProperty(TRACE_MESSAGE_PROP,
+				TRACE_MESSAGE_DEFAULT)).booleanValue();
+
+		TRACE_DROP = new Boolean(props.getProperty(TRACE_DROP_PROP,
+				TRACE_DROP_DEFAULT)).booleanValue();
+
+		TRACE_REG = new Boolean(props.getProperty(TRACE_REG_PROP,
+				TRACE_REG_DEFAULT)).booleanValue();
+
+		MCAST_TTL = Integer.parseInt(props.getProperty(MCAST_TTL_PROP,
+				MCAST_TTL_DEFAULT));
+
+		MCAST_MAX_WAIT = Integer.parseInt(props.getProperty(
+				MCAST_MAX_WAIT_PROP, MCAST_MAX_WAIT_DEFAULT));
+
+		DATAGRAM_MAX_WAIT = Integer.parseInt(props.getProperty(
+				DATAGRAM_MAX_WAIT_PROP, DATAGRAM_MAX_WAIT_DEFAULT));
+
+		MCAST_TIMEOUTS = parseTimeouts(props.getProperty(MCAST_TIMEOUTS_PROP,
+				MCAST_TIMEOUTS_DEFAULT));
+
+		DATAGRAM_TIMEOUTS = parseTimeouts(props.getProperty(
+				DATAGRAM_TIMEOUTS_PROP, DATAGRAM_TIMEOUTS_DEFAULT));
+
+		MTU = Integer.parseInt(props.getProperty(MTU_PROP, MTU_DEFAULT));
+
+		SECURITY_ENABLED = new Boolean(props.getProperty(SECURITY_ENABLED_PROP,
+				SECURITY_ENABLED_DEFAULT)).booleanValue();
+
+		SPI = props.getProperty(SPI_PROP, SPI_DEFAULT);
+
+		WAIT_TIME = Integer.parseInt(props.getProperty(WAIT_TIME_PROP,
+				WAIT_TIME_DEFAULT));
+
+		CONVERGENCE_FAILERCOUNT = Integer.parseInt(props.getProperty(
+				CONVERGENCE_FAILERCOUNT_PROP, DEFAULT_CONVERGENCE_FAILERCOUNT));
+
+		DEBUG_ENABLED = new Boolean(props.getProperty(DEBUG_ENABLED_PROP,
+				"false")).booleanValue();
+
+		CONFIG_START_WAIT = Integer.parseInt(props.getProperty(
+				CONFIG_START_WAIT_PROP, CONFIG_START_WAIT_DEFAULT));
+
+		CONFIG_DA_FIND = Integer.parseInt(props.getProperty(
+				CONFIG_DA_FIND_PROP, CONFIG_DA_FIND_DEFAULT));
+
+		CONFIG_REG_ACTIVE = Integer.parseInt(props.getProperty(
+				CONFIG_REG_ACTIVE_PROP, CONFIG_REG_ACTIVE_DEFAULT));
+
+		CONFIG_RETRY = Integer.parseInt(props.getProperty(CONFIG_RETRY_PROP,
+				CONFIG_RETRY_DEFAULT));
+
+		CONFIG_RETRY_MAX = Integer.parseInt(props.getProperty(
+				CONFIG_RETRY_MAX_PROP, CONFIG_RETRY_MAX_DEFAULT));
+
+		CONFIG_DA_BEAT = Integer.parseInt(props.getProperty(
+				CONFIG_DA_BEAT_PROP, CONFIG_DA_BEAT_DEFAULT));
+
+		CONFIG_DA_ATTRIBUTES = props.getProperty(CONFIG_DA_ATTRIBUTES_PROP,
+				CONFIG_DA_ATTRIBUTES_DEFAULT);
+
+		if (SECURITY_ENABLED) {
+			PUBLIC_KEY_CACHE = new HashMap<String, PublicKey>(0);
+			PRIVATE_KEY_CACHE = new HashMap<String, PrivateKey>(0);
+		}
+	}
+
+	/**
+	 * returns the network interfaces.
+	 * 
+	 * @return interfaces
+	 */
+	String[] getInterfaces() {
+		return INTERFACES;
+	}
+
+	/**
+	 * get the port.
+	 * 
+	 * @return the port
+	 */
+	int getPort() {
+		return PORT;
+	}
+
+	/**
+	 * get the scopes.
+	 * 
+	 * @return the scopes.
+	 */
+	public String getScopes() {
+		return SCOPES;
+	}
+
+	/**
+	 * get the predefined DA addresses.
+	 * 
+	 * @return the DA addresses.
+	 */
+	String[] getDaAddresses() {
+		return DA_ADDRESSES;
+	}
+
+	/**
+	 * get no DA discovery
+	 * 
+	 * @return true, if DA discovery is disabled
+	 */
+	boolean getNoDaDiscovery() {
+		return NO_DA_DISCOVERY;
+	}
+
+	/**
+	 * trace DA traffic ?
+	 * 
+	 * @return true if trace is enabled.
+	 */
+	boolean getTraceDaTraffic() {
+		return TRACE_DA_TRAFFIC;
+	}
+
+	/**
+	 * trace messages ?
+	 * 
+	 * @return true if trace is enabled.
+	 */
+	boolean getTraceMessage() {
+		return TRACE_MESSAGES;
+	}
+
+	/**
+	 * trace dropped messages ?
+	 * 
+	 * @return true if trace is enabled.
+	 */
+	boolean getTraceDrop() {
+		return TRACE_DROP;
+	}
+
+	/**
+	 * trace registrations ?
+	 * 
+	 * @return true if trace is enabled.
+	 */
+	boolean getTraceReg() {
+		return TRACE_REG;
+	}
+
+	/**
+	 * get the multicast TTL.
+	 * 
+	 * @return the multicast TTL.
+	 */
+	int getMcastTTL() {
+		return MCAST_TTL;
+	}
+
+	/**
+	 * get the multicast max wait time.
+	 * 
+	 * @return the max wait time.
+	 */
+	int getMcastMaxWait() {
+		return MCAST_MAX_WAIT;
+	}
+
+	/**
+	 * get the datagram max wait time.
+	 * 
+	 * @return the datagram max wait time.
+	 */
+	int getDatagramMaxWait() {
+		return DATAGRAM_MAX_WAIT;
+	}
+
+	/**
+	 * parse timeout lists.
+	 * 
+	 * @param s
+	 *            a timeout list string.
+	 * @return the timeout int array.
+	 */
+	private static int[] parseTimeouts(final String s) {
+		StringTokenizer st = new StringTokenizer(s, ",");
+		int[] timeouts = new int[st.countTokens()];
+		for (int i = 0; i < timeouts.length; i++) {
+			timeouts[i] = Integer.parseInt(st.nextToken());
+		}
+		return timeouts;
+	}
+
+	/**
+	 * get the multicast timeouts.
+	 * 
+	 * @return the multicast timeouts.
+	 */
+	int[] getMcastTimeouts() {
+		return MCAST_TIMEOUTS;
+	}
+
+	/**
+	 * get the datagram timeouts.
+	 * 
+	 * @return the datagram timeouts.
+	 */
+	int[] getDatagramTimeouts() {
+		return DATAGRAM_TIMEOUTS;
+	}
+
+	/**
+	 * get the MTU.
+	 * 
+	 * @return the MTU.
+	 */
+	public int getMTU() {
+		return MTU;
+	}
+
+	/**
+	 * is security enabled ?
+	 * 
+	 * @return true if security is enabled.
+	 */
+	public boolean getSecurityEnabled() {
+		return SECURITY_ENABLED;
+	}
+
+	/**
+	 * get the SPIs.
+	 * 
+	 * @return the SPI string list.
+	 */
+	public String getSPI() {
+		return SPI;
+	}
+
+	/**
+	 * get the public key for a certain SPI.
+	 * 
+	 * @param spi
+	 *            the SPI.
+	 * @return the location of the public key.
+	 * @throws IOException
+	 * @throws GeneralSecurityException
+	 */
+	public PublicKey getPublicKey(final String spi) throws IOException,
+			GeneralSecurityException {
+		PublicKey key = (PublicKey) PUBLIC_KEY_CACHE.get(spi);
+		if (key != null) {
+			return key;
+		}
+		FileInputStream keyfis = new FileInputStream(System
+				.getProperty(PUBLIC_KEY_PROP + spi));
+		byte[] encKey = new byte[keyfis.available()];
+		keyfis.read(encKey);
+		keyfis.close();
+		X509EncodedKeySpec pubKeySpec = new X509EncodedKeySpec(encKey);
+		KeyFactory keyFactory = KeyFactory.getInstance("DSA");
+		key = keyFactory.generatePublic(pubKeySpec);
+		PUBLIC_KEY_CACHE.put(spi, key);
+		return key;
+	}
+
+	/**
+	 * get the private key for a certain SPI.
+	 * 
+	 * @param spi
+	 *            the SPI.
+	 * @return the location of the private key.
+	 * @throws IOException
+	 * @throws GeneralSecurityException
+	 */
+	public PrivateKey getPrivateKey(final String spi) throws IOException,
+			GeneralSecurityException {
+		PrivateKey key = (PrivateKey) PRIVATE_KEY_CACHE.get(spi);
+		if (key != null) {
+			return key;
+		}
+		FileInputStream keyfis = new FileInputStream(System
+				.getProperty(PRIVATE_KEY_PROP + spi));
+
+		byte[] encKey = new byte[keyfis.available()];
+		keyfis.read(encKey);
+		keyfis.close();
+
+		PKCS8EncodedKeySpec privKeySpec = new PKCS8EncodedKeySpec(encKey);
+
+		KeyFactory keyFactory = KeyFactory.getInstance("DSA");
+		key = keyFactory.generatePrivate(privKeySpec);
+		PRIVATE_KEY_CACHE.put(spi, key);
+		return key;
+	}
+
+	/**
+	 * get the default wait time.
+	 * 
+	 * @return the default wait time.
+	 */
+	int getWaitTime() {
+		return WAIT_TIME;
+	}
+
+	/**
+	 * Defines after how many inconclusive multicastConvergence cycles the
+	 * attempt is aborted. It indirectly defines how many multicast convergence
+	 * {@link SLPMessage}.SRVTYPERQST get send during an attempt.
+	 * 
+	 * This value can be seen as an heuristical optimization to stop multicast
+	 * convergence early if inconclusive
+	 * 
+	 * @return how many inconclusive cycles are allowed
+	 */
+	int getConvergenceFailerCount() {
+		return CONVERGENCE_FAILERCOUNT;
+	}
+
+	public boolean getDebugEnabled() {
+		return DEBUG_ENABLED;
+	}
+
+	public int getTCPTimeout() {
+		// TODO wire this to the properties if necessary
+		return 5000; // 5sec
+	}
+
+	public int getConfigStartWait() {
+		return CONFIG_START_WAIT;
+	}
+
+	public int getConfigDaFind() {
+		return CONFIG_DA_FIND;
+	}
+
+	public int getConfigRegActive() {
+		return CONFIG_REG_ACTIVE;
+	}
+
+	public int getConfigRetry() {
+		return CONFIG_RETRY;
+	}
+
+	public int getConfigRetryMax() {
+		return CONFIG_RETRY_MAX;
+	}
+
+	public int getConfigDABeat() {
+		return CONFIG_DA_BEAT;
+	}
+
+	public String getConfigDAAttributes() {
+		return CONFIG_DA_ATTRIBUTES;
+	}
+}

Propchange: directory/sandbox/slp/src/main/java/org/apache/directory/slp/impl/SLPConfiguration.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Added: directory/sandbox/slp/src/main/java/org/apache/directory/slp/impl/SLPCore.java
URL: http://svn.apache.org/viewvc/directory/sandbox/slp/src/main/java/org/apache/directory/slp/impl/SLPCore.java?rev=782968&view=auto
==============================================================================
--- directory/sandbox/slp/src/main/java/org/apache/directory/slp/impl/SLPCore.java (added)
+++ directory/sandbox/slp/src/main/java/org/apache/directory/slp/impl/SLPCore.java Tue Jun  9 12:00:29 2009
@@ -0,0 +1,1422 @@
+/* 
+ *   Licensed to the Apache Software Foundation (ASF) under one
+ *   or more contributor license agreements.  See the NOTICE file
+ *   distributed with this work for additional information
+ *   regarding copyright ownership.  The ASF licenses this file
+ *   to you under the Apache License, Version 2.0 (the
+ *   "License"); you may not use this file except in compliance
+ *   with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *   Unless required by applicable law or agreed to in writing,
+ *   software distributed under the License is distributed on an
+ *   "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *   KIND, either express or implied.  See the License for the
+ *   specific language governing permissions and limitations
+ *   under the License.
+ *   
+ */
+package org.apache.directory.slp.impl;
+
+
+import java.io.File;
+import java.io.IOException;
+import java.lang.reflect.Constructor;
+import java.net.InetAddress;
+import java.net.InetSocketAddress;
+import java.net.NetworkInterface;
+import java.net.SocketException;
+import java.net.UnknownHostException;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Enumeration;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Locale;
+import java.util.Map;
+import java.util.concurrent.Executors;
+
+import org.apache.directory.slp.ReplyFuture;
+import org.apache.directory.slp.ServiceLocationException;
+import org.apache.directory.slp.ServiceStore;
+import org.apache.directory.slp.ServiceType;
+import org.apache.directory.slp.codec.SLPProtocolCodecFactory;
+import org.apache.directory.slp.impl.da.DirectoryAgentDaemon;
+import org.apache.directory.slp.messages.AbstractSLPMessage;
+import org.apache.directory.slp.messages.AbstractSLPReplyMessage;
+import org.apache.directory.slp.messages.AbstractSLPRequestMessage;
+import org.apache.directory.slp.messages.DAAdvertisementMessage;
+import org.apache.directory.slp.messages.ServiceRequestMessage;
+import org.apache.mina.core.future.ConnectFuture;
+import org.apache.mina.core.future.WriteFuture;
+import org.apache.mina.core.session.IoSession;
+import org.apache.mina.filter.codec.ProtocolCodecFilter;
+import org.apache.mina.filter.executor.ExecutorFilter;
+import org.apache.mina.transport.socket.DatagramSessionConfig;
+import org.apache.mina.transport.socket.apr.AprDatagramAcceptor;
+import org.apache.mina.transport.socket.apr.AprDatagramConnector;
+import org.apache.mina.transport.socket.apr.AprDatagramSession;
+import org.apache.mina.transport.socket.apr.AprSocketAcceptor;
+import org.apache.mina.transport.socket.apr.AprSocketConnector;
+
+/**
+ * the core class of the jSLP implementation.
+ * <code>ch.ethz.iks.slp.ServiceLocationManager</code> inherits from this
+ * class.
+ * 
+ * @see ch.ethz.iks.slp.impl.ServiceLocationManager
+ * @author Jan S. Rellermeyer
+ */
+public class SLPCore {
+
+	private static volatile boolean isInitialized = false;
+	private static volatile boolean isListening = false; // is the UA listening for adverts?
+	private static volatile boolean isSAInitialized = false;
+	private static volatile boolean isDAInitialized = false;
+
+	protected static PlatformAbstraction platform;
+
+	/**
+	 * the default empty locale. Used for messages that don't specify a locale.
+	 */
+	static public final Locale DEFAULT_LOCALE = Locale.getDefault();
+
+	/**
+	 * the port for SLP communication.
+	 */
+	public static final int SLP_PORT;
+
+	/**
+	 * the reserved (standard) port.
+	 */
+	public static final int SLP_RESERVED_PORT = 427; 
+
+	/**
+	 * the standard SLP multicast address.
+	 */
+	public static final String SLP_MCAST_ADDRESS = "239.255.255.253";
+
+	/**
+	 * 
+	 */
+	public static final InetAddress MCAST_ADDRESS;
+
+	/**
+	 * the SLP configuration.
+	 */
+	public static final SLPConfiguration CONFIG;
+
+	/**
+	 * currently only for debugging.
+	 */
+	static final boolean TCP_ONLY = false;
+
+	/**
+	 * the standard service type for DAs.
+	 */
+	static final String SLP_DA_TYPE = "service:directory-agent";
+
+	/**
+	 * my own ip. Used to check if this peer is already in the previous
+	 * responder list.
+	 */
+	static String[] myIPs;
+
+	/**
+	 * configured to perform no DA discovery ?
+	 */
+	static final boolean noDiscovery;
+	static String discoveryException="";
+
+	/**
+	 * the constructor for <code>Advertiser</code> instances, if an
+	 * implementation exists.
+	 */
+	protected static final Constructor advertiser;
+
+	/**
+	 * the constructor for <code>Locator</code> instances, if an
+	 * implementation exists.
+	 */
+	protected static final Constructor locator;
+
+	/**
+	 * the constructor for <code>SLPDaemon</code> instances, if an
+	 * implementation exists.
+	 */
+	private static final Constructor daemonConstr;
+
+	/**
+	 * the daemon instance, if the implementation exists and no other daemon is
+	 * already running on the machine.
+	 */
+	private static SLPDaemon daemon;
+
+
+	/**
+	 * the constructor for <code>DirectoryAgent</code> instances, if an
+	 * implementation exists.
+	 */
+	protected static final Constructor directoryAgent;
+
+	/**
+	 * the constructor for <code>DirectoryAgentDaemon</code> instances, if an
+	 * implementation exists.
+	 */
+	protected static final Constructor daDaemonConstr;
+
+
+	/**
+	 * the DA daemon instance, if the implementation exists and no other DA is
+	 * already running on the machine. 
+	 */
+	public static DirectoryAgentDaemon daDaemon;
+
+
+	/**
+	 * the next free XID.
+	 */
+	private static short nextXid;
+
+	/**
+	 * used to asynchronously receive replies. query XID -> reply queue (List)
+	 */
+	private static Map<Integer,List<AbstractSLPMessage>> replyListeners = new HashMap<Integer,List<AbstractSLPMessage>>();
+
+	/**
+	 * Map of DAs:
+	 * 
+	 * String scope -> list of Strings of DA URLs.
+	 */
+	static Map<String,List<String>> dAs = new HashMap<String,List<String>>();
+
+	
+	/**
+	 * Map of sBTs for known DAs:
+	 * 
+	 * String IP-Address -> Integer (32bit timestamp)
+	 * 
+	 */
+	static Map<String,Integer> statelessBootTimestamps = new HashMap<String, Integer>();
+	
+	
+	/**
+	 * Map of DA SPIs:
+	 * 
+	 * String DA URL -> String String.
+	 */
+	static Map<String,List<String>> dASPIs = new HashMap<String,List<String>>(); // DA URL -> List of SPIs
+
+
+	/**
+	 * timestamp of last DA lookup. According to RFC2608 a DA lookup may only be performed every CONFIG_DA_FIND seconds
+	 */
+	private static long lastDaLookup = 0;
+
+	static InetAddress LOCALHOST;
+
+	/**
+	 * MINA Connectors (outgoing)
+	 * 
+	 * SLPCore sends all messages, yet receives only replies.
+	 * The daemon listens for incoming UDP and TCP packets (requests) on SLP_PORT
+	 * 
+	 */
+	private static AprDatagramConnector sender; //sends UDP packets (default)
+	private static AprDatagramConnector[] senderList; //one for each interface
+
+
+	//We also need a SocketConnector to send messages by TCP if necessary (and get the reply)
+	private static AprSocketConnector tcpsender;
+
+	//we also need dynamic acceptors to be able to listen for replies to multicast messages
+	private static AprDatagramAcceptor[] receiverList;
+
+	// the main receiver listening on the SLP port.
+	// UAs: receive multicast DAAdverts
+	// SAs: receive SrvRqsts
+	// DAs: the whole !#
+	private static AprDatagramAcceptor multicastAcceptor;
+	private static AprSocketAcceptor multicastTCPAcceptor;
+
+	private static final SLPHandler handler = new SLPHandler();
+
+	
+	/**
+	 * initialize the core class.
+	 */
+	static {
+		try {
+			LOCALHOST = InetAddress.getLocalHost();
+		} catch (Throwable t) {
+			t.printStackTrace();
+		}
+
+		final Class[] locale = new Class[] { Locale.class };
+
+		// check, if an Advertiser implementation is available
+		Constructor constr = null;
+		try {
+			constr = Class.forName("ch.ethz.iks.slp.impl.AdvertiserImpl")
+			.getConstructor(locale);
+		} catch (Exception e) {
+		}
+		advertiser = constr;
+
+		// check, if a Locator implementation is available
+		constr = null;
+		try {
+			constr = Class.forName("ch.ethz.iks.slp.impl.LocatorImpl")
+			.getConstructor(locale);
+		} catch (Exception e) {
+		}
+		locator = constr;
+
+		//		 check, if a DA is available
+		constr = null;
+		try {
+			constr = Class.forName("ch.ethz.iks.slp.impl.da.DirectoryAgentImpl")
+			.getConstructor(new Class[]{});
+		} catch (Exception e) {
+		}
+		directoryAgent = constr;
+
+		// check, if a Daemon is available
+		constr = null;
+		try {
+			constr = Class.forName("ch.ethz.iks.slp.impl.SLPDaemonImpl")
+			.getConstructor(new Class[]{});
+		} catch (Exception e) {
+		}
+		daemonConstr = constr;
+
+
+		// check, if a DADaemon is available
+		constr = null;
+		try {
+			constr = Class.forName("ch.ethz.iks.slp.impl.da.DirectoryAgentDaemonImpl")
+			.getConstructor(new Class[]{});
+		} catch (Exception e) {
+		}
+		daDaemonConstr = constr;
+
+
+		// read in the property file, if it exists
+		File propFile = new File("jslp.properties");
+		SLPConfiguration config;
+		try {
+			config = propFile.exists() ? new SLPConfiguration(propFile)
+			: new SLPConfiguration();
+		} catch (IOException e1) {
+			System.out.println("Could not parse the property file" + propFile.toString());
+			e1.printStackTrace();
+			config = new SLPConfiguration();
+		}
+		CONFIG = config;
+
+		noDiscovery = CONFIG.getNoDaDiscovery();
+
+		// determine the interfaces on which jSLP runs on
+		String[] IPs = CONFIG.getInterfaces();
+		if (IPs == null) {
+			List<String> workingInterfaces = new ArrayList<String>();
+			try {
+				// changed by Lorenz to work on Debian systems
+				Enumeration<NetworkInterface> nets = NetworkInterface.getNetworkInterfaces();
+				for (NetworkInterface intf : Collections.list(nets)){
+					Enumeration<InetAddress> inetAdds = intf.getInetAddresses();
+					String ip = "";
+					while (inetAdds.hasMoreElements()){
+						ip = inetAdds.nextElement().getHostAddress();
+						if (ip.indexOf(":")==-1){
+							break;
+						}
+					}
+
+					if (!ip.equals("") && ip.indexOf(":")==-1){
+						workingInterfaces.add(ip);
+					}
+
+				}
+			} catch (SocketException se){
+
+			}
+			IPs = workingInterfaces.toArray(new String[]{});
+
+
+		}
+		myIPs = IPs;
+		SLP_PORT = CONFIG.getPort();
+
+		// initialize the XID with a random number
+		nextXid = (short) Math.round(Math.random() * Short.MAX_VALUE);
+
+		InetAddress mcast = null;
+		try {
+			mcast = InetAddress.getByName(SLPCore.SLP_MCAST_ADDRESS);
+		} catch (UnknownHostException e1) {
+			e1.printStackTrace();
+		}
+
+		MCAST_ADDRESS = mcast;
+	}
+
+
+
+	/**
+	 * Initialize the daemon for the SA
+	 */
+	protected static void initSA(){
+
+		if (isSAInitialized){
+			return;
+		}
+		if (!isInitialized){
+			init();
+		}
+		if (!isListening) {
+			try {
+				initializeListeners();
+			} catch (ServiceLocationException sle){
+				System.out.println("[SLPCORE]: Unable to initialize MINA aceptors, aborting");
+				//System.exit(1);
+			}
+		}
+		
+		// check, if there is already a SLP daemon runnung on port 427
+		// that can be either a jSLP daemon, or an OpenSLP daemon or something
+		// else. If not, try to start a new daemon instance.
+		if (daemonConstr != null) {
+			try {
+				daemon = (SLPDaemon) daemonConstr.newInstance(new Object[]{});
+				isSAInitialized=true;
+			} catch (Exception e) {
+				daemon = null;
+			}
+		}
+		isSAInitialized = true;
+		
+		String[] daAddresses = CONFIG.getDaAddresses();
+		if (daAddresses == null) {
+			if (noDiscovery) {
+				throw new IllegalArgumentException(
+				"Configuration 'net.slp.noDaDiscovery=true' requires a non-empty list of preconfigured DAs");
+			}
+		} else {
+			try {
+
+				// process the preconfigured DAs
+				final ServiceRequestMessage req = new ServiceRequestMessage();
+				req.setServiceType(new ServiceType(SLP_DA_TYPE));
+				for (int i = 0; i < daAddresses.length; i++) {
+					try {
+						InetAddress addr = InetAddress.getByName(daAddresses[i]);
+						discoveryException = daAddresses[i];
+						InetSocketAddress sock = new InetSocketAddress(addr,SLP_PORT);
+						DAAdvertisementMessage daa = (DAAdvertisementMessage) sendUnicastMessage(
+								req,sock, true);
+						if (daa==null){
+							platform.logWarning("Error communicating with " + daAddresses[i]);
+							continue;
+						}
+						discoveryException = "";
+						String[] scopes = (String[]) daa.getScopes();
+						for (int j = 0; j < scopes.length; j++) {
+							platform.logDebug("jSLP is adding DA, "
+									+ daAddresses[i] + " for the Scope, "
+									+ scopes[j]);
+							SLPUtils.addValue(dAs, scopes[i].toLowerCase(), daAddresses[i]);
+						}
+					} catch (ServiceLocationException e) {
+						discoveryException = "";
+						platform.logWarning("Error communicating with " + daAddresses[i], e);
+					} catch (UnknownHostException e) {
+						discoveryException="";
+						platform.logWarning("Unknown net.slp.DAAddresses address: " + daAddresses[i], e);
+					}
+				}
+			} catch (IllegalArgumentException ise) {
+				discoveryException="";
+				platform.logDebug("May never happen", ise);
+			}
+		}
+
+	}
+
+	protected static void initDA(ServiceStore store){
+
+		if (isDAInitialized){
+			return;
+		}
+		if (!isInitialized){
+			init();
+		}
+		if (!isListening) {
+			try {
+				initializeListeners();
+			} catch (ServiceLocationException sle){
+				System.out.println("[SLPCORE]: Unable to initialize MINA aceptors, aborting");
+			}
+		}
+
+		
+
+		// TODO: localization
+		if (daDaemonConstr != null) {
+			try {
+				daDaemon = (DirectoryAgentDaemon) daDaemonConstr.newInstance(new Object[]{});
+				daDaemon.setStore(store);
+				isDAInitialized=true;
+			} catch (Exception e) {
+				e.printStackTrace();
+				daDaemon = null;
+			}
+		}
+
+	}
+
+
+	protected static void init() {
+		if(isInitialized) {
+			return;
+		}
+
+		initializeMina();
+
+
+		isInitialized = true;
+
+		platform.logDebug("jSLP is running on the following interfaces: "
+				+ java.util.Arrays.asList(myIPs));
+		platform.logDebug("jSLP is using port: " + SLP_PORT);
+
+		String[] daAddresses = CONFIG.getDaAddresses();
+		if (daAddresses == null) {
+			if (noDiscovery) {
+				throw new IllegalArgumentException(
+				"Configuration 'net.slp.noDaDiscovery=true' requires a non-empty list of preconfigured DAs");
+			}
+		} else {
+			try {
+
+				// process the preconfigured DAs
+				final ServiceRequestMessage req = new ServiceRequestMessage();
+				req.setServiceType(new ServiceType(SLP_DA_TYPE));
+				for (int i = 0; i < daAddresses.length; i++) {
+					try {
+						InetAddress addr = InetAddress.getByName(daAddresses[i]);
+						InetSocketAddress sock = new InetSocketAddress(addr,SLP_PORT);
+						DAAdvertisementMessage daa = (DAAdvertisementMessage) sendUnicastMessage(
+								req,sock, true);
+						if (daa==null){
+							platform.logWarning("Error communicating with " + daAddresses[i]);
+							continue;
+						}
+						String[] scopes = (String[]) daa.getScopes();
+						for (int j = 0; j < scopes.length; j++) {
+							platform.logDebug("jSLP is adding DA, "
+									+ daAddresses[i] + " for the Scope, "
+									+ scopes[j]);
+							SLPUtils.addValue(dAs, scopes[i].toLowerCase(), daAddresses[i]);
+						}
+					} catch (ServiceLocationException e) {
+						platform.logWarning("Error communicating with " + daAddresses[i], e);
+					} catch (UnknownHostException e) {
+						platform.logWarning("Unknown net.slp.DAAddresses address: " + daAddresses[i], e);
+					}
+				}
+			} catch (IllegalArgumentException ise) {
+				platform.logDebug("May never happen", ise);
+			}
+		}
+
+		if (!noDiscovery) {
+			// perform an initial lookup
+			try {
+				List<String> scopes = new ArrayList<String>();
+				scopes.add("default");
+				//	wait CONFIG_START_WAIT
+				// added by Lorenz just to make it clear that RFC2608 section 12.2.1 has been considered
+				long rand = Math.round(Math.random()*CONFIG.getConfigStartWait());
+				Thread.sleep(rand);
+				daLookup((String[]) scopes.toArray(new String[]{}));
+			} catch (Exception e) {
+				platform.logError("Exception in initial DA lookup", e);
+			}
+		}
+
+	}
+
+	public static synchronized void shutdownAdvertiser(){
+		daemon=null;
+		isSAInitialized= false;
+	}
+
+	public static synchronized void shutdownDirectoryAgent(){
+		if (daDaemon!=null){
+			daDaemon.shutdown();
+		}
+		daDaemon=null;
+		isDAInitialized = false;
+	}
+
+//	public static synchronized void shutdownUserAgent(){
+//		if (!isSAInitialized && !isDAInitialized && isInitialized){
+//			sender.dispose();
+//			for (AprDatagramConnector ac : senderList){
+//				ac.dispose();
+//			}
+//			tcpsender.dispose();
+//			for (AprDatagramAcceptor aa : receiverList){
+//				aa.dispose();
+//			}
+//			multicastAcceptor.dispose();
+//			multicastTCPAcceptor.dispose();
+//			isInitialized = false;
+//		}
+//	}
+	
+	
+	/**
+	 * get my own IP.
+	 * 
+	 * @return the own IP.
+	 */
+	public static InetAddress getMyIP() {
+		try {
+			int i = 0;
+			String result = myIPs[i];
+			while ((result.equals("127.0.0.1") || result.equals("127.0.1.1")) && (myIPs.length > (i+1))){
+				result = myIPs[i];
+			}
+
+			if (result.equals("127.0.1.1")){
+				return InetAddress.getByName("127.0.0.1");
+			}
+			return InetAddress.getByName(result);
+
+		} catch (UnknownHostException e) {
+			platform.logError("Unknown net.slp.interfaces address: " + myIPs[0], e);
+			return null;
+		}
+	}
+
+	/**
+	 * get the list of all available scopes.
+	 * 
+	 * @return a List of all available scopes. RFC 2614 proposes
+	 *         <code>Vector</code> but jSLP returns <code>List</code>.
+	 * @throws ServiceLocationException
+	 *             in case of an exception in the underlying framework.
+	 */
+	public static List<String> findScopes() throws ServiceLocationException {
+		return new ArrayList<String>(dAs.keySet());
+	}
+
+
+
+	/**
+	 * get the next XID.
+	 * 
+	 * @return the next XID.
+	 */
+	static short nextXid() {
+		if (nextXid == 0) {
+			nextXid = 1;
+		}
+		return nextXid++;
+	}
+
+	/**
+	 * find DAs for the scopes by sending a multicast service request for
+	 * service <i>service:directory-agent</i>.
+	 * 
+	 * First parameter changed from List to String[] for compatibility reasons
+	 * 
+	 * @param scopes
+	 *            an <code>Array</code> of scopes.
+	 * @throws ServiceLocationException
+	 *             in case of network errors.
+	 */
+	static void daLookup(final String[] scopes) throws ServiceLocationException {
+
+		// added by Lorenz to ensure adherence to RFC2608 section 12.2.1
+		if ((System.currentTimeMillis()-lastDaLookup) < CONFIG.getConfigDaFind()){
+			// oops, too soon...
+			return;
+		}
+		receiverList = new AprDatagramAcceptor[myIPs.length];
+		try {
+			// change by TomoTherapy Inc
+			// added loop for each IP for each interface
+			// used 1.4 SocketAddress
+			// altered by Jan to be backwards compatible with Java 2
+			// changed by Lorenz to send the same message out on each interface and then wait...
+//			build a ServiceRequestMessage
+			ServiceRequestMessage sreq = new ServiceRequestMessage();
+			sreq.setServiceType(new ServiceType(SLP_DA_TYPE));
+			sreq.setScopes(scopes);
+			sreq.setLocale(SLPCore.DEFAULT_LOCALE);
+			sreq.setXid(SLPCore.nextXid());
+			sreq.setMulticast(true);
+			InetSocketAddress addr = new InetSocketAddress(MCAST_ADDRESS, SLP_PORT);
+			WriteFuture[] futures = new WriteFuture[myIPs.length];
+			// send the message over each interface with the same xid
+			for (int i = 0; i < myIPs.length; i++) {
+				try {
+					platform.logTraceMessage("SENT " + sreq + "(udp multicast)");
+					ConnectFuture connFuture = senderList[i].connect(addr);
+					connFuture.await();
+					IoSession session = (AprDatagramSession) connFuture.getSession();
+					InetSocketAddress local = (InetSocketAddress) session.getLocalAddress();
+					receiverList[i] = initReceiver(local);
+					futures[i] = session.write(sreq);
+					platform.logTraceMessage("SENT (" + addr.getHostName() + ":" + addr.getPort() + ") "
+							+ sreq + " (via udp port " +((InetSocketAddress) session.getLocalAddress()).getPort()+")");
+				} catch (InterruptedException ie){
+					// what do i have to de here?
+				}
+			} 
+			// make sure the unused receivers are disposed when their lifetime is up
+			setupReceiverThread(CONFIG.getWaitTime());
+			// check if they all went out
+			for (int i = 0; i < futures.length; i++) {
+				boolean success = false;
+				try {
+					// it would actually be better to wait for a total of WaitTime, not WaitTime per future...
+					success = futures[i].await(CONFIG.getWaitTime());
+				} catch (InterruptedException ie){
+					// what do i have to do here? decrement i and continue? 
+				}
+				if (!success) {
+					// blacklist address
+					final List<String> remaining = new ArrayList<String>(java.util.Arrays
+							.asList(myIPs));
+					final String faulty = myIPs[i];
+					remaining.remove(faulty);
+					myIPs = (String[]) remaining.toArray(new String[remaining
+					                                                .size()]);
+					platform.logDebug("Blacklisting IP " + faulty);
+				} 
+			}
+			// don't forget to set the timestamp ;)
+			lastDaLookup = System.currentTimeMillis();
+
+		} catch (IllegalArgumentException ise) {
+			platform.logDebug("May never happen, no filter set", ise);
+		}
+	}
+
+	/**
+	 * send a unicast message over TCP. 
+	 * 
+	 * @param msg
+	 *            the message.
+	 * @return the reply.
+	 * @throws ServiceLocationException
+	 *             in case of network errors.
+	 */
+	static AbstractSLPReplyMessage sendMessageTCP(final AbstractSLPMessage msg,final InetSocketAddress addr, final boolean expectReply)
+	throws ServiceLocationException {
+		try {
+			// Debian and co. have an entry for 127.0.1.1 which leads to problems, 
+			//therefor that address is changed to 127.0.0.1
+			InetSocketAddress sendAddr = addr;
+			if (addr.getAddress().getHostAddress().equals("127.0.1.1")){
+				sendAddr = new InetSocketAddress("127.0.0.1",SLP_PORT);
+			}
+			if (msg.getXid() == 0) {
+				msg.setXid(nextXid());
+			}
+			ConnectFuture future1 = tcpsender.connect(sendAddr);
+			future1.awaitUninterruptibly();
+			if (!future1.isConnected()) {
+				throw new ServiceLocationException(ServiceLocationException.NETWORK_INIT_FAILED,"Unable to open TCP socket");
+			}
+			IoSession session = future1.getSession();            
+			session.write(msg);
+			platform.logTraceMessage("SENT (" + addr.getAddress().getHostAddress() + ":" + addr.getPort() + ") "
+					+ msg + " (via tcp port " + ((InetSocketAddress)session.getLocalAddress()).getPort()
+					+ ")");
+
+			if (!expectReply){
+				session.close(false);
+				return null;
+			}
+
+//			need to wait for a reply that is handled by the receiver
+			synchronized (replyListeners){
+				List<AbstractSLPMessage> reply = (List<AbstractSLPMessage>) replyListeners.get(new Integer(msg.getXid()));
+				long start = System.currentTimeMillis();
+				while(reply.isEmpty()){
+					if (System.currentTimeMillis()-start>SLPCore.CONFIG.getWaitTime()){
+						session.close(false);
+						throw new ServiceLocationException(ServiceLocationException.NETWORK_TIMED_OUT,"Reply timed out");
+					}
+					replyListeners.wait(SLPCore.CONFIG.getWaitTime(),SLPCore.CONFIG.getWaitTime());
+				}
+				session.close(false);
+				return (AbstractSLPReplyMessage) reply.get(0);
+			}
+
+
+		} catch (Exception e) {
+			throw new ServiceLocationException(
+					ServiceLocationException.NETWORK_ERROR, e.getMessage());
+		}
+	}
+
+	/**
+	 * send a unicast message over UDP.
+	 * 
+	 * @param msg
+	 *            the message to be sent.
+	 * @param addr
+	 * 			  the InetSocketAddress containing the destination address
+	 * @param expectReply
+	 *            waits for a reply if set to true.
+	 * @return the reply.
+	 * @throws ServiceLocationException
+	 *             in case of network errors etc.
+	 */
+	static AbstractSLPReplyMessage sendReliableUnicastMessage(final AbstractSLPMessage msg,final InetSocketAddress addr,
+			final boolean expectReply) throws ServiceLocationException {
+		List<AbstractSLPMessage> reply = new ArrayList<AbstractSLPMessage>();
+		if (msg.getXid() == 0) {
+			msg.setXid(nextXid());
+		}
+		if (msg.getSize() > CONFIG.getMTU() || TCP_ONLY) {
+			return sendMessageTCP(msg, addr, expectReply);
+		}
+		try {
+
+			//register this send event to catch replies
+			if (expectReply){
+				synchronized (replyListeners){
+					reply = new ArrayList<AbstractSLPMessage>();
+					replyListeners.put(new Integer(msg.getXid()), reply);
+				}
+			}
+			// Again, Debian can mess things up a bit, so we fix that here...
+			InetSocketAddress sendAddr = addr;
+			if (addr.getAddress().getHostAddress().equals("127.0.1.1")){
+				sendAddr = new InetSocketAddress("127.0.0.1",addr.getPort());
+			}
+			ConnectFuture connFuture = sender.connect(sendAddr);
+			connFuture.await(CONFIG.getDatagramMaxWait());
+			if (!connFuture.isConnected()){
+				platform.logError("Failed to send over udp: "+msg+" to "+addr.getAddress().getHostAddress()+":"+addr.getPort());
+				return null;
+			}
+			IoSession session = (AprDatagramSession) connFuture.getSession();
+			session.write(msg);
+
+			platform.logTraceMessage("SENT (" + addr.getAddress().getHostAddress() + ":" + addr.getPort() + ") "
+					+ msg + " (via udp port " +((InetSocketAddress) session.getLocalAddress()).getPort()
+					+ ")");
+			if (!expectReply){
+				session.close(false);
+				return null;
+			}
+
+
+
+
+			// changed by Lorenz to ensure operation according to RFC2608 section 12.3
+			//need to wait for a reply that is handled by the receiver
+			synchronized (replyListeners){
+
+				reply=(List<AbstractSLPMessage>) replyListeners.get(new Integer(msg.getXid()));
+			}
+			synchronized (reply){
+				long now = System.currentTimeMillis();
+				long finalTimeout = now + CONFIG.getConfigRetryMax();
+				long waittime = CONFIG.getConfigRetry();
+				while(reply.isEmpty()){
+					if ((now=System.currentTimeMillis())>=finalTimeout){
+						return null;
+					}
+					reply.wait(waittime);
+					if (reply.isEmpty()){
+						// resend
+						if (session.isConnected()){
+							session.write(msg);
+						} else {
+							return null;
+						}
+						now = System.currentTimeMillis();
+						waittime = 2*waittime;
+					}
+				}
+				AbstractSLPReplyMessage r = (AbstractSLPReplyMessage) reply.get(0);
+				//remove the "waiting for reply" registration
+				replyListeners.remove(new Integer(msg.getXid()));
+				session.close(false);
+				return r;
+			}
+
+
+		} catch (Throwable t) {
+			if (t instanceof IllegalMonitorStateException){
+				platform.logDebug(t.getMessage(), t);
+				throw new ServiceLocationException(ServiceLocationException.NETWORK_TIMED_OUT,"Reply timed out");
+			} else {
+				platform.logDebug(t.getMessage(), t);
+				throw new ServiceLocationException((short) 1, t.getMessage());
+			}
+		}
+	}
+
+
+	/**
+	 * send a unicast message over UDP.
+	 * 
+	 * @param msg
+	 *            the message to be sent.
+	 * @param addr
+	 * 			  the InetSocketAddress containing the destination address
+	 * @param expectReply
+	 *            waits for a reply if set to true.
+	 * @return the reply.
+	 * @throws ServiceLocationException
+	 *             in case of network errors etc.
+	 */
+	public static AbstractSLPReplyMessage sendUnicastMessage(final AbstractSLPMessage msg,final InetSocketAddress addr,
+			final boolean expectReply) throws ServiceLocationException {
+		List<AbstractSLPMessage> reply = new ArrayList<AbstractSLPMessage>();
+		if (msg.getXid() == 0) {
+			msg.setXid(nextXid());
+		}
+		if (msg.getSize() > CONFIG.getMTU() || TCP_ONLY) {
+			return sendMessageTCP(msg, addr, expectReply);
+		}
+		try {
+
+			//register this send event to catch replies
+			if (expectReply){
+				synchronized (replyListeners){
+					reply = new ArrayList<AbstractSLPMessage>();
+					replyListeners.put(new Integer(msg.getXid()), reply);
+				}
+			}
+			// Again, Debian can mess things up a bit, so we fix that here...
+			InetSocketAddress sendAddr = addr;
+			if (addr.getAddress().getHostAddress().equals("127.0.1.1")){
+				sendAddr = new InetSocketAddress("127.0.0.1",addr.getPort());
+			}
+			ConnectFuture connFuture = sender.connect(sendAddr);
+			connFuture.await(CONFIG.getDatagramMaxWait());
+			if (!connFuture.isConnected()){
+				platform.logError("Failed to send over udp: "+msg+" to "+addr.getAddress().getHostAddress()+":"+addr.getPort());
+				return null;
+			} 
+			IoSession session = (AprDatagramSession) connFuture.getSession();
+			session.write(msg);
+
+			platform.logTraceMessage("SENT (" + addr.getAddress().getHostAddress() + ":" + addr.getPort() + ") "
+					+ msg + " (via udp port " +((InetSocketAddress) session.getLocalAddress()).getPort()
+					+ ")");
+			if (!expectReply){
+				session.close(false);
+				return null;
+			}
+
+
+
+			//need to wait for a reply that is handled by the receiver
+			synchronized (replyListeners){
+
+				reply=(List<AbstractSLPMessage>) replyListeners.get(new Integer(msg.getXid()));
+			}
+			synchronized (reply){
+				long now = System.currentTimeMillis();
+				long timeout = System.currentTimeMillis()+CONFIG.getDatagramMaxWait();
+				while(reply.isEmpty()){
+					if ((now=System.currentTimeMillis())>=timeout){
+						return null;
+					}
+					reply.wait(timeout-now);
+				}
+				AbstractSLPReplyMessage r = (AbstractSLPReplyMessage) reply.get(0);
+				//remove the "waiting for reply" registration
+				replyListeners.remove(new Integer(msg.getXid()));
+				session.close(false);
+				return r;
+			}
+
+
+
+
+		} catch (Throwable t) {
+			if (t instanceof IllegalMonitorStateException){
+				platform.logDebug(t.getMessage(), t);
+				throw new ServiceLocationException(ServiceLocationException.NETWORK_TIMED_OUT,"Reply timed out");
+			} else {
+				platform.logDebug(t.getMessage(), t);
+				throw new ServiceLocationException((short) 1, t.getMessage());
+			}
+		}
+	}
+
+
+
+
+	/**
+	 * send a request via multicast convergence algorithm.
+	 * 
+	 * @param msg
+	 *            the message.
+	 * @return the collected reply messages.
+	 * @throws ServiceLocationException
+	 *             in case of network errors.
+	 */
+	static void multicastConvergence(final ReplyFuture replyfuture,final AbstractSLPRequestMessage msg)
+	throws ServiceLocationException {
+
+		if (msg.getXid() == 0) {
+			msg.setXid(SLPCore.nextXid());
+		}
+
+		new MulticastConvergenceThread(replyfuture,msg);
+
+
+
+	}
+
+	private static boolean isLocalResponder(InetAddress addr) {
+		if (addr.getHostAddress().equals("127.0.0.1")){
+			return true;
+		}
+		for (int i = 0; i < SLPCore.myIPs.length; i++) {
+			if (addr.getHostAddress().equals(SLPCore.myIPs[i])) {
+				return true;
+			}
+		}
+		return false;
+	}
+
+
+
+	/**
+	 * Initialize the MINA components
+	 */
+	private static void initializeMina(){
+		try {
+			// initialize the UDP senders, required by both SA and UA
+			senderList=new AprDatagramConnector[myIPs.length];
+			for (int i=0;i<myIPs.length;i++){
+				AprDatagramConnector adc = new AprDatagramConnector();
+				adc.getSessionConfig().setUseReadOperation(true);
+				adc.setTtl(CONFIG.getMcastTTL());
+				adc.setMulticastInterface(myIPs[i]); 
+				adc.setHandler(handler);
+				adc.getFilterChain().addLast("codec", new ProtocolCodecFilter(new SLPProtocolCodecFactory()));
+				adc.getSessionConfig().setReuseAddress(true);
+				senderList[i]=adc;
+			}
+
+			// default sender, sends out over default multicast interface...
+			sender = new AprDatagramConnector();
+			sender.getSessionConfig().setUseReadOperation(true);
+			sender.setTtl(CONFIG.getMcastTTL());
+			sender.setHandler(handler);
+			sender.getFilterChain().addLast("codec", new ProtocolCodecFilter(new SLPProtocolCodecFactory()));
+			sender.getSessionConfig().setReuseAddress(true);
+
+			// initialize the TCP sender (and reply-receiver...)
+			tcpsender = new AprSocketConnector();
+			tcpsender.getFilterChain().addLast("codec", new ProtocolCodecFilter(new SLPProtocolCodecFactory()));
+			tcpsender.setHandler(handler);
+
+
+		} catch (Exception e){
+			platform.logError("[SLPCore] Unable to initialize MINA framework, aborting.", e);
+			System.out.println("[SLPCORE]: Unable to initialize MINA framework, possibly because another SLP implementation is running on the same ports");
+		}
+
+	}
+
+
+	protected static void initializeListeners() throws ServiceLocationException{
+		if (isListening){
+			return;
+		}
+		try{
+			multicastTCPAcceptor = new AprSocketAcceptor();
+			multicastTCPAcceptor.setHandler(handler);
+			multicastTCPAcceptor.getFilterChain().addLast("codec", new ProtocolCodecFilter(new SLPProtocolCodecFactory()));
+			//TODO: add thread model ?
+			multicastTCPAcceptor.setReuseAddress(true);
+			multicastTCPAcceptor.bind(new InetSocketAddress(SLPCore.SLP_PORT));
+
+
+			//set up the UDP receiver
+			multicastAcceptor = new AprDatagramAcceptor();
+			multicastAcceptor.setHandler(handler);
+			multicastAcceptor.joinGroup(SLPCore.MCAST_ADDRESS.getHostAddress());
+			multicastAcceptor.getFilterChain().addLast("codec", new ProtocolCodecFilter(new SLPProtocolCodecFactory()));
+			multicastAcceptor.getFilterChain().addLast("threadPool", new ExecutorFilter(Executors.newFixedThreadPool(10)));
+
+			DatagramSessionConfig dcfg = multicastAcceptor.getSessionConfig();
+			dcfg.setReuseAddress(true);
+			multicastAcceptor.bind(new InetSocketAddress(SLPCore.SLP_PORT));
+			
+			isListening = true;
+			
+		} catch (Exception e){
+			platform.logError("[SLPCore] Unable to initialize MINA acceptors.", e);
+			throw new ServiceLocationException(ServiceLocationException.NETWORK_INIT_FAILED,e.getMessage());
+		}
+
+	}
+
+
+
+	/**
+	 * initialize a new receiver to listen for replies to multicast requests
+	 * 
+	 * @param localaddress
+	 * 			The address this receiver should listen on (unicast)
+	 * @return
+	 * 			The initialized and bound AprDatagramAcceptor
+	 * 
+	 * @throws ServiceLocationException
+	 */
+	private static AprDatagramAcceptor initReceiver(InetSocketAddress localaddress) throws ServiceLocationException {
+		AprDatagramAcceptor recv = new AprDatagramAcceptor();
+		try {
+			if (localaddress.getPort()==0){
+				//if no port is specified, listen on the default SLP port for this application
+				localaddress = new InetSocketAddress(localaddress.getAddress().getHostAddress(),SLP_PORT);
+			}
+			if (localaddress.getAddress().getHostAddress().equals("127.0.1.1")){
+				//Debian and co. have an entry in .hosts that messes things up, this line fixes that
+				localaddress = new InetSocketAddress("127.0.0.1",localaddress.getPort());
+			}
+			//initialize the UDP receiver.
+			recv.setHandler(handler);
+			recv.getFilterChain().addLast("codec", new ProtocolCodecFilter(new SLPProtocolCodecFactory()));
+			// let each incoming packet be processed in a new thread if possible, as this acceptor
+			// deals with replies to multicast requests
+			DatagramSessionConfig dcfg = recv.getSessionConfig();
+			dcfg.setReuseAddress(true);
+			recv.bind(localaddress);
+			return recv;
+		} catch (Exception e){
+			recv.dispose();
+			throw new ServiceLocationException(ServiceLocationException.NETWORK_INIT_FAILED,"Unable to set up UDP receiver");
+		}
+	}
+
+
+
+	public static SLPDaemon getDaemon(){
+		return daemon;
+	}
+
+	public static DirectoryAgentDaemon getDirectoryAgentDaemon(){
+		return daDaemon;
+	}
+
+	public static List<String> getDas(String scope){
+		return dAs.get(scope.toLowerCase());
+	}
+
+	public static PlatformAbstraction getPlatform(){
+		return platform;
+	}
+
+	public static synchronized Map getReplyListeners(){
+		return replyListeners;
+	}
+
+
+
+	/**
+	 * add a reply to the queue and notify any thread waiting for such a reply...
+	 * 
+	 * @param msg
+	 * 			the message to be added as a reply
+	 * @param address
+	 * 			the source address, only required for logging
+	 */
+	public static synchronized void addReply(AbstractSLPMessage msg, InetSocketAddress address){
+		List<AbstractSLPMessage> queue = (List<AbstractSLPMessage>) replyListeners.get(new Integer(msg.getXid()));
+		if (queue != null) {
+			synchronized (queue) {
+				queue.add(msg);
+				queue.notifyAll();
+			}
+			return;
+		} else {
+			platform.logTraceReg("SRVREPLY recieved ("
+					+ address.getAddress() + ":" + address.getPort() + ") "
+					+ msg.toString()
+					+ " but not replyListeners present anymore");
+		}
+		return;
+	}
+
+	/**
+	 * setup a new receiver thread for DA lookup.
+	 * 
+	 * @param minLifetime
+	 *            the minimum lifetime of the receiver thread.
+	 */
+	private static void setupReceiverThread(final long minLifetime) {
+		new Thread("DALookupThread") {
+			public void run() {
+				platform.logDebug("[DALOOKUP]: Thread starting with lifetime " + minLifetime);
+
+				// calculate the end of lifetime
+				long timeout = System.currentTimeMillis() + minLifetime+1000;
+				long now;
+
+				// while lifetime is not expired
+				while ((now=System.currentTimeMillis()) < timeout) {
+					try {
+						long remain = timeout-now;
+						Thread.sleep(remain);
+					} catch (InterruptedException ie){
+						continue;
+					}
+				}
+				for (int i=0;i<receiverList.length;i++){
+					receiverList[i].dispose();
+				}
+				platform.logDebug("[DALOOKUP]: Thread stopping after " + minLifetime);
+			}
+		}.start();
+	}
+
+	private static class MulticastConvergenceThread extends Thread {
+
+
+		private final ReplyFuture replyfuture;
+		private final AbstractSLPRequestMessage msg;
+
+		public MulticastConvergenceThread(ReplyFuture rf,AbstractSLPRequestMessage req){
+			super("MulticastConvergenceThread");
+			replyfuture=rf;
+			msg=req;
+			start();
+		}
+
+
+		public void run() {
+			//System.out.println("Entering MCC Algorithm...");
+//			One receiver for each interface on which mulitcast requests are sent
+			AprDatagramAcceptor[] recv = new AprDatagramAcceptor[myIPs.length];
+			AprDatagramSession[] sessions = new AprDatagramSession[myIPs.length];
+//			number of interfaces that don't work correctly
+			int failedInterfaces = 0;
+			try {
+
+				long start = System.currentTimeMillis();
+
+				List<AbstractSLPMessage> replyQueue = new ArrayList<AbstractSLPMessage>();
+				List<String> responders = new ArrayList<String>();
+				if (msg.getPrevResponders()!=null){
+					for (String r : msg.getPrevResponders()){
+						responders.add(r);
+					}
+				}
+				List<String> responses = new ArrayList<String>();
+
+				if (msg.getXid() == 0) {
+					msg.setXid(SLPCore.nextXid());
+				}
+
+				// register the reply queue as listener
+				Integer queryXID = new Integer(msg.getXid());
+				synchronized (replyListeners) {
+					replyListeners.put(queryXID, replyQueue);
+				}
+
+
+
+				// send to localhost, in case the OS does not support multicast over
+				// loopback which can fail if no SA is running locally
+				try {
+					InetSocketAddress local = new InetSocketAddress(LOCALHOST.getHostAddress(),SLP_PORT);
+					replyQueue.add(sendMessageTCP(msg,local,true));
+				} catch (ServiceLocationException e) {
+
+				}
+				msg.setMulticast(true);
+				InetSocketAddress remoteaddr = new InetSocketAddress(MCAST_ADDRESS.getHostAddress(),SLP_PORT);
+
+				AbstractSLPReplyMessage reply;
+
+
+				for (int i = 0; i < myIPs.length; i++) {
+					try {
+						// initialize the sessions and the receivers
+						InetSocketAddress localaddr = new InetSocketAddress(myIPs[i],0);
+
+						ConnectFuture connFuture = senderList[i].connect(remoteaddr);
+						try {
+							connFuture.await(CONFIG.getDatagramMaxWait());
+						} catch (InterruptedException ie){
+
+						}
+						if (!connFuture.isConnected()){
+							platform.logError("Failed to send over udp: "+msg+" to "+remoteaddr.getAddress().getHostAddress()+":"+remoteaddr.getPort());
+							i--;
+							failedInterfaces++;
+							continue;
+						} 
+						sessions[i] = (AprDatagramSession) connFuture.getSession();
+						localaddr = new InetSocketAddress(myIPs[i],((InetSocketAddress)sessions[i].getLocalAddress()).getPort());
+
+						recv[i] = initReceiver(localaddr);
+					} catch (ServiceLocationException sle){
+						// the receiver for this interface couldn't get started...
+						failedInterfaces++;
+						i--;
+						continue;
+					}
+
+				}   
+
+
+				// the multicast convergence algorithm
+				long totalTimeout = System.currentTimeMillis()
+				+ CONFIG.getMcastMaxWait();
+				int[] transmissionSchedule = SLPCore.CONFIG.getMcastTimeouts();
+				int retryCounter = 0;
+				long nextTimeout;
+				int failCounter = 0;
+				boolean seenNew = false;
+				boolean seenLocalResponse = false; 
+				nextTimeout = System.currentTimeMillis()
+				+ transmissionSchedule[retryCounter];
+
+				while (!Thread.currentThread().isInterrupted()
+						&& totalTimeout > System.currentTimeMillis()
+						&& nextTimeout > System.currentTimeMillis()
+						&& retryCounter < transmissionSchedule.length
+						&& failCounter < CONFIG.getConvergenceFailerCount()) {
+					platform.logDebug("[MCC]: starting round " + retryCounter);
+					//System.out.println("Entering round "+retryCounter);
+					msg.setPrevResponders((String[]) responders.toArray(new String[]{}));
+
+					// finish convergence in case of message size exeeds MTU
+					if (msg.getSize() > CONFIG.getMTU()) {
+						for (int i=0;i<sessions.length-failedInterfaces;i++){
+							sessions[i].close(true);
+							recv[i].dispose();
+							replyfuture.setDone(msg.getScopes(),false);
+						}
+						break;
+					}
+
+
+					if (msg.getSize() > CONFIG.getMTU() || TCP_ONLY) {
+						try {
+							sendMessageTCP(msg, remoteaddr, false);
+						} catch (ServiceLocationException sle){
+							//couldn't send message over tcp...
+						}
+					}
+					for (int i = 0; i < sessions.length-failedInterfaces; i++){
+						sessions[i].write(msg);
+						platform.logTraceMessage("SENT " + msg + " on interface " + myIPs[i]);
+					}
+
+					/**
+					 * @fix: bug #1518729. Changed processing of the replyQueue.
+					 *       Thanks to Richard Reid for figuring out the problem
+					 *       with multicast replies and proposing the fix
+					 */
+					try {
+						Thread.sleep(transmissionSchedule[retryCounter]);
+					} catch (InterruptedException dontcare) {
+						// Restore the interrupted status
+						Thread.currentThread().interrupt();
+					}
+
+					synchronized (replyQueue) {
+						// did something else wake us up ?
+						if (replyQueue.isEmpty()) {
+							failCounter++;
+							nextTimeout = System.currentTimeMillis()
+							+ transmissionSchedule[retryCounter++];
+							continue;
+						}
+						while (!replyQueue.isEmpty()) {
+							reply = (AbstractSLPReplyMessage) replyQueue.remove(0);
+							// silently drop duplicate responses, process only new results
+							if (!responders.contains(reply.getSource())) {
+								if (isLocalResponder(InetAddress.getByName(reply.getSource()))) {
+									if (seenLocalResponse) {
+										continue;
+									} else {
+										seenLocalResponse = true;
+									}
+								}
+								seenNew = true;
+								responders.add(reply.getSource());
+								responses.addAll(reply.getResultAsList());
+								replyfuture.add(reply);
+
+
+							}
+						}
+
+						if (!seenNew) {
+							failCounter++;
+						} else {
+							seenNew = false;
+						}
+					}
+					nextTimeout = System.currentTimeMillis()
+					+ transmissionSchedule[retryCounter++];
+				}
+				for (int i=0;i<sessions.length-failedInterfaces;i++){
+					sessions[i].close(true);
+					recv[i].dispose();
+				}
+
+
+				// we are done, remove the listener queue
+				synchronized (replyListeners) {
+					replyListeners.remove(queryXID);
+				}
+
+				platform.logDebug("convergence for xid=" + msg.getXid()
+						+ " finished after "
+						+ (System.currentTimeMillis() - start)
+						+ " ms, result: " + responses);
+
+				replyfuture.setDone(msg.getScopes(),false);
+			} catch (IOException ioe) {
+				for (int i=0;i<recv.length-failedInterfaces;i++){
+					sessions[i].close(true);
+					recv[i].dispose();
+					//replyfuture.setDone();
+				}
+
+				platform.logDebug(ioe.getMessage(), ioe);
+			}
+
+		}
+
+
+
+
+	}
+
+	public static void shutdownCore(){
+		if (daDaemon!=null){
+			daDaemon.shutdown();
+		}
+		if (daemon!=null){
+			shutdownAdvertiser();
+		}
+		
+	}
+
+
+}

Propchange: directory/sandbox/slp/src/main/java/org/apache/directory/slp/impl/SLPCore.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Added: directory/sandbox/slp/src/main/java/org/apache/directory/slp/impl/SLPDaemon.java
URL: http://svn.apache.org/viewvc/directory/sandbox/slp/src/main/java/org/apache/directory/slp/impl/SLPDaemon.java?rev=782968&view=auto
==============================================================================
--- directory/sandbox/slp/src/main/java/org/apache/directory/slp/impl/SLPDaemon.java (added)
+++ directory/sandbox/slp/src/main/java/org/apache/directory/slp/impl/SLPDaemon.java Tue Jun  9 12:00:29 2009
@@ -0,0 +1,59 @@
+/* 
+ *   Licensed to the Apache Software Foundation (ASF) under one
+ *   or more contributor license agreements.  See the NOTICE file
+ *   distributed with this work for additional information
+ *   regarding copyright ownership.  The ASF licenses this file
+ *   to you under the Apache License, Version 2.0 (the
+ *   "License"); you may not use this file except in compliance
+ *   with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *   Unless required by applicable law or agreed to in writing,
+ *   software distributed under the License is distributed on an
+ *   "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *   KIND, either express or implied.  See the License for the
+ *   specific language governing permissions and limitations
+ *   under the License.
+ *   
+ */
+package org.apache.directory.slp.impl;
+
+import org.apache.directory.slp.ServiceLocationException;
+import org.apache.directory.slp.messages.AbstractSLPMessage;
+import org.apache.directory.slp.messages.AbstractSLPReplyMessage;
+import org.apache.directory.slp.messages.DAAdvertisementMessage;
+
+
+
+
+
+/**
+ * the SLPDeaemon interface. Factored out to make the daemon part optional as
+ * part of the jSLP modularity.
+ * 
+ * @author Jan S. Rellermeyer
+ */
+public interface SLPDaemon {
+
+	/**
+	 * called, when a new DA has been discovered.
+	 * 
+	 * @param advert
+	 *            the <code>DAAdvertisement</code> received from the new DA.
+	 */
+	void newDaDiscovered(DAAdvertisementMessage advert);
+
+	/**
+	 * handle a message dispatched by SLPCore.
+	 * 
+	 * @param msg
+	 *            the message.
+	 * @return the reply message or <code>null</code>.
+	 * @throws ServiceLocationException
+	 *             if something goes wrong.
+	 */
+	AbstractSLPReplyMessage handleMessage(final AbstractSLPMessage msg)
+			throws ServiceLocationException;
+
+}

Propchange: directory/sandbox/slp/src/main/java/org/apache/directory/slp/impl/SLPDaemon.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain