SipProfile.java revision 58ee2acba8953814cc4bf65d2f28f7dd498b5779
1/*
2 * Copyright (C) 2010 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package android.net.sip;
18
19import android.os.Parcel;
20import android.os.Parcelable;
21import android.text.TextUtils;
22
23import java.io.ObjectStreamException;
24import java.io.Serializable;
25import java.text.ParseException;
26import javax.sip.InvalidArgumentException;
27import javax.sip.ListeningPoint;
28import javax.sip.PeerUnavailableException;
29import javax.sip.SipFactory;
30import javax.sip.address.Address;
31import javax.sip.address.AddressFactory;
32import javax.sip.address.SipURI;
33import javax.sip.address.URI;
34
35/**
36 * Defines a SIP profile, including a SIP account, domain and server information.
37 * <p>You can create a {@link SipProfile} using {@link
38 * SipProfile.Builder}. You can also retrieve one from a {@link SipSession}, using {@link
39 * SipSession#getLocalProfile} and {@link SipSession#getPeerProfile}.</p>
40 */
41public class SipProfile implements Parcelable, Serializable, Cloneable {
42    private static final long serialVersionUID = 1L;
43    private static final int DEFAULT_PORT = 5060;
44    private static final String TCP = "TCP";
45    private static final String UDP = "UDP";
46    private Address mAddress;
47    private String mProxyAddress;
48    private String mPassword;
49    private String mDomain;
50    private String mProtocol = UDP;
51    private String mProfileName;
52    private int mPort = DEFAULT_PORT;
53    private boolean mSendKeepAlive = false;
54    private boolean mAutoRegistration = true;
55    private transient int mCallingUid = 0;
56
57    public static final Parcelable.Creator<SipProfile> CREATOR =
58            new Parcelable.Creator<SipProfile>() {
59                public SipProfile createFromParcel(Parcel in) {
60                    return new SipProfile(in);
61                }
62
63                public SipProfile[] newArray(int size) {
64                    return new SipProfile[size];
65                }
66            };
67
68    /**
69     * Helper class for creating a {@link SipProfile}.
70     */
71    public static class Builder {
72        private AddressFactory mAddressFactory;
73        private SipProfile mProfile = new SipProfile();
74        private SipURI mUri;
75        private String mDisplayName;
76        private String mProxyAddress;
77
78        {
79            try {
80                mAddressFactory =
81                        SipFactory.getInstance().createAddressFactory();
82            } catch (PeerUnavailableException e) {
83                throw new RuntimeException(e);
84            }
85        }
86
87        /**
88         * Creates a builder based on the given profile.
89         */
90        public Builder(SipProfile profile) {
91            if (profile == null) throw new NullPointerException();
92            try {
93                mProfile = (SipProfile) profile.clone();
94            } catch (CloneNotSupportedException e) {
95                throw new RuntimeException("should not occur", e);
96            }
97            mProfile.mAddress = null;
98            mUri = profile.getUri();
99            mUri.setUserPassword(profile.getPassword());
100            mDisplayName = profile.getDisplayName();
101            mProxyAddress = profile.getProxyAddress();
102            mProfile.mPort = profile.getPort();
103        }
104
105        /**
106         * Constructor.
107         *
108         * @param uriString the URI string as "sip:<user_name>@<domain>"
109         * @throws ParseException if the string is not a valid URI
110         */
111        public Builder(String uriString) throws ParseException {
112            if (uriString == null) {
113                throw new NullPointerException("uriString cannot be null");
114            }
115            URI uri = mAddressFactory.createURI(fix(uriString));
116            if (uri instanceof SipURI) {
117                mUri = (SipURI) uri;
118            } else {
119                throw new ParseException(uriString + " is not a SIP URI", 0);
120            }
121            mProfile.mDomain = mUri.getHost();
122        }
123
124        /**
125         * Constructor.
126         *
127         * @param username username of the SIP account
128         * @param serverDomain the SIP server domain; if the network address
129         *      is different from the domain, use {@link #setOutboundProxy} to
130         *      set server address
131         * @throws ParseException if the parameters are not valid
132         */
133        public Builder(String username, String serverDomain)
134                throws ParseException {
135            if ((username == null) || (serverDomain == null)) {
136                throw new NullPointerException(
137                        "username and serverDomain cannot be null");
138            }
139            mUri = mAddressFactory.createSipURI(username, serverDomain);
140            mProfile.mDomain = serverDomain;
141        }
142
143        private String fix(String uriString) {
144            return (uriString.trim().toLowerCase().startsWith("sip:")
145                    ? uriString
146                    : "sip:" + uriString);
147        }
148
149        /**
150         * Sets the name of the profile. This name is given by user.
151         *
152         * @param name name of the profile
153         * @return this builder object
154         */
155        public Builder setProfileName(String name) {
156            mProfile.mProfileName = name;
157            return this;
158        }
159
160        /**
161         * Sets the password of the SIP account
162         *
163         * @param password password of the SIP account
164         * @return this builder object
165         */
166        public Builder setPassword(String password) {
167            mUri.setUserPassword(password);
168            return this;
169        }
170
171        /**
172         * Sets the port number of the server. By default, it is 5060.
173         *
174         * @param port port number of the server
175         * @return this builder object
176         * @throws IllegalArgumentException if the port number is out of range
177         */
178        public Builder setPort(int port) throws IllegalArgumentException {
179            if ((port > 65535) || (port < 1000)) {
180                throw new IllegalArgumentException("incorrect port arugment: " + port);
181            }
182            mProfile.mPort = port;
183            return this;
184        }
185
186        /**
187         * Sets the protocol used to connect to the SIP server. Currently,
188         * only "UDP" and "TCP" are supported.
189         *
190         * @param protocol the protocol string
191         * @return this builder object
192         * @throws IllegalArgumentException if the protocol is not recognized
193         */
194        public Builder setProtocol(String protocol)
195                throws IllegalArgumentException {
196            if (protocol == null) {
197                throw new NullPointerException("protocol cannot be null");
198            }
199            protocol = protocol.toUpperCase();
200            if (!protocol.equals(UDP) && !protocol.equals(TCP)) {
201                throw new IllegalArgumentException(
202                        "unsupported protocol: " + protocol);
203            }
204            mProfile.mProtocol = protocol;
205            return this;
206        }
207
208        /**
209         * Sets the outbound proxy of the SIP server.
210         *
211         * @param outboundProxy the network address of the outbound proxy
212         * @return this builder object
213         */
214        public Builder setOutboundProxy(String outboundProxy) {
215            mProxyAddress = outboundProxy;
216            return this;
217        }
218
219        /**
220         * Sets the display name of the user.
221         *
222         * @param displayName display name of the user
223         * @return this builder object
224         */
225        public Builder setDisplayName(String displayName) {
226            mDisplayName = displayName;
227            return this;
228        }
229
230        /**
231         * Sets the send keep-alive flag.
232         *
233         * @param flag true if sending keep-alive message is required,
234         *      false otherwise
235         * @return this builder object
236         */
237        public Builder setSendKeepAlive(boolean flag) {
238            mProfile.mSendKeepAlive = flag;
239            return this;
240        }
241
242
243        /**
244         * Sets the auto. registration flag.
245         *
246         * @param flag true if the profile will be registered automatically,
247         *      false otherwise
248         * @return this builder object
249         */
250        public Builder setAutoRegistration(boolean flag) {
251            mProfile.mAutoRegistration = flag;
252            return this;
253        }
254
255        /**
256         * Builds and returns the SIP profile object.
257         *
258         * @return the profile object created
259         */
260        public SipProfile build() {
261            // remove password from URI
262            mProfile.mPassword = mUri.getUserPassword();
263            mUri.setUserPassword(null);
264            try {
265                if (!TextUtils.isEmpty(mProxyAddress)) {
266                    SipURI uri = (SipURI)
267                            mAddressFactory.createURI(fix(mProxyAddress));
268                    mProfile.mProxyAddress = uri.getHost();
269                } else {
270                    if (!mProfile.mProtocol.equals(UDP)) {
271                        mUri.setTransportParam(mProfile.mProtocol);
272                    }
273                    if (mProfile.mPort != DEFAULT_PORT) {
274                        mUri.setPort(mProfile.mPort);
275                    }
276                }
277                mProfile.mAddress = mAddressFactory.createAddress(
278                        mDisplayName, mUri);
279            } catch (InvalidArgumentException e) {
280                throw new RuntimeException(e);
281            } catch (ParseException e) {
282                // must not occur
283                throw new RuntimeException(e);
284            }
285            return mProfile;
286        }
287    }
288
289    private SipProfile() {
290    }
291
292    private SipProfile(Parcel in) {
293        mAddress = (Address) in.readSerializable();
294        mProxyAddress = in.readString();
295        mPassword = in.readString();
296        mDomain = in.readString();
297        mProtocol = in.readString();
298        mProfileName = in.readString();
299        mSendKeepAlive = (in.readInt() == 0) ? false : true;
300        mAutoRegistration = (in.readInt() == 0) ? false : true;
301        mCallingUid = in.readInt();
302        mPort = in.readInt();
303    }
304
305    @Override
306    public void writeToParcel(Parcel out, int flags) {
307        out.writeSerializable(mAddress);
308        out.writeString(mProxyAddress);
309        out.writeString(mPassword);
310        out.writeString(mDomain);
311        out.writeString(mProtocol);
312        out.writeString(mProfileName);
313        out.writeInt(mSendKeepAlive ? 1 : 0);
314        out.writeInt(mAutoRegistration ? 1 : 0);
315        out.writeInt(mCallingUid);
316        out.writeInt(mPort);
317    }
318
319    @Override
320    public int describeContents() {
321        return 0;
322    }
323
324    /**
325     * Gets the SIP URI of this profile.
326     *
327     * @return the SIP URI of this profile
328     * @hide
329     */
330    public SipURI getUri() {
331        return (SipURI) mAddress.getURI();
332    }
333
334    /**
335     * Gets the SIP URI string of this profile.
336     *
337     * @return the SIP URI string of this profile
338     */
339    public String getUriString() {
340        // We need to return the sip uri domain instead of
341        // the SIP URI with transport, port information if
342        // the outbound proxy address exists.
343        if (!TextUtils.isEmpty(mProxyAddress)) {
344            return "sip:" + getUserName() + "@" + mDomain;
345        }
346        return getUri().toString();
347    }
348
349    /**
350     * Gets the SIP address of this profile.
351     *
352     * @return the SIP address of this profile
353     * @hide
354     */
355    public Address getSipAddress() {
356        return mAddress;
357    }
358
359    /**
360     * Gets the display name of the user.
361     *
362     * @return the display name of the user
363     */
364    public String getDisplayName() {
365        return mAddress.getDisplayName();
366    }
367
368    /**
369     * Gets the username.
370     *
371     * @return the username
372     */
373    public String getUserName() {
374        return getUri().getUser();
375    }
376
377    /**
378     * Gets the password.
379     *
380     * @return the password
381     */
382    public String getPassword() {
383        return mPassword;
384    }
385
386    /**
387     * Gets the SIP domain.
388     *
389     * @return the SIP domain
390     */
391    public String getSipDomain() {
392        return mDomain;
393    }
394
395    /**
396     * Gets the port number of the SIP server.
397     *
398     * @return the port number of the SIP server
399     */
400    public int getPort() {
401        return mPort;
402    }
403
404    /**
405     * Gets the protocol used to connect to the server.
406     *
407     * @return the protocol
408     */
409    public String getProtocol() {
410        return mProtocol;
411    }
412
413    /**
414     * Gets the network address of the server outbound proxy.
415     *
416     * @return the network address of the server outbound proxy
417     */
418    public String getProxyAddress() {
419        return mProxyAddress;
420    }
421
422    /**
423     * Gets the (user-defined) name of the profile.
424     *
425     * @return name of the profile
426     */
427    public String getProfileName() {
428        return mProfileName;
429    }
430
431    /**
432     * Gets the flag of 'Sending keep-alive'.
433     *
434     * @return the flag of sending SIP keep-alive messages.
435     */
436    public boolean getSendKeepAlive() {
437        return mSendKeepAlive;
438    }
439
440    /**
441     * Gets the flag of 'Auto Registration'.
442     *
443     * @return the flag of registering the profile automatically.
444     */
445    public boolean getAutoRegistration() {
446        return mAutoRegistration;
447    }
448
449    /**
450     * Sets the calling process's Uid in the sip service.
451     * @hide
452     */
453    public void setCallingUid(int uid) {
454        mCallingUid = uid;
455    }
456
457    /**
458     * Gets the calling process's Uid in the sip settings.
459     * @hide
460     */
461    public int getCallingUid() {
462        return mCallingUid;
463    }
464
465    private Object readResolve() throws ObjectStreamException {
466        // For compatibility.
467        if (mPort == 0) mPort = DEFAULT_PORT;
468        return this;
469    }
470}
471