motify compile link error

motify compile link error
This commit is contained in:
ant 2016-09-18 09:03:25 +08:00
parent 923914edae
commit 03e74a8e50
5418 changed files with 1367914 additions and 206149 deletions

View file

@ -1,19 +1,19 @@
<?xml version="1.0" encoding="UTF-8"?>
<module external.linked.project.id="WiGadget" external.linked.project.path="$MODULE_DIR$" external.root.project.path="$MODULE_DIR$" external.system.id="GRADLE" external.system.module.group="" external.system.module.version="unspecified" type="JAVA_MODULE" version="4">
<component name="FacetManager">
<facet type="java-gradle" name="Java-Gradle">
<configuration>
<option name="BUILD_FOLDER_PATH" value="$MODULE_DIR$/build" />
<option name="BUILDABLE" value="false" />
</configuration>
</facet>
</component>
<component name="NewModuleRootManager" LANGUAGE_LEVEL="JDK_1_7" inherit-compiler-output="true">
<exclude-output />
<content url="file://$MODULE_DIR$">
<excludeFolder url="file://$MODULE_DIR$/.gradle" />
</content>
<orderEntry type="inheritedJdk" />
<orderEntry type="sourceFolder" forTests="false" />
</component>
<?xml version="1.0" encoding="UTF-8"?>
<module external.linked.project.id="WiGadget" external.linked.project.path="$MODULE_DIR$" external.root.project.path="$MODULE_DIR$" external.system.id="GRADLE" external.system.module.group="" external.system.module.version="unspecified" type="JAVA_MODULE" version="4">
<component name="FacetManager">
<facet type="java-gradle" name="Java-Gradle">
<configuration>
<option name="BUILD_FOLDER_PATH" value="$MODULE_DIR$/build" />
<option name="BUILDABLE" value="false" />
</configuration>
</facet>
</component>
<component name="NewModuleRootManager" LANGUAGE_LEVEL="JDK_1_7" inherit-compiler-output="true">
<exclude-output />
<content url="file://$MODULE_DIR$">
<excludeFolder url="file://$MODULE_DIR$/.gradle" />
</content>
<orderEntry type="inheritedJdk" />
<orderEntry type="sourceFolder" forTests="false" />
</component>
</module>

View file

@ -1,102 +1,102 @@
<?xml version="1.0" encoding="UTF-8"?>
<module external.linked.project.id=":app" external.linked.project.path="$MODULE_DIR$" external.root.project.path="$MODULE_DIR$/.." external.system.id="GRADLE" external.system.module.group="WiGadget" external.system.module.version="unspecified" type="JAVA_MODULE" version="4">
<component name="FacetManager">
<facet type="android-gradle" name="Android-Gradle">
<configuration>
<option name="GRADLE_PROJECT_PATH" value=":app" />
</configuration>
</facet>
<facet type="android" name="Android">
<configuration>
<option name="SELECTED_BUILD_VARIANT" value="debug" />
<option name="SELECTED_TEST_ARTIFACT" value="_android_test_" />
<option name="ASSEMBLE_TASK_NAME" value="assembleDebug" />
<option name="COMPILE_JAVA_TASK_NAME" value="compileDebugSources" />
<option name="ASSEMBLE_TEST_TASK_NAME" value="assembleDebugAndroidTest" />
<option name="COMPILE_JAVA_TEST_TASK_NAME" value="compileDebugAndroidTestSources" />
<afterSyncTasks>
<task>generateDebugAndroidTestSources</task>
<task>generateDebugSources</task>
</afterSyncTasks>
<option name="ALLOW_USER_CONFIGURATION" value="false" />
<option name="MANIFEST_FILE_RELATIVE_PATH" value="/src/main/AndroidManifest.xml" />
<option name="RES_FOLDER_RELATIVE_PATH" value="/src/main/res" />
<option name="RES_FOLDERS_RELATIVE_PATH" value="file://$MODULE_DIR$/src/main/res" />
<option name="ASSETS_FOLDER_RELATIVE_PATH" value="/src/main/assets" />
</configuration>
</facet>
</component>
<component name="NewModuleRootManager" LANGUAGE_LEVEL="JDK_1_7" inherit-compiler-output="false">
<output url="file://$MODULE_DIR$/build/intermediates/classes/debug" />
<output-test url="file://$MODULE_DIR$/build/intermediates/classes/androidTest/debug" />
<exclude-output />
<content url="file://$MODULE_DIR$">
<sourceFolder url="file://$MODULE_DIR$/build/generated/source/r/debug" isTestSource="false" generated="true" />
<sourceFolder url="file://$MODULE_DIR$/build/generated/source/aidl/debug" isTestSource="false" generated="true" />
<sourceFolder url="file://$MODULE_DIR$/build/generated/source/buildConfig/debug" isTestSource="false" generated="true" />
<sourceFolder url="file://$MODULE_DIR$/build/generated/source/rs/debug" isTestSource="false" generated="true" />
<sourceFolder url="file://$MODULE_DIR$/build/generated/res/rs/debug" type="java-resource" />
<sourceFolder url="file://$MODULE_DIR$/build/generated/res/generated/debug" type="java-resource" />
<sourceFolder url="file://$MODULE_DIR$/build/generated/source/r/androidTest/debug" isTestSource="true" generated="true" />
<sourceFolder url="file://$MODULE_DIR$/build/generated/source/aidl/androidTest/debug" isTestSource="true" generated="true" />
<sourceFolder url="file://$MODULE_DIR$/build/generated/source/buildConfig/androidTest/debug" isTestSource="true" generated="true" />
<sourceFolder url="file://$MODULE_DIR$/build/generated/source/rs/androidTest/debug" isTestSource="true" generated="true" />
<sourceFolder url="file://$MODULE_DIR$/build/generated/res/rs/androidTest/debug" type="java-test-resource" />
<sourceFolder url="file://$MODULE_DIR$/build/generated/res/generated/androidTest/debug" type="java-test-resource" />
<sourceFolder url="file://$MODULE_DIR$/src/debug/res" type="java-resource" />
<sourceFolder url="file://$MODULE_DIR$/src/debug/resources" type="java-resource" />
<sourceFolder url="file://$MODULE_DIR$/src/debug/assets" type="java-resource" />
<sourceFolder url="file://$MODULE_DIR$/src/debug/aidl" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/src/debug/java" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/src/debug/jni" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/src/debug/rs" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/src/main/res" type="java-resource" />
<sourceFolder url="file://$MODULE_DIR$/src/main/resources" type="java-resource" />
<sourceFolder url="file://$MODULE_DIR$/src/main/assets" type="java-resource" />
<sourceFolder url="file://$MODULE_DIR$/src/main/aidl" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/src/main/java" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/src/main/jni" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/src/main/rs" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/src/androidTest/res" type="java-test-resource" />
<sourceFolder url="file://$MODULE_DIR$/src/androidTest/resources" type="java-test-resource" />
<sourceFolder url="file://$MODULE_DIR$/src/androidTest/assets" type="java-test-resource" />
<sourceFolder url="file://$MODULE_DIR$/src/androidTest/aidl" isTestSource="true" />
<sourceFolder url="file://$MODULE_DIR$/src/androidTest/java" isTestSource="true" />
<sourceFolder url="file://$MODULE_DIR$/src/androidTest/jni" isTestSource="true" />
<sourceFolder url="file://$MODULE_DIR$/src/androidTest/rs" isTestSource="true" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/assets" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/bundles" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/classes" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/coverage-instrumented-classes" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/dependency-cache" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/dex" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/dex-cache" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/exploded-aar/com.android.support/appcompat-v7/21.0.3/jars" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/exploded-aar/com.android.support/support-v4/21.0.3/jars" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/incremental" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/jacoco" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/javaResources" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/libs" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/lint" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/manifests" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/ndk" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/pre-dexed" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/proguard" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/res" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/rs" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/symbols" />
<excludeFolder url="file://$MODULE_DIR$/build/outputs" />
<excludeFolder url="file://$MODULE_DIR$/build/tmp" />
</content>
<orderEntry type="jdk" jdkName="Android API 21 Platform" jdkType="Android SDK" />
<orderEntry type="sourceFolder" forTests="false" />
<orderEntry type="library" exported="" name="appcompat-v7-21.0.3" level="project" />
<orderEntry type="library" exported="" name="firebase-client-android-2.2.4" level="project" />
<orderEntry type="library" exported="" name="support-annotations-21.0.3" level="project" />
<orderEntry type="library" exported="" name="jmdns-3.4.1" level="project" />
<orderEntry type="library" exported="" name="support-v4-21.0.3" level="project" />
<orderEntry type="library" exported="" name="androidplot-core-0.6.1" level="project" />
<orderEntry type="library" exported="" name="commons-codec-1.6-repack" level="project" />
<orderEntry type="library" exported="" name="jmdns" level="project" />
</component>
<?xml version="1.0" encoding="UTF-8"?>
<module external.linked.project.id=":app" external.linked.project.path="$MODULE_DIR$" external.root.project.path="$MODULE_DIR$/.." external.system.id="GRADLE" external.system.module.group="WiGadget" external.system.module.version="unspecified" type="JAVA_MODULE" version="4">
<component name="FacetManager">
<facet type="android-gradle" name="Android-Gradle">
<configuration>
<option name="GRADLE_PROJECT_PATH" value=":app" />
</configuration>
</facet>
<facet type="android" name="Android">
<configuration>
<option name="SELECTED_BUILD_VARIANT" value="debug" />
<option name="SELECTED_TEST_ARTIFACT" value="_android_test_" />
<option name="ASSEMBLE_TASK_NAME" value="assembleDebug" />
<option name="COMPILE_JAVA_TASK_NAME" value="compileDebugSources" />
<option name="ASSEMBLE_TEST_TASK_NAME" value="assembleDebugAndroidTest" />
<option name="COMPILE_JAVA_TEST_TASK_NAME" value="compileDebugAndroidTestSources" />
<afterSyncTasks>
<task>generateDebugAndroidTestSources</task>
<task>generateDebugSources</task>
</afterSyncTasks>
<option name="ALLOW_USER_CONFIGURATION" value="false" />
<option name="MANIFEST_FILE_RELATIVE_PATH" value="/src/main/AndroidManifest.xml" />
<option name="RES_FOLDER_RELATIVE_PATH" value="/src/main/res" />
<option name="RES_FOLDERS_RELATIVE_PATH" value="file://$MODULE_DIR$/src/main/res" />
<option name="ASSETS_FOLDER_RELATIVE_PATH" value="/src/main/assets" />
</configuration>
</facet>
</component>
<component name="NewModuleRootManager" LANGUAGE_LEVEL="JDK_1_7" inherit-compiler-output="false">
<output url="file://$MODULE_DIR$/build/intermediates/classes/debug" />
<output-test url="file://$MODULE_DIR$/build/intermediates/classes/androidTest/debug" />
<exclude-output />
<content url="file://$MODULE_DIR$">
<sourceFolder url="file://$MODULE_DIR$/build/generated/source/r/debug" isTestSource="false" generated="true" />
<sourceFolder url="file://$MODULE_DIR$/build/generated/source/aidl/debug" isTestSource="false" generated="true" />
<sourceFolder url="file://$MODULE_DIR$/build/generated/source/buildConfig/debug" isTestSource="false" generated="true" />
<sourceFolder url="file://$MODULE_DIR$/build/generated/source/rs/debug" isTestSource="false" generated="true" />
<sourceFolder url="file://$MODULE_DIR$/build/generated/res/rs/debug" type="java-resource" />
<sourceFolder url="file://$MODULE_DIR$/build/generated/res/generated/debug" type="java-resource" />
<sourceFolder url="file://$MODULE_DIR$/build/generated/source/r/androidTest/debug" isTestSource="true" generated="true" />
<sourceFolder url="file://$MODULE_DIR$/build/generated/source/aidl/androidTest/debug" isTestSource="true" generated="true" />
<sourceFolder url="file://$MODULE_DIR$/build/generated/source/buildConfig/androidTest/debug" isTestSource="true" generated="true" />
<sourceFolder url="file://$MODULE_DIR$/build/generated/source/rs/androidTest/debug" isTestSource="true" generated="true" />
<sourceFolder url="file://$MODULE_DIR$/build/generated/res/rs/androidTest/debug" type="java-test-resource" />
<sourceFolder url="file://$MODULE_DIR$/build/generated/res/generated/androidTest/debug" type="java-test-resource" />
<sourceFolder url="file://$MODULE_DIR$/src/debug/res" type="java-resource" />
<sourceFolder url="file://$MODULE_DIR$/src/debug/resources" type="java-resource" />
<sourceFolder url="file://$MODULE_DIR$/src/debug/assets" type="java-resource" />
<sourceFolder url="file://$MODULE_DIR$/src/debug/aidl" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/src/debug/java" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/src/debug/jni" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/src/debug/rs" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/src/main/res" type="java-resource" />
<sourceFolder url="file://$MODULE_DIR$/src/main/resources" type="java-resource" />
<sourceFolder url="file://$MODULE_DIR$/src/main/assets" type="java-resource" />
<sourceFolder url="file://$MODULE_DIR$/src/main/aidl" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/src/main/java" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/src/main/jni" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/src/main/rs" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/src/androidTest/res" type="java-test-resource" />
<sourceFolder url="file://$MODULE_DIR$/src/androidTest/resources" type="java-test-resource" />
<sourceFolder url="file://$MODULE_DIR$/src/androidTest/assets" type="java-test-resource" />
<sourceFolder url="file://$MODULE_DIR$/src/androidTest/aidl" isTestSource="true" />
<sourceFolder url="file://$MODULE_DIR$/src/androidTest/java" isTestSource="true" />
<sourceFolder url="file://$MODULE_DIR$/src/androidTest/jni" isTestSource="true" />
<sourceFolder url="file://$MODULE_DIR$/src/androidTest/rs" isTestSource="true" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/assets" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/bundles" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/classes" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/coverage-instrumented-classes" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/dependency-cache" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/dex" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/dex-cache" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/exploded-aar/com.android.support/appcompat-v7/21.0.3/jars" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/exploded-aar/com.android.support/support-v4/21.0.3/jars" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/incremental" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/jacoco" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/javaResources" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/libs" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/lint" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/manifests" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/ndk" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/pre-dexed" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/proguard" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/res" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/rs" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/symbols" />
<excludeFolder url="file://$MODULE_DIR$/build/outputs" />
<excludeFolder url="file://$MODULE_DIR$/build/tmp" />
</content>
<orderEntry type="jdk" jdkName="Android API 21 Platform" jdkType="Android SDK" />
<orderEntry type="sourceFolder" forTests="false" />
<orderEntry type="library" exported="" name="appcompat-v7-21.0.3" level="project" />
<orderEntry type="library" exported="" name="firebase-client-android-2.2.4" level="project" />
<orderEntry type="library" exported="" name="support-annotations-21.0.3" level="project" />
<orderEntry type="library" exported="" name="jmdns-3.4.1" level="project" />
<orderEntry type="library" exported="" name="support-v4-21.0.3" level="project" />
<orderEntry type="library" exported="" name="androidplot-core-0.6.1" level="project" />
<orderEntry type="library" exported="" name="commons-codec-1.6-repack" level="project" />
<orderEntry type="library" exported="" name="jmdns" level="project" />
</component>
</module>

View file

@ -1,33 +1,33 @@
package com.realtek.wigadget;
import android.graphics.Bitmap;
public class DeviceIcon {
private Bitmap deviceIcon;
private String deviceMac;
private String deviceDescription;
public DeviceIcon(Bitmap icon, String description, String mac) {
super();
this.deviceIcon = icon;
this.deviceDescription=description;
this.deviceMac = mac;
}
public Bitmap getDeviceIcon() {
return deviceIcon;
}
public String getDeviceDescription() {
return deviceDescription;
}
public void setDeviceDescription(String description) {
this.deviceDescription = description;
}
public String getDeviceMac(){
return deviceMac;
}
}
package com.realtek.wigadget;
import android.graphics.Bitmap;
public class DeviceIcon {
private Bitmap deviceIcon;
private String deviceMac;
private String deviceDescription;
public DeviceIcon(Bitmap icon, String description, String mac) {
super();
this.deviceIcon = icon;
this.deviceDescription=description;
this.deviceMac = mac;
}
public Bitmap getDeviceIcon() {
return deviceIcon;
}
public String getDeviceDescription() {
return deviceDescription;
}
public void setDeviceDescription(String description) {
this.deviceDescription = description;
}
public String getDeviceMac(){
return deviceMac;
}
}

View file

@ -1,58 +1,58 @@
package com.realtek.wigadget;
import android.app.Activity;
import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.ImageView;
import android.widget.TextView;
import java.util.ArrayList;
public class GridViewAdapter extends ArrayAdapter<DeviceIcon> {
private Context context;
private int layoutResourceId;
private ArrayList<DeviceIcon> iconArrayList = new ArrayList<DeviceIcon>();
public GridViewAdapter(Context context, int layoutResourceId, ArrayList<DeviceIcon> iconArrayList) {
super(context, layoutResourceId, iconArrayList);
this.layoutResourceId = layoutResourceId;
this.context = context;
this.iconArrayList = iconArrayList;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
View row = convertView;
ViewHolder holder;
if (row == null) {
LayoutInflater inflater = ((Activity) context).getLayoutInflater();
row = inflater.inflate(layoutResourceId, parent, false);
holder = new ViewHolder();
holder.deviceDescription = (TextView) row.findViewById(R.id.text);
holder.deviceIcon = (ImageView) row.findViewById(R.id.image);
row.setTag(holder);
} else {
holder = (ViewHolder) row.getTag();
}
DeviceIcon item = iconArrayList.get(position);
holder.deviceDescription.setText(item.getDeviceDescription());
holder.deviceIcon.setImageBitmap(item.getDeviceIcon());
return row;
}
static class ViewHolder {
TextView deviceDescription;
ImageView deviceIcon;
}
public DeviceIcon getDeviceIconAt(int idx){
return iconArrayList.get(idx);
}
package com.realtek.wigadget;
import android.app.Activity;
import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.ImageView;
import android.widget.TextView;
import java.util.ArrayList;
public class GridViewAdapter extends ArrayAdapter<DeviceIcon> {
private Context context;
private int layoutResourceId;
private ArrayList<DeviceIcon> iconArrayList = new ArrayList<DeviceIcon>();
public GridViewAdapter(Context context, int layoutResourceId, ArrayList<DeviceIcon> iconArrayList) {
super(context, layoutResourceId, iconArrayList);
this.layoutResourceId = layoutResourceId;
this.context = context;
this.iconArrayList = iconArrayList;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
View row = convertView;
ViewHolder holder;
if (row == null) {
LayoutInflater inflater = ((Activity) context).getLayoutInflater();
row = inflater.inflate(layoutResourceId, parent, false);
holder = new ViewHolder();
holder.deviceDescription = (TextView) row.findViewById(R.id.text);
holder.deviceIcon = (ImageView) row.findViewById(R.id.image);
row.setTag(holder);
} else {
holder = (ViewHolder) row.getTag();
}
DeviceIcon item = iconArrayList.get(position);
holder.deviceDescription.setText(item.getDeviceDescription());
holder.deviceIcon.setImageBitmap(item.getDeviceIcon());
return row;
}
static class ViewHolder {
TextView deviceDescription;
ImageView deviceIcon;
}
public DeviceIcon getDeviceIconAt(int idx){
return iconArrayList.get(idx);
}
}

View file

@ -1,387 +1,387 @@
package com.realtek.wigadget;
import android.app.Activity;
import android.content.SharedPreferences;
import android.graphics.Color;
import android.media.MediaPlayer;
import android.os.Bundle;
import android.preference.PreferenceManager;
import android.util.Log;
import android.widget.TextView;
import com.androidplot.ui.SizeLayoutType;
import com.androidplot.ui.SizeMetrics;
import com.androidplot.xy.BoundaryMode;
import com.androidplot.xy.LineAndPointFormatter;
import com.androidplot.xy.PointLabelFormatter;
import com.androidplot.xy.SimpleXYSeries;
import com.androidplot.xy.XYPlot;
import com.androidplot.xy.XYSeries;
import com.androidplot.xy.XYStepMode;
import com.firebase.client.DataSnapshot;
import com.firebase.client.Firebase;
import com.firebase.client.FirebaseError;
import com.firebase.client.ValueEventListener;
import org.json.JSONObject;
import java.net.InetAddress;
import java.text.DecimalFormat;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Vector;
public class HTSensorActivity extends Activity {
private static final Constants c = Constants.getInstance();
private AES128 mAES = new AES128();
private String mIp;
private int mPort;
private String mAESKey;
private String mFirebaseAppId;
private String mMac;
private String mDescription;
private TextView textViewTemp;
private TextView textViewHumi;
private boolean runLocalLink = true;
private boolean runCloudLink = true;
private XYPlot plot;
private List<Double> timeList= new Vector<>();
private List<Double> temperatureList=new Vector<>();
private List<Double> humidityList=new Vector<>();
private int maxListSize = 6;
private long timeCounter = 0;
private boolean receivedNewData =false;
private SharedPreferences sp;
private int dataUpdateDelay = c.val_ht_sensor_default_data_update_frequency;
private boolean alarmOptions = c.val_ht_sensor_default_alarm_options;
private double tempTresh = c.val_ht_sensor_default_temperature_threshold;
private double humiTresh = c.val_ht_sensor_default_humidity_threshold;
private String alarmSound = c.val_ht_sensor_default_alarm_sound;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_device_ht);
mIp=getIntent().getStringExtra(c.key_ip);
mPort=getIntent().getIntExtra(c.key_port, c.val_device_not_found);
mMac=getIntent().getStringExtra(c.key_mac);
mAESKey=getIntent().getStringExtra(c.key_shared_key);
mFirebaseAppId=getIntent().getStringExtra(c.key_firebase_app_id);
mDescription=getIntent().getStringExtra(c.key_device_description);
setTitle(mDescription);
textViewTemp = (TextView)findViewById(R.id.textViewTemperature);
textViewHumi = (TextView)findViewById(R.id.textViewHumidity);
loadSharedPreference();
if((!mIp.equals(c.val_empty))&&(mPort!=c.val_device_not_found)){
try {
amebaLocalLink(mIp, mPort);
}
catch (Exception e){
Log.e(c.tag_ht_sensor_activity,"connectToAmeba() Exception e "+e);
}
}
else {
amebaCloudLink(mFirebaseAppId);
}
plotChart();
}
@Override
protected void onDestroy() {
super.onDestroy();
runLocalLink = false;
runCloudLink = false;
Log.v(c.tag_ht_sensor_activity, "onDestroy()");
}
private void loadSharedPreference(){
sp = PreferenceManager.getDefaultSharedPreferences(getBaseContext());
dataUpdateDelay = Integer.parseInt(sp.getString(c.key_ht_sensor_data_update_frequency, Integer.toString(dataUpdateDelay)));
alarmOptions = sp.getBoolean(c.key_ht_sensor_alarm_options,false);
tempTresh = Double.parseDouble(sp.getString(c.key_ht_sensor_temperature_threshold, Double.toString(tempTresh)));
humiTresh=Double.parseDouble(sp.getString(c.key_ht_sensor_humidity_threshold,Double.toString(humiTresh)));
alarmSound=sp.getString(c.key_ht_sensor_alarm_sound, alarmSound);
}
private void playAlarm(double temp, double humi){
if((alarmOptions)&&((temp>tempTresh)||(humi>humiTresh))){
String sound = alarmSound;
MediaPlayer mediaPlayer;
if(sound.equals(c.val_ht_sensor_alarm_sound_altair)){
mediaPlayer = MediaPlayer.create(this, R.raw.sound_altair);
}
else if(sound.equals(c.val_ht_sensor_alarm_sound_ariel)){
mediaPlayer = MediaPlayer.create(this,R.raw.sound_ariel);
}
else if(sound.equals(c.val_ht_sensor_alarm_sound_fomalhaut)){
mediaPlayer = MediaPlayer.create(this,R.raw.sound_fomalhaut);
}
else if(sound.equals(c.val_ht_sensor_alarm_sound_tinkerbell)){
mediaPlayer = MediaPlayer.create(this,R.raw.sound_tinkerbell);
}
else {
mediaPlayer = MediaPlayer.create(this,R.raw.sound_ding);
}
mediaPlayer.start();
}
}
private void amebaLocalLink(String ip, int port)throws Exception{
final TcpClient tcpClient = new TcpClient();
Log.v(c.tag_ht_sensor_activity, "amebaLocalLink() ip/port: " + ip + "/" + port);
Log.v(c.tag_ht_sensor_activity, "amebaLocalLink() AES key: " + mAESKey);
final String mIp=ip;
final int mPort=port;
class AmebaLocalLinkGetDataThread extends Thread{
@Override
public void run() {
while (runLocalLink){
try {
Thread.sleep(dataUpdateDelay);
Log.v(c.tag_ht_sensor_activity,"amebaLocalLink() get data frequency: Every "+dataUpdateDelay+"ms");
}
catch (InterruptedException e){Log.e(c.tag_ht_sensor_activity,"AmebaLocalLinkGetDataThread InterruptedException e"+e);}
try {
String txEnc = mAES.encryptToStringOfShortArray("request", mAESKey);
Log.v(c.tag_ht_sensor_activity, "amebaLocalLink() txEnc: " + txEnc);
String rxEnc = tcpClient.echo(InetAddress.getByName(mIp), mPort, txEnc);
Log.v(c.tag_ht_sensor_activity,"amebaLocalLink() rxEnc: "+rxEnc);
String rx = mAES.decryptFromStringOfShortArray(rxEnc,mAESKey);
Log.v(c.tag_ht_sensor_activity, "amebaLocalLink() rx: " + rx);
////////////////////////parse json data////////////////////////
JSONObject jObject = new JSONObject(rx);
final double hum = jObject.getDouble(c.key_humidity);
final double tem = jObject.getDouble(c.key_temperature);
////////////////////////parse json data////////////////////////
runOnUiThread(new Runnable() {
@Override
public void run() {
textViewTemp.setText("" +tem);
textViewHumi.setText(""+hum);
updateDataList(tem,hum);
playAlarm(tem,hum);
}
});
}
catch (Exception e){Log.e(c.tag_ht_sensor_activity,"AmebaLocalLinkGetDataThread Exception e"+e);}
}//while(true)
}
}
new AmebaLocalLinkGetDataThread().start();
}
private void amebaCloudLink(String firebaseAppId){
String firebaseURL = "https://"+firebaseAppId+".firebaseio.com";
Firebase.setAndroidContext(this);
final Firebase firebaseRef = new Firebase(firebaseURL);
Log.v(c.tag_ht_sensor_activity, "amebaCloudLink() connect to firebase: " + firebaseURL);
firebaseRef.child(c.nsd_service_ht).child(mMac).addValueEventListener(new ValueEventListener() {
@Override
public void onDataChange(DataSnapshot snapshot) {
if (runCloudLink) {
Map<String, Object> newData = (Map<String, Object>) snapshot.getValue();
try {
double hum = Double.parseDouble((String) newData.get(c.key_humidity));
double tem = Double.parseDouble((String) newData.get(c.key_temperature));
textViewTemp.setText("" + tem);
textViewHumi.setText("" + hum);
updateDataList(tem, hum);
playAlarm(tem, hum);
Log.v(c.tag_ht_sensor_activity, snapshot.getValue().toString());
} catch (Exception e) {
Log.e(c.tag_ht_sensor_activity, "onDataChange() Exception e " + e);
}
}
}
@Override
public void onCancelled(FirebaseError error) {
Log.e(c.tag_ht_sensor_activity, "onCancelled() FirebaseError error" + error);
}
});
}
//////////////////////////////////////////////plot//////////////////////////////////////////////
private void plotChart(){
//init lists
timeList.add((double)0);
temperatureList.add((double)0);
humidityList.add((double)0);
new Thread() {
public void run() {
while (runLocalLink) {
try {
runOnUiThread(new Runnable() {
@Override
public void run() {
//update plot data
timeCounter++;
timeList.add((double)timeCounter);
while (timeList.size()>maxListSize){
timeList.remove(0);
}
//sync data with time:
if(!receivedNewData){
//push data manually
updateDataList(temperatureList.get(temperatureList.size()-1),humidityList.get(humidityList.size()-1));
}
//sync list length
//consider 1.when series size < timelist size 2.when series size > timelist size
while (temperatureList.size()<timeList.size()){
temperatureList.add(temperatureList.get(temperatureList.size()-1));
}
while (humidityList.size()<timeList.size()){
humidityList.add(humidityList.get(humidityList.size()-1));
}
while (temperatureList.size()>timeList.size()){
temperatureList.remove(0);
}
while (humidityList.size()>timeList.size()){
humidityList.remove(0);
}
try{
plot.clear();
}
catch (Exception e){
Log.e(c.tag_ht_sensor_activity,"Exception e"+e);
}
//////////////////////////////////////////////////plot setup//////////////////////////////////////////////////
// initialize our XYPlot reference:
plot = (XYPlot) findViewById(R.id.mySimpleXYPlot);
plot.setBorderStyle(XYPlot.BorderStyle.NONE, null, null);
plot.setGridPadding(5, 25, 25, 5);
plot.getGraphWidget().setSize(new SizeMetrics(0, SizeLayoutType.FILL, 0, SizeLayoutType.FILL));
plot.getGraphWidget().getBackgroundPaint().setColor(Color.argb(0, 0, 0, 0));
plot.getGraphWidget().getGridBackgroundPaint().setColor(Color.argb(0, 0, 0, 0));
//domain -- x
plot.getGraphWidget().getDomainLabelPaint().setColor(Color.BLACK);
plot.getGraphWidget().getDomainOriginLabelPaint().setColor(Color.BLACK);
plot.getGraphWidget().getDomainOriginLinePaint().setColor(Color.BLACK);
plot.setDomainValueFormat(new DecimalFormat("0"));
plot.setDomainStep(XYStepMode.INCREMENT_BY_VAL, 1);
plot.setDomainStepValue(1);
//range -- y
plot.getGraphWidget().getRangeLabelPaint().setColor(Color.BLACK);
plot.getGraphWidget().getRangeOriginLabelPaint().setColor(Color.BLACK);
plot.getGraphWidget().getRangeOriginLinePaint().setColor(Color.BLACK);
plot.setRangeValueFormat(new DecimalFormat("0"));
plot.setRangeStep(XYStepMode.INCREMENT_BY_VAL, 1);
plot.setRangeStepValue(5);
//label
plot.getDomainLabelWidget().getLabelPaint().setColor(Color.BLACK);
plot.getRangeLabelWidget().getLabelPaint().setColor(Color.BLACK);
// Create a formatter to use for drawing a series using LineAndPointRenderer
// and configure it from xml:
LineAndPointFormatter seriesHumiFormat = new LineAndPointFormatter();
seriesHumiFormat.setPointLabelFormatter(new PointLabelFormatter());
seriesHumiFormat.configure(getApplicationContext(), R.xml.line_point_formatter_with_plf1);
// same as above:
LineAndPointFormatter seriesTempFormat = new LineAndPointFormatter();
seriesTempFormat.setPointLabelFormatter(new PointLabelFormatter());
seriesTempFormat.configure(getApplicationContext(), R.xml.line_point_formatter_with_plf2);
// reduce the number of range labels
plot.setTicksPerRangeLabel(3);
plot.getGraphWidget().setDomainLabelOrientation(-45);
XYSeries seriesHumi = new SimpleXYSeries(timeList, humidityList, "Humidity");
XYSeries seriesTemp = new SimpleXYSeries(timeList, temperatureList, "Temperature");
plot.addSeries(seriesHumi, seriesHumiFormat);
plot.addSeries(seriesTemp, seriesTempFormat);
// handle the boundary bug -> define a boundary, DO NOT USE DEFAULT SETTINGS
List<Double> readings =new Vector<>();
for (double r : temperatureList){
readings.add(r);
}
for (double r : humidityList){
readings.add(r);
}
Collections.sort(readings);
double min=readings.get(0);
double max=readings.get(readings.size()-1);
plot.setRangeBoundaries(min,max, BoundaryMode.FIXED);
Log.v(c.tag_ht_sensor_activity,"plotChart() set range boundaries ("+min+","+max+")");
//////////////////////////////////////////////////plot setup//////////////////////////////////////////////////
plot.redraw();
receivedNewData=false;
Log.v(c.tag_ht_sensor_activity,"plotChart(): List.size:" + timeList.size());
Log.v(c.tag_ht_sensor_activity, "plotChart(): temperatureList.end: " + temperatureList.get(temperatureList.size() - 1));
Log.v(c.tag_ht_sensor_activity,"plotChart(): humidityList.end: "+humidityList.get(humidityList.size()-1));
}
});
Thread.sleep(c.val_ui_update_period_ms);
} catch (InterruptedException e) {
e.printStackTrace();
}
}//while()
}
}.start();
}
private void updateDataList(double temperature, double humidity){
temperatureList.add(temperature);
humidityList.add(humidity);
while(temperatureList.size()>maxListSize){
temperatureList.remove(0);
}
while(humidityList.size()>maxListSize){
humidityList.remove(0);
}
receivedNewData =true;
}
}
package com.realtek.wigadget;
import android.app.Activity;
import android.content.SharedPreferences;
import android.graphics.Color;
import android.media.MediaPlayer;
import android.os.Bundle;
import android.preference.PreferenceManager;
import android.util.Log;
import android.widget.TextView;
import com.androidplot.ui.SizeLayoutType;
import com.androidplot.ui.SizeMetrics;
import com.androidplot.xy.BoundaryMode;
import com.androidplot.xy.LineAndPointFormatter;
import com.androidplot.xy.PointLabelFormatter;
import com.androidplot.xy.SimpleXYSeries;
import com.androidplot.xy.XYPlot;
import com.androidplot.xy.XYSeries;
import com.androidplot.xy.XYStepMode;
import com.firebase.client.DataSnapshot;
import com.firebase.client.Firebase;
import com.firebase.client.FirebaseError;
import com.firebase.client.ValueEventListener;
import org.json.JSONObject;
import java.net.InetAddress;
import java.text.DecimalFormat;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Vector;
public class HTSensorActivity extends Activity {
private static final Constants c = Constants.getInstance();
private AES128 mAES = new AES128();
private String mIp;
private int mPort;
private String mAESKey;
private String mFirebaseAppId;
private String mMac;
private String mDescription;
private TextView textViewTemp;
private TextView textViewHumi;
private boolean runLocalLink = true;
private boolean runCloudLink = true;
private XYPlot plot;
private List<Double> timeList= new Vector<>();
private List<Double> temperatureList=new Vector<>();
private List<Double> humidityList=new Vector<>();
private int maxListSize = 6;
private long timeCounter = 0;
private boolean receivedNewData =false;
private SharedPreferences sp;
private int dataUpdateDelay = c.val_ht_sensor_default_data_update_frequency;
private boolean alarmOptions = c.val_ht_sensor_default_alarm_options;
private double tempTresh = c.val_ht_sensor_default_temperature_threshold;
private double humiTresh = c.val_ht_sensor_default_humidity_threshold;
private String alarmSound = c.val_ht_sensor_default_alarm_sound;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_device_ht);
mIp=getIntent().getStringExtra(c.key_ip);
mPort=getIntent().getIntExtra(c.key_port, c.val_device_not_found);
mMac=getIntent().getStringExtra(c.key_mac);
mAESKey=getIntent().getStringExtra(c.key_shared_key);
mFirebaseAppId=getIntent().getStringExtra(c.key_firebase_app_id);
mDescription=getIntent().getStringExtra(c.key_device_description);
setTitle(mDescription);
textViewTemp = (TextView)findViewById(R.id.textViewTemperature);
textViewHumi = (TextView)findViewById(R.id.textViewHumidity);
loadSharedPreference();
if((!mIp.equals(c.val_empty))&&(mPort!=c.val_device_not_found)){
try {
amebaLocalLink(mIp, mPort);
}
catch (Exception e){
Log.e(c.tag_ht_sensor_activity,"connectToAmeba() Exception e "+e);
}
}
else {
amebaCloudLink(mFirebaseAppId);
}
plotChart();
}
@Override
protected void onDestroy() {
super.onDestroy();
runLocalLink = false;
runCloudLink = false;
Log.v(c.tag_ht_sensor_activity, "onDestroy()");
}
private void loadSharedPreference(){
sp = PreferenceManager.getDefaultSharedPreferences(getBaseContext());
dataUpdateDelay = Integer.parseInt(sp.getString(c.key_ht_sensor_data_update_frequency, Integer.toString(dataUpdateDelay)));
alarmOptions = sp.getBoolean(c.key_ht_sensor_alarm_options,false);
tempTresh = Double.parseDouble(sp.getString(c.key_ht_sensor_temperature_threshold, Double.toString(tempTresh)));
humiTresh=Double.parseDouble(sp.getString(c.key_ht_sensor_humidity_threshold,Double.toString(humiTresh)));
alarmSound=sp.getString(c.key_ht_sensor_alarm_sound, alarmSound);
}
private void playAlarm(double temp, double humi){
if((alarmOptions)&&((temp>tempTresh)||(humi>humiTresh))){
String sound = alarmSound;
MediaPlayer mediaPlayer;
if(sound.equals(c.val_ht_sensor_alarm_sound_altair)){
mediaPlayer = MediaPlayer.create(this, R.raw.sound_altair);
}
else if(sound.equals(c.val_ht_sensor_alarm_sound_ariel)){
mediaPlayer = MediaPlayer.create(this,R.raw.sound_ariel);
}
else if(sound.equals(c.val_ht_sensor_alarm_sound_fomalhaut)){
mediaPlayer = MediaPlayer.create(this,R.raw.sound_fomalhaut);
}
else if(sound.equals(c.val_ht_sensor_alarm_sound_tinkerbell)){
mediaPlayer = MediaPlayer.create(this,R.raw.sound_tinkerbell);
}
else {
mediaPlayer = MediaPlayer.create(this,R.raw.sound_ding);
}
mediaPlayer.start();
}
}
private void amebaLocalLink(String ip, int port)throws Exception{
final TcpClient tcpClient = new TcpClient();
Log.v(c.tag_ht_sensor_activity, "amebaLocalLink() ip/port: " + ip + "/" + port);
Log.v(c.tag_ht_sensor_activity, "amebaLocalLink() AES key: " + mAESKey);
final String mIp=ip;
final int mPort=port;
class AmebaLocalLinkGetDataThread extends Thread{
@Override
public void run() {
while (runLocalLink){
try {
Thread.sleep(dataUpdateDelay);
Log.v(c.tag_ht_sensor_activity,"amebaLocalLink() get data frequency: Every "+dataUpdateDelay+"ms");
}
catch (InterruptedException e){Log.e(c.tag_ht_sensor_activity,"AmebaLocalLinkGetDataThread InterruptedException e"+e);}
try {
String txEnc = mAES.encryptToStringOfShortArray("request", mAESKey);
Log.v(c.tag_ht_sensor_activity, "amebaLocalLink() txEnc: " + txEnc);
String rxEnc = tcpClient.echo(InetAddress.getByName(mIp), mPort, txEnc);
Log.v(c.tag_ht_sensor_activity,"amebaLocalLink() rxEnc: "+rxEnc);
String rx = mAES.decryptFromStringOfShortArray(rxEnc,mAESKey);
Log.v(c.tag_ht_sensor_activity, "amebaLocalLink() rx: " + rx);
////////////////////////parse json data////////////////////////
JSONObject jObject = new JSONObject(rx);
final double hum = jObject.getDouble(c.key_humidity);
final double tem = jObject.getDouble(c.key_temperature);
////////////////////////parse json data////////////////////////
runOnUiThread(new Runnable() {
@Override
public void run() {
textViewTemp.setText("" +tem);
textViewHumi.setText(""+hum);
updateDataList(tem,hum);
playAlarm(tem,hum);
}
});
}
catch (Exception e){Log.e(c.tag_ht_sensor_activity,"AmebaLocalLinkGetDataThread Exception e"+e);}
}//while(true)
}
}
new AmebaLocalLinkGetDataThread().start();
}
private void amebaCloudLink(String firebaseAppId){
String firebaseURL = "https://"+firebaseAppId+".firebaseio.com";
Firebase.setAndroidContext(this);
final Firebase firebaseRef = new Firebase(firebaseURL);
Log.v(c.tag_ht_sensor_activity, "amebaCloudLink() connect to firebase: " + firebaseURL);
firebaseRef.child(c.nsd_service_ht).child(mMac).addValueEventListener(new ValueEventListener() {
@Override
public void onDataChange(DataSnapshot snapshot) {
if (runCloudLink) {
Map<String, Object> newData = (Map<String, Object>) snapshot.getValue();
try {
double hum = Double.parseDouble((String) newData.get(c.key_humidity));
double tem = Double.parseDouble((String) newData.get(c.key_temperature));
textViewTemp.setText("" + tem);
textViewHumi.setText("" + hum);
updateDataList(tem, hum);
playAlarm(tem, hum);
Log.v(c.tag_ht_sensor_activity, snapshot.getValue().toString());
} catch (Exception e) {
Log.e(c.tag_ht_sensor_activity, "onDataChange() Exception e " + e);
}
}
}
@Override
public void onCancelled(FirebaseError error) {
Log.e(c.tag_ht_sensor_activity, "onCancelled() FirebaseError error" + error);
}
});
}
//////////////////////////////////////////////plot//////////////////////////////////////////////
private void plotChart(){
//init lists
timeList.add((double)0);
temperatureList.add((double)0);
humidityList.add((double)0);
new Thread() {
public void run() {
while (runLocalLink) {
try {
runOnUiThread(new Runnable() {
@Override
public void run() {
//update plot data
timeCounter++;
timeList.add((double)timeCounter);
while (timeList.size()>maxListSize){
timeList.remove(0);
}
//sync data with time:
if(!receivedNewData){
//push data manually
updateDataList(temperatureList.get(temperatureList.size()-1),humidityList.get(humidityList.size()-1));
}
//sync list length
//consider 1.when series size < timelist size 2.when series size > timelist size
while (temperatureList.size()<timeList.size()){
temperatureList.add(temperatureList.get(temperatureList.size()-1));
}
while (humidityList.size()<timeList.size()){
humidityList.add(humidityList.get(humidityList.size()-1));
}
while (temperatureList.size()>timeList.size()){
temperatureList.remove(0);
}
while (humidityList.size()>timeList.size()){
humidityList.remove(0);
}
try{
plot.clear();
}
catch (Exception e){
Log.e(c.tag_ht_sensor_activity,"Exception e"+e);
}
//////////////////////////////////////////////////plot setup//////////////////////////////////////////////////
// initialize our XYPlot reference:
plot = (XYPlot) findViewById(R.id.mySimpleXYPlot);
plot.setBorderStyle(XYPlot.BorderStyle.NONE, null, null);
plot.setGridPadding(5, 25, 25, 5);
plot.getGraphWidget().setSize(new SizeMetrics(0, SizeLayoutType.FILL, 0, SizeLayoutType.FILL));
plot.getGraphWidget().getBackgroundPaint().setColor(Color.argb(0, 0, 0, 0));
plot.getGraphWidget().getGridBackgroundPaint().setColor(Color.argb(0, 0, 0, 0));
//domain -- x
plot.getGraphWidget().getDomainLabelPaint().setColor(Color.BLACK);
plot.getGraphWidget().getDomainOriginLabelPaint().setColor(Color.BLACK);
plot.getGraphWidget().getDomainOriginLinePaint().setColor(Color.BLACK);
plot.setDomainValueFormat(new DecimalFormat("0"));
plot.setDomainStep(XYStepMode.INCREMENT_BY_VAL, 1);
plot.setDomainStepValue(1);
//range -- y
plot.getGraphWidget().getRangeLabelPaint().setColor(Color.BLACK);
plot.getGraphWidget().getRangeOriginLabelPaint().setColor(Color.BLACK);
plot.getGraphWidget().getRangeOriginLinePaint().setColor(Color.BLACK);
plot.setRangeValueFormat(new DecimalFormat("0"));
plot.setRangeStep(XYStepMode.INCREMENT_BY_VAL, 1);
plot.setRangeStepValue(5);
//label
plot.getDomainLabelWidget().getLabelPaint().setColor(Color.BLACK);
plot.getRangeLabelWidget().getLabelPaint().setColor(Color.BLACK);
// Create a formatter to use for drawing a series using LineAndPointRenderer
// and configure it from xml:
LineAndPointFormatter seriesHumiFormat = new LineAndPointFormatter();
seriesHumiFormat.setPointLabelFormatter(new PointLabelFormatter());
seriesHumiFormat.configure(getApplicationContext(), R.xml.line_point_formatter_with_plf1);
// same as above:
LineAndPointFormatter seriesTempFormat = new LineAndPointFormatter();
seriesTempFormat.setPointLabelFormatter(new PointLabelFormatter());
seriesTempFormat.configure(getApplicationContext(), R.xml.line_point_formatter_with_plf2);
// reduce the number of range labels
plot.setTicksPerRangeLabel(3);
plot.getGraphWidget().setDomainLabelOrientation(-45);
XYSeries seriesHumi = new SimpleXYSeries(timeList, humidityList, "Humidity");
XYSeries seriesTemp = new SimpleXYSeries(timeList, temperatureList, "Temperature");
plot.addSeries(seriesHumi, seriesHumiFormat);
plot.addSeries(seriesTemp, seriesTempFormat);
// handle the boundary bug -> define a boundary, DO NOT USE DEFAULT SETTINGS
List<Double> readings =new Vector<>();
for (double r : temperatureList){
readings.add(r);
}
for (double r : humidityList){
readings.add(r);
}
Collections.sort(readings);
double min=readings.get(0);
double max=readings.get(readings.size()-1);
plot.setRangeBoundaries(min,max, BoundaryMode.FIXED);
Log.v(c.tag_ht_sensor_activity,"plotChart() set range boundaries ("+min+","+max+")");
//////////////////////////////////////////////////plot setup//////////////////////////////////////////////////
plot.redraw();
receivedNewData=false;
Log.v(c.tag_ht_sensor_activity,"plotChart(): List.size:" + timeList.size());
Log.v(c.tag_ht_sensor_activity, "plotChart(): temperatureList.end: " + temperatureList.get(temperatureList.size() - 1));
Log.v(c.tag_ht_sensor_activity,"plotChart(): humidityList.end: "+humidityList.get(humidityList.size()-1));
}
});
Thread.sleep(c.val_ui_update_period_ms);
} catch (InterruptedException e) {
e.printStackTrace();
}
}//while()
}
}.start();
}
private void updateDataList(double temperature, double humidity){
temperatureList.add(temperature);
humidityList.add(humidity);
while(temperatureList.size()>maxListSize){
temperatureList.remove(0);
}
while(humidityList.size()>maxListSize){
humidityList.remove(0);
}
receivedNewData =true;
}
}

View file

@ -1,126 +1,126 @@
package com.realtek.wigadget;
import android.content.Context;
import android.net.wifi.WifiManager;
import android.os.AsyncTask;
import android.text.format.Formatter;
import android.util.Log;
import org.json.JSONException;
import java.io.IOException;
import java.net.InetAddress;
import javax.jmdns.JmDNS;
import javax.jmdns.ServiceEvent;
import javax.jmdns.ServiceListener;
/**
* Created by WUJINZHOU on 5/2/15.
*/
public class NsdHelper extends AsyncTask<Void, Void, Void> {
static final Constants c = Constants.getInstance();
private final String mServiceType = c.nsd_service_type;
private final String tag = c.tag_nsd_helper;
private DeviceList mDeviceList;
private JmDNS jmdns = null;
private ServiceListener listener = null;
private WifiManager wifi = null;
private WifiManager.MulticastLock multicastLock = null;
private Context mContext =null;
public NsdHelper(Context context)throws JSONException,IOException{
mContext=context;
mDeviceList=DeviceList.getInstance(mContext);
}
@Override
protected Void doInBackground(Void... params) {
startNSD();
return null;
}
@Override
protected void onCancelled() {
super.onCancelled();
stopNSD();
}
private void startNSD() {
Log.v(tag, "startNSD() ");
try {
wifi = (WifiManager) mContext.getSystemService(Context.WIFI_SERVICE);
String ip = Formatter.formatIpAddress(wifi.getConnectionInfo().getIpAddress());
String hostname = InetAddress.getByName(InetAddress.getByName(ip).getHostName()).toString();
multicastLock = wifi.createMulticastLock(getClass().getName());
multicastLock.setReferenceCounted(true);
multicastLock.acquire();
jmdns = JmDNS.create(InetAddress.getByName(ip),hostname);
jmdns.addServiceListener(mServiceType, listener = new ServiceListener() {
@Override
public void serviceAdded(ServiceEvent event) {
jmdns.requestServiceInfo(event.getType(), event.getName(), true);
Log.v(tag, "serviceAdded() " + event.getName());
}
@Override
public void serviceRemoved(ServiceEvent event) {
Log.v(tag, "serviceRemoved() " + event.getName());
}
@Override
public void serviceResolved(ServiceEvent event) {
try {
mDeviceList.tempListUpdate(event);
String mac = event.getInfo().getPropertyString(c.key_mac);
String pairState = event.getInfo().getPropertyString(c.key_pair_state);
Log.v(tag, "serviceResolved() " + "mac: " + mac + " pair state: " + pairState);
} catch (JSONException e) {
Log.e(tag, "serviceResolved() JSONException e" + e);
} catch (IOException e) {
Log.e(tag, "serviceResolved() IOException e" + e);
}
}
});
} catch (IOException e) {
Log.e(tag,"startNSD() IOException e:"+e);
e.printStackTrace();
}
}
private void stopNSD() {
Log.v(tag,"stopNSD() ");
if (jmdns != null) {
if (listener != null) {
jmdns.removeServiceListener(mServiceType, listener);
listener = null;
}
jmdns.unregisterAllServices();
try {
jmdns.close();
} catch (IOException e) {
Log.e(tag,"stopNSD() IOException e:"+e);
e.printStackTrace();
}
jmdns = null;
}
if (multicastLock != null) {
multicastLock.release();
multicastLock = null;
}
}
}
package com.realtek.wigadget;
import android.content.Context;
import android.net.wifi.WifiManager;
import android.os.AsyncTask;
import android.text.format.Formatter;
import android.util.Log;
import org.json.JSONException;
import java.io.IOException;
import java.net.InetAddress;
import javax.jmdns.JmDNS;
import javax.jmdns.ServiceEvent;
import javax.jmdns.ServiceListener;
/**
* Created by WUJINZHOU on 5/2/15.
*/
public class NsdHelper extends AsyncTask<Void, Void, Void> {
static final Constants c = Constants.getInstance();
private final String mServiceType = c.nsd_service_type;
private final String tag = c.tag_nsd_helper;
private DeviceList mDeviceList;
private JmDNS jmdns = null;
private ServiceListener listener = null;
private WifiManager wifi = null;
private WifiManager.MulticastLock multicastLock = null;
private Context mContext =null;
public NsdHelper(Context context)throws JSONException,IOException{
mContext=context;
mDeviceList=DeviceList.getInstance(mContext);
}
@Override
protected Void doInBackground(Void... params) {
startNSD();
return null;
}
@Override
protected void onCancelled() {
super.onCancelled();
stopNSD();
}
private void startNSD() {
Log.v(tag, "startNSD() ");
try {
wifi = (WifiManager) mContext.getSystemService(Context.WIFI_SERVICE);
String ip = Formatter.formatIpAddress(wifi.getConnectionInfo().getIpAddress());
String hostname = InetAddress.getByName(InetAddress.getByName(ip).getHostName()).toString();
multicastLock = wifi.createMulticastLock(getClass().getName());
multicastLock.setReferenceCounted(true);
multicastLock.acquire();
jmdns = JmDNS.create(InetAddress.getByName(ip),hostname);
jmdns.addServiceListener(mServiceType, listener = new ServiceListener() {
@Override
public void serviceAdded(ServiceEvent event) {
jmdns.requestServiceInfo(event.getType(), event.getName(), true);
Log.v(tag, "serviceAdded() " + event.getName());
}
@Override
public void serviceRemoved(ServiceEvent event) {
Log.v(tag, "serviceRemoved() " + event.getName());
}
@Override
public void serviceResolved(ServiceEvent event) {
try {
mDeviceList.tempListUpdate(event);
String mac = event.getInfo().getPropertyString(c.key_mac);
String pairState = event.getInfo().getPropertyString(c.key_pair_state);
Log.v(tag, "serviceResolved() " + "mac: " + mac + " pair state: " + pairState);
} catch (JSONException e) {
Log.e(tag, "serviceResolved() JSONException e" + e);
} catch (IOException e) {
Log.e(tag, "serviceResolved() IOException e" + e);
}
}
});
} catch (IOException e) {
Log.e(tag,"startNSD() IOException e:"+e);
e.printStackTrace();
}
}
private void stopNSD() {
Log.v(tag,"stopNSD() ");
if (jmdns != null) {
if (listener != null) {
jmdns.removeServiceListener(mServiceType, listener);
listener = null;
}
jmdns.unregisterAllServices();
try {
jmdns.close();
} catch (IOException e) {
Log.e(tag,"stopNSD() IOException e:"+e);
e.printStackTrace();
}
jmdns = null;
}
if (multicastLock != null) {
multicastLock.release();
multicastLock = null;
}
}
}

View file

@ -1,433 +1,433 @@
// /Copyright 2003-2005 Arthur van Hoff, Rick Blair
// Licensed under Apache License version 2.0
// Original license LGPL
package javax.jmdns;
import java.io.Closeable;
import java.io.IOException;
import java.net.InetAddress;
import java.util.Collection;
import java.util.Map;
import javax.jmdns.impl.JmDNSImpl;
/**
* mDNS implementation in Java.
*
* @author Arthur van Hoff, Rick Blair, Jeff Sonstein, Werner Randelshofer, Pierre Frisch, Scott Lewis, Scott Cytacki
*/
public abstract class JmDNS implements Closeable {
/**
*
*/
public static interface Delegate {
/**
* This method is called if JmDNS cannot recover from an I/O error.
*
* @param dns
* target DNS
* @param infos
* service info registered with the DNS
*/
public void cannotRecoverFromIOError(JmDNS dns, Collection<ServiceInfo> infos);
}
/**
* The version of JmDNS.
*/
public static final String VERSION = "3.4.2";
/**
* <p>
* Create an instance of JmDNS.
* </p>
* <p>
* <b>Note:</b> This is a convenience method. The preferred constructor is {@link #create(InetAddress, String)}.<br/>
* Check that your platform correctly handle the default localhost IP address and the local hostname. In doubt use the explicit constructor.<br/>
* This call is equivalent to <code>create(null, null)</code>.
* </p>
*
* @see #create(InetAddress, String)
* @return jmDNS instance
* @exception IOException
* if an exception occurs during the socket creation
*/
public static JmDNS create() throws IOException {
return new JmDNSImpl(null, null);
}
/**
* <p>
* Create an instance of JmDNS and bind it to a specific network interface given its IP-address.
* </p>
* <p>
* <b>Note:</b> This is a convenience method. The preferred constructor is {@link #create(InetAddress, String)}.<br/>
* Check that your platform correctly handle the default localhost IP address and the local hostname. In doubt use the explicit constructor.<br/>
* This call is equivalent to <code>create(addr, null)</code>.
* </p>
*
* @see #create(InetAddress, String)
* @param addr
* IP address to bind to.
* @return jmDNS instance
* @exception IOException
* if an exception occurs during the socket creation
*/
public static JmDNS create(final InetAddress addr) throws IOException {
return new JmDNSImpl(addr, null);
}
/**
* <p>
* Create an instance of JmDNS.
* </p>
* <p>
* <b>Note:</b> This is a convenience method. The preferred constructor is {@link #create(InetAddress, String)}.<br/>
* Check that your platform correctly handle the default localhost IP address and the local hostname. In doubt use the explicit constructor.<br/>
* This call is equivalent to <code>create(null, name)</code>.
* </p>
*
* @see #create(InetAddress, String)
* @param name
* name of the newly created JmDNS
* @return jmDNS instance
* @exception IOException
* if an exception occurs during the socket creation
*/
public static JmDNS create(final String name) throws IOException {
return new JmDNSImpl(null, name);
}
/**
* <p>
* Create an instance of JmDNS and bind it to a specific network interface given its IP-address.
* </p>
* If <code>addr</code> parameter is null this method will try to resolve to a local IP address of the machine using a network discovery:
* <ol>
* <li>Check the system property <code>net.mdns.interface</code></li>
* <li>Check the JVM local host</li>
* <li>Use the {@link NetworkTopologyDiscovery} to find a valid network interface and IP.</li>
* <li>In the last resort bind to the loopback address. This is non functional in most cases.</li>
* </ol>
* If <code>name</code> parameter is null will use the hostname. The hostname is determined by the following algorithm:
* <ol>
* <li>Get the hostname from the InetAdress obtained before.</li>
* <li>If the hostname is a reverse lookup default to <code>JmDNS name</code> or <code>computer</code> if null.</li>
* <li>If the name contains <code>'.'</code> replace them by <code>'-'</code></li>
* <li>Add <code>.local.</code> at the end of the name.</li>
* </ol>
* <p>
* <b>Note:</b> If you need to use a custom {@link NetworkTopologyDiscovery} it must be setup before any call to this method. This is done by setting up a {@link NetworkTopologyDiscovery.Factory.ClassDelegate} and installing it using
* {@link NetworkTopologyDiscovery.Factory#setClassDelegate(NetworkTopologyDiscovery.Factory.ClassDelegate)}. This must be done before creating a {@link JmDNS} or {@link JmmDNS} instance.
* </p>
*
* @param addr
* IP address to bind to.
* @param name
* name of the newly created JmDNS
* @return jmDNS instance
* @exception IOException
* if an exception occurs during the socket creation
*/
public static JmDNS create(final InetAddress addr, final String name) throws IOException {
return new JmDNSImpl(addr, name);
}
/**
* Return the name of the JmDNS instance. This is an arbitrary string that is useful for distinguishing instances.
*
* @return name of the JmDNS
*/
public abstract String getName();
/**
* Return the HostName associated with this JmDNS instance. Note: May not be the same as what started. The host name is subject to negotiation.
*
* @return Host name
*/
public abstract String getHostName();
/**
* Return the address of the interface to which this instance of JmDNS is bound.
*
* @return Internet Address
* @exception IOException
* if there is an error in the underlying protocol, such as a TCP error.
*/
public abstract InetAddress getInetAddress() throws IOException;
/**
* Return the address of the interface to which this instance of JmDNS is bound.
*
* @return Internet Address
* @exception IOException
* if there is an error in the underlying protocol, such as a TCP error.
* @deprecated do not use this implementation yields unpredictable results use {@link #getInetAddress()}
*/
@Deprecated
public abstract InetAddress getInterface() throws IOException;
/**
* Get service information. If the information is not cached, the method will block until updated information is received.
* <p/>
* Usage note: Do not call this method from the AWT event dispatcher thread. You will make the user interface unresponsive.
*
* @param type
* fully qualified service type, such as <code>_http._tcp.local.</code> .
* @param name
* unqualified service name, such as <code>foobar</code> .
* @return null if the service information cannot be obtained
*/
public abstract ServiceInfo getServiceInfo(String type, String name);
/**
* Get service information. If the information is not cached, the method will block for the given timeout until updated information is received.
* <p/>
* Usage note: If you call this method from the AWT event dispatcher thread, use a small timeout, or you will make the user interface unresponsive.
*
* @param type
* full qualified service type, such as <code>_http._tcp.local.</code> .
* @param name
* unqualified service name, such as <code>foobar</code> .
* @param timeout
* timeout in milliseconds. Typical timeout should be 5s.
* @return null if the service information cannot be obtained
*/
public abstract ServiceInfo getServiceInfo(String type, String name, long timeout);
/**
* Get service information. If the information is not cached, the method will block until updated information is received.
* <p/>
* Usage note: Do not call this method from the AWT event dispatcher thread. You will make the user interface unresponsive.
*
* @param type
* fully qualified service type, such as <code>_http._tcp.local.</code> .
* @param name
* unqualified service name, such as <code>foobar</code> .
* @param persistent
* if <code>true</code> ServiceListener.resolveService will be called whenever new new information is received.
* @return null if the service information cannot be obtained
*/
public abstract ServiceInfo getServiceInfo(String type, String name, boolean persistent);
/**
* Get service information. If the information is not cached, the method will block for the given timeout until updated information is received.
* <p/>
* Usage note: If you call this method from the AWT event dispatcher thread, use a small timeout, or you will make the user interface unresponsive.
*
* @param type
* full qualified service type, such as <code>_http._tcp.local.</code> .
* @param name
* unqualified service name, such as <code>foobar</code> .
* @param timeout
* timeout in milliseconds. Typical timeout should be 5s.
* @param persistent
* if <code>true</code> ServiceListener.resolveService will be called whenever new new information is received.
* @return null if the service information cannot be obtained
*/
public abstract ServiceInfo getServiceInfo(String type, String name, boolean persistent, long timeout);
/**
* Request service information. The information about the service is requested and the ServiceListener.resolveService method is called as soon as it is available.
* <p/>
* Usage note: Do not call this method from the AWT event dispatcher thread. You will make the user interface unresponsive.
*
* @param type
* full qualified service type, such as <code>_http._tcp.local.</code> .
* @param name
* unqualified service name, such as <code>foobar</code> .
*/
public abstract void requestServiceInfo(String type, String name);
/**
* Request service information. The information about the service is requested and the ServiceListener.resolveService method is called as soon as it is available.
* <p/>
* Usage note: Do not call this method from the AWT event dispatcher thread. You will make the user interface unresponsive.
*
* @param type
* full qualified service type, such as <code>_http._tcp.local.</code> .
* @param name
* unqualified service name, such as <code>foobar</code> .
* @param persistent
* if <code>true</code> ServiceListener.resolveService will be called whenever new new information is received.
*/
public abstract void requestServiceInfo(String type, String name, boolean persistent);
/**
* Request service information. The information about the service is requested and the ServiceListener.resolveService method is called as soon as it is available.
*
* @param type
* full qualified service type, such as <code>_http._tcp.local.</code> .
* @param name
* unqualified service name, such as <code>foobar</code> .
* @param timeout
* timeout in milliseconds
*/
public abstract void requestServiceInfo(String type, String name, long timeout);
/**
* Request service information. The information about the service is requested and the ServiceListener.resolveService method is called as soon as it is available.
*
* @param type
* full qualified service type, such as <code>_http._tcp.local.</code> .
* @param name
* unqualified service name, such as <code>foobar</code> .
* @param persistent
* if <code>true</code> ServiceListener.resolveService will be called whenever new new information is received.
* @param timeout
* timeout in milliseconds
*/
public abstract void requestServiceInfo(String type, String name, boolean persistent, long timeout);
/**
* Listen for service types.
*
* @param listener
* listener for service types
* @exception IOException
* if there is an error in the underlying protocol, such as a TCP error.
*/
public abstract void addServiceTypeListener(ServiceTypeListener listener) throws IOException;
/**
* Remove listener for service types.
*
* @param listener
* listener for service types
*/
public abstract void removeServiceTypeListener(ServiceTypeListener listener);
/**
* Listen for services of a given type. The type has to be a fully qualified type name such as <code>_http._tcp.local.</code>.
*
* @param type
* full qualified service type, such as <code>_http._tcp.local.</code>.
* @param listener
* listener for service updates
*/
public abstract void addServiceListener(String type, ServiceListener listener);
/**
* Remove listener for services of a given type.
*
* @param type
* full qualified service type, such as <code>_http._tcp.local.</code>.
* @param listener
* listener for service updates
*/
public abstract void removeServiceListener(String type, ServiceListener listener);
/**
* Register a service. The service is registered for access by other jmdns clients. The name of the service may be changed to make it unique.<br>
* Note that the given {@code ServiceInfo} is bound to this {@code JmDNS} instance, and should not be reused for any other {@linkplain #registerService(ServiceInfo)}.
*
* @param info
* service info to register
* @exception IOException
* if there is an error in the underlying protocol, such as a TCP error.
*/
public abstract void registerService(ServiceInfo info) throws IOException;
/**
* Unregister a service. The service should have been registered.
* <p>
* <b>Note:</b> Unregistered services will not disappear form the list of services immediately. According to the specification, when unregistering services we send goodbye packets and then wait <b>1s</b> before purging the cache.<br/>
* This is support for shared records that can be rescued by some other cooperation DNS.
*
* <pre>
* Clients receiving a Multicast DNS Response with a TTL of zero SHOULD NOT immediately delete the record from the cache, but instead record a TTL of 1 and then delete the record one second later.
* </pre>
*
* </p>
*
* @param info
* service info to remove
*/
public abstract void unregisterService(ServiceInfo info);
/**
* Unregister all services.
*/
public abstract void unregisterAllServices();
/**
* Register a service type. If this service type was not already known, all service listeners will be notified of the new service type.
* <p>
* Service types are automatically registered as they are discovered.
* </p>
*
* @param type
* full qualified service type, such as <code>_http._tcp.local.</code>.
* @return <code>true</code> if the type or subtype was added, <code>false</code> if the type was already registered.
*/
public abstract boolean registerServiceType(String type);
/**
* List Services and serviceTypes. Debugging Only
*
* @deprecated since 3.2.2
*/
@Deprecated
public abstract void printServices();
/**
* Returns a list of service infos of the specified type.
*
* @param type
* Service type name, such as <code>_http._tcp.local.</code>.
* @return An array of service instance.
*/
public abstract ServiceInfo[] list(String type);
/**
* Returns a list of service infos of the specified type.
*
* @param type
* Service type name, such as <code>_http._tcp.local.</code>.
* @param timeout
* timeout in milliseconds. Typical timeout should be 6s.
* @return An array of service instance.
*/
public abstract ServiceInfo[] list(String type, long timeout);
/**
* Returns a list of service infos of the specified type sorted by subtype. Any service that do not register a subtype is listed in the empty subtype section.
*
* @param type
* Service type name, such as <code>_http._tcp.local.</code>.
* @return A dictionary of service info by subtypes.
*/
public abstract Map<String, ServiceInfo[]> listBySubtype(String type);
/**
* Returns a list of service infos of the specified type sorted by subtype. Any service that do not register a subtype is listed in the empty subtype section.
*
* @param type
* Service type name, such as <code>_http._tcp.local.</code>.
* @param timeout
* timeout in milliseconds. Typical timeout should be 6s.
* @return A dictionary of service info by subtypes.
*/
public abstract Map<String, ServiceInfo[]> listBySubtype(String type, long timeout);
/**
* Returns the instance delegate
*
* @return instance delegate
*/
public abstract Delegate getDelegate();
/**
* Sets the instance delegate
*
* @param value
* new instance delegate
* @return previous instance delegate
*/
public abstract Delegate setDelegate(Delegate value);
}
// /Copyright 2003-2005 Arthur van Hoff, Rick Blair
// Licensed under Apache License version 2.0
// Original license LGPL
package javax.jmdns;
import java.io.Closeable;
import java.io.IOException;
import java.net.InetAddress;
import java.util.Collection;
import java.util.Map;
import javax.jmdns.impl.JmDNSImpl;
/**
* mDNS implementation in Java.
*
* @author Arthur van Hoff, Rick Blair, Jeff Sonstein, Werner Randelshofer, Pierre Frisch, Scott Lewis, Scott Cytacki
*/
public abstract class JmDNS implements Closeable {
/**
*
*/
public static interface Delegate {
/**
* This method is called if JmDNS cannot recover from an I/O error.
*
* @param dns
* target DNS
* @param infos
* service info registered with the DNS
*/
public void cannotRecoverFromIOError(JmDNS dns, Collection<ServiceInfo> infos);
}
/**
* The version of JmDNS.
*/
public static final String VERSION = "3.4.2";
/**
* <p>
* Create an instance of JmDNS.
* </p>
* <p>
* <b>Note:</b> This is a convenience method. The preferred constructor is {@link #create(InetAddress, String)}.<br/>
* Check that your platform correctly handle the default localhost IP address and the local hostname. In doubt use the explicit constructor.<br/>
* This call is equivalent to <code>create(null, null)</code>.
* </p>
*
* @see #create(InetAddress, String)
* @return jmDNS instance
* @exception IOException
* if an exception occurs during the socket creation
*/
public static JmDNS create() throws IOException {
return new JmDNSImpl(null, null);
}
/**
* <p>
* Create an instance of JmDNS and bind it to a specific network interface given its IP-address.
* </p>
* <p>
* <b>Note:</b> This is a convenience method. The preferred constructor is {@link #create(InetAddress, String)}.<br/>
* Check that your platform correctly handle the default localhost IP address and the local hostname. In doubt use the explicit constructor.<br/>
* This call is equivalent to <code>create(addr, null)</code>.
* </p>
*
* @see #create(InetAddress, String)
* @param addr
* IP address to bind to.
* @return jmDNS instance
* @exception IOException
* if an exception occurs during the socket creation
*/
public static JmDNS create(final InetAddress addr) throws IOException {
return new JmDNSImpl(addr, null);
}
/**
* <p>
* Create an instance of JmDNS.
* </p>
* <p>
* <b>Note:</b> This is a convenience method. The preferred constructor is {@link #create(InetAddress, String)}.<br/>
* Check that your platform correctly handle the default localhost IP address and the local hostname. In doubt use the explicit constructor.<br/>
* This call is equivalent to <code>create(null, name)</code>.
* </p>
*
* @see #create(InetAddress, String)
* @param name
* name of the newly created JmDNS
* @return jmDNS instance
* @exception IOException
* if an exception occurs during the socket creation
*/
public static JmDNS create(final String name) throws IOException {
return new JmDNSImpl(null, name);
}
/**
* <p>
* Create an instance of JmDNS and bind it to a specific network interface given its IP-address.
* </p>
* If <code>addr</code> parameter is null this method will try to resolve to a local IP address of the machine using a network discovery:
* <ol>
* <li>Check the system property <code>net.mdns.interface</code></li>
* <li>Check the JVM local host</li>
* <li>Use the {@link NetworkTopologyDiscovery} to find a valid network interface and IP.</li>
* <li>In the last resort bind to the loopback address. This is non functional in most cases.</li>
* </ol>
* If <code>name</code> parameter is null will use the hostname. The hostname is determined by the following algorithm:
* <ol>
* <li>Get the hostname from the InetAdress obtained before.</li>
* <li>If the hostname is a reverse lookup default to <code>JmDNS name</code> or <code>computer</code> if null.</li>
* <li>If the name contains <code>'.'</code> replace them by <code>'-'</code></li>
* <li>Add <code>.local.</code> at the end of the name.</li>
* </ol>
* <p>
* <b>Note:</b> If you need to use a custom {@link NetworkTopologyDiscovery} it must be setup before any call to this method. This is done by setting up a {@link NetworkTopologyDiscovery.Factory.ClassDelegate} and installing it using
* {@link NetworkTopologyDiscovery.Factory#setClassDelegate(NetworkTopologyDiscovery.Factory.ClassDelegate)}. This must be done before creating a {@link JmDNS} or {@link JmmDNS} instance.
* </p>
*
* @param addr
* IP address to bind to.
* @param name
* name of the newly created JmDNS
* @return jmDNS instance
* @exception IOException
* if an exception occurs during the socket creation
*/
public static JmDNS create(final InetAddress addr, final String name) throws IOException {
return new JmDNSImpl(addr, name);
}
/**
* Return the name of the JmDNS instance. This is an arbitrary string that is useful for distinguishing instances.
*
* @return name of the JmDNS
*/
public abstract String getName();
/**
* Return the HostName associated with this JmDNS instance. Note: May not be the same as what started. The host name is subject to negotiation.
*
* @return Host name
*/
public abstract String getHostName();
/**
* Return the address of the interface to which this instance of JmDNS is bound.
*
* @return Internet Address
* @exception IOException
* if there is an error in the underlying protocol, such as a TCP error.
*/
public abstract InetAddress getInetAddress() throws IOException;
/**
* Return the address of the interface to which this instance of JmDNS is bound.
*
* @return Internet Address
* @exception IOException
* if there is an error in the underlying protocol, such as a TCP error.
* @deprecated do not use this implementation yields unpredictable results use {@link #getInetAddress()}
*/
@Deprecated
public abstract InetAddress getInterface() throws IOException;
/**
* Get service information. If the information is not cached, the method will block until updated information is received.
* <p/>
* Usage note: Do not call this method from the AWT event dispatcher thread. You will make the user interface unresponsive.
*
* @param type
* fully qualified service type, such as <code>_http._tcp.local.</code> .
* @param name
* unqualified service name, such as <code>foobar</code> .
* @return null if the service information cannot be obtained
*/
public abstract ServiceInfo getServiceInfo(String type, String name);
/**
* Get service information. If the information is not cached, the method will block for the given timeout until updated information is received.
* <p/>
* Usage note: If you call this method from the AWT event dispatcher thread, use a small timeout, or you will make the user interface unresponsive.
*
* @param type
* full qualified service type, such as <code>_http._tcp.local.</code> .
* @param name
* unqualified service name, such as <code>foobar</code> .
* @param timeout
* timeout in milliseconds. Typical timeout should be 5s.
* @return null if the service information cannot be obtained
*/
public abstract ServiceInfo getServiceInfo(String type, String name, long timeout);
/**
* Get service information. If the information is not cached, the method will block until updated information is received.
* <p/>
* Usage note: Do not call this method from the AWT event dispatcher thread. You will make the user interface unresponsive.
*
* @param type
* fully qualified service type, such as <code>_http._tcp.local.</code> .
* @param name
* unqualified service name, such as <code>foobar</code> .
* @param persistent
* if <code>true</code> ServiceListener.resolveService will be called whenever new new information is received.
* @return null if the service information cannot be obtained
*/
public abstract ServiceInfo getServiceInfo(String type, String name, boolean persistent);
/**
* Get service information. If the information is not cached, the method will block for the given timeout until updated information is received.
* <p/>
* Usage note: If you call this method from the AWT event dispatcher thread, use a small timeout, or you will make the user interface unresponsive.
*
* @param type
* full qualified service type, such as <code>_http._tcp.local.</code> .
* @param name
* unqualified service name, such as <code>foobar</code> .
* @param timeout
* timeout in milliseconds. Typical timeout should be 5s.
* @param persistent
* if <code>true</code> ServiceListener.resolveService will be called whenever new new information is received.
* @return null if the service information cannot be obtained
*/
public abstract ServiceInfo getServiceInfo(String type, String name, boolean persistent, long timeout);
/**
* Request service information. The information about the service is requested and the ServiceListener.resolveService method is called as soon as it is available.
* <p/>
* Usage note: Do not call this method from the AWT event dispatcher thread. You will make the user interface unresponsive.
*
* @param type
* full qualified service type, such as <code>_http._tcp.local.</code> .
* @param name
* unqualified service name, such as <code>foobar</code> .
*/
public abstract void requestServiceInfo(String type, String name);
/**
* Request service information. The information about the service is requested and the ServiceListener.resolveService method is called as soon as it is available.
* <p/>
* Usage note: Do not call this method from the AWT event dispatcher thread. You will make the user interface unresponsive.
*
* @param type
* full qualified service type, such as <code>_http._tcp.local.</code> .
* @param name
* unqualified service name, such as <code>foobar</code> .
* @param persistent
* if <code>true</code> ServiceListener.resolveService will be called whenever new new information is received.
*/
public abstract void requestServiceInfo(String type, String name, boolean persistent);
/**
* Request service information. The information about the service is requested and the ServiceListener.resolveService method is called as soon as it is available.
*
* @param type
* full qualified service type, such as <code>_http._tcp.local.</code> .
* @param name
* unqualified service name, such as <code>foobar</code> .
* @param timeout
* timeout in milliseconds
*/
public abstract void requestServiceInfo(String type, String name, long timeout);
/**
* Request service information. The information about the service is requested and the ServiceListener.resolveService method is called as soon as it is available.
*
* @param type
* full qualified service type, such as <code>_http._tcp.local.</code> .
* @param name
* unqualified service name, such as <code>foobar</code> .
* @param persistent
* if <code>true</code> ServiceListener.resolveService will be called whenever new new information is received.
* @param timeout
* timeout in milliseconds
*/
public abstract void requestServiceInfo(String type, String name, boolean persistent, long timeout);
/**
* Listen for service types.
*
* @param listener
* listener for service types
* @exception IOException
* if there is an error in the underlying protocol, such as a TCP error.
*/
public abstract void addServiceTypeListener(ServiceTypeListener listener) throws IOException;
/**
* Remove listener for service types.
*
* @param listener
* listener for service types
*/
public abstract void removeServiceTypeListener(ServiceTypeListener listener);
/**
* Listen for services of a given type. The type has to be a fully qualified type name such as <code>_http._tcp.local.</code>.
*
* @param type
* full qualified service type, such as <code>_http._tcp.local.</code>.
* @param listener
* listener for service updates
*/
public abstract void addServiceListener(String type, ServiceListener listener);
/**
* Remove listener for services of a given type.
*
* @param type
* full qualified service type, such as <code>_http._tcp.local.</code>.
* @param listener
* listener for service updates
*/
public abstract void removeServiceListener(String type, ServiceListener listener);
/**
* Register a service. The service is registered for access by other jmdns clients. The name of the service may be changed to make it unique.<br>
* Note that the given {@code ServiceInfo} is bound to this {@code JmDNS} instance, and should not be reused for any other {@linkplain #registerService(ServiceInfo)}.
*
* @param info
* service info to register
* @exception IOException
* if there is an error in the underlying protocol, such as a TCP error.
*/
public abstract void registerService(ServiceInfo info) throws IOException;
/**
* Unregister a service. The service should have been registered.
* <p>
* <b>Note:</b> Unregistered services will not disappear form the list of services immediately. According to the specification, when unregistering services we send goodbye packets and then wait <b>1s</b> before purging the cache.<br/>
* This is support for shared records that can be rescued by some other cooperation DNS.
*
* <pre>
* Clients receiving a Multicast DNS Response with a TTL of zero SHOULD NOT immediately delete the record from the cache, but instead record a TTL of 1 and then delete the record one second later.
* </pre>
*
* </p>
*
* @param info
* service info to remove
*/
public abstract void unregisterService(ServiceInfo info);
/**
* Unregister all services.
*/
public abstract void unregisterAllServices();
/**
* Register a service type. If this service type was not already known, all service listeners will be notified of the new service type.
* <p>
* Service types are automatically registered as they are discovered.
* </p>
*
* @param type
* full qualified service type, such as <code>_http._tcp.local.</code>.
* @return <code>true</code> if the type or subtype was added, <code>false</code> if the type was already registered.
*/
public abstract boolean registerServiceType(String type);
/**
* List Services and serviceTypes. Debugging Only
*
* @deprecated since 3.2.2
*/
@Deprecated
public abstract void printServices();
/**
* Returns a list of service infos of the specified type.
*
* @param type
* Service type name, such as <code>_http._tcp.local.</code>.
* @return An array of service instance.
*/
public abstract ServiceInfo[] list(String type);
/**
* Returns a list of service infos of the specified type.
*
* @param type
* Service type name, such as <code>_http._tcp.local.</code>.
* @param timeout
* timeout in milliseconds. Typical timeout should be 6s.
* @return An array of service instance.
*/
public abstract ServiceInfo[] list(String type, long timeout);
/**
* Returns a list of service infos of the specified type sorted by subtype. Any service that do not register a subtype is listed in the empty subtype section.
*
* @param type
* Service type name, such as <code>_http._tcp.local.</code>.
* @return A dictionary of service info by subtypes.
*/
public abstract Map<String, ServiceInfo[]> listBySubtype(String type);
/**
* Returns a list of service infos of the specified type sorted by subtype. Any service that do not register a subtype is listed in the empty subtype section.
*
* @param type
* Service type name, such as <code>_http._tcp.local.</code>.
* @param timeout
* timeout in milliseconds. Typical timeout should be 6s.
* @return A dictionary of service info by subtypes.
*/
public abstract Map<String, ServiceInfo[]> listBySubtype(String type, long timeout);
/**
* Returns the instance delegate
*
* @return instance delegate
*/
public abstract Delegate getDelegate();
/**
* Sets the instance delegate
*
* @param value
* new instance delegate
* @return previous instance delegate
*/
public abstract Delegate setDelegate(Delegate value);
}

View file

@ -1,426 +1,426 @@
/**
*
*/
package javax.jmdns;
import java.io.Closeable;
import java.io.IOException;
import java.net.InetAddress;
import java.util.Map;
import java.util.concurrent.atomic.AtomicReference;
import javax.jmdns.impl.JmmDNSImpl;
/**
* <p>
* Java Multihomed Multicast DNS
* </p>
* Uses an underlying {@link JmDNS} instance for each {@link InetAddress} found on this computer.<br/>
* This class will monitor network topology changes, and will create or destroy JmDNS instances as required. It is your responsibility to maintain services registration (hint: use a {@link NetworkTopologyListener}).<br/>
* Most of this class methods have no notion of transaction: if an Exception is raised in the middle of execution, you may be in an incoherent state.
* <p>
* <b>Note:</b> This API is experimental and may change in the future please let us know what work and what does not work in your application.
* </p>
*
* @author C&eacute;drik Lime, Pierre Frisch
*/
public interface JmmDNS extends Closeable {
/**
* JmmDNS.Factory enable the creation of new instance of JmmDNS.
*/
public static final class Factory {
private static volatile JmmDNS _instance;
/**
* This interface defines a delegate to the EOClassDescriptionRegister class to enable subclassing.
*/
public static interface ClassDelegate {
/**
* Allows the delegate the opportunity to construct and return a different JmmDNS.
*
* @return Should return a new JmmDNS.
* @see #classDelegate()
* @see #setClassDelegate(ClassDelegate anObject)
*/
public JmmDNS newJmmDNS();
}
private static final AtomicReference<ClassDelegate> _databaseClassDelegate = new AtomicReference<ClassDelegate>();
private Factory() {
super();
}
/**
* Assigns <code>delegate</code> as JmmDNS's class delegate. The class delegate is optional.
*
* @param delegate
* The object to set as JmmDNS's class delegate.
* @see #classDelegate()
* @see JmmDNS.Factory.ClassDelegate
*/
public static void setClassDelegate(ClassDelegate delegate) {
_databaseClassDelegate.set(delegate);
}
/**
* Returns JmmDNS's class delegate.
*
* @return JmmDNS's class delegate.
* @see #setClassDelegate(ClassDelegate anObject)
* @see JmmDNS.Factory.ClassDelegate
*/
public static ClassDelegate classDelegate() {
return _databaseClassDelegate.get();
}
/**
* Returns a new instance of JmmDNS using the class delegate if it exists.
*
* @return new instance of JmmDNS
*/
protected static JmmDNS newJmmDNS() {
JmmDNS dns = null;
ClassDelegate delegate = _databaseClassDelegate.get();
if (delegate != null) {
dns = delegate.newJmmDNS();
}
return (dns != null ? dns : new JmmDNSImpl());
}
/**
* Return the instance of the Multihomed Multicast DNS.
*
* @return the JmmDNS
*/
public static JmmDNS getInstance() {
if (_instance == null) {
synchronized (Factory.class) {
if (_instance == null) {
_instance = JmmDNS.Factory.newJmmDNS();
}
}
}
return _instance;
}
/**
* Closes the instance if still running and discard it.
*
* @throws IOException
*/
public static void close() throws IOException {
synchronized (Factory.class) {
_instance.close();
_instance = null;
}
}
}
/**
* Return the names of the JmDNS instances.
*
* @return list of name of the JmDNS
* @see javax.jmdns.JmDNS#getName()
*/
public abstract String[] getNames();
/**
* Return the list HostName associated with this JmmDNS instance.
*
* @return list of host names
* @see javax.jmdns.JmDNS#getHostName()
*/
public abstract String[] getHostNames();
/**
* Return the list of addresses of the interface to which this instance of JmmDNS is bound.
*
* @return list of Internet Address
* @exception IOException
* @see javax.jmdns.JmDNS#getInetAddress()
*/
public abstract InetAddress[] getInetAddresses() throws IOException;
/**
* Return the list of addresses of the interface to which this instance of JmmDNS is bound.
*
* @return list of Internet Address
* @exception IOException
* @see javax.jmdns.JmDNS#getInterface()
* @deprecated do not use this implementation yields unpredictable results use {@link #getInetAddresses()}
*/
@Deprecated
public abstract InetAddress[] getInterfaces() throws IOException;
/**
* Return a list of all the registered JmDNS instances
*
* @return list of JmDNS instances
*/
public abstract JmDNS[] getDNS();
/**
* Get service information. If the information is not cached, the method will block until updated information is received on all DNS.
* <p/>
* Usage note: Do not call this method from the AWT event dispatcher thread. You will make the user interface unresponsive.
*
* @param type
* fully qualified service type, such as <code>_http._tcp.local.</code> .
* @param name
* unqualified service name, such as <code>foobar</code> .
* @return list of service info. If no service info is found the list is empty.
* @see javax.jmdns.JmDNS#getServiceInfo(java.lang.String, java.lang.String)
*/
public abstract ServiceInfo[] getServiceInfos(String type, String name);
/**
* Get service information. If the information is not cached, the method will block until updated information is received on all DNS.
* <p/>
* Usage note: If you call this method from the AWT event dispatcher thread, use a small timeout, or you will make the user interface unresponsive.
*
* @param type
* full qualified service type, such as <code>_http._tcp.local.</code> .
* @param name
* unqualified service name, such as <code>foobar</code> .
* @param timeout
* timeout in milliseconds. Typical timeout should be 5s.
* @return list of service info. If no service info is found the list is empty.
* @see javax.jmdns.JmDNS#getServiceInfo(java.lang.String, java.lang.String, long)
*/
public abstract ServiceInfo[] getServiceInfos(String type, String name, long timeout);
/**
* Get service information. If the information is not cached, the method will block until updated information is received on all DNS.
* <p/>
* Usage note: If you call this method from the AWT event dispatcher thread, use a small timeout, or you will make the user interface unresponsive.
*
* @param type
* full qualified service type, such as <code>_http._tcp.local.</code> .
* @param name
* unqualified service name, such as <code>foobar</code> .
* @param persistent
* if <code>true</code> ServiceListener.resolveService will be called whenever new new information is received.
* @return list of service info. If no service info is found the list is empty.
* @see javax.jmdns.JmDNS#getServiceInfo(java.lang.String, java.lang.String, boolean)
*/
public abstract ServiceInfo[] getServiceInfos(String type, String name, boolean persistent);
/**
* Get service information. If the information is not cached, the method will block until updated information is received on all DNS.
* <p/>
* Usage note: If you call this method from the AWT event dispatcher thread, use a small timeout, or you will make the user interface unresponsive.
*
* @param type
* full qualified service type, such as <code>_http._tcp.local.</code> .
* @param name
* unqualified service name, such as <code>foobar</code> .
* @param timeout
* timeout in milliseconds. Typical timeout should be 5s.
* @param persistent
* if <code>true</code> ServiceListener.resolveService will be called whenever new new information is received.
* @return list of service info. If no service info is found the list is empty.
* @see javax.jmdns.JmDNS#getServiceInfo(java.lang.String, java.lang.String, boolean, long)
*/
public abstract ServiceInfo[] getServiceInfos(String type, String name, boolean persistent, long timeout);
/**
* Request service information. The information about the service is requested and the ServiceListener.resolveService method is called as soon as it is available.
*
* @param type
* full qualified service type, such as <code>_http._tcp.local.</code> .
* @param name
* unqualified service name, such as <code>foobar</code> .
* @see javax.jmdns.JmDNS#requestServiceInfo(java.lang.String, java.lang.String)
*/
public abstract void requestServiceInfo(String type, String name);
/**
* Request service information. The information about the service is requested and the ServiceListener.resolveService method is called as soon as it is available.
*
* @param type
* full qualified service type, such as <code>_http._tcp.local.</code> .
* @param name
* unqualified service name, such as <code>foobar</code> .
* @param persistent
* if <code>true</code> ServiceListener.resolveService will be called whenever new new information is received.
* @see javax.jmdns.JmDNS#requestServiceInfo(java.lang.String, java.lang.String, boolean)
*/
public abstract void requestServiceInfo(String type, String name, boolean persistent);
/**
* Request service information. The information about the service is requested and the ServiceListener.resolveService method is called as soon as it is available.
*
* @param type
* full qualified service type, such as <code>_http._tcp.local.</code> .
* @param name
* unqualified service name, such as <code>foobar</code> .
* @param timeout
* timeout in milliseconds
* @see javax.jmdns.JmDNS#requestServiceInfo(java.lang.String, java.lang.String, long)
*/
public abstract void requestServiceInfo(String type, String name, long timeout);
/**
* Request service information. The information about the service is requested and the ServiceListener.resolveService method is called as soon as it is available.
*
* @param type
* full qualified service type, such as <code>_http._tcp.local.</code> .
* @param name
* unqualified service name, such as <code>foobar</code> .
* @param persistent
* if <code>true</code> ServiceListener.resolveService will be called whenever new new information is received.
* @param timeout
* timeout in milliseconds
* @see javax.jmdns.JmDNS#requestServiceInfo(java.lang.String, java.lang.String, boolean, long)
*/
public abstract void requestServiceInfo(String type, String name, boolean persistent, long timeout);
/**
* Listen for service types.
*
* @param listener
* listener for service types
* @exception IOException
* @see javax.jmdns.JmDNS#addServiceTypeListener(javax.jmdns.ServiceTypeListener)
*/
public abstract void addServiceTypeListener(ServiceTypeListener listener) throws IOException;
/**
* Remove listener for service types.
*
* @param listener
* listener for service types
* @see javax.jmdns.JmDNS#removeServiceTypeListener(javax.jmdns.ServiceTypeListener)
*/
public abstract void removeServiceTypeListener(ServiceTypeListener listener);
/**
* Listen for services of a given type. The type has to be a fully qualified type name such as <code>_http._tcp.local.</code>.
*
* @param type
* full qualified service type, such as <code>_http._tcp.local.</code>.
* @param listener
* listener for service updates
* @see javax.jmdns.JmDNS#addServiceListener(java.lang.String, javax.jmdns.ServiceListener)
*/
public abstract void addServiceListener(String type, ServiceListener listener);
/**
* Remove listener for services of a given type.
*
* @param type
* full qualified service type, such as <code>_http._tcp.local.</code>.
* @param listener
* listener for service updates
* @see javax.jmdns.JmDNS#removeServiceListener(java.lang.String, javax.jmdns.ServiceListener)
*/
public abstract void removeServiceListener(String type, ServiceListener listener);
/**
* Register a service. The service is registered for access by other jmdns clients. The name of the service may be changed to make it unique.<br>
* <b>Note</b> the Service info is cloned for each network interface.
*
* @param info
* service info to register
* @exception IOException
* @see javax.jmdns.JmDNS#registerService(javax.jmdns.ServiceInfo)
*/
public abstract void registerService(ServiceInfo info) throws IOException;
/**
* Unregister a service. The service should have been registered.
*
* @param info
* service info to remove
* @see javax.jmdns.JmDNS#unregisterService(javax.jmdns.ServiceInfo)
*/
public abstract void unregisterService(ServiceInfo info);
/**
* Unregister all services.
*
* @see javax.jmdns.JmDNS#unregisterAllServices()
*/
public abstract void unregisterAllServices();
/**
* Register a service type. If this service type was not already known, all service listeners will be notified of the new service type. Service types are automatically registered as they are discovered.
*
* @param type
* full qualified service type, such as <code>_http._tcp.local.</code>.
* @see javax.jmdns.JmDNS#registerServiceType(java.lang.String)
*/
public abstract void registerServiceType(String type);
/**
* Returns a list of service infos of the specified type.
*
* @param type
* Service type name, such as <code>_http._tcp.local.</code>.
* @return An array of service instance.
* @see javax.jmdns.JmDNS#list(java.lang.String)
*/
public abstract ServiceInfo[] list(String type);
/**
* Returns a list of service infos of the specified type.
*
* @param type
* Service type name, such as <code>_http._tcp.local.</code>.
* @param timeout
* timeout in milliseconds. Typical timeout should be 6s.
* @return An array of service instance.
* @see javax.jmdns.JmDNS#list(java.lang.String, long)
*/
public abstract ServiceInfo[] list(String type, long timeout);
/**
* Returns a list of service infos of the specified type sorted by subtype. Any service that do not register a subtype is listed in the empty subtype section.
*
* @param type
* Service type name, such as <code>_http._tcp.local.</code>.
* @return A dictionary of service info by subtypes.
* @see javax.jmdns.JmDNS#listBySubtype(java.lang.String)
*/
public abstract Map<String, ServiceInfo[]> listBySubtype(String type);
/**
* Returns a list of service infos of the specified type sorted by subtype. Any service that do not register a subtype is listed in the empty subtype section.
*
* @param type
* Service type name, such as <code>_http._tcp.local.</code>.
* @param timeout
* timeout in milliseconds. Typical timeout should be 6s.
* @return A dictionary of service info by subtypes.
* @see javax.jmdns.JmDNS#listBySubtype(java.lang.String, long)
*/
public abstract Map<String, ServiceInfo[]> listBySubtype(String type, long timeout);
/**
* Listen to network changes.
*
* @param listener
* listener for network changes
*/
public abstract void addNetworkTopologyListener(NetworkTopologyListener listener);
/**
* Remove listener for network changes.
*
* @param listener
* listener for network changes
*/
public abstract void removeNetworkTopologyListener(NetworkTopologyListener listener);
/**
* Returns list of network change listeners
*
* @return list of network change listeners
*/
public abstract NetworkTopologyListener[] networkListeners();
}
/**
*
*/
package javax.jmdns;
import java.io.Closeable;
import java.io.IOException;
import java.net.InetAddress;
import java.util.Map;
import java.util.concurrent.atomic.AtomicReference;
import javax.jmdns.impl.JmmDNSImpl;
/**
* <p>
* Java Multihomed Multicast DNS
* </p>
* Uses an underlying {@link JmDNS} instance for each {@link InetAddress} found on this computer.<br/>
* This class will monitor network topology changes, and will create or destroy JmDNS instances as required. It is your responsibility to maintain services registration (hint: use a {@link NetworkTopologyListener}).<br/>
* Most of this class methods have no notion of transaction: if an Exception is raised in the middle of execution, you may be in an incoherent state.
* <p>
* <b>Note:</b> This API is experimental and may change in the future please let us know what work and what does not work in your application.
* </p>
*
* @author C&eacute;drik Lime, Pierre Frisch
*/
public interface JmmDNS extends Closeable {
/**
* JmmDNS.Factory enable the creation of new instance of JmmDNS.
*/
public static final class Factory {
private static volatile JmmDNS _instance;
/**
* This interface defines a delegate to the EOClassDescriptionRegister class to enable subclassing.
*/
public static interface ClassDelegate {
/**
* Allows the delegate the opportunity to construct and return a different JmmDNS.
*
* @return Should return a new JmmDNS.
* @see #classDelegate()
* @see #setClassDelegate(ClassDelegate anObject)
*/
public JmmDNS newJmmDNS();
}
private static final AtomicReference<ClassDelegate> _databaseClassDelegate = new AtomicReference<ClassDelegate>();
private Factory() {
super();
}
/**
* Assigns <code>delegate</code> as JmmDNS's class delegate. The class delegate is optional.
*
* @param delegate
* The object to set as JmmDNS's class delegate.
* @see #classDelegate()
* @see JmmDNS.Factory.ClassDelegate
*/
public static void setClassDelegate(ClassDelegate delegate) {
_databaseClassDelegate.set(delegate);
}
/**
* Returns JmmDNS's class delegate.
*
* @return JmmDNS's class delegate.
* @see #setClassDelegate(ClassDelegate anObject)
* @see JmmDNS.Factory.ClassDelegate
*/
public static ClassDelegate classDelegate() {
return _databaseClassDelegate.get();
}
/**
* Returns a new instance of JmmDNS using the class delegate if it exists.
*
* @return new instance of JmmDNS
*/
protected static JmmDNS newJmmDNS() {
JmmDNS dns = null;
ClassDelegate delegate = _databaseClassDelegate.get();
if (delegate != null) {
dns = delegate.newJmmDNS();
}
return (dns != null ? dns : new JmmDNSImpl());
}
/**
* Return the instance of the Multihomed Multicast DNS.
*
* @return the JmmDNS
*/
public static JmmDNS getInstance() {
if (_instance == null) {
synchronized (Factory.class) {
if (_instance == null) {
_instance = JmmDNS.Factory.newJmmDNS();
}
}
}
return _instance;
}
/**
* Closes the instance if still running and discard it.
*
* @throws IOException
*/
public static void close() throws IOException {
synchronized (Factory.class) {
_instance.close();
_instance = null;
}
}
}
/**
* Return the names of the JmDNS instances.
*
* @return list of name of the JmDNS
* @see javax.jmdns.JmDNS#getName()
*/
public abstract String[] getNames();
/**
* Return the list HostName associated with this JmmDNS instance.
*
* @return list of host names
* @see javax.jmdns.JmDNS#getHostName()
*/
public abstract String[] getHostNames();
/**
* Return the list of addresses of the interface to which this instance of JmmDNS is bound.
*
* @return list of Internet Address
* @exception IOException
* @see javax.jmdns.JmDNS#getInetAddress()
*/
public abstract InetAddress[] getInetAddresses() throws IOException;
/**
* Return the list of addresses of the interface to which this instance of JmmDNS is bound.
*
* @return list of Internet Address
* @exception IOException
* @see javax.jmdns.JmDNS#getInterface()
* @deprecated do not use this implementation yields unpredictable results use {@link #getInetAddresses()}
*/
@Deprecated
public abstract InetAddress[] getInterfaces() throws IOException;
/**
* Return a list of all the registered JmDNS instances
*
* @return list of JmDNS instances
*/
public abstract JmDNS[] getDNS();
/**
* Get service information. If the information is not cached, the method will block until updated information is received on all DNS.
* <p/>
* Usage note: Do not call this method from the AWT event dispatcher thread. You will make the user interface unresponsive.
*
* @param type
* fully qualified service type, such as <code>_http._tcp.local.</code> .
* @param name
* unqualified service name, such as <code>foobar</code> .
* @return list of service info. If no service info is found the list is empty.
* @see javax.jmdns.JmDNS#getServiceInfo(java.lang.String, java.lang.String)
*/
public abstract ServiceInfo[] getServiceInfos(String type, String name);
/**
* Get service information. If the information is not cached, the method will block until updated information is received on all DNS.
* <p/>
* Usage note: If you call this method from the AWT event dispatcher thread, use a small timeout, or you will make the user interface unresponsive.
*
* @param type
* full qualified service type, such as <code>_http._tcp.local.</code> .
* @param name
* unqualified service name, such as <code>foobar</code> .
* @param timeout
* timeout in milliseconds. Typical timeout should be 5s.
* @return list of service info. If no service info is found the list is empty.
* @see javax.jmdns.JmDNS#getServiceInfo(java.lang.String, java.lang.String, long)
*/
public abstract ServiceInfo[] getServiceInfos(String type, String name, long timeout);
/**
* Get service information. If the information is not cached, the method will block until updated information is received on all DNS.
* <p/>
* Usage note: If you call this method from the AWT event dispatcher thread, use a small timeout, or you will make the user interface unresponsive.
*
* @param type
* full qualified service type, such as <code>_http._tcp.local.</code> .
* @param name
* unqualified service name, such as <code>foobar</code> .
* @param persistent
* if <code>true</code> ServiceListener.resolveService will be called whenever new new information is received.
* @return list of service info. If no service info is found the list is empty.
* @see javax.jmdns.JmDNS#getServiceInfo(java.lang.String, java.lang.String, boolean)
*/
public abstract ServiceInfo[] getServiceInfos(String type, String name, boolean persistent);
/**
* Get service information. If the information is not cached, the method will block until updated information is received on all DNS.
* <p/>
* Usage note: If you call this method from the AWT event dispatcher thread, use a small timeout, or you will make the user interface unresponsive.
*
* @param type
* full qualified service type, such as <code>_http._tcp.local.</code> .
* @param name
* unqualified service name, such as <code>foobar</code> .
* @param timeout
* timeout in milliseconds. Typical timeout should be 5s.
* @param persistent
* if <code>true</code> ServiceListener.resolveService will be called whenever new new information is received.
* @return list of service info. If no service info is found the list is empty.
* @see javax.jmdns.JmDNS#getServiceInfo(java.lang.String, java.lang.String, boolean, long)
*/
public abstract ServiceInfo[] getServiceInfos(String type, String name, boolean persistent, long timeout);
/**
* Request service information. The information about the service is requested and the ServiceListener.resolveService method is called as soon as it is available.
*
* @param type
* full qualified service type, such as <code>_http._tcp.local.</code> .
* @param name
* unqualified service name, such as <code>foobar</code> .
* @see javax.jmdns.JmDNS#requestServiceInfo(java.lang.String, java.lang.String)
*/
public abstract void requestServiceInfo(String type, String name);
/**
* Request service information. The information about the service is requested and the ServiceListener.resolveService method is called as soon as it is available.
*
* @param type
* full qualified service type, such as <code>_http._tcp.local.</code> .
* @param name
* unqualified service name, such as <code>foobar</code> .
* @param persistent
* if <code>true</code> ServiceListener.resolveService will be called whenever new new information is received.
* @see javax.jmdns.JmDNS#requestServiceInfo(java.lang.String, java.lang.String, boolean)
*/
public abstract void requestServiceInfo(String type, String name, boolean persistent);
/**
* Request service information. The information about the service is requested and the ServiceListener.resolveService method is called as soon as it is available.
*
* @param type
* full qualified service type, such as <code>_http._tcp.local.</code> .
* @param name
* unqualified service name, such as <code>foobar</code> .
* @param timeout
* timeout in milliseconds
* @see javax.jmdns.JmDNS#requestServiceInfo(java.lang.String, java.lang.String, long)
*/
public abstract void requestServiceInfo(String type, String name, long timeout);
/**
* Request service information. The information about the service is requested and the ServiceListener.resolveService method is called as soon as it is available.
*
* @param type
* full qualified service type, such as <code>_http._tcp.local.</code> .
* @param name
* unqualified service name, such as <code>foobar</code> .
* @param persistent
* if <code>true</code> ServiceListener.resolveService will be called whenever new new information is received.
* @param timeout
* timeout in milliseconds
* @see javax.jmdns.JmDNS#requestServiceInfo(java.lang.String, java.lang.String, boolean, long)
*/
public abstract void requestServiceInfo(String type, String name, boolean persistent, long timeout);
/**
* Listen for service types.
*
* @param listener
* listener for service types
* @exception IOException
* @see javax.jmdns.JmDNS#addServiceTypeListener(javax.jmdns.ServiceTypeListener)
*/
public abstract void addServiceTypeListener(ServiceTypeListener listener) throws IOException;
/**
* Remove listener for service types.
*
* @param listener
* listener for service types
* @see javax.jmdns.JmDNS#removeServiceTypeListener(javax.jmdns.ServiceTypeListener)
*/
public abstract void removeServiceTypeListener(ServiceTypeListener listener);
/**
* Listen for services of a given type. The type has to be a fully qualified type name such as <code>_http._tcp.local.</code>.
*
* @param type
* full qualified service type, such as <code>_http._tcp.local.</code>.
* @param listener
* listener for service updates
* @see javax.jmdns.JmDNS#addServiceListener(java.lang.String, javax.jmdns.ServiceListener)
*/
public abstract void addServiceListener(String type, ServiceListener listener);
/**
* Remove listener for services of a given type.
*
* @param type
* full qualified service type, such as <code>_http._tcp.local.</code>.
* @param listener
* listener for service updates
* @see javax.jmdns.JmDNS#removeServiceListener(java.lang.String, javax.jmdns.ServiceListener)
*/
public abstract void removeServiceListener(String type, ServiceListener listener);
/**
* Register a service. The service is registered for access by other jmdns clients. The name of the service may be changed to make it unique.<br>
* <b>Note</b> the Service info is cloned for each network interface.
*
* @param info
* service info to register
* @exception IOException
* @see javax.jmdns.JmDNS#registerService(javax.jmdns.ServiceInfo)
*/
public abstract void registerService(ServiceInfo info) throws IOException;
/**
* Unregister a service. The service should have been registered.
*
* @param info
* service info to remove
* @see javax.jmdns.JmDNS#unregisterService(javax.jmdns.ServiceInfo)
*/
public abstract void unregisterService(ServiceInfo info);
/**
* Unregister all services.
*
* @see javax.jmdns.JmDNS#unregisterAllServices()
*/
public abstract void unregisterAllServices();
/**
* Register a service type. If this service type was not already known, all service listeners will be notified of the new service type. Service types are automatically registered as they are discovered.
*
* @param type
* full qualified service type, such as <code>_http._tcp.local.</code>.
* @see javax.jmdns.JmDNS#registerServiceType(java.lang.String)
*/
public abstract void registerServiceType(String type);
/**
* Returns a list of service infos of the specified type.
*
* @param type
* Service type name, such as <code>_http._tcp.local.</code>.
* @return An array of service instance.
* @see javax.jmdns.JmDNS#list(java.lang.String)
*/
public abstract ServiceInfo[] list(String type);
/**
* Returns a list of service infos of the specified type.
*
* @param type
* Service type name, such as <code>_http._tcp.local.</code>.
* @param timeout
* timeout in milliseconds. Typical timeout should be 6s.
* @return An array of service instance.
* @see javax.jmdns.JmDNS#list(java.lang.String, long)
*/
public abstract ServiceInfo[] list(String type, long timeout);
/**
* Returns a list of service infos of the specified type sorted by subtype. Any service that do not register a subtype is listed in the empty subtype section.
*
* @param type
* Service type name, such as <code>_http._tcp.local.</code>.
* @return A dictionary of service info by subtypes.
* @see javax.jmdns.JmDNS#listBySubtype(java.lang.String)
*/
public abstract Map<String, ServiceInfo[]> listBySubtype(String type);
/**
* Returns a list of service infos of the specified type sorted by subtype. Any service that do not register a subtype is listed in the empty subtype section.
*
* @param type
* Service type name, such as <code>_http._tcp.local.</code>.
* @param timeout
* timeout in milliseconds. Typical timeout should be 6s.
* @return A dictionary of service info by subtypes.
* @see javax.jmdns.JmDNS#listBySubtype(java.lang.String, long)
*/
public abstract Map<String, ServiceInfo[]> listBySubtype(String type, long timeout);
/**
* Listen to network changes.
*
* @param listener
* listener for network changes
*/
public abstract void addNetworkTopologyListener(NetworkTopologyListener listener);
/**
* Remove listener for network changes.
*
* @param listener
* listener for network changes
*/
public abstract void removeNetworkTopologyListener(NetworkTopologyListener listener);
/**
* Returns list of network change listeners
*
* @return list of network change listeners
*/
public abstract NetworkTopologyListener[] networkListeners();
}

View file

@ -1,164 +1,164 @@
package javax.jmdns;
import java.net.InetAddress;
import java.net.NetworkInterface;
import java.util.concurrent.atomic.AtomicReference;
import javax.jmdns.impl.NetworkTopologyDiscoveryImpl;
/**
* This class is used to resolve the list of Internet address to use when attaching JmDNS to the network.
* <p>
* To create you own filtering class for Internet Addresses you will need to implement the class and the factory delegate. These must be called before any other call to JmDNS.
*
* <pre>
* public static class MyNetworkTopologyDiscovery implements NetworkTopologyDiscovery {
*
* &#064;Override
* public InetAddress[] getInetAddresses() {
* // TODO Auto-generated method stub
* return null;
* }
*
* &#064;Override
* public boolean useInetAddress(NetworkInterface networkInterface, InetAddress interfaceAddress) {
* // TODO Auto-generated method stub
* return false;
* }
*
* }
*
* public static class MyClass implements NetworkTopologyDiscovery.Factory.ClassDelegate {
* public MyClass() {
* super();
* NetworkTopologyDiscovery.Factory.setClassDelegate(this);
*
* // Access JmDNS or JmmDNS
* }
*
* &#064;Override
* public NetworkTopologyDiscovery newNetworkTopologyDiscovery() {
* return new MyNetworkTopologyDiscovery();
* }
*
* }
* </pre>
*
* </p>
*
* @author Pierre Frisch
*/
public interface NetworkTopologyDiscovery {
/**
* NetworkTopologyDiscovery.Factory enable the creation of new instance of NetworkTopologyDiscovery.
*/
public static final class Factory {
private static volatile NetworkTopologyDiscovery _instance;
/**
* This interface defines a delegate to the NetworkTopologyDiscovery.Factory class to enable subclassing.
*/
public static interface ClassDelegate {
/**
* Allows the delegate the opportunity to construct and return a different NetworkTopologyDiscovery.
*
* @return Should return a new NetworkTopologyDiscovery Object.
* @see #classDelegate()
* @see #setClassDelegate(ClassDelegate anObject)
*/
public NetworkTopologyDiscovery newNetworkTopologyDiscovery();
}
private static final AtomicReference<Factory.ClassDelegate> _databaseClassDelegate = new AtomicReference<Factory.ClassDelegate>();
private Factory() {
super();
}
/**
* Assigns <code>delegate</code> as NetworkTopologyDiscovery's class delegate. The class delegate is optional.
*
* @param delegate
* The object to set as NetworkTopologyDiscovery's class delegate.
* @see #classDelegate()
* @see JmmDNS.Factory.ClassDelegate
*/
public static void setClassDelegate(Factory.ClassDelegate delegate) {
_databaseClassDelegate.set(delegate);
}
/**
* Returns NetworkTopologyDiscovery's class delegate.
*
* @return NetworkTopologyDiscovery's class delegate.
* @see #setClassDelegate(ClassDelegate anObject)
* @see JmmDNS.Factory.ClassDelegate
*/
public static Factory.ClassDelegate classDelegate() {
return _databaseClassDelegate.get();
}
/**
* Returns a new instance of NetworkTopologyDiscovery using the class delegate if it exists.
*
* @return new instance of NetworkTopologyDiscovery
*/
protected static NetworkTopologyDiscovery newNetworkTopologyDiscovery() {
NetworkTopologyDiscovery instance = null;
Factory.ClassDelegate delegate = _databaseClassDelegate.get();
if (delegate != null) {
instance = delegate.newNetworkTopologyDiscovery();
}
return (instance != null ? instance : new NetworkTopologyDiscoveryImpl());
}
/**
* Return the instance of the Multihomed Multicast DNS.
*
* @return the JmmDNS
*/
public static NetworkTopologyDiscovery getInstance() {
if (_instance == null) {
synchronized (NetworkTopologyDiscovery.Factory.class) {
if (_instance == null) {
_instance = NetworkTopologyDiscovery.Factory.newNetworkTopologyDiscovery();
}
}
}
return _instance;
}
}
/**
* Get all local Internet Addresses for the machine.
*
* @return Set of InetAddress
*/
public abstract InetAddress[] getInetAddresses();
/**
* Check if a given InetAddress should be used for mDNS
*
* @param networkInterface
* @param interfaceAddress
* @return <code>true</code> is the address is to be used, <code>false</code> otherwise.
*/
public boolean useInetAddress(NetworkInterface networkInterface, InetAddress interfaceAddress);
/**
* Locks the given InetAddress if the device requires it.
*
* @param interfaceAddress
*/
public void lockInetAddress(InetAddress interfaceAddress);
/**
* Locks the given InetAddress if the device requires it.
*
* @param interfaceAddress
*/
public void unlockInetAddress(InetAddress interfaceAddress);
package javax.jmdns;
import java.net.InetAddress;
import java.net.NetworkInterface;
import java.util.concurrent.atomic.AtomicReference;
import javax.jmdns.impl.NetworkTopologyDiscoveryImpl;
/**
* This class is used to resolve the list of Internet address to use when attaching JmDNS to the network.
* <p>
* To create you own filtering class for Internet Addresses you will need to implement the class and the factory delegate. These must be called before any other call to JmDNS.
*
* <pre>
* public static class MyNetworkTopologyDiscovery implements NetworkTopologyDiscovery {
*
* &#064;Override
* public InetAddress[] getInetAddresses() {
* // TODO Auto-generated method stub
* return null;
* }
*
* &#064;Override
* public boolean useInetAddress(NetworkInterface networkInterface, InetAddress interfaceAddress) {
* // TODO Auto-generated method stub
* return false;
* }
*
* }
*
* public static class MyClass implements NetworkTopologyDiscovery.Factory.ClassDelegate {
* public MyClass() {
* super();
* NetworkTopologyDiscovery.Factory.setClassDelegate(this);
*
* // Access JmDNS or JmmDNS
* }
*
* &#064;Override
* public NetworkTopologyDiscovery newNetworkTopologyDiscovery() {
* return new MyNetworkTopologyDiscovery();
* }
*
* }
* </pre>
*
* </p>
*
* @author Pierre Frisch
*/
public interface NetworkTopologyDiscovery {
/**
* NetworkTopologyDiscovery.Factory enable the creation of new instance of NetworkTopologyDiscovery.
*/
public static final class Factory {
private static volatile NetworkTopologyDiscovery _instance;
/**
* This interface defines a delegate to the NetworkTopologyDiscovery.Factory class to enable subclassing.
*/
public static interface ClassDelegate {
/**
* Allows the delegate the opportunity to construct and return a different NetworkTopologyDiscovery.
*
* @return Should return a new NetworkTopologyDiscovery Object.
* @see #classDelegate()
* @see #setClassDelegate(ClassDelegate anObject)
*/
public NetworkTopologyDiscovery newNetworkTopologyDiscovery();
}
private static final AtomicReference<Factory.ClassDelegate> _databaseClassDelegate = new AtomicReference<Factory.ClassDelegate>();
private Factory() {
super();
}
/**
* Assigns <code>delegate</code> as NetworkTopologyDiscovery's class delegate. The class delegate is optional.
*
* @param delegate
* The object to set as NetworkTopologyDiscovery's class delegate.
* @see #classDelegate()
* @see JmmDNS.Factory.ClassDelegate
*/
public static void setClassDelegate(Factory.ClassDelegate delegate) {
_databaseClassDelegate.set(delegate);
}
/**
* Returns NetworkTopologyDiscovery's class delegate.
*
* @return NetworkTopologyDiscovery's class delegate.
* @see #setClassDelegate(ClassDelegate anObject)
* @see JmmDNS.Factory.ClassDelegate
*/
public static Factory.ClassDelegate classDelegate() {
return _databaseClassDelegate.get();
}
/**
* Returns a new instance of NetworkTopologyDiscovery using the class delegate if it exists.
*
* @return new instance of NetworkTopologyDiscovery
*/
protected static NetworkTopologyDiscovery newNetworkTopologyDiscovery() {
NetworkTopologyDiscovery instance = null;
Factory.ClassDelegate delegate = _databaseClassDelegate.get();
if (delegate != null) {
instance = delegate.newNetworkTopologyDiscovery();
}
return (instance != null ? instance : new NetworkTopologyDiscoveryImpl());
}
/**
* Return the instance of the Multihomed Multicast DNS.
*
* @return the JmmDNS
*/
public static NetworkTopologyDiscovery getInstance() {
if (_instance == null) {
synchronized (NetworkTopologyDiscovery.Factory.class) {
if (_instance == null) {
_instance = NetworkTopologyDiscovery.Factory.newNetworkTopologyDiscovery();
}
}
}
return _instance;
}
}
/**
* Get all local Internet Addresses for the machine.
*
* @return Set of InetAddress
*/
public abstract InetAddress[] getInetAddresses();
/**
* Check if a given InetAddress should be used for mDNS
*
* @param networkInterface
* @param interfaceAddress
* @return <code>true</code> is the address is to be used, <code>false</code> otherwise.
*/
public boolean useInetAddress(NetworkInterface networkInterface, InetAddress interfaceAddress);
/**
* Locks the given InetAddress if the device requires it.
*
* @param interfaceAddress
*/
public void lockInetAddress(InetAddress interfaceAddress);
/**
* Locks the given InetAddress if the device requires it.
*
* @param interfaceAddress
*/
public void unlockInetAddress(InetAddress interfaceAddress);
}

View file

@ -1,45 +1,45 @@
/**
*
*/
package javax.jmdns;
import java.net.InetAddress;
import java.util.EventObject;
/**
* @author C&eacute;drik Lime, Pierre Frisch
*/
public abstract class NetworkTopologyEvent extends EventObject {
/**
*
*/
private static final long serialVersionUID = -8630033521752540987L;
/**
* Constructs a Service Event.
*
* @param eventSource
* The DNS on which the Event initially occurred.
* @exception IllegalArgumentException
* if source is null.
*/
protected NetworkTopologyEvent(final Object eventSource) {
super(eventSource);
}
/**
* Returns the JmDNS instance associated with the event or null if it is a generic event.
*
* @return JmDNS instance
*/
public abstract JmDNS getDNS();
/**
* The Internet address affected by this event.
*
* @return InetAddress
*/
public abstract InetAddress getInetAddress();
}
/**
*
*/
package javax.jmdns;
import java.net.InetAddress;
import java.util.EventObject;
/**
* @author C&eacute;drik Lime, Pierre Frisch
*/
public abstract class NetworkTopologyEvent extends EventObject {
/**
*
*/
private static final long serialVersionUID = -8630033521752540987L;
/**
* Constructs a Service Event.
*
* @param eventSource
* The DNS on which the Event initially occurred.
* @exception IllegalArgumentException
* if source is null.
*/
protected NetworkTopologyEvent(final Object eventSource) {
super(eventSource);
}
/**
* Returns the JmDNS instance associated with the event or null if it is a generic event.
*
* @return JmDNS instance
*/
public abstract JmDNS getDNS();
/**
* The Internet address affected by this event.
*
* @return InetAddress
*/
public abstract InetAddress getInetAddress();
}

View file

@ -1,30 +1,30 @@
/**
*
*/
package javax.jmdns;
import java.util.EventListener;
/**
* Listener for network topology updates.
*
* @author C&eacute;drik Lime, Pierre Frisch
*/
public interface NetworkTopologyListener extends EventListener {
/**
* A network address has been added.<br/>
*
* @param event
* The NetworkTopologyEvent providing the name and fully qualified type of the service.
*/
void inetAddressAdded(NetworkTopologyEvent event);
/**
* A network address has been removed.
*
* @param event
* The NetworkTopologyEvent providing the name and fully qualified type of the service.
*/
void inetAddressRemoved(NetworkTopologyEvent event);
}
/**
*
*/
package javax.jmdns;
import java.util.EventListener;
/**
* Listener for network topology updates.
*
* @author C&eacute;drik Lime, Pierre Frisch
*/
public interface NetworkTopologyListener extends EventListener {
/**
* A network address has been added.<br/>
*
* @param event
* The NetworkTopologyEvent providing the name and fully qualified type of the service.
*/
void inetAddressAdded(NetworkTopologyEvent event);
/**
* A network address has been removed.
*
* @param event
* The NetworkTopologyEvent providing the name and fully qualified type of the service.
*/
void inetAddressRemoved(NetworkTopologyEvent event);
}

View file

@ -1,74 +1,74 @@
// Copyright 2003-2005 Arthur van Hoff, Rick Blair
// Licensed under Apache License version 2.0
// Original license LGPL
package javax.jmdns;
import java.util.EventObject;
/**
*
*/
public abstract class ServiceEvent extends EventObject implements Cloneable {
/**
*
*/
private static final long serialVersionUID = -8558445644541006271L;
/**
* Constructs a Service Event.
*
* @param eventSource
* The object on which the Event initially occurred.
* @exception IllegalArgumentException
* if source is null.
*/
public ServiceEvent(final Object eventSource) {
super(eventSource);
}
/**
* Returns the JmDNS instance which originated the event.
*
* @return JmDNS instance
*/
public abstract JmDNS getDNS();
/**
* Returns the fully qualified type of the service.
*
* @return type of the service.
*/
public abstract String getType();
/**
* Returns the instance name of the service. Always returns null, if the event is sent to a service type listener.
*
* @return name of the service
*/
public abstract String getName();
/**
* Returns the service info record, or null if the service could not be resolved. Always returns null, if the event is sent to a service type listener.
*
* @return service info record
* @see javax.jmdns.ServiceEvent#getInfo()
*/
public abstract ServiceInfo getInfo();
/*
* (non-Javadoc)
* @see java.lang.Object#clone()
*/
@Override
public ServiceEvent clone() {
try {
return (ServiceEvent) super.clone();
} catch (CloneNotSupportedException exception) {
// clone is supported
return null;
}
}
// Copyright 2003-2005 Arthur van Hoff, Rick Blair
// Licensed under Apache License version 2.0
// Original license LGPL
package javax.jmdns;
import java.util.EventObject;
/**
*
*/
public abstract class ServiceEvent extends EventObject implements Cloneable {
/**
*
*/
private static final long serialVersionUID = -8558445644541006271L;
/**
* Constructs a Service Event.
*
* @param eventSource
* The object on which the Event initially occurred.
* @exception IllegalArgumentException
* if source is null.
*/
public ServiceEvent(final Object eventSource) {
super(eventSource);
}
/**
* Returns the JmDNS instance which originated the event.
*
* @return JmDNS instance
*/
public abstract JmDNS getDNS();
/**
* Returns the fully qualified type of the service.
*
* @return type of the service.
*/
public abstract String getType();
/**
* Returns the instance name of the service. Always returns null, if the event is sent to a service type listener.
*
* @return name of the service
*/
public abstract String getName();
/**
* Returns the service info record, or null if the service could not be resolved. Always returns null, if the event is sent to a service type listener.
*
* @return service info record
* @see javax.jmdns.ServiceEvent#getInfo()
*/
public abstract ServiceInfo getInfo();
/*
* (non-Javadoc)
* @see java.lang.Object#clone()
*/
@Override
public ServiceEvent clone() {
try {
return (ServiceEvent) super.clone();
} catch (CloneNotSupportedException exception) {
// clone is supported
return null;
}
}
}

View file

@ -1,293 +1,293 @@
// Copyright 2003-2005 Arthur van Hoff Rick Blair
// Licensed under Apache License version 2.0
// Original license LGPL
package javax.jmdns.impl;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import java.util.concurrent.ConcurrentHashMap;
import javax.jmdns.impl.constants.DNSRecordClass;
import javax.jmdns.impl.constants.DNSRecordType;
/**
* A table of DNS entries. This is a map table which can handle multiple entries with the same name.
* <p/>
* Storing multiple entries with the same name is implemented using a linked list. This is hidden from the user and can change in later implementation.
* <p/>
* Here's how to iterate over all entries:
*
* <pre>
* for (Iterator i=dnscache.allValues().iterator(); i.hasNext(); ) {
* DNSEntry entry = i.next();
* ...do something with entry...
* }
* </pre>
* <p/>
* And here's how to iterate over all entries having a given name:
*
* <pre>
* for (Iterator i=dnscache.getDNSEntryList(name).iterator(); i.hasNext(); ) {
* DNSEntry entry = i.next();
* ...do something with entry...
* }
* </pre>
*
* @author Arthur van Hoff, Werner Randelshofer, Rick Blair, Pierre Frisch
*/
public class DNSCache extends ConcurrentHashMap<String, List<DNSEntry>> {
// private static Logger logger = Logger.getLogger(DNSCache.class.getName());
private static final long serialVersionUID = 3024739453186759259L;
/**
*
*/
public DNSCache() {
this(1024);
}
/**
* @param map
*/
public DNSCache(DNSCache map) {
this(map != null ? map.size() : 1024);
if (map != null) {
this.putAll(map);
}
}
/**
* Create a table with a given initial size.
*
* @param initialCapacity
*/
public DNSCache(int initialCapacity) {
super(initialCapacity);
}
// ====================================================================
// Map
/**
* {@inheritDoc}
*/
@Override
protected Object clone() throws CloneNotSupportedException {
return new DNSCache(this);
}
// ====================================================================
/**
* Returns all entries in the cache
*
* @return all entries in the cache
*/
public Collection<DNSEntry> allValues() {
List<DNSEntry> allValues = new ArrayList<DNSEntry>();
for (List<? extends DNSEntry> entry : this.values()) {
if (entry != null) {
allValues.addAll(entry);
}
}
return allValues;
}
/**
* Iterate only over items with matching name. Returns an list of DNSEntry or null. To retrieve all entries, one must iterate over this linked list.
*
* @param name
* @return list of DNSEntries
*/
public Collection<? extends DNSEntry> getDNSEntryList(String name) {
Collection<? extends DNSEntry> entryList = this._getDNSEntryList(name);
if (entryList != null) {
synchronized (entryList) {
entryList = new ArrayList<DNSEntry>(entryList);
}
} else {
entryList = Collections.emptyList();
}
return entryList;
}
private Collection<? extends DNSEntry> _getDNSEntryList(String name) {
return this.get(name != null ? name.toLowerCase() : null);
}
/**
* Get a matching DNS entry from the table (using isSameEntry). Returns the entry that was found.
*
* @param dnsEntry
* @return DNSEntry
*/
public DNSEntry getDNSEntry(DNSEntry dnsEntry) {
DNSEntry result = null;
if (dnsEntry != null) {
Collection<? extends DNSEntry> entryList = this._getDNSEntryList(dnsEntry.getKey());
if (entryList != null) {
synchronized (entryList) {
for (DNSEntry testDNSEntry : entryList) {
if (testDNSEntry.isSameEntry(dnsEntry)) {
result = testDNSEntry;
break;
}
}
}
}
}
return result;
}
/**
* Get a matching DNS entry from the table.
*
* @param name
* @param type
* @param recordClass
* @return DNSEntry
*/
public DNSEntry getDNSEntry(String name, DNSRecordType type, DNSRecordClass recordClass) {
DNSEntry result = null;
Collection<? extends DNSEntry> entryList = this._getDNSEntryList(name);
if (entryList != null) {
synchronized (entryList) {
for (DNSEntry testDNSEntry : entryList) {
if (testDNSEntry.matchRecordType(type) && testDNSEntry.matchRecordClass(recordClass)) {
result = testDNSEntry;
break;
}
}
}
}
return result;
}
/**
* Get all matching DNS entries from the table.
*
* @param name
* @param type
* @param recordClass
* @return list of entries
*/
public Collection<? extends DNSEntry> getDNSEntryList(String name, DNSRecordType type, DNSRecordClass recordClass) {
Collection<? extends DNSEntry> entryList = this._getDNSEntryList(name);
if (entryList != null) {
synchronized (entryList) {
entryList = new ArrayList<DNSEntry>(entryList);
for (Iterator<? extends DNSEntry> i = entryList.iterator(); i.hasNext();) {
DNSEntry testDNSEntry = i.next();
if (!testDNSEntry.matchRecordType(type) || (!testDNSEntry.matchRecordClass(recordClass))) {
i.remove();
}
}
}
} else {
entryList = Collections.emptyList();
}
return entryList;
}
/**
* Adds an entry to the table.
*
* @param dnsEntry
* @return true if the entry was added
*/
public boolean addDNSEntry(final DNSEntry dnsEntry) {
boolean result = false;
if (dnsEntry != null) {
List<DNSEntry> entryList = this.get(dnsEntry.getKey());
if (entryList == null) {
this.putIfAbsent(dnsEntry.getKey(), new ArrayList<DNSEntry>());
entryList = this.get(dnsEntry.getKey());
}
synchronized (entryList) {
entryList.add(dnsEntry);
}
// This is probably not very informative
result = true;
}
return result;
}
/**
* Removes a specific entry from the table. Returns true if the entry was found.
*
* @param dnsEntry
* @return true if the entry was removed
*/
public boolean removeDNSEntry(DNSEntry dnsEntry) {
boolean result = false;
if (dnsEntry != null) {
List<DNSEntry> entryList = this.get(dnsEntry.getKey());
if (entryList != null) {
synchronized (entryList) {
entryList.remove(dnsEntry);
}
}
}
return result;
}
/**
* Replace an existing entry by a new one.<br/>
* <b>Note:</b> the 2 entries must have the same key.
*
* @param newDNSEntry
* @param existingDNSEntry
* @return <code>true</code> if the entry has been replace, <code>false</code> otherwise.
*/
public boolean replaceDNSEntry(DNSEntry newDNSEntry, DNSEntry existingDNSEntry) {
boolean result = false;
if ((newDNSEntry != null) && (existingDNSEntry != null) && (newDNSEntry.getKey().equals(existingDNSEntry.getKey()))) {
List<DNSEntry> entryList = this.get(newDNSEntry.getKey());
if (entryList == null) {
this.putIfAbsent(newDNSEntry.getKey(), new ArrayList<DNSEntry>());
entryList = this.get(newDNSEntry.getKey());
}
synchronized (entryList) {
entryList.remove(existingDNSEntry);
entryList.add(newDNSEntry);
}
// This is probably not very informative
result = true;
}
return result;
}
/**
* {@inheritDoc}
*/
@Override
public synchronized String toString() {
StringBuffer aLog = new StringBuffer(2000);
aLog.append("\t---- cache ----");
for (String key : this.keySet()) {
aLog.append("\n\t\t");
aLog.append("\n\t\tname '");
aLog.append(key);
aLog.append("' ");
List<? extends DNSEntry> entryList = this.get(key);
if ((entryList != null) && (!entryList.isEmpty())) {
synchronized (entryList) {
for (DNSEntry entry : entryList) {
aLog.append("\n\t\t\t");
aLog.append(entry.toString());
}
}
} else {
aLog.append(" no entries");
}
}
return aLog.toString();
}
}
// Copyright 2003-2005 Arthur van Hoff Rick Blair
// Licensed under Apache License version 2.0
// Original license LGPL
package javax.jmdns.impl;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import java.util.concurrent.ConcurrentHashMap;
import javax.jmdns.impl.constants.DNSRecordClass;
import javax.jmdns.impl.constants.DNSRecordType;
/**
* A table of DNS entries. This is a map table which can handle multiple entries with the same name.
* <p/>
* Storing multiple entries with the same name is implemented using a linked list. This is hidden from the user and can change in later implementation.
* <p/>
* Here's how to iterate over all entries:
*
* <pre>
* for (Iterator i=dnscache.allValues().iterator(); i.hasNext(); ) {
* DNSEntry entry = i.next();
* ...do something with entry...
* }
* </pre>
* <p/>
* And here's how to iterate over all entries having a given name:
*
* <pre>
* for (Iterator i=dnscache.getDNSEntryList(name).iterator(); i.hasNext(); ) {
* DNSEntry entry = i.next();
* ...do something with entry...
* }
* </pre>
*
* @author Arthur van Hoff, Werner Randelshofer, Rick Blair, Pierre Frisch
*/
public class DNSCache extends ConcurrentHashMap<String, List<DNSEntry>> {
// private static Logger logger = Logger.getLogger(DNSCache.class.getName());
private static final long serialVersionUID = 3024739453186759259L;
/**
*
*/
public DNSCache() {
this(1024);
}
/**
* @param map
*/
public DNSCache(DNSCache map) {
this(map != null ? map.size() : 1024);
if (map != null) {
this.putAll(map);
}
}
/**
* Create a table with a given initial size.
*
* @param initialCapacity
*/
public DNSCache(int initialCapacity) {
super(initialCapacity);
}
// ====================================================================
// Map
/**
* {@inheritDoc}
*/
@Override
protected Object clone() throws CloneNotSupportedException {
return new DNSCache(this);
}
// ====================================================================
/**
* Returns all entries in the cache
*
* @return all entries in the cache
*/
public Collection<DNSEntry> allValues() {
List<DNSEntry> allValues = new ArrayList<DNSEntry>();
for (List<? extends DNSEntry> entry : this.values()) {
if (entry != null) {
allValues.addAll(entry);
}
}
return allValues;
}
/**
* Iterate only over items with matching name. Returns an list of DNSEntry or null. To retrieve all entries, one must iterate over this linked list.
*
* @param name
* @return list of DNSEntries
*/
public Collection<? extends DNSEntry> getDNSEntryList(String name) {
Collection<? extends DNSEntry> entryList = this._getDNSEntryList(name);
if (entryList != null) {
synchronized (entryList) {
entryList = new ArrayList<DNSEntry>(entryList);
}
} else {
entryList = Collections.emptyList();
}
return entryList;
}
private Collection<? extends DNSEntry> _getDNSEntryList(String name) {
return this.get(name != null ? name.toLowerCase() : null);
}
/**
* Get a matching DNS entry from the table (using isSameEntry). Returns the entry that was found.
*
* @param dnsEntry
* @return DNSEntry
*/
public DNSEntry getDNSEntry(DNSEntry dnsEntry) {
DNSEntry result = null;
if (dnsEntry != null) {
Collection<? extends DNSEntry> entryList = this._getDNSEntryList(dnsEntry.getKey());
if (entryList != null) {
synchronized (entryList) {
for (DNSEntry testDNSEntry : entryList) {
if (testDNSEntry.isSameEntry(dnsEntry)) {
result = testDNSEntry;
break;
}
}
}
}
}
return result;
}
/**
* Get a matching DNS entry from the table.
*
* @param name
* @param type
* @param recordClass
* @return DNSEntry
*/
public DNSEntry getDNSEntry(String name, DNSRecordType type, DNSRecordClass recordClass) {
DNSEntry result = null;
Collection<? extends DNSEntry> entryList = this._getDNSEntryList(name);
if (entryList != null) {
synchronized (entryList) {
for (DNSEntry testDNSEntry : entryList) {
if (testDNSEntry.matchRecordType(type) && testDNSEntry.matchRecordClass(recordClass)) {
result = testDNSEntry;
break;
}
}
}
}
return result;
}
/**
* Get all matching DNS entries from the table.
*
* @param name
* @param type
* @param recordClass
* @return list of entries
*/
public Collection<? extends DNSEntry> getDNSEntryList(String name, DNSRecordType type, DNSRecordClass recordClass) {
Collection<? extends DNSEntry> entryList = this._getDNSEntryList(name);
if (entryList != null) {
synchronized (entryList) {
entryList = new ArrayList<DNSEntry>(entryList);
for (Iterator<? extends DNSEntry> i = entryList.iterator(); i.hasNext();) {
DNSEntry testDNSEntry = i.next();
if (!testDNSEntry.matchRecordType(type) || (!testDNSEntry.matchRecordClass(recordClass))) {
i.remove();
}
}
}
} else {
entryList = Collections.emptyList();
}
return entryList;
}
/**
* Adds an entry to the table.
*
* @param dnsEntry
* @return true if the entry was added
*/
public boolean addDNSEntry(final DNSEntry dnsEntry) {
boolean result = false;
if (dnsEntry != null) {
List<DNSEntry> entryList = this.get(dnsEntry.getKey());
if (entryList == null) {
this.putIfAbsent(dnsEntry.getKey(), new ArrayList<DNSEntry>());
entryList = this.get(dnsEntry.getKey());
}
synchronized (entryList) {
entryList.add(dnsEntry);
}
// This is probably not very informative
result = true;
}
return result;
}
/**
* Removes a specific entry from the table. Returns true if the entry was found.
*
* @param dnsEntry
* @return true if the entry was removed
*/
public boolean removeDNSEntry(DNSEntry dnsEntry) {
boolean result = false;
if (dnsEntry != null) {
List<DNSEntry> entryList = this.get(dnsEntry.getKey());
if (entryList != null) {
synchronized (entryList) {
entryList.remove(dnsEntry);
}
}
}
return result;
}
/**
* Replace an existing entry by a new one.<br/>
* <b>Note:</b> the 2 entries must have the same key.
*
* @param newDNSEntry
* @param existingDNSEntry
* @return <code>true</code> if the entry has been replace, <code>false</code> otherwise.
*/
public boolean replaceDNSEntry(DNSEntry newDNSEntry, DNSEntry existingDNSEntry) {
boolean result = false;
if ((newDNSEntry != null) && (existingDNSEntry != null) && (newDNSEntry.getKey().equals(existingDNSEntry.getKey()))) {
List<DNSEntry> entryList = this.get(newDNSEntry.getKey());
if (entryList == null) {
this.putIfAbsent(newDNSEntry.getKey(), new ArrayList<DNSEntry>());
entryList = this.get(newDNSEntry.getKey());
}
synchronized (entryList) {
entryList.remove(existingDNSEntry);
entryList.add(newDNSEntry);
}
// This is probably not very informative
result = true;
}
return result;
}
/**
* {@inheritDoc}
*/
@Override
public synchronized String toString() {
StringBuffer aLog = new StringBuffer(2000);
aLog.append("\t---- cache ----");
for (String key : this.keySet()) {
aLog.append("\n\t\t");
aLog.append("\n\t\tname '");
aLog.append(key);
aLog.append("' ");
List<? extends DNSEntry> entryList = this.get(key);
if ((entryList != null) && (!entryList.isEmpty())) {
synchronized (entryList) {
for (DNSEntry entry : entryList) {
aLog.append("\n\t\t\t");
aLog.append(entry.toString());
}
}
} else {
aLog.append(" no entries");
}
}
return aLog.toString();
}
}

View file

@ -1,316 +1,316 @@
// Copyright 2003-2005 Arthur van Hoff, Rick Blair
// Licensed under Apache License version 2.0
// Original license LGPL
package javax.jmdns.impl;
import java.io.ByteArrayOutputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.util.Collections;
import java.util.Map;
import javax.jmdns.ServiceInfo.Fields;
import javax.jmdns.impl.constants.DNSRecordClass;
import javax.jmdns.impl.constants.DNSRecordType;
/**
* DNS entry with a name, type, and class. This is the base class for questions and records.
*
* @author Arthur van Hoff, Pierre Frisch, Rick Blair
*/
public abstract class DNSEntry {
// private static Logger logger = Logger.getLogger(DNSEntry.class.getName());
private final String _key;
private final String _name;
private final String _type;
private final DNSRecordType _recordType;
private final DNSRecordClass _dnsClass;
private final boolean _unique;
final Map<Fields, String> _qualifiedNameMap;
/**
* Create an entry.
*/
DNSEntry(String name, DNSRecordType type, DNSRecordClass recordClass, boolean unique) {
_name = name;
// _key = (name != null ? name.trim().toLowerCase() : null);
_recordType = type;
_dnsClass = recordClass;
_unique = unique;
_qualifiedNameMap = ServiceInfoImpl.decodeQualifiedNameMapForType(this.getName());
String domain = _qualifiedNameMap.get(Fields.Domain);
String protocol = _qualifiedNameMap.get(Fields.Protocol);
String application = _qualifiedNameMap.get(Fields.Application);
String instance = _qualifiedNameMap.get(Fields.Instance).toLowerCase();
_type = (application.length() > 0 ? "_" + application + "." : "") + (protocol.length() > 0 ? "_" + protocol + "." : "") + domain + ".";
_key = ((instance.length() > 0 ? instance + "." : "") + _type).toLowerCase();
}
/*
* (non-Javadoc)
* @see java.lang.Object#equals(java.lang.Object)
*/
@Override
public boolean equals(Object obj) {
boolean result = false;
if (obj instanceof DNSEntry) {
DNSEntry other = (DNSEntry) obj;
result = this.getKey().equals(other.getKey()) && this.getRecordType().equals(other.getRecordType()) && this.getRecordClass() == other.getRecordClass();
}
return result;
}
/**
* Check if two entries have exactly the same name, type, and class.
*
* @param entry
* @return <code>true</code> if the two entries have are for the same record, <code>false</code> otherwise
*/
public boolean isSameEntry(DNSEntry entry) {
return this.getKey().equals(entry.getKey()) && this.matchRecordType(entry.getRecordType()) && this.matchRecordClass(entry.getRecordClass());
}
/**
* Check if two entries have the same subtype.
*
* @param other
* @return <code>true</code> if the two entries have are for the same subtype, <code>false</code> otherwise
*/
public boolean sameSubtype(DNSEntry other) {
return this.getSubtype().equals(other.getSubtype());
}
/**
* Check if the requested record class match the current record class
*
* @param recordClass
* @return <code>true</code> if the two entries have compatible class, <code>false</code> otherwise
*/
public boolean matchRecordClass(DNSRecordClass recordClass) {
return (DNSRecordClass.CLASS_ANY == recordClass) || (DNSRecordClass.CLASS_ANY == this.getRecordClass()) || this.getRecordClass().equals(recordClass);
}
/**
* Check if the requested record tyep match the current record type
*
* @param recordType
* @return <code>true</code> if the two entries have compatible type, <code>false</code> otherwise
*/
public boolean matchRecordType(DNSRecordType recordType) {
return this.getRecordType().equals(recordType);
}
/**
* Returns the subtype of this entry
*
* @return subtype of this entry
*/
public String getSubtype() {
String subtype = this.getQualifiedNameMap().get(Fields.Subtype);
return (subtype != null ? subtype : "");
}
/**
* Returns the name of this entry
*
* @return name of this entry
*/
public String getName() {
return (_name != null ? _name : "");
}
/**
* @return the type
*/
public String getType() {
return (_type != null ? _type : "");
}
/**
* Returns the key for this entry. The key is the lower case name.
*
* @return key for this entry
*/
public String getKey() {
return (_key != null ? _key : "");
}
/**
* @return record type
*/
public DNSRecordType getRecordType() {
return (_recordType != null ? _recordType : DNSRecordType.TYPE_IGNORE);
}
/**
* @return record class
*/
public DNSRecordClass getRecordClass() {
return (_dnsClass != null ? _dnsClass : DNSRecordClass.CLASS_UNKNOWN);
}
/**
* @return true if unique
*/
public boolean isUnique() {
return _unique;
}
public Map<Fields, String> getQualifiedNameMap() {
return Collections.unmodifiableMap(_qualifiedNameMap);
}
public boolean isServicesDiscoveryMetaQuery() {
return _qualifiedNameMap.get(Fields.Application).equals("dns-sd") && _qualifiedNameMap.get(Fields.Instance).equals("_services");
}
public boolean isDomainDiscoveryQuery() {
// b._dns-sd._udp.<domain>.
// db._dns-sd._udp.<domain>.
// r._dns-sd._udp.<domain>.
// dr._dns-sd._udp.<domain>.
// lb._dns-sd._udp.<domain>.
if (_qualifiedNameMap.get(Fields.Application).equals("dns-sd")) {
String name = _qualifiedNameMap.get(Fields.Instance);
return "b".equals(name) || "db".equals(name) || "r".equals(name) || "dr".equals(name) || "lb".equals(name);
}
return false;
}
public boolean isReverseLookup() {
return this.isV4ReverseLookup() || this.isV6ReverseLookup();
}
public boolean isV4ReverseLookup() {
return _qualifiedNameMap.get(Fields.Domain).endsWith("in-addr.arpa");
}
public boolean isV6ReverseLookup() {
return _qualifiedNameMap.get(Fields.Domain).endsWith("ip6.arpa");
}
/**
* Check if the record is stale, i.e. it has outlived more than half of its TTL.
*
* @param now
* update date
* @return <code>true</code> is the record is stale, <code>false</code> otherwise.
*/
public abstract boolean isStale(long now);
/**
* Check if the record is expired.
*
* @param now
* update date
* @return <code>true</code> is the record is expired, <code>false</code> otherwise.
*/
public abstract boolean isExpired(long now);
/**
* Check that 2 entries are of the same class.
*
* @param entry
* @return <code>true</code> is the two class are the same, <code>false</code> otherwise.
*/
public boolean isSameRecordClass(DNSEntry entry) {
return (entry != null) && (entry.getRecordClass() == this.getRecordClass());
}
/**
* Check that 2 entries are of the same type.
*
* @param entry
* @return <code>true</code> is the two type are the same, <code>false</code> otherwise.
*/
public boolean isSameType(DNSEntry entry) {
return (entry != null) && (entry.getRecordType() == this.getRecordType());
}
/**
* @param dout
* @exception IOException
*/
protected void toByteArray(DataOutputStream dout) throws IOException {
dout.write(this.getName().getBytes("UTF8"));
dout.writeShort(this.getRecordType().indexValue());
dout.writeShort(this.getRecordClass().indexValue());
}
/**
* Creates a byte array representation of this record. This is needed for tie-break tests according to draft-cheshire-dnsext-multicastdns-04.txt chapter 9.2.
*
* @return byte array representation
*/
protected byte[] toByteArray() {
try {
ByteArrayOutputStream bout = new ByteArrayOutputStream();
DataOutputStream dout = new DataOutputStream(bout);
this.toByteArray(dout);
dout.close();
return bout.toByteArray();
} catch (IOException e) {
throw new InternalError();
}
}
/**
* Does a lexicographic comparison of the byte array representation of this record and that record. This is needed for tie-break tests according to draft-cheshire-dnsext-multicastdns-04.txt chapter 9.2.
*
* @param that
* @return a negative integer, zero, or a positive integer as this object is less than, equal to, or greater than the specified object.
*/
public int compareTo(DNSEntry that) {
byte[] thisBytes = this.toByteArray();
byte[] thatBytes = that.toByteArray();
for (int i = 0, n = Math.min(thisBytes.length, thatBytes.length); i < n; i++) {
if (thisBytes[i] > thatBytes[i]) {
return 1;
} else if (thisBytes[i] < thatBytes[i]) {
return -1;
}
}
return thisBytes.length - thatBytes.length;
}
/**
* Overriden, to return a value which is consistent with the value returned by equals(Object).
*/
@Override
public int hashCode() {
return this.getKey().hashCode() + this.getRecordType().indexValue() + this.getRecordClass().indexValue();
}
/*
* (non-Javadoc)
* @see java.lang.Object#toString()
*/
@Override
public String toString() {
StringBuilder aLog = new StringBuilder(200);
aLog.append("[" + this.getClass().getSimpleName() + "@" + System.identityHashCode(this));
aLog.append(" type: " + this.getRecordType());
aLog.append(", class: " + this.getRecordClass());
aLog.append((_unique ? "-unique," : ","));
aLog.append(" name: " + _name);
this.toString(aLog);
aLog.append("]");
return aLog.toString();
}
/**
* @param aLog
*/
protected void toString(StringBuilder aLog) {
// Stub
}
}
// Copyright 2003-2005 Arthur van Hoff, Rick Blair
// Licensed under Apache License version 2.0
// Original license LGPL
package javax.jmdns.impl;
import java.io.ByteArrayOutputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.util.Collections;
import java.util.Map;
import javax.jmdns.ServiceInfo.Fields;
import javax.jmdns.impl.constants.DNSRecordClass;
import javax.jmdns.impl.constants.DNSRecordType;
/**
* DNS entry with a name, type, and class. This is the base class for questions and records.
*
* @author Arthur van Hoff, Pierre Frisch, Rick Blair
*/
public abstract class DNSEntry {
// private static Logger logger = Logger.getLogger(DNSEntry.class.getName());
private final String _key;
private final String _name;
private final String _type;
private final DNSRecordType _recordType;
private final DNSRecordClass _dnsClass;
private final boolean _unique;
final Map<Fields, String> _qualifiedNameMap;
/**
* Create an entry.
*/
DNSEntry(String name, DNSRecordType type, DNSRecordClass recordClass, boolean unique) {
_name = name;
// _key = (name != null ? name.trim().toLowerCase() : null);
_recordType = type;
_dnsClass = recordClass;
_unique = unique;
_qualifiedNameMap = ServiceInfoImpl.decodeQualifiedNameMapForType(this.getName());
String domain = _qualifiedNameMap.get(Fields.Domain);
String protocol = _qualifiedNameMap.get(Fields.Protocol);
String application = _qualifiedNameMap.get(Fields.Application);
String instance = _qualifiedNameMap.get(Fields.Instance).toLowerCase();
_type = (application.length() > 0 ? "_" + application + "." : "") + (protocol.length() > 0 ? "_" + protocol + "." : "") + domain + ".";
_key = ((instance.length() > 0 ? instance + "." : "") + _type).toLowerCase();
}
/*
* (non-Javadoc)
* @see java.lang.Object#equals(java.lang.Object)
*/
@Override
public boolean equals(Object obj) {
boolean result = false;
if (obj instanceof DNSEntry) {
DNSEntry other = (DNSEntry) obj;
result = this.getKey().equals(other.getKey()) && this.getRecordType().equals(other.getRecordType()) && this.getRecordClass() == other.getRecordClass();
}
return result;
}
/**
* Check if two entries have exactly the same name, type, and class.
*
* @param entry
* @return <code>true</code> if the two entries have are for the same record, <code>false</code> otherwise
*/
public boolean isSameEntry(DNSEntry entry) {
return this.getKey().equals(entry.getKey()) && this.matchRecordType(entry.getRecordType()) && this.matchRecordClass(entry.getRecordClass());
}
/**
* Check if two entries have the same subtype.
*
* @param other
* @return <code>true</code> if the two entries have are for the same subtype, <code>false</code> otherwise
*/
public boolean sameSubtype(DNSEntry other) {
return this.getSubtype().equals(other.getSubtype());
}
/**
* Check if the requested record class match the current record class
*
* @param recordClass
* @return <code>true</code> if the two entries have compatible class, <code>false</code> otherwise
*/
public boolean matchRecordClass(DNSRecordClass recordClass) {
return (DNSRecordClass.CLASS_ANY == recordClass) || (DNSRecordClass.CLASS_ANY == this.getRecordClass()) || this.getRecordClass().equals(recordClass);
}
/**
* Check if the requested record tyep match the current record type
*
* @param recordType
* @return <code>true</code> if the two entries have compatible type, <code>false</code> otherwise
*/
public boolean matchRecordType(DNSRecordType recordType) {
return this.getRecordType().equals(recordType);
}
/**
* Returns the subtype of this entry
*
* @return subtype of this entry
*/
public String getSubtype() {
String subtype = this.getQualifiedNameMap().get(Fields.Subtype);
return (subtype != null ? subtype : "");
}
/**
* Returns the name of this entry
*
* @return name of this entry
*/
public String getName() {
return (_name != null ? _name : "");
}
/**
* @return the type
*/
public String getType() {
return (_type != null ? _type : "");
}
/**
* Returns the key for this entry. The key is the lower case name.
*
* @return key for this entry
*/
public String getKey() {
return (_key != null ? _key : "");
}
/**
* @return record type
*/
public DNSRecordType getRecordType() {
return (_recordType != null ? _recordType : DNSRecordType.TYPE_IGNORE);
}
/**
* @return record class
*/
public DNSRecordClass getRecordClass() {
return (_dnsClass != null ? _dnsClass : DNSRecordClass.CLASS_UNKNOWN);
}
/**
* @return true if unique
*/
public boolean isUnique() {
return _unique;
}
public Map<Fields, String> getQualifiedNameMap() {
return Collections.unmodifiableMap(_qualifiedNameMap);
}
public boolean isServicesDiscoveryMetaQuery() {
return _qualifiedNameMap.get(Fields.Application).equals("dns-sd") && _qualifiedNameMap.get(Fields.Instance).equals("_services");
}
public boolean isDomainDiscoveryQuery() {
// b._dns-sd._udp.<domain>.
// db._dns-sd._udp.<domain>.
// r._dns-sd._udp.<domain>.
// dr._dns-sd._udp.<domain>.
// lb._dns-sd._udp.<domain>.
if (_qualifiedNameMap.get(Fields.Application).equals("dns-sd")) {
String name = _qualifiedNameMap.get(Fields.Instance);
return "b".equals(name) || "db".equals(name) || "r".equals(name) || "dr".equals(name) || "lb".equals(name);
}
return false;
}
public boolean isReverseLookup() {
return this.isV4ReverseLookup() || this.isV6ReverseLookup();
}
public boolean isV4ReverseLookup() {
return _qualifiedNameMap.get(Fields.Domain).endsWith("in-addr.arpa");
}
public boolean isV6ReverseLookup() {
return _qualifiedNameMap.get(Fields.Domain).endsWith("ip6.arpa");
}
/**
* Check if the record is stale, i.e. it has outlived more than half of its TTL.
*
* @param now
* update date
* @return <code>true</code> is the record is stale, <code>false</code> otherwise.
*/
public abstract boolean isStale(long now);
/**
* Check if the record is expired.
*
* @param now
* update date
* @return <code>true</code> is the record is expired, <code>false</code> otherwise.
*/
public abstract boolean isExpired(long now);
/**
* Check that 2 entries are of the same class.
*
* @param entry
* @return <code>true</code> is the two class are the same, <code>false</code> otherwise.
*/
public boolean isSameRecordClass(DNSEntry entry) {
return (entry != null) && (entry.getRecordClass() == this.getRecordClass());
}
/**
* Check that 2 entries are of the same type.
*
* @param entry
* @return <code>true</code> is the two type are the same, <code>false</code> otherwise.
*/
public boolean isSameType(DNSEntry entry) {
return (entry != null) && (entry.getRecordType() == this.getRecordType());
}
/**
* @param dout
* @exception IOException
*/
protected void toByteArray(DataOutputStream dout) throws IOException {
dout.write(this.getName().getBytes("UTF8"));
dout.writeShort(this.getRecordType().indexValue());
dout.writeShort(this.getRecordClass().indexValue());
}
/**
* Creates a byte array representation of this record. This is needed for tie-break tests according to draft-cheshire-dnsext-multicastdns-04.txt chapter 9.2.
*
* @return byte array representation
*/
protected byte[] toByteArray() {
try {
ByteArrayOutputStream bout = new ByteArrayOutputStream();
DataOutputStream dout = new DataOutputStream(bout);
this.toByteArray(dout);
dout.close();
return bout.toByteArray();
} catch (IOException e) {
throw new InternalError();
}
}
/**
* Does a lexicographic comparison of the byte array representation of this record and that record. This is needed for tie-break tests according to draft-cheshire-dnsext-multicastdns-04.txt chapter 9.2.
*
* @param that
* @return a negative integer, zero, or a positive integer as this object is less than, equal to, or greater than the specified object.
*/
public int compareTo(DNSEntry that) {
byte[] thisBytes = this.toByteArray();
byte[] thatBytes = that.toByteArray();
for (int i = 0, n = Math.min(thisBytes.length, thatBytes.length); i < n; i++) {
if (thisBytes[i] > thatBytes[i]) {
return 1;
} else if (thisBytes[i] < thatBytes[i]) {
return -1;
}
}
return thisBytes.length - thatBytes.length;
}
/**
* Overriden, to return a value which is consistent with the value returned by equals(Object).
*/
@Override
public int hashCode() {
return this.getKey().hashCode() + this.getRecordType().indexValue() + this.getRecordClass().indexValue();
}
/*
* (non-Javadoc)
* @see java.lang.Object#toString()
*/
@Override
public String toString() {
StringBuilder aLog = new StringBuilder(200);
aLog.append("[" + this.getClass().getSimpleName() + "@" + System.identityHashCode(this));
aLog.append(" type: " + this.getRecordType());
aLog.append(", class: " + this.getRecordClass());
aLog.append((_unique ? "-unique," : ","));
aLog.append(" name: " + _name);
this.toString(aLog);
aLog.append("]");
return aLog.toString();
}
/**
* @param aLog
*/
protected void toString(StringBuilder aLog) {
// Stub
}
}

View file

@ -1,28 +1,28 @@
// Copyright 2003-2005 Arthur van Hoff, Rick Blair
// Licensed under Apache License version 2.0
// Original license LGPL
package javax.jmdns.impl;
// REMIND: Listener should follow Java idiom for listener or have a different
// name.
/**
* DNSListener. Listener for record updates.
*
* @author Werner Randelshofer, Rick Blair
* @version 1.0 May 22, 2004 Created.
*/
interface DNSListener {
/**
* Update a DNS record.
*
* @param dnsCache
* record cache
* @param now
* update date
* @param record
* DNS record
*/
void updateRecord(DNSCache dnsCache, long now, DNSEntry record);
}
// Copyright 2003-2005 Arthur van Hoff, Rick Blair
// Licensed under Apache License version 2.0
// Original license LGPL
package javax.jmdns.impl;
// REMIND: Listener should follow Java idiom for listener or have a different
// name.
/**
* DNSListener. Listener for record updates.
*
* @author Werner Randelshofer, Rick Blair
* @version 1.0 May 22, 2004 Created.
*/
interface DNSListener {
/**
* Update a DNS record.
*
* @param dnsCache
* record cache
* @param now
* update date
* @param record
* DNS record
*/
void updateRecord(DNSCache dnsCache, long now, DNSEntry record);
}

View file

@ -1,335 +1,335 @@
/**
*
*/
package javax.jmdns.impl;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.LinkedList;
import java.util.List;
import javax.jmdns.impl.constants.DNSConstants;
/**
* DNSMessage define a DNS message either incoming or outgoing.
*
* @author Werner Randelshofer, Rick Blair, Pierre Frisch
*/
public abstract class DNSMessage {
/**
*
*/
public static final boolean MULTICAST = true;
/**
*
*/
public static final boolean UNICAST = false;
// protected DatagramPacket _packet;
// protected int _off;
// protected int _len;
// protected byte[] _data;
private int _id;
boolean _multicast;
private int _flags;
protected final List<DNSQuestion> _questions;
protected final List<DNSRecord> _answers;
protected final List<DNSRecord> _authoritativeAnswers;
protected final List<DNSRecord> _additionals;
/**
* @param flags
* @param id
* @param multicast
*/
protected DNSMessage(int flags, int id, boolean multicast) {
super();
_flags = flags;
_id = id;
_multicast = multicast;
_questions = Collections.synchronizedList(new LinkedList<DNSQuestion>());
_answers = Collections.synchronizedList(new LinkedList<DNSRecord>());
_authoritativeAnswers = Collections.synchronizedList(new LinkedList<DNSRecord>());
_additionals = Collections.synchronizedList(new LinkedList<DNSRecord>());
}
// public DatagramPacket getPacket() {
// return _packet;
// }
//
// public int getOffset() {
// return _off;
// }
//
// public int getLength() {
// return _len;
// }
//
// public byte[] getData() {
// if ( _data == null ) _data = new byte[DNSConstants.MAX_MSG_TYPICAL];
// return _data;
// }
/**
* @return message id
*/
public int getId() {
return (_multicast ? 0 : _id);
}
/**
* @param id
* the id to set
*/
public void setId(int id) {
this._id = id;
}
/**
* @return message flags
*/
public int getFlags() {
return _flags;
}
/**
* @param flags
* the flags to set
*/
public void setFlags(int flags) {
this._flags = flags;
}
/**
* @return true if multicast
*/
public boolean isMulticast() {
return _multicast;
}
/**
* @return list of questions
*/
public Collection<? extends DNSQuestion> getQuestions() {
return _questions;
}
/**
* @return number of questions in the message
*/
public int getNumberOfQuestions() {
return this.getQuestions().size();
}
public Collection<? extends DNSRecord> getAllAnswers() {
List<DNSRecord> aList = new ArrayList<DNSRecord>(_answers.size() + _authoritativeAnswers.size() + _additionals.size());
aList.addAll(_answers);
aList.addAll(_authoritativeAnswers);
aList.addAll(_additionals);
return aList;
}
/**
* @return list of answers
*/
public Collection<? extends DNSRecord> getAnswers() {
return _answers;
}
/**
* @return number of answers in the message
*/
public int getNumberOfAnswers() {
return this.getAnswers().size();
}
/**
* @return list of authorities
*/
public Collection<? extends DNSRecord> getAuthorities() {
return _authoritativeAnswers;
}
/**
* @return number of authorities in the message
*/
public int getNumberOfAuthorities() {
return this.getAuthorities().size();
}
/**
* @return list of additional answers
*/
public Collection<? extends DNSRecord> getAdditionals() {
return _additionals;
}
/**
* @return number of additional in the message
*/
public int getNumberOfAdditionals() {
return this.getAdditionals().size();
}
/**
* Check is the response code is valid<br/>
* The only valid value is zero all other values signify an error and the message must be ignored.
*
* @return true if the message has a valid response code.
*/
public boolean isValidResponseCode() {
return (_flags & DNSConstants.FLAGS_RCODE) == 0;
}
/**
* Returns the operation code value. Currently only standard query 0 is valid.
*
* @return The operation code value.
*/
public int getOperationCode() {
return (_flags & DNSConstants.FLAGS_OPCODE) >> 11;
}
/**
* Check if the message is truncated.
*
* @return true if the message was truncated
*/
public boolean isTruncated() {
return (_flags & DNSConstants.FLAGS_TC) != 0;
}
/**
* Check if the message is an authoritative answer.
*
* @return true if the message is an authoritative answer
*/
public boolean isAuthoritativeAnswer() {
return (_flags & DNSConstants.FLAGS_AA) != 0;
}
/**
* Check if the message is a query.
*
* @return true is the message is a query
*/
public boolean isQuery() {
return (_flags & DNSConstants.FLAGS_QR_MASK) == DNSConstants.FLAGS_QR_QUERY;
}
/**
* Check if the message is a response.
*
* @return true is the message is a response
*/
public boolean isResponse() {
return (_flags & DNSConstants.FLAGS_QR_MASK) == DNSConstants.FLAGS_QR_RESPONSE;
}
/**
* Check if the message is empty
*
* @return true is the message is empty
*/
public boolean isEmpty() {
return (this.getNumberOfQuestions() + this.getNumberOfAnswers() + this.getNumberOfAuthorities() + this.getNumberOfAdditionals()) == 0;
}
/**
* Debugging.
*/
String print() {
StringBuffer buf = new StringBuffer(200);
buf.append(this.toString());
buf.append("\n");
for (DNSQuestion question : _questions) {
buf.append("\tquestion: ");
buf.append(question);
buf.append("\n");
}
for (DNSRecord answer : _answers) {
buf.append("\tanswer: ");
buf.append(answer);
buf.append("\n");
}
for (DNSRecord answer : _authoritativeAnswers) {
buf.append("\tauthoritative: ");
buf.append(answer);
buf.append("\n");
}
for (DNSRecord answer : _additionals) {
buf.append("\tadditional: ");
buf.append(answer);
buf.append("\n");
}
return buf.toString();
}
/**
* Debugging.
*
* @param data
* @return data dump
*/
protected String print(byte[] data) {
StringBuilder buf = new StringBuilder(4000);
for (int off = 0, len = data.length; off < len; off += 32) {
int n = Math.min(32, len - off);
if (off < 0x10) {
buf.append(' ');
}
if (off < 0x100) {
buf.append(' ');
}
if (off < 0x1000) {
buf.append(' ');
}
buf.append(Integer.toHexString(off));
buf.append(':');
int index = 0;
for (index = 0; index < n; index++) {
if ((index % 8) == 0) {
buf.append(' ');
}
buf.append(Integer.toHexString((data[off + index] & 0xF0) >> 4));
buf.append(Integer.toHexString((data[off + index] & 0x0F) >> 0));
}
// for incomplete lines
if (index < 32) {
for (int i = index; i < 32; i++) {
if ((i % 8) == 0) {
buf.append(' ');
}
buf.append(" ");
}
}
buf.append(" ");
for (index = 0; index < n; index++) {
if ((index % 8) == 0) {
buf.append(' ');
}
int ch = data[off + index] & 0xFF;
buf.append(((ch > ' ') && (ch < 127)) ? (char) ch : '.');
}
buf.append("\n");
// limit message size
if (off + 32 >= 2048) {
buf.append("....\n");
break;
}
}
return buf.toString();
}
}
/**
*
*/
package javax.jmdns.impl;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.LinkedList;
import java.util.List;
import javax.jmdns.impl.constants.DNSConstants;
/**
* DNSMessage define a DNS message either incoming or outgoing.
*
* @author Werner Randelshofer, Rick Blair, Pierre Frisch
*/
public abstract class DNSMessage {
/**
*
*/
public static final boolean MULTICAST = true;
/**
*
*/
public static final boolean UNICAST = false;
// protected DatagramPacket _packet;
// protected int _off;
// protected int _len;
// protected byte[] _data;
private int _id;
boolean _multicast;
private int _flags;
protected final List<DNSQuestion> _questions;
protected final List<DNSRecord> _answers;
protected final List<DNSRecord> _authoritativeAnswers;
protected final List<DNSRecord> _additionals;
/**
* @param flags
* @param id
* @param multicast
*/
protected DNSMessage(int flags, int id, boolean multicast) {
super();
_flags = flags;
_id = id;
_multicast = multicast;
_questions = Collections.synchronizedList(new LinkedList<DNSQuestion>());
_answers = Collections.synchronizedList(new LinkedList<DNSRecord>());
_authoritativeAnswers = Collections.synchronizedList(new LinkedList<DNSRecord>());
_additionals = Collections.synchronizedList(new LinkedList<DNSRecord>());
}
// public DatagramPacket getPacket() {
// return _packet;
// }
//
// public int getOffset() {
// return _off;
// }
//
// public int getLength() {
// return _len;
// }
//
// public byte[] getData() {
// if ( _data == null ) _data = new byte[DNSConstants.MAX_MSG_TYPICAL];
// return _data;
// }
/**
* @return message id
*/
public int getId() {
return (_multicast ? 0 : _id);
}
/**
* @param id
* the id to set
*/
public void setId(int id) {
this._id = id;
}
/**
* @return message flags
*/
public int getFlags() {
return _flags;
}
/**
* @param flags
* the flags to set
*/
public void setFlags(int flags) {
this._flags = flags;
}
/**
* @return true if multicast
*/
public boolean isMulticast() {
return _multicast;
}
/**
* @return list of questions
*/
public Collection<? extends DNSQuestion> getQuestions() {
return _questions;
}
/**
* @return number of questions in the message
*/
public int getNumberOfQuestions() {
return this.getQuestions().size();
}
public Collection<? extends DNSRecord> getAllAnswers() {
List<DNSRecord> aList = new ArrayList<DNSRecord>(_answers.size() + _authoritativeAnswers.size() + _additionals.size());
aList.addAll(_answers);
aList.addAll(_authoritativeAnswers);
aList.addAll(_additionals);
return aList;
}
/**
* @return list of answers
*/
public Collection<? extends DNSRecord> getAnswers() {
return _answers;
}
/**
* @return number of answers in the message
*/
public int getNumberOfAnswers() {
return this.getAnswers().size();
}
/**
* @return list of authorities
*/
public Collection<? extends DNSRecord> getAuthorities() {
return _authoritativeAnswers;
}
/**
* @return number of authorities in the message
*/
public int getNumberOfAuthorities() {
return this.getAuthorities().size();
}
/**
* @return list of additional answers
*/
public Collection<? extends DNSRecord> getAdditionals() {
return _additionals;
}
/**
* @return number of additional in the message
*/
public int getNumberOfAdditionals() {
return this.getAdditionals().size();
}
/**
* Check is the response code is valid<br/>
* The only valid value is zero all other values signify an error and the message must be ignored.
*
* @return true if the message has a valid response code.
*/
public boolean isValidResponseCode() {
return (_flags & DNSConstants.FLAGS_RCODE) == 0;
}
/**
* Returns the operation code value. Currently only standard query 0 is valid.
*
* @return The operation code value.
*/
public int getOperationCode() {
return (_flags & DNSConstants.FLAGS_OPCODE) >> 11;
}
/**
* Check if the message is truncated.
*
* @return true if the message was truncated
*/
public boolean isTruncated() {
return (_flags & DNSConstants.FLAGS_TC) != 0;
}
/**
* Check if the message is an authoritative answer.
*
* @return true if the message is an authoritative answer
*/
public boolean isAuthoritativeAnswer() {
return (_flags & DNSConstants.FLAGS_AA) != 0;
}
/**
* Check if the message is a query.
*
* @return true is the message is a query
*/
public boolean isQuery() {
return (_flags & DNSConstants.FLAGS_QR_MASK) == DNSConstants.FLAGS_QR_QUERY;
}
/**
* Check if the message is a response.
*
* @return true is the message is a response
*/
public boolean isResponse() {
return (_flags & DNSConstants.FLAGS_QR_MASK) == DNSConstants.FLAGS_QR_RESPONSE;
}
/**
* Check if the message is empty
*
* @return true is the message is empty
*/
public boolean isEmpty() {
return (this.getNumberOfQuestions() + this.getNumberOfAnswers() + this.getNumberOfAuthorities() + this.getNumberOfAdditionals()) == 0;
}
/**
* Debugging.
*/
String print() {
StringBuffer buf = new StringBuffer(200);
buf.append(this.toString());
buf.append("\n");
for (DNSQuestion question : _questions) {
buf.append("\tquestion: ");
buf.append(question);
buf.append("\n");
}
for (DNSRecord answer : _answers) {
buf.append("\tanswer: ");
buf.append(answer);
buf.append("\n");
}
for (DNSRecord answer : _authoritativeAnswers) {
buf.append("\tauthoritative: ");
buf.append(answer);
buf.append("\n");
}
for (DNSRecord answer : _additionals) {
buf.append("\tadditional: ");
buf.append(answer);
buf.append("\n");
}
return buf.toString();
}
/**
* Debugging.
*
* @param data
* @return data dump
*/
protected String print(byte[] data) {
StringBuilder buf = new StringBuilder(4000);
for (int off = 0, len = data.length; off < len; off += 32) {
int n = Math.min(32, len - off);
if (off < 0x10) {
buf.append(' ');
}
if (off < 0x100) {
buf.append(' ');
}
if (off < 0x1000) {
buf.append(' ');
}
buf.append(Integer.toHexString(off));
buf.append(':');
int index = 0;
for (index = 0; index < n; index++) {
if ((index % 8) == 0) {
buf.append(' ');
}
buf.append(Integer.toHexString((data[off + index] & 0xF0) >> 4));
buf.append(Integer.toHexString((data[off + index] & 0x0F) >> 0));
}
// for incomplete lines
if (index < 32) {
for (int i = index; i < 32; i++) {
if ((i % 8) == 0) {
buf.append(' ');
}
buf.append(" ");
}
}
buf.append(" ");
for (index = 0; index < n; index++) {
if ((index % 8) == 0) {
buf.append(' ');
}
int ch = data[off + index] & 0xFF;
buf.append(((ch > ' ') && (ch < 127)) ? (char) ch : '.');
}
buf.append("\n");
// limit message size
if (off + 32 >= 2048) {
buf.append("....\n");
break;
}
}
return buf.toString();
}
}

View file

@ -1,446 +1,446 @@
// Copyright 2003-2005 Arthur van Hoff, Rick Blair
// Licensed under Apache License version 2.0
// Original license LGPL
package javax.jmdns.impl;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import javax.jmdns.impl.constants.DNSConstants;
import javax.jmdns.impl.constants.DNSRecordClass;
/**
* An outgoing DNS message.
*
* @author Arthur van Hoff, Rick Blair, Werner Randelshofer
*/
public final class DNSOutgoing extends DNSMessage {
public static class MessageOutputStream extends ByteArrayOutputStream {
private final DNSOutgoing _out;
private final int _offset;
/**
* Creates a new message stream, with a buffer capacity of the specified size, in bytes.
*
* @param size
* the initial size.
* @exception IllegalArgumentException
* if size is negative.
*/
MessageOutputStream(int size, DNSOutgoing out) {
this(size, out, 0);
}
MessageOutputStream(int size, DNSOutgoing out, int offset) {
super(size);
_out = out;
_offset = offset;
}
void writeByte(int value) {
this.write(value & 0xFF);
}
void writeBytes(String str, int off, int len) {
for (int i = 0; i < len; i++) {
writeByte(str.charAt(off + i));
}
}
void writeBytes(byte data[]) {
if (data != null) {
writeBytes(data, 0, data.length);
}
}
void writeBytes(byte data[], int off, int len) {
for (int i = 0; i < len; i++) {
writeByte(data[off + i]);
}
}
void writeShort(int value) {
writeByte(value >> 8);
writeByte(value);
}
void writeInt(int value) {
writeShort(value >> 16);
writeShort(value);
}
void writeUTF(String str, int off, int len) {
// compute utf length
int utflen = 0;
for (int i = 0; i < len; i++) {
int ch = str.charAt(off + i);
if ((ch >= 0x0001) && (ch <= 0x007F)) {
utflen += 1;
} else {
if (ch > 0x07FF) {
utflen += 3;
} else {
utflen += 2;
}
}
}
// write utf length
writeByte(utflen);
// write utf data
for (int i = 0; i < len; i++) {
int ch = str.charAt(off + i);
if ((ch >= 0x0001) && (ch <= 0x007F)) {
writeByte(ch);
} else {
if (ch > 0x07FF) {
writeByte(0xE0 | ((ch >> 12) & 0x0F));
writeByte(0x80 | ((ch >> 6) & 0x3F));
writeByte(0x80 | ((ch >> 0) & 0x3F));
} else {
writeByte(0xC0 | ((ch >> 6) & 0x1F));
writeByte(0x80 | ((ch >> 0) & 0x3F));
}
}
}
}
void writeName(String name) {
writeName(name, true);
}
void writeName(String name, boolean useCompression) {
String aName = name;
while (true) {
int n = aName.indexOf('.');
if (n < 0) {
n = aName.length();
}
if (n <= 0) {
writeByte(0);
return;
}
String label = aName.substring(0, n);
if (useCompression && USE_DOMAIN_NAME_COMPRESSION) {
Integer offset = _out._names.get(aName);
if (offset != null) {
int val = offset.intValue();
writeByte((val >> 8) | 0xC0);
writeByte(val & 0xFF);
return;
}
_out._names.put(aName, Integer.valueOf(this.size() + _offset));
writeUTF(label, 0, label.length());
} else {
writeUTF(label, 0, label.length());
}
aName = aName.substring(n);
if (aName.startsWith(".")) {
aName = aName.substring(1);
}
}
}
void writeQuestion(DNSQuestion question) {
writeName(question.getName());
writeShort(question.getRecordType().indexValue());
writeShort(question.getRecordClass().indexValue());
}
void writeRecord(DNSRecord rec, long now) {
writeName(rec.getName());
writeShort(rec.getRecordType().indexValue());
writeShort(rec.getRecordClass().indexValue() | ((rec.isUnique() && _out.isMulticast()) ? DNSRecordClass.CLASS_UNIQUE : 0));
writeInt((now == 0) ? rec.getTTL() : rec.getRemainingTTL(now));
// We need to take into account the 2 size bytes
MessageOutputStream record = new MessageOutputStream(512, _out, _offset + this.size() + 2);
rec.write(record);
byte[] byteArray = record.toByteArray();
writeShort(byteArray.length);
write(byteArray, 0, byteArray.length);
}
}
/**
* This can be used to turn off domain name compression. This was helpful for tracking problems interacting with other mdns implementations.
*/
public static boolean USE_DOMAIN_NAME_COMPRESSION = true;
Map<String, Integer> _names;
private int _maxUDPPayload;
private final MessageOutputStream _questionsBytes;
private final MessageOutputStream _answersBytes;
private final MessageOutputStream _authoritativeAnswersBytes;
private final MessageOutputStream _additionalsAnswersBytes;
private final static int HEADER_SIZE = 12;
/**
* Create an outgoing multicast query or response.
*
* @param flags
*/
public DNSOutgoing(int flags) {
this(flags, true, DNSConstants.MAX_MSG_TYPICAL);
}
/**
* Create an outgoing query or response.
*
* @param flags
* @param multicast
*/
public DNSOutgoing(int flags, boolean multicast) {
this(flags, multicast, DNSConstants.MAX_MSG_TYPICAL);
}
/**
* Create an outgoing query or response.
*
* @param flags
* @param multicast
* @param senderUDPPayload
* The sender's UDP payload size is the number of bytes of the largest UDP payload that can be reassembled and delivered in the sender's network stack.
*/
public DNSOutgoing(int flags, boolean multicast, int senderUDPPayload) {
super(flags, 0, multicast);
_names = new HashMap<String, Integer>();
_maxUDPPayload = (senderUDPPayload > 0 ? senderUDPPayload : DNSConstants.MAX_MSG_TYPICAL);
_questionsBytes = new MessageOutputStream(senderUDPPayload, this);
_answersBytes = new MessageOutputStream(senderUDPPayload, this);
_authoritativeAnswersBytes = new MessageOutputStream(senderUDPPayload, this);
_additionalsAnswersBytes = new MessageOutputStream(senderUDPPayload, this);
}
/**
* Return the number of byte available in the message.
*
* @return available space
*/
public int availableSpace() {
return _maxUDPPayload - HEADER_SIZE - _questionsBytes.size() - _answersBytes.size() - _authoritativeAnswersBytes.size() - _additionalsAnswersBytes.size();
}
/**
* Add a question to the message.
*
* @param rec
* @exception IOException
*/
public void addQuestion(DNSQuestion rec) throws IOException {
MessageOutputStream record = new MessageOutputStream(512, this);
record.writeQuestion(rec);
byte[] byteArray = record.toByteArray();
if (byteArray.length < this.availableSpace()) {
_questions.add(rec);
_questionsBytes.write(byteArray, 0, byteArray.length);
} else {
throw new IOException("message full");
}
}
/**
* Add an answer if it is not suppressed.
*
* @param in
* @param rec
* @exception IOException
*/
public void addAnswer(DNSIncoming in, DNSRecord rec) throws IOException {
if ((in == null) || !rec.suppressedBy(in)) {
this.addAnswer(rec, 0);
}
}
/**
* Add an answer to the message.
*
* @param rec
* @param now
* @exception IOException
*/
public void addAnswer(DNSRecord rec, long now) throws IOException {
if (rec != null) {
if ((now == 0) || !rec.isExpired(now)) {
MessageOutputStream record = new MessageOutputStream(512, this);
record.writeRecord(rec, now);
byte[] byteArray = record.toByteArray();
if (byteArray.length < this.availableSpace()) {
_answers.add(rec);
_answersBytes.write(byteArray, 0, byteArray.length);
} else {
throw new IOException("message full");
}
}
}
}
/**
* Add an authoritative answer to the message.
*
* @param rec
* @exception IOException
*/
public void addAuthorativeAnswer(DNSRecord rec) throws IOException {
MessageOutputStream record = new MessageOutputStream(512, this);
record.writeRecord(rec, 0);
byte[] byteArray = record.toByteArray();
if (byteArray.length < this.availableSpace()) {
_authoritativeAnswers.add(rec);
_authoritativeAnswersBytes.write(byteArray, 0, byteArray.length);
} else {
throw new IOException("message full");
}
}
/**
* Add an additional answer to the record. Omit if there is no room.
*
* @param in
* @param rec
* @exception IOException
*/
public void addAdditionalAnswer(DNSIncoming in, DNSRecord rec) throws IOException {
MessageOutputStream record = new MessageOutputStream(512, this);
record.writeRecord(rec, 0);
byte[] byteArray = record.toByteArray();
if (byteArray.length < this.availableSpace()) {
_additionals.add(rec);
_additionalsAnswersBytes.write(byteArray, 0, byteArray.length);
} else {
throw new IOException("message full");
}
}
/**
* Builds the final message buffer to be send and returns it.
*
* @return bytes to send.
*/
public byte[] data() {
long now = System.currentTimeMillis(); // System.currentTimeMillis()
_names.clear();
MessageOutputStream message = new MessageOutputStream(_maxUDPPayload, this);
message.writeShort(_multicast ? 0 : this.getId());
message.writeShort(this.getFlags());
message.writeShort(this.getNumberOfQuestions());
message.writeShort(this.getNumberOfAnswers());
message.writeShort(this.getNumberOfAuthorities());
message.writeShort(this.getNumberOfAdditionals());
for (DNSQuestion question : _questions) {
message.writeQuestion(question);
}
for (DNSRecord record : _answers) {
message.writeRecord(record, now);
}
for (DNSRecord record : _authoritativeAnswers) {
message.writeRecord(record, now);
}
for (DNSRecord record : _additionals) {
message.writeRecord(record, now);
}
return message.toByteArray();
}
/**
* Debugging.
*/
String print(boolean dump) {
StringBuilder buf = new StringBuilder();
buf.append(this.print());
if (dump) {
buf.append(this.print(this.data()));
}
return buf.toString();
}
@Override
public String toString() {
StringBuffer buf = new StringBuffer();
buf.append(isQuery() ? "dns[query:" : "dns[response:");
buf.append(" id=0x");
buf.append(Integer.toHexString(this.getId()));
if (this.getFlags() != 0) {
buf.append(", flags=0x");
buf.append(Integer.toHexString(this.getFlags()));
if (this.isResponse()) {
buf.append(":r");
}
if (this.isAuthoritativeAnswer()) {
buf.append(":aa");
}
if (this.isTruncated()) {
buf.append(":tc");
}
}
if (this.getNumberOfQuestions() > 0) {
buf.append(", questions=");
buf.append(this.getNumberOfQuestions());
}
if (this.getNumberOfAnswers() > 0) {
buf.append(", answers=");
buf.append(this.getNumberOfAnswers());
}
if (this.getNumberOfAuthorities() > 0) {
buf.append(", authorities=");
buf.append(this.getNumberOfAuthorities());
}
if (this.getNumberOfAdditionals() > 0) {
buf.append(", additionals=");
buf.append(this.getNumberOfAdditionals());
}
if (this.getNumberOfQuestions() > 0) {
buf.append("\nquestions:");
for (DNSQuestion question : _questions) {
buf.append("\n\t");
buf.append(question);
}
}
if (this.getNumberOfAnswers() > 0) {
buf.append("\nanswers:");
for (DNSRecord record : _answers) {
buf.append("\n\t");
buf.append(record);
}
}
if (this.getNumberOfAuthorities() > 0) {
buf.append("\nauthorities:");
for (DNSRecord record : _authoritativeAnswers) {
buf.append("\n\t");
buf.append(record);
}
}
if (this.getNumberOfAdditionals() > 0) {
buf.append("\nadditionals:");
for (DNSRecord record : _additionals) {
buf.append("\n\t");
buf.append(record);
}
}
buf.append("\nnames=");
buf.append(_names);
buf.append("]");
return buf.toString();
}
/**
* @return the maxUDPPayload
*/
public int getMaxUDPPayload() {
return this._maxUDPPayload;
}
}
// Copyright 2003-2005 Arthur van Hoff, Rick Blair
// Licensed under Apache License version 2.0
// Original license LGPL
package javax.jmdns.impl;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import javax.jmdns.impl.constants.DNSConstants;
import javax.jmdns.impl.constants.DNSRecordClass;
/**
* An outgoing DNS message.
*
* @author Arthur van Hoff, Rick Blair, Werner Randelshofer
*/
public final class DNSOutgoing extends DNSMessage {
public static class MessageOutputStream extends ByteArrayOutputStream {
private final DNSOutgoing _out;
private final int _offset;
/**
* Creates a new message stream, with a buffer capacity of the specified size, in bytes.
*
* @param size
* the initial size.
* @exception IllegalArgumentException
* if size is negative.
*/
MessageOutputStream(int size, DNSOutgoing out) {
this(size, out, 0);
}
MessageOutputStream(int size, DNSOutgoing out, int offset) {
super(size);
_out = out;
_offset = offset;
}
void writeByte(int value) {
this.write(value & 0xFF);
}
void writeBytes(String str, int off, int len) {
for (int i = 0; i < len; i++) {
writeByte(str.charAt(off + i));
}
}
void writeBytes(byte data[]) {
if (data != null) {
writeBytes(data, 0, data.length);
}
}
void writeBytes(byte data[], int off, int len) {
for (int i = 0; i < len; i++) {
writeByte(data[off + i]);
}
}
void writeShort(int value) {
writeByte(value >> 8);
writeByte(value);
}
void writeInt(int value) {
writeShort(value >> 16);
writeShort(value);
}
void writeUTF(String str, int off, int len) {
// compute utf length
int utflen = 0;
for (int i = 0; i < len; i++) {
int ch = str.charAt(off + i);
if ((ch >= 0x0001) && (ch <= 0x007F)) {
utflen += 1;
} else {
if (ch > 0x07FF) {
utflen += 3;
} else {
utflen += 2;
}
}
}
// write utf length
writeByte(utflen);
// write utf data
for (int i = 0; i < len; i++) {
int ch = str.charAt(off + i);
if ((ch >= 0x0001) && (ch <= 0x007F)) {
writeByte(ch);
} else {
if (ch > 0x07FF) {
writeByte(0xE0 | ((ch >> 12) & 0x0F));
writeByte(0x80 | ((ch >> 6) & 0x3F));
writeByte(0x80 | ((ch >> 0) & 0x3F));
} else {
writeByte(0xC0 | ((ch >> 6) & 0x1F));
writeByte(0x80 | ((ch >> 0) & 0x3F));
}
}
}
}
void writeName(String name) {
writeName(name, true);
}
void writeName(String name, boolean useCompression) {
String aName = name;
while (true) {
int n = aName.indexOf('.');
if (n < 0) {
n = aName.length();
}
if (n <= 0) {
writeByte(0);
return;
}
String label = aName.substring(0, n);
if (useCompression && USE_DOMAIN_NAME_COMPRESSION) {
Integer offset = _out._names.get(aName);
if (offset != null) {
int val = offset.intValue();
writeByte((val >> 8) | 0xC0);
writeByte(val & 0xFF);
return;
}
_out._names.put(aName, Integer.valueOf(this.size() + _offset));
writeUTF(label, 0, label.length());
} else {
writeUTF(label, 0, label.length());
}
aName = aName.substring(n);
if (aName.startsWith(".")) {
aName = aName.substring(1);
}
}
}
void writeQuestion(DNSQuestion question) {
writeName(question.getName());
writeShort(question.getRecordType().indexValue());
writeShort(question.getRecordClass().indexValue());
}
void writeRecord(DNSRecord rec, long now) {
writeName(rec.getName());
writeShort(rec.getRecordType().indexValue());
writeShort(rec.getRecordClass().indexValue() | ((rec.isUnique() && _out.isMulticast()) ? DNSRecordClass.CLASS_UNIQUE : 0));
writeInt((now == 0) ? rec.getTTL() : rec.getRemainingTTL(now));
// We need to take into account the 2 size bytes
MessageOutputStream record = new MessageOutputStream(512, _out, _offset + this.size() + 2);
rec.write(record);
byte[] byteArray = record.toByteArray();
writeShort(byteArray.length);
write(byteArray, 0, byteArray.length);
}
}
/**
* This can be used to turn off domain name compression. This was helpful for tracking problems interacting with other mdns implementations.
*/
public static boolean USE_DOMAIN_NAME_COMPRESSION = true;
Map<String, Integer> _names;
private int _maxUDPPayload;
private final MessageOutputStream _questionsBytes;
private final MessageOutputStream _answersBytes;
private final MessageOutputStream _authoritativeAnswersBytes;
private final MessageOutputStream _additionalsAnswersBytes;
private final static int HEADER_SIZE = 12;
/**
* Create an outgoing multicast query or response.
*
* @param flags
*/
public DNSOutgoing(int flags) {
this(flags, true, DNSConstants.MAX_MSG_TYPICAL);
}
/**
* Create an outgoing query or response.
*
* @param flags
* @param multicast
*/
public DNSOutgoing(int flags, boolean multicast) {
this(flags, multicast, DNSConstants.MAX_MSG_TYPICAL);
}
/**
* Create an outgoing query or response.
*
* @param flags
* @param multicast
* @param senderUDPPayload
* The sender's UDP payload size is the number of bytes of the largest UDP payload that can be reassembled and delivered in the sender's network stack.
*/
public DNSOutgoing(int flags, boolean multicast, int senderUDPPayload) {
super(flags, 0, multicast);
_names = new HashMap<String, Integer>();
_maxUDPPayload = (senderUDPPayload > 0 ? senderUDPPayload : DNSConstants.MAX_MSG_TYPICAL);
_questionsBytes = new MessageOutputStream(senderUDPPayload, this);
_answersBytes = new MessageOutputStream(senderUDPPayload, this);
_authoritativeAnswersBytes = new MessageOutputStream(senderUDPPayload, this);
_additionalsAnswersBytes = new MessageOutputStream(senderUDPPayload, this);
}
/**
* Return the number of byte available in the message.
*
* @return available space
*/
public int availableSpace() {
return _maxUDPPayload - HEADER_SIZE - _questionsBytes.size() - _answersBytes.size() - _authoritativeAnswersBytes.size() - _additionalsAnswersBytes.size();
}
/**
* Add a question to the message.
*
* @param rec
* @exception IOException
*/
public void addQuestion(DNSQuestion rec) throws IOException {
MessageOutputStream record = new MessageOutputStream(512, this);
record.writeQuestion(rec);
byte[] byteArray = record.toByteArray();
if (byteArray.length < this.availableSpace()) {
_questions.add(rec);
_questionsBytes.write(byteArray, 0, byteArray.length);
} else {
throw new IOException("message full");
}
}
/**
* Add an answer if it is not suppressed.
*
* @param in
* @param rec
* @exception IOException
*/
public void addAnswer(DNSIncoming in, DNSRecord rec) throws IOException {
if ((in == null) || !rec.suppressedBy(in)) {
this.addAnswer(rec, 0);
}
}
/**
* Add an answer to the message.
*
* @param rec
* @param now
* @exception IOException
*/
public void addAnswer(DNSRecord rec, long now) throws IOException {
if (rec != null) {
if ((now == 0) || !rec.isExpired(now)) {
MessageOutputStream record = new MessageOutputStream(512, this);
record.writeRecord(rec, now);
byte[] byteArray = record.toByteArray();
if (byteArray.length < this.availableSpace()) {
_answers.add(rec);
_answersBytes.write(byteArray, 0, byteArray.length);
} else {
throw new IOException("message full");
}
}
}
}
/**
* Add an authoritative answer to the message.
*
* @param rec
* @exception IOException
*/
public void addAuthorativeAnswer(DNSRecord rec) throws IOException {
MessageOutputStream record = new MessageOutputStream(512, this);
record.writeRecord(rec, 0);
byte[] byteArray = record.toByteArray();
if (byteArray.length < this.availableSpace()) {
_authoritativeAnswers.add(rec);
_authoritativeAnswersBytes.write(byteArray, 0, byteArray.length);
} else {
throw new IOException("message full");
}
}
/**
* Add an additional answer to the record. Omit if there is no room.
*
* @param in
* @param rec
* @exception IOException
*/
public void addAdditionalAnswer(DNSIncoming in, DNSRecord rec) throws IOException {
MessageOutputStream record = new MessageOutputStream(512, this);
record.writeRecord(rec, 0);
byte[] byteArray = record.toByteArray();
if (byteArray.length < this.availableSpace()) {
_additionals.add(rec);
_additionalsAnswersBytes.write(byteArray, 0, byteArray.length);
} else {
throw new IOException("message full");
}
}
/**
* Builds the final message buffer to be send and returns it.
*
* @return bytes to send.
*/
public byte[] data() {
long now = System.currentTimeMillis(); // System.currentTimeMillis()
_names.clear();
MessageOutputStream message = new MessageOutputStream(_maxUDPPayload, this);
message.writeShort(_multicast ? 0 : this.getId());
message.writeShort(this.getFlags());
message.writeShort(this.getNumberOfQuestions());
message.writeShort(this.getNumberOfAnswers());
message.writeShort(this.getNumberOfAuthorities());
message.writeShort(this.getNumberOfAdditionals());
for (DNSQuestion question : _questions) {
message.writeQuestion(question);
}
for (DNSRecord record : _answers) {
message.writeRecord(record, now);
}
for (DNSRecord record : _authoritativeAnswers) {
message.writeRecord(record, now);
}
for (DNSRecord record : _additionals) {
message.writeRecord(record, now);
}
return message.toByteArray();
}
/**
* Debugging.
*/
String print(boolean dump) {
StringBuilder buf = new StringBuilder();
buf.append(this.print());
if (dump) {
buf.append(this.print(this.data()));
}
return buf.toString();
}
@Override
public String toString() {
StringBuffer buf = new StringBuffer();
buf.append(isQuery() ? "dns[query:" : "dns[response:");
buf.append(" id=0x");
buf.append(Integer.toHexString(this.getId()));
if (this.getFlags() != 0) {
buf.append(", flags=0x");
buf.append(Integer.toHexString(this.getFlags()));
if (this.isResponse()) {
buf.append(":r");
}
if (this.isAuthoritativeAnswer()) {
buf.append(":aa");
}
if (this.isTruncated()) {
buf.append(":tc");
}
}
if (this.getNumberOfQuestions() > 0) {
buf.append(", questions=");
buf.append(this.getNumberOfQuestions());
}
if (this.getNumberOfAnswers() > 0) {
buf.append(", answers=");
buf.append(this.getNumberOfAnswers());
}
if (this.getNumberOfAuthorities() > 0) {
buf.append(", authorities=");
buf.append(this.getNumberOfAuthorities());
}
if (this.getNumberOfAdditionals() > 0) {
buf.append(", additionals=");
buf.append(this.getNumberOfAdditionals());
}
if (this.getNumberOfQuestions() > 0) {
buf.append("\nquestions:");
for (DNSQuestion question : _questions) {
buf.append("\n\t");
buf.append(question);
}
}
if (this.getNumberOfAnswers() > 0) {
buf.append("\nanswers:");
for (DNSRecord record : _answers) {
buf.append("\n\t");
buf.append(record);
}
}
if (this.getNumberOfAuthorities() > 0) {
buf.append("\nauthorities:");
for (DNSRecord record : _authoritativeAnswers) {
buf.append("\n\t");
buf.append(record);
}
}
if (this.getNumberOfAdditionals() > 0) {
buf.append("\nadditionals:");
for (DNSRecord record : _additionals) {
buf.append("\n\t");
buf.append(record);
}
}
buf.append("\nnames=");
buf.append(_names);
buf.append("]");
return buf.toString();
}
/**
* @return the maxUDPPayload
*/
public int getMaxUDPPayload() {
return this._maxUDPPayload;
}
}

View file

@ -1,328 +1,328 @@
// Copyright 2003-2005 Arthur van Hoff, Rick Blair
// Licensed under Apache License version 2.0
// Original license LGPL
package javax.jmdns.impl;
import java.net.InetAddress;
import java.util.Set;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.jmdns.ServiceInfo;
import javax.jmdns.ServiceInfo.Fields;
import javax.jmdns.impl.JmDNSImpl.ServiceTypeEntry;
import javax.jmdns.impl.constants.DNSConstants;
import javax.jmdns.impl.constants.DNSRecordClass;
import javax.jmdns.impl.constants.DNSRecordType;
/**
* A DNS question.
*
* @author Arthur van Hoff, Pierre Frisch
*/
public class DNSQuestion extends DNSEntry {
private static Logger logger = Logger.getLogger(DNSQuestion.class.getName());
/**
* Address question.
*/
private static class DNS4Address extends DNSQuestion {
DNS4Address(String name, DNSRecordType type, DNSRecordClass recordClass, boolean unique) {
super(name, type, recordClass, unique);
}
@Override
public void addAnswers(JmDNSImpl jmDNSImpl, Set<DNSRecord> answers) {
DNSRecord answer = jmDNSImpl.getLocalHost().getDNSAddressRecord(this.getRecordType(), DNSRecordClass.UNIQUE, DNSConstants.DNS_TTL);
if (answer != null) {
answers.add(answer);
}
}
@Override
public boolean iAmTheOnlyOne(JmDNSImpl jmDNSImpl) {
String name = this.getName().toLowerCase();
return jmDNSImpl.getLocalHost().getName().equals(name) || jmDNSImpl.getServices().keySet().contains(name);
}
}
/**
* Address question.
*/
private static class DNS6Address extends DNSQuestion {
DNS6Address(String name, DNSRecordType type, DNSRecordClass recordClass, boolean unique) {
super(name, type, recordClass, unique);
}
@Override
public void addAnswers(JmDNSImpl jmDNSImpl, Set<DNSRecord> answers) {
DNSRecord answer = jmDNSImpl.getLocalHost().getDNSAddressRecord(this.getRecordType(), DNSRecordClass.UNIQUE, DNSConstants.DNS_TTL);
if (answer != null) {
answers.add(answer);
}
}
@Override
public boolean iAmTheOnlyOne(JmDNSImpl jmDNSImpl) {
String name = this.getName().toLowerCase();
return jmDNSImpl.getLocalHost().getName().equals(name) || jmDNSImpl.getServices().keySet().contains(name);
}
}
/**
* Host Information question.
*/
private static class HostInformation extends DNSQuestion {
HostInformation(String name, DNSRecordType type, DNSRecordClass recordClass, boolean unique) {
super(name, type, recordClass, unique);
}
}
/**
* Pointer question.
*/
private static class Pointer extends DNSQuestion {
Pointer(String name, DNSRecordType type, DNSRecordClass recordClass, boolean unique) {
super(name, type, recordClass, unique);
}
@Override
public void addAnswers(JmDNSImpl jmDNSImpl, Set<DNSRecord> answers) {
// find matching services
for (ServiceInfo serviceInfo : jmDNSImpl.getServices().values()) {
this.addAnswersForServiceInfo(jmDNSImpl, answers, (ServiceInfoImpl) serviceInfo);
}
if (this.isServicesDiscoveryMetaQuery()) {
for (String serviceType : jmDNSImpl.getServiceTypes().keySet()) {
ServiceTypeEntry typeEntry = jmDNSImpl.getServiceTypes().get(serviceType);
answers.add(new DNSRecord.Pointer("_services._dns-sd._udp.local.", DNSRecordClass.CLASS_IN, DNSRecordClass.NOT_UNIQUE, DNSConstants.DNS_TTL, typeEntry.getType()));
}
} else if (this.isReverseLookup()) {
String ipValue = this.getQualifiedNameMap().get(Fields.Instance);
if ((ipValue != null) && (ipValue.length() > 0)) {
InetAddress address = jmDNSImpl.getLocalHost().getInetAddress();
String hostIPAddress = (address != null ? address.getHostAddress() : "");
if (ipValue.equalsIgnoreCase(hostIPAddress)) {
if (this.isV4ReverseLookup()) {
answers.add(jmDNSImpl.getLocalHost().getDNSReverseAddressRecord(DNSRecordType.TYPE_A, DNSRecordClass.NOT_UNIQUE, DNSConstants.DNS_TTL));
}
if (this.isV6ReverseLookup()) {
answers.add(jmDNSImpl.getLocalHost().getDNSReverseAddressRecord(DNSRecordType.TYPE_AAAA, DNSRecordClass.NOT_UNIQUE, DNSConstants.DNS_TTL));
}
}
}
} else if (this.isDomainDiscoveryQuery()) {
// FIXME [PJYF Nov 16 2010] We do not currently support domain discovery
}
}
}
/**
* Service question.
*/
private static class Service extends DNSQuestion {
Service(String name, DNSRecordType type, DNSRecordClass recordClass, boolean unique) {
super(name, type, recordClass, unique);
}
@Override
public void addAnswers(JmDNSImpl jmDNSImpl, Set<DNSRecord> answers) {
String loname = this.getName().toLowerCase();
if (jmDNSImpl.getLocalHost().getName().equalsIgnoreCase(loname)) {
// type = DNSConstants.TYPE_A;
answers.addAll(jmDNSImpl.getLocalHost().answers(this.getRecordClass(), this.isUnique(), DNSConstants.DNS_TTL));
return;
}
// Service type request
if (jmDNSImpl.getServiceTypes().containsKey(loname)) {
DNSQuestion question = new Pointer(this.getName(), DNSRecordType.TYPE_PTR, this.getRecordClass(), this.isUnique());
question.addAnswers(jmDNSImpl, answers);
return;
}
this.addAnswersForServiceInfo(jmDNSImpl, answers, (ServiceInfoImpl) jmDNSImpl.getServices().get(loname));
}
@Override
public boolean iAmTheOnlyOne(JmDNSImpl jmDNSImpl) {
String name = this.getName().toLowerCase();
return jmDNSImpl.getLocalHost().getName().equals(name) || jmDNSImpl.getServices().keySet().contains(name);
}
}
/**
* Text question.
*/
private static class Text extends DNSQuestion {
Text(String name, DNSRecordType type, DNSRecordClass recordClass, boolean unique) {
super(name, type, recordClass, unique);
}
@Override
public void addAnswers(JmDNSImpl jmDNSImpl, Set<DNSRecord> answers) {
this.addAnswersForServiceInfo(jmDNSImpl, answers, (ServiceInfoImpl) jmDNSImpl.getServices().get(this.getName().toLowerCase()));
}
@Override
public boolean iAmTheOnlyOne(JmDNSImpl jmDNSImpl) {
String name = this.getName().toLowerCase();
return jmDNSImpl.getLocalHost().getName().equals(name) || jmDNSImpl.getServices().keySet().contains(name);
}
}
/**
* AllRecords question.
*/
private static class AllRecords extends DNSQuestion {
AllRecords(String name, DNSRecordType type, DNSRecordClass recordClass, boolean unique) {
super(name, type, recordClass, unique);
}
@Override
public boolean isSameType(DNSEntry entry) {
// We match all non null entry
return (entry != null);
}
@Override
public void addAnswers(JmDNSImpl jmDNSImpl, Set<DNSRecord> answers) {
String loname = this.getName().toLowerCase();
if (jmDNSImpl.getLocalHost().getName().equalsIgnoreCase(loname)) {
// type = DNSConstants.TYPE_A;
answers.addAll(jmDNSImpl.getLocalHost().answers(this.getRecordClass(), this.isUnique(), DNSConstants.DNS_TTL));
return;
}
// Service type request
if (jmDNSImpl.getServiceTypes().containsKey(loname)) {
DNSQuestion question = new Pointer(this.getName(), DNSRecordType.TYPE_PTR, this.getRecordClass(), this.isUnique());
question.addAnswers(jmDNSImpl, answers);
return;
}
this.addAnswersForServiceInfo(jmDNSImpl, answers, (ServiceInfoImpl) jmDNSImpl.getServices().get(loname));
}
@Override
public boolean iAmTheOnlyOne(JmDNSImpl jmDNSImpl) {
String name = this.getName().toLowerCase();
return jmDNSImpl.getLocalHost().getName().equals(name) || jmDNSImpl.getServices().keySet().contains(name);
}
}
DNSQuestion(String name, DNSRecordType type, DNSRecordClass recordClass, boolean unique) {
super(name, type, recordClass, unique);
}
/**
* Create a question.
*
* @param name
* DNS name to be resolved
* @param type
* Record type to resolve
* @param recordClass
* Record class to resolve
* @param unique
* Request unicast response (Currently not supported in this implementation)
* @return new question
*/
public static DNSQuestion newQuestion(String name, DNSRecordType type, DNSRecordClass recordClass, boolean unique) {
switch (type) {
case TYPE_A:
return new DNS4Address(name, type, recordClass, unique);
case TYPE_A6:
return new DNS6Address(name, type, recordClass, unique);
case TYPE_AAAA:
return new DNS6Address(name, type, recordClass, unique);
case TYPE_ANY:
return new AllRecords(name, type, recordClass, unique);
case TYPE_HINFO:
return new HostInformation(name, type, recordClass, unique);
case TYPE_PTR:
return new Pointer(name, type, recordClass, unique);
case TYPE_SRV:
return new Service(name, type, recordClass, unique);
case TYPE_TXT:
return new Text(name, type, recordClass, unique);
default:
return new DNSQuestion(name, type, recordClass, unique);
}
}
/**
* Check if this question is answered by a given DNS record.
*/
boolean answeredBy(DNSEntry rec) {
return this.isSameRecordClass(rec) && this.isSameType(rec) && this.getName().equals(rec.getName());
}
/**
* Adds answers to the list for our question.
*
* @param jmDNSImpl
* DNS holding the records
* @param answers
* List of previous answer to append.
*/
public void addAnswers(JmDNSImpl jmDNSImpl, Set<DNSRecord> answers) {
// By default we do nothing
}
protected void addAnswersForServiceInfo(JmDNSImpl jmDNSImpl, Set<DNSRecord> answers, ServiceInfoImpl info) {
if ((info != null) && info.isAnnounced()) {
if (this.getName().equalsIgnoreCase(info.getQualifiedName()) || this.getName().equalsIgnoreCase(info.getType()) || this.getName().equalsIgnoreCase(info.getTypeWithSubtype())) {
answers.addAll(jmDNSImpl.getLocalHost().answers(this.getRecordClass(), DNSRecordClass.UNIQUE, DNSConstants.DNS_TTL));
answers.addAll(info.answers(this.getRecordClass(), DNSRecordClass.UNIQUE, DNSConstants.DNS_TTL, jmDNSImpl.getLocalHost()));
}
if (logger.isLoggable(Level.FINER)) {
logger.finer(jmDNSImpl.getName() + " DNSQuestion(" + this.getName() + ").addAnswersForServiceInfo(): info: " + info + "\n" + answers);
}
}
}
/*
* (non-Javadoc)
* @see javax.jmdns.impl.DNSEntry#isStale(long)
*/
@Override
public boolean isStale(long now) {
return false;
}
/*
* (non-Javadoc)
* @see javax.jmdns.impl.DNSEntry#isExpired(long)
*/
@Override
public boolean isExpired(long now) {
return false;
}
/**
* Checks if we are the only to be able to answer that question.
*
* @param jmDNSImpl
* DNS holding the records
* @return <code>true</code> if we are the only one with the answer to the question, <code>false</code> otherwise.
*/
public boolean iAmTheOnlyOne(JmDNSImpl jmDNSImpl) {
return false;
}
/*
* (non-Javadoc)
* @see javax.jmdns.impl.DNSEntry#toString(java.lang.StringBuilder)
*/
@Override
public void toString(StringBuilder aLog) {
// do nothing
}
// Copyright 2003-2005 Arthur van Hoff, Rick Blair
// Licensed under Apache License version 2.0
// Original license LGPL
package javax.jmdns.impl;
import java.net.InetAddress;
import java.util.Set;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.jmdns.ServiceInfo;
import javax.jmdns.ServiceInfo.Fields;
import javax.jmdns.impl.JmDNSImpl.ServiceTypeEntry;
import javax.jmdns.impl.constants.DNSConstants;
import javax.jmdns.impl.constants.DNSRecordClass;
import javax.jmdns.impl.constants.DNSRecordType;
/**
* A DNS question.
*
* @author Arthur van Hoff, Pierre Frisch
*/
public class DNSQuestion extends DNSEntry {
private static Logger logger = Logger.getLogger(DNSQuestion.class.getName());
/**
* Address question.
*/
private static class DNS4Address extends DNSQuestion {
DNS4Address(String name, DNSRecordType type, DNSRecordClass recordClass, boolean unique) {
super(name, type, recordClass, unique);
}
@Override
public void addAnswers(JmDNSImpl jmDNSImpl, Set<DNSRecord> answers) {
DNSRecord answer = jmDNSImpl.getLocalHost().getDNSAddressRecord(this.getRecordType(), DNSRecordClass.UNIQUE, DNSConstants.DNS_TTL);
if (answer != null) {
answers.add(answer);
}
}
@Override
public boolean iAmTheOnlyOne(JmDNSImpl jmDNSImpl) {
String name = this.getName().toLowerCase();
return jmDNSImpl.getLocalHost().getName().equals(name) || jmDNSImpl.getServices().keySet().contains(name);
}
}
/**
* Address question.
*/
private static class DNS6Address extends DNSQuestion {
DNS6Address(String name, DNSRecordType type, DNSRecordClass recordClass, boolean unique) {
super(name, type, recordClass, unique);
}
@Override
public void addAnswers(JmDNSImpl jmDNSImpl, Set<DNSRecord> answers) {
DNSRecord answer = jmDNSImpl.getLocalHost().getDNSAddressRecord(this.getRecordType(), DNSRecordClass.UNIQUE, DNSConstants.DNS_TTL);
if (answer != null) {
answers.add(answer);
}
}
@Override
public boolean iAmTheOnlyOne(JmDNSImpl jmDNSImpl) {
String name = this.getName().toLowerCase();
return jmDNSImpl.getLocalHost().getName().equals(name) || jmDNSImpl.getServices().keySet().contains(name);
}
}
/**
* Host Information question.
*/
private static class HostInformation extends DNSQuestion {
HostInformation(String name, DNSRecordType type, DNSRecordClass recordClass, boolean unique) {
super(name, type, recordClass, unique);
}
}
/**
* Pointer question.
*/
private static class Pointer extends DNSQuestion {
Pointer(String name, DNSRecordType type, DNSRecordClass recordClass, boolean unique) {
super(name, type, recordClass, unique);
}
@Override
public void addAnswers(JmDNSImpl jmDNSImpl, Set<DNSRecord> answers) {
// find matching services
for (ServiceInfo serviceInfo : jmDNSImpl.getServices().values()) {
this.addAnswersForServiceInfo(jmDNSImpl, answers, (ServiceInfoImpl) serviceInfo);
}
if (this.isServicesDiscoveryMetaQuery()) {
for (String serviceType : jmDNSImpl.getServiceTypes().keySet()) {
ServiceTypeEntry typeEntry = jmDNSImpl.getServiceTypes().get(serviceType);
answers.add(new DNSRecord.Pointer("_services._dns-sd._udp.local.", DNSRecordClass.CLASS_IN, DNSRecordClass.NOT_UNIQUE, DNSConstants.DNS_TTL, typeEntry.getType()));
}
} else if (this.isReverseLookup()) {
String ipValue = this.getQualifiedNameMap().get(Fields.Instance);
if ((ipValue != null) && (ipValue.length() > 0)) {
InetAddress address = jmDNSImpl.getLocalHost().getInetAddress();
String hostIPAddress = (address != null ? address.getHostAddress() : "");
if (ipValue.equalsIgnoreCase(hostIPAddress)) {
if (this.isV4ReverseLookup()) {
answers.add(jmDNSImpl.getLocalHost().getDNSReverseAddressRecord(DNSRecordType.TYPE_A, DNSRecordClass.NOT_UNIQUE, DNSConstants.DNS_TTL));
}
if (this.isV6ReverseLookup()) {
answers.add(jmDNSImpl.getLocalHost().getDNSReverseAddressRecord(DNSRecordType.TYPE_AAAA, DNSRecordClass.NOT_UNIQUE, DNSConstants.DNS_TTL));
}
}
}
} else if (this.isDomainDiscoveryQuery()) {
// FIXME [PJYF Nov 16 2010] We do not currently support domain discovery
}
}
}
/**
* Service question.
*/
private static class Service extends DNSQuestion {
Service(String name, DNSRecordType type, DNSRecordClass recordClass, boolean unique) {
super(name, type, recordClass, unique);
}
@Override
public void addAnswers(JmDNSImpl jmDNSImpl, Set<DNSRecord> answers) {
String loname = this.getName().toLowerCase();
if (jmDNSImpl.getLocalHost().getName().equalsIgnoreCase(loname)) {
// type = DNSConstants.TYPE_A;
answers.addAll(jmDNSImpl.getLocalHost().answers(this.getRecordClass(), this.isUnique(), DNSConstants.DNS_TTL));
return;
}
// Service type request
if (jmDNSImpl.getServiceTypes().containsKey(loname)) {
DNSQuestion question = new Pointer(this.getName(), DNSRecordType.TYPE_PTR, this.getRecordClass(), this.isUnique());
question.addAnswers(jmDNSImpl, answers);
return;
}
this.addAnswersForServiceInfo(jmDNSImpl, answers, (ServiceInfoImpl) jmDNSImpl.getServices().get(loname));
}
@Override
public boolean iAmTheOnlyOne(JmDNSImpl jmDNSImpl) {
String name = this.getName().toLowerCase();
return jmDNSImpl.getLocalHost().getName().equals(name) || jmDNSImpl.getServices().keySet().contains(name);
}
}
/**
* Text question.
*/
private static class Text extends DNSQuestion {
Text(String name, DNSRecordType type, DNSRecordClass recordClass, boolean unique) {
super(name, type, recordClass, unique);
}
@Override
public void addAnswers(JmDNSImpl jmDNSImpl, Set<DNSRecord> answers) {
this.addAnswersForServiceInfo(jmDNSImpl, answers, (ServiceInfoImpl) jmDNSImpl.getServices().get(this.getName().toLowerCase()));
}
@Override
public boolean iAmTheOnlyOne(JmDNSImpl jmDNSImpl) {
String name = this.getName().toLowerCase();
return jmDNSImpl.getLocalHost().getName().equals(name) || jmDNSImpl.getServices().keySet().contains(name);
}
}
/**
* AllRecords question.
*/
private static class AllRecords extends DNSQuestion {
AllRecords(String name, DNSRecordType type, DNSRecordClass recordClass, boolean unique) {
super(name, type, recordClass, unique);
}
@Override
public boolean isSameType(DNSEntry entry) {
// We match all non null entry
return (entry != null);
}
@Override
public void addAnswers(JmDNSImpl jmDNSImpl, Set<DNSRecord> answers) {
String loname = this.getName().toLowerCase();
if (jmDNSImpl.getLocalHost().getName().equalsIgnoreCase(loname)) {
// type = DNSConstants.TYPE_A;
answers.addAll(jmDNSImpl.getLocalHost().answers(this.getRecordClass(), this.isUnique(), DNSConstants.DNS_TTL));
return;
}
// Service type request
if (jmDNSImpl.getServiceTypes().containsKey(loname)) {
DNSQuestion question = new Pointer(this.getName(), DNSRecordType.TYPE_PTR, this.getRecordClass(), this.isUnique());
question.addAnswers(jmDNSImpl, answers);
return;
}
this.addAnswersForServiceInfo(jmDNSImpl, answers, (ServiceInfoImpl) jmDNSImpl.getServices().get(loname));
}
@Override
public boolean iAmTheOnlyOne(JmDNSImpl jmDNSImpl) {
String name = this.getName().toLowerCase();
return jmDNSImpl.getLocalHost().getName().equals(name) || jmDNSImpl.getServices().keySet().contains(name);
}
}
DNSQuestion(String name, DNSRecordType type, DNSRecordClass recordClass, boolean unique) {
super(name, type, recordClass, unique);
}
/**
* Create a question.
*
* @param name
* DNS name to be resolved
* @param type
* Record type to resolve
* @param recordClass
* Record class to resolve
* @param unique
* Request unicast response (Currently not supported in this implementation)
* @return new question
*/
public static DNSQuestion newQuestion(String name, DNSRecordType type, DNSRecordClass recordClass, boolean unique) {
switch (type) {
case TYPE_A:
return new DNS4Address(name, type, recordClass, unique);
case TYPE_A6:
return new DNS6Address(name, type, recordClass, unique);
case TYPE_AAAA:
return new DNS6Address(name, type, recordClass, unique);
case TYPE_ANY:
return new AllRecords(name, type, recordClass, unique);
case TYPE_HINFO:
return new HostInformation(name, type, recordClass, unique);
case TYPE_PTR:
return new Pointer(name, type, recordClass, unique);
case TYPE_SRV:
return new Service(name, type, recordClass, unique);
case TYPE_TXT:
return new Text(name, type, recordClass, unique);
default:
return new DNSQuestion(name, type, recordClass, unique);
}
}
/**
* Check if this question is answered by a given DNS record.
*/
boolean answeredBy(DNSEntry rec) {
return this.isSameRecordClass(rec) && this.isSameType(rec) && this.getName().equals(rec.getName());
}
/**
* Adds answers to the list for our question.
*
* @param jmDNSImpl
* DNS holding the records
* @param answers
* List of previous answer to append.
*/
public void addAnswers(JmDNSImpl jmDNSImpl, Set<DNSRecord> answers) {
// By default we do nothing
}
protected void addAnswersForServiceInfo(JmDNSImpl jmDNSImpl, Set<DNSRecord> answers, ServiceInfoImpl info) {
if ((info != null) && info.isAnnounced()) {
if (this.getName().equalsIgnoreCase(info.getQualifiedName()) || this.getName().equalsIgnoreCase(info.getType()) || this.getName().equalsIgnoreCase(info.getTypeWithSubtype())) {
answers.addAll(jmDNSImpl.getLocalHost().answers(this.getRecordClass(), DNSRecordClass.UNIQUE, DNSConstants.DNS_TTL));
answers.addAll(info.answers(this.getRecordClass(), DNSRecordClass.UNIQUE, DNSConstants.DNS_TTL, jmDNSImpl.getLocalHost()));
}
if (logger.isLoggable(Level.FINER)) {
logger.finer(jmDNSImpl.getName() + " DNSQuestion(" + this.getName() + ").addAnswersForServiceInfo(): info: " + info + "\n" + answers);
}
}
}
/*
* (non-Javadoc)
* @see javax.jmdns.impl.DNSEntry#isStale(long)
*/
@Override
public boolean isStale(long now) {
return false;
}
/*
* (non-Javadoc)
* @see javax.jmdns.impl.DNSEntry#isExpired(long)
*/
@Override
public boolean isExpired(long now) {
return false;
}
/**
* Checks if we are the only to be able to answer that question.
*
* @param jmDNSImpl
* DNS holding the records
* @return <code>true</code> if we are the only one with the answer to the question, <code>false</code> otherwise.
*/
public boolean iAmTheOnlyOne(JmDNSImpl jmDNSImpl) {
return false;
}
/*
* (non-Javadoc)
* @see javax.jmdns.impl.DNSEntry#toString(java.lang.StringBuilder)
*/
@Override
public void toString(StringBuilder aLog) {
// do nothing
}
}

View file

@ -1,474 +1,474 @@
/**
*
*/
package javax.jmdns.impl;
import java.util.Date;
import java.util.Timer;
import java.util.TimerTask;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import java.util.concurrent.atomic.AtomicReference;
import javax.jmdns.impl.tasks.RecordReaper;
import javax.jmdns.impl.tasks.Responder;
import javax.jmdns.impl.tasks.resolver.ServiceInfoResolver;
import javax.jmdns.impl.tasks.resolver.ServiceResolver;
import javax.jmdns.impl.tasks.resolver.TypeResolver;
import javax.jmdns.impl.tasks.state.Announcer;
import javax.jmdns.impl.tasks.state.Canceler;
import javax.jmdns.impl.tasks.state.Prober;
import javax.jmdns.impl.tasks.state.Renewer;
/**
* This class is used by JmDNS to start the various task required to run the DNS discovery. This interface is only there in order to support MANET modifications.
* <p>
* <b>Note: </b> This is not considered as part of the general public API of JmDNS.
* </p>
*
* @author Pierre Frisch
*/
public interface DNSTaskStarter {
/**
* DNSTaskStarter.Factory enable the creation of new instance of DNSTaskStarter.
*/
public static final class Factory {
private static volatile Factory _instance;
private final ConcurrentMap<JmDNSImpl, DNSTaskStarter> _instances;
/**
* This interface defines a delegate to the DNSTaskStarter class to enable subclassing.
*/
public static interface ClassDelegate {
/**
* Allows the delegate the opportunity to construct and return a different DNSTaskStarter.
*
* @param jmDNSImpl
* jmDNS instance
* @return Should return a new DNSTaskStarter Object.
* @see #classDelegate()
* @see #setClassDelegate(ClassDelegate anObject)
*/
public DNSTaskStarter newDNSTaskStarter(JmDNSImpl jmDNSImpl);
}
private static final AtomicReference<Factory.ClassDelegate> _databaseClassDelegate = new AtomicReference<Factory.ClassDelegate>();
private Factory() {
super();
_instances = new ConcurrentHashMap<JmDNSImpl, DNSTaskStarter>(20);
}
/**
* Assigns <code>delegate</code> as DNSTaskStarter's class delegate. The class delegate is optional.
*
* @param delegate
* The object to set as DNSTaskStarter's class delegate.
* @see #classDelegate()
* @see DNSTaskStarter.Factory.ClassDelegate
*/
public static void setClassDelegate(Factory.ClassDelegate delegate) {
_databaseClassDelegate.set(delegate);
}
/**
* Returns DNSTaskStarter's class delegate.
*
* @return DNSTaskStarter's class delegate.
* @see #setClassDelegate(ClassDelegate anObject)
* @see DNSTaskStarter.Factory.ClassDelegate
*/
public static Factory.ClassDelegate classDelegate() {
return _databaseClassDelegate.get();
}
/**
* Returns a new instance of DNSTaskStarter using the class delegate if it exists.
*
* @param jmDNSImpl
* jmDNS instance
* @return new instance of DNSTaskStarter
*/
protected static DNSTaskStarter newDNSTaskStarter(JmDNSImpl jmDNSImpl) {
DNSTaskStarter instance = null;
Factory.ClassDelegate delegate = _databaseClassDelegate.get();
if (delegate != null) {
instance = delegate.newDNSTaskStarter(jmDNSImpl);
}
return (instance != null ? instance : new DNSTaskStarterImpl(jmDNSImpl));
}
/**
* Return the instance of the DNSTaskStarter Factory.
*
* @return DNSTaskStarter Factory
*/
public static Factory getInstance() {
if (_instance == null) {
synchronized (DNSTaskStarter.Factory.class) {
if (_instance == null) {
_instance = new Factory();
}
}
}
return _instance;
}
/**
* Return the instance of the DNSTaskStarter for the JmDNS.
*
* @param jmDNSImpl
* jmDNS instance
* @return the DNSTaskStarter
*/
public DNSTaskStarter getStarter(JmDNSImpl jmDNSImpl) {
DNSTaskStarter starter = _instances.get(jmDNSImpl);
if (starter == null) {
_instances.putIfAbsent(jmDNSImpl, newDNSTaskStarter(jmDNSImpl));
starter = _instances.get(jmDNSImpl);
}
return starter;
}
/**
* Dispose of the DNSTaskStarter instance associated with this JmDNS.
*
* @param jmDNSImpl
* jmDNS instance
*/
public void disposeStarter(JmDNSImpl jmDNSImpl) {
_instances.remove(jmDNSImpl);
}
}
public static final class DNSTaskStarterImpl implements DNSTaskStarter {
private final JmDNSImpl _jmDNSImpl;
/**
* The timer is used to dispatch all outgoing messages of JmDNS. It is also used to dispatch maintenance tasks for the DNS cache.
*/
private final Timer _timer;
/**
* The timer is used to dispatch maintenance tasks for the DNS cache.
*/
private final Timer _stateTimer;
public static class StarterTimer extends Timer {
// This is needed because in some case we cancel the timers before all the task have finished running and in some case they will try to reschedule
private volatile boolean _cancelled;
/**
*
*/
public StarterTimer() {
super();
_cancelled = false;
}
/**
* @param isDaemon
*/
public StarterTimer(boolean isDaemon) {
super(isDaemon);
_cancelled = false;
}
/**
* @param name
* @param isDaemon
*/
public StarterTimer(String name, boolean isDaemon) {
super(name, isDaemon);
_cancelled = false;
}
/**
* @param name
*/
public StarterTimer(String name) {
super(name);
_cancelled = false;
}
/*
* (non-Javadoc)
* @see java.util.Timer#cancel()
*/
@Override
public synchronized void cancel() {
if (_cancelled) return;
_cancelled = true;
super.cancel();
}
/*
* (non-Javadoc)
* @see java.util.Timer#schedule(java.util.TimerTask, long)
*/
@Override
public synchronized void schedule(TimerTask task, long delay) {
if (_cancelled) return;
super.schedule(task, delay);
}
/*
* (non-Javadoc)
* @see java.util.Timer#schedule(java.util.TimerTask, java.util.Date)
*/
@Override
public synchronized void schedule(TimerTask task, Date time) {
if (_cancelled) return;
super.schedule(task, time);
}
/*
* (non-Javadoc)
* @see java.util.Timer#schedule(java.util.TimerTask, long, long)
*/
@Override
public synchronized void schedule(TimerTask task, long delay, long period) {
if (_cancelled) return;
super.schedule(task, delay, period);
}
/*
* (non-Javadoc)
* @see java.util.Timer#schedule(java.util.TimerTask, java.util.Date, long)
*/
@Override
public synchronized void schedule(TimerTask task, Date firstTime, long period) {
if (_cancelled) return;
super.schedule(task, firstTime, period);
}
/*
* (non-Javadoc)
* @see java.util.Timer#scheduleAtFixedRate(java.util.TimerTask, long, long)
*/
@Override
public synchronized void scheduleAtFixedRate(TimerTask task, long delay, long period) {
if (_cancelled) return;
super.scheduleAtFixedRate(task, delay, period);
}
/*
* (non-Javadoc)
* @see java.util.Timer#scheduleAtFixedRate(java.util.TimerTask, java.util.Date, long)
*/
@Override
public synchronized void scheduleAtFixedRate(TimerTask task, Date firstTime, long period) {
if (_cancelled) return;
super.scheduleAtFixedRate(task, firstTime, period);
}
}
public DNSTaskStarterImpl(JmDNSImpl jmDNSImpl) {
super();
_jmDNSImpl = jmDNSImpl;
_timer = new StarterTimer("JmDNS(" + _jmDNSImpl.getName() + ").Timer", true);
_stateTimer = new StarterTimer("JmDNS(" + _jmDNSImpl.getName() + ").State.Timer", true);
}
/*
* (non-Javadoc)
* @see javax.jmdns.impl.DNSTaskStarter#purgeTimer()
*/
@Override
public void purgeTimer() {
_timer.purge();
}
/*
* (non-Javadoc)
* @see javax.jmdns.impl.DNSTaskStarter#purgeStateTimer()
*/
@Override
public void purgeStateTimer() {
_stateTimer.purge();
}
/*
* (non-Javadoc)
* @see javax.jmdns.impl.DNSTaskStarter#cancelTimer()
*/
@Override
public void cancelTimer() {
_timer.cancel();
}
/*
* (non-Javadoc)
* @see javax.jmdns.impl.DNSTaskStarter#cancelStateTimer()
*/
@Override
public void cancelStateTimer() {
_stateTimer.cancel();
}
/*
* (non-Javadoc)
* @see javax.jmdns.impl.DNSTaskStarter#startProber()
*/
@Override
public void startProber() {
new Prober(_jmDNSImpl).start(_stateTimer);
}
/*
* (non-Javadoc)
* @see javax.jmdns.impl.DNSTaskStarter#startAnnouncer()
*/
@Override
public void startAnnouncer() {
new Announcer(_jmDNSImpl).start(_stateTimer);
}
/*
* (non-Javadoc)
* @see javax.jmdns.impl.DNSTaskStarter#startRenewer()
*/
@Override
public void startRenewer() {
new Renewer(_jmDNSImpl).start(_stateTimer);
}
/*
* (non-Javadoc)
* @see javax.jmdns.impl.DNSTaskStarter#startCanceler()
*/
@Override
public void startCanceler() {
new Canceler(_jmDNSImpl).start(_stateTimer);
}
/*
* (non-Javadoc)
* @see javax.jmdns.impl.DNSTaskStarter#startReaper()
*/
@Override
public void startReaper() {
new RecordReaper(_jmDNSImpl).start(_timer);
}
/*
* (non-Javadoc)
* @see javax.jmdns.impl.DNSTaskStarter#startServiceInfoResolver(javax.jmdns.impl.ServiceInfoImpl)
*/
@Override
public void startServiceInfoResolver(ServiceInfoImpl info) {
new ServiceInfoResolver(_jmDNSImpl, info).start(_timer);
}
/*
* (non-Javadoc)
* @see javax.jmdns.impl.DNSTaskStarter#startTypeResolver()
*/
@Override
public void startTypeResolver() {
new TypeResolver(_jmDNSImpl).start(_timer);
}
/*
* (non-Javadoc)
* @see javax.jmdns.impl.DNSTaskStarter#startServiceResolver(java.lang.String)
*/
@Override
public void startServiceResolver(String type) {
new ServiceResolver(_jmDNSImpl, type).start(_timer);
}
/*
* (non-Javadoc)
* @see javax.jmdns.impl.DNSTaskStarter#startResponder(javax.jmdns.impl.DNSIncoming, int)
*/
@Override
public void startResponder(DNSIncoming in, int port) {
new Responder(_jmDNSImpl, in, port).start(_timer);
}
}
/**
* Purge the general task timer
*/
public void purgeTimer();
/**
* Purge the state task timer
*/
public void purgeStateTimer();
/**
* Cancel the generals task timer
*/
public void cancelTimer();
/**
* Cancel the state task timer
*/
public void cancelStateTimer();
/**
* Start a new prober task
*/
public void startProber();
/**
* Start a new announcer task
*/
public void startAnnouncer();
/**
* Start a new renewer task
*/
public void startRenewer();
/**
* Start a new canceler task
*/
public void startCanceler();
/**
* Start a new reaper task. There is only supposed to be one reaper running at a time.
*/
public void startReaper();
/**
* Start a new service info resolver task
*
* @param info
* service info to resolve
*/
public void startServiceInfoResolver(ServiceInfoImpl info);
/**
* Start a new service type resolver task
*/
public void startTypeResolver();
/**
* Start a new service resolver task
*
* @param type
* service type to resolve
*/
public void startServiceResolver(String type);
/**
* Start a new responder task
*
* @param in
* incoming message
* @param port
* incoming port
*/
public void startResponder(DNSIncoming in, int port);
}
/**
*
*/
package javax.jmdns.impl;
import java.util.Date;
import java.util.Timer;
import java.util.TimerTask;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import java.util.concurrent.atomic.AtomicReference;
import javax.jmdns.impl.tasks.RecordReaper;
import javax.jmdns.impl.tasks.Responder;
import javax.jmdns.impl.tasks.resolver.ServiceInfoResolver;
import javax.jmdns.impl.tasks.resolver.ServiceResolver;
import javax.jmdns.impl.tasks.resolver.TypeResolver;
import javax.jmdns.impl.tasks.state.Announcer;
import javax.jmdns.impl.tasks.state.Canceler;
import javax.jmdns.impl.tasks.state.Prober;
import javax.jmdns.impl.tasks.state.Renewer;
/**
* This class is used by JmDNS to start the various task required to run the DNS discovery. This interface is only there in order to support MANET modifications.
* <p>
* <b>Note: </b> This is not considered as part of the general public API of JmDNS.
* </p>
*
* @author Pierre Frisch
*/
public interface DNSTaskStarter {
/**
* DNSTaskStarter.Factory enable the creation of new instance of DNSTaskStarter.
*/
public static final class Factory {
private static volatile Factory _instance;
private final ConcurrentMap<JmDNSImpl, DNSTaskStarter> _instances;
/**
* This interface defines a delegate to the DNSTaskStarter class to enable subclassing.
*/
public static interface ClassDelegate {
/**
* Allows the delegate the opportunity to construct and return a different DNSTaskStarter.
*
* @param jmDNSImpl
* jmDNS instance
* @return Should return a new DNSTaskStarter Object.
* @see #classDelegate()
* @see #setClassDelegate(ClassDelegate anObject)
*/
public DNSTaskStarter newDNSTaskStarter(JmDNSImpl jmDNSImpl);
}
private static final AtomicReference<Factory.ClassDelegate> _databaseClassDelegate = new AtomicReference<Factory.ClassDelegate>();
private Factory() {
super();
_instances = new ConcurrentHashMap<JmDNSImpl, DNSTaskStarter>(20);
}
/**
* Assigns <code>delegate</code> as DNSTaskStarter's class delegate. The class delegate is optional.
*
* @param delegate
* The object to set as DNSTaskStarter's class delegate.
* @see #classDelegate()
* @see DNSTaskStarter.Factory.ClassDelegate
*/
public static void setClassDelegate(Factory.ClassDelegate delegate) {
_databaseClassDelegate.set(delegate);
}
/**
* Returns DNSTaskStarter's class delegate.
*
* @return DNSTaskStarter's class delegate.
* @see #setClassDelegate(ClassDelegate anObject)
* @see DNSTaskStarter.Factory.ClassDelegate
*/
public static Factory.ClassDelegate classDelegate() {
return _databaseClassDelegate.get();
}
/**
* Returns a new instance of DNSTaskStarter using the class delegate if it exists.
*
* @param jmDNSImpl
* jmDNS instance
* @return new instance of DNSTaskStarter
*/
protected static DNSTaskStarter newDNSTaskStarter(JmDNSImpl jmDNSImpl) {
DNSTaskStarter instance = null;
Factory.ClassDelegate delegate = _databaseClassDelegate.get();
if (delegate != null) {
instance = delegate.newDNSTaskStarter(jmDNSImpl);
}
return (instance != null ? instance : new DNSTaskStarterImpl(jmDNSImpl));
}
/**
* Return the instance of the DNSTaskStarter Factory.
*
* @return DNSTaskStarter Factory
*/
public static Factory getInstance() {
if (_instance == null) {
synchronized (DNSTaskStarter.Factory.class) {
if (_instance == null) {
_instance = new Factory();
}
}
}
return _instance;
}
/**
* Return the instance of the DNSTaskStarter for the JmDNS.
*
* @param jmDNSImpl
* jmDNS instance
* @return the DNSTaskStarter
*/
public DNSTaskStarter getStarter(JmDNSImpl jmDNSImpl) {
DNSTaskStarter starter = _instances.get(jmDNSImpl);
if (starter == null) {
_instances.putIfAbsent(jmDNSImpl, newDNSTaskStarter(jmDNSImpl));
starter = _instances.get(jmDNSImpl);
}
return starter;
}
/**
* Dispose of the DNSTaskStarter instance associated with this JmDNS.
*
* @param jmDNSImpl
* jmDNS instance
*/
public void disposeStarter(JmDNSImpl jmDNSImpl) {
_instances.remove(jmDNSImpl);
}
}
public static final class DNSTaskStarterImpl implements DNSTaskStarter {
private final JmDNSImpl _jmDNSImpl;
/**
* The timer is used to dispatch all outgoing messages of JmDNS. It is also used to dispatch maintenance tasks for the DNS cache.
*/
private final Timer _timer;
/**
* The timer is used to dispatch maintenance tasks for the DNS cache.
*/
private final Timer _stateTimer;
public static class StarterTimer extends Timer {
// This is needed because in some case we cancel the timers before all the task have finished running and in some case they will try to reschedule
private volatile boolean _cancelled;
/**
*
*/
public StarterTimer() {
super();
_cancelled = false;
}
/**
* @param isDaemon
*/
public StarterTimer(boolean isDaemon) {
super(isDaemon);
_cancelled = false;
}
/**
* @param name
* @param isDaemon
*/
public StarterTimer(String name, boolean isDaemon) {
super(name, isDaemon);
_cancelled = false;
}
/**
* @param name
*/
public StarterTimer(String name) {
super(name);
_cancelled = false;
}
/*
* (non-Javadoc)
* @see java.util.Timer#cancel()
*/
@Override
public synchronized void cancel() {
if (_cancelled) return;
_cancelled = true;
super.cancel();
}
/*
* (non-Javadoc)
* @see java.util.Timer#schedule(java.util.TimerTask, long)
*/
@Override
public synchronized void schedule(TimerTask task, long delay) {
if (_cancelled) return;
super.schedule(task, delay);
}
/*
* (non-Javadoc)
* @see java.util.Timer#schedule(java.util.TimerTask, java.util.Date)
*/
@Override
public synchronized void schedule(TimerTask task, Date time) {
if (_cancelled) return;
super.schedule(task, time);
}
/*
* (non-Javadoc)
* @see java.util.Timer#schedule(java.util.TimerTask, long, long)
*/
@Override
public synchronized void schedule(TimerTask task, long delay, long period) {
if (_cancelled) return;
super.schedule(task, delay, period);
}
/*
* (non-Javadoc)
* @see java.util.Timer#schedule(java.util.TimerTask, java.util.Date, long)
*/
@Override
public synchronized void schedule(TimerTask task, Date firstTime, long period) {
if (_cancelled) return;
super.schedule(task, firstTime, period);
}
/*
* (non-Javadoc)
* @see java.util.Timer#scheduleAtFixedRate(java.util.TimerTask, long, long)
*/
@Override
public synchronized void scheduleAtFixedRate(TimerTask task, long delay, long period) {
if (_cancelled) return;
super.scheduleAtFixedRate(task, delay, period);
}
/*
* (non-Javadoc)
* @see java.util.Timer#scheduleAtFixedRate(java.util.TimerTask, java.util.Date, long)
*/
@Override
public synchronized void scheduleAtFixedRate(TimerTask task, Date firstTime, long period) {
if (_cancelled) return;
super.scheduleAtFixedRate(task, firstTime, period);
}
}
public DNSTaskStarterImpl(JmDNSImpl jmDNSImpl) {
super();
_jmDNSImpl = jmDNSImpl;
_timer = new StarterTimer("JmDNS(" + _jmDNSImpl.getName() + ").Timer", true);
_stateTimer = new StarterTimer("JmDNS(" + _jmDNSImpl.getName() + ").State.Timer", true);
}
/*
* (non-Javadoc)
* @see javax.jmdns.impl.DNSTaskStarter#purgeTimer()
*/
@Override
public void purgeTimer() {
_timer.purge();
}
/*
* (non-Javadoc)
* @see javax.jmdns.impl.DNSTaskStarter#purgeStateTimer()
*/
@Override
public void purgeStateTimer() {
_stateTimer.purge();
}
/*
* (non-Javadoc)
* @see javax.jmdns.impl.DNSTaskStarter#cancelTimer()
*/
@Override
public void cancelTimer() {
_timer.cancel();
}
/*
* (non-Javadoc)
* @see javax.jmdns.impl.DNSTaskStarter#cancelStateTimer()
*/
@Override
public void cancelStateTimer() {
_stateTimer.cancel();
}
/*
* (non-Javadoc)
* @see javax.jmdns.impl.DNSTaskStarter#startProber()
*/
@Override
public void startProber() {
new Prober(_jmDNSImpl).start(_stateTimer);
}
/*
* (non-Javadoc)
* @see javax.jmdns.impl.DNSTaskStarter#startAnnouncer()
*/
@Override
public void startAnnouncer() {
new Announcer(_jmDNSImpl).start(_stateTimer);
}
/*
* (non-Javadoc)
* @see javax.jmdns.impl.DNSTaskStarter#startRenewer()
*/
@Override
public void startRenewer() {
new Renewer(_jmDNSImpl).start(_stateTimer);
}
/*
* (non-Javadoc)
* @see javax.jmdns.impl.DNSTaskStarter#startCanceler()
*/
@Override
public void startCanceler() {
new Canceler(_jmDNSImpl).start(_stateTimer);
}
/*
* (non-Javadoc)
* @see javax.jmdns.impl.DNSTaskStarter#startReaper()
*/
@Override
public void startReaper() {
new RecordReaper(_jmDNSImpl).start(_timer);
}
/*
* (non-Javadoc)
* @see javax.jmdns.impl.DNSTaskStarter#startServiceInfoResolver(javax.jmdns.impl.ServiceInfoImpl)
*/
@Override
public void startServiceInfoResolver(ServiceInfoImpl info) {
new ServiceInfoResolver(_jmDNSImpl, info).start(_timer);
}
/*
* (non-Javadoc)
* @see javax.jmdns.impl.DNSTaskStarter#startTypeResolver()
*/
@Override
public void startTypeResolver() {
new TypeResolver(_jmDNSImpl).start(_timer);
}
/*
* (non-Javadoc)
* @see javax.jmdns.impl.DNSTaskStarter#startServiceResolver(java.lang.String)
*/
@Override
public void startServiceResolver(String type) {
new ServiceResolver(_jmDNSImpl, type).start(_timer);
}
/*
* (non-Javadoc)
* @see javax.jmdns.impl.DNSTaskStarter#startResponder(javax.jmdns.impl.DNSIncoming, int)
*/
@Override
public void startResponder(DNSIncoming in, int port) {
new Responder(_jmDNSImpl, in, port).start(_timer);
}
}
/**
* Purge the general task timer
*/
public void purgeTimer();
/**
* Purge the state task timer
*/
public void purgeStateTimer();
/**
* Cancel the generals task timer
*/
public void cancelTimer();
/**
* Cancel the state task timer
*/
public void cancelStateTimer();
/**
* Start a new prober task
*/
public void startProber();
/**
* Start a new announcer task
*/
public void startAnnouncer();
/**
* Start a new renewer task
*/
public void startRenewer();
/**
* Start a new canceler task
*/
public void startCanceler();
/**
* Start a new reaper task. There is only supposed to be one reaper running at a time.
*/
public void startReaper();
/**
* Start a new service info resolver task
*
* @param info
* service info to resolve
*/
public void startServiceInfoResolver(ServiceInfoImpl info);
/**
* Start a new service type resolver task
*/
public void startTypeResolver();
/**
* Start a new service resolver task
*
* @param type
* service type to resolve
*/
public void startServiceResolver(String type);
/**
* Start a new responder task
*
* @param in
* incoming message
* @param port
* incoming port
*/
public void startResponder(DNSIncoming in, int port);
}

View file

@ -1,434 +1,434 @@
// Copyright 2003-2005 Arthur van Hoff, Rick Blair
// Licensed under Apache License version 2.0
// Original license LGPL
package javax.jmdns.impl;
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.Inet4Address;
import java.net.Inet6Address;
import java.net.InetAddress;
import java.net.NetworkInterface;
import java.net.UnknownHostException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.jmdns.NetworkTopologyDiscovery;
import javax.jmdns.impl.constants.DNSConstants;
import javax.jmdns.impl.constants.DNSRecordClass;
import javax.jmdns.impl.constants.DNSRecordType;
import javax.jmdns.impl.constants.DNSState;
import javax.jmdns.impl.tasks.DNSTask;
/**
* HostInfo information on the local host to be able to cope with change of addresses.
*
* @author Pierre Frisch, Werner Randelshofer
*/
public class HostInfo implements DNSStatefulObject {
private static Logger logger = Logger.getLogger(HostInfo.class.getName());
protected String _name;
protected InetAddress _address;
protected NetworkInterface _interfaze;
private final HostInfoState _state;
private final static class HostInfoState extends DNSStatefulObject.DefaultImplementation {
private static final long serialVersionUID = -8191476803620402088L;
/**
* @param dns
*/
public HostInfoState(JmDNSImpl dns) {
super();
this.setDns(dns);
}
}
/**
* @param address
* IP address to bind
* @param dns
* JmDNS instance
* @param jmdnsName
* JmDNS name
* @return new HostInfo
*/
public static HostInfo newHostInfo(InetAddress address, JmDNSImpl dns, String jmdnsName) {
HostInfo localhost = null;
String aName = (jmdnsName != null ? jmdnsName : "");
InetAddress addr = address;
try {
if (addr == null) {
String ip = System.getProperty("net.mdns.interface");
if (ip != null) {
addr = InetAddress.getByName(ip);
} else {
addr = InetAddress.getLocalHost();
if (addr.isLoopbackAddress()) {
// Find local address that isn't a loopback address
InetAddress[] addresses = NetworkTopologyDiscovery.Factory.getInstance().getInetAddresses();
if (addresses.length > 0) {
addr = addresses[0];
}
}
}
if (addr.isLoopbackAddress()) {
logger.warning("Could not find any address beside the loopback.");
}
}
if (aName.length() == 0) {
aName = addr.getHostName();
}
if (aName.contains("in-addr.arpa") || (aName.equals(addr.getHostAddress()))) {
aName = ((jmdnsName != null) && (jmdnsName.length() > 0) ? jmdnsName : addr.getHostAddress());
}
} catch (final IOException e) {
logger.log(Level.WARNING, "Could not intialize the host network interface on " + address + "because of an error: " + e.getMessage(), e);
// This is only used for running unit test on Debian / Ubuntu
addr = loopbackAddress();
aName = ((jmdnsName != null) && (jmdnsName.length() > 0) ? jmdnsName : "computer");
}
// A host name with "." is illegal. so strip off everything and append .local.
// We also need to be carefull that the .local may already be there
int index = aName.indexOf(".local");
if (index > 0) {
aName = aName.substring(0, index);
}
aName = aName.replace('.', '-');
aName += ".local.";
localhost = new HostInfo(addr, aName, dns);
return localhost;
}
private static InetAddress loopbackAddress() {
try {
return InetAddress.getByName(null);
} catch (UnknownHostException exception) {
return null;
}
}
private HostInfo(final InetAddress address, final String name, final JmDNSImpl dns) {
super();
this._state = new HostInfoState(dns);
this._address = address;
this._name = name;
if (address != null) {
try {
_interfaze = NetworkInterface.getByInetAddress(address);
} catch (Exception exception) {
logger.log(Level.SEVERE, "LocalHostInfo() exception ", exception);
}
}
}
public String getName() {
return _name;
}
public InetAddress getInetAddress() {
return _address;
}
Inet4Address getInet4Address() {
if (this.getInetAddress() instanceof Inet4Address) {
return (Inet4Address) _address;
}
return null;
}
Inet6Address getInet6Address() {
if (this.getInetAddress() instanceof Inet6Address) {
return (Inet6Address) _address;
}
return null;
}
public NetworkInterface getInterface() {
return _interfaze;
}
public boolean conflictWithRecord(DNSRecord.Address record) {
DNSRecord.Address hostAddress = this.getDNSAddressRecord(record.getRecordType(), record.isUnique(), DNSConstants.DNS_TTL);
if (hostAddress != null) {
return hostAddress.sameType(record) && hostAddress.sameName(record) && (!hostAddress.sameValue(record));
}
return false;
}
synchronized String incrementHostName() {
_name = NameRegister.Factory.getRegistry().incrementName(this.getInetAddress(), _name, NameRegister.NameType.HOST);
return _name;
}
boolean shouldIgnorePacket(DatagramPacket packet) {
boolean result = false;
if (this.getInetAddress() != null) {
InetAddress from = packet.getAddress();
if (from != null) {
if ((this.getInetAddress().isLinkLocalAddress() || this.getInetAddress().isMCLinkLocal()) && (!from.isLinkLocalAddress())) {
// A host sending Multicast DNS queries to a link-local destination
// address (including the 224.0.0.251 and FF02::FB link-local multicast
// addresses) MUST only accept responses to that query that originate
// from the local link, and silently discard any other response packets.
// Without this check, it could be possible for remote rogue hosts to
// send spoof answer packets (perhaps unicast to the victim host) which
// the receiving machine could misinterpret as having originated on the
// local link.
result = true;
}
// if (from.isLinkLocalAddress() && (!this.getInetAddress().isLinkLocalAddress())) {
// // Ignore linklocal packets on regular interfaces, unless this is
// // also a linklocal interface. This is to avoid duplicates. This is
// // a terrible hack caused by the lack of an API to get the address
// // of the interface on which the packet was received.
// result = true;
// }
if (from.isLoopbackAddress() && (!this.getInetAddress().isLoopbackAddress())) {
// Ignore loopback packets on a regular interface unless this is also a loopback interface.
result = true;
}
}
}
return result;
}
DNSRecord.Address getDNSAddressRecord(DNSRecordType type, boolean unique, int ttl) {
switch (type) {
case TYPE_A:
return this.getDNS4AddressRecord(unique, ttl);
case TYPE_A6:
case TYPE_AAAA:
return this.getDNS6AddressRecord(unique, ttl);
default:
}
return null;
}
private DNSRecord.Address getDNS4AddressRecord(boolean unique, int ttl) {
if (this.getInetAddress() instanceof Inet4Address) {
return new DNSRecord.IPv4Address(this.getName(), DNSRecordClass.CLASS_IN, unique, ttl, this.getInetAddress());
}
return null;
}
private DNSRecord.Address getDNS6AddressRecord(boolean unique, int ttl) {
if (this.getInetAddress() instanceof Inet6Address) {
return new DNSRecord.IPv6Address(this.getName(), DNSRecordClass.CLASS_IN, unique, ttl, this.getInetAddress());
}
return null;
}
DNSRecord.Pointer getDNSReverseAddressRecord(DNSRecordType type, boolean unique, int ttl) {
switch (type) {
case TYPE_A:
return this.getDNS4ReverseAddressRecord(unique, ttl);
case TYPE_A6:
case TYPE_AAAA:
return this.getDNS6ReverseAddressRecord(unique, ttl);
default:
}
return null;
}
private DNSRecord.Pointer getDNS4ReverseAddressRecord(boolean unique, int ttl) {
if (this.getInetAddress() instanceof Inet4Address) {
return new DNSRecord.Pointer(this.getInetAddress().getHostAddress() + ".in-addr.arpa.", DNSRecordClass.CLASS_IN, unique, ttl, this.getName());
}
return null;
}
private DNSRecord.Pointer getDNS6ReverseAddressRecord(boolean unique, int ttl) {
if (this.getInetAddress() instanceof Inet6Address) {
return new DNSRecord.Pointer(this.getInetAddress().getHostAddress() + ".ip6.arpa.", DNSRecordClass.CLASS_IN, unique, ttl, this.getName());
}
return null;
}
@Override
public String toString() {
StringBuilder buf = new StringBuilder(1024);
buf.append("local host info[");
buf.append(getName() != null ? getName() : "no name");
buf.append(", ");
buf.append(getInterface() != null ? getInterface().getDisplayName() : "???");
buf.append(":");
buf.append(getInetAddress() != null ? getInetAddress().getHostAddress() : "no address");
buf.append(", ");
buf.append(_state);
buf.append("]");
return buf.toString();
}
public Collection<DNSRecord> answers(DNSRecordClass recordClass, boolean unique, int ttl) {
List<DNSRecord> list = new ArrayList<DNSRecord>();
DNSRecord answer = this.getDNS4AddressRecord(unique, ttl);
if ((answer != null) && answer.matchRecordClass(recordClass)) {
list.add(answer);
}
answer = this.getDNS6AddressRecord(unique, ttl);
if ((answer != null) && answer.matchRecordClass(recordClass)) {
list.add(answer);
}
return list;
}
/**
* {@inheritDoc}
*/
@Override
public JmDNSImpl getDns() {
return this._state.getDns();
}
/**
* {@inheritDoc}
*/
@Override
public boolean advanceState(DNSTask task) {
return this._state.advanceState(task);
}
/**
* {@inheritDoc}
*/
@Override
public void removeAssociationWithTask(DNSTask task) {
this._state.removeAssociationWithTask(task);
}
/**
* {@inheritDoc}
*/
@Override
public boolean revertState() {
return this._state.revertState();
}
/**
* {@inheritDoc}
*/
@Override
public void associateWithTask(DNSTask task, DNSState state) {
this._state.associateWithTask(task, state);
}
/**
* {@inheritDoc}
*/
@Override
public boolean isAssociatedWithTask(DNSTask task, DNSState state) {
return this._state.isAssociatedWithTask(task, state);
}
/**
* {@inheritDoc}
*/
@Override
public boolean cancelState() {
return this._state.cancelState();
}
/**
* {@inheritDoc}
*/
@Override
public boolean closeState() {
return this._state.closeState();
}
/**
* {@inheritDoc}
*/
@Override
public boolean recoverState() {
return this._state.recoverState();
}
/**
* {@inheritDoc}
*/
@Override
public boolean isProbing() {
return this._state.isProbing();
}
/**
* {@inheritDoc}
*/
@Override
public boolean isAnnouncing() {
return this._state.isAnnouncing();
}
/**
* {@inheritDoc}
*/
@Override
public boolean isAnnounced() {
return this._state.isAnnounced();
}
/**
* {@inheritDoc}
*/
@Override
public boolean isCanceling() {
return this._state.isCanceling();
}
/**
* {@inheritDoc}
*/
@Override
public boolean isCanceled() {
return this._state.isCanceled();
}
/**
* {@inheritDoc}
*/
@Override
public boolean isClosing() {
return this._state.isClosing();
}
/**
* {@inheritDoc}
*/
@Override
public boolean isClosed() {
return this._state.isClosed();
}
/**
* {@inheritDoc}
*/
@Override
public boolean waitForAnnounced(long timeout) {
return _state.waitForAnnounced(timeout);
}
/**
* {@inheritDoc}
*/
@Override
public boolean waitForCanceled(long timeout) {
if (_address == null) {
// No need to wait this was never announced.
return true;
}
return _state.waitForCanceled(timeout);
}
}
// Copyright 2003-2005 Arthur van Hoff, Rick Blair
// Licensed under Apache License version 2.0
// Original license LGPL
package javax.jmdns.impl;
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.Inet4Address;
import java.net.Inet6Address;
import java.net.InetAddress;
import java.net.NetworkInterface;
import java.net.UnknownHostException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.jmdns.NetworkTopologyDiscovery;
import javax.jmdns.impl.constants.DNSConstants;
import javax.jmdns.impl.constants.DNSRecordClass;
import javax.jmdns.impl.constants.DNSRecordType;
import javax.jmdns.impl.constants.DNSState;
import javax.jmdns.impl.tasks.DNSTask;
/**
* HostInfo information on the local host to be able to cope with change of addresses.
*
* @author Pierre Frisch, Werner Randelshofer
*/
public class HostInfo implements DNSStatefulObject {
private static Logger logger = Logger.getLogger(HostInfo.class.getName());
protected String _name;
protected InetAddress _address;
protected NetworkInterface _interfaze;
private final HostInfoState _state;
private final static class HostInfoState extends DNSStatefulObject.DefaultImplementation {
private static final long serialVersionUID = -8191476803620402088L;
/**
* @param dns
*/
public HostInfoState(JmDNSImpl dns) {
super();
this.setDns(dns);
}
}
/**
* @param address
* IP address to bind
* @param dns
* JmDNS instance
* @param jmdnsName
* JmDNS name
* @return new HostInfo
*/
public static HostInfo newHostInfo(InetAddress address, JmDNSImpl dns, String jmdnsName) {
HostInfo localhost = null;
String aName = (jmdnsName != null ? jmdnsName : "");
InetAddress addr = address;
try {
if (addr == null) {
String ip = System.getProperty("net.mdns.interface");
if (ip != null) {
addr = InetAddress.getByName(ip);
} else {
addr = InetAddress.getLocalHost();
if (addr.isLoopbackAddress()) {
// Find local address that isn't a loopback address
InetAddress[] addresses = NetworkTopologyDiscovery.Factory.getInstance().getInetAddresses();
if (addresses.length > 0) {
addr = addresses[0];
}
}
}
if (addr.isLoopbackAddress()) {
logger.warning("Could not find any address beside the loopback.");
}
}
if (aName.length() == 0) {
aName = addr.getHostName();
}
if (aName.contains("in-addr.arpa") || (aName.equals(addr.getHostAddress()))) {
aName = ((jmdnsName != null) && (jmdnsName.length() > 0) ? jmdnsName : addr.getHostAddress());
}
} catch (final IOException e) {
logger.log(Level.WARNING, "Could not intialize the host network interface on " + address + "because of an error: " + e.getMessage(), e);
// This is only used for running unit test on Debian / Ubuntu
addr = loopbackAddress();
aName = ((jmdnsName != null) && (jmdnsName.length() > 0) ? jmdnsName : "computer");
}
// A host name with "." is illegal. so strip off everything and append .local.
// We also need to be carefull that the .local may already be there
int index = aName.indexOf(".local");
if (index > 0) {
aName = aName.substring(0, index);
}
aName = aName.replace('.', '-');
aName += ".local.";
localhost = new HostInfo(addr, aName, dns);
return localhost;
}
private static InetAddress loopbackAddress() {
try {
return InetAddress.getByName(null);
} catch (UnknownHostException exception) {
return null;
}
}
private HostInfo(final InetAddress address, final String name, final JmDNSImpl dns) {
super();
this._state = new HostInfoState(dns);
this._address = address;
this._name = name;
if (address != null) {
try {
_interfaze = NetworkInterface.getByInetAddress(address);
} catch (Exception exception) {
logger.log(Level.SEVERE, "LocalHostInfo() exception ", exception);
}
}
}
public String getName() {
return _name;
}
public InetAddress getInetAddress() {
return _address;
}
Inet4Address getInet4Address() {
if (this.getInetAddress() instanceof Inet4Address) {
return (Inet4Address) _address;
}
return null;
}
Inet6Address getInet6Address() {
if (this.getInetAddress() instanceof Inet6Address) {
return (Inet6Address) _address;
}
return null;
}
public NetworkInterface getInterface() {
return _interfaze;
}
public boolean conflictWithRecord(DNSRecord.Address record) {
DNSRecord.Address hostAddress = this.getDNSAddressRecord(record.getRecordType(), record.isUnique(), DNSConstants.DNS_TTL);
if (hostAddress != null) {
return hostAddress.sameType(record) && hostAddress.sameName(record) && (!hostAddress.sameValue(record));
}
return false;
}
synchronized String incrementHostName() {
_name = NameRegister.Factory.getRegistry().incrementName(this.getInetAddress(), _name, NameRegister.NameType.HOST);
return _name;
}
boolean shouldIgnorePacket(DatagramPacket packet) {
boolean result = false;
if (this.getInetAddress() != null) {
InetAddress from = packet.getAddress();
if (from != null) {
if ((this.getInetAddress().isLinkLocalAddress() || this.getInetAddress().isMCLinkLocal()) && (!from.isLinkLocalAddress())) {
// A host sending Multicast DNS queries to a link-local destination
// address (including the 224.0.0.251 and FF02::FB link-local multicast
// addresses) MUST only accept responses to that query that originate
// from the local link, and silently discard any other response packets.
// Without this check, it could be possible for remote rogue hosts to
// send spoof answer packets (perhaps unicast to the victim host) which
// the receiving machine could misinterpret as having originated on the
// local link.
result = true;
}
// if (from.isLinkLocalAddress() && (!this.getInetAddress().isLinkLocalAddress())) {
// // Ignore linklocal packets on regular interfaces, unless this is
// // also a linklocal interface. This is to avoid duplicates. This is
// // a terrible hack caused by the lack of an API to get the address
// // of the interface on which the packet was received.
// result = true;
// }
if (from.isLoopbackAddress() && (!this.getInetAddress().isLoopbackAddress())) {
// Ignore loopback packets on a regular interface unless this is also a loopback interface.
result = true;
}
}
}
return result;
}
DNSRecord.Address getDNSAddressRecord(DNSRecordType type, boolean unique, int ttl) {
switch (type) {
case TYPE_A:
return this.getDNS4AddressRecord(unique, ttl);
case TYPE_A6:
case TYPE_AAAA:
return this.getDNS6AddressRecord(unique, ttl);
default:
}
return null;
}
private DNSRecord.Address getDNS4AddressRecord(boolean unique, int ttl) {
if (this.getInetAddress() instanceof Inet4Address) {
return new DNSRecord.IPv4Address(this.getName(), DNSRecordClass.CLASS_IN, unique, ttl, this.getInetAddress());
}
return null;
}
private DNSRecord.Address getDNS6AddressRecord(boolean unique, int ttl) {
if (this.getInetAddress() instanceof Inet6Address) {
return new DNSRecord.IPv6Address(this.getName(), DNSRecordClass.CLASS_IN, unique, ttl, this.getInetAddress());
}
return null;
}
DNSRecord.Pointer getDNSReverseAddressRecord(DNSRecordType type, boolean unique, int ttl) {
switch (type) {
case TYPE_A:
return this.getDNS4ReverseAddressRecord(unique, ttl);
case TYPE_A6:
case TYPE_AAAA:
return this.getDNS6ReverseAddressRecord(unique, ttl);
default:
}
return null;
}
private DNSRecord.Pointer getDNS4ReverseAddressRecord(boolean unique, int ttl) {
if (this.getInetAddress() instanceof Inet4Address) {
return new DNSRecord.Pointer(this.getInetAddress().getHostAddress() + ".in-addr.arpa.", DNSRecordClass.CLASS_IN, unique, ttl, this.getName());
}
return null;
}
private DNSRecord.Pointer getDNS6ReverseAddressRecord(boolean unique, int ttl) {
if (this.getInetAddress() instanceof Inet6Address) {
return new DNSRecord.Pointer(this.getInetAddress().getHostAddress() + ".ip6.arpa.", DNSRecordClass.CLASS_IN, unique, ttl, this.getName());
}
return null;
}
@Override
public String toString() {
StringBuilder buf = new StringBuilder(1024);
buf.append("local host info[");
buf.append(getName() != null ? getName() : "no name");
buf.append(", ");
buf.append(getInterface() != null ? getInterface().getDisplayName() : "???");
buf.append(":");
buf.append(getInetAddress() != null ? getInetAddress().getHostAddress() : "no address");
buf.append(", ");
buf.append(_state);
buf.append("]");
return buf.toString();
}
public Collection<DNSRecord> answers(DNSRecordClass recordClass, boolean unique, int ttl) {
List<DNSRecord> list = new ArrayList<DNSRecord>();
DNSRecord answer = this.getDNS4AddressRecord(unique, ttl);
if ((answer != null) && answer.matchRecordClass(recordClass)) {
list.add(answer);
}
answer = this.getDNS6AddressRecord(unique, ttl);
if ((answer != null) && answer.matchRecordClass(recordClass)) {
list.add(answer);
}
return list;
}
/**
* {@inheritDoc}
*/
@Override
public JmDNSImpl getDns() {
return this._state.getDns();
}
/**
* {@inheritDoc}
*/
@Override
public boolean advanceState(DNSTask task) {
return this._state.advanceState(task);
}
/**
* {@inheritDoc}
*/
@Override
public void removeAssociationWithTask(DNSTask task) {
this._state.removeAssociationWithTask(task);
}
/**
* {@inheritDoc}
*/
@Override
public boolean revertState() {
return this._state.revertState();
}
/**
* {@inheritDoc}
*/
@Override
public void associateWithTask(DNSTask task, DNSState state) {
this._state.associateWithTask(task, state);
}
/**
* {@inheritDoc}
*/
@Override
public boolean isAssociatedWithTask(DNSTask task, DNSState state) {
return this._state.isAssociatedWithTask(task, state);
}
/**
* {@inheritDoc}
*/
@Override
public boolean cancelState() {
return this._state.cancelState();
}
/**
* {@inheritDoc}
*/
@Override
public boolean closeState() {
return this._state.closeState();
}
/**
* {@inheritDoc}
*/
@Override
public boolean recoverState() {
return this._state.recoverState();
}
/**
* {@inheritDoc}
*/
@Override
public boolean isProbing() {
return this._state.isProbing();
}
/**
* {@inheritDoc}
*/
@Override
public boolean isAnnouncing() {
return this._state.isAnnouncing();
}
/**
* {@inheritDoc}
*/
@Override
public boolean isAnnounced() {
return this._state.isAnnounced();
}
/**
* {@inheritDoc}
*/
@Override
public boolean isCanceling() {
return this._state.isCanceling();
}
/**
* {@inheritDoc}
*/
@Override
public boolean isCanceled() {
return this._state.isCanceled();
}
/**
* {@inheritDoc}
*/
@Override
public boolean isClosing() {
return this._state.isClosing();
}
/**
* {@inheritDoc}
*/
@Override
public boolean isClosed() {
return this._state.isClosed();
}
/**
* {@inheritDoc}
*/
@Override
public boolean waitForAnnounced(long timeout) {
return _state.waitForAnnounced(timeout);
}
/**
* {@inheritDoc}
*/
@Override
public boolean waitForCanceled(long timeout) {
if (_address == null) {
// No need to wait this was never announced.
return true;
}
return _state.waitForCanceled(timeout);
}
}

View file

@ -1,286 +1,286 @@
/**
*
*/
package javax.jmdns.impl;
import java.util.EventListener;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import java.util.logging.Logger;
import javax.jmdns.JmDNS;
import javax.jmdns.ServiceEvent;
import javax.jmdns.ServiceInfo;
import javax.jmdns.ServiceListener;
import javax.jmdns.ServiceTypeListener;
/**
* This class track the status of listener.<br/>
* The main purpose of this class is to collapse consecutive events so that we can guarantee the correct call back sequence.
*
* @param <T>
* listener type
*/
public class ListenerStatus<T extends EventListener> {
public static class ServiceListenerStatus extends ListenerStatus<ServiceListener> {
private static Logger logger = Logger.getLogger(ServiceListenerStatus.class.getName());
private final ConcurrentMap<String, ServiceInfo> _addedServices;
/**
* @param listener
* listener being tracked.
* @param synch
* true if that listener can be called asynchronously
*/
public ServiceListenerStatus(ServiceListener listener, boolean synch) {
super(listener, synch);
_addedServices = new ConcurrentHashMap<String, ServiceInfo>(32);
}
/**
* A service has been added.<br/>
* <b>Note:</b>This event is only the service added event. The service info associated with this event does not include resolution information.<br/>
* To get the full resolved information you need to listen to {@link #serviceResolved(ServiceEvent)} or call {@link JmDNS#getServiceInfo(String, String, long)}
*
* <pre>
* ServiceInfo info = event.getDNS().getServiceInfo(event.getType(), event.getName())
* </pre>
* <p>
* Please note that service resolution may take a few second to resolve.
* </p>
*
* @param event
* The ServiceEvent providing the name and fully qualified type of the service.
*/
void serviceAdded(ServiceEvent event) {
String qualifiedName = event.getName() + "." + event.getType();
if (null == _addedServices.putIfAbsent(qualifiedName, event.getInfo().clone())) {
this.getListener().serviceAdded(event);
ServiceInfo info = event.getInfo();
if ((info != null) && (info.hasData())) {
this.getListener().serviceResolved(event);
}
} else {
logger.finer("Service Added called for a service already added: " + event);
}
}
/**
* A service has been removed.
*
* @param event
* The ServiceEvent providing the name and fully qualified type of the service.
*/
void serviceRemoved(ServiceEvent event) {
String qualifiedName = event.getName() + "." + event.getType();
if (_addedServices.remove(qualifiedName, _addedServices.get(qualifiedName))) {
this.getListener().serviceRemoved(event);
} else {
logger.finer("Service Removed called for a service already removed: " + event);
}
}
/**
* A service has been resolved. Its details are now available in the ServiceInfo record.<br/>
* <b>Note:</b>This call back will never be called if the service does not resolve.<br/>
*
* @param event
* The ServiceEvent providing the name, the fully qualified type of the service, and the service info record.
*/
synchronized void serviceResolved(ServiceEvent event) {
ServiceInfo info = event.getInfo();
if ((info != null) && (info.hasData())) {
String qualifiedName = event.getName() + "." + event.getType();
ServiceInfo previousServiceInfo = _addedServices.get(qualifiedName);
if (!_sameInfo(info, previousServiceInfo)) {
if (null == previousServiceInfo) {
if (null == _addedServices.putIfAbsent(qualifiedName, info.clone())) {
this.getListener().serviceResolved(event);
}
} else {
if (_addedServices.replace(qualifiedName, previousServiceInfo, info.clone())) {
this.getListener().serviceResolved(event);
}
}
} else {
logger.finer("Service Resolved called for a service already resolved: " + event);
}
} else {
logger.warning("Service Resolved called for an unresolved event: " + event);
}
}
private static final boolean _sameInfo(ServiceInfo info, ServiceInfo lastInfo) {
if (info == null) return false;
if (lastInfo == null) return false;
if (!info.equals(lastInfo)) return false;
byte[] text = info.getTextBytes();
byte[] lastText = lastInfo.getTextBytes();
if (text.length != lastText.length) return false;
for (int i = 0; i < text.length; i++) {
if (text[i] != lastText[i]) return false;
}
return true;
}
/*
* (non-Javadoc)
* @see java.lang.Object#toString()
*/
@Override
public String toString() {
StringBuilder aLog = new StringBuilder(2048);
aLog.append("[Status for ");
aLog.append(this.getListener().toString());
if (_addedServices.isEmpty()) {
aLog.append(" no type event ");
} else {
aLog.append(" (");
for (String service : _addedServices.keySet()) {
aLog.append(service + ", ");
}
aLog.append(") ");
}
aLog.append("]");
return aLog.toString();
}
}
public static class ServiceTypeListenerStatus extends ListenerStatus<ServiceTypeListener> {
private static Logger logger = Logger.getLogger(ServiceTypeListenerStatus.class.getName());
private final ConcurrentMap<String, String> _addedTypes;
/**
* @param listener
* listener being tracked.
* @param synch
* true if that listener can be called asynchronously
*/
public ServiceTypeListenerStatus(ServiceTypeListener listener, boolean synch) {
super(listener, synch);
_addedTypes = new ConcurrentHashMap<String, String>(32);
}
/**
* A new service type was discovered.
*
* @param event
* The service event providing the fully qualified type of the service.
*/
void serviceTypeAdded(ServiceEvent event) {
if (null == _addedTypes.putIfAbsent(event.getType(), event.getType())) {
this.getListener().serviceTypeAdded(event);
} else {
logger.finest("Service Type Added called for a service type already added: " + event);
}
}
/**
* A new subtype for the service type was discovered.
*
* <pre>
* &lt;sub&gt;._sub.&lt;app&gt;.&lt;protocol&gt;.&lt;servicedomain&gt;.&lt;parentdomain&gt;.
* </pre>
*
* @param event
* The service event providing the fully qualified type of the service with subtype.
*/
void subTypeForServiceTypeAdded(ServiceEvent event) {
if (null == _addedTypes.putIfAbsent(event.getType(), event.getType())) {
this.getListener().subTypeForServiceTypeAdded(event);
} else {
logger.finest("Service Sub Type Added called for a service sub type already added: " + event);
}
}
/*
* (non-Javadoc)
* @see java.lang.Object#toString()
*/
@Override
public String toString() {
StringBuilder aLog = new StringBuilder(2048);
aLog.append("[Status for ");
aLog.append(this.getListener().toString());
if (_addedTypes.isEmpty()) {
aLog.append(" no type event ");
} else {
aLog.append(" (");
for (String type : _addedTypes.keySet()) {
aLog.append(type + ", ");
}
aLog.append(") ");
}
aLog.append("]");
return aLog.toString();
}
}
public final static boolean SYNCHONEOUS = true;
public final static boolean ASYNCHONEOUS = false;
private final T _listener;
private final boolean _synch;
/**
* @param listener
* listener being tracked.
* @param synch
* true if that listener can be called asynchronously
*/
public ListenerStatus(T listener, boolean synch) {
super();
_listener = listener;
_synch = synch;
}
/**
* @return the listener
*/
public T getListener() {
return _listener;
}
/**
* Return <cod>true</code> if the listener must be called synchronously.
*
* @return the synch
*/
public boolean isSynchronous() {
return _synch;
}
/*
* (non-Javadoc)
* @see java.lang.Object#hashCode()
*/
@Override
public int hashCode() {
return this.getListener().hashCode();
}
/*
* (non-Javadoc)
* @see java.lang.Object#equals(java.lang.Object)
*/
@Override
public boolean equals(Object obj) {
return (obj instanceof ListenerStatus) && this.getListener().equals(((ListenerStatus<?>) obj).getListener());
}
/*
* (non-Javadoc)
* @see java.lang.Object#toString()
*/
@Override
public String toString() {
return "[Status for " + this.getListener().toString() + "]";
}
}
/**
*
*/
package javax.jmdns.impl;
import java.util.EventListener;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import java.util.logging.Logger;
import javax.jmdns.JmDNS;
import javax.jmdns.ServiceEvent;
import javax.jmdns.ServiceInfo;
import javax.jmdns.ServiceListener;
import javax.jmdns.ServiceTypeListener;
/**
* This class track the status of listener.<br/>
* The main purpose of this class is to collapse consecutive events so that we can guarantee the correct call back sequence.
*
* @param <T>
* listener type
*/
public class ListenerStatus<T extends EventListener> {
public static class ServiceListenerStatus extends ListenerStatus<ServiceListener> {
private static Logger logger = Logger.getLogger(ServiceListenerStatus.class.getName());
private final ConcurrentMap<String, ServiceInfo> _addedServices;
/**
* @param listener
* listener being tracked.
* @param synch
* true if that listener can be called asynchronously
*/
public ServiceListenerStatus(ServiceListener listener, boolean synch) {
super(listener, synch);
_addedServices = new ConcurrentHashMap<String, ServiceInfo>(32);
}
/**
* A service has been added.<br/>
* <b>Note:</b>This event is only the service added event. The service info associated with this event does not include resolution information.<br/>
* To get the full resolved information you need to listen to {@link #serviceResolved(ServiceEvent)} or call {@link JmDNS#getServiceInfo(String, String, long)}
*
* <pre>
* ServiceInfo info = event.getDNS().getServiceInfo(event.getType(), event.getName())
* </pre>
* <p>
* Please note that service resolution may take a few second to resolve.
* </p>
*
* @param event
* The ServiceEvent providing the name and fully qualified type of the service.
*/
void serviceAdded(ServiceEvent event) {
String qualifiedName = event.getName() + "." + event.getType();
if (null == _addedServices.putIfAbsent(qualifiedName, event.getInfo().clone())) {
this.getListener().serviceAdded(event);
ServiceInfo info = event.getInfo();
if ((info != null) && (info.hasData())) {
this.getListener().serviceResolved(event);
}
} else {
logger.finer("Service Added called for a service already added: " + event);
}
}
/**
* A service has been removed.
*
* @param event
* The ServiceEvent providing the name and fully qualified type of the service.
*/
void serviceRemoved(ServiceEvent event) {
String qualifiedName = event.getName() + "." + event.getType();
if (_addedServices.remove(qualifiedName, _addedServices.get(qualifiedName))) {
this.getListener().serviceRemoved(event);
} else {
logger.finer("Service Removed called for a service already removed: " + event);
}
}
/**
* A service has been resolved. Its details are now available in the ServiceInfo record.<br/>
* <b>Note:</b>This call back will never be called if the service does not resolve.<br/>
*
* @param event
* The ServiceEvent providing the name, the fully qualified type of the service, and the service info record.
*/
synchronized void serviceResolved(ServiceEvent event) {
ServiceInfo info = event.getInfo();
if ((info != null) && (info.hasData())) {
String qualifiedName = event.getName() + "." + event.getType();
ServiceInfo previousServiceInfo = _addedServices.get(qualifiedName);
if (!_sameInfo(info, previousServiceInfo)) {
if (null == previousServiceInfo) {
if (null == _addedServices.putIfAbsent(qualifiedName, info.clone())) {
this.getListener().serviceResolved(event);
}
} else {
if (_addedServices.replace(qualifiedName, previousServiceInfo, info.clone())) {
this.getListener().serviceResolved(event);
}
}
} else {
logger.finer("Service Resolved called for a service already resolved: " + event);
}
} else {
logger.warning("Service Resolved called for an unresolved event: " + event);
}
}
private static final boolean _sameInfo(ServiceInfo info, ServiceInfo lastInfo) {
if (info == null) return false;
if (lastInfo == null) return false;
if (!info.equals(lastInfo)) return false;
byte[] text = info.getTextBytes();
byte[] lastText = lastInfo.getTextBytes();
if (text.length != lastText.length) return false;
for (int i = 0; i < text.length; i++) {
if (text[i] != lastText[i]) return false;
}
return true;
}
/*
* (non-Javadoc)
* @see java.lang.Object#toString()
*/
@Override
public String toString() {
StringBuilder aLog = new StringBuilder(2048);
aLog.append("[Status for ");
aLog.append(this.getListener().toString());
if (_addedServices.isEmpty()) {
aLog.append(" no type event ");
} else {
aLog.append(" (");
for (String service : _addedServices.keySet()) {
aLog.append(service + ", ");
}
aLog.append(") ");
}
aLog.append("]");
return aLog.toString();
}
}
public static class ServiceTypeListenerStatus extends ListenerStatus<ServiceTypeListener> {
private static Logger logger = Logger.getLogger(ServiceTypeListenerStatus.class.getName());
private final ConcurrentMap<String, String> _addedTypes;
/**
* @param listener
* listener being tracked.
* @param synch
* true if that listener can be called asynchronously
*/
public ServiceTypeListenerStatus(ServiceTypeListener listener, boolean synch) {
super(listener, synch);
_addedTypes = new ConcurrentHashMap<String, String>(32);
}
/**
* A new service type was discovered.
*
* @param event
* The service event providing the fully qualified type of the service.
*/
void serviceTypeAdded(ServiceEvent event) {
if (null == _addedTypes.putIfAbsent(event.getType(), event.getType())) {
this.getListener().serviceTypeAdded(event);
} else {
logger.finest("Service Type Added called for a service type already added: " + event);
}
}
/**
* A new subtype for the service type was discovered.
*
* <pre>
* &lt;sub&gt;._sub.&lt;app&gt;.&lt;protocol&gt;.&lt;servicedomain&gt;.&lt;parentdomain&gt;.
* </pre>
*
* @param event
* The service event providing the fully qualified type of the service with subtype.
*/
void subTypeForServiceTypeAdded(ServiceEvent event) {
if (null == _addedTypes.putIfAbsent(event.getType(), event.getType())) {
this.getListener().subTypeForServiceTypeAdded(event);
} else {
logger.finest("Service Sub Type Added called for a service sub type already added: " + event);
}
}
/*
* (non-Javadoc)
* @see java.lang.Object#toString()
*/
@Override
public String toString() {
StringBuilder aLog = new StringBuilder(2048);
aLog.append("[Status for ");
aLog.append(this.getListener().toString());
if (_addedTypes.isEmpty()) {
aLog.append(" no type event ");
} else {
aLog.append(" (");
for (String type : _addedTypes.keySet()) {
aLog.append(type + ", ");
}
aLog.append(") ");
}
aLog.append("]");
return aLog.toString();
}
}
public final static boolean SYNCHONEOUS = true;
public final static boolean ASYNCHONEOUS = false;
private final T _listener;
private final boolean _synch;
/**
* @param listener
* listener being tracked.
* @param synch
* true if that listener can be called asynchronously
*/
public ListenerStatus(T listener, boolean synch) {
super();
_listener = listener;
_synch = synch;
}
/**
* @return the listener
*/
public T getListener() {
return _listener;
}
/**
* Return <cod>true</code> if the listener must be called synchronously.
*
* @return the synch
*/
public boolean isSynchronous() {
return _synch;
}
/*
* (non-Javadoc)
* @see java.lang.Object#hashCode()
*/
@Override
public int hashCode() {
return this.getListener().hashCode();
}
/*
* (non-Javadoc)
* @see java.lang.Object#equals(java.lang.Object)
*/
@Override
public boolean equals(Object obj) {
return (obj instanceof ListenerStatus) && this.getListener().equals(((ListenerStatus<?>) obj).getListener());
}
/*
* (non-Javadoc)
* @see java.lang.Object#toString()
*/
@Override
public String toString() {
return "[Status for " + this.getListener().toString() + "]";
}
}

View file

@ -1,274 +1,274 @@
/**
*
*/
package javax.jmdns.impl;
import java.net.InetAddress;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
/**
*
*/
public interface NameRegister {
/**
*
*/
public enum NameType {
/**
* This name represents a host name
*/
HOST,
/**
* This name represents a service name
*/
SERVICE,
}
public static abstract class BaseRegister implements NameRegister {
protected String incrementNameWithDash(String name) {
StringBuilder givenName = new StringBuilder(name.length() + 5);
int hostNameCount = 0;
int plocal = name.indexOf(".local.");
int punder = name.lastIndexOf('-');
if (punder < 0) {
// This is the first increment
hostNameCount = 1;
givenName.append(name.substring(0, plocal));
} else {
try {
int value = Integer.parseInt(name.substring(punder + 1, plocal));
hostNameCount = value + 1;
givenName.append(name.substring(0, punder));
} catch (Exception e) {
// If we got an exception this means that we have a name with a "-"
hostNameCount = 1;
givenName.append(name.substring(0, plocal));
}
}
givenName.append('-');
givenName.append(hostNameCount);
givenName.append(".local.");
return givenName.toString();
}
protected String incrementNameWithParentesis(String name) {
StringBuilder givenName = new StringBuilder(name.length() + 5);
final int l = name.lastIndexOf('(');
final int r = name.lastIndexOf(')');
if ((l >= 0) && (l < r)) {
try {
givenName.append(name.substring(0, l));
givenName.append('(');
givenName.append(Integer.parseInt(name.substring(l + 1, r)) + 1);
givenName.append(')');
} catch (final NumberFormatException e) {
givenName.setLength(0);
givenName.append(name);
givenName.append(" (2)");
}
} else {
givenName.append(name);
givenName.append(" (2)");
}
return givenName.toString();
}
}
public static class UniqueNamePerInterface extends BaseRegister {
private final ConcurrentMap<InetAddress, String> _hostNames;
private final ConcurrentMap<InetAddress, Set<String>> _serviceNames;
public UniqueNamePerInterface() {
super();
_hostNames = new ConcurrentHashMap<InetAddress, String>();
_serviceNames = new ConcurrentHashMap<InetAddress, Set<String>>();
}
/*
* (non-Javadoc)
* @see javax.jmdns.impl.NameRegister#register(java.net.InetAddress, java.lang.String, javax.jmdns.impl.NameRegister.NameType)
*/
@Override
public void register(InetAddress networkInterface, String name, NameType type) {
switch (type) {
case HOST:
break;
case SERVICE:
break;
default:
// this is trash to keep the compiler happy
}
}
/*
* (non-Javadoc)
* @see javax.jmdns.impl.NameRegister#checkName(java.net.InetAddress, java.lang.String, javax.jmdns.impl.NameRegister.NameType)
*/
@Override
public boolean checkName(InetAddress networkInterface, String name, NameType type) {
switch (type) {
case HOST:
String hostname = _hostNames.get(networkInterface);
return hostname != null && hostname.equals(name);
case SERVICE:
Set<String> names = _serviceNames.get(networkInterface);
return names != null && names.contains(names);
default:
// this is trash to keep the compiler happy
return false;
}
}
/*
* (non-Javadoc)
* @see javax.jmdns.impl.NameRegister#incrementHostName(java.net.InetAddress, java.lang.String, javax.jmdns.impl.NameRegister.NameType)
*/
@Override
public String incrementName(InetAddress networkInterface, String name, NameType type) {
switch (type) {
case HOST:
return this.incrementNameWithDash(name);
case SERVICE:
return this.incrementNameWithParentesis(name);
default:
// this is trash to keep the compiler happy
return name;
}
}
}
public static class UniqueNameAcrossInterface extends BaseRegister {
/*
* (non-Javadoc)
* @see javax.jmdns.impl.NameRegister#register(java.net.InetAddress, java.lang.String, javax.jmdns.impl.NameRegister.NameType)
*/
@Override
public void register(InetAddress networkInterface, String name, NameType type) {
switch (type) {
case HOST:
break;
case SERVICE:
break;
default:
// this is trash to keep the compiler happy
}
}
/*
* (non-Javadoc)
* @see javax.jmdns.impl.NameRegister#checkName(java.net.InetAddress, java.lang.String, javax.jmdns.impl.NameRegister.NameType)
*/
@Override
public boolean checkName(InetAddress networkInterface, String name, NameType type) {
switch (type) {
case HOST:
return false;
case SERVICE:
return false;
default:
// this is trash to keep the compiler happy
return false;
}
}
/*
* (non-Javadoc)
* @see javax.jmdns.impl.NameRegister#incrementHostName(java.net.InetAddress, java.lang.String, javax.jmdns.impl.NameRegister.NameType)
*/
@Override
public String incrementName(InetAddress networkInterface, String name, NameType type) {
switch (type) {
case HOST:
return this.incrementNameWithDash(name);
case SERVICE:
return this.incrementNameWithParentesis(name);
default:
// this is trash to keep the compiler happy
return name;
}
}
}
public static class Factory {
private static volatile NameRegister _register;
/**
* Register a Name register.
*
* @param register
* new register
* @throws IllegalStateException
* the register can only be set once
*/
public static void setRegistry(NameRegister register) throws IllegalStateException {
if (_register != null) {
throw new IllegalStateException("The register can only be set once.");
}
if (register != null) {
_register = register;
}
}
/**
* Returns the name register.
*
* @return name register
*/
public static NameRegister getRegistry() {
if (_register == null) {
_register = new UniqueNamePerInterface();
}
return _register;
}
}
/**
* Registers a name that is defended by this group of mDNS.
*
* @param networkInterface
* IP address to handle
* @param name
* name to register
* @param type
* name type to register
*/
public abstract void register(InetAddress networkInterface, String name, NameType type);
/**
* Checks a name that is defended by this group of mDNS.
*
* @param networkInterface
* IP address to handle
* @param name
* name to check
* @param type
* name type to check
* @return <code>true</code> if the name is not in conflict, <code>flase</code> otherwise.
*/
public abstract boolean checkName(InetAddress networkInterface, String name, NameType type);
/**
* Increments a name that is defended by this group of mDNS after it has been found in conflict.
*
* @param networkInterface
* IP address to handle
* @param name
* name to increment
* @param type
* name type to increments
* @return new name
*/
public abstract String incrementName(InetAddress networkInterface, String name, NameType type);
}
/**
*
*/
package javax.jmdns.impl;
import java.net.InetAddress;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
/**
*
*/
public interface NameRegister {
/**
*
*/
public enum NameType {
/**
* This name represents a host name
*/
HOST,
/**
* This name represents a service name
*/
SERVICE,
}
public static abstract class BaseRegister implements NameRegister {
protected String incrementNameWithDash(String name) {
StringBuilder givenName = new StringBuilder(name.length() + 5);
int hostNameCount = 0;
int plocal = name.indexOf(".local.");
int punder = name.lastIndexOf('-');
if (punder < 0) {
// This is the first increment
hostNameCount = 1;
givenName.append(name.substring(0, plocal));
} else {
try {
int value = Integer.parseInt(name.substring(punder + 1, plocal));
hostNameCount = value + 1;
givenName.append(name.substring(0, punder));
} catch (Exception e) {
// If we got an exception this means that we have a name with a "-"
hostNameCount = 1;
givenName.append(name.substring(0, plocal));
}
}
givenName.append('-');
givenName.append(hostNameCount);
givenName.append(".local.");
return givenName.toString();
}
protected String incrementNameWithParentesis(String name) {
StringBuilder givenName = new StringBuilder(name.length() + 5);
final int l = name.lastIndexOf('(');
final int r = name.lastIndexOf(')');
if ((l >= 0) && (l < r)) {
try {
givenName.append(name.substring(0, l));
givenName.append('(');
givenName.append(Integer.parseInt(name.substring(l + 1, r)) + 1);
givenName.append(')');
} catch (final NumberFormatException e) {
givenName.setLength(0);
givenName.append(name);
givenName.append(" (2)");
}
} else {
givenName.append(name);
givenName.append(" (2)");
}
return givenName.toString();
}
}
public static class UniqueNamePerInterface extends BaseRegister {
private final ConcurrentMap<InetAddress, String> _hostNames;
private final ConcurrentMap<InetAddress, Set<String>> _serviceNames;
public UniqueNamePerInterface() {
super();
_hostNames = new ConcurrentHashMap<InetAddress, String>();
_serviceNames = new ConcurrentHashMap<InetAddress, Set<String>>();
}
/*
* (non-Javadoc)
* @see javax.jmdns.impl.NameRegister#register(java.net.InetAddress, java.lang.String, javax.jmdns.impl.NameRegister.NameType)
*/
@Override
public void register(InetAddress networkInterface, String name, NameType type) {
switch (type) {
case HOST:
break;
case SERVICE:
break;
default:
// this is trash to keep the compiler happy
}
}
/*
* (non-Javadoc)
* @see javax.jmdns.impl.NameRegister#checkName(java.net.InetAddress, java.lang.String, javax.jmdns.impl.NameRegister.NameType)
*/
@Override
public boolean checkName(InetAddress networkInterface, String name, NameType type) {
switch (type) {
case HOST:
String hostname = _hostNames.get(networkInterface);
return hostname != null && hostname.equals(name);
case SERVICE:
Set<String> names = _serviceNames.get(networkInterface);
return names != null && names.contains(names);
default:
// this is trash to keep the compiler happy
return false;
}
}
/*
* (non-Javadoc)
* @see javax.jmdns.impl.NameRegister#incrementHostName(java.net.InetAddress, java.lang.String, javax.jmdns.impl.NameRegister.NameType)
*/
@Override
public String incrementName(InetAddress networkInterface, String name, NameType type) {
switch (type) {
case HOST:
return this.incrementNameWithDash(name);
case SERVICE:
return this.incrementNameWithParentesis(name);
default:
// this is trash to keep the compiler happy
return name;
}
}
}
public static class UniqueNameAcrossInterface extends BaseRegister {
/*
* (non-Javadoc)
* @see javax.jmdns.impl.NameRegister#register(java.net.InetAddress, java.lang.String, javax.jmdns.impl.NameRegister.NameType)
*/
@Override
public void register(InetAddress networkInterface, String name, NameType type) {
switch (type) {
case HOST:
break;
case SERVICE:
break;
default:
// this is trash to keep the compiler happy
}
}
/*
* (non-Javadoc)
* @see javax.jmdns.impl.NameRegister#checkName(java.net.InetAddress, java.lang.String, javax.jmdns.impl.NameRegister.NameType)
*/
@Override
public boolean checkName(InetAddress networkInterface, String name, NameType type) {
switch (type) {
case HOST:
return false;
case SERVICE:
return false;
default:
// this is trash to keep the compiler happy
return false;
}
}
/*
* (non-Javadoc)
* @see javax.jmdns.impl.NameRegister#incrementHostName(java.net.InetAddress, java.lang.String, javax.jmdns.impl.NameRegister.NameType)
*/
@Override
public String incrementName(InetAddress networkInterface, String name, NameType type) {
switch (type) {
case HOST:
return this.incrementNameWithDash(name);
case SERVICE:
return this.incrementNameWithParentesis(name);
default:
// this is trash to keep the compiler happy
return name;
}
}
}
public static class Factory {
private static volatile NameRegister _register;
/**
* Register a Name register.
*
* @param register
* new register
* @throws IllegalStateException
* the register can only be set once
*/
public static void setRegistry(NameRegister register) throws IllegalStateException {
if (_register != null) {
throw new IllegalStateException("The register can only be set once.");
}
if (register != null) {
_register = register;
}
}
/**
* Returns the name register.
*
* @return name register
*/
public static NameRegister getRegistry() {
if (_register == null) {
_register = new UniqueNamePerInterface();
}
return _register;
}
}
/**
* Registers a name that is defended by this group of mDNS.
*
* @param networkInterface
* IP address to handle
* @param name
* name to register
* @param type
* name type to register
*/
public abstract void register(InetAddress networkInterface, String name, NameType type);
/**
* Checks a name that is defended by this group of mDNS.
*
* @param networkInterface
* IP address to handle
* @param name
* name to check
* @param type
* name type to check
* @return <code>true</code> if the name is not in conflict, <code>flase</code> otherwise.
*/
public abstract boolean checkName(InetAddress networkInterface, String name, NameType type);
/**
* Increments a name that is defended by this group of mDNS after it has been found in conflict.
*
* @param networkInterface
* IP address to handle
* @param name
* name to increment
* @param type
* name type to increments
* @return new name
*/
public abstract String incrementName(InetAddress networkInterface, String name, NameType type);
}

View file

@ -1,129 +1,129 @@
/**
*
*/
package javax.jmdns.impl;
import java.lang.reflect.Method;
import java.net.InetAddress;
import java.net.NetworkInterface;
import java.net.SocketException;
import java.util.Enumeration;
import java.util.HashSet;
import java.util.Set;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.jmdns.NetworkTopologyDiscovery;
/**
* This class implements NetworkTopologyDiscovery.
*
* @author Pierre Frisch
*/
public class NetworkTopologyDiscoveryImpl implements NetworkTopologyDiscovery {
private final static Logger logger = Logger.getLogger(NetworkTopologyDiscoveryImpl.class.getName());
private final Method _isUp;
private final Method _supportsMulticast;
/**
*
*/
public NetworkTopologyDiscoveryImpl() {
super();
Method isUp;
try {
isUp = NetworkInterface.class.getMethod("isUp", (Class<?>[]) null);
} catch (Exception exception) {
// We do not want to throw anything if the method does not exist.
isUp = null;
}
_isUp = isUp;
Method supportsMulticast;
try {
supportsMulticast = NetworkInterface.class.getMethod("supportsMulticast", (Class<?>[]) null);
} catch (Exception exception) {
// We do not want to throw anything if the method does not exist.
supportsMulticast = null;
}
_supportsMulticast = supportsMulticast;
}
/*
* (non-Javadoc)
* @see javax.jmdns.JmmDNS.NetworkTopologyDiscovery#getInetAddresses()
*/
@Override
public InetAddress[] getInetAddresses() {
Set<InetAddress> result = new HashSet<InetAddress>();
try {
for (Enumeration<NetworkInterface> nifs = NetworkInterface.getNetworkInterfaces(); nifs.hasMoreElements();) {
NetworkInterface nif = nifs.nextElement();
for (Enumeration<InetAddress> iaenum = nif.getInetAddresses(); iaenum.hasMoreElements();) {
InetAddress interfaceAddress = iaenum.nextElement();
if (logger.isLoggable(Level.FINEST)) {
logger.finest("Found NetworkInterface/InetAddress: " + nif + " -- " + interfaceAddress);
}
if (this.useInetAddress(nif, interfaceAddress)) {
result.add(interfaceAddress);
}
}
}
} catch (SocketException se) {
logger.warning("Error while fetching network interfaces addresses: " + se);
}
return result.toArray(new InetAddress[result.size()]);
}
/*
* (non-Javadoc)
* @see javax.jmdns.JmmDNS.NetworkTopologyDiscovery#useInetAddress(java.net.NetworkInterface, java.net.InetAddress)
*/
@Override
public boolean useInetAddress(NetworkInterface networkInterface, InetAddress interfaceAddress) {
try {
if (_isUp != null) {
try {
if (!((Boolean) _isUp.invoke(networkInterface, (Object[]) null)).booleanValue()) {
return false;
}
} catch (Exception exception) {
// We should hide that exception.
}
}
if (_supportsMulticast != null) {
try {
if (!((Boolean) _supportsMulticast.invoke(networkInterface, (Object[]) null)).booleanValue()) {
return false;
}
} catch (Exception exception) {
// We should hide that exception.
}
}
return true;
} catch (Exception exception) {
return false;
}
}
/*
* (non-Javadoc)
* @see javax.jmdns.NetworkTopologyDiscovery#lockInetAddress(java.net.InetAddress)
*/
@Override
public void lockInetAddress(InetAddress interfaceAddress) {
// Default implementation does nothing.
}
/*
* (non-Javadoc)
* @see javax.jmdns.NetworkTopologyDiscovery#unlockInetAddress(java.net.InetAddress)
*/
@Override
public void unlockInetAddress(InetAddress interfaceAddress) {
// Default implementation does nothing.
}
}
/**
*
*/
package javax.jmdns.impl;
import java.lang.reflect.Method;
import java.net.InetAddress;
import java.net.NetworkInterface;
import java.net.SocketException;
import java.util.Enumeration;
import java.util.HashSet;
import java.util.Set;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.jmdns.NetworkTopologyDiscovery;
/**
* This class implements NetworkTopologyDiscovery.
*
* @author Pierre Frisch
*/
public class NetworkTopologyDiscoveryImpl implements NetworkTopologyDiscovery {
private final static Logger logger = Logger.getLogger(NetworkTopologyDiscoveryImpl.class.getName());
private final Method _isUp;
private final Method _supportsMulticast;
/**
*
*/
public NetworkTopologyDiscoveryImpl() {
super();
Method isUp;
try {
isUp = NetworkInterface.class.getMethod("isUp", (Class<?>[]) null);
} catch (Exception exception) {
// We do not want to throw anything if the method does not exist.
isUp = null;
}
_isUp = isUp;
Method supportsMulticast;
try {
supportsMulticast = NetworkInterface.class.getMethod("supportsMulticast", (Class<?>[]) null);
} catch (Exception exception) {
// We do not want to throw anything if the method does not exist.
supportsMulticast = null;
}
_supportsMulticast = supportsMulticast;
}
/*
* (non-Javadoc)
* @see javax.jmdns.JmmDNS.NetworkTopologyDiscovery#getInetAddresses()
*/
@Override
public InetAddress[] getInetAddresses() {
Set<InetAddress> result = new HashSet<InetAddress>();
try {
for (Enumeration<NetworkInterface> nifs = NetworkInterface.getNetworkInterfaces(); nifs.hasMoreElements();) {
NetworkInterface nif = nifs.nextElement();
for (Enumeration<InetAddress> iaenum = nif.getInetAddresses(); iaenum.hasMoreElements();) {
InetAddress interfaceAddress = iaenum.nextElement();
if (logger.isLoggable(Level.FINEST)) {
logger.finest("Found NetworkInterface/InetAddress: " + nif + " -- " + interfaceAddress);
}
if (this.useInetAddress(nif, interfaceAddress)) {
result.add(interfaceAddress);
}
}
}
} catch (SocketException se) {
logger.warning("Error while fetching network interfaces addresses: " + se);
}
return result.toArray(new InetAddress[result.size()]);
}
/*
* (non-Javadoc)
* @see javax.jmdns.JmmDNS.NetworkTopologyDiscovery#useInetAddress(java.net.NetworkInterface, java.net.InetAddress)
*/
@Override
public boolean useInetAddress(NetworkInterface networkInterface, InetAddress interfaceAddress) {
try {
if (_isUp != null) {
try {
if (!((Boolean) _isUp.invoke(networkInterface, (Object[]) null)).booleanValue()) {
return false;
}
} catch (Exception exception) {
// We should hide that exception.
}
}
if (_supportsMulticast != null) {
try {
if (!((Boolean) _supportsMulticast.invoke(networkInterface, (Object[]) null)).booleanValue()) {
return false;
}
} catch (Exception exception) {
// We should hide that exception.
}
}
return true;
} catch (Exception exception) {
return false;
}
}
/*
* (non-Javadoc)
* @see javax.jmdns.NetworkTopologyDiscovery#lockInetAddress(java.net.InetAddress)
*/
@Override
public void lockInetAddress(InetAddress interfaceAddress) {
// Default implementation does nothing.
}
/*
* (non-Javadoc)
* @see javax.jmdns.NetworkTopologyDiscovery#unlockInetAddress(java.net.InetAddress)
*/
@Override
public void unlockInetAddress(InetAddress interfaceAddress) {
// Default implementation does nothing.
}
}

View file

@ -1,82 +1,82 @@
/**
*
*/
package javax.jmdns.impl;
import java.net.InetAddress;
import javax.jmdns.JmDNS;
import javax.jmdns.NetworkTopologyEvent;
import javax.jmdns.NetworkTopologyListener;
/**
* @author C&eacute;drik Lime, Pierre Frisch
*/
public class NetworkTopologyEventImpl extends NetworkTopologyEvent implements Cloneable {
/**
*
*/
private static final long serialVersionUID = 1445606146153550463L;
private final InetAddress _inetAddress;
/**
* Constructs a Network Topology Event.
*
* @param jmDNS
* @param inetAddress
* @exception IllegalArgumentException
* if source is null.
*/
public NetworkTopologyEventImpl(JmDNS jmDNS, InetAddress inetAddress) {
super(jmDNS);
this._inetAddress = inetAddress;
}
NetworkTopologyEventImpl(NetworkTopologyListener jmmDNS, InetAddress inetAddress) {
super(jmmDNS);
this._inetAddress = inetAddress;
}
/*
* (non-Javadoc)
* @see javax.jmdns.NetworkTopologyEvent#getDNS()
*/
@Override
public JmDNS getDNS() {
return (this.getSource() instanceof JmDNS ? (JmDNS) getSource() : null);
}
/*
* (non-Javadoc)
* @see javax.jmdns.NetworkTopologyEvent#getInetAddress()
*/
@Override
public InetAddress getInetAddress() {
return _inetAddress;
}
@Override
public String toString() {
StringBuilder buf = new StringBuilder();
buf.append("[" + this.getClass().getSimpleName() + "@" + System.identityHashCode(this) + " ");
buf.append("\n\tinetAddress: '");
buf.append(this.getInetAddress());
buf.append("']");
// buf.append("' source: ");
// buf.append("\n\t" + source + "");
// buf.append("\n]");
return buf.toString();
}
/*
* (non-Javadoc)
* @see java.lang.Object#clone()
*/
@Override
public NetworkTopologyEventImpl clone() throws CloneNotSupportedException {
return new NetworkTopologyEventImpl(getDNS(), getInetAddress());
}
}
/**
*
*/
package javax.jmdns.impl;
import java.net.InetAddress;
import javax.jmdns.JmDNS;
import javax.jmdns.NetworkTopologyEvent;
import javax.jmdns.NetworkTopologyListener;
/**
* @author C&eacute;drik Lime, Pierre Frisch
*/
public class NetworkTopologyEventImpl extends NetworkTopologyEvent implements Cloneable {
/**
*
*/
private static final long serialVersionUID = 1445606146153550463L;
private final InetAddress _inetAddress;
/**
* Constructs a Network Topology Event.
*
* @param jmDNS
* @param inetAddress
* @exception IllegalArgumentException
* if source is null.
*/
public NetworkTopologyEventImpl(JmDNS jmDNS, InetAddress inetAddress) {
super(jmDNS);
this._inetAddress = inetAddress;
}
NetworkTopologyEventImpl(NetworkTopologyListener jmmDNS, InetAddress inetAddress) {
super(jmmDNS);
this._inetAddress = inetAddress;
}
/*
* (non-Javadoc)
* @see javax.jmdns.NetworkTopologyEvent#getDNS()
*/
@Override
public JmDNS getDNS() {
return (this.getSource() instanceof JmDNS ? (JmDNS) getSource() : null);
}
/*
* (non-Javadoc)
* @see javax.jmdns.NetworkTopologyEvent#getInetAddress()
*/
@Override
public InetAddress getInetAddress() {
return _inetAddress;
}
@Override
public String toString() {
StringBuilder buf = new StringBuilder();
buf.append("[" + this.getClass().getSimpleName() + "@" + System.identityHashCode(this) + " ");
buf.append("\n\tinetAddress: '");
buf.append(this.getInetAddress());
buf.append("']");
// buf.append("' source: ");
// buf.append("\n\t" + source + "");
// buf.append("\n]");
return buf.toString();
}
/*
* (non-Javadoc)
* @see java.lang.Object#clone()
*/
@Override
public NetworkTopologyEventImpl clone() throws CloneNotSupportedException {
return new NetworkTopologyEventImpl(getDNS(), getInetAddress());
}
}

View file

@ -1,124 +1,124 @@
// /Copyright 2003-2005 Arthur van Hoff, Rick Blair
// Licensed under Apache License version 2.0
// Original license LGPL
package javax.jmdns.impl;
import javax.jmdns.JmDNS;
import javax.jmdns.ServiceEvent;
import javax.jmdns.ServiceInfo;
/**
* ServiceEvent.
*
* @author Werner Randelshofer, Rick Blair
*/
/**
*
*/
public class ServiceEventImpl extends ServiceEvent {
/**
*
*/
private static final long serialVersionUID = 7107973622016897488L;
// private static Logger logger = Logger.getLogger(ServiceEvent.class.getName());
/**
* The type name of the service.
*/
private final String _type;
/**
* The instance name of the service. Or null, if the event was fired to a service type listener.
*/
private final String _name;
/**
* The service info record, or null if the service could be be resolved. This is also null, if the event was fired to a service type listener.
*/
private final ServiceInfo _info;
/**
* Creates a new instance.
*
* @param jmDNS
* the JmDNS instance which originated the event.
* @param type
* the type name of the service.
* @param name
* the instance name of the service.
* @param info
* the service info record, or null if the service could be be resolved.
*/
public ServiceEventImpl(JmDNSImpl jmDNS, String type, String name, ServiceInfo info) {
super(jmDNS);
this._type = type;
this._name = name;
this._info = info;
}
/*
* (non-Javadoc)
* @see javax.jmdns.ServiceEvent#getDNS()
*/
@Override
public JmDNS getDNS() {
return (JmDNS) getSource();
}
/*
* (non-Javadoc)
* @see javax.jmdns.ServiceEvent#getType()
*/
@Override
public String getType() {
return _type;
}
/*
* (non-Javadoc)
* @see javax.jmdns.ServiceEvent#getName()
*/
@Override
public String getName() {
return _name;
}
/*
* (non-Javadoc)
* @see java.util.EventObject#toString()
*/
@Override
public String toString() {
StringBuilder buf = new StringBuilder();
buf.append("[" + this.getClass().getSimpleName() + "@" + System.identityHashCode(this) + " ");
buf.append("\n\tname: '");
buf.append(this.getName());
buf.append("' type: '");
buf.append(this.getType());
buf.append("' info: '");
buf.append(this.getInfo());
buf.append("']");
// buf.append("' source: ");
// buf.append("\n\t" + source + "");
// buf.append("\n]");
return buf.toString();
}
/*
* (non-Javadoc)
* @see javax.jmdns.ServiceEvent#getInfo()
*/
@Override
public ServiceInfo getInfo() {
return _info;
}
/*
* (non-Javadoc)
* @see javax.jmdns.ServiceEvent#clone()
*/
@Override
public ServiceEventImpl clone() {
ServiceInfoImpl newInfo = new ServiceInfoImpl(this.getInfo());
return new ServiceEventImpl((JmDNSImpl) this.getDNS(), this.getType(), this.getName(), newInfo);
}
}
// /Copyright 2003-2005 Arthur van Hoff, Rick Blair
// Licensed under Apache License version 2.0
// Original license LGPL
package javax.jmdns.impl;
import javax.jmdns.JmDNS;
import javax.jmdns.ServiceEvent;
import javax.jmdns.ServiceInfo;
/**
* ServiceEvent.
*
* @author Werner Randelshofer, Rick Blair
*/
/**
*
*/
public class ServiceEventImpl extends ServiceEvent {
/**
*
*/
private static final long serialVersionUID = 7107973622016897488L;
// private static Logger logger = Logger.getLogger(ServiceEvent.class.getName());
/**
* The type name of the service.
*/
private final String _type;
/**
* The instance name of the service. Or null, if the event was fired to a service type listener.
*/
private final String _name;
/**
* The service info record, or null if the service could be be resolved. This is also null, if the event was fired to a service type listener.
*/
private final ServiceInfo _info;
/**
* Creates a new instance.
*
* @param jmDNS
* the JmDNS instance which originated the event.
* @param type
* the type name of the service.
* @param name
* the instance name of the service.
* @param info
* the service info record, or null if the service could be be resolved.
*/
public ServiceEventImpl(JmDNSImpl jmDNS, String type, String name, ServiceInfo info) {
super(jmDNS);
this._type = type;
this._name = name;
this._info = info;
}
/*
* (non-Javadoc)
* @see javax.jmdns.ServiceEvent#getDNS()
*/
@Override
public JmDNS getDNS() {
return (JmDNS) getSource();
}
/*
* (non-Javadoc)
* @see javax.jmdns.ServiceEvent#getType()
*/
@Override
public String getType() {
return _type;
}
/*
* (non-Javadoc)
* @see javax.jmdns.ServiceEvent#getName()
*/
@Override
public String getName() {
return _name;
}
/*
* (non-Javadoc)
* @see java.util.EventObject#toString()
*/
@Override
public String toString() {
StringBuilder buf = new StringBuilder();
buf.append("[" + this.getClass().getSimpleName() + "@" + System.identityHashCode(this) + " ");
buf.append("\n\tname: '");
buf.append(this.getName());
buf.append("' type: '");
buf.append(this.getType());
buf.append("' info: '");
buf.append(this.getInfo());
buf.append("']");
// buf.append("' source: ");
// buf.append("\n\t" + source + "");
// buf.append("\n]");
return buf.toString();
}
/*
* (non-Javadoc)
* @see javax.jmdns.ServiceEvent#getInfo()
*/
@Override
public ServiceInfo getInfo() {
return _info;
}
/*
* (non-Javadoc)
* @see javax.jmdns.ServiceEvent#clone()
*/
@Override
public ServiceEventImpl clone() {
ServiceInfoImpl newInfo = new ServiceInfoImpl(this.getInfo());
return new ServiceEventImpl((JmDNSImpl) this.getDNS(), this.getType(), this.getName(), newInfo);
}
}

View file

@ -1,87 +1,87 @@
// Copyright 2003-2005 Arthur van Hoff, Rick Blair
// Licensed under Apache License version 2.0
// Original license LGPL
package javax.jmdns.impl;
import java.io.IOException;
import java.net.DatagramPacket;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.jmdns.impl.constants.DNSConstants;
/**
* Listen for multicast packets.
*/
class SocketListener extends Thread {
static Logger logger = Logger.getLogger(SocketListener.class.getName());
/**
*
*/
private final JmDNSImpl _jmDNSImpl;
/**
* @param jmDNSImpl
*/
SocketListener(JmDNSImpl jmDNSImpl) {
super("SocketListener(" + (jmDNSImpl != null ? jmDNSImpl.getName() : "") + ")");
this.setDaemon(true);
this._jmDNSImpl = jmDNSImpl;
}
@Override
public void run() {
try {
byte buf[] = new byte[DNSConstants.MAX_MSG_ABSOLUTE];
DatagramPacket packet = new DatagramPacket(buf, buf.length);
while (!this._jmDNSImpl.isCanceling() && !this._jmDNSImpl.isCanceled()) {
packet.setLength(buf.length);
this._jmDNSImpl.getSocket().receive(packet);
if (this._jmDNSImpl.isCanceling() || this._jmDNSImpl.isCanceled() || this._jmDNSImpl.isClosing() || this._jmDNSImpl.isClosed()) {
break;
}
try {
if (this._jmDNSImpl.getLocalHost().shouldIgnorePacket(packet)) {
continue;
}
DNSIncoming msg = new DNSIncoming(packet);
if (msg.isValidResponseCode()) {
if (logger.isLoggable(Level.FINEST)) {
logger.finest(this.getName() + ".run() JmDNS in:" + msg.print(true));
}
if (msg.isQuery()) {
if (packet.getPort() != DNSConstants.MDNS_PORT) {
this._jmDNSImpl.handleQuery(msg, packet.getAddress(), packet.getPort());
}
this._jmDNSImpl.handleQuery(msg, this._jmDNSImpl.getGroup(), DNSConstants.MDNS_PORT);
} else {
this._jmDNSImpl.handleResponse(msg);
}
} else {
if (logger.isLoggable(Level.FINE)) {
logger.fine(this.getName() + ".run() JmDNS in message with error code:" + msg.print(true));
}
}
} catch (IOException e) {
logger.log(Level.WARNING, this.getName() + ".run() exception ", e);
}
}
} catch (IOException e) {
if (!this._jmDNSImpl.isCanceling() && !this._jmDNSImpl.isCanceled() && !this._jmDNSImpl.isClosing() && !this._jmDNSImpl.isClosed()) {
logger.log(Level.WARNING, this.getName() + ".run() exception ", e);
this._jmDNSImpl.recover();
}
}
if (logger.isLoggable(Level.FINEST)) {
logger.finest(this.getName() + ".run() exiting.");
}
}
public JmDNSImpl getDns() {
return _jmDNSImpl;
}
}
// Copyright 2003-2005 Arthur van Hoff, Rick Blair
// Licensed under Apache License version 2.0
// Original license LGPL
package javax.jmdns.impl;
import java.io.IOException;
import java.net.DatagramPacket;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.jmdns.impl.constants.DNSConstants;
/**
* Listen for multicast packets.
*/
class SocketListener extends Thread {
static Logger logger = Logger.getLogger(SocketListener.class.getName());
/**
*
*/
private final JmDNSImpl _jmDNSImpl;
/**
* @param jmDNSImpl
*/
SocketListener(JmDNSImpl jmDNSImpl) {
super("SocketListener(" + (jmDNSImpl != null ? jmDNSImpl.getName() : "") + ")");
this.setDaemon(true);
this._jmDNSImpl = jmDNSImpl;
}
@Override
public void run() {
try {
byte buf[] = new byte[DNSConstants.MAX_MSG_ABSOLUTE];
DatagramPacket packet = new DatagramPacket(buf, buf.length);
while (!this._jmDNSImpl.isCanceling() && !this._jmDNSImpl.isCanceled()) {
packet.setLength(buf.length);
this._jmDNSImpl.getSocket().receive(packet);
if (this._jmDNSImpl.isCanceling() || this._jmDNSImpl.isCanceled() || this._jmDNSImpl.isClosing() || this._jmDNSImpl.isClosed()) {
break;
}
try {
if (this._jmDNSImpl.getLocalHost().shouldIgnorePacket(packet)) {
continue;
}
DNSIncoming msg = new DNSIncoming(packet);
if (msg.isValidResponseCode()) {
if (logger.isLoggable(Level.FINEST)) {
logger.finest(this.getName() + ".run() JmDNS in:" + msg.print(true));
}
if (msg.isQuery()) {
if (packet.getPort() != DNSConstants.MDNS_PORT) {
this._jmDNSImpl.handleQuery(msg, packet.getAddress(), packet.getPort());
}
this._jmDNSImpl.handleQuery(msg, this._jmDNSImpl.getGroup(), DNSConstants.MDNS_PORT);
} else {
this._jmDNSImpl.handleResponse(msg);
}
} else {
if (logger.isLoggable(Level.FINE)) {
logger.fine(this.getName() + ".run() JmDNS in message with error code:" + msg.print(true));
}
}
} catch (IOException e) {
logger.log(Level.WARNING, this.getName() + ".run() exception ", e);
}
}
} catch (IOException e) {
if (!this._jmDNSImpl.isCanceling() && !this._jmDNSImpl.isCanceled() && !this._jmDNSImpl.isClosing() && !this._jmDNSImpl.isClosed()) {
logger.log(Level.WARNING, this.getName() + ".run() exception ", e);
this._jmDNSImpl.recover();
}
}
if (logger.isLoggable(Level.FINEST)) {
logger.finest(this.getName() + ".run() exiting.");
}
}
public JmDNSImpl getDns() {
return _jmDNSImpl;
}
}

View file

@ -1,62 +1,62 @@
// Copyright 2003-2005 Arthur van Hoff, Rick Blair
// Licensed under Apache License version 2.0
// Original license LGPL
package javax.jmdns.impl.constants;
/**
* DNS constants.
*
* @author Arthur van Hoff, Jeff Sonstein, Werner Randelshofer, Pierre Frisch, Rick Blair
*/
public final class DNSConstants {
// http://www.iana.org/assignments/dns-parameters
// changed to final class - jeffs
public static final String MDNS_GROUP = "224.0.0.251";
public static final String MDNS_GROUP_IPV6 = "FF02::FB";
public static final int MDNS_PORT = Integer.parseInt(System.getProperty("net.mdns.port", "5353"));
public static final int DNS_PORT = 53;
public static final int DNS_TTL = 60 * 60; // default one hour TTL
// public static final int DNS_TTL = 120 * 60; // two hour TTL (draft-cheshire-dnsext-multicastdns.txt ch 13)
public static final int MAX_MSG_TYPICAL = 1460;
public static final int MAX_MSG_ABSOLUTE = 8972;
public static final int FLAGS_QR_MASK = 0x8000; // Query response mask
public static final int FLAGS_QR_QUERY = 0x0000; // Query
public static final int FLAGS_QR_RESPONSE = 0x8000; // Response
public static final int FLAGS_OPCODE = 0x7800; // Operation code
public static final int FLAGS_AA = 0x0400; // Authorative answer
public static final int FLAGS_TC = 0x0200; // Truncated
public static final int FLAGS_RD = 0x0100; // Recursion desired
public static final int FLAGS_RA = 0x8000; // Recursion available
public static final int FLAGS_Z = 0x0040; // Zero
public static final int FLAGS_AD = 0x0020; // Authentic data
public static final int FLAGS_CD = 0x0010; // Checking disabled
public static final int FLAGS_RCODE = 0x000F; // Response code
// Time Intervals for various functions
public static final int SHARED_QUERY_TIME = 20; // milliseconds before send shared query
public static final int QUERY_WAIT_INTERVAL = 225; // milliseconds between query loops.
public static final int PROBE_WAIT_INTERVAL = 250; // milliseconds between probe loops.
public static final int RESPONSE_MIN_WAIT_INTERVAL = 20; // minimal wait interval for response.
public static final int RESPONSE_MAX_WAIT_INTERVAL = 115; // maximal wait interval for response
public static final int PROBE_CONFLICT_INTERVAL = 1000; // milliseconds to wait after conflict.
public static final int PROBE_THROTTLE_COUNT = 10; // After x tries go 1 time a sec. on probes.
public static final int PROBE_THROTTLE_COUNT_INTERVAL = 5000; // We only increment the throttle count, if the previous increment is inside this interval.
public static final int ANNOUNCE_WAIT_INTERVAL = 1000; // milliseconds between Announce loops.
public static final int RECORD_REAPER_INTERVAL = 10000; // milliseconds between cache cleanups.
public static final int RECORD_EXPIRY_DELAY = 1; // This is 1s delay used in ttl and therefore in seconds
public static final int KNOWN_ANSWER_TTL = 120;
public static final int ANNOUNCED_RENEWAL_TTL_INTERVAL = DNS_TTL * 500; // 50% of the TTL in milliseconds
public static final long CLOSE_TIMEOUT = ANNOUNCE_WAIT_INTERVAL * 5L;
public static final long SERVICE_INFO_TIMEOUT = ANNOUNCE_WAIT_INTERVAL * 6L;
public static final int NETWORK_CHECK_INTERVAL = 10 * 1000; // 10 secondes
}
// Copyright 2003-2005 Arthur van Hoff, Rick Blair
// Licensed under Apache License version 2.0
// Original license LGPL
package javax.jmdns.impl.constants;
/**
* DNS constants.
*
* @author Arthur van Hoff, Jeff Sonstein, Werner Randelshofer, Pierre Frisch, Rick Blair
*/
public final class DNSConstants {
// http://www.iana.org/assignments/dns-parameters
// changed to final class - jeffs
public static final String MDNS_GROUP = "224.0.0.251";
public static final String MDNS_GROUP_IPV6 = "FF02::FB";
public static final int MDNS_PORT = Integer.parseInt(System.getProperty("net.mdns.port", "5353"));
public static final int DNS_PORT = 53;
public static final int DNS_TTL = 60 * 60; // default one hour TTL
// public static final int DNS_TTL = 120 * 60; // two hour TTL (draft-cheshire-dnsext-multicastdns.txt ch 13)
public static final int MAX_MSG_TYPICAL = 1460;
public static final int MAX_MSG_ABSOLUTE = 8972;
public static final int FLAGS_QR_MASK = 0x8000; // Query response mask
public static final int FLAGS_QR_QUERY = 0x0000; // Query
public static final int FLAGS_QR_RESPONSE = 0x8000; // Response
public static final int FLAGS_OPCODE = 0x7800; // Operation code
public static final int FLAGS_AA = 0x0400; // Authorative answer
public static final int FLAGS_TC = 0x0200; // Truncated
public static final int FLAGS_RD = 0x0100; // Recursion desired
public static final int FLAGS_RA = 0x8000; // Recursion available
public static final int FLAGS_Z = 0x0040; // Zero
public static final int FLAGS_AD = 0x0020; // Authentic data
public static final int FLAGS_CD = 0x0010; // Checking disabled
public static final int FLAGS_RCODE = 0x000F; // Response code
// Time Intervals for various functions
public static final int SHARED_QUERY_TIME = 20; // milliseconds before send shared query
public static final int QUERY_WAIT_INTERVAL = 225; // milliseconds between query loops.
public static final int PROBE_WAIT_INTERVAL = 250; // milliseconds between probe loops.
public static final int RESPONSE_MIN_WAIT_INTERVAL = 20; // minimal wait interval for response.
public static final int RESPONSE_MAX_WAIT_INTERVAL = 115; // maximal wait interval for response
public static final int PROBE_CONFLICT_INTERVAL = 1000; // milliseconds to wait after conflict.
public static final int PROBE_THROTTLE_COUNT = 10; // After x tries go 1 time a sec. on probes.
public static final int PROBE_THROTTLE_COUNT_INTERVAL = 5000; // We only increment the throttle count, if the previous increment is inside this interval.
public static final int ANNOUNCE_WAIT_INTERVAL = 1000; // milliseconds between Announce loops.
public static final int RECORD_REAPER_INTERVAL = 10000; // milliseconds between cache cleanups.
public static final int RECORD_EXPIRY_DELAY = 1; // This is 1s delay used in ttl and therefore in seconds
public static final int KNOWN_ANSWER_TTL = 120;
public static final int ANNOUNCED_RENEWAL_TTL_INTERVAL = DNS_TTL * 500; // 50% of the TTL in milliseconds
public static final long CLOSE_TIMEOUT = ANNOUNCE_WAIT_INTERVAL * 5L;
public static final long SERVICE_INFO_TIMEOUT = ANNOUNCE_WAIT_INTERVAL * 6L;
public static final int NETWORK_CHECK_INTERVAL = 10 * 1000; // 10 secondes
}

View file

@ -1,87 +1,87 @@
/**
*
*/
package javax.jmdns.impl.constants;
/**
* DNS label.
*
* @author Arthur van Hoff, Jeff Sonstein, Werner Randelshofer, Pierre Frisch, Rick Blair
*/
public enum DNSLabel {
/**
* This is unallocated.
*/
Unknown("", 0x80),
/**
* Standard label [RFC 1035]
*/
Standard("standard label", 0x00),
/**
* Compressed label [RFC 1035]
*/
Compressed("compressed label", 0xC0),
/**
* Extended label [RFC 2671]
*/
Extended("extended label", 0x40);
/**
* DNS label types are encoded on the first 2 bits
*/
static final int LABEL_MASK = 0xC0;
static final int LABEL_NOT_MASK = 0x3F;
private final String _externalName;
private final int _index;
DNSLabel(String name, int index) {
_externalName = name;
_index = index;
}
/**
* Return the string representation of this type
*
* @return String
*/
public String externalName() {
return _externalName;
}
/**
* Return the numeric value of this type
*
* @return String
*/
public int indexValue() {
return _index;
}
/**
* @param index
* @return label
*/
public static DNSLabel labelForByte(int index) {
int maskedIndex = index & LABEL_MASK;
for (DNSLabel aLabel : DNSLabel.values()) {
if (aLabel._index == maskedIndex) return aLabel;
}
return Unknown;
}
/**
* @param index
* @return masked value
*/
public static int labelValue(int index) {
return index & LABEL_NOT_MASK;
}
@Override
public String toString() {
return this.name() + " index " + this.indexValue();
}
}
/**
*
*/
package javax.jmdns.impl.constants;
/**
* DNS label.
*
* @author Arthur van Hoff, Jeff Sonstein, Werner Randelshofer, Pierre Frisch, Rick Blair
*/
public enum DNSLabel {
/**
* This is unallocated.
*/
Unknown("", 0x80),
/**
* Standard label [RFC 1035]
*/
Standard("standard label", 0x00),
/**
* Compressed label [RFC 1035]
*/
Compressed("compressed label", 0xC0),
/**
* Extended label [RFC 2671]
*/
Extended("extended label", 0x40);
/**
* DNS label types are encoded on the first 2 bits
*/
static final int LABEL_MASK = 0xC0;
static final int LABEL_NOT_MASK = 0x3F;
private final String _externalName;
private final int _index;
DNSLabel(String name, int index) {
_externalName = name;
_index = index;
}
/**
* Return the string representation of this type
*
* @return String
*/
public String externalName() {
return _externalName;
}
/**
* Return the numeric value of this type
*
* @return String
*/
public int indexValue() {
return _index;
}
/**
* @param index
* @return label
*/
public static DNSLabel labelForByte(int index) {
int maskedIndex = index & LABEL_MASK;
for (DNSLabel aLabel : DNSLabel.values()) {
if (aLabel._index == maskedIndex) return aLabel;
}
return Unknown;
}
/**
* @param index
* @return masked value
*/
public static int labelValue(int index) {
return index & LABEL_NOT_MASK;
}
@Override
public String toString() {
return this.name() + " index " + this.indexValue();
}
}

View file

@ -1,86 +1,86 @@
/**
*
*/
package javax.jmdns.impl.constants;
/**
* DNS operation code.
*
* @author Arthur van Hoff, Jeff Sonstein, Werner Randelshofer, Pierre Frisch, Rick Blair
*/
public enum DNSOperationCode {
/**
* Query [RFC1035]
*/
Query("Query", 0),
/**
* IQuery (Inverse Query, Obsolete) [RFC3425]
*/
IQuery("Inverse Query", 1),
/**
* Status [RFC1035]
*/
Status("Status", 2),
/**
* Unassigned
*/
Unassigned("Unassigned", 3),
/**
* Notify [RFC1996]
*/
Notify("Notify", 4),
/**
* Update [RFC2136]
*/
Update("Update", 5);
/**
* DNS RCode types are encoded on the last 4 bits
*/
static final int OpCode_MASK = 0x7800;
private final String _externalName;
private final int _index;
DNSOperationCode(String name, int index) {
_externalName = name;
_index = index;
}
/**
* Return the string representation of this type
*
* @return String
*/
public String externalName() {
return _externalName;
}
/**
* Return the numeric value of this type
*
* @return String
*/
public int indexValue() {
return _index;
}
/**
* @param flags
* @return label
*/
public static DNSOperationCode operationCodeForFlags(int flags) {
int maskedIndex = (flags & OpCode_MASK) >> 11;
for (DNSOperationCode aCode : DNSOperationCode.values()) {
if (aCode._index == maskedIndex) return aCode;
}
return Unassigned;
}
@Override
public String toString() {
return this.name() + " index " + this.indexValue();
}
}
/**
*
*/
package javax.jmdns.impl.constants;
/**
* DNS operation code.
*
* @author Arthur van Hoff, Jeff Sonstein, Werner Randelshofer, Pierre Frisch, Rick Blair
*/
public enum DNSOperationCode {
/**
* Query [RFC1035]
*/
Query("Query", 0),
/**
* IQuery (Inverse Query, Obsolete) [RFC3425]
*/
IQuery("Inverse Query", 1),
/**
* Status [RFC1035]
*/
Status("Status", 2),
/**
* Unassigned
*/
Unassigned("Unassigned", 3),
/**
* Notify [RFC1996]
*/
Notify("Notify", 4),
/**
* Update [RFC2136]
*/
Update("Update", 5);
/**
* DNS RCode types are encoded on the last 4 bits
*/
static final int OpCode_MASK = 0x7800;
private final String _externalName;
private final int _index;
DNSOperationCode(String name, int index) {
_externalName = name;
_index = index;
}
/**
* Return the string representation of this type
*
* @return String
*/
public String externalName() {
return _externalName;
}
/**
* Return the numeric value of this type
*
* @return String
*/
public int indexValue() {
return _index;
}
/**
* @param flags
* @return label
*/
public static DNSOperationCode operationCodeForFlags(int flags) {
int maskedIndex = (flags & OpCode_MASK) >> 11;
for (DNSOperationCode aCode : DNSOperationCode.values()) {
if (aCode._index == maskedIndex) return aCode;
}
return Unassigned;
}
@Override
public String toString() {
return this.name() + " index " + this.indexValue();
}
}

View file

@ -1,78 +1,78 @@
/**
*
*/
package javax.jmdns.impl.constants;
/**
* DNS option code.
*
* @author Arthur van Hoff, Pierre Frisch, Rick Blair
*/
public enum DNSOptionCode {
/**
* Token
*/
Unknown("Unknown", 65535),
/**
* Long-Lived Queries Option [http://files.dns-sd.org/draft-sekar-dns-llq.txt]
*/
LLQ("LLQ", 1),
/**
* Update Leases Option [http://files.dns-sd.org/draft-sekar-dns-ul.txt]
*/
UL("UL", 2),
/**
* Name Server Identifier Option [RFC5001]
*/
NSID("NSID", 3),
/**
* Owner Option [draft-cheshire-edns0-owner-option]
*/
Owner("Owner", 4);
private final String _externalName;
private final int _index;
DNSOptionCode(String name, int index) {
_externalName = name;
_index = index;
}
/**
* Return the string representation of this type
*
* @return String
*/
public String externalName() {
return _externalName;
}
/**
* Return the numeric value of this type
*
* @return String
*/
public int indexValue() {
return _index;
}
/**
* @param optioncode
* @return label
*/
public static DNSOptionCode resultCodeForFlags(int optioncode) {
int maskedIndex = optioncode;
for (DNSOptionCode aCode : DNSOptionCode.values()) {
if (aCode._index == maskedIndex) return aCode;
}
return Unknown;
}
@Override
public String toString() {
return this.name() + " index " + this.indexValue();
}
}
/**
*
*/
package javax.jmdns.impl.constants;
/**
* DNS option code.
*
* @author Arthur van Hoff, Pierre Frisch, Rick Blair
*/
public enum DNSOptionCode {
/**
* Token
*/
Unknown("Unknown", 65535),
/**
* Long-Lived Queries Option [http://files.dns-sd.org/draft-sekar-dns-llq.txt]
*/
LLQ("LLQ", 1),
/**
* Update Leases Option [http://files.dns-sd.org/draft-sekar-dns-ul.txt]
*/
UL("UL", 2),
/**
* Name Server Identifier Option [RFC5001]
*/
NSID("NSID", 3),
/**
* Owner Option [draft-cheshire-edns0-owner-option]
*/
Owner("Owner", 4);
private final String _externalName;
private final int _index;
DNSOptionCode(String name, int index) {
_externalName = name;
_index = index;
}
/**
* Return the string representation of this type
*
* @return String
*/
public String externalName() {
return _externalName;
}
/**
* Return the numeric value of this type
*
* @return String
*/
public int indexValue() {
return _index;
}
/**
* @param optioncode
* @return label
*/
public static DNSOptionCode resultCodeForFlags(int optioncode) {
int maskedIndex = optioncode;
for (DNSOptionCode aCode : DNSOptionCode.values()) {
if (aCode._index == maskedIndex) return aCode;
}
return Unknown;
}
@Override
public String toString() {
return this.name() + " index " + this.indexValue();
}
}

View file

@ -1,138 +1,138 @@
/**
*
*/
package javax.jmdns.impl.constants;
import java.util.logging.Level;
import java.util.logging.Logger;
/**
* DNS Record Class
*
* @author Arthur van Hoff, Jeff Sonstein, Werner Randelshofer, Pierre Frisch, Rick Blair
*/
public enum DNSRecordClass {
/**
*
*/
CLASS_UNKNOWN("?", 0),
/**
* static final Internet
*/
CLASS_IN("in", 1),
/**
* CSNET
*/
CLASS_CS("cs", 2),
/**
* CHAOS
*/
CLASS_CH("ch", 3),
/**
* Hesiod
*/
CLASS_HS("hs", 4),
/**
* Used in DNS UPDATE [RFC 2136]
*/
CLASS_NONE("none", 254),
/**
* Not a DNS class, but a DNS query class, meaning "all classes"
*/
CLASS_ANY("any", 255);
private static Logger logger = Logger.getLogger(DNSRecordClass.class.getName());
/**
* Multicast DNS uses the bottom 15 bits to identify the record class...<br/>
* Except for pseudo records like OPT.
*/
public static final int CLASS_MASK = 0x7FFF;
/**
* For answers the top bit indicates that all other cached records are now invalid.<br/>
* For questions it indicates that we should send a unicast response.
*/
public static final int CLASS_UNIQUE = 0x8000;
/**
*
*/
public static final boolean UNIQUE = true;
/**
*
*/
public static final boolean NOT_UNIQUE = false;
private final String _externalName;
private final int _index;
DNSRecordClass(String name, int index) {
_externalName = name;
_index = index;
}
/**
* Return the string representation of this type
*
* @return String
*/
public String externalName() {
return _externalName;
}
/**
* Return the numeric value of this type
*
* @return String
*/
public int indexValue() {
return _index;
}
/**
* Checks if the class is unique
*
* @param index
* @return <code>true</code> is the class is unique, <code>false</code> otherwise.
*/
public boolean isUnique(int index) {
return (this != CLASS_UNKNOWN) && ((index & CLASS_UNIQUE) != 0);
}
/**
* @param name
* @return class for name
*/
public static DNSRecordClass classForName(String name) {
if (name != null) {
String aName = name.toLowerCase();
for (DNSRecordClass aClass : DNSRecordClass.values()) {
if (aClass._externalName.equals(aName)) return aClass;
}
}
logger.log(Level.WARNING, "Could not find record class for name: " + name);
return CLASS_UNKNOWN;
}
/**
* @param index
* @return class for name
*/
public static DNSRecordClass classForIndex(int index) {
int maskedIndex = index & CLASS_MASK;
for (DNSRecordClass aClass : DNSRecordClass.values()) {
if (aClass._index == maskedIndex) return aClass;
}
logger.log(Level.WARNING, "Could not find record class for index: " + index);
return CLASS_UNKNOWN;
}
@Override
public String toString() {
return this.name() + " index " + this.indexValue();
}
}
/**
*
*/
package javax.jmdns.impl.constants;
import java.util.logging.Level;
import java.util.logging.Logger;
/**
* DNS Record Class
*
* @author Arthur van Hoff, Jeff Sonstein, Werner Randelshofer, Pierre Frisch, Rick Blair
*/
public enum DNSRecordClass {
/**
*
*/
CLASS_UNKNOWN("?", 0),
/**
* static final Internet
*/
CLASS_IN("in", 1),
/**
* CSNET
*/
CLASS_CS("cs", 2),
/**
* CHAOS
*/
CLASS_CH("ch", 3),
/**
* Hesiod
*/
CLASS_HS("hs", 4),
/**
* Used in DNS UPDATE [RFC 2136]
*/
CLASS_NONE("none", 254),
/**
* Not a DNS class, but a DNS query class, meaning "all classes"
*/
CLASS_ANY("any", 255);
private static Logger logger = Logger.getLogger(DNSRecordClass.class.getName());
/**
* Multicast DNS uses the bottom 15 bits to identify the record class...<br/>
* Except for pseudo records like OPT.
*/
public static final int CLASS_MASK = 0x7FFF;
/**
* For answers the top bit indicates that all other cached records are now invalid.<br/>
* For questions it indicates that we should send a unicast response.
*/
public static final int CLASS_UNIQUE = 0x8000;
/**
*
*/
public static final boolean UNIQUE = true;
/**
*
*/
public static final boolean NOT_UNIQUE = false;
private final String _externalName;
private final int _index;
DNSRecordClass(String name, int index) {
_externalName = name;
_index = index;
}
/**
* Return the string representation of this type
*
* @return String
*/
public String externalName() {
return _externalName;
}
/**
* Return the numeric value of this type
*
* @return String
*/
public int indexValue() {
return _index;
}
/**
* Checks if the class is unique
*
* @param index
* @return <code>true</code> is the class is unique, <code>false</code> otherwise.
*/
public boolean isUnique(int index) {
return (this != CLASS_UNKNOWN) && ((index & CLASS_UNIQUE) != 0);
}
/**
* @param name
* @return class for name
*/
public static DNSRecordClass classForName(String name) {
if (name != null) {
String aName = name.toLowerCase();
for (DNSRecordClass aClass : DNSRecordClass.values()) {
if (aClass._externalName.equals(aName)) return aClass;
}
}
logger.log(Level.WARNING, "Could not find record class for name: " + name);
return CLASS_UNKNOWN;
}
/**
* @param index
* @return class for name
*/
public static DNSRecordClass classForIndex(int index) {
int maskedIndex = index & CLASS_MASK;
for (DNSRecordClass aClass : DNSRecordClass.values()) {
if (aClass._index == maskedIndex) return aClass;
}
logger.log(Level.WARNING, "Could not find record class for index: " + index);
return CLASS_UNKNOWN;
}
@Override
public String toString() {
return this.name() + " index " + this.indexValue();
}
}

View file

@ -1,312 +1,312 @@
/**
*
*/
package javax.jmdns.impl.constants;
import java.util.logging.Logger;
/**
* DNS Record Type
*
* @author Arthur van Hoff, Jeff Sonstein, Werner Randelshofer, Pierre Frisch, Rick Blair
*/
public enum DNSRecordType {
/**
* Address
*/
TYPE_IGNORE("ignore", 0),
/**
* Address
*/
TYPE_A("a", 1),
/**
* Name Server
*/
TYPE_NS("ns", 2),
/**
* Mail Destination
*/
TYPE_MD("md", 3),
/**
* Mail Forwarder
*/
TYPE_MF("mf", 4),
/**
* Canonical Name
*/
TYPE_CNAME("cname", 5),
/**
* Start of Authority
*/
TYPE_SOA("soa", 6),
/**
* Mailbox
*/
TYPE_MB("mb", 7),
/**
* Mail Group
*/
TYPE_MG("mg", 8),
/**
* Mail Rename
*/
TYPE_MR("mr", 9),
/**
* NULL RR
*/
TYPE_NULL("null", 10),
/**
* Well-known-service
*/
TYPE_WKS("wks", 11),
/**
* Domain Name pointer
*/
TYPE_PTR("ptr", 12),
/**
* Host information
*/
TYPE_HINFO("hinfo", 13),
/**
* Mailbox information
*/
TYPE_MINFO("minfo", 14),
/**
* Mail exchanger
*/
TYPE_MX("mx", 15),
/**
* Arbitrary text string
*/
TYPE_TXT("txt", 16),
/**
* for Responsible Person [RFC1183]
*/
TYPE_RP("rp", 17),
/**
* for AFS Data Base location [RFC1183]
*/
TYPE_AFSDB("afsdb", 18),
/**
* for X.25 PSDN address [RFC1183]
*/
TYPE_X25("x25", 19),
/**
* for ISDN address [RFC1183]
*/
TYPE_ISDN("isdn", 20),
/**
* for Route Through [RFC1183]
*/
TYPE_RT("rt", 21),
/**
* for NSAP address, NSAP style A record [RFC1706]
*/
TYPE_NSAP("nsap", 22),
/**
*
*/
TYPE_NSAP_PTR("nsap-otr", 23),
/**
* for security signature [RFC2931]
*/
TYPE_SIG("sig", 24),
/**
* for security key [RFC2535]
*/
TYPE_KEY("key", 25),
/**
* X.400 mail mapping information [RFC2163]
*/
TYPE_PX("px", 26),
/**
* Geographical Position [RFC1712]
*/
TYPE_GPOS("gpos", 27),
/**
* IP6 Address [Thomson]
*/
TYPE_AAAA("aaaa", 28),
/**
* Location Information [Vixie]
*/
TYPE_LOC("loc", 29),
/**
* Next Domain - OBSOLETE [RFC2535, RFC3755]
*/
TYPE_NXT("nxt", 30),
/**
* Endpoint Identifier [Patton]
*/
TYPE_EID("eid", 31),
/**
* Nimrod Locator [Patton]
*/
TYPE_NIMLOC("nimloc", 32),
/**
* Server Selection [RFC2782]
*/
TYPE_SRV("srv", 33),
/**
* ATM Address [Dobrowski]
*/
TYPE_ATMA("atma", 34),
/**
* Naming Authority Pointer [RFC2168, RFC2915]
*/
TYPE_NAPTR("naptr", 35),
/**
* Key Exchanger [RFC2230]
*/
TYPE_KX("kx", 36),
/**
* CERT [RFC2538]
*/
TYPE_CERT("cert", 37),
/**
* A6 [RFC2874]
*/
TYPE_A6("a6", 38),
/**
* DNAME [RFC2672]
*/
TYPE_DNAME("dname", 39),
/**
* SINK [Eastlake]
*/
TYPE_SINK("sink", 40),
/**
* OPT [RFC2671]
*/
TYPE_OPT("opt", 41),
/**
* APL [RFC3123]
*/
TYPE_APL("apl", 42),
/**
* Delegation Signer [RFC3658]
*/
TYPE_DS("ds", 43),
/**
* SSH Key Fingerprint [RFC-ietf-secsh-dns-05.txt]
*/
TYPE_SSHFP("sshfp", 44),
/**
* RRSIG [RFC3755]
*/
TYPE_RRSIG("rrsig", 46),
/**
* NSEC [RFC3755]
*/
TYPE_NSEC("nsec", 47),
/**
* DNSKEY [RFC3755]
*/
TYPE_DNSKEY("dnskey", 48),
/**
* [IANA-Reserved]
*/
TYPE_UINFO("uinfo", 100),
/**
* [IANA-Reserved]
*/
TYPE_UID("uid", 101),
/**
* [IANA-Reserved]
*/
TYPE_GID("gid", 102),
/**
* [IANA-Reserved]
*/
TYPE_UNSPEC("unspec", 103),
/**
* Transaction Key [RFC2930]
*/
TYPE_TKEY("tkey", 249),
/**
* Transaction Signature [RFC2845]
*/
TYPE_TSIG("tsig", 250),
/**
* Incremental transfer [RFC1995]
*/
TYPE_IXFR("ixfr", 251),
/**
* Transfer of an entire zone [RFC1035]
*/
TYPE_AXFR("axfr", 252),
/**
* Mailbox-related records (MB, MG or MR) [RFC1035]
*/
TYPE_MAILA("mails", 253),
/**
* Mail agent RRs (Obsolete - see MX) [RFC1035]
*/
TYPE_MAILB("mailb", 254),
/**
* Request for all records [RFC1035]
*/
TYPE_ANY("any", 255);
private static Logger logger = Logger.getLogger(DNSRecordType.class.getName());
private final String _externalName;
private final int _index;
DNSRecordType(String name, int index) {
_externalName = name;
_index = index;
}
/**
* Return the string representation of this type
*
* @return String
*/
public String externalName() {
return _externalName;
}
/**
* Return the numeric value of this type
*
* @return String
*/
public int indexValue() {
return _index;
}
/**
* @param name
* @return type for name
*/
public static DNSRecordType typeForName(String name) {
if (name != null) {
String aName = name.toLowerCase();
for (DNSRecordType aType : DNSRecordType.values()) {
if (aType._externalName.equals(aName)) return aType;
}
}
logger.severe("Could not find record type for name: " + name);
return TYPE_IGNORE;
}
/**
* @param index
* @return type for name
*/
public static DNSRecordType typeForIndex(int index) {
for (DNSRecordType aType : DNSRecordType.values()) {
if (aType._index == index) return aType;
}
logger.severe("Could not find record type for index: " + index);
return TYPE_IGNORE;
}
@Override
public String toString() {
return this.name() + " index " + this.indexValue();
}
}
/**
*
*/
package javax.jmdns.impl.constants;
import java.util.logging.Logger;
/**
* DNS Record Type
*
* @author Arthur van Hoff, Jeff Sonstein, Werner Randelshofer, Pierre Frisch, Rick Blair
*/
public enum DNSRecordType {
/**
* Address
*/
TYPE_IGNORE("ignore", 0),
/**
* Address
*/
TYPE_A("a", 1),
/**
* Name Server
*/
TYPE_NS("ns", 2),
/**
* Mail Destination
*/
TYPE_MD("md", 3),
/**
* Mail Forwarder
*/
TYPE_MF("mf", 4),
/**
* Canonical Name
*/
TYPE_CNAME("cname", 5),
/**
* Start of Authority
*/
TYPE_SOA("soa", 6),
/**
* Mailbox
*/
TYPE_MB("mb", 7),
/**
* Mail Group
*/
TYPE_MG("mg", 8),
/**
* Mail Rename
*/
TYPE_MR("mr", 9),
/**
* NULL RR
*/
TYPE_NULL("null", 10),
/**
* Well-known-service
*/
TYPE_WKS("wks", 11),
/**
* Domain Name pointer
*/
TYPE_PTR("ptr", 12),
/**
* Host information
*/
TYPE_HINFO("hinfo", 13),
/**
* Mailbox information
*/
TYPE_MINFO("minfo", 14),
/**
* Mail exchanger
*/
TYPE_MX("mx", 15),
/**
* Arbitrary text string
*/
TYPE_TXT("txt", 16),
/**
* for Responsible Person [RFC1183]
*/
TYPE_RP("rp", 17),
/**
* for AFS Data Base location [RFC1183]
*/
TYPE_AFSDB("afsdb", 18),
/**
* for X.25 PSDN address [RFC1183]
*/
TYPE_X25("x25", 19),
/**
* for ISDN address [RFC1183]
*/
TYPE_ISDN("isdn", 20),
/**
* for Route Through [RFC1183]
*/
TYPE_RT("rt", 21),
/**
* for NSAP address, NSAP style A record [RFC1706]
*/
TYPE_NSAP("nsap", 22),
/**
*
*/
TYPE_NSAP_PTR("nsap-otr", 23),
/**
* for security signature [RFC2931]
*/
TYPE_SIG("sig", 24),
/**
* for security key [RFC2535]
*/
TYPE_KEY("key", 25),
/**
* X.400 mail mapping information [RFC2163]
*/
TYPE_PX("px", 26),
/**
* Geographical Position [RFC1712]
*/
TYPE_GPOS("gpos", 27),
/**
* IP6 Address [Thomson]
*/
TYPE_AAAA("aaaa", 28),
/**
* Location Information [Vixie]
*/
TYPE_LOC("loc", 29),
/**
* Next Domain - OBSOLETE [RFC2535, RFC3755]
*/
TYPE_NXT("nxt", 30),
/**
* Endpoint Identifier [Patton]
*/
TYPE_EID("eid", 31),
/**
* Nimrod Locator [Patton]
*/
TYPE_NIMLOC("nimloc", 32),
/**
* Server Selection [RFC2782]
*/
TYPE_SRV("srv", 33),
/**
* ATM Address [Dobrowski]
*/
TYPE_ATMA("atma", 34),
/**
* Naming Authority Pointer [RFC2168, RFC2915]
*/
TYPE_NAPTR("naptr", 35),
/**
* Key Exchanger [RFC2230]
*/
TYPE_KX("kx", 36),
/**
* CERT [RFC2538]
*/
TYPE_CERT("cert", 37),
/**
* A6 [RFC2874]
*/
TYPE_A6("a6", 38),
/**
* DNAME [RFC2672]
*/
TYPE_DNAME("dname", 39),
/**
* SINK [Eastlake]
*/
TYPE_SINK("sink", 40),
/**
* OPT [RFC2671]
*/
TYPE_OPT("opt", 41),
/**
* APL [RFC3123]
*/
TYPE_APL("apl", 42),
/**
* Delegation Signer [RFC3658]
*/
TYPE_DS("ds", 43),
/**
* SSH Key Fingerprint [RFC-ietf-secsh-dns-05.txt]
*/
TYPE_SSHFP("sshfp", 44),
/**
* RRSIG [RFC3755]
*/
TYPE_RRSIG("rrsig", 46),
/**
* NSEC [RFC3755]
*/
TYPE_NSEC("nsec", 47),
/**
* DNSKEY [RFC3755]
*/
TYPE_DNSKEY("dnskey", 48),
/**
* [IANA-Reserved]
*/
TYPE_UINFO("uinfo", 100),
/**
* [IANA-Reserved]
*/
TYPE_UID("uid", 101),
/**
* [IANA-Reserved]
*/
TYPE_GID("gid", 102),
/**
* [IANA-Reserved]
*/
TYPE_UNSPEC("unspec", 103),
/**
* Transaction Key [RFC2930]
*/
TYPE_TKEY("tkey", 249),
/**
* Transaction Signature [RFC2845]
*/
TYPE_TSIG("tsig", 250),
/**
* Incremental transfer [RFC1995]
*/
TYPE_IXFR("ixfr", 251),
/**
* Transfer of an entire zone [RFC1035]
*/
TYPE_AXFR("axfr", 252),
/**
* Mailbox-related records (MB, MG or MR) [RFC1035]
*/
TYPE_MAILA("mails", 253),
/**
* Mail agent RRs (Obsolete - see MX) [RFC1035]
*/
TYPE_MAILB("mailb", 254),
/**
* Request for all records [RFC1035]
*/
TYPE_ANY("any", 255);
private static Logger logger = Logger.getLogger(DNSRecordType.class.getName());
private final String _externalName;
private final int _index;
DNSRecordType(String name, int index) {
_externalName = name;
_index = index;
}
/**
* Return the string representation of this type
*
* @return String
*/
public String externalName() {
return _externalName;
}
/**
* Return the numeric value of this type
*
* @return String
*/
public int indexValue() {
return _index;
}
/**
* @param name
* @return type for name
*/
public static DNSRecordType typeForName(String name) {
if (name != null) {
String aName = name.toLowerCase();
for (DNSRecordType aType : DNSRecordType.values()) {
if (aType._externalName.equals(aName)) return aType;
}
}
logger.severe("Could not find record type for name: " + name);
return TYPE_IGNORE;
}
/**
* @param index
* @return type for name
*/
public static DNSRecordType typeForIndex(int index) {
for (DNSRecordType aType : DNSRecordType.values()) {
if (aType._index == index) return aType;
}
logger.severe("Could not find record type for index: " + index);
return TYPE_IGNORE;
}
@Override
public String toString() {
return this.name() + " index " + this.indexValue();
}
}

View file

@ -1,149 +1,149 @@
/**
*
*/
package javax.jmdns.impl.constants;
/**
* DNS result code.
*
* @author Arthur van Hoff, Jeff Sonstein, Werner Randelshofer, Pierre Frisch, Rick Blair
*/
public enum DNSResultCode {
/**
* Token
*/
Unknown("Unknown", 65535),
/**
* No Error [RFC1035]
*/
NoError("No Error", 0),
/**
* Format Error [RFC1035]
*/
FormErr("Format Error", 1),
/**
* Server Failure [RFC1035]
*/
ServFail("Server Failure", 2),
/**
* Non-Existent Domain [RFC1035]
*/
NXDomain("Non-Existent Domain", 3),
/**
* Not Implemented [RFC1035]
*/
NotImp("Not Implemented", 4),
/**
* Query Refused [RFC1035]
*/
Refused("Query Refused", 5),
/**
* Name Exists when it should not [RFC2136]
*/
YXDomain("Name Exists when it should not", 6),
/**
* RR Set Exists when it should not [RFC2136]
*/
YXRRSet("RR Set Exists when it should not", 7),
/**
* RR Set that should exist does not [RFC2136]
*/
NXRRSet("RR Set that should exist does not", 8),
/**
* Server Not Authoritative for zone [RFC2136]]
*/
NotAuth("Server Not Authoritative for zone", 9),
/**
* Name not contained in zone [RFC2136]
*/
NotZone("NotZone Name not contained in zone", 10),
;
// 0 NoError No Error [RFC1035]
// 1 FormErr Format Error [RFC1035]
// 2 ServFail Server Failure [RFC1035]
// 3 NXDomain Non-Existent Domain [RFC1035]
// 4 NotImp Not Implemented [RFC1035]
// 5 Refused Query Refused [RFC1035]
// 6 YXDomain Name Exists when it should not [RFC2136]
// 7 YXRRSet RR Set Exists when it should not [RFC2136]
// 8 NXRRSet RR Set that should exist does not [RFC2136]
// 9 NotAuth Server Not Authoritative for zone [RFC2136]
// 10 NotZone Name not contained in zone [RFC2136]
// 11-15 Unassigned
// 16 BADVERS Bad OPT Version [RFC2671]
// 16 BADSIG TSIG Signature Failure [RFC2845]
// 17 BADKEY Key not recognized [RFC2845]
// 18 BADTIME Signature out of time window [RFC2845]
// 19 BADMODE Bad TKEY Mode [RFC2930]
// 20 BADNAME Duplicate key name [RFC2930]
// 21 BADALG Algorithm not supported [RFC2930]
// 22 BADTRUNC Bad Truncation [RFC4635]
// 23-3840 Unassigned
// 3841-4095 Reserved for Private Use [RFC5395]
// 4096-65534 Unassigned
// 65535 Reserved, can be allocated by Standards Action [RFC5395]
/**
* DNS Result Code types are encoded on the last 4 bits
*/
final static int RCode_MASK = 0x0F;
/**
* DNS Extended Result Code types are encoded on the first 8 bits
*/
final static int ExtendedRCode_MASK = 0xFF;
private final String _externalName;
private final int _index;
DNSResultCode(String name, int index) {
_externalName = name;
_index = index;
}
/**
* Return the string representation of this type
*
* @return String
*/
public String externalName() {
return _externalName;
}
/**
* Return the numeric value of this type
*
* @return String
*/
public int indexValue() {
return _index;
}
/**
* @param flags
* @return label
*/
public static DNSResultCode resultCodeForFlags(int flags) {
int maskedIndex = flags & RCode_MASK;
for (DNSResultCode aCode : DNSResultCode.values()) {
if (aCode._index == maskedIndex) return aCode;
}
return Unknown;
}
public static DNSResultCode resultCodeForFlags(int flags, int extendedRCode) {
int maskedIndex = ((extendedRCode >> 28) & ExtendedRCode_MASK) | (flags & RCode_MASK);
for (DNSResultCode aCode : DNSResultCode.values()) {
if (aCode._index == maskedIndex) return aCode;
}
return Unknown;
}
@Override
public String toString() {
return this.name() + " index " + this.indexValue();
}
}
/**
*
*/
package javax.jmdns.impl.constants;
/**
* DNS result code.
*
* @author Arthur van Hoff, Jeff Sonstein, Werner Randelshofer, Pierre Frisch, Rick Blair
*/
public enum DNSResultCode {
/**
* Token
*/
Unknown("Unknown", 65535),
/**
* No Error [RFC1035]
*/
NoError("No Error", 0),
/**
* Format Error [RFC1035]
*/
FormErr("Format Error", 1),
/**
* Server Failure [RFC1035]
*/
ServFail("Server Failure", 2),
/**
* Non-Existent Domain [RFC1035]
*/
NXDomain("Non-Existent Domain", 3),
/**
* Not Implemented [RFC1035]
*/
NotImp("Not Implemented", 4),
/**
* Query Refused [RFC1035]
*/
Refused("Query Refused", 5),
/**
* Name Exists when it should not [RFC2136]
*/
YXDomain("Name Exists when it should not", 6),
/**
* RR Set Exists when it should not [RFC2136]
*/
YXRRSet("RR Set Exists when it should not", 7),
/**
* RR Set that should exist does not [RFC2136]
*/
NXRRSet("RR Set that should exist does not", 8),
/**
* Server Not Authoritative for zone [RFC2136]]
*/
NotAuth("Server Not Authoritative for zone", 9),
/**
* Name not contained in zone [RFC2136]
*/
NotZone("NotZone Name not contained in zone", 10),
;
// 0 NoError No Error [RFC1035]
// 1 FormErr Format Error [RFC1035]
// 2 ServFail Server Failure [RFC1035]
// 3 NXDomain Non-Existent Domain [RFC1035]
// 4 NotImp Not Implemented [RFC1035]
// 5 Refused Query Refused [RFC1035]
// 6 YXDomain Name Exists when it should not [RFC2136]
// 7 YXRRSet RR Set Exists when it should not [RFC2136]
// 8 NXRRSet RR Set that should exist does not [RFC2136]
// 9 NotAuth Server Not Authoritative for zone [RFC2136]
// 10 NotZone Name not contained in zone [RFC2136]
// 11-15 Unassigned
// 16 BADVERS Bad OPT Version [RFC2671]
// 16 BADSIG TSIG Signature Failure [RFC2845]
// 17 BADKEY Key not recognized [RFC2845]
// 18 BADTIME Signature out of time window [RFC2845]
// 19 BADMODE Bad TKEY Mode [RFC2930]
// 20 BADNAME Duplicate key name [RFC2930]
// 21 BADALG Algorithm not supported [RFC2930]
// 22 BADTRUNC Bad Truncation [RFC4635]
// 23-3840 Unassigned
// 3841-4095 Reserved for Private Use [RFC5395]
// 4096-65534 Unassigned
// 65535 Reserved, can be allocated by Standards Action [RFC5395]
/**
* DNS Result Code types are encoded on the last 4 bits
*/
final static int RCode_MASK = 0x0F;
/**
* DNS Extended Result Code types are encoded on the first 8 bits
*/
final static int ExtendedRCode_MASK = 0xFF;
private final String _externalName;
private final int _index;
DNSResultCode(String name, int index) {
_externalName = name;
_index = index;
}
/**
* Return the string representation of this type
*
* @return String
*/
public String externalName() {
return _externalName;
}
/**
* Return the numeric value of this type
*
* @return String
*/
public int indexValue() {
return _index;
}
/**
* @param flags
* @return label
*/
public static DNSResultCode resultCodeForFlags(int flags) {
int maskedIndex = flags & RCode_MASK;
for (DNSResultCode aCode : DNSResultCode.values()) {
if (aCode._index == maskedIndex) return aCode;
}
return Unknown;
}
public static DNSResultCode resultCodeForFlags(int flags, int extendedRCode) {
int maskedIndex = ((extendedRCode >> 28) & ExtendedRCode_MASK) | (flags & RCode_MASK);
for (DNSResultCode aCode : DNSResultCode.values()) {
if (aCode._index == maskedIndex) return aCode;
}
return Unknown;
}
@Override
public String toString() {
return this.name() + " index " + this.indexValue();
}
}

View file

@ -1,215 +1,215 @@
// Copyright 2003-2005 Arthur van Hoff, Rick Blair
// Licensed under Apache License version 2.0
// Original license LGPL
package javax.jmdns.impl.constants;
/**
* DNSState defines the possible states for services registered with JmDNS.
*
* @author Werner Randelshofer, Rick Blair, Pierre Frisch
*/
public enum DNSState {
/**
*
*/
PROBING_1("probing 1", StateClass.probing),
/**
*
*/
PROBING_2("probing 2", StateClass.probing),
/**
*
*/
PROBING_3("probing 3", StateClass.probing),
/**
*
*/
ANNOUNCING_1("announcing 1", StateClass.announcing),
/**
*
*/
ANNOUNCING_2("announcing 2", StateClass.announcing),
/**
*
*/
ANNOUNCED("announced", StateClass.announced),
/**
*
*/
CANCELING_1("canceling 1", StateClass.canceling),
/**
*
*/
CANCELING_2("canceling 2", StateClass.canceling),
/**
*
*/
CANCELING_3("canceling 3", StateClass.canceling),
/**
*
*/
CANCELED("canceled", StateClass.canceled),
/**
*
*/
CLOSING("closing", StateClass.closing),
/**
*
*/
CLOSED("closed", StateClass.closed);
private enum StateClass {
probing, announcing, announced, canceling, canceled, closing, closed
}
// private static Logger logger = Logger.getLogger(DNSState.class.getName());
private final String _name;
private final StateClass _state;
private DNSState(String name, StateClass state) {
_name = name;
_state = state;
}
@Override
public final String toString() {
return _name;
}
/**
* Returns the next advanced state.<br/>
* In general, this advances one step in the following sequence: PROBING_1, PROBING_2, PROBING_3, ANNOUNCING_1, ANNOUNCING_2, ANNOUNCED.<br/>
* or CANCELING_1, CANCELING_2, CANCELING_3, CANCELED Does not advance for ANNOUNCED and CANCELED state.
*
* @return next state
*/
public final DNSState advance() {
switch (this) {
case PROBING_1:
return PROBING_2;
case PROBING_2:
return PROBING_3;
case PROBING_3:
return ANNOUNCING_1;
case ANNOUNCING_1:
return ANNOUNCING_2;
case ANNOUNCING_2:
return ANNOUNCED;
case ANNOUNCED:
return ANNOUNCED;
case CANCELING_1:
return CANCELING_2;
case CANCELING_2:
return CANCELING_3;
case CANCELING_3:
return CANCELED;
case CANCELED:
return CANCELED;
case CLOSING:
return CLOSED;
case CLOSED:
return CLOSED;
default:
// This is just to keep the compiler happy as we have covered all cases before.
return this;
}
}
/**
* Returns to the next reverted state. All states except CANCELED revert to PROBING_1. Status CANCELED does not revert.
*
* @return reverted state
*/
public final DNSState revert() {
switch (this) {
case PROBING_1:
case PROBING_2:
case PROBING_3:
case ANNOUNCING_1:
case ANNOUNCING_2:
case ANNOUNCED:
return PROBING_1;
case CANCELING_1:
case CANCELING_2:
case CANCELING_3:
return CANCELING_1;
case CANCELED:
return CANCELED;
case CLOSING:
return CLOSING;
case CLOSED:
return CLOSED;
default:
// This is just to keep the compiler happy as we have covered all cases before.
return this;
}
}
/**
* Returns true, if this is a probing state.
*
* @return <code>true</code> if probing state, <code>false</code> otherwise
*/
public final boolean isProbing() {
return _state == StateClass.probing;
}
/**
* Returns true, if this is an announcing state.
*
* @return <code>true</code> if announcing state, <code>false</code> otherwise
*/
public final boolean isAnnouncing() {
return _state == StateClass.announcing;
}
/**
* Returns true, if this is an announced state.
*
* @return <code>true</code> if announced state, <code>false</code> otherwise
*/
public final boolean isAnnounced() {
return _state == StateClass.announced;
}
/**
* Returns true, if this is a canceling state.
*
* @return <code>true</code> if canceling state, <code>false</code> otherwise
*/
public final boolean isCanceling() {
return _state == StateClass.canceling;
}
/**
* Returns true, if this is a canceled state.
*
* @return <code>true</code> if canceled state, <code>false</code> otherwise
*/
public final boolean isCanceled() {
return _state == StateClass.canceled;
}
/**
* Returns true, if this is a closing state.
*
* @return <code>true</code> if closing state, <code>false</code> otherwise
*/
public final boolean isClosing() {
return _state == StateClass.closing;
}
/**
* Returns true, if this is a closing state.
*
* @return <code>true</code> if closed state, <code>false</code> otherwise
*/
public final boolean isClosed() {
return _state == StateClass.closed;
}
}
// Copyright 2003-2005 Arthur van Hoff, Rick Blair
// Licensed under Apache License version 2.0
// Original license LGPL
package javax.jmdns.impl.constants;
/**
* DNSState defines the possible states for services registered with JmDNS.
*
* @author Werner Randelshofer, Rick Blair, Pierre Frisch
*/
public enum DNSState {
/**
*
*/
PROBING_1("probing 1", StateClass.probing),
/**
*
*/
PROBING_2("probing 2", StateClass.probing),
/**
*
*/
PROBING_3("probing 3", StateClass.probing),
/**
*
*/
ANNOUNCING_1("announcing 1", StateClass.announcing),
/**
*
*/
ANNOUNCING_2("announcing 2", StateClass.announcing),
/**
*
*/
ANNOUNCED("announced", StateClass.announced),
/**
*
*/
CANCELING_1("canceling 1", StateClass.canceling),
/**
*
*/
CANCELING_2("canceling 2", StateClass.canceling),
/**
*
*/
CANCELING_3("canceling 3", StateClass.canceling),
/**
*
*/
CANCELED("canceled", StateClass.canceled),
/**
*
*/
CLOSING("closing", StateClass.closing),
/**
*
*/
CLOSED("closed", StateClass.closed);
private enum StateClass {
probing, announcing, announced, canceling, canceled, closing, closed
}
// private static Logger logger = Logger.getLogger(DNSState.class.getName());
private final String _name;
private final StateClass _state;
private DNSState(String name, StateClass state) {
_name = name;
_state = state;
}
@Override
public final String toString() {
return _name;
}
/**
* Returns the next advanced state.<br/>
* In general, this advances one step in the following sequence: PROBING_1, PROBING_2, PROBING_3, ANNOUNCING_1, ANNOUNCING_2, ANNOUNCED.<br/>
* or CANCELING_1, CANCELING_2, CANCELING_3, CANCELED Does not advance for ANNOUNCED and CANCELED state.
*
* @return next state
*/
public final DNSState advance() {
switch (this) {
case PROBING_1:
return PROBING_2;
case PROBING_2:
return PROBING_3;
case PROBING_3:
return ANNOUNCING_1;
case ANNOUNCING_1:
return ANNOUNCING_2;
case ANNOUNCING_2:
return ANNOUNCED;
case ANNOUNCED:
return ANNOUNCED;
case CANCELING_1:
return CANCELING_2;
case CANCELING_2:
return CANCELING_3;
case CANCELING_3:
return CANCELED;
case CANCELED:
return CANCELED;
case CLOSING:
return CLOSED;
case CLOSED:
return CLOSED;
default:
// This is just to keep the compiler happy as we have covered all cases before.
return this;
}
}
/**
* Returns to the next reverted state. All states except CANCELED revert to PROBING_1. Status CANCELED does not revert.
*
* @return reverted state
*/
public final DNSState revert() {
switch (this) {
case PROBING_1:
case PROBING_2:
case PROBING_3:
case ANNOUNCING_1:
case ANNOUNCING_2:
case ANNOUNCED:
return PROBING_1;
case CANCELING_1:
case CANCELING_2:
case CANCELING_3:
return CANCELING_1;
case CANCELED:
return CANCELED;
case CLOSING:
return CLOSING;
case CLOSED:
return CLOSED;
default:
// This is just to keep the compiler happy as we have covered all cases before.
return this;
}
}
/**
* Returns true, if this is a probing state.
*
* @return <code>true</code> if probing state, <code>false</code> otherwise
*/
public final boolean isProbing() {
return _state == StateClass.probing;
}
/**
* Returns true, if this is an announcing state.
*
* @return <code>true</code> if announcing state, <code>false</code> otherwise
*/
public final boolean isAnnouncing() {
return _state == StateClass.announcing;
}
/**
* Returns true, if this is an announced state.
*
* @return <code>true</code> if announced state, <code>false</code> otherwise
*/
public final boolean isAnnounced() {
return _state == StateClass.announced;
}
/**
* Returns true, if this is a canceling state.
*
* @return <code>true</code> if canceling state, <code>false</code> otherwise
*/
public final boolean isCanceling() {
return _state == StateClass.canceling;
}
/**
* Returns true, if this is a canceled state.
*
* @return <code>true</code> if canceled state, <code>false</code> otherwise
*/
public final boolean isCanceled() {
return _state == StateClass.canceled;
}
/**
* Returns true, if this is a closing state.
*
* @return <code>true</code> if closing state, <code>false</code> otherwise
*/
public final boolean isClosing() {
return _state == StateClass.closing;
}
/**
* Returns true, if this is a closing state.
*
* @return <code>true</code> if closed state, <code>false</code> otherwise
*/
public final boolean isClosed() {
return _state == StateClass.closed;
}
}

View file

@ -1,2 +1,2 @@
package javax.jmdns.impl.constants;
package javax.jmdns.impl.constants;

View file

@ -1,2 +1,2 @@
package javax.jmdns.impl;
package javax.jmdns.impl;

View file

@ -1,223 +1,223 @@
// Licensed under Apache License version 2.0
package javax.jmdns.impl.tasks;
import java.io.IOException;
import java.util.Timer;
import java.util.TimerTask;
import javax.jmdns.impl.DNSIncoming;
import javax.jmdns.impl.DNSOutgoing;
import javax.jmdns.impl.DNSQuestion;
import javax.jmdns.impl.DNSRecord;
import javax.jmdns.impl.JmDNSImpl;
import javax.jmdns.impl.constants.DNSConstants;
/**
* This is the root class for all task scheduled by the timer in JmDNS.
*
* @author Pierre Frisch
*/
public abstract class DNSTask extends TimerTask {
/**
*
*/
private final JmDNSImpl _jmDNSImpl;
/**
* @param jmDNSImpl
*/
protected DNSTask(JmDNSImpl jmDNSImpl) {
super();
this._jmDNSImpl = jmDNSImpl;
}
/**
* Return the DNS associated with this task.
*
* @return associated DNS
*/
public JmDNSImpl getDns() {
return _jmDNSImpl;
}
/**
* Start this task.
*
* @param timer
* task timer.
*/
public abstract void start(Timer timer);
/**
* Return this task name.
*
* @return task name
*/
public abstract String getName();
/*
* (non-Javadoc)
* @see java.lang.Object#toString()
*/
@Override
public String toString() {
return this.getName();
}
/**
* Add a question to the message.
*
* @param out
* outgoing message
* @param rec
* DNS question
* @return outgoing message for the next question
* @exception IOException
*/
public DNSOutgoing addQuestion(DNSOutgoing out, DNSQuestion rec) throws IOException {
DNSOutgoing newOut = out;
try {
newOut.addQuestion(rec);
} catch (final IOException e) {
int flags = newOut.getFlags();
boolean multicast = newOut.isMulticast();
int maxUDPPayload = newOut.getMaxUDPPayload();
int id = newOut.getId();
newOut.setFlags(flags | DNSConstants.FLAGS_TC);
newOut.setId(id);
this._jmDNSImpl.send(newOut);
newOut = new DNSOutgoing(flags, multicast, maxUDPPayload);
newOut.addQuestion(rec);
}
return newOut;
}
/**
* Add an answer if it is not suppressed.
*
* @param out
* outgoing message
* @param in
* incoming request
* @param rec
* DNS record answer
* @return outgoing message for the next answer
* @exception IOException
*/
public DNSOutgoing addAnswer(DNSOutgoing out, DNSIncoming in, DNSRecord rec) throws IOException {
DNSOutgoing newOut = out;
try {
newOut.addAnswer(in, rec);
} catch (final IOException e) {
int flags = newOut.getFlags();
boolean multicast = newOut.isMulticast();
int maxUDPPayload = newOut.getMaxUDPPayload();
int id = newOut.getId();
newOut.setFlags(flags | DNSConstants.FLAGS_TC);
newOut.setId(id);
this._jmDNSImpl.send(newOut);
newOut = new DNSOutgoing(flags, multicast, maxUDPPayload);
newOut.addAnswer(in, rec);
}
return newOut;
}
/**
* Add an answer to the message.
*
* @param out
* outgoing message
* @param rec
* DNS record answer
* @param now
* @return outgoing message for the next answer
* @exception IOException
*/
public DNSOutgoing addAnswer(DNSOutgoing out, DNSRecord rec, long now) throws IOException {
DNSOutgoing newOut = out;
try {
newOut.addAnswer(rec, now);
} catch (final IOException e) {
int flags = newOut.getFlags();
boolean multicast = newOut.isMulticast();
int maxUDPPayload = newOut.getMaxUDPPayload();
int id = newOut.getId();
newOut.setFlags(flags | DNSConstants.FLAGS_TC);
newOut.setId(id);
this._jmDNSImpl.send(newOut);
newOut = new DNSOutgoing(flags, multicast, maxUDPPayload);
newOut.addAnswer(rec, now);
}
return newOut;
}
/**
* Add an authoritative answer to the message.
*
* @param out
* outgoing message
* @param rec
* DNS record answer
* @return outgoing message for the next answer
* @exception IOException
*/
public DNSOutgoing addAuthoritativeAnswer(DNSOutgoing out, DNSRecord rec) throws IOException {
DNSOutgoing newOut = out;
try {
newOut.addAuthorativeAnswer(rec);
} catch (final IOException e) {
int flags = newOut.getFlags();
boolean multicast = newOut.isMulticast();
int maxUDPPayload = newOut.getMaxUDPPayload();
int id = newOut.getId();
newOut.setFlags(flags | DNSConstants.FLAGS_TC);
newOut.setId(id);
this._jmDNSImpl.send(newOut);
newOut = new DNSOutgoing(flags, multicast, maxUDPPayload);
newOut.addAuthorativeAnswer(rec);
}
return newOut;
}
/**
* Add an additional answer to the record. Omit if there is no room.
*
* @param out
* outgoing message
* @param in
* incoming request
* @param rec
* DNS record answer
* @return outgoing message for the next answer
* @exception IOException
*/
public DNSOutgoing addAdditionalAnswer(DNSOutgoing out, DNSIncoming in, DNSRecord rec) throws IOException {
DNSOutgoing newOut = out;
try {
newOut.addAdditionalAnswer(in, rec);
} catch (final IOException e) {
int flags = newOut.getFlags();
boolean multicast = newOut.isMulticast();
int maxUDPPayload = newOut.getMaxUDPPayload();
int id = newOut.getId();
newOut.setFlags(flags | DNSConstants.FLAGS_TC);
newOut.setId(id);
this._jmDNSImpl.send(newOut);
newOut = new DNSOutgoing(flags, multicast, maxUDPPayload);
newOut.addAdditionalAnswer(in, rec);
}
return newOut;
}
}
// Licensed under Apache License version 2.0
package javax.jmdns.impl.tasks;
import java.io.IOException;
import java.util.Timer;
import java.util.TimerTask;
import javax.jmdns.impl.DNSIncoming;
import javax.jmdns.impl.DNSOutgoing;
import javax.jmdns.impl.DNSQuestion;
import javax.jmdns.impl.DNSRecord;
import javax.jmdns.impl.JmDNSImpl;
import javax.jmdns.impl.constants.DNSConstants;
/**
* This is the root class for all task scheduled by the timer in JmDNS.
*
* @author Pierre Frisch
*/
public abstract class DNSTask extends TimerTask {
/**
*
*/
private final JmDNSImpl _jmDNSImpl;
/**
* @param jmDNSImpl
*/
protected DNSTask(JmDNSImpl jmDNSImpl) {
super();
this._jmDNSImpl = jmDNSImpl;
}
/**
* Return the DNS associated with this task.
*
* @return associated DNS
*/
public JmDNSImpl getDns() {
return _jmDNSImpl;
}
/**
* Start this task.
*
* @param timer
* task timer.
*/
public abstract void start(Timer timer);
/**
* Return this task name.
*
* @return task name
*/
public abstract String getName();
/*
* (non-Javadoc)
* @see java.lang.Object#toString()
*/
@Override
public String toString() {
return this.getName();
}
/**
* Add a question to the message.
*
* @param out
* outgoing message
* @param rec
* DNS question
* @return outgoing message for the next question
* @exception IOException
*/
public DNSOutgoing addQuestion(DNSOutgoing out, DNSQuestion rec) throws IOException {
DNSOutgoing newOut = out;
try {
newOut.addQuestion(rec);
} catch (final IOException e) {
int flags = newOut.getFlags();
boolean multicast = newOut.isMulticast();
int maxUDPPayload = newOut.getMaxUDPPayload();
int id = newOut.getId();
newOut.setFlags(flags | DNSConstants.FLAGS_TC);
newOut.setId(id);
this._jmDNSImpl.send(newOut);
newOut = new DNSOutgoing(flags, multicast, maxUDPPayload);
newOut.addQuestion(rec);
}
return newOut;
}
/**
* Add an answer if it is not suppressed.
*
* @param out
* outgoing message
* @param in
* incoming request
* @param rec
* DNS record answer
* @return outgoing message for the next answer
* @exception IOException
*/
public DNSOutgoing addAnswer(DNSOutgoing out, DNSIncoming in, DNSRecord rec) throws IOException {
DNSOutgoing newOut = out;
try {
newOut.addAnswer(in, rec);
} catch (final IOException e) {
int flags = newOut.getFlags();
boolean multicast = newOut.isMulticast();
int maxUDPPayload = newOut.getMaxUDPPayload();
int id = newOut.getId();
newOut.setFlags(flags | DNSConstants.FLAGS_TC);
newOut.setId(id);
this._jmDNSImpl.send(newOut);
newOut = new DNSOutgoing(flags, multicast, maxUDPPayload);
newOut.addAnswer(in, rec);
}
return newOut;
}
/**
* Add an answer to the message.
*
* @param out
* outgoing message
* @param rec
* DNS record answer
* @param now
* @return outgoing message for the next answer
* @exception IOException
*/
public DNSOutgoing addAnswer(DNSOutgoing out, DNSRecord rec, long now) throws IOException {
DNSOutgoing newOut = out;
try {
newOut.addAnswer(rec, now);
} catch (final IOException e) {
int flags = newOut.getFlags();
boolean multicast = newOut.isMulticast();
int maxUDPPayload = newOut.getMaxUDPPayload();
int id = newOut.getId();
newOut.setFlags(flags | DNSConstants.FLAGS_TC);
newOut.setId(id);
this._jmDNSImpl.send(newOut);
newOut = new DNSOutgoing(flags, multicast, maxUDPPayload);
newOut.addAnswer(rec, now);
}
return newOut;
}
/**
* Add an authoritative answer to the message.
*
* @param out
* outgoing message
* @param rec
* DNS record answer
* @return outgoing message for the next answer
* @exception IOException
*/
public DNSOutgoing addAuthoritativeAnswer(DNSOutgoing out, DNSRecord rec) throws IOException {
DNSOutgoing newOut = out;
try {
newOut.addAuthorativeAnswer(rec);
} catch (final IOException e) {
int flags = newOut.getFlags();
boolean multicast = newOut.isMulticast();
int maxUDPPayload = newOut.getMaxUDPPayload();
int id = newOut.getId();
newOut.setFlags(flags | DNSConstants.FLAGS_TC);
newOut.setId(id);
this._jmDNSImpl.send(newOut);
newOut = new DNSOutgoing(flags, multicast, maxUDPPayload);
newOut.addAuthorativeAnswer(rec);
}
return newOut;
}
/**
* Add an additional answer to the record. Omit if there is no room.
*
* @param out
* outgoing message
* @param in
* incoming request
* @param rec
* DNS record answer
* @return outgoing message for the next answer
* @exception IOException
*/
public DNSOutgoing addAdditionalAnswer(DNSOutgoing out, DNSIncoming in, DNSRecord rec) throws IOException {
DNSOutgoing newOut = out;
try {
newOut.addAdditionalAnswer(in, rec);
} catch (final IOException e) {
int flags = newOut.getFlags();
boolean multicast = newOut.isMulticast();
int maxUDPPayload = newOut.getMaxUDPPayload();
int id = newOut.getId();
newOut.setFlags(flags | DNSConstants.FLAGS_TC);
newOut.setId(id);
this._jmDNSImpl.send(newOut);
newOut = new DNSOutgoing(flags, multicast, maxUDPPayload);
newOut.addAdditionalAnswer(in, rec);
}
return newOut;
}
}

View file

@ -1,61 +1,61 @@
// Copyright 2003-2005 Arthur van Hoff, Rick Blair
// Licensed under Apache License version 2.0
// Original license LGPL
package javax.jmdns.impl.tasks;
import java.util.Timer;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.jmdns.impl.JmDNSImpl;
import javax.jmdns.impl.constants.DNSConstants;
/**
* Periodically removes expired entries from the cache.
*/
public class RecordReaper extends DNSTask {
static Logger logger = Logger.getLogger(RecordReaper.class.getName());
/**
* @param jmDNSImpl
*/
public RecordReaper(JmDNSImpl jmDNSImpl) {
super(jmDNSImpl);
}
/*
* (non-Javadoc)
* @see javax.jmdns.impl.tasks.DNSTask#getName()
*/
@Override
public String getName() {
return "RecordReaper(" + (this.getDns() != null ? this.getDns().getName() : "") + ")";
}
/*
* (non-Javadoc)
* @see javax.jmdns.impl.tasks.DNSTask#start(java.util.Timer)
*/
@Override
public void start(Timer timer) {
if (!this.getDns().isCanceling() && !this.getDns().isCanceled()) {
timer.schedule(this, DNSConstants.RECORD_REAPER_INTERVAL, DNSConstants.RECORD_REAPER_INTERVAL);
}
}
@Override
public void run() {
if (this.getDns().isCanceling() || this.getDns().isCanceled()) {
return;
}
if (logger.isLoggable(Level.FINEST)) {
logger.finest(this.getName() + ".run() JmDNS reaping cache");
}
// Remove expired answers from the cache
// -------------------------------------
this.getDns().cleanCache();
}
// Copyright 2003-2005 Arthur van Hoff, Rick Blair
// Licensed under Apache License version 2.0
// Original license LGPL
package javax.jmdns.impl.tasks;
import java.util.Timer;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.jmdns.impl.JmDNSImpl;
import javax.jmdns.impl.constants.DNSConstants;
/**
* Periodically removes expired entries from the cache.
*/
public class RecordReaper extends DNSTask {
static Logger logger = Logger.getLogger(RecordReaper.class.getName());
/**
* @param jmDNSImpl
*/
public RecordReaper(JmDNSImpl jmDNSImpl) {
super(jmDNSImpl);
}
/*
* (non-Javadoc)
* @see javax.jmdns.impl.tasks.DNSTask#getName()
*/
@Override
public String getName() {
return "RecordReaper(" + (this.getDns() != null ? this.getDns().getName() : "") + ")";
}
/*
* (non-Javadoc)
* @see javax.jmdns.impl.tasks.DNSTask#start(java.util.Timer)
*/
@Override
public void start(Timer timer) {
if (!this.getDns().isCanceling() && !this.getDns().isCanceled()) {
timer.schedule(this, DNSConstants.RECORD_REAPER_INTERVAL, DNSConstants.RECORD_REAPER_INTERVAL);
}
}
@Override
public void run() {
if (this.getDns().isCanceling() || this.getDns().isCanceled()) {
return;
}
if (logger.isLoggable(Level.FINEST)) {
logger.finest(this.getName() + ".run() JmDNS reaping cache");
}
// Remove expired answers from the cache
// -------------------------------------
this.getDns().cleanCache();
}
}

View file

@ -1,157 +1,157 @@
// Copyright 2003-2005 Arthur van Hoff, Rick Blair
// Licensed under Apache License version 2.0
// Original license LGPL
package javax.jmdns.impl.tasks;
import java.util.HashSet;
import java.util.Set;
import java.util.Timer;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.jmdns.impl.DNSIncoming;
import javax.jmdns.impl.DNSOutgoing;
import javax.jmdns.impl.DNSQuestion;
import javax.jmdns.impl.DNSRecord;
import javax.jmdns.impl.JmDNSImpl;
import javax.jmdns.impl.constants.DNSConstants;
/**
* The Responder sends a single answer for the specified service infos and for the host name.
*/
public class Responder extends DNSTask {
static Logger logger = Logger.getLogger(Responder.class.getName());
/**
*
*/
private final DNSIncoming _in;
/**
*
*/
private final boolean _unicast;
public Responder(JmDNSImpl jmDNSImpl, DNSIncoming in, int port) {
super(jmDNSImpl);
this._in = in;
this._unicast = (port != DNSConstants.MDNS_PORT);
}
/*
* (non-Javadoc)
* @see javax.jmdns.impl.tasks.DNSTask#getName()
*/
@Override
public String getName() {
return "Responder(" + (this.getDns() != null ? this.getDns().getName() : "") + ")";
}
/*
* (non-Javadoc)
* @see java.lang.Object#toString()
*/
@Override
public String toString() {
return super.toString() + " incomming: " + _in;
}
/*
* (non-Javadoc)
* @see javax.jmdns.impl.tasks.DNSTask#start(java.util.Timer)
*/
@Override
public void start(Timer timer) {
// According to draft-cheshire-dnsext-multicastdns.txt chapter "7 Responding":
// We respond immediately if we know for sure, that we are the only one who can respond to the query.
// In all other cases, we respond within 20-120 ms.
//
// According to draft-cheshire-dnsext-multicastdns.txt chapter "6.2 Multi-Packet Known Answer Suppression":
// We respond after 20-120 ms if the query is truncated.
boolean iAmTheOnlyOne = true;
for (DNSQuestion question : _in.getQuestions()) {
if (logger.isLoggable(Level.FINEST)) {
logger.finest(this.getName() + "start() question=" + question);
}
iAmTheOnlyOne = question.iAmTheOnlyOne(this.getDns());
if (!iAmTheOnlyOne) {
break;
}
}
int delay = (iAmTheOnlyOne && !_in.isTruncated()) ? 0 : DNSConstants.RESPONSE_MIN_WAIT_INTERVAL + JmDNSImpl.getRandom().nextInt(DNSConstants.RESPONSE_MAX_WAIT_INTERVAL - DNSConstants.RESPONSE_MIN_WAIT_INTERVAL + 1) - _in.elapseSinceArrival();
if (delay < 0) {
delay = 0;
}
if (logger.isLoggable(Level.FINEST)) {
logger.finest(this.getName() + "start() Responder chosen delay=" + delay);
}
if (!this.getDns().isCanceling() && !this.getDns().isCanceled()) {
timer.schedule(this, delay);
}
}
@Override
public void run() {
this.getDns().respondToQuery(_in);
// We use these sets to prevent duplicate records
Set<DNSQuestion> questions = new HashSet<DNSQuestion>();
Set<DNSRecord> answers = new HashSet<DNSRecord>();
if (this.getDns().isAnnounced()) {
try {
// Answer questions
for (DNSQuestion question : _in.getQuestions()) {
if (logger.isLoggable(Level.FINER)) {
logger.finer(this.getName() + "run() JmDNS responding to: " + question);
}
// for unicast responses the question must be included
if (_unicast) {
// out.addQuestion(q);
questions.add(question);
}
question.addAnswers(this.getDns(), answers);
}
// remove known answers, if the ttl is at least half of the correct value. (See Draft Cheshire chapter 7.1.).
long now = System.currentTimeMillis();
for (DNSRecord knownAnswer : _in.getAnswers()) {
if (knownAnswer.isStale(now)) {
answers.remove(knownAnswer);
if (logger.isLoggable(Level.FINER)) {
logger.finer(this.getName() + "JmDNS Responder Known Answer Removed");
}
}
}
// respond if we have answers
if (!answers.isEmpty()) {
if (logger.isLoggable(Level.FINER)) {
logger.finer(this.getName() + "run() JmDNS responding");
}
DNSOutgoing out = new DNSOutgoing(DNSConstants.FLAGS_QR_RESPONSE | DNSConstants.FLAGS_AA, !_unicast, _in.getSenderUDPPayload());
out.setId(_in.getId());
for (DNSQuestion question : questions) {
if (question != null) {
out = this.addQuestion(out, question);
}
}
for (DNSRecord answer : answers) {
if (answer != null) {
out = this.addAnswer(out, _in, answer);
}
}
if (!out.isEmpty()) this.getDns().send(out);
}
// this.cancel();
} catch (Throwable e) {
logger.log(Level.WARNING, this.getName() + "run() exception ", e);
this.getDns().close();
}
}
}
// Copyright 2003-2005 Arthur van Hoff, Rick Blair
// Licensed under Apache License version 2.0
// Original license LGPL
package javax.jmdns.impl.tasks;
import java.util.HashSet;
import java.util.Set;
import java.util.Timer;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.jmdns.impl.DNSIncoming;
import javax.jmdns.impl.DNSOutgoing;
import javax.jmdns.impl.DNSQuestion;
import javax.jmdns.impl.DNSRecord;
import javax.jmdns.impl.JmDNSImpl;
import javax.jmdns.impl.constants.DNSConstants;
/**
* The Responder sends a single answer for the specified service infos and for the host name.
*/
public class Responder extends DNSTask {
static Logger logger = Logger.getLogger(Responder.class.getName());
/**
*
*/
private final DNSIncoming _in;
/**
*
*/
private final boolean _unicast;
public Responder(JmDNSImpl jmDNSImpl, DNSIncoming in, int port) {
super(jmDNSImpl);
this._in = in;
this._unicast = (port != DNSConstants.MDNS_PORT);
}
/*
* (non-Javadoc)
* @see javax.jmdns.impl.tasks.DNSTask#getName()
*/
@Override
public String getName() {
return "Responder(" + (this.getDns() != null ? this.getDns().getName() : "") + ")";
}
/*
* (non-Javadoc)
* @see java.lang.Object#toString()
*/
@Override
public String toString() {
return super.toString() + " incomming: " + _in;
}
/*
* (non-Javadoc)
* @see javax.jmdns.impl.tasks.DNSTask#start(java.util.Timer)
*/
@Override
public void start(Timer timer) {
// According to draft-cheshire-dnsext-multicastdns.txt chapter "7 Responding":
// We respond immediately if we know for sure, that we are the only one who can respond to the query.
// In all other cases, we respond within 20-120 ms.
//
// According to draft-cheshire-dnsext-multicastdns.txt chapter "6.2 Multi-Packet Known Answer Suppression":
// We respond after 20-120 ms if the query is truncated.
boolean iAmTheOnlyOne = true;
for (DNSQuestion question : _in.getQuestions()) {
if (logger.isLoggable(Level.FINEST)) {
logger.finest(this.getName() + "start() question=" + question);
}
iAmTheOnlyOne = question.iAmTheOnlyOne(this.getDns());
if (!iAmTheOnlyOne) {
break;
}
}
int delay = (iAmTheOnlyOne && !_in.isTruncated()) ? 0 : DNSConstants.RESPONSE_MIN_WAIT_INTERVAL + JmDNSImpl.getRandom().nextInt(DNSConstants.RESPONSE_MAX_WAIT_INTERVAL - DNSConstants.RESPONSE_MIN_WAIT_INTERVAL + 1) - _in.elapseSinceArrival();
if (delay < 0) {
delay = 0;
}
if (logger.isLoggable(Level.FINEST)) {
logger.finest(this.getName() + "start() Responder chosen delay=" + delay);
}
if (!this.getDns().isCanceling() && !this.getDns().isCanceled()) {
timer.schedule(this, delay);
}
}
@Override
public void run() {
this.getDns().respondToQuery(_in);
// We use these sets to prevent duplicate records
Set<DNSQuestion> questions = new HashSet<DNSQuestion>();
Set<DNSRecord> answers = new HashSet<DNSRecord>();
if (this.getDns().isAnnounced()) {
try {
// Answer questions
for (DNSQuestion question : _in.getQuestions()) {
if (logger.isLoggable(Level.FINER)) {
logger.finer(this.getName() + "run() JmDNS responding to: " + question);
}
// for unicast responses the question must be included
if (_unicast) {
// out.addQuestion(q);
questions.add(question);
}
question.addAnswers(this.getDns(), answers);
}
// remove known answers, if the ttl is at least half of the correct value. (See Draft Cheshire chapter 7.1.).
long now = System.currentTimeMillis();
for (DNSRecord knownAnswer : _in.getAnswers()) {
if (knownAnswer.isStale(now)) {
answers.remove(knownAnswer);
if (logger.isLoggable(Level.FINER)) {
logger.finer(this.getName() + "JmDNS Responder Known Answer Removed");
}
}
}
// respond if we have answers
if (!answers.isEmpty()) {
if (logger.isLoggable(Level.FINER)) {
logger.finer(this.getName() + "run() JmDNS responding");
}
DNSOutgoing out = new DNSOutgoing(DNSConstants.FLAGS_QR_RESPONSE | DNSConstants.FLAGS_AA, !_unicast, _in.getSenderUDPPayload());
out.setId(_in.getId());
for (DNSQuestion question : questions) {
if (question != null) {
out = this.addQuestion(out, question);
}
}
for (DNSRecord answer : answers) {
if (answer != null) {
out = this.addAnswer(out, _in, answer);
}
}
if (!out.isEmpty()) this.getDns().send(out);
}
// this.cancel();
} catch (Throwable e) {
logger.log(Level.WARNING, this.getName() + "run() exception ", e);
this.getDns().close();
}
}
}
}

View file

@ -1,2 +1,2 @@
package javax.jmdns.impl.tasks;
package javax.jmdns.impl.tasks;

View file

@ -1,116 +1,116 @@
// Licensed under Apache License version 2.0
package javax.jmdns.impl.tasks.resolver;
import java.io.IOException;
import java.util.Timer;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.jmdns.impl.DNSOutgoing;
import javax.jmdns.impl.JmDNSImpl;
import javax.jmdns.impl.constants.DNSConstants;
import javax.jmdns.impl.tasks.DNSTask;
/**
* This is the root class for all resolver tasks.
*
* @author Pierre Frisch
*/
public abstract class DNSResolverTask extends DNSTask {
private static Logger logger = Logger.getLogger(DNSResolverTask.class.getName());
/**
* Counts the number of queries being sent.
*/
protected int _count = 0;
/**
* @param jmDNSImpl
*/
public DNSResolverTask(JmDNSImpl jmDNSImpl) {
super(jmDNSImpl);
}
/*
* (non-Javadoc)
* @see java.lang.Object#toString()
*/
@Override
public String toString() {
return super.toString() + " count: " + _count;
}
/*
* (non-Javadoc)
* @see javax.jmdns.impl.tasks.DNSTask#start(java.util.Timer)
*/
@Override
public void start(Timer timer) {
if (!this.getDns().isCanceling() && !this.getDns().isCanceled()) {
timer.schedule(this, DNSConstants.QUERY_WAIT_INTERVAL, DNSConstants.QUERY_WAIT_INTERVAL);
}
}
/*
* (non-Javadoc)
* @see java.util.TimerTask#run()
*/
@Override
public void run() {
try {
if (this.getDns().isCanceling() || this.getDns().isCanceled()) {
this.cancel();
} else {
if (_count++ < 3) {
if (logger.isLoggable(Level.FINER)) {
logger.finer(this.getName() + ".run() JmDNS " + this.description());
}
DNSOutgoing out = new DNSOutgoing(DNSConstants.FLAGS_QR_QUERY);
out = this.addQuestions(out);
if (this.getDns().isAnnounced()) {
out = this.addAnswers(out);
}
if (!out.isEmpty()) {
this.getDns().send(out);
}
} else {
// After three queries, we can quit.
this.cancel();
}
}
} catch (Throwable e) {
logger.log(Level.WARNING, this.getName() + ".run() exception ", e);
this.getDns().recover();
}
}
/**
* Overridden by subclasses to add questions to the message.<br/>
* <b>Note:</b> Because of message size limitation the returned message may be different than the message parameter.
*
* @param out
* outgoing message
* @return the outgoing message.
* @exception IOException
*/
protected abstract DNSOutgoing addQuestions(DNSOutgoing out) throws IOException;
/**
* Overridden by subclasses to add questions to the message.<br/>
* <b>Note:</b> Because of message size limitation the returned message may be different than the message parameter.
*
* @param out
* outgoing message
* @return the outgoing message.
* @exception IOException
*/
protected abstract DNSOutgoing addAnswers(DNSOutgoing out) throws IOException;
/**
* Returns a description of the resolver for debugging
*
* @return resolver description
*/
protected abstract String description();
}
// Licensed under Apache License version 2.0
package javax.jmdns.impl.tasks.resolver;
import java.io.IOException;
import java.util.Timer;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.jmdns.impl.DNSOutgoing;
import javax.jmdns.impl.JmDNSImpl;
import javax.jmdns.impl.constants.DNSConstants;
import javax.jmdns.impl.tasks.DNSTask;
/**
* This is the root class for all resolver tasks.
*
* @author Pierre Frisch
*/
public abstract class DNSResolverTask extends DNSTask {
private static Logger logger = Logger.getLogger(DNSResolverTask.class.getName());
/**
* Counts the number of queries being sent.
*/
protected int _count = 0;
/**
* @param jmDNSImpl
*/
public DNSResolverTask(JmDNSImpl jmDNSImpl) {
super(jmDNSImpl);
}
/*
* (non-Javadoc)
* @see java.lang.Object#toString()
*/
@Override
public String toString() {
return super.toString() + " count: " + _count;
}
/*
* (non-Javadoc)
* @see javax.jmdns.impl.tasks.DNSTask#start(java.util.Timer)
*/
@Override
public void start(Timer timer) {
if (!this.getDns().isCanceling() && !this.getDns().isCanceled()) {
timer.schedule(this, DNSConstants.QUERY_WAIT_INTERVAL, DNSConstants.QUERY_WAIT_INTERVAL);
}
}
/*
* (non-Javadoc)
* @see java.util.TimerTask#run()
*/
@Override
public void run() {
try {
if (this.getDns().isCanceling() || this.getDns().isCanceled()) {
this.cancel();
} else {
if (_count++ < 3) {
if (logger.isLoggable(Level.FINER)) {
logger.finer(this.getName() + ".run() JmDNS " + this.description());
}
DNSOutgoing out = new DNSOutgoing(DNSConstants.FLAGS_QR_QUERY);
out = this.addQuestions(out);
if (this.getDns().isAnnounced()) {
out = this.addAnswers(out);
}
if (!out.isEmpty()) {
this.getDns().send(out);
}
} else {
// After three queries, we can quit.
this.cancel();
}
}
} catch (Throwable e) {
logger.log(Level.WARNING, this.getName() + ".run() exception ", e);
this.getDns().recover();
}
}
/**
* Overridden by subclasses to add questions to the message.<br/>
* <b>Note:</b> Because of message size limitation the returned message may be different than the message parameter.
*
* @param out
* outgoing message
* @return the outgoing message.
* @exception IOException
*/
protected abstract DNSOutgoing addQuestions(DNSOutgoing out) throws IOException;
/**
* Overridden by subclasses to add questions to the message.<br/>
* <b>Note:</b> Because of message size limitation the returned message may be different than the message parameter.
*
* @param out
* outgoing message
* @return the outgoing message.
* @exception IOException
*/
protected abstract DNSOutgoing addAnswers(DNSOutgoing out) throws IOException;
/**
* Returns a description of the resolver for debugging
*
* @return resolver description
*/
protected abstract String description();
}

View file

@ -1,107 +1,107 @@
// Copyright 2003-2005 Arthur van Hoff, Rick Blair
// Licensed under Apache License version 2.0
// Original license LGPL
package javax.jmdns.impl.tasks.resolver;
import java.io.IOException;
import javax.jmdns.impl.DNSEntry;
import javax.jmdns.impl.DNSOutgoing;
import javax.jmdns.impl.DNSQuestion;
import javax.jmdns.impl.DNSRecord;
import javax.jmdns.impl.JmDNSImpl;
import javax.jmdns.impl.ServiceInfoImpl;
import javax.jmdns.impl.constants.DNSRecordClass;
import javax.jmdns.impl.constants.DNSRecordType;
/**
* The ServiceInfoResolver queries up to three times consecutively for a service info, and then removes itself from the timer.
* <p/>
* The ServiceInfoResolver will run only if JmDNS is in state ANNOUNCED. REMIND: Prevent having multiple service resolvers for the same info in the timer queue.
*/
public class ServiceInfoResolver extends DNSResolverTask {
private final ServiceInfoImpl _info;
public ServiceInfoResolver(JmDNSImpl jmDNSImpl, ServiceInfoImpl info) {
super(jmDNSImpl);
this._info = info;
info.setDns(this.getDns());
this.getDns().addListener(info, DNSQuestion.newQuestion(info.getQualifiedName(), DNSRecordType.TYPE_ANY, DNSRecordClass.CLASS_IN, DNSRecordClass.NOT_UNIQUE));
}
/*
* (non-Javadoc)
* @see javax.jmdns.impl.tasks.DNSTask#getName()
*/
@Override
public String getName() {
return "ServiceInfoResolver(" + (this.getDns() != null ? this.getDns().getName() : "") + ")";
}
/*
* (non-Javadoc)
* @see java.util.TimerTask#cancel()
*/
@Override
public boolean cancel() {
// We should not forget to remove the listener
boolean result = super.cancel();
if (!_info.isPersistent()) {
this.getDns().removeListener(_info);
}
return result;
}
/*
* (non-Javadoc)
* @see javax.jmdns.impl.tasks.Resolver#addAnswers(javax.jmdns.impl.DNSOutgoing)
*/
@Override
protected DNSOutgoing addAnswers(DNSOutgoing out) throws IOException {
DNSOutgoing newOut = out;
if (!_info.hasData()) {
long now = System.currentTimeMillis();
newOut = this.addAnswer(newOut, (DNSRecord) this.getDns().getCache().getDNSEntry(_info.getQualifiedName(), DNSRecordType.TYPE_SRV, DNSRecordClass.CLASS_IN), now);
newOut = this.addAnswer(newOut, (DNSRecord) this.getDns().getCache().getDNSEntry(_info.getQualifiedName(), DNSRecordType.TYPE_TXT, DNSRecordClass.CLASS_IN), now);
if (_info.getServer().length() > 0) {
for (DNSEntry addressEntry : this.getDns().getCache().getDNSEntryList(_info.getServer(), DNSRecordType.TYPE_A, DNSRecordClass.CLASS_IN)) {
newOut = this.addAnswer(newOut, (DNSRecord) addressEntry, now);
}
for (DNSEntry addressEntry : this.getDns().getCache().getDNSEntryList(_info.getServer(), DNSRecordType.TYPE_AAAA, DNSRecordClass.CLASS_IN)) {
newOut = this.addAnswer(newOut, (DNSRecord) addressEntry, now);
}
}
}
return newOut;
}
/*
* (non-Javadoc)
* @see javax.jmdns.impl.tasks.Resolver#addQuestions(javax.jmdns.impl.DNSOutgoing)
*/
@Override
protected DNSOutgoing addQuestions(DNSOutgoing out) throws IOException {
DNSOutgoing newOut = out;
if (!_info.hasData()) {
newOut = this.addQuestion(newOut, DNSQuestion.newQuestion(_info.getQualifiedName(), DNSRecordType.TYPE_SRV, DNSRecordClass.CLASS_IN, DNSRecordClass.NOT_UNIQUE));
newOut = this.addQuestion(newOut, DNSQuestion.newQuestion(_info.getQualifiedName(), DNSRecordType.TYPE_TXT, DNSRecordClass.CLASS_IN, DNSRecordClass.NOT_UNIQUE));
if (_info.getServer().length() > 0) {
newOut = this.addQuestion(newOut, DNSQuestion.newQuestion(_info.getServer(), DNSRecordType.TYPE_A, DNSRecordClass.CLASS_IN, DNSRecordClass.NOT_UNIQUE));
newOut = this.addQuestion(newOut, DNSQuestion.newQuestion(_info.getServer(), DNSRecordType.TYPE_AAAA, DNSRecordClass.CLASS_IN, DNSRecordClass.NOT_UNIQUE));
}
}
return newOut;
}
/*
* (non-Javadoc)
* @see javax.jmdns.impl.tasks.Resolver#description()
*/
@Override
protected String description() {
return "querying service info: " + (_info != null ? _info.getQualifiedName() : "null");
}
// Copyright 2003-2005 Arthur van Hoff, Rick Blair
// Licensed under Apache License version 2.0
// Original license LGPL
package javax.jmdns.impl.tasks.resolver;
import java.io.IOException;
import javax.jmdns.impl.DNSEntry;
import javax.jmdns.impl.DNSOutgoing;
import javax.jmdns.impl.DNSQuestion;
import javax.jmdns.impl.DNSRecord;
import javax.jmdns.impl.JmDNSImpl;
import javax.jmdns.impl.ServiceInfoImpl;
import javax.jmdns.impl.constants.DNSRecordClass;
import javax.jmdns.impl.constants.DNSRecordType;
/**
* The ServiceInfoResolver queries up to three times consecutively for a service info, and then removes itself from the timer.
* <p/>
* The ServiceInfoResolver will run only if JmDNS is in state ANNOUNCED. REMIND: Prevent having multiple service resolvers for the same info in the timer queue.
*/
public class ServiceInfoResolver extends DNSResolverTask {
private final ServiceInfoImpl _info;
public ServiceInfoResolver(JmDNSImpl jmDNSImpl, ServiceInfoImpl info) {
super(jmDNSImpl);
this._info = info;
info.setDns(this.getDns());
this.getDns().addListener(info, DNSQuestion.newQuestion(info.getQualifiedName(), DNSRecordType.TYPE_ANY, DNSRecordClass.CLASS_IN, DNSRecordClass.NOT_UNIQUE));
}
/*
* (non-Javadoc)
* @see javax.jmdns.impl.tasks.DNSTask#getName()
*/
@Override
public String getName() {
return "ServiceInfoResolver(" + (this.getDns() != null ? this.getDns().getName() : "") + ")";
}
/*
* (non-Javadoc)
* @see java.util.TimerTask#cancel()
*/
@Override
public boolean cancel() {
// We should not forget to remove the listener
boolean result = super.cancel();
if (!_info.isPersistent()) {
this.getDns().removeListener(_info);
}
return result;
}
/*
* (non-Javadoc)
* @see javax.jmdns.impl.tasks.Resolver#addAnswers(javax.jmdns.impl.DNSOutgoing)
*/
@Override
protected DNSOutgoing addAnswers(DNSOutgoing out) throws IOException {
DNSOutgoing newOut = out;
if (!_info.hasData()) {
long now = System.currentTimeMillis();
newOut = this.addAnswer(newOut, (DNSRecord) this.getDns().getCache().getDNSEntry(_info.getQualifiedName(), DNSRecordType.TYPE_SRV, DNSRecordClass.CLASS_IN), now);
newOut = this.addAnswer(newOut, (DNSRecord) this.getDns().getCache().getDNSEntry(_info.getQualifiedName(), DNSRecordType.TYPE_TXT, DNSRecordClass.CLASS_IN), now);
if (_info.getServer().length() > 0) {
for (DNSEntry addressEntry : this.getDns().getCache().getDNSEntryList(_info.getServer(), DNSRecordType.TYPE_A, DNSRecordClass.CLASS_IN)) {
newOut = this.addAnswer(newOut, (DNSRecord) addressEntry, now);
}
for (DNSEntry addressEntry : this.getDns().getCache().getDNSEntryList(_info.getServer(), DNSRecordType.TYPE_AAAA, DNSRecordClass.CLASS_IN)) {
newOut = this.addAnswer(newOut, (DNSRecord) addressEntry, now);
}
}
}
return newOut;
}
/*
* (non-Javadoc)
* @see javax.jmdns.impl.tasks.Resolver#addQuestions(javax.jmdns.impl.DNSOutgoing)
*/
@Override
protected DNSOutgoing addQuestions(DNSOutgoing out) throws IOException {
DNSOutgoing newOut = out;
if (!_info.hasData()) {
newOut = this.addQuestion(newOut, DNSQuestion.newQuestion(_info.getQualifiedName(), DNSRecordType.TYPE_SRV, DNSRecordClass.CLASS_IN, DNSRecordClass.NOT_UNIQUE));
newOut = this.addQuestion(newOut, DNSQuestion.newQuestion(_info.getQualifiedName(), DNSRecordType.TYPE_TXT, DNSRecordClass.CLASS_IN, DNSRecordClass.NOT_UNIQUE));
if (_info.getServer().length() > 0) {
newOut = this.addQuestion(newOut, DNSQuestion.newQuestion(_info.getServer(), DNSRecordType.TYPE_A, DNSRecordClass.CLASS_IN, DNSRecordClass.NOT_UNIQUE));
newOut = this.addQuestion(newOut, DNSQuestion.newQuestion(_info.getServer(), DNSRecordType.TYPE_AAAA, DNSRecordClass.CLASS_IN, DNSRecordClass.NOT_UNIQUE));
}
}
return newOut;
}
/*
* (non-Javadoc)
* @see javax.jmdns.impl.tasks.Resolver#description()
*/
@Override
protected String description() {
return "querying service info: " + (_info != null ? _info.getQualifiedName() : "null");
}
}

View file

@ -1,77 +1,77 @@
// Copyright 2003-2005 Arthur van Hoff, Rick Blair
// Licensed under Apache License version 2.0
// Original license LGPL
package javax.jmdns.impl.tasks.resolver;
import java.io.IOException;
import javax.jmdns.ServiceInfo;
import javax.jmdns.impl.DNSOutgoing;
import javax.jmdns.impl.DNSQuestion;
import javax.jmdns.impl.DNSRecord;
import javax.jmdns.impl.JmDNSImpl;
import javax.jmdns.impl.constants.DNSConstants;
import javax.jmdns.impl.constants.DNSRecordClass;
import javax.jmdns.impl.constants.DNSRecordType;
/**
* The ServiceResolver queries three times consecutively for services of a given type, and then removes itself from the timer.
* <p/>
* The ServiceResolver will run only if JmDNS is in state ANNOUNCED. REMIND: Prevent having multiple service resolvers for the same type in the timer queue.
*/
public class ServiceResolver extends DNSResolverTask {
private final String _type;
public ServiceResolver(JmDNSImpl jmDNSImpl, String type) {
super(jmDNSImpl);
this._type = type;
}
/*
* (non-Javadoc)
* @see javax.jmdns.impl.tasks.DNSTask#getName()
*/
@Override
public String getName() {
return "ServiceResolver(" + (this.getDns() != null ? this.getDns().getName() : "") + ")";
}
/*
* (non-Javadoc)
* @see javax.jmdns.impl.tasks.Resolver#addAnswers(javax.jmdns.impl.DNSOutgoing)
*/
@Override
protected DNSOutgoing addAnswers(DNSOutgoing out) throws IOException {
DNSOutgoing newOut = out;
long now = System.currentTimeMillis();
for (ServiceInfo info : this.getDns().getServices().values()) {
newOut = this.addAnswer(newOut, new DNSRecord.Pointer(info.getType(), DNSRecordClass.CLASS_IN, DNSRecordClass.NOT_UNIQUE, DNSConstants.DNS_TTL, info.getQualifiedName()), now);
// newOut = this.addAnswer(newOut, new DNSRecord.Service(info.getQualifiedName(), DNSRecordClass.CLASS_IN, DNSRecordClass.NOT_UNIQUE, DNSConstants.DNS_TTL, info.getPriority(), info.getWeight(), info.getPort(),
// this.getDns().getLocalHost().getName()), now);
}
return newOut;
}
/*
* (non-Javadoc)
* @see javax.jmdns.impl.tasks.Resolver#addQuestions(javax.jmdns.impl.DNSOutgoing)
*/
@Override
protected DNSOutgoing addQuestions(DNSOutgoing out) throws IOException {
DNSOutgoing newOut = out;
newOut = this.addQuestion(newOut, DNSQuestion.newQuestion(_type, DNSRecordType.TYPE_PTR, DNSRecordClass.CLASS_IN, DNSRecordClass.NOT_UNIQUE));
// newOut = this.addQuestion(newOut, DNSQuestion.newQuestion(_type, DNSRecordType.TYPE_SRV, DNSRecordClass.CLASS_IN, DNSRecordClass.NOT_UNIQUE));
return newOut;
}
/*
* (non-Javadoc)
* @see javax.jmdns.impl.tasks.Resolver#description()
*/
@Override
protected String description() {
return "querying service";
}
// Copyright 2003-2005 Arthur van Hoff, Rick Blair
// Licensed under Apache License version 2.0
// Original license LGPL
package javax.jmdns.impl.tasks.resolver;
import java.io.IOException;
import javax.jmdns.ServiceInfo;
import javax.jmdns.impl.DNSOutgoing;
import javax.jmdns.impl.DNSQuestion;
import javax.jmdns.impl.DNSRecord;
import javax.jmdns.impl.JmDNSImpl;
import javax.jmdns.impl.constants.DNSConstants;
import javax.jmdns.impl.constants.DNSRecordClass;
import javax.jmdns.impl.constants.DNSRecordType;
/**
* The ServiceResolver queries three times consecutively for services of a given type, and then removes itself from the timer.
* <p/>
* The ServiceResolver will run only if JmDNS is in state ANNOUNCED. REMIND: Prevent having multiple service resolvers for the same type in the timer queue.
*/
public class ServiceResolver extends DNSResolverTask {
private final String _type;
public ServiceResolver(JmDNSImpl jmDNSImpl, String type) {
super(jmDNSImpl);
this._type = type;
}
/*
* (non-Javadoc)
* @see javax.jmdns.impl.tasks.DNSTask#getName()
*/
@Override
public String getName() {
return "ServiceResolver(" + (this.getDns() != null ? this.getDns().getName() : "") + ")";
}
/*
* (non-Javadoc)
* @see javax.jmdns.impl.tasks.Resolver#addAnswers(javax.jmdns.impl.DNSOutgoing)
*/
@Override
protected DNSOutgoing addAnswers(DNSOutgoing out) throws IOException {
DNSOutgoing newOut = out;
long now = System.currentTimeMillis();
for (ServiceInfo info : this.getDns().getServices().values()) {
newOut = this.addAnswer(newOut, new DNSRecord.Pointer(info.getType(), DNSRecordClass.CLASS_IN, DNSRecordClass.NOT_UNIQUE, DNSConstants.DNS_TTL, info.getQualifiedName()), now);
// newOut = this.addAnswer(newOut, new DNSRecord.Service(info.getQualifiedName(), DNSRecordClass.CLASS_IN, DNSRecordClass.NOT_UNIQUE, DNSConstants.DNS_TTL, info.getPriority(), info.getWeight(), info.getPort(),
// this.getDns().getLocalHost().getName()), now);
}
return newOut;
}
/*
* (non-Javadoc)
* @see javax.jmdns.impl.tasks.Resolver#addQuestions(javax.jmdns.impl.DNSOutgoing)
*/
@Override
protected DNSOutgoing addQuestions(DNSOutgoing out) throws IOException {
DNSOutgoing newOut = out;
newOut = this.addQuestion(newOut, DNSQuestion.newQuestion(_type, DNSRecordType.TYPE_PTR, DNSRecordClass.CLASS_IN, DNSRecordClass.NOT_UNIQUE));
// newOut = this.addQuestion(newOut, DNSQuestion.newQuestion(_type, DNSRecordType.TYPE_SRV, DNSRecordClass.CLASS_IN, DNSRecordClass.NOT_UNIQUE));
return newOut;
}
/*
* (non-Javadoc)
* @see javax.jmdns.impl.tasks.Resolver#description()
*/
@Override
protected String description() {
return "querying service";
}
}

View file

@ -1,75 +1,75 @@
// Copyright 2003-2005 Arthur van Hoff, Rick Blair
// Licensed under Apache License version 2.0
// Original license LGPL
package javax.jmdns.impl.tasks.resolver;
import java.io.IOException;
import javax.jmdns.impl.DNSOutgoing;
import javax.jmdns.impl.DNSQuestion;
import javax.jmdns.impl.DNSRecord;
import javax.jmdns.impl.JmDNSImpl;
import javax.jmdns.impl.JmDNSImpl.ServiceTypeEntry;
import javax.jmdns.impl.constants.DNSConstants;
import javax.jmdns.impl.constants.DNSRecordClass;
import javax.jmdns.impl.constants.DNSRecordType;
/**
* Helper class to resolve service types.
* <p/>
* The TypeResolver queries three times consecutively for service types, and then removes itself from the timer.
* <p/>
* The TypeResolver will run only if JmDNS is in state ANNOUNCED.
*/
public class TypeResolver extends DNSResolverTask {
/**
* @param jmDNSImpl
*/
public TypeResolver(JmDNSImpl jmDNSImpl) {
super(jmDNSImpl);
}
/*
* (non-Javadoc)
* @see javax.jmdns.impl.tasks.DNSTask#getName()
*/
@Override
public String getName() {
return "TypeResolver(" + (this.getDns() != null ? this.getDns().getName() : "") + ")";
}
/*
* (non-Javadoc)
* @see javax.jmdns.impl.tasks.Resolver#addAnswers(javax.jmdns.impl.DNSOutgoing)
*/
@Override
protected DNSOutgoing addAnswers(DNSOutgoing out) throws IOException {
DNSOutgoing newOut = out;
long now = System.currentTimeMillis();
for (String type : this.getDns().getServiceTypes().keySet()) {
ServiceTypeEntry typeEntry = this.getDns().getServiceTypes().get(type);
newOut = this.addAnswer(newOut, new DNSRecord.Pointer("_services._dns-sd._udp.local.", DNSRecordClass.CLASS_IN, DNSRecordClass.NOT_UNIQUE, DNSConstants.DNS_TTL, typeEntry.getType()), now);
}
return newOut;
}
/*
* (non-Javadoc)
* @see javax.jmdns.impl.tasks.Resolver#addQuestions(javax.jmdns.impl.DNSOutgoing)
*/
@Override
protected DNSOutgoing addQuestions(DNSOutgoing out) throws IOException {
return this.addQuestion(out, DNSQuestion.newQuestion("_services._dns-sd._udp.local.", DNSRecordType.TYPE_PTR, DNSRecordClass.CLASS_IN, DNSRecordClass.NOT_UNIQUE));
}
/*
* (non-Javadoc)
* @see javax.jmdns.impl.tasks.Resolver#description()
*/
@Override
protected String description() {
return "querying type";
}
// Copyright 2003-2005 Arthur van Hoff, Rick Blair
// Licensed under Apache License version 2.0
// Original license LGPL
package javax.jmdns.impl.tasks.resolver;
import java.io.IOException;
import javax.jmdns.impl.DNSOutgoing;
import javax.jmdns.impl.DNSQuestion;
import javax.jmdns.impl.DNSRecord;
import javax.jmdns.impl.JmDNSImpl;
import javax.jmdns.impl.JmDNSImpl.ServiceTypeEntry;
import javax.jmdns.impl.constants.DNSConstants;
import javax.jmdns.impl.constants.DNSRecordClass;
import javax.jmdns.impl.constants.DNSRecordType;
/**
* Helper class to resolve service types.
* <p/>
* The TypeResolver queries three times consecutively for service types, and then removes itself from the timer.
* <p/>
* The TypeResolver will run only if JmDNS is in state ANNOUNCED.
*/
public class TypeResolver extends DNSResolverTask {
/**
* @param jmDNSImpl
*/
public TypeResolver(JmDNSImpl jmDNSImpl) {
super(jmDNSImpl);
}
/*
* (non-Javadoc)
* @see javax.jmdns.impl.tasks.DNSTask#getName()
*/
@Override
public String getName() {
return "TypeResolver(" + (this.getDns() != null ? this.getDns().getName() : "") + ")";
}
/*
* (non-Javadoc)
* @see javax.jmdns.impl.tasks.Resolver#addAnswers(javax.jmdns.impl.DNSOutgoing)
*/
@Override
protected DNSOutgoing addAnswers(DNSOutgoing out) throws IOException {
DNSOutgoing newOut = out;
long now = System.currentTimeMillis();
for (String type : this.getDns().getServiceTypes().keySet()) {
ServiceTypeEntry typeEntry = this.getDns().getServiceTypes().get(type);
newOut = this.addAnswer(newOut, new DNSRecord.Pointer("_services._dns-sd._udp.local.", DNSRecordClass.CLASS_IN, DNSRecordClass.NOT_UNIQUE, DNSConstants.DNS_TTL, typeEntry.getType()), now);
}
return newOut;
}
/*
* (non-Javadoc)
* @see javax.jmdns.impl.tasks.Resolver#addQuestions(javax.jmdns.impl.DNSOutgoing)
*/
@Override
protected DNSOutgoing addQuestions(DNSOutgoing out) throws IOException {
return this.addQuestion(out, DNSQuestion.newQuestion("_services._dns-sd._udp.local.", DNSRecordType.TYPE_PTR, DNSRecordClass.CLASS_IN, DNSRecordClass.NOT_UNIQUE));
}
/*
* (non-Javadoc)
* @see javax.jmdns.impl.tasks.Resolver#description()
*/
@Override
protected String description() {
return "querying type";
}
}

View file

@ -1,2 +1,2 @@
package javax.jmdns.impl.tasks.resolver;
package javax.jmdns.impl.tasks.resolver;

View file

@ -1,146 +1,146 @@
// Copyright 2003-2005 Arthur van Hoff, Rick Blair
// Licensed under Apache License version 2.0
// Original license LGPL
package javax.jmdns.impl.tasks.state;
import java.io.IOException;
import java.util.Timer;
import java.util.logging.Logger;
import javax.jmdns.impl.DNSOutgoing;
import javax.jmdns.impl.DNSRecord;
import javax.jmdns.impl.JmDNSImpl;
import javax.jmdns.impl.ServiceInfoImpl;
import javax.jmdns.impl.constants.DNSConstants;
import javax.jmdns.impl.constants.DNSRecordClass;
import javax.jmdns.impl.constants.DNSState;
/**
* The Announcer sends an accumulated query of all announces, and advances the state of all serviceInfos, for which it has sent an announce. The Announcer also sends announcements and advances the state of JmDNS itself.
* <p/>
* When the announcer has run two times, it finishes.
*/
public class Announcer extends DNSStateTask {
static Logger logger = Logger.getLogger(Announcer.class.getName());
public Announcer(JmDNSImpl jmDNSImpl) {
super(jmDNSImpl, defaultTTL());
this.setTaskState(DNSState.ANNOUNCING_1);
this.associate(DNSState.ANNOUNCING_1);
}
/*
* (non-Javadoc)
* @see javax.jmdns.impl.tasks.DNSTask#getName()
*/
@Override
public String getName() {
return "Announcer(" + (this.getDns() != null ? this.getDns().getName() : "") + ")";
}
/*
* (non-Javadoc)
* @see java.lang.Object#toString()
*/
@Override
public String toString() {
return super.toString() + " state: " + this.getTaskState();
}
/*
* (non-Javadoc)
* @see javax.jmdns.impl.tasks.DNSTask#start(java.util.Timer)
*/
@Override
public void start(Timer timer) {
if (!this.getDns().isCanceling() && !this.getDns().isCanceled()) {
timer.schedule(this, DNSConstants.ANNOUNCE_WAIT_INTERVAL, DNSConstants.ANNOUNCE_WAIT_INTERVAL);
}
}
@Override
public boolean cancel() {
this.removeAssociation();
return super.cancel();
}
/*
* (non-Javadoc)
* @see javax.jmdns.impl.tasks.state.DNSStateTask#getTaskDescription()
*/
@Override
public String getTaskDescription() {
return "announcing";
}
/*
* (non-Javadoc)
* @see javax.jmdns.impl.tasks.state.DNSStateTask#checkRunCondition()
*/
@Override
protected boolean checkRunCondition() {
return !this.getDns().isCanceling() && !this.getDns().isCanceled();
}
/*
* (non-Javadoc)
* @see javax.jmdns.impl.tasks.state.DNSStateTask#createOugoing()
*/
@Override
protected DNSOutgoing createOugoing() {
return new DNSOutgoing(DNSConstants.FLAGS_QR_RESPONSE | DNSConstants.FLAGS_AA);
}
/*
* (non-Javadoc)
* @see javax.jmdns.impl.tasks.state.DNSStateTask#buildOutgoingForDNS(javax.jmdns.impl.DNSOutgoing)
*/
@Override
protected DNSOutgoing buildOutgoingForDNS(DNSOutgoing out) throws IOException {
DNSOutgoing newOut = out;
for (DNSRecord answer : this.getDns().getLocalHost().answers(DNSRecordClass.CLASS_ANY, DNSRecordClass.UNIQUE, this.getTTL())) {
newOut = this.addAnswer(newOut, null, answer);
}
return newOut;
}
/*
* (non-Javadoc)
* @see javax.jmdns.impl.tasks.state.DNSStateTask#buildOutgoingForInfo(javax.jmdns.impl.ServiceInfoImpl, javax.jmdns.impl.DNSOutgoing)
*/
@Override
protected DNSOutgoing buildOutgoingForInfo(ServiceInfoImpl info, DNSOutgoing out) throws IOException {
DNSOutgoing newOut = out;
for (DNSRecord answer : info.answers(DNSRecordClass.CLASS_ANY, DNSRecordClass.UNIQUE, this.getTTL(), this.getDns().getLocalHost())) {
newOut = this.addAnswer(newOut, null, answer);
}
return newOut;
}
/*
* (non-Javadoc)
* @see javax.jmdns.impl.tasks.state.DNSStateTask#recoverTask(java.lang.Throwable)
*/
@Override
protected void recoverTask(Throwable e) {
this.getDns().recover();
}
/*
* (non-Javadoc)
* @see javax.jmdns.impl.tasks.state.DNSStateTask#advanceTask()
*/
@Override
protected void advanceTask() {
this.setTaskState(this.getTaskState().advance());
if (!this.getTaskState().isAnnouncing()) {
this.cancel();
this.getDns().startRenewer();
}
}
// Copyright 2003-2005 Arthur van Hoff, Rick Blair
// Licensed under Apache License version 2.0
// Original license LGPL
package javax.jmdns.impl.tasks.state;
import java.io.IOException;
import java.util.Timer;
import java.util.logging.Logger;
import javax.jmdns.impl.DNSOutgoing;
import javax.jmdns.impl.DNSRecord;
import javax.jmdns.impl.JmDNSImpl;
import javax.jmdns.impl.ServiceInfoImpl;
import javax.jmdns.impl.constants.DNSConstants;
import javax.jmdns.impl.constants.DNSRecordClass;
import javax.jmdns.impl.constants.DNSState;
/**
* The Announcer sends an accumulated query of all announces, and advances the state of all serviceInfos, for which it has sent an announce. The Announcer also sends announcements and advances the state of JmDNS itself.
* <p/>
* When the announcer has run two times, it finishes.
*/
public class Announcer extends DNSStateTask {
static Logger logger = Logger.getLogger(Announcer.class.getName());
public Announcer(JmDNSImpl jmDNSImpl) {
super(jmDNSImpl, defaultTTL());
this.setTaskState(DNSState.ANNOUNCING_1);
this.associate(DNSState.ANNOUNCING_1);
}
/*
* (non-Javadoc)
* @see javax.jmdns.impl.tasks.DNSTask#getName()
*/
@Override
public String getName() {
return "Announcer(" + (this.getDns() != null ? this.getDns().getName() : "") + ")";
}
/*
* (non-Javadoc)
* @see java.lang.Object#toString()
*/
@Override
public String toString() {
return super.toString() + " state: " + this.getTaskState();
}
/*
* (non-Javadoc)
* @see javax.jmdns.impl.tasks.DNSTask#start(java.util.Timer)
*/
@Override
public void start(Timer timer) {
if (!this.getDns().isCanceling() && !this.getDns().isCanceled()) {
timer.schedule(this, DNSConstants.ANNOUNCE_WAIT_INTERVAL, DNSConstants.ANNOUNCE_WAIT_INTERVAL);
}
}
@Override
public boolean cancel() {
this.removeAssociation();
return super.cancel();
}
/*
* (non-Javadoc)
* @see javax.jmdns.impl.tasks.state.DNSStateTask#getTaskDescription()
*/
@Override
public String getTaskDescription() {
return "announcing";
}
/*
* (non-Javadoc)
* @see javax.jmdns.impl.tasks.state.DNSStateTask#checkRunCondition()
*/
@Override
protected boolean checkRunCondition() {
return !this.getDns().isCanceling() && !this.getDns().isCanceled();
}
/*
* (non-Javadoc)
* @see javax.jmdns.impl.tasks.state.DNSStateTask#createOugoing()
*/
@Override
protected DNSOutgoing createOugoing() {
return new DNSOutgoing(DNSConstants.FLAGS_QR_RESPONSE | DNSConstants.FLAGS_AA);
}
/*
* (non-Javadoc)
* @see javax.jmdns.impl.tasks.state.DNSStateTask#buildOutgoingForDNS(javax.jmdns.impl.DNSOutgoing)
*/
@Override
protected DNSOutgoing buildOutgoingForDNS(DNSOutgoing out) throws IOException {
DNSOutgoing newOut = out;
for (DNSRecord answer : this.getDns().getLocalHost().answers(DNSRecordClass.CLASS_ANY, DNSRecordClass.UNIQUE, this.getTTL())) {
newOut = this.addAnswer(newOut, null, answer);
}
return newOut;
}
/*
* (non-Javadoc)
* @see javax.jmdns.impl.tasks.state.DNSStateTask#buildOutgoingForInfo(javax.jmdns.impl.ServiceInfoImpl, javax.jmdns.impl.DNSOutgoing)
*/
@Override
protected DNSOutgoing buildOutgoingForInfo(ServiceInfoImpl info, DNSOutgoing out) throws IOException {
DNSOutgoing newOut = out;
for (DNSRecord answer : info.answers(DNSRecordClass.CLASS_ANY, DNSRecordClass.UNIQUE, this.getTTL(), this.getDns().getLocalHost())) {
newOut = this.addAnswer(newOut, null, answer);
}
return newOut;
}
/*
* (non-Javadoc)
* @see javax.jmdns.impl.tasks.state.DNSStateTask#recoverTask(java.lang.Throwable)
*/
@Override
protected void recoverTask(Throwable e) {
this.getDns().recover();
}
/*
* (non-Javadoc)
* @see javax.jmdns.impl.tasks.state.DNSStateTask#advanceTask()
*/
@Override
protected void advanceTask() {
this.setTaskState(this.getTaskState().advance());
if (!this.getTaskState().isAnnouncing()) {
this.cancel();
this.getDns().startRenewer();
}
}
}

View file

@ -1,143 +1,143 @@
// Copyright 2003-2005 Arthur van Hoff, Rick Blair
// Licensed under Apache License version 2.0
// Original license LGPL
package javax.jmdns.impl.tasks.state;
import java.io.IOException;
import java.util.Timer;
import java.util.logging.Logger;
import javax.jmdns.impl.DNSOutgoing;
import javax.jmdns.impl.DNSRecord;
import javax.jmdns.impl.JmDNSImpl;
import javax.jmdns.impl.ServiceInfoImpl;
import javax.jmdns.impl.constants.DNSConstants;
import javax.jmdns.impl.constants.DNSRecordClass;
import javax.jmdns.impl.constants.DNSState;
/**
* The Canceler sends two announces with TTL=0 for the specified services.
*/
public class Canceler extends DNSStateTask {
static Logger logger = Logger.getLogger(Canceler.class.getName());
public Canceler(JmDNSImpl jmDNSImpl) {
super(jmDNSImpl, 0);
this.setTaskState(DNSState.CANCELING_1);
this.associate(DNSState.CANCELING_1);
}
/*
* (non-Javadoc)
* @see javax.jmdns.impl.tasks.DNSTask#getName()
*/
@Override
public String getName() {
return "Canceler(" + (this.getDns() != null ? this.getDns().getName() : "") + ")";
}
/*
* (non-Javadoc)
* @see java.lang.Object#toString()
*/
@Override
public String toString() {
return super.toString() + " state: " + this.getTaskState();
}
/*
* (non-Javadoc)
* @see javax.jmdns.impl.tasks.DNSTask#start(java.util.Timer)
*/
@Override
public void start(Timer timer) {
timer.schedule(this, 0, DNSConstants.ANNOUNCE_WAIT_INTERVAL);
}
/*
* (non-Javadoc)
* @see java.util.TimerTask#cancel()
*/
@Override
public boolean cancel() {
this.removeAssociation();
return super.cancel();
}
/*
* (non-Javadoc)
* @see javax.jmdns.impl.tasks.state.DNSStateTask#getTaskDescription()
*/
@Override
public String getTaskDescription() {
return "canceling";
}
/*
* (non-Javadoc)
* @see javax.jmdns.impl.tasks.state.DNSStateTask#checkRunCondition()
*/
@Override
protected boolean checkRunCondition() {
return true;
}
/*
* (non-Javadoc)
* @see javax.jmdns.impl.tasks.state.DNSStateTask#createOugoing()
*/
@Override
protected DNSOutgoing createOugoing() {
return new DNSOutgoing(DNSConstants.FLAGS_QR_RESPONSE | DNSConstants.FLAGS_AA);
}
/*
* (non-Javadoc)
* @see javax.jmdns.impl.tasks.state.DNSStateTask#buildOutgoingForDNS(javax.jmdns.impl.DNSOutgoing)
*/
@Override
protected DNSOutgoing buildOutgoingForDNS(DNSOutgoing out) throws IOException {
DNSOutgoing newOut = out;
for (DNSRecord answer : this.getDns().getLocalHost().answers(DNSRecordClass.CLASS_ANY, DNSRecordClass.UNIQUE, this.getTTL())) {
newOut = this.addAnswer(newOut, null, answer);
}
return newOut;
}
/*
* (non-Javadoc)
* @see javax.jmdns.impl.tasks.state.DNSStateTask#buildOutgoingForInfo(javax.jmdns.impl.ServiceInfoImpl, javax.jmdns.impl.DNSOutgoing)
*/
@Override
protected DNSOutgoing buildOutgoingForInfo(ServiceInfoImpl info, DNSOutgoing out) throws IOException {
DNSOutgoing newOut = out;
for (DNSRecord answer : info.answers(DNSRecordClass.CLASS_ANY, DNSRecordClass.UNIQUE, this.getTTL(), this.getDns().getLocalHost())) {
newOut = this.addAnswer(newOut, null, answer);
}
return newOut;
}
/*
* (non-Javadoc)
* @see javax.jmdns.impl.tasks.state.DNSStateTask#recoverTask(java.lang.Throwable)
*/
@Override
protected void recoverTask(Throwable e) {
this.getDns().recover();
}
/*
* (non-Javadoc)
* @see javax.jmdns.impl.tasks.state.DNSStateTask#advanceTask()
*/
@Override
protected void advanceTask() {
this.setTaskState(this.getTaskState().advance());
if (!this.getTaskState().isCanceling()) {
cancel();
}
}
// Copyright 2003-2005 Arthur van Hoff, Rick Blair
// Licensed under Apache License version 2.0
// Original license LGPL
package javax.jmdns.impl.tasks.state;
import java.io.IOException;
import java.util.Timer;
import java.util.logging.Logger;
import javax.jmdns.impl.DNSOutgoing;
import javax.jmdns.impl.DNSRecord;
import javax.jmdns.impl.JmDNSImpl;
import javax.jmdns.impl.ServiceInfoImpl;
import javax.jmdns.impl.constants.DNSConstants;
import javax.jmdns.impl.constants.DNSRecordClass;
import javax.jmdns.impl.constants.DNSState;
/**
* The Canceler sends two announces with TTL=0 for the specified services.
*/
public class Canceler extends DNSStateTask {
static Logger logger = Logger.getLogger(Canceler.class.getName());
public Canceler(JmDNSImpl jmDNSImpl) {
super(jmDNSImpl, 0);
this.setTaskState(DNSState.CANCELING_1);
this.associate(DNSState.CANCELING_1);
}
/*
* (non-Javadoc)
* @see javax.jmdns.impl.tasks.DNSTask#getName()
*/
@Override
public String getName() {
return "Canceler(" + (this.getDns() != null ? this.getDns().getName() : "") + ")";
}
/*
* (non-Javadoc)
* @see java.lang.Object#toString()
*/
@Override
public String toString() {
return super.toString() + " state: " + this.getTaskState();
}
/*
* (non-Javadoc)
* @see javax.jmdns.impl.tasks.DNSTask#start(java.util.Timer)
*/
@Override
public void start(Timer timer) {
timer.schedule(this, 0, DNSConstants.ANNOUNCE_WAIT_INTERVAL);
}
/*
* (non-Javadoc)
* @see java.util.TimerTask#cancel()
*/
@Override
public boolean cancel() {
this.removeAssociation();
return super.cancel();
}
/*
* (non-Javadoc)
* @see javax.jmdns.impl.tasks.state.DNSStateTask#getTaskDescription()
*/
@Override
public String getTaskDescription() {
return "canceling";
}
/*
* (non-Javadoc)
* @see javax.jmdns.impl.tasks.state.DNSStateTask#checkRunCondition()
*/
@Override
protected boolean checkRunCondition() {
return true;
}
/*
* (non-Javadoc)
* @see javax.jmdns.impl.tasks.state.DNSStateTask#createOugoing()
*/
@Override
protected DNSOutgoing createOugoing() {
return new DNSOutgoing(DNSConstants.FLAGS_QR_RESPONSE | DNSConstants.FLAGS_AA);
}
/*
* (non-Javadoc)
* @see javax.jmdns.impl.tasks.state.DNSStateTask#buildOutgoingForDNS(javax.jmdns.impl.DNSOutgoing)
*/
@Override
protected DNSOutgoing buildOutgoingForDNS(DNSOutgoing out) throws IOException {
DNSOutgoing newOut = out;
for (DNSRecord answer : this.getDns().getLocalHost().answers(DNSRecordClass.CLASS_ANY, DNSRecordClass.UNIQUE, this.getTTL())) {
newOut = this.addAnswer(newOut, null, answer);
}
return newOut;
}
/*
* (non-Javadoc)
* @see javax.jmdns.impl.tasks.state.DNSStateTask#buildOutgoingForInfo(javax.jmdns.impl.ServiceInfoImpl, javax.jmdns.impl.DNSOutgoing)
*/
@Override
protected DNSOutgoing buildOutgoingForInfo(ServiceInfoImpl info, DNSOutgoing out) throws IOException {
DNSOutgoing newOut = out;
for (DNSRecord answer : info.answers(DNSRecordClass.CLASS_ANY, DNSRecordClass.UNIQUE, this.getTTL(), this.getDns().getLocalHost())) {
newOut = this.addAnswer(newOut, null, answer);
}
return newOut;
}
/*
* (non-Javadoc)
* @see javax.jmdns.impl.tasks.state.DNSStateTask#recoverTask(java.lang.Throwable)
*/
@Override
protected void recoverTask(Throwable e) {
this.getDns().recover();
}
/*
* (non-Javadoc)
* @see javax.jmdns.impl.tasks.state.DNSStateTask#advanceTask()
*/
@Override
protected void advanceTask() {
this.setTaskState(this.getTaskState().advance());
if (!this.getTaskState().isCanceling()) {
cancel();
}
}
}

View file

@ -1,188 +1,188 @@
// Licensed under Apache License version 2.0
package javax.jmdns.impl.tasks.state;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.jmdns.ServiceInfo;
import javax.jmdns.impl.DNSOutgoing;
import javax.jmdns.impl.DNSStatefulObject;
import javax.jmdns.impl.JmDNSImpl;
import javax.jmdns.impl.ServiceInfoImpl;
import javax.jmdns.impl.constants.DNSConstants;
import javax.jmdns.impl.constants.DNSState;
import javax.jmdns.impl.tasks.DNSTask;
/**
* This is the root class for all state tasks. These tasks work with objects that implements the {@link javax.jmdns.impl.DNSStatefulObject} interface and therefore participate in the state machine.
*
* @author Pierre Frisch
*/
public abstract class DNSStateTask extends DNSTask {
static Logger logger1 = Logger.getLogger(DNSStateTask.class.getName());
/**
* By setting a 0 ttl we effectively expire the record.
*/
private final int _ttl;
private static int _defaultTTL = DNSConstants.DNS_TTL;
/**
* The state of the task.
*/
private DNSState _taskState = null;
public abstract String getTaskDescription();
public static int defaultTTL() {
return _defaultTTL;
}
/**
* For testing only do not use in production.
*
* @param value
*/
public static void setDefaultTTL(int value) {
_defaultTTL = value;
}
/**
* @param jmDNSImpl
* @param ttl
*/
public DNSStateTask(JmDNSImpl jmDNSImpl, int ttl) {
super(jmDNSImpl);
_ttl = ttl;
}
/**
* @return the ttl
*/
public int getTTL() {
return _ttl;
}
/**
* Associate the DNS host and the service infos with this task if not already associated and in the same state.
*
* @param state
* target state
*/
protected void associate(DNSState state) {
synchronized (this.getDns()) {
this.getDns().associateWithTask(this, state);
}
for (ServiceInfo serviceInfo : this.getDns().getServices().values()) {
((ServiceInfoImpl) serviceInfo).associateWithTask(this, state);
}
}
/**
* Remove the DNS host and service info association with this task.
*/
protected void removeAssociation() {
// Remove association from host to this
synchronized (this.getDns()) {
this.getDns().removeAssociationWithTask(this);
}
// Remove associations from services to this
for (ServiceInfo serviceInfo : this.getDns().getServices().values()) {
((ServiceInfoImpl) serviceInfo).removeAssociationWithTask(this);
}
}
@Override
public void run() {
DNSOutgoing out = this.createOugoing();
try {
if (!this.checkRunCondition()) {
this.cancel();
return;
}
List<DNSStatefulObject> stateObjects = new ArrayList<DNSStatefulObject>();
// send probes for JmDNS itself
synchronized (this.getDns()) {
if (this.getDns().isAssociatedWithTask(this, this.getTaskState())) {
logger1.finer(this.getName() + ".run() JmDNS " + this.getTaskDescription() + " " + this.getDns().getName());
stateObjects.add(this.getDns());
out = this.buildOutgoingForDNS(out);
}
}
// send probes for services
for (ServiceInfo serviceInfo : this.getDns().getServices().values()) {
ServiceInfoImpl info = (ServiceInfoImpl) serviceInfo;
synchronized (info) {
if (info.isAssociatedWithTask(this, this.getTaskState())) {
logger1.fine(this.getName() + ".run() JmDNS " + this.getTaskDescription() + " " + info.getQualifiedName());
stateObjects.add(info);
out = this.buildOutgoingForInfo(info, out);
}
}
}
if (!out.isEmpty()) {
logger1.finer(this.getName() + ".run() JmDNS " + this.getTaskDescription() + " #" + this.getTaskState());
this.getDns().send(out);
// Advance the state of objects.
this.advanceObjectsState(stateObjects);
} else {
// Advance the state of objects.
this.advanceObjectsState(stateObjects);
// If we have nothing to send, another timer taskState ahead of us has done the job for us. We can cancel.
cancel();
return;
}
} catch (Throwable e) {
logger1.log(Level.WARNING, this.getName() + ".run() exception ", e);
this.recoverTask(e);
}
this.advanceTask();
}
protected abstract boolean checkRunCondition();
protected abstract DNSOutgoing buildOutgoingForDNS(DNSOutgoing out) throws IOException;
protected abstract DNSOutgoing buildOutgoingForInfo(ServiceInfoImpl info, DNSOutgoing out) throws IOException;
protected abstract DNSOutgoing createOugoing();
protected void advanceObjectsState(List<DNSStatefulObject> list) {
if (list != null) {
for (DNSStatefulObject object : list) {
synchronized (object) {
object.advanceState(this);
}
}
}
}
protected abstract void recoverTask(Throwable e);
protected abstract void advanceTask();
/**
* @return the taskState
*/
protected DNSState getTaskState() {
return this._taskState;
}
/**
* @param taskState
* the taskState to set
*/
protected void setTaskState(DNSState taskState) {
this._taskState = taskState;
}
}
// Licensed under Apache License version 2.0
package javax.jmdns.impl.tasks.state;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.jmdns.ServiceInfo;
import javax.jmdns.impl.DNSOutgoing;
import javax.jmdns.impl.DNSStatefulObject;
import javax.jmdns.impl.JmDNSImpl;
import javax.jmdns.impl.ServiceInfoImpl;
import javax.jmdns.impl.constants.DNSConstants;
import javax.jmdns.impl.constants.DNSState;
import javax.jmdns.impl.tasks.DNSTask;
/**
* This is the root class for all state tasks. These tasks work with objects that implements the {@link javax.jmdns.impl.DNSStatefulObject} interface and therefore participate in the state machine.
*
* @author Pierre Frisch
*/
public abstract class DNSStateTask extends DNSTask {
static Logger logger1 = Logger.getLogger(DNSStateTask.class.getName());
/**
* By setting a 0 ttl we effectively expire the record.
*/
private final int _ttl;
private static int _defaultTTL = DNSConstants.DNS_TTL;
/**
* The state of the task.
*/
private DNSState _taskState = null;
public abstract String getTaskDescription();
public static int defaultTTL() {
return _defaultTTL;
}
/**
* For testing only do not use in production.
*
* @param value
*/
public static void setDefaultTTL(int value) {
_defaultTTL = value;
}
/**
* @param jmDNSImpl
* @param ttl
*/
public DNSStateTask(JmDNSImpl jmDNSImpl, int ttl) {
super(jmDNSImpl);
_ttl = ttl;
}
/**
* @return the ttl
*/
public int getTTL() {
return _ttl;
}
/**
* Associate the DNS host and the service infos with this task if not already associated and in the same state.
*
* @param state
* target state
*/
protected void associate(DNSState state) {
synchronized (this.getDns()) {
this.getDns().associateWithTask(this, state);
}
for (ServiceInfo serviceInfo : this.getDns().getServices().values()) {
((ServiceInfoImpl) serviceInfo).associateWithTask(this, state);
}
}
/**
* Remove the DNS host and service info association with this task.
*/
protected void removeAssociation() {
// Remove association from host to this
synchronized (this.getDns()) {
this.getDns().removeAssociationWithTask(this);
}
// Remove associations from services to this
for (ServiceInfo serviceInfo : this.getDns().getServices().values()) {
((ServiceInfoImpl) serviceInfo).removeAssociationWithTask(this);
}
}
@Override
public void run() {
DNSOutgoing out = this.createOugoing();
try {
if (!this.checkRunCondition()) {
this.cancel();
return;
}
List<DNSStatefulObject> stateObjects = new ArrayList<DNSStatefulObject>();
// send probes for JmDNS itself
synchronized (this.getDns()) {
if (this.getDns().isAssociatedWithTask(this, this.getTaskState())) {
logger1.finer(this.getName() + ".run() JmDNS " + this.getTaskDescription() + " " + this.getDns().getName());
stateObjects.add(this.getDns());
out = this.buildOutgoingForDNS(out);
}
}
// send probes for services
for (ServiceInfo serviceInfo : this.getDns().getServices().values()) {
ServiceInfoImpl info = (ServiceInfoImpl) serviceInfo;
synchronized (info) {
if (info.isAssociatedWithTask(this, this.getTaskState())) {
logger1.fine(this.getName() + ".run() JmDNS " + this.getTaskDescription() + " " + info.getQualifiedName());
stateObjects.add(info);
out = this.buildOutgoingForInfo(info, out);
}
}
}
if (!out.isEmpty()) {
logger1.finer(this.getName() + ".run() JmDNS " + this.getTaskDescription() + " #" + this.getTaskState());
this.getDns().send(out);
// Advance the state of objects.
this.advanceObjectsState(stateObjects);
} else {
// Advance the state of objects.
this.advanceObjectsState(stateObjects);
// If we have nothing to send, another timer taskState ahead of us has done the job for us. We can cancel.
cancel();
return;
}
} catch (Throwable e) {
logger1.log(Level.WARNING, this.getName() + ".run() exception ", e);
this.recoverTask(e);
}
this.advanceTask();
}
protected abstract boolean checkRunCondition();
protected abstract DNSOutgoing buildOutgoingForDNS(DNSOutgoing out) throws IOException;
protected abstract DNSOutgoing buildOutgoingForInfo(ServiceInfoImpl info, DNSOutgoing out) throws IOException;
protected abstract DNSOutgoing createOugoing();
protected void advanceObjectsState(List<DNSStatefulObject> list) {
if (list != null) {
for (DNSStatefulObject object : list) {
synchronized (object) {
object.advanceState(this);
}
}
}
}
protected abstract void recoverTask(Throwable e);
protected abstract void advanceTask();
/**
* @return the taskState
*/
protected DNSState getTaskState() {
return this._taskState;
}
/**
* @param taskState
* the taskState to set
*/
protected void setTaskState(DNSState taskState) {
this._taskState = taskState;
}
}

View file

@ -1,161 +1,161 @@
// Copyright 2003-2005 Arthur van Hoff, Rick Blair
// Licensed under Apache License version 2.0
// Original license LGPL
package javax.jmdns.impl.tasks.state;
import java.io.IOException;
import java.util.Timer;
import java.util.logging.Logger;
import javax.jmdns.impl.DNSOutgoing;
import javax.jmdns.impl.DNSQuestion;
import javax.jmdns.impl.DNSRecord;
import javax.jmdns.impl.JmDNSImpl;
import javax.jmdns.impl.ServiceInfoImpl;
import javax.jmdns.impl.constants.DNSConstants;
import javax.jmdns.impl.constants.DNSRecordClass;
import javax.jmdns.impl.constants.DNSRecordType;
import javax.jmdns.impl.constants.DNSState;
/**
* The Prober sends three consecutive probes for all service infos that needs probing as well as for the host name. The state of each service info of the host name is advanced, when a probe has been sent for it. When the prober has run three times,
* it launches an Announcer.
* <p/>
* If a conflict during probes occurs, the affected service infos (and affected host name) are taken away from the prober. This eventually causes the prober to cancel itself.
*/
public class Prober extends DNSStateTask {
static Logger logger = Logger.getLogger(Prober.class.getName());
public Prober(JmDNSImpl jmDNSImpl) {
super(jmDNSImpl, defaultTTL());
this.setTaskState(DNSState.PROBING_1);
this.associate(DNSState.PROBING_1);
}
/*
* (non-Javadoc)
* @see javax.jmdns.impl.tasks.DNSTask#getName()
*/
@Override
public String getName() {
return "Prober(" + (this.getDns() != null ? this.getDns().getName() : "") + ")";
}
/*
* (non-Javadoc)
* @see java.lang.Object#toString()
*/
@Override
public String toString() {
return super.toString() + " state: " + this.getTaskState();
}
/*
* (non-Javadoc)
* @see javax.jmdns.impl.tasks.DNSTask#start(java.util.Timer)
*/
@Override
public void start(Timer timer) {
long now = System.currentTimeMillis();
if (now - this.getDns().getLastThrottleIncrement() < DNSConstants.PROBE_THROTTLE_COUNT_INTERVAL) {
this.getDns().setThrottle(this.getDns().getThrottle() + 1);
} else {
this.getDns().setThrottle(1);
}
this.getDns().setLastThrottleIncrement(now);
if (this.getDns().isAnnounced() && this.getDns().getThrottle() < DNSConstants.PROBE_THROTTLE_COUNT) {
timer.schedule(this, JmDNSImpl.getRandom().nextInt(1 + DNSConstants.PROBE_WAIT_INTERVAL), DNSConstants.PROBE_WAIT_INTERVAL);
} else if (!this.getDns().isCanceling() && !this.getDns().isCanceled()) {
timer.schedule(this, DNSConstants.PROBE_CONFLICT_INTERVAL, DNSConstants.PROBE_CONFLICT_INTERVAL);
}
}
@Override
public boolean cancel() {
this.removeAssociation();
return super.cancel();
}
/*
* (non-Javadoc)
* @see javax.jmdns.impl.tasks.state.DNSStateTask#getTaskDescription()
*/
@Override
public String getTaskDescription() {
return "probing";
}
/*
* (non-Javadoc)
* @see javax.jmdns.impl.tasks.state.DNSStateTask#checkRunCondition()
*/
@Override
protected boolean checkRunCondition() {
return !this.getDns().isCanceling() && !this.getDns().isCanceled();
}
/*
* (non-Javadoc)
* @see javax.jmdns.impl.tasks.state.DNSStateTask#createOugoing()
*/
@Override
protected DNSOutgoing createOugoing() {
return new DNSOutgoing(DNSConstants.FLAGS_QR_QUERY);
}
/*
* (non-Javadoc)
* @see javax.jmdns.impl.tasks.state.DNSStateTask#buildOutgoingForDNS(javax.jmdns.impl.DNSOutgoing)
*/
@Override
protected DNSOutgoing buildOutgoingForDNS(DNSOutgoing out) throws IOException {
DNSOutgoing newOut = out;
newOut.addQuestion(DNSQuestion.newQuestion(this.getDns().getLocalHost().getName(), DNSRecordType.TYPE_ANY, DNSRecordClass.CLASS_IN, DNSRecordClass.NOT_UNIQUE));
for (DNSRecord answer : this.getDns().getLocalHost().answers(DNSRecordClass.CLASS_ANY, DNSRecordClass.NOT_UNIQUE, this.getTTL())) {
newOut = this.addAuthoritativeAnswer(newOut, answer);
}
return newOut;
}
/*
* (non-Javadoc)
* @see javax.jmdns.impl.tasks.state.DNSStateTask#buildOutgoingForInfo(javax.jmdns.impl.ServiceInfoImpl, javax.jmdns.impl.DNSOutgoing)
*/
@Override
protected DNSOutgoing buildOutgoingForInfo(ServiceInfoImpl info, DNSOutgoing out) throws IOException {
DNSOutgoing newOut = out;
newOut = this.addQuestion(newOut, DNSQuestion.newQuestion(info.getQualifiedName(), DNSRecordType.TYPE_ANY, DNSRecordClass.CLASS_IN, DNSRecordClass.NOT_UNIQUE));
// the "unique" flag should be not set here because these answers haven't been proven unique yet this means the record will not exactly match the announcement record
newOut = this.addAuthoritativeAnswer(newOut, new DNSRecord.Service(info.getQualifiedName(), DNSRecordClass.CLASS_IN, DNSRecordClass.NOT_UNIQUE, this.getTTL(), info.getPriority(), info.getWeight(), info.getPort(), this.getDns().getLocalHost()
.getName()));
return newOut;
}
/*
* (non-Javadoc)
* @see javax.jmdns.impl.tasks.state.DNSStateTask#recoverTask(java.lang.Throwable)
*/
@Override
protected void recoverTask(Throwable e) {
this.getDns().recover();
}
/*
* (non-Javadoc)
* @see javax.jmdns.impl.tasks.state.DNSStateTask#advanceTask()
*/
@Override
protected void advanceTask() {
this.setTaskState(this.getTaskState().advance());
if (!this.getTaskState().isProbing()) {
cancel();
this.getDns().startAnnouncer();
}
}
// Copyright 2003-2005 Arthur van Hoff, Rick Blair
// Licensed under Apache License version 2.0
// Original license LGPL
package javax.jmdns.impl.tasks.state;
import java.io.IOException;
import java.util.Timer;
import java.util.logging.Logger;
import javax.jmdns.impl.DNSOutgoing;
import javax.jmdns.impl.DNSQuestion;
import javax.jmdns.impl.DNSRecord;
import javax.jmdns.impl.JmDNSImpl;
import javax.jmdns.impl.ServiceInfoImpl;
import javax.jmdns.impl.constants.DNSConstants;
import javax.jmdns.impl.constants.DNSRecordClass;
import javax.jmdns.impl.constants.DNSRecordType;
import javax.jmdns.impl.constants.DNSState;
/**
* The Prober sends three consecutive probes for all service infos that needs probing as well as for the host name. The state of each service info of the host name is advanced, when a probe has been sent for it. When the prober has run three times,
* it launches an Announcer.
* <p/>
* If a conflict during probes occurs, the affected service infos (and affected host name) are taken away from the prober. This eventually causes the prober to cancel itself.
*/
public class Prober extends DNSStateTask {
static Logger logger = Logger.getLogger(Prober.class.getName());
public Prober(JmDNSImpl jmDNSImpl) {
super(jmDNSImpl, defaultTTL());
this.setTaskState(DNSState.PROBING_1);
this.associate(DNSState.PROBING_1);
}
/*
* (non-Javadoc)
* @see javax.jmdns.impl.tasks.DNSTask#getName()
*/
@Override
public String getName() {
return "Prober(" + (this.getDns() != null ? this.getDns().getName() : "") + ")";
}
/*
* (non-Javadoc)
* @see java.lang.Object#toString()
*/
@Override
public String toString() {
return super.toString() + " state: " + this.getTaskState();
}
/*
* (non-Javadoc)
* @see javax.jmdns.impl.tasks.DNSTask#start(java.util.Timer)
*/
@Override
public void start(Timer timer) {
long now = System.currentTimeMillis();
if (now - this.getDns().getLastThrottleIncrement() < DNSConstants.PROBE_THROTTLE_COUNT_INTERVAL) {
this.getDns().setThrottle(this.getDns().getThrottle() + 1);
} else {
this.getDns().setThrottle(1);
}
this.getDns().setLastThrottleIncrement(now);
if (this.getDns().isAnnounced() && this.getDns().getThrottle() < DNSConstants.PROBE_THROTTLE_COUNT) {
timer.schedule(this, JmDNSImpl.getRandom().nextInt(1 + DNSConstants.PROBE_WAIT_INTERVAL), DNSConstants.PROBE_WAIT_INTERVAL);
} else if (!this.getDns().isCanceling() && !this.getDns().isCanceled()) {
timer.schedule(this, DNSConstants.PROBE_CONFLICT_INTERVAL, DNSConstants.PROBE_CONFLICT_INTERVAL);
}
}
@Override
public boolean cancel() {
this.removeAssociation();
return super.cancel();
}
/*
* (non-Javadoc)
* @see javax.jmdns.impl.tasks.state.DNSStateTask#getTaskDescription()
*/
@Override
public String getTaskDescription() {
return "probing";
}
/*
* (non-Javadoc)
* @see javax.jmdns.impl.tasks.state.DNSStateTask#checkRunCondition()
*/
@Override
protected boolean checkRunCondition() {
return !this.getDns().isCanceling() && !this.getDns().isCanceled();
}
/*
* (non-Javadoc)
* @see javax.jmdns.impl.tasks.state.DNSStateTask#createOugoing()
*/
@Override
protected DNSOutgoing createOugoing() {
return new DNSOutgoing(DNSConstants.FLAGS_QR_QUERY);
}
/*
* (non-Javadoc)
* @see javax.jmdns.impl.tasks.state.DNSStateTask#buildOutgoingForDNS(javax.jmdns.impl.DNSOutgoing)
*/
@Override
protected DNSOutgoing buildOutgoingForDNS(DNSOutgoing out) throws IOException {
DNSOutgoing newOut = out;
newOut.addQuestion(DNSQuestion.newQuestion(this.getDns().getLocalHost().getName(), DNSRecordType.TYPE_ANY, DNSRecordClass.CLASS_IN, DNSRecordClass.NOT_UNIQUE));
for (DNSRecord answer : this.getDns().getLocalHost().answers(DNSRecordClass.CLASS_ANY, DNSRecordClass.NOT_UNIQUE, this.getTTL())) {
newOut = this.addAuthoritativeAnswer(newOut, answer);
}
return newOut;
}
/*
* (non-Javadoc)
* @see javax.jmdns.impl.tasks.state.DNSStateTask#buildOutgoingForInfo(javax.jmdns.impl.ServiceInfoImpl, javax.jmdns.impl.DNSOutgoing)
*/
@Override
protected DNSOutgoing buildOutgoingForInfo(ServiceInfoImpl info, DNSOutgoing out) throws IOException {
DNSOutgoing newOut = out;
newOut = this.addQuestion(newOut, DNSQuestion.newQuestion(info.getQualifiedName(), DNSRecordType.TYPE_ANY, DNSRecordClass.CLASS_IN, DNSRecordClass.NOT_UNIQUE));
// the "unique" flag should be not set here because these answers haven't been proven unique yet this means the record will not exactly match the announcement record
newOut = this.addAuthoritativeAnswer(newOut, new DNSRecord.Service(info.getQualifiedName(), DNSRecordClass.CLASS_IN, DNSRecordClass.NOT_UNIQUE, this.getTTL(), info.getPriority(), info.getWeight(), info.getPort(), this.getDns().getLocalHost()
.getName()));
return newOut;
}
/*
* (non-Javadoc)
* @see javax.jmdns.impl.tasks.state.DNSStateTask#recoverTask(java.lang.Throwable)
*/
@Override
protected void recoverTask(Throwable e) {
this.getDns().recover();
}
/*
* (non-Javadoc)
* @see javax.jmdns.impl.tasks.state.DNSStateTask#advanceTask()
*/
@Override
protected void advanceTask() {
this.setTaskState(this.getTaskState().advance());
if (!this.getTaskState().isProbing()) {
cancel();
this.getDns().startAnnouncer();
}
}
}

View file

@ -1,141 +1,141 @@
// Copyright 2003-2005 Arthur van Hoff, Rick Blair
// Licensed under Apache License version 2.0
// Original license LGPL
package javax.jmdns.impl.tasks.state;
import java.io.IOException;
import java.util.Timer;
import java.util.logging.Logger;
import javax.jmdns.impl.DNSOutgoing;
import javax.jmdns.impl.DNSRecord;
import javax.jmdns.impl.JmDNSImpl;
import javax.jmdns.impl.ServiceInfoImpl;
import javax.jmdns.impl.constants.DNSConstants;
import javax.jmdns.impl.constants.DNSRecordClass;
import javax.jmdns.impl.constants.DNSState;
/**
* The Renewer is there to send renewal announcement when the record expire for ours infos.
*/
public class Renewer extends DNSStateTask {
static Logger logger = Logger.getLogger(Renewer.class.getName());
public Renewer(JmDNSImpl jmDNSImpl) {
super(jmDNSImpl, defaultTTL());
this.setTaskState(DNSState.ANNOUNCED);
this.associate(DNSState.ANNOUNCED);
}
/*
* (non-Javadoc)
* @see javax.jmdns.impl.tasks.DNSTask#getName()
*/
@Override
public String getName() {
return "Renewer(" + (this.getDns() != null ? this.getDns().getName() : "") + ")";
}
/*
* (non-Javadoc)
* @see java.lang.Object#toString()
*/
@Override
public String toString() {
return super.toString() + " state: " + this.getTaskState();
}
/*
* (non-Javadoc)
* @see javax.jmdns.impl.tasks.DNSTask#start(java.util.Timer)
*/
@Override
public void start(Timer timer) {
if (!this.getDns().isCanceling() && !this.getDns().isCanceled()) {
timer.schedule(this, DNSConstants.ANNOUNCED_RENEWAL_TTL_INTERVAL, DNSConstants.ANNOUNCED_RENEWAL_TTL_INTERVAL);
}
}
@Override
public boolean cancel() {
this.removeAssociation();
return super.cancel();
}
/*
* (non-Javadoc)
* @see javax.jmdns.impl.tasks.state.DNSStateTask#getTaskDescription()
*/
@Override
public String getTaskDescription() {
return "renewing";
}
/*
* (non-Javadoc)
* @see javax.jmdns.impl.tasks.state.DNSStateTask#checkRunCondition()
*/
@Override
protected boolean checkRunCondition() {
return !this.getDns().isCanceling() && !this.getDns().isCanceled();
}
/*
* (non-Javadoc)
* @see javax.jmdns.impl.tasks.state.DNSStateTask#createOugoing()
*/
@Override
protected DNSOutgoing createOugoing() {
return new DNSOutgoing(DNSConstants.FLAGS_QR_RESPONSE | DNSConstants.FLAGS_AA);
}
/*
* (non-Javadoc)
* @see javax.jmdns.impl.tasks.state.DNSStateTask#buildOutgoingForDNS(javax.jmdns.impl.DNSOutgoing)
*/
@Override
protected DNSOutgoing buildOutgoingForDNS(DNSOutgoing out) throws IOException {
DNSOutgoing newOut = out;
for (DNSRecord answer : this.getDns().getLocalHost().answers(DNSRecordClass.CLASS_ANY, DNSRecordClass.UNIQUE, this.getTTL())) {
newOut = this.addAnswer(newOut, null, answer);
}
return newOut;
}
/*
* (non-Javadoc)
* @see javax.jmdns.impl.tasks.state.DNSStateTask#buildOutgoingForInfo(javax.jmdns.impl.ServiceInfoImpl, javax.jmdns.impl.DNSOutgoing)
*/
@Override
protected DNSOutgoing buildOutgoingForInfo(ServiceInfoImpl info, DNSOutgoing out) throws IOException {
DNSOutgoing newOut = out;
for (DNSRecord answer : info.answers(DNSRecordClass.CLASS_ANY, DNSRecordClass.UNIQUE, this.getTTL(), this.getDns().getLocalHost())) {
newOut = this.addAnswer(newOut, null, answer);
}
return newOut;
}
/*
* (non-Javadoc)
* @see javax.jmdns.impl.tasks.state.DNSStateTask#recoverTask(java.lang.Throwable)
*/
@Override
protected void recoverTask(Throwable e) {
this.getDns().recover();
}
/*
* (non-Javadoc)
* @see javax.jmdns.impl.tasks.state.DNSStateTask#advanceTask()
*/
@Override
protected void advanceTask() {
this.setTaskState(this.getTaskState().advance());
if (!this.getTaskState().isAnnounced()) {
cancel();
}
}
// Copyright 2003-2005 Arthur van Hoff, Rick Blair
// Licensed under Apache License version 2.0
// Original license LGPL
package javax.jmdns.impl.tasks.state;
import java.io.IOException;
import java.util.Timer;
import java.util.logging.Logger;
import javax.jmdns.impl.DNSOutgoing;
import javax.jmdns.impl.DNSRecord;
import javax.jmdns.impl.JmDNSImpl;
import javax.jmdns.impl.ServiceInfoImpl;
import javax.jmdns.impl.constants.DNSConstants;
import javax.jmdns.impl.constants.DNSRecordClass;
import javax.jmdns.impl.constants.DNSState;
/**
* The Renewer is there to send renewal announcement when the record expire for ours infos.
*/
public class Renewer extends DNSStateTask {
static Logger logger = Logger.getLogger(Renewer.class.getName());
public Renewer(JmDNSImpl jmDNSImpl) {
super(jmDNSImpl, defaultTTL());
this.setTaskState(DNSState.ANNOUNCED);
this.associate(DNSState.ANNOUNCED);
}
/*
* (non-Javadoc)
* @see javax.jmdns.impl.tasks.DNSTask#getName()
*/
@Override
public String getName() {
return "Renewer(" + (this.getDns() != null ? this.getDns().getName() : "") + ")";
}
/*
* (non-Javadoc)
* @see java.lang.Object#toString()
*/
@Override
public String toString() {
return super.toString() + " state: " + this.getTaskState();
}
/*
* (non-Javadoc)
* @see javax.jmdns.impl.tasks.DNSTask#start(java.util.Timer)
*/
@Override
public void start(Timer timer) {
if (!this.getDns().isCanceling() && !this.getDns().isCanceled()) {
timer.schedule(this, DNSConstants.ANNOUNCED_RENEWAL_TTL_INTERVAL, DNSConstants.ANNOUNCED_RENEWAL_TTL_INTERVAL);
}
}
@Override
public boolean cancel() {
this.removeAssociation();
return super.cancel();
}
/*
* (non-Javadoc)
* @see javax.jmdns.impl.tasks.state.DNSStateTask#getTaskDescription()
*/
@Override
public String getTaskDescription() {
return "renewing";
}
/*
* (non-Javadoc)
* @see javax.jmdns.impl.tasks.state.DNSStateTask#checkRunCondition()
*/
@Override
protected boolean checkRunCondition() {
return !this.getDns().isCanceling() && !this.getDns().isCanceled();
}
/*
* (non-Javadoc)
* @see javax.jmdns.impl.tasks.state.DNSStateTask#createOugoing()
*/
@Override
protected DNSOutgoing createOugoing() {
return new DNSOutgoing(DNSConstants.FLAGS_QR_RESPONSE | DNSConstants.FLAGS_AA);
}
/*
* (non-Javadoc)
* @see javax.jmdns.impl.tasks.state.DNSStateTask#buildOutgoingForDNS(javax.jmdns.impl.DNSOutgoing)
*/
@Override
protected DNSOutgoing buildOutgoingForDNS(DNSOutgoing out) throws IOException {
DNSOutgoing newOut = out;
for (DNSRecord answer : this.getDns().getLocalHost().answers(DNSRecordClass.CLASS_ANY, DNSRecordClass.UNIQUE, this.getTTL())) {
newOut = this.addAnswer(newOut, null, answer);
}
return newOut;
}
/*
* (non-Javadoc)
* @see javax.jmdns.impl.tasks.state.DNSStateTask#buildOutgoingForInfo(javax.jmdns.impl.ServiceInfoImpl, javax.jmdns.impl.DNSOutgoing)
*/
@Override
protected DNSOutgoing buildOutgoingForInfo(ServiceInfoImpl info, DNSOutgoing out) throws IOException {
DNSOutgoing newOut = out;
for (DNSRecord answer : info.answers(DNSRecordClass.CLASS_ANY, DNSRecordClass.UNIQUE, this.getTTL(), this.getDns().getLocalHost())) {
newOut = this.addAnswer(newOut, null, answer);
}
return newOut;
}
/*
* (non-Javadoc)
* @see javax.jmdns.impl.tasks.state.DNSStateTask#recoverTask(java.lang.Throwable)
*/
@Override
protected void recoverTask(Throwable e) {
this.getDns().recover();
}
/*
* (non-Javadoc)
* @see javax.jmdns.impl.tasks.state.DNSStateTask#advanceTask()
*/
@Override
protected void advanceTask() {
this.setTaskState(this.getTaskState().advance());
if (!this.getTaskState().isAnnounced()) {
cancel();
}
}
}

View file

@ -1,2 +1,2 @@
package javax.jmdns.impl.tasks.state;
package javax.jmdns.impl.tasks.state;

View file

@ -1,35 +1,35 @@
// Copyright 2003-2012 Arthur van Hoff, Rick Blair
// Licensed under Apache License version 2.0
// Original license LGPL
package javax.jmdns.impl.util;
import java.util.concurrent.Executors;
import java.util.concurrent.ThreadFactory;
/**
* Custom thread factory which sets the name to make it easier to identify where the pooled threads were created.
*
* @author Trejkaz, Pierre Frisch
*/
public class NamedThreadFactory implements ThreadFactory {
private final ThreadFactory _delegate;
private final String _namePrefix;
/**
* Constructs the thread factory.
*
* @param namePrefix a prefix to append to thread names (will be separated from the default thread name by a space.)
*/
public NamedThreadFactory(String namePrefix) {
this._namePrefix = namePrefix;
_delegate = Executors.defaultThreadFactory();
}
@Override
public Thread newThread(Runnable runnable) {
Thread thread = _delegate.newThread(runnable);
thread.setName(_namePrefix + ' ' + thread.getName());
return thread;
}
}
// Copyright 2003-2012 Arthur van Hoff, Rick Blair
// Licensed under Apache License version 2.0
// Original license LGPL
package javax.jmdns.impl.util;
import java.util.concurrent.Executors;
import java.util.concurrent.ThreadFactory;
/**
* Custom thread factory which sets the name to make it easier to identify where the pooled threads were created.
*
* @author Trejkaz, Pierre Frisch
*/
public class NamedThreadFactory implements ThreadFactory {
private final ThreadFactory _delegate;
private final String _namePrefix;
/**
* Constructs the thread factory.
*
* @param namePrefix a prefix to append to thread names (will be separated from the default thread name by a space.)
*/
public NamedThreadFactory(String namePrefix) {
this._namePrefix = namePrefix;
_delegate = Executors.defaultThreadFactory();
}
@Override
public Thread newThread(Runnable runnable) {
Thread thread = _delegate.newThread(runnable);
thread.setName(_namePrefix + ' ' + thread.getName());
return thread;
}
}

View file

@ -1,9 +1,9 @@
package javax.jmdns;
/**
* JmDNS is a Java implementation of multi-cast DNS and can be used for service registration and discovery in local area networks. JmDNS is fully compatible with Apple's Bonjour. The project was originally started in December 2002 by Arthur van Hoff
* at Strangeberry. In November 2003 the project was moved to SourceForge, and the name was changed from JRendezvous to JmDNS for legal reasons. Many thanks to Stuart Cheshire for help and moral support.
* <p>
* <a href="http://jmdns.sourceforge.net/">http://jmdns.sourceforge.net/<a>
* </p>
**/
package javax.jmdns;
/**
* JmDNS is a Java implementation of multi-cast DNS and can be used for service registration and discovery in local area networks. JmDNS is fully compatible with Apple's Bonjour. The project was originally started in December 2002 by Arthur van Hoff
* at Strangeberry. In November 2003 the project was moved to SourceForge, and the name was changed from JRendezvous to JmDNS for legal reasons. Many thanks to Stuart Cheshire for help and moral support.
* <p>
* <a href="http://jmdns.sourceforge.net/">http://jmdns.sourceforge.net/<a>
* </p>
**/

View file

@ -1,8 +1,8 @@
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="@color/grid_item_pressed" android:state_pressed="true" />
<item android:drawable="@color/grid_item_selected" android:state_selected="true" />
<item android:drawable="@color/transparent" />
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="@color/grid_item_pressed" android:state_pressed="true" />
<item android:drawable="@color/grid_item_selected" android:state_selected="true" />
<item android:drawable="@color/transparent" />
</selector>

View file

@ -1,78 +1,78 @@
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Temperature"
android:id="@+id/textViewTemperatureTitle"
android:textSize="25sp"
android:gravity="center"
android:layout_gravity="center_horizontal"
android:layout_alignParentTop="true"
android:layout_centerHorizontal="true"
android:layout_marginTop="25dp" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="......"
android:id="@+id/textViewTemperature"
android:textSize="18sp"
android:gravity="center"
android:layout_gravity="center_horizontal"
android:layout_alignParentTop="true"
android:layout_centerHorizontal="true"
android:layout_marginTop="68dp" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Humidity"
android:id="@+id/textViewHumidityTitle"
android:textSize="25sp"
android:gravity="center"
android:layout_gravity="center_horizontal"
android:layout_alignParentTop="true"
android:layout_centerHorizontal="true"
android:layout_marginTop="111dp" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="......"
android:id="@+id/textViewHumidity"
android:textSize="18sp"
android:gravity="center"
android:layout_gravity="center_horizontal"
android:layout_alignParentTop="true"
android:layout_centerHorizontal="true"
android:layout_marginTop="154dp" />
<com.androidplot.xy.XYPlot
android:id="@+id/mySimpleXYPlot"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:layout_marginTop="197dp"
androidPlot.rangeLabel="Reading"
androidPlot.domainLabel="Time"
androidPlot.plotLabelTextSize="13dp"
androidPlot.rangeLabelTextSize="13dp"
androidPlot.domainLabelTextSize="13dp"
androidPlot.graphWidget.rangeLabelPaint.textSize="13dp"
androidPlot.graphWidget.rangeOriginLabelPaint.textSize="13dp"
androidPlot.graphWidget.domainLabelPaint.textSize="13dp"
androidPlot.graphWidget.domainOriginLabelPaint.textSize="13dp"
androidPlot.legendWidget.textPaint.textSize="10dp"
androidPlot.legendWidget.iconSizeMetrics.heightMetric.value="10dp"
androidPlot.legendWidget.iconSizeMetrics.widthMetric.value="10dp"
androidPlot.legendWidget.heightMetric.value="20dp"
androidPlot.graphWidget.marginBottom="25dp"
androidPlot.legendWidget.positionMetrics.anchor="right_bottom"/>
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Temperature"
android:id="@+id/textViewTemperatureTitle"
android:textSize="25sp"
android:gravity="center"
android:layout_gravity="center_horizontal"
android:layout_alignParentTop="true"
android:layout_centerHorizontal="true"
android:layout_marginTop="25dp" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="......"
android:id="@+id/textViewTemperature"
android:textSize="18sp"
android:gravity="center"
android:layout_gravity="center_horizontal"
android:layout_alignParentTop="true"
android:layout_centerHorizontal="true"
android:layout_marginTop="68dp" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Humidity"
android:id="@+id/textViewHumidityTitle"
android:textSize="25sp"
android:gravity="center"
android:layout_gravity="center_horizontal"
android:layout_alignParentTop="true"
android:layout_centerHorizontal="true"
android:layout_marginTop="111dp" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="......"
android:id="@+id/textViewHumidity"
android:textSize="18sp"
android:gravity="center"
android:layout_gravity="center_horizontal"
android:layout_alignParentTop="true"
android:layout_centerHorizontal="true"
android:layout_marginTop="154dp" />
<com.androidplot.xy.XYPlot
android:id="@+id/mySimpleXYPlot"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:layout_marginTop="197dp"
androidPlot.rangeLabel="Reading"
androidPlot.domainLabel="Time"
androidPlot.plotLabelTextSize="13dp"
androidPlot.rangeLabelTextSize="13dp"
androidPlot.domainLabelTextSize="13dp"
androidPlot.graphWidget.rangeLabelPaint.textSize="13dp"
androidPlot.graphWidget.rangeOriginLabelPaint.textSize="13dp"
androidPlot.graphWidget.domainLabelPaint.textSize="13dp"
androidPlot.graphWidget.domainOriginLabelPaint.textSize="13dp"
androidPlot.legendWidget.textPaint.textSize="10dp"
androidPlot.legendWidget.iconSizeMetrics.heightMetric.value="10dp"
androidPlot.legendWidget.iconSizeMetrics.widthMetric.value="10dp"
androidPlot.legendWidget.heightMetric.value="20dp"
androidPlot.graphWidget.marginBottom="25dp"
androidPlot.legendWidget.positionMetrics.anchor="right_bottom"/>
</RelativeLayout>

View file

@ -1,38 +1,38 @@
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="48dp"
android:background="@drawable/list_selector">
<ImageView
android:id="@+id/icon"
android:layout_width="25dp"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:layout_marginLeft="12dp"
android:layout_marginRight="12dp"
android:contentDescription="@string/desc_list_item_icon"
android:src="@drawable/ic_rtk_white"
android:layout_centerVertical="true" />
<TextView
android:id="@+id/title"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_toRightOf="@id/icon"
android:minHeight="?android:attr/listPreferredItemHeightSmall"
android:textAppearance="?android:attr/textAppearanceListItemSmall"
android:textColor="@color/list_item_title"
android:gravity="center_vertical"
android:paddingRight="40dp"/>
<TextView android:id="@+id/counter"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="@drawable/bg_counter"
android:layout_alignParentRight="true"
android:layout_centerVertical="true"
android:layout_marginRight="8dp"
android:textColor="@color/counter_text_color"/>
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="48dp"
android:background="@drawable/list_selector">
<ImageView
android:id="@+id/icon"
android:layout_width="25dp"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:layout_marginLeft="12dp"
android:layout_marginRight="12dp"
android:contentDescription="@string/desc_list_item_icon"
android:src="@drawable/ic_rtk_white"
android:layout_centerVertical="true" />
<TextView
android:id="@+id/title"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_toRightOf="@id/icon"
android:minHeight="?android:attr/listPreferredItemHeightSmall"
android:textAppearance="?android:attr/textAppearanceListItemSmall"
android:textColor="@color/list_item_title"
android:gravity="center_vertical"
android:paddingRight="40dp"/>
<TextView android:id="@+id/counter"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="@drawable/bg_counter"
android:layout_alignParentRight="true"
android:layout_centerVertical="true"
android:layout_marginRight="8dp"
android:textColor="@color/counter_text_color"/>
</RelativeLayout>

View file

@ -1,28 +1,28 @@
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="5dp"
android:background="@drawable/grid_selector"
android:orientation="vertical"
android:padding="5dp"
android:gravity="center">
<ImageView
android:id="@+id/image"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:scaleType="centerInside"
android:layout_gravity="center"
android:contentDescription="gridView Cell Image" />
<TextView
android:id="@+id/text"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:maxLines="2"
android:ellipsize="end"
android:gravity="center"
android:textSize="12sp"
android:layout_gravity="center" />
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="5dp"
android:background="@drawable/grid_selector"
android:orientation="vertical"
android:padding="5dp"
android:gravity="center">
<ImageView
android:id="@+id/image"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:scaleType="centerInside"
android:layout_gravity="center"
android:contentDescription="gridView Cell Image" />
<TextView
android:id="@+id/text"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:maxLines="2"
android:ellipsize="end"
android:gravity="center"
android:textSize="12sp"
android:layout_gravity="center" />
</LinearLayout>

View file

@ -1,109 +1,109 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="app_name">WiGadget</string>
<string name="action_settings">Settings</string>
<!-- Name Title for Each Fragment -->
<string name="about_fragment_title">About</string>
<string name="my_device_fragment_title">My Device</string>
<string name="find_device_fragment_title">Find Device</string>
<!-- Name Title for Each Fragments -->
<!-- Nav Drawer Menu Items -->
<string-array name="nav_drawer_items">
<item >My Device</item>
<item >Find Device</item>
<item >About</item>
</string-array>
<array name="nav_drawer_icons">
<item>@drawable/ic_my_device</item>
<item>@drawable/ic_find_device</item>
<item>@drawable/ic_about</item>
</array>
<string name="desc_list_item_icon">Item Icon</string>
<!-- Nav Drawer Menu Items -->
<!-- Popup Dialog Device Options -->
<string name="popup_dialog_title_options">Device Options</string>
<string name="option_rename">Rename Device</string>
<string name="option_remove">Remove Device</string>
<string-array name="my_device_popup_dialog_options">
<item>Rename Device</item>
<item>Remove Device</item>
</string-array>
<string name="option_request_share">Ask for Sharing</string>
<string name="option_pair_device">Pair</string>
<string-array name="find_device_popup_share">
<item>Ask for Sharing</item>
</string-array>
<string-array name="find_device_popup_pair">
<item>Pair</item>
</string-array>
<!-- Popup Dialog Device Options-->
<!-- Popup Dialog Rename Device -->
<string name="rename_device_popup_dialog_title">New Name</string>
<!-- Popup Dialog Rename Device -->
<!-- Popup Dialog Firebase App Id -->
<string name="firebase_app_id_popup_dialog_title">Firebase App ID</string>
<!-- Popup Dialog Firebase App Id -->
<!-- Icons for ameba device -->
<!--<string name="device_ht">device_ht_sensor</string>-->
<string-array name="device_ht">
<item>@drawable/ic_device_ht_sensor_local_online</item>
<item>@drawable/ic_device_ht_sensor_local_offline</item>
<item>@drawable/ic_device_ht_sensor_cloud_online</item>
<item>@drawable/ic_device_ht_sensor_cloud_offline</item>
</string-array>
<!--<string name="device_unknown">device_unknown</string>-->
<string-array name="device_unknown">
<item>@drawable/ic_device_unknown_local_online</item>
<item>@drawable/ic_device_unknown_local_offline</item>
<item>@drawable/ic_device_unknown_cloud_online</item>
<item>@drawable/ic_device_unknown_cloud_offline</item>
</string-array>
<!-- Icons for ameba device -->
<!-- App Preferences Settings -->
<!-- ht data update frequency -->
<string-array name="ht_data_update_frequency_name">
<item>Every 1 second</item>
<item>Every 2 seconds</item>
<item>Every 3 seconds</item>
</string-array>
<string-array name="ht_data_update_frequency_value">
<item>1000</item>
<item>2000</item>
<item>3000</item>
</string-array>
<!-- ht alarm sound -->
<string-array name="ht_alarm_sound_name">
<item>Altair</item>
<item>Ariel</item>
<item>Ding</item>
<item>Fomalhaut</item>
<item>Tinkerbell</item>
</string-array>
<string-array name="ht_alarm_sound_value">
<item>sound_altair</item>
<item>sound_ariel</item>
<item>sound_ding</item>
<item>sound_fomalhaut</item>
<item>sound_tinkerbell</item>
</string-array>
<!-- App Preferences Settings -->
</resources>
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="app_name">WiGadget</string>
<string name="action_settings">Settings</string>
<!-- Name Title for Each Fragment -->
<string name="about_fragment_title">About</string>
<string name="my_device_fragment_title">My Device</string>
<string name="find_device_fragment_title">Find Device</string>
<!-- Name Title for Each Fragments -->
<!-- Nav Drawer Menu Items -->
<string-array name="nav_drawer_items">
<item >My Device</item>
<item >Find Device</item>
<item >About</item>
</string-array>
<array name="nav_drawer_icons">
<item>@drawable/ic_my_device</item>
<item>@drawable/ic_find_device</item>
<item>@drawable/ic_about</item>
</array>
<string name="desc_list_item_icon">Item Icon</string>
<!-- Nav Drawer Menu Items -->
<!-- Popup Dialog Device Options -->
<string name="popup_dialog_title_options">Device Options</string>
<string name="option_rename">Rename Device</string>
<string name="option_remove">Remove Device</string>
<string-array name="my_device_popup_dialog_options">
<item>Rename Device</item>
<item>Remove Device</item>
</string-array>
<string name="option_request_share">Ask for Sharing</string>
<string name="option_pair_device">Pair</string>
<string-array name="find_device_popup_share">
<item>Ask for Sharing</item>
</string-array>
<string-array name="find_device_popup_pair">
<item>Pair</item>
</string-array>
<!-- Popup Dialog Device Options-->
<!-- Popup Dialog Rename Device -->
<string name="rename_device_popup_dialog_title">New Name</string>
<!-- Popup Dialog Rename Device -->
<!-- Popup Dialog Firebase App Id -->
<string name="firebase_app_id_popup_dialog_title">Firebase App ID</string>
<!-- Popup Dialog Firebase App Id -->
<!-- Icons for ameba device -->
<!--<string name="device_ht">device_ht_sensor</string>-->
<string-array name="device_ht">
<item>@drawable/ic_device_ht_sensor_local_online</item>
<item>@drawable/ic_device_ht_sensor_local_offline</item>
<item>@drawable/ic_device_ht_sensor_cloud_online</item>
<item>@drawable/ic_device_ht_sensor_cloud_offline</item>
</string-array>
<!--<string name="device_unknown">device_unknown</string>-->
<string-array name="device_unknown">
<item>@drawable/ic_device_unknown_local_online</item>
<item>@drawable/ic_device_unknown_local_offline</item>
<item>@drawable/ic_device_unknown_cloud_online</item>
<item>@drawable/ic_device_unknown_cloud_offline</item>
</string-array>
<!-- Icons for ameba device -->
<!-- App Preferences Settings -->
<!-- ht data update frequency -->
<string-array name="ht_data_update_frequency_name">
<item>Every 1 second</item>
<item>Every 2 seconds</item>
<item>Every 3 seconds</item>
</string-array>
<string-array name="ht_data_update_frequency_value">
<item>1000</item>
<item>2000</item>
<item>3000</item>
</string-array>
<!-- ht alarm sound -->
<string-array name="ht_alarm_sound_name">
<item>Altair</item>
<item>Ariel</item>
<item>Ding</item>
<item>Fomalhaut</item>
<item>Tinkerbell</item>
</string-array>
<string-array name="ht_alarm_sound_value">
<item>sound_altair</item>
<item>sound_ariel</item>
<item>sound_ding</item>
<item>sound_fomalhaut</item>
<item>sound_tinkerbell</item>
</string-array>
<!-- App Preferences Settings -->
</resources>

View file

@ -1,7 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<config
linePaint.strokeWidth="1dp"
linePaint.color="#00CA00"
vertexPaint.color="#007700"
fillPaint.color="#00000000"
<?xml version="1.0" encoding="utf-8"?>
<config
linePaint.strokeWidth="1dp"
linePaint.color="#00CA00"
vertexPaint.color="#007700"
fillPaint.color="#00000000"
pointLabelFormatter.textPaint.color="#000000"/>

View file

@ -1,7 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<config
linePaint.strokeWidth="1dp"
linePaint.color="#0000CA"
vertexPaint.color="#000077"
fillPaint.color="#00000000"
<?xml version="1.0" encoding="utf-8"?>
<config
linePaint.strokeWidth="1dp"
linePaint.color="#0000CA"
vertexPaint.color="#000077"
fillPaint.color="#00000000"
pointLabelFormatter.textPaint.color="#000000"/>

View file

@ -1,54 +1,54 @@
<?xml version="1.0" encoding="utf-8"?>
<items version="2" >
<item
jar="/Users/WUJINZHOU/Mega/Programming/Java/Android_Studio/WiGadget/app/build/intermediates/exploded-aar/com.android.support/support-v4/21.0.3/jars/libs/internal_impl-21.0.3.jar"
jumboMode="false"
revision="21.1.2"
sha1="01ec05bfbafcc07646ba813000bf2ef11742dd03">
<dex dex="/Users/WUJINZHOU/Mega/Programming/Java/Android_Studio/WiGadget/app/build/intermediates/pre-dexed/debug/internal_impl-21.0.3-56d864dc91253a73fc9430f0d4a58b77989262bb.jar" />
</item>
<item
jar="/Users/WUJINZHOU/Mega/Programming/Java/Android_Studio/WiGadget/app/libs/androidplot-core-0.6.1.jar"
jumboMode="false"
revision="21.1.2"
sha1="3db0daea52375b26bfa61c59b8df93950bdefbbc">
<dex dex="/Users/WUJINZHOU/Mega/Programming/Java/Android_Studio/WiGadget/app/build/intermediates/pre-dexed/debug/androidplot-core-0.6.1-11d44a66eb81ac94dc1006cc6d76431c7dddb574.jar" />
</item>
<item
jar="/Users/WUJINZHOU/Mega/Programming/Java/Android_Studio/WiGadget/app/build/intermediates/exploded-aar/com.android.support/appcompat-v7/21.0.3/jars/classes.jar"
jumboMode="false"
revision="21.1.2"
sha1="81d42bf983a8741f4888a6e333e454e4a5e0eeb7">
<dex dex="/Users/WUJINZHOU/Mega/Programming/Java/Android_Studio/WiGadget/app/build/intermediates/pre-dexed/debug/classes-6cf20f80cc02d565a10f3730353f5181817a5195.jar" />
</item>
<item
jar="/Users/WUJINZHOU/Mega/Programming/Java/Android_Studio/WiGadget/app/libs/commons-codec-1.6-repack.jar"
jumboMode="false"
revision="21.1.2"
sha1="a42ebfad39f2287abc34adaae0633f867e1d65e0">
<dex dex="/Users/WUJINZHOU/Mega/Programming/Java/Android_Studio/WiGadget/app/build/intermediates/pre-dexed/debug/commons-codec-1.6-repack-9017459ec2448317eca71b280e4199394f09b398.jar" />
</item>
<item
jar="/Users/WUJINZHOU/Mega/Programming/Java/Android_Studio/WiGadget/app/build/intermediates/exploded-aar/com.android.support/support-v4/21.0.3/jars/classes.jar"
jumboMode="false"
revision="21.1.2"
sha1="2c91c949a45a21cdecf26e03951e46c7beec9ad8">
<dex dex="/Users/WUJINZHOU/Mega/Programming/Java/Android_Studio/WiGadget/app/build/intermediates/pre-dexed/debug/classes-41fbb662baea75c50164b7114ba050f49713a164.jar" />
</item>
<item
jar="/Users/WUJINZHOU/Mega/Programming/Java/Android_Studio/WiGadget/app/libs/firebase-client-android-2.2.4.jar"
jumboMode="false"
revision="21.1.2"
sha1="ebf4e7781b5fa09a256dcc00e82f0a97d7a23d50">
<dex dex="/Users/WUJINZHOU/Mega/Programming/Java/Android_Studio/WiGadget/app/build/intermediates/pre-dexed/debug/firebase-client-android-2.2.4-1cf4013aadb75032a6e70b76e14f3096de5522f9.jar" />
</item>
<item
jar="/Users/WUJINZHOU/Library/Android/sdk/extras/android/m2repository/com/android/support/support-annotations/21.0.3/support-annotations-21.0.3.jar"
jumboMode="false"
revision="21.1.2"
sha1="4b74cefe1f0c1b819e7260c8627a14674e37fd35">
<dex dex="/Users/WUJINZHOU/Mega/Programming/Java/Android_Studio/WiGadget/app/build/intermediates/pre-dexed/debug/support-annotations-21.0.3-3753a08e2977461103295ffba186504c104159ef.jar" />
</item>
</items>
<?xml version="1.0" encoding="utf-8"?>
<items version="2" >
<item
jar="/Users/WUJINZHOU/Mega/Programming/Java/Android_Studio/WiGadget/app/build/intermediates/exploded-aar/com.android.support/support-v4/21.0.3/jars/libs/internal_impl-21.0.3.jar"
jumboMode="false"
revision="21.1.2"
sha1="01ec05bfbafcc07646ba813000bf2ef11742dd03">
<dex dex="/Users/WUJINZHOU/Mega/Programming/Java/Android_Studio/WiGadget/app/build/intermediates/pre-dexed/debug/internal_impl-21.0.3-56d864dc91253a73fc9430f0d4a58b77989262bb.jar" />
</item>
<item
jar="/Users/WUJINZHOU/Mega/Programming/Java/Android_Studio/WiGadget/app/libs/androidplot-core-0.6.1.jar"
jumboMode="false"
revision="21.1.2"
sha1="3db0daea52375b26bfa61c59b8df93950bdefbbc">
<dex dex="/Users/WUJINZHOU/Mega/Programming/Java/Android_Studio/WiGadget/app/build/intermediates/pre-dexed/debug/androidplot-core-0.6.1-11d44a66eb81ac94dc1006cc6d76431c7dddb574.jar" />
</item>
<item
jar="/Users/WUJINZHOU/Mega/Programming/Java/Android_Studio/WiGadget/app/build/intermediates/exploded-aar/com.android.support/appcompat-v7/21.0.3/jars/classes.jar"
jumboMode="false"
revision="21.1.2"
sha1="81d42bf983a8741f4888a6e333e454e4a5e0eeb7">
<dex dex="/Users/WUJINZHOU/Mega/Programming/Java/Android_Studio/WiGadget/app/build/intermediates/pre-dexed/debug/classes-6cf20f80cc02d565a10f3730353f5181817a5195.jar" />
</item>
<item
jar="/Users/WUJINZHOU/Mega/Programming/Java/Android_Studio/WiGadget/app/libs/commons-codec-1.6-repack.jar"
jumboMode="false"
revision="21.1.2"
sha1="a42ebfad39f2287abc34adaae0633f867e1d65e0">
<dex dex="/Users/WUJINZHOU/Mega/Programming/Java/Android_Studio/WiGadget/app/build/intermediates/pre-dexed/debug/commons-codec-1.6-repack-9017459ec2448317eca71b280e4199394f09b398.jar" />
</item>
<item
jar="/Users/WUJINZHOU/Mega/Programming/Java/Android_Studio/WiGadget/app/build/intermediates/exploded-aar/com.android.support/support-v4/21.0.3/jars/classes.jar"
jumboMode="false"
revision="21.1.2"
sha1="2c91c949a45a21cdecf26e03951e46c7beec9ad8">
<dex dex="/Users/WUJINZHOU/Mega/Programming/Java/Android_Studio/WiGadget/app/build/intermediates/pre-dexed/debug/classes-41fbb662baea75c50164b7114ba050f49713a164.jar" />
</item>
<item
jar="/Users/WUJINZHOU/Mega/Programming/Java/Android_Studio/WiGadget/app/libs/firebase-client-android-2.2.4.jar"
jumboMode="false"
revision="21.1.2"
sha1="ebf4e7781b5fa09a256dcc00e82f0a97d7a23d50">
<dex dex="/Users/WUJINZHOU/Mega/Programming/Java/Android_Studio/WiGadget/app/build/intermediates/pre-dexed/debug/firebase-client-android-2.2.4-1cf4013aadb75032a6e70b76e14f3096de5522f9.jar" />
</item>
<item
jar="/Users/WUJINZHOU/Library/Android/sdk/extras/android/m2repository/com/android/support/support-annotations/21.0.3/support-annotations-21.0.3.jar"
jumboMode="false"
revision="21.1.2"
sha1="4b74cefe1f0c1b819e7260c8627a14674e37fd35">
<dex dex="/Users/WUJINZHOU/Mega/Programming/Java/Android_Studio/WiGadget/app/build/intermediates/pre-dexed/debug/support-annotations-21.0.3-3753a08e2977461103295ffba186504c104159ef.jar" />
</item>
</items>

View file

@ -1,6 +1,6 @@
#Wed Apr 10 15:27:10 PDT 2013
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-2.2.1-all.zip
#Wed Apr 10 15:27:10 PDT 2013
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-2.2.1-all.zip

View file

@ -1,164 +1,164 @@
#!/usr/bin/env bash
##############################################################################
##
## Gradle start up script for UN*X
##
##############################################################################
# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
DEFAULT_JVM_OPTS=""
APP_NAME="Gradle"
APP_BASE_NAME=`basename "$0"`
# Use the maximum available, or set MAX_FD != -1 to use that value.
MAX_FD="maximum"
warn ( ) {
echo "$*"
}
die ( ) {
echo
echo "$*"
echo
exit 1
}
# OS specific support (must be 'true' or 'false').
cygwin=false
msys=false
darwin=false
case "`uname`" in
CYGWIN* )
cygwin=true
;;
Darwin* )
darwin=true
;;
MINGW* )
msys=true
;;
esac
# For Cygwin, ensure paths are in UNIX format before anything is touched.
if $cygwin ; then
[ -n "$JAVA_HOME" ] && JAVA_HOME=`cygpath --unix "$JAVA_HOME"`
fi
# Attempt to set APP_HOME
# Resolve links: $0 may be a link
PRG="$0"
# Need this for relative symlinks.
while [ -h "$PRG" ] ; do
ls=`ls -ld "$PRG"`
link=`expr "$ls" : '.*-> \(.*\)$'`
if expr "$link" : '/.*' > /dev/null; then
PRG="$link"
else
PRG=`dirname "$PRG"`"/$link"
fi
done
SAVED="`pwd`"
cd "`dirname \"$PRG\"`/" >&-
APP_HOME="`pwd -P`"
cd "$SAVED" >&-
CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
# Determine the Java command to use to start the JVM.
if [ -n "$JAVA_HOME" ] ; then
if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
# IBM's JDK on AIX uses strange locations for the executables
JAVACMD="$JAVA_HOME/jre/sh/java"
else
JAVACMD="$JAVA_HOME/bin/java"
fi
if [ ! -x "$JAVACMD" ] ; then
die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
Please set the JAVA_HOME variable in your environment to match the
location of your Java installation."
fi
else
JAVACMD="java"
which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
Please set the JAVA_HOME variable in your environment to match the
location of your Java installation."
fi
# Increase the maximum file descriptors if we can.
if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then
MAX_FD_LIMIT=`ulimit -H -n`
if [ $? -eq 0 ] ; then
if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
MAX_FD="$MAX_FD_LIMIT"
fi
ulimit -n $MAX_FD
if [ $? -ne 0 ] ; then
warn "Could not set maximum file descriptor limit: $MAX_FD"
fi
else
warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
fi
fi
# For Darwin, add options to specify how the application appears in the dock
if $darwin; then
GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
fi
# For Cygwin, switch paths to Windows format before running java
if $cygwin ; then
APP_HOME=`cygpath --path --mixed "$APP_HOME"`
CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
# We build the pattern for arguments to be converted via cygpath
ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
SEP=""
for dir in $ROOTDIRSRAW ; do
ROOTDIRS="$ROOTDIRS$SEP$dir"
SEP="|"
done
OURCYGPATTERN="(^($ROOTDIRS))"
# Add a user-defined pattern to the cygpath arguments
if [ "$GRADLE_CYGPATTERN" != "" ] ; then
OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
fi
# Now convert the arguments - kludge to limit ourselves to /bin/sh
i=0
for arg in "$@" ; do
CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
else
eval `echo args$i`="\"$arg\""
fi
i=$((i+1))
done
case $i in
(0) set -- ;;
(1) set -- "$args0" ;;
(2) set -- "$args0" "$args1" ;;
(3) set -- "$args0" "$args1" "$args2" ;;
(4) set -- "$args0" "$args1" "$args2" "$args3" ;;
(5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
(6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
(7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
(8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
(9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
esac
fi
# Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules
function splitJvmOpts() {
JVM_OPTS=("$@")
}
eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS
JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME"
exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@"
#!/usr/bin/env bash
##############################################################################
##
## Gradle start up script for UN*X
##
##############################################################################
# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
DEFAULT_JVM_OPTS=""
APP_NAME="Gradle"
APP_BASE_NAME=`basename "$0"`
# Use the maximum available, or set MAX_FD != -1 to use that value.
MAX_FD="maximum"
warn ( ) {
echo "$*"
}
die ( ) {
echo
echo "$*"
echo
exit 1
}
# OS specific support (must be 'true' or 'false').
cygwin=false
msys=false
darwin=false
case "`uname`" in
CYGWIN* )
cygwin=true
;;
Darwin* )
darwin=true
;;
MINGW* )
msys=true
;;
esac
# For Cygwin, ensure paths are in UNIX format before anything is touched.
if $cygwin ; then
[ -n "$JAVA_HOME" ] && JAVA_HOME=`cygpath --unix "$JAVA_HOME"`
fi
# Attempt to set APP_HOME
# Resolve links: $0 may be a link
PRG="$0"
# Need this for relative symlinks.
while [ -h "$PRG" ] ; do
ls=`ls -ld "$PRG"`
link=`expr "$ls" : '.*-> \(.*\)$'`
if expr "$link" : '/.*' > /dev/null; then
PRG="$link"
else
PRG=`dirname "$PRG"`"/$link"
fi
done
SAVED="`pwd`"
cd "`dirname \"$PRG\"`/" >&-
APP_HOME="`pwd -P`"
cd "$SAVED" >&-
CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
# Determine the Java command to use to start the JVM.
if [ -n "$JAVA_HOME" ] ; then
if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
# IBM's JDK on AIX uses strange locations for the executables
JAVACMD="$JAVA_HOME/jre/sh/java"
else
JAVACMD="$JAVA_HOME/bin/java"
fi
if [ ! -x "$JAVACMD" ] ; then
die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
Please set the JAVA_HOME variable in your environment to match the
location of your Java installation."
fi
else
JAVACMD="java"
which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
Please set the JAVA_HOME variable in your environment to match the
location of your Java installation."
fi
# Increase the maximum file descriptors if we can.
if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then
MAX_FD_LIMIT=`ulimit -H -n`
if [ $? -eq 0 ] ; then
if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
MAX_FD="$MAX_FD_LIMIT"
fi
ulimit -n $MAX_FD
if [ $? -ne 0 ] ; then
warn "Could not set maximum file descriptor limit: $MAX_FD"
fi
else
warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
fi
fi
# For Darwin, add options to specify how the application appears in the dock
if $darwin; then
GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
fi
# For Cygwin, switch paths to Windows format before running java
if $cygwin ; then
APP_HOME=`cygpath --path --mixed "$APP_HOME"`
CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
# We build the pattern for arguments to be converted via cygpath
ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
SEP=""
for dir in $ROOTDIRSRAW ; do
ROOTDIRS="$ROOTDIRS$SEP$dir"
SEP="|"
done
OURCYGPATTERN="(^($ROOTDIRS))"
# Add a user-defined pattern to the cygpath arguments
if [ "$GRADLE_CYGPATTERN" != "" ] ; then
OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
fi
# Now convert the arguments - kludge to limit ourselves to /bin/sh
i=0
for arg in "$@" ; do
CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
else
eval `echo args$i`="\"$arg\""
fi
i=$((i+1))
done
case $i in
(0) set -- ;;
(1) set -- "$args0" ;;
(2) set -- "$args0" "$args1" ;;
(3) set -- "$args0" "$args1" "$args2" ;;
(4) set -- "$args0" "$args1" "$args2" "$args3" ;;
(5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
(6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
(7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
(8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
(9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
esac
fi
# Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules
function splitJvmOpts() {
JVM_OPTS=("$@")
}
eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS
JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME"
exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@"

View file

@ -1,11 +1,11 @@
## This file is automatically generated by Android Studio.
# Do not modify this file -- YOUR CHANGES WILL BE ERASED!
#
# This file must *NOT* be checked into Version Control Systems,
# as it contains information specific to your local configuration.
#
# Location of the SDK. This is only used by Gradle.
# For customization when using a Version Control System, please read the
# header note.
#Fri Aug 21 11:20:02 SGT 2015
sdk.dir=/Users/WUJINZHOU/Library/Android/sdk
## This file is automatically generated by Android Studio.
# Do not modify this file -- YOUR CHANGES WILL BE ERASED!
#
# This file must *NOT* be checked into Version Control Systems,
# as it contains information specific to your local configuration.
#
# Location of the SDK. This is only used by Gradle.
# For customization when using a Version Control System, please read the
# header note.
#Fri Aug 21 11:20:02 SGT 2015
sdk.dir=/Users/WUJINZHOU/Library/Android/sdk