aboutsummaryrefslogtreecommitdiffstats
path: root/src/net/java/sip/communicator/impl/protocol/sip/net/ProxyConnection.java
blob: f7079f4452731027225073632b47543c2aed02fc (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
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
/*
 * Jitsi, the OpenSource Java VoIP and Instant Messaging client.
 *
 * Copyright @ 2015 Atlassian Pty Ltd
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package net.java.sip.communicator.impl.protocol.sip.net;

import static net.java.sip.communicator.service.protocol.ProtocolProviderFactory.PROXY_AUTO_CONFIG;

import java.net.*;
import java.util.*;

import net.java.sip.communicator.impl.protocol.sip.*;
import net.java.sip.communicator.service.dns.*;

/**
 * Abstract class for the determining the address for the SIP proxy.
 *
 * @author Ingo Bauersachs
 */
public abstract class ProxyConnection
{
    private List<String> returnedAddresses = new LinkedList<String>();

    protected String transport;
    protected InetSocketAddress socketAddress;
    protected final SipAccountIDImpl account;

    /**
     * Creates a new instance of this class.
     * @param account the account of this SIP protocol instance
     */
    protected ProxyConnection(SipAccountIDImpl account)
    {
        this.account = account;
    }

    /**
     * Gets the address to use for the next connection attempt.
     * @return the address of the last lookup.
     */
    public final InetSocketAddress getAddress()
    {
        return socketAddress;
    }

    /**
     * Gets the transport to use for the next connection attempt.
     * @return the transport of the last lookup.
     */
    public final String getTransport()
    {
        return transport;
    }

    /**
     * In case we are using an outbound proxy this method returns
     * a suitable string for use with Router.
     * The method returns <tt>null</tt> otherwise.
     *
     * @return the string of our outbound proxy if we are using one and
     * <tt>null</tt> otherwise.
     */
    public final String getOutboundProxyString()
    {
        if(socketAddress == null)
            return null;

        InetAddress proxyAddress = socketAddress.getAddress();
        StringBuilder proxyStringBuffer
            = new StringBuilder(proxyAddress.getHostAddress());

        if(proxyAddress instanceof Inet6Address)
        {
            proxyStringBuffer.insert(0, '[');
            proxyStringBuffer.append(']');
        }

        proxyStringBuffer.append(':');
        proxyStringBuffer.append(socketAddress.getPort());
        proxyStringBuffer.append('/');
        proxyStringBuffer.append(transport);

        return proxyStringBuffer.toString();
    }

    /**
     * Compares an InetAddress against the active outbound proxy. The comparison
     * is by reference, not equals.
     *
     * @param addressToTest The addres to test.
     * @return True when the InetAddress is the same as the outbound proxy.
     */
    public final boolean isSameInetAddress(InetAddress addressToTest)
    {
        // if the proxy is not yet initialized then this is not the provider
        // that caused this comparison
        if(socketAddress == null)
            return false;
        return addressToTest == socketAddress.getAddress();
    }

    /**
     * Retrieves the next address to use from DNS. Duplicate results are
     * suppressed.
     *
     * @return True if a new address is available through {@link #getAddress()},
     *         false if the last address was reached. A new lookup from scratch
     *         can be started by calling {@link #reset()}.
     * @throws DnssecException if there is a problem related to DNSSEC
     */
    public final boolean getNextAddress() throws DnssecException
    {
        boolean result;
        String key = null;
        do
        {
            result = getNextAddressFromDns();
            if(result && socketAddress != null)
            {
                key = getOutboundProxyString();
                if(!returnedAddresses.contains(key))
                {
                    returnedAddresses.add(key);
                    break;
                }
            }
        }
        while(result && returnedAddresses.contains(key));
        return result;
    }

    /**
     * Implementations must use this method to get the next address, but do not
     * have to care about duplicate addresses.
     *
     * @return True when a further address was available.
     * @throws DnssecException when a DNSSEC validation failure occured.
     */
    protected abstract boolean getNextAddressFromDns()
        throws DnssecException;

    /**
     * Resets the lookup to it's initial state. Overriders methods have to call
     * this method through a super-call.
     */
    public void reset()
    {
        returnedAddresses.clear();
    }

    /**
     * Factory method to create a proxy connection based on the account settings
     * of the protocol provider.
     *
     * @param pps the protocol provider that needs a SIP server connection.
     * @return An instance of a derived class.
     */
    public static ProxyConnection create(ProtocolProviderServiceSipImpl pps)
    {
        if (pps.getAccountID().getAccountPropertyBoolean(PROXY_AUTO_CONFIG,
            true))
            return new AutoProxyConnection((SipAccountIDImpl) pps.getAccountID(),
                pps.getDefaultTransport());
        else
            return new ManualProxyConnection((SipAccountIDImpl) pps.getAccountID());
    }
}