summaryrefslogtreecommitdiffstats
blob: 0fc7976f4cc7b51c501c30154ab239a135d916aa (plain)
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
/*
 * Copyright (c) 2010-2012, Isode Limited, London, England.
 * All rights reserved.
 */
/*
 * Copyright (c) 2010 Remko Tronçon
 * Licensed under the GNU General Public License v3.
 * See Documentation/Licenses/GPLv3.txt for more information.
 */

package com.isode.stroke.network;

import com.isode.stroke.eventloop.Event.Callback;
import com.isode.stroke.eventloop.EventLoop;
import com.isode.stroke.eventloop.EventOwner;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Hashtable;
import javax.naming.NamingException;
import javax.naming.directory.Attribute;
import javax.naming.directory.Attributes;
import javax.naming.directory.DirContext;
import javax.naming.directory.InitialDirContext;

public class PlatformDomainNameServiceQuery extends DomainNameServiceQuery implements EventOwner {

    private class QueryThread extends Thread {

        @Override
        public void run() {
            final Collection<Result> results = new ArrayList<Result>();
            Hashtable env = new Hashtable();
            env.put("java.naming.factory.initial", "com.sun.jndi.dns.DnsContextFactory");
            env.put("java.naming.provider.url", "dns:");
            DirContext ctx = null;
            try {
                ctx = new InitialDirContext(env);
                Attributes attrs = ctx.getAttributes(service, new String[]{"SRV"});
                Attribute attribute = attrs.get("SRV");
                for (int i = 0; attribute != null && i < attribute.size(); i++) {
                    /* SRV results are going to be returned in the space-separated format
                     * Priority Weight Port Target
                     * (See RFC2782)
                     */
                    String[] srvParts = ((String) attribute.get(i)).split(" ");
                    String host = srvParts[3];
                    if (host.endsWith(".")) {
                        host = host.substring(0, host.length() - 1);
                    }
                    Result result = new Result(host, Integer.parseInt(srvParts[2]), Integer.parseInt(srvParts[0]), Integer.parseInt(srvParts[1]));
                    results.add(result);
                }
            } catch (NamingException ex) {
                /* Turns out that you get the exception just for not finding a result, so we want to fall through to A lookups and ignore.*/
            }

            eventLoop.postEvent(new Callback() {
                public void run() {
                    onResult.emit(results);
                }
            });
            //close the context as otherwise this will lead to open sockets in
            //CLOSE_WAIT condition
            if(ctx != null) {
                try {
                    ctx.close();
                } catch (NamingException e) {
                    //at least we try to close the context
                }
            }
        }
    }

    public PlatformDomainNameServiceQuery(String service, EventLoop eventLoop) {
        this.service = service;
        this.eventLoop = eventLoop;
    }

    @Override
    public void run() {
        QueryThread thread = new QueryThread();
        thread.setDaemon(true);
        thread.start();
    }
    private final String service;
    private final EventLoop eventLoop;
}