-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathmdns.java
executable file
·223 lines (203 loc) · 8.96 KB
/
mdns.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
///usr/bin/env jbang "$0" "$@" ; exit $?
//DEPS org.jmdns:jmdns:3.5.7
package scripts;
import java.io.IOException;
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.function.BiFunction;
import java.util.function.Function;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Collectors;
import javax.jmdns.JmDNS;
import javax.jmdns.ServiceEvent;
import javax.jmdns.ServiceInfo;
import javax.jmdns.ServiceListener;
import javax.jmdns.ServiceTypeListener;
public class mdns {
private static String format = "e a s h n";
private static int timeout = 0;
private static List<String> filters = new ArrayList<>();
private static boolean caseInsensitive;
private static String exec;
private static class MDnsServiceListener implements ServiceListener {
@Override
public void serviceAdded(ServiceEvent event) {
if (accept("ADD", event.getInfo())) {
showInfo(format, "ADD", event.getInfo());
execCmd(exec, "ADD", event.getInfo());
}
}
@Override
public void serviceRemoved(ServiceEvent event) {
if (accept("REM", event.getInfo())) {
showInfo(format, "REM", event.getInfo());
execCmd(exec, "REM", event.getInfo());
}
}
@Override
public void serviceResolved(ServiceEvent event) {
if (accept("RES", event.getInfo())) {
showInfo(format, "RES", event.getInfo());
execCmd(exec, "RES", event.getInfo());
}
}
private static boolean accept(String eventType, ServiceInfo info) {
return filters.stream().allMatch(filter -> accept(filter, eventType, info));
}
private static boolean accept(String filter, String eventType, ServiceInfo info) {
String[] parts;
BiFunction<String, String, Boolean> func = (a, b) -> caseInsensitive ? !a.equalsIgnoreCase(b) : !a.equals(b);
parts = filter.split("!=");
if (parts.length != 2) {
func = (a, b) -> caseInsensitive ? a.equalsIgnoreCase(b) : a.equals(b);
parts = filter.split("=");
}
if (parts.length != 2) {
func = (a, b) -> caseInsensitive ? !a.toLowerCase().contains(b.toLowerCase()) : !a.contains(b);
parts = filter.split("!~");
}
if (parts.length != 2) {
func = (a, b) -> caseInsensitive ? a.toLowerCase().contains(b.toLowerCase()) : a.contains(b);
parts = filter.split("~");
}
return parts.length == 2
&& !parts[0].isEmpty()
&& func.apply(getInfo(parts[0].charAt(0), eventType, info), parts[1]);
}
private static void showInfo(String fmt, String eventType, ServiceInfo info) {
if (!fmt.isEmpty()) {
String str = fmt.codePoints().mapToObj(ch -> getInfo(ch, eventType, info)).collect(Collectors.joining());
System.out.println(str.toString());
}
}
private static void execCmd(String exec, String eventType, ServiceInfo info) {
if (exec != null) {
exec = replace(exec, "%(.)", m -> getInfo(m.group(1).charAt(0), eventType, info));
try {
ProcessBuilder pb = new ProcessBuilder();
if (System.getenv("SHELL") != null) {
pb.command("sh", "-c", exec);
} else {
pb.command("cmd.exe", "/c", exec);
}
pb.inheritIO().start();
} catch (IOException e) {
System.err.println("Error executing command");
e.printStackTrace(System.err);
}
}
}
private static String getInfo(int ch, String eventType, ServiceInfo info) {
switch (ch) {
case 'a': return info.getApplication();
case 'd': return info.getDomain();
case 'e': return eventType;
case 'h': return Arrays.toString(info.getHostAddresses());
case 'i': return Arrays.toString(info.getInet4Addresses());
case 'I': return Arrays.toString(info.getInet6Addresses());
case 'k': return info.getKey();
case 'n': return info.getName();
case 'p': return info.getProtocol();
case 'P': return Integer.toString(info.getPort());
case 'q': return info.getQualifiedName();
case 's': return info.getServer();
case 'S': return info.getSubtype();
case 't': return info.getType();
case 'T': return info.getTypeWithSubtype();
case 'u': return Arrays.toString(info.getURLs());
case 'z': return info.getNiceTextString();
case 'Z': return info.toString();
default:
return Character.toString(ch);
}
}
}
private static String replace(String input, String regex, Function<Matcher, String> callback) {
return replace(input, Pattern.compile(regex), callback);
}
private static String replace(String input, Pattern regex, Function<Matcher, String> callback) {
StringBuffer resultString = new StringBuffer();
Matcher regexMatcher = regex.matcher(input);
while (regexMatcher.find()) {
regexMatcher.appendReplacement(resultString, callback.apply(regexMatcher));
}
regexMatcher.appendTail(resultString);
return resultString.toString();
}
public static void main(String... args) throws InterruptedException {
for (int i = 0; i < args.length; i++) {
String arg = args[i];
switch (arg) {
case "-t":
case "--timeout":
timeout = Integer.parseInt(args[++i]);
break;
case "-f":
case "--filter":
filters.add(args[++i]);
break;
case "-i":
caseInsensitive = true;
break;
case "-x":
case "--exec":
exec = args[++i];
break;
case "-h":
case "--help":
System.out.println("Usage: mdns [--timeout|-t <seconds>] [-i] [--filter|-f <info>(=|~)<text>]... [<info>]...");
System.out.println("Where <info> is any of the following characters:");
System.out.println(" a - Application");
System.out.println(" d - Domain");
System.out.println(" e - Event Type (ADD|REM|RES)");
System.out.println(" h - Host Addresses");
System.out.println(" i - Inet4 Addresses");
System.out.println(" I - Inet6 Addresses");
System.out.println(" k - Key");
System.out.println(" n - Name");
System.out.println(" p - Protocol");
System.out.println(" P - Port");
System.out.println(" q - Qualified Name");
System.out.println(" s - Server");
System.out.println(" S - Subtype");
System.out.println(" t - Type");
System.out.println(" T - Type with Subtype");
System.out.println(" u - URLs");
System.out.println(" z - as string");
System.out.println(" Z - as long string");
System.exit(1);
default:
format = arg;
break;
}
}
try (JmDNS jmdns = JmDNS.create(InetAddress.getLocalHost())) {
// Listen for types
jmdns.addServiceTypeListener(new ServiceTypeListener() {
@Override
public void serviceTypeAdded(ServiceEvent event) {
// Now listen for services of this type
jmdns.addServiceListener(event.getType(), new MDnsServiceListener());
}
@Override
public void subTypeForServiceTypeAdded(ServiceEvent event) {
jmdns.addServiceListener(event.getType(), new MDnsServiceListener());
}
});
// Wait for timeout or user interrupt
if (timeout > 0) {
Thread.sleep(timeout * 1000);
} else {
Thread.currentThread().join();
}
} catch (UnknownHostException e) {
System.err.println(e.getMessage());
} catch (IOException e) {
System.err.println(e.getMessage());
}
}
}