1
2
3
4
5 package javax.jmdns.impl;
6
7 import java.io.DataOutputStream;
8 import java.io.IOException;
9 import java.io.UnsupportedEncodingException;
10 import java.net.Inet4Address;
11 import java.net.Inet6Address;
12 import java.net.InetAddress;
13 import java.net.UnknownHostException;
14 import java.util.HashMap;
15 import java.util.Map;
16 import java.util.logging.Level;
17 import java.util.logging.Logger;
18
19 import javax.jmdns.ServiceEvent;
20 import javax.jmdns.ServiceInfo;
21 import javax.jmdns.ServiceInfo.Fields;
22 import javax.jmdns.impl.DNSOutgoing.MessageOutputStream;
23 import javax.jmdns.impl.constants.DNSConstants;
24 import javax.jmdns.impl.constants.DNSRecordClass;
25 import javax.jmdns.impl.constants.DNSRecordType;
26
27
28
29
30
31
32 public abstract class DNSRecord extends DNSEntry {
33 private static Logger logger = Logger.getLogger(DNSRecord.class.getName());
34 private int _ttl;
35 private long _created;
36
37
38
39
40 private InetAddress _source;
41
42
43
44
45 DNSRecord(String name, DNSRecordType type, DNSRecordClass recordClass, boolean unique, int ttl) {
46 super(name, type, recordClass, unique);
47 this._ttl = ttl;
48 this._created = System.currentTimeMillis();
49 }
50
51
52
53
54
55 @Override
56 public boolean equals(Object other) {
57 return (other instanceof DNSRecord) && super.equals(other) && sameValue((DNSRecord) other);
58 }
59
60
61
62
63 abstract boolean sameValue(DNSRecord other);
64
65
66
67
68 boolean sameType(DNSRecord other) {
69 return this.getRecordType() == other.getRecordType();
70 }
71
72
73
74
75
76
77 abstract boolean handleQuery(JmDNSImpl dns, long expirationTime);
78
79
80
81
82
83
84 abstract boolean handleResponse(JmDNSImpl dns);
85
86
87
88
89 abstract DNSOutgoing addAnswer(JmDNSImpl dns, DNSIncoming in, InetAddress addr, int port, DNSOutgoing out) throws IOException;
90
91
92
93
94 boolean suppressedBy(DNSIncoming msg) {
95 try {
96 for (DNSRecord answer : msg.getAllAnswers()) {
97 if (suppressedBy(answer)) {
98 return true;
99 }
100 }
101 return false;
102 } catch (ArrayIndexOutOfBoundsException e) {
103 logger.log(Level.WARNING, "suppressedBy() message " + msg + " exception ", e);
104
105 return false;
106 }
107 }
108
109
110
111
112 boolean suppressedBy(DNSRecord other) {
113 if (this.equals(other) && (other._ttl > _ttl / 2)) {
114 return true;
115 }
116 return false;
117 }
118
119
120
121
122 long getExpirationTime(int percent) {
123
124 return _created + (percent * _ttl * 10L);
125 }
126
127
128
129
130 int getRemainingTTL(long now) {
131 return (int) Math.max(0, (getExpirationTime(100) - now) / 1000);
132 }
133
134
135
136
137
138 @Override
139 public boolean isExpired(long now) {
140 return getExpirationTime(100) <= now;
141 }
142
143
144
145
146
147 @Override
148 public boolean isStale(long now) {
149 return getExpirationTime(50) <= now;
150 }
151
152
153
154
155 void resetTTL(DNSRecord other) {
156 _created = other._created;
157 _ttl = other._ttl;
158 }
159
160
161
162
163 void setWillExpireSoon(long now) {
164 _created = now;
165 _ttl = DNSConstants.RECORD_EXPIRY_DELAY;
166 }
167
168
169
170
171 abstract void write(MessageOutputStream out);
172
173 public static class IPv4Address extends Address {
174
175 IPv4Address(String name, DNSRecordClass recordClass, boolean unique, int ttl, InetAddress addr) {
176 super(name, DNSRecordType.TYPE_A, recordClass, unique, ttl, addr);
177 }
178
179 IPv4Address(String name, DNSRecordClass recordClass, boolean unique, int ttl, byte[] rawAddress) {
180 super(name, DNSRecordType.TYPE_A, recordClass, unique, ttl, rawAddress);
181 }
182
183 @Override
184 void write(MessageOutputStream out) {
185 if (_addr != null) {
186 byte[] buffer = _addr.getAddress();
187
188 if (_addr instanceof Inet4Address) {
189
190 } else {
191
192 byte[] tempbuffer = buffer;
193 buffer = new byte[4];
194 System.arraycopy(tempbuffer, 12, buffer, 0, 4);
195 }
196 int length = buffer.length;
197 out.writeBytes(buffer, 0, length);
198 }
199 }
200
201
202
203
204
205 @Override
206 public ServiceInfo getServiceInfo(boolean persistent) {
207
208 ServiceInfoImpl info = (ServiceInfoImpl) super.getServiceInfo(persistent);
209 info.addAddress((Inet4Address) _addr);
210 return info;
211 }
212
213 }
214
215 public static class IPv6Address extends Address {
216
217 IPv6Address(String name, DNSRecordClass recordClass, boolean unique, int ttl, InetAddress addr) {
218 super(name, DNSRecordType.TYPE_AAAA, recordClass, unique, ttl, addr);
219 }
220
221 IPv6Address(String name, DNSRecordClass recordClass, boolean unique, int ttl, byte[] rawAddress) {
222 super(name, DNSRecordType.TYPE_AAAA, recordClass, unique, ttl, rawAddress);
223 }
224
225 @Override
226 void write(MessageOutputStream out) {
227 if (_addr != null) {
228 byte[] buffer = _addr.getAddress();
229
230 if (_addr instanceof Inet4Address) {
231 byte[] tempbuffer = buffer;
232 buffer = new byte[16];
233 for (int i = 0; i < 16; i++) {
234 if (i < 11) {
235 buffer[i] = tempbuffer[i - 12];
236 } else {
237 buffer[i] = 0;
238 }
239 }
240 }
241 int length = buffer.length;
242 out.writeBytes(buffer, 0, length);
243 }
244 }
245
246
247
248
249
250 @Override
251 public ServiceInfo getServiceInfo(boolean persistent) {
252
253 ServiceInfoImpl info = (ServiceInfoImpl) super.getServiceInfo(persistent);
254 info.addAddress((Inet6Address) _addr);
255 return info;
256 }
257
258 }
259
260
261
262
263 public static abstract class Address extends DNSRecord {
264 private static Logger logger1 = Logger.getLogger(Address.class.getName());
265
266 InetAddress _addr;
267
268 protected Address(String name, DNSRecordType type, DNSRecordClass recordClass, boolean unique, int ttl, InetAddress addr) {
269 super(name, type, recordClass, unique, ttl);
270 this._addr = addr;
271 }
272
273 protected Address(String name, DNSRecordType type, DNSRecordClass recordClass, boolean unique, int ttl, byte[] rawAddress) {
274 super(name, type, recordClass, unique, ttl);
275 try {
276 this._addr = InetAddress.getByAddress(rawAddress);
277 } catch (UnknownHostException exception) {
278 logger1.log(Level.WARNING, "Address() exception ", exception);
279 }
280 }
281
282 boolean same(DNSRecord other) {
283 if (! (other instanceof Address) ) {
284 return false;
285 }
286 return ((sameName(other)) && ((sameValue(other))));
287 }
288
289 boolean sameName(DNSRecord other) {
290 return this.getName().equalsIgnoreCase(other.getName());
291 }
292
293 @Override
294 boolean sameValue(DNSRecord other) {
295 if (! (other instanceof Address) ) {
296 return false;
297 }
298 Address address = (Address) other;
299 if ((this.getAddress() == null) && (address.getAddress() != null)) {
300 return false;
301 }
302 return this.getAddress().equals(address.getAddress());
303 }
304
305 @Override
306 public boolean isSingleValued() {
307 return false;
308 }
309
310 InetAddress getAddress() {
311 return _addr;
312 }
313
314
315
316
317 @Override
318 protected void toByteArray(DataOutputStream dout) throws IOException {
319 super.toByteArray(dout);
320 byte[] buffer = this.getAddress().getAddress();
321 for (int i = 0; i < buffer.length; i++) {
322 dout.writeByte(buffer[i]);
323 }
324 }
325
326
327
328
329 @Override
330 boolean handleQuery(JmDNSImpl dns, long expirationTime) {
331 if (dns.getLocalHost().conflictWithRecord(this)) {
332 DNSRecord.Address localAddress = dns.getLocalHost().getDNSAddressRecord(this.getRecordType(), this.isUnique(), DNSConstants.DNS_TTL);
333 int comparison = this.compareTo(localAddress);
334
335 if (comparison == 0) {
336
337
338
339
340 logger1.finer("handleQuery() Ignoring an identical address query");
341 return false;
342 }
343
344 logger1.finer("handleQuery() Conflicting query detected.");
345
346 if (dns.isProbing() && comparison > 0) {
347
348 dns.getLocalHost().incrementHostName();
349 dns.getCache().clear();
350 for (ServiceInfo serviceInfo : dns.getServices().values()) {
351 ServiceInfoImpl info = (ServiceInfoImpl) serviceInfo;
352 info.revertState();
353 }
354 }
355 dns.revertState();
356 return true;
357 }
358 return false;
359 }
360
361
362
363
364 @Override
365 boolean handleResponse(JmDNSImpl dns) {
366 if (dns.getLocalHost().conflictWithRecord(this)) {
367 logger1.finer("handleResponse() Denial detected");
368
369 if (dns.isProbing()) {
370 dns.getLocalHost().incrementHostName();
371 dns.getCache().clear();
372 for (ServiceInfo serviceInfo : dns.getServices().values()) {
373 ServiceInfoImpl info = (ServiceInfoImpl) serviceInfo;
374 info.revertState();
375 }
376 }
377 dns.revertState();
378 return true;
379 }
380 return false;
381 }
382
383 @Override
384 DNSOutgoing addAnswer(JmDNSImpl dns, DNSIncoming in, InetAddress addr, int port, DNSOutgoing out) throws IOException {
385 return out;
386 }
387
388
389
390
391
392 @Override
393 public ServiceInfo getServiceInfo(boolean persistent) {
394 ServiceInfoImpl info = new ServiceInfoImpl(this.getQualifiedNameMap(), 0, 0, 0, persistent, (byte[]) null);
395
396 return info;
397 }
398
399
400
401
402
403 @Override
404 public ServiceEvent getServiceEvent(JmDNSImpl dns) {
405 ServiceInfo info = this.getServiceInfo(false);
406 ((ServiceInfoImpl) info).setDns(dns);
407 return new ServiceEventImpl(dns, info.getType(), info.getName(), info);
408 }
409
410
411
412
413
414 @Override
415 protected void toString(StringBuilder aLog) {
416 super.toString(aLog);
417 aLog.append(" address: '" + (this.getAddress() != null ? this.getAddress().getHostAddress() : "null") + "'");
418 }
419
420 }
421
422
423
424
425 public static class Pointer extends DNSRecord {
426
427 private final String _alias;
428
429 public Pointer(String name, DNSRecordClass recordClass, boolean unique, int ttl, String alias) {
430 super(name, DNSRecordType.TYPE_PTR, recordClass, unique, ttl);
431 this._alias = alias;
432 }
433
434
435
436
437
438 @Override
439 public boolean isSameEntry(DNSEntry entry) {
440 return super.isSameEntry(entry) && (entry instanceof Pointer) && this.sameValue((Pointer) entry);
441 }
442
443 @Override
444 void write(MessageOutputStream out) {
445 out.writeName(_alias);
446 }
447
448 @Override
449 boolean sameValue(DNSRecord other) {
450 if (! (other instanceof Pointer) ) {
451 return false;
452 }
453 Pointer pointer = (Pointer) other;
454 if ((_alias == null) && (pointer._alias != null)) {
455 return false;
456 }
457 return _alias.equals(pointer._alias);
458 }
459
460 @Override
461 public boolean isSingleValued() {
462 return false;
463 }
464
465 @Override
466 boolean handleQuery(JmDNSImpl dns, long expirationTime) {
467
468
469 return false;
470 }
471
472 @Override
473 boolean handleResponse(JmDNSImpl dns) {
474
475
476 return false;
477 }
478
479 String getAlias() {
480 return _alias;
481 }
482
483 @Override
484 DNSOutgoing addAnswer(JmDNSImpl dns, DNSIncoming in, InetAddress addr, int port, DNSOutgoing out) throws IOException {
485 return out;
486 }
487
488
489
490
491
492 @Override
493 public ServiceInfo getServiceInfo(boolean persistent) {
494 if (this.isServicesDiscoveryMetaQuery()) {
495
496 Map<Fields, String> map = ServiceInfoImpl.decodeQualifiedNameMapForType(this.getAlias());
497 return new ServiceInfoImpl(map, 0, 0, 0, persistent, (byte[]) null);
498 } else if (this.isReverseLookup()) {
499 return new ServiceInfoImpl(this.getQualifiedNameMap(), 0, 0, 0, persistent, (byte[]) null);
500 } else if (this.isDomainDiscoveryQuery()) {
501
502 return new ServiceInfoImpl(this.getQualifiedNameMap(), 0, 0, 0, persistent, (byte[]) null);
503 }
504 Map<Fields, String> map = ServiceInfoImpl.decodeQualifiedNameMapForType(this.getAlias());
505 map.put(Fields.Subtype, this.getQualifiedNameMap().get(Fields.Subtype));
506 return new ServiceInfoImpl(map, 0, 0, 0, persistent, this.getAlias());
507 }
508
509
510
511
512
513 @Override
514 public ServiceEvent getServiceEvent(JmDNSImpl dns) {
515 ServiceInfo info = this.getServiceInfo(false);
516 ((ServiceInfoImpl) info).setDns(dns);
517 String domainName = info.getType();
518 String serviceName = JmDNSImpl.toUnqualifiedName(domainName, this.getAlias());
519 return new ServiceEventImpl(dns, domainName, serviceName, info);
520 }
521
522
523
524
525
526 @Override
527 protected void toString(StringBuilder aLog) {
528 super.toString(aLog);
529 aLog.append(" alias: '" + (_alias != null ? _alias.toString() : "null") + "'");
530 }
531
532 }
533
534 public final static byte[] EMPTY_TXT = new byte[] { 0 };
535
536 public static class Text extends DNSRecord {
537
538 private final byte[] _text;
539
540 public Text(String name, DNSRecordClass recordClass, boolean unique, int ttl, byte text[]) {
541 super(name, DNSRecordType.TYPE_TXT, recordClass, unique, ttl);
542 this._text = (text != null && text.length > 0 ? text : EMPTY_TXT);
543 }
544
545
546
547
548 byte[] getText() {
549 return this._text;
550 }
551
552 @Override
553 void write(MessageOutputStream out) {
554 out.writeBytes(_text, 0, _text.length);
555 }
556
557 @Override
558 boolean sameValue(DNSRecord other) {
559 if (! (other instanceof Text) ) {
560 return false;
561 }
562 Text txt = (Text) other;
563 if ((_text == null) && (txt._text != null)) {
564 return false;
565 }
566 if (txt._text.length != _text.length) {
567 return false;
568 }
569 for (int i = _text.length; i-- > 0;) {
570 if (txt._text[i] != _text[i]) {
571 return false;
572 }
573 }
574 return true;
575 }
576
577 @Override
578 public boolean isSingleValued() {
579 return true;
580 }
581
582 @Override
583 boolean handleQuery(JmDNSImpl dns, long expirationTime) {
584
585
586 return false;
587 }
588
589 @Override
590 boolean handleResponse(JmDNSImpl dns) {
591
592
593
594
595
596 return false;
597 }
598
599 @Override
600 DNSOutgoing addAnswer(JmDNSImpl dns, DNSIncoming in, InetAddress addr, int port, DNSOutgoing out) throws IOException {
601 return out;
602 }
603
604
605
606
607
608 @Override
609 public ServiceInfo getServiceInfo(boolean persistent) {
610 return new ServiceInfoImpl(this.getQualifiedNameMap(), 0, 0, 0, persistent, _text);
611 }
612
613
614
615
616
617 @Override
618 public ServiceEvent getServiceEvent(JmDNSImpl dns) {
619 ServiceInfo info = this.getServiceInfo(false);
620 ((ServiceInfoImpl) info).setDns(dns);
621 return new ServiceEventImpl(dns, info.getType(), info.getName(), info);
622 }
623
624
625
626
627
628 @Override
629 protected void toString(StringBuilder aLog) {
630 super.toString(aLog);
631 aLog.append(" text: '" + ((_text.length > 20) ? new String(_text, 0, 17) + "..." : new String(_text)) + "'");
632 }
633
634 }
635
636
637
638
639 public static class Service extends DNSRecord {
640 private static Logger logger1 = Logger.getLogger(Service.class.getName());
641 private final int _priority;
642 private final int _weight;
643 private final int _port;
644 private final String _server;
645
646 public Service(String name, DNSRecordClass recordClass, boolean unique, int ttl, int priority, int weight, int port, String server) {
647 super(name, DNSRecordType.TYPE_SRV, recordClass, unique, ttl);
648 this._priority = priority;
649 this._weight = weight;
650 this._port = port;
651 this._server = server;
652 }
653
654 @Override
655 void write(MessageOutputStream out) {
656 out.writeShort(_priority);
657 out.writeShort(_weight);
658 out.writeShort(_port);
659 if (DNSIncoming.USE_DOMAIN_NAME_FORMAT_FOR_SRV_TARGET) {
660 out.writeName(_server);
661 } else {
662
663 out.writeUTF(_server, 0, _server.length());
664
665
666
667 out.writeByte(0);
668 }
669 }
670
671 @Override
672 protected void toByteArray(DataOutputStream dout) throws IOException {
673 super.toByteArray(dout);
674 dout.writeShort(_priority);
675 dout.writeShort(_weight);
676 dout.writeShort(_port);
677 try {
678 dout.write(_server.getBytes("UTF-8"));
679 } catch (UnsupportedEncodingException exception) {
680
681 }
682 }
683
684 String getServer() {
685 return _server;
686 }
687
688
689
690
691 public int getPriority() {
692 return this._priority;
693 }
694
695
696
697
698 public int getWeight() {
699 return this._weight;
700 }
701
702
703
704
705 public int getPort() {
706 return this._port;
707 }
708
709 @Override
710 boolean sameValue(DNSRecord other) {
711 if (! (other instanceof Service) ) {
712 return false;
713 }
714 Service s = (Service) other;
715 return (_priority == s._priority) && (_weight == s._weight) && (_port == s._port) && _server.equals(s._server);
716 }
717
718 @Override
719 public boolean isSingleValued() {
720 return true;
721 }
722
723 @Override
724 boolean handleQuery(JmDNSImpl dns, long expirationTime) {
725 ServiceInfoImpl info = (ServiceInfoImpl) dns.getServices().get(this.getKey());
726 if (info != null && (info.isAnnouncing() || info.isAnnounced()) && (_port != info.getPort() || !_server.equalsIgnoreCase(dns.getLocalHost().getName()))) {
727 logger1.finer("handleQuery() Conflicting probe detected from: " + getRecordSource());
728 DNSRecord.Service localService = new DNSRecord.Service(info.getQualifiedName(), DNSRecordClass.CLASS_IN, DNSRecordClass.UNIQUE, DNSConstants.DNS_TTL, info.getPriority(), info.getWeight(), info.getPort(), dns.getLocalHost().getName());
729
730
731 try {
732 if (dns.getInterface().equals(getRecordSource())) {
733 logger1.warning("Got conflicting probe from ourselves\n" + "incoming: " + this.toString() + "\n" + "local : " + localService.toString());
734 }
735 } catch (IOException e) {
736 logger1.log(Level.WARNING, "IOException", e);
737 }
738
739 int comparison = this.compareTo(localService);
740
741 if (comparison == 0) {
742
743
744
745
746 logger1.finer("handleQuery() Ignoring a identical service query");
747 return false;
748 }
749
750
751 if (info.isProbing() && comparison > 0) {
752
753 String oldName = info.getQualifiedName().toLowerCase();
754 info.setName(dns.incrementName(info.getName()));
755 dns.getServices().remove(oldName);
756 dns.getServices().put(info.getQualifiedName().toLowerCase(), info);
757 logger1.finer("handleQuery() Lost tie break: new unique name chosen:" + info.getName());
758
759
760 info.revertState();
761 } else {
762
763
764 return false;
765 }
766
767 return true;
768
769 }
770 return false;
771 }
772
773 @Override
774 boolean handleResponse(JmDNSImpl dns) {
775 ServiceInfoImpl info = (ServiceInfoImpl) dns.getServices().get(this.getKey());
776 if (info != null && (_port != info.getPort() || !_server.equalsIgnoreCase(dns.getLocalHost().getName()))) {
777 logger1.finer("handleResponse() Denial detected");
778
779 if (info.isProbing()) {
780 String oldName = info.getQualifiedName().toLowerCase();
781 info.setName(dns.incrementName(info.getName()));
782 dns.getServices().remove(oldName);
783 dns.getServices().put(info.getQualifiedName().toLowerCase(), info);
784 logger1.finer("handleResponse() New unique name chose:" + info.getName());
785
786 }
787 info.revertState();
788 return true;
789 }
790 return false;
791 }
792
793 @Override
794 DNSOutgoing addAnswer(JmDNSImpl dns, DNSIncoming in, InetAddress addr, int port, DNSOutgoing out) throws IOException {
795 ServiceInfoImpl info = (ServiceInfoImpl) dns.getServices().get(this.getKey());
796 if (info != null) {
797 if (this._port == info.getPort() != _server.equals(dns.getLocalHost().getName())) {
798 return dns.addAnswer(in, addr, port, out, new DNSRecord.Service(info.getQualifiedName(), DNSRecordClass.CLASS_IN, DNSRecordClass.UNIQUE, DNSConstants.DNS_TTL, info.getPriority(), info.getWeight(), info.getPort(), dns
799 .getLocalHost().getName()));
800 }
801 }
802 return out;
803 }
804
805
806
807
808
809 @Override
810 public ServiceInfo getServiceInfo(boolean persistent) {
811 return new ServiceInfoImpl(this.getQualifiedNameMap(), _port, _weight, _priority, persistent, _server);
812 }
813
814
815
816
817
818 @Override
819 public ServiceEvent getServiceEvent(JmDNSImpl dns) {
820 ServiceInfo info = this.getServiceInfo(false);
821 ((ServiceInfoImpl) info).setDns(dns);
822
823
824
825
826
827
828
829
830
831
832 return new ServiceEventImpl(dns, info.getType(), info.getName(), info);
833
834 }
835
836
837
838
839
840 @Override
841 protected void toString(StringBuilder aLog) {
842 super.toString(aLog);
843 aLog.append(" server: '" + _server + ":" + _port + "'");
844 }
845
846 }
847
848 public static class HostInformation extends DNSRecord {
849 String _os;
850 String _cpu;
851
852
853
854
855
856
857
858
859
860 public HostInformation(String name, DNSRecordClass recordClass, boolean unique, int ttl, String cpu, String os) {
861 super(name, DNSRecordType.TYPE_HINFO, recordClass, unique, ttl);
862 _cpu = cpu;
863 _os = os;
864 }
865
866
867
868
869
870 @Override
871 DNSOutgoing addAnswer(JmDNSImpl dns, DNSIncoming in, InetAddress addr, int port, DNSOutgoing out) throws IOException {
872 return out;
873 }
874
875
876
877
878
879 @Override
880 boolean handleQuery(JmDNSImpl dns, long expirationTime) {
881 return false;
882 }
883
884
885
886
887
888 @Override
889 boolean handleResponse(JmDNSImpl dns) {
890 return false;
891 }
892
893
894
895
896
897 @Override
898 boolean sameValue(DNSRecord other) {
899 if (! (other instanceof HostInformation) ) {
900 return false;
901 }
902 HostInformation hinfo = (HostInformation) other;
903 if ((_cpu == null) && (hinfo._cpu != null)) {
904 return false;
905 }
906 if ((_os == null) && (hinfo._os != null)) {
907 return false;
908 }
909 return _cpu.equals(hinfo._cpu) && _os.equals(hinfo._os);
910 }
911
912
913
914
915
916 @Override
917 public boolean isSingleValued() {
918 return true;
919 }
920
921
922
923
924
925 @Override
926 void write(MessageOutputStream out) {
927 String hostInfo = _cpu + " " + _os;
928 out.writeUTF(hostInfo, 0, hostInfo.length());
929 }
930
931
932
933
934
935 @Override
936 public ServiceInfo getServiceInfo(boolean persistent) {
937 Map<String, String> hinfo = new HashMap<String, String>(2);
938 hinfo.put("cpu", _cpu);
939 hinfo.put("os", _os);
940 return new ServiceInfoImpl(this.getQualifiedNameMap(), 0, 0, 0, persistent, hinfo);
941 }
942
943
944
945
946
947 @Override
948 public ServiceEvent getServiceEvent(JmDNSImpl dns) {
949 ServiceInfo info = this.getServiceInfo(false);
950 ((ServiceInfoImpl) info).setDns(dns);
951 return new ServiceEventImpl(dns, info.getType(), info.getName(), info);
952 }
953
954
955
956
957
958 @Override
959 protected void toString(StringBuilder aLog) {
960 super.toString(aLog);
961 aLog.append(" cpu: '" + _cpu + "' os: '" + _os + "'");
962 }
963
964 }
965
966
967
968
969
970
971 public abstract boolean isSingleValued();
972
973
974
975
976
977
978 public ServiceInfo getServiceInfo() {
979 return this.getServiceInfo(false);
980 }
981
982
983
984
985
986
987
988
989 public abstract ServiceInfo getServiceInfo(boolean persistent);
990
991
992
993
994
995
996
997
998 public abstract ServiceEvent getServiceEvent(JmDNSImpl dns);
999
1000 public void setRecordSource(InetAddress source) {
1001 this._source = source;
1002 }
1003
1004 public InetAddress getRecordSource() {
1005 return _source;
1006 }
1007
1008
1009
1010
1011
1012 @Override
1013 protected void toString(StringBuilder aLog) {
1014 super.toString(aLog);
1015 aLog.append(" ttl: '" + getRemainingTTL(System.currentTimeMillis()) + "/" + _ttl + "'");
1016 }
1017
1018 public void setTTL(int ttl) {
1019 this._ttl = ttl;
1020 }
1021
1022 public int getTTL() {
1023 return _ttl;
1024 }
1025 }