blob: 34d91dd7f84fb8ec06488a710ccf7eebc6f79f99 [file] [log] [blame]
Chung-yih Wang363c2ab2010-08-05 10:21:20 +08001/*
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
Chung-yih Wangf0532922010-11-03 13:11:53 +080023import java.io.ObjectStreamException;
Chung-yih Wang363c2ab2010-08-05 10:21:20 +080024import 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/**
Scott Main02b1d682010-10-22 11:29:57 -070036 * 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>
Chung-yih Wang363c2ab2010-08-05 10:21:20 +080040 */
Hung-ying Tyancf95f5d2010-08-23 21:36:14 +080041public class SipProfile implements Parcelable, Serializable, Cloneable {
Chung-yih Wang363c2ab2010-08-05 10:21:20 +080042 private static final long serialVersionUID = 1L;
43 private static final int DEFAULT_PORT = 5060;
Chung-yih Wangf0532922010-11-03 13:11:53 +080044 private static final String TCP = "TCP";
45 private static final String UDP = "UDP";
Chung-yih Wang363c2ab2010-08-05 10:21:20 +080046 private Address mAddress;
47 private String mProxyAddress;
48 private String mPassword;
49 private String mDomain;
Chung-yih Wangf0532922010-11-03 13:11:53 +080050 private String mProtocol = UDP;
Chung-yih Wang363c2ab2010-08-05 10:21:20 +080051 private String mProfileName;
Chung-yih Wang0f7de882011-01-06 18:44:43 +080052 private String mAuthUserName;
Chung-yih Wangf0532922010-11-03 13:11:53 +080053 private int mPort = DEFAULT_PORT;
Chung-yih Wang363c2ab2010-08-05 10:21:20 +080054 private boolean mSendKeepAlive = false;
55 private boolean mAutoRegistration = true;
Hung-ying Tyan60264b302010-09-01 09:15:10 +080056 private transient int mCallingUid = 0;
Chung-yih Wang363c2ab2010-08-05 10:21:20 +080057
Chung-yih Wang363c2ab2010-08-05 10:21:20 +080058 public static final Parcelable.Creator<SipProfile> CREATOR =
59 new Parcelable.Creator<SipProfile>() {
60 public SipProfile createFromParcel(Parcel in) {
61 return new SipProfile(in);
62 }
63
64 public SipProfile[] newArray(int size) {
65 return new SipProfile[size];
66 }
67 };
68
69 /**
Scott Main02b1d682010-10-22 11:29:57 -070070 * Helper class for creating a {@link SipProfile}.
Chung-yih Wang363c2ab2010-08-05 10:21:20 +080071 */
72 public static class Builder {
73 private AddressFactory mAddressFactory;
74 private SipProfile mProfile = new SipProfile();
75 private SipURI mUri;
76 private String mDisplayName;
77 private String mProxyAddress;
78
79 {
80 try {
81 mAddressFactory =
82 SipFactory.getInstance().createAddressFactory();
83 } catch (PeerUnavailableException e) {
84 throw new RuntimeException(e);
85 }
86 }
87
88 /**
Hung-ying Tyancf95f5d2010-08-23 21:36:14 +080089 * Creates a builder based on the given profile.
90 */
91 public Builder(SipProfile profile) {
92 if (profile == null) throw new NullPointerException();
93 try {
94 mProfile = (SipProfile) profile.clone();
95 } catch (CloneNotSupportedException e) {
96 throw new RuntimeException("should not occur", e);
97 }
98 mProfile.mAddress = null;
99 mUri = profile.getUri();
100 mUri.setUserPassword(profile.getPassword());
101 mDisplayName = profile.getDisplayName();
102 mProxyAddress = profile.getProxyAddress();
Chung-yih Wangf0532922010-11-03 13:11:53 +0800103 mProfile.mPort = profile.getPort();
Hung-ying Tyancf95f5d2010-08-23 21:36:14 +0800104 }
105
106 /**
Chung-yih Wang363c2ab2010-08-05 10:21:20 +0800107 * Constructor.
108 *
109 * @param uriString the URI string as "sip:<user_name>@<domain>"
110 * @throws ParseException if the string is not a valid URI
111 */
112 public Builder(String uriString) throws ParseException {
113 if (uriString == null) {
114 throw new NullPointerException("uriString cannot be null");
115 }
116 URI uri = mAddressFactory.createURI(fix(uriString));
117 if (uri instanceof SipURI) {
118 mUri = (SipURI) uri;
119 } else {
120 throw new ParseException(uriString + " is not a SIP URI", 0);
121 }
122 mProfile.mDomain = mUri.getHost();
123 }
124
125 /**
126 * Constructor.
127 *
128 * @param username username of the SIP account
129 * @param serverDomain the SIP server domain; if the network address
Hung-ying Tyan286bb5a2010-09-14 20:43:54 +0800130 * is different from the domain, use {@link #setOutboundProxy} to
131 * set server address
Chung-yih Wang363c2ab2010-08-05 10:21:20 +0800132 * @throws ParseException if the parameters are not valid
133 */
134 public Builder(String username, String serverDomain)
135 throws ParseException {
136 if ((username == null) || (serverDomain == null)) {
137 throw new NullPointerException(
138 "username and serverDomain cannot be null");
139 }
140 mUri = mAddressFactory.createSipURI(username, serverDomain);
141 mProfile.mDomain = serverDomain;
142 }
143
144 private String fix(String uriString) {
145 return (uriString.trim().toLowerCase().startsWith("sip:")
146 ? uriString
147 : "sip:" + uriString);
148 }
149
150 /**
Chung-yih Wang0f7de882011-01-06 18:44:43 +0800151 * Sets the username used for authentication.
152 *
Chung-yih Wang9e25df42011-02-10 15:20:41 +0800153 * @param name authentication username of the profile
Chung-yih Wang0f7de882011-01-06 18:44:43 +0800154 * @return this builder object
Chung-yih Wang0f7de882011-01-06 18:44:43 +0800155 */
156 public Builder setAuthUserName(String name) {
157 mProfile.mAuthUserName = name;
158 return this;
159 }
160
161 /**
Chung-yih Wang363c2ab2010-08-05 10:21:20 +0800162 * Sets the name of the profile. This name is given by user.
163 *
164 * @param name name of the profile
165 * @return this builder object
166 */
167 public Builder setProfileName(String name) {
168 mProfile.mProfileName = name;
169 return this;
170 }
171
172 /**
173 * Sets the password of the SIP account
174 *
175 * @param password password of the SIP account
176 * @return this builder object
177 */
178 public Builder setPassword(String password) {
179 mUri.setUserPassword(password);
180 return this;
181 }
182
183 /**
184 * Sets the port number of the server. By default, it is 5060.
185 *
186 * @param port port number of the server
187 * @return this builder object
Hung-ying Tyan99bf4e42010-09-14 20:12:59 +0800188 * @throws IllegalArgumentException if the port number is out of range
Chung-yih Wang363c2ab2010-08-05 10:21:20 +0800189 */
Hung-ying Tyan99bf4e42010-09-14 20:12:59 +0800190 public Builder setPort(int port) throws IllegalArgumentException {
Chung-yih Wangf0532922010-11-03 13:11:53 +0800191 if ((port > 65535) || (port < 1000)) {
Hung-ying Tyaneecf4a62010-12-16 16:13:29 +0800192 throw new IllegalArgumentException("incorrect port arugment: " + port);
Hung-ying Tyan99bf4e42010-09-14 20:12:59 +0800193 }
Chung-yih Wangf0532922010-11-03 13:11:53 +0800194 mProfile.mPort = port;
195 return this;
Chung-yih Wang363c2ab2010-08-05 10:21:20 +0800196 }
197
198 /**
199 * Sets the protocol used to connect to the SIP server. Currently,
200 * only "UDP" and "TCP" are supported.
201 *
202 * @param protocol the protocol string
203 * @return this builder object
Hung-ying Tyan99bf4e42010-09-14 20:12:59 +0800204 * @throws IllegalArgumentException if the protocol is not recognized
Chung-yih Wang363c2ab2010-08-05 10:21:20 +0800205 */
206 public Builder setProtocol(String protocol)
Hung-ying Tyan99bf4e42010-09-14 20:12:59 +0800207 throws IllegalArgumentException {
Chung-yih Wang363c2ab2010-08-05 10:21:20 +0800208 if (protocol == null) {
209 throw new NullPointerException("protocol cannot be null");
210 }
211 protocol = protocol.toUpperCase();
Chung-yih Wangf0532922010-11-03 13:11:53 +0800212 if (!protocol.equals(UDP) && !protocol.equals(TCP)) {
Hung-ying Tyan99bf4e42010-09-14 20:12:59 +0800213 throw new IllegalArgumentException(
Chung-yih Wang363c2ab2010-08-05 10:21:20 +0800214 "unsupported protocol: " + protocol);
215 }
216 mProfile.mProtocol = protocol;
217 return this;
218 }
219
220 /**
221 * Sets the outbound proxy of the SIP server.
222 *
223 * @param outboundProxy the network address of the outbound proxy
224 * @return this builder object
225 */
226 public Builder setOutboundProxy(String outboundProxy) {
227 mProxyAddress = outboundProxy;
228 return this;
229 }
230
231 /**
232 * Sets the display name of the user.
233 *
234 * @param displayName display name of the user
235 * @return this builder object
236 */
237 public Builder setDisplayName(String displayName) {
238 mDisplayName = displayName;
239 return this;
240 }
241
242 /**
243 * Sets the send keep-alive flag.
244 *
245 * @param flag true if sending keep-alive message is required,
246 * false otherwise
247 * @return this builder object
248 */
249 public Builder setSendKeepAlive(boolean flag) {
250 mProfile.mSendKeepAlive = flag;
251 return this;
252 }
253
254
255 /**
256 * Sets the auto. registration flag.
257 *
258 * @param flag true if the profile will be registered automatically,
259 * false otherwise
260 * @return this builder object
261 */
262 public Builder setAutoRegistration(boolean flag) {
263 mProfile.mAutoRegistration = flag;
264 return this;
265 }
266
267 /**
268 * Builds and returns the SIP profile object.
269 *
270 * @return the profile object created
271 */
272 public SipProfile build() {
273 // remove password from URI
274 mProfile.mPassword = mUri.getUserPassword();
275 mUri.setUserPassword(null);
276 try {
Chung-yih Wang363c2ab2010-08-05 10:21:20 +0800277 if (!TextUtils.isEmpty(mProxyAddress)) {
278 SipURI uri = (SipURI)
279 mAddressFactory.createURI(fix(mProxyAddress));
280 mProfile.mProxyAddress = uri.getHost();
Chung-yih Wangf0532922010-11-03 13:11:53 +0800281 } else {
282 if (!mProfile.mProtocol.equals(UDP)) {
283 mUri.setTransportParam(mProfile.mProtocol);
284 }
285 if (mProfile.mPort != DEFAULT_PORT) {
286 mUri.setPort(mProfile.mPort);
287 }
Chung-yih Wang363c2ab2010-08-05 10:21:20 +0800288 }
Chung-yih Wangf0532922010-11-03 13:11:53 +0800289 mProfile.mAddress = mAddressFactory.createAddress(
290 mDisplayName, mUri);
291 } catch (InvalidArgumentException e) {
292 throw new RuntimeException(e);
Chung-yih Wang363c2ab2010-08-05 10:21:20 +0800293 } catch (ParseException e) {
294 // must not occur
295 throw new RuntimeException(e);
296 }
297 return mProfile;
298 }
299 }
300
301 private SipProfile() {
302 }
303
304 private SipProfile(Parcel in) {
305 mAddress = (Address) in.readSerializable();
306 mProxyAddress = in.readString();
307 mPassword = in.readString();
308 mDomain = in.readString();
309 mProtocol = in.readString();
310 mProfileName = in.readString();
311 mSendKeepAlive = (in.readInt() == 0) ? false : true;
312 mAutoRegistration = (in.readInt() == 0) ? false : true;
Chung-yih Wang5424c8d2010-08-25 19:02:18 +0800313 mCallingUid = in.readInt();
Chung-yih Wangf0532922010-11-03 13:11:53 +0800314 mPort = in.readInt();
Chung-yih Wang0f7de882011-01-06 18:44:43 +0800315 mAuthUserName = in.readString();
Chung-yih Wang363c2ab2010-08-05 10:21:20 +0800316 }
317
Hung-ying Tyan84a357b2010-09-16 04:11:32 +0800318 @Override
Chung-yih Wang363c2ab2010-08-05 10:21:20 +0800319 public void writeToParcel(Parcel out, int flags) {
320 out.writeSerializable(mAddress);
321 out.writeString(mProxyAddress);
322 out.writeString(mPassword);
323 out.writeString(mDomain);
324 out.writeString(mProtocol);
325 out.writeString(mProfileName);
326 out.writeInt(mSendKeepAlive ? 1 : 0);
327 out.writeInt(mAutoRegistration ? 1 : 0);
Chung-yih Wang5424c8d2010-08-25 19:02:18 +0800328 out.writeInt(mCallingUid);
Chung-yih Wangf0532922010-11-03 13:11:53 +0800329 out.writeInt(mPort);
Chung-yih Wang0f7de882011-01-06 18:44:43 +0800330 out.writeString(mAuthUserName);
Chung-yih Wang363c2ab2010-08-05 10:21:20 +0800331 }
332
Hung-ying Tyan84a357b2010-09-16 04:11:32 +0800333 @Override
Chung-yih Wang363c2ab2010-08-05 10:21:20 +0800334 public int describeContents() {
335 return 0;
336 }
337
338 /**
339 * Gets the SIP URI of this profile.
340 *
341 * @return the SIP URI of this profile
Hung-ying Tyan286bb5a2010-09-14 20:43:54 +0800342 * @hide
Chung-yih Wang363c2ab2010-08-05 10:21:20 +0800343 */
344 public SipURI getUri() {
345 return (SipURI) mAddress.getURI();
346 }
347
348 /**
349 * Gets the SIP URI string of this profile.
350 *
351 * @return the SIP URI string of this profile
352 */
353 public String getUriString() {
Chung-yih Wangf0532922010-11-03 13:11:53 +0800354 // We need to return the sip uri domain instead of
355 // the SIP URI with transport, port information if
356 // the outbound proxy address exists.
357 if (!TextUtils.isEmpty(mProxyAddress)) {
358 return "sip:" + getUserName() + "@" + mDomain;
359 }
360 return getUri().toString();
Chung-yih Wang363c2ab2010-08-05 10:21:20 +0800361 }
362
363 /**
364 * Gets the SIP address of this profile.
365 *
366 * @return the SIP address of this profile
Hung-ying Tyan286bb5a2010-09-14 20:43:54 +0800367 * @hide
Chung-yih Wang363c2ab2010-08-05 10:21:20 +0800368 */
369 public Address getSipAddress() {
370 return mAddress;
371 }
372
373 /**
374 * Gets the display name of the user.
375 *
376 * @return the display name of the user
377 */
378 public String getDisplayName() {
379 return mAddress.getDisplayName();
380 }
381
382 /**
383 * Gets the username.
384 *
385 * @return the username
386 */
387 public String getUserName() {
388 return getUri().getUser();
389 }
390
391 /**
Chung-yih Wang0f7de882011-01-06 18:44:43 +0800392 * Gets the username for authentication. If it is null, then the username
Chung-yih Wang9e25df42011-02-10 15:20:41 +0800393 * is used in authentication instead.
Chung-yih Wang0f7de882011-01-06 18:44:43 +0800394 *
Chung-yih Wang9e25df42011-02-10 15:20:41 +0800395 * @return the authentication username
396 * @see #getUserName
Chung-yih Wang0f7de882011-01-06 18:44:43 +0800397 */
398 public String getAuthUserName() {
399 return mAuthUserName;
400 }
401
402 /**
Chung-yih Wang363c2ab2010-08-05 10:21:20 +0800403 * Gets the password.
404 *
405 * @return the password
406 */
407 public String getPassword() {
408 return mPassword;
409 }
410
411 /**
412 * Gets the SIP domain.
413 *
414 * @return the SIP domain
415 */
416 public String getSipDomain() {
417 return mDomain;
418 }
419
420 /**
421 * Gets the port number of the SIP server.
422 *
423 * @return the port number of the SIP server
424 */
425 public int getPort() {
Chung-yih Wangf0532922010-11-03 13:11:53 +0800426 return mPort;
Chung-yih Wang363c2ab2010-08-05 10:21:20 +0800427 }
428
429 /**
430 * Gets the protocol used to connect to the server.
431 *
432 * @return the protocol
433 */
434 public String getProtocol() {
435 return mProtocol;
436 }
437
438 /**
439 * Gets the network address of the server outbound proxy.
440 *
441 * @return the network address of the server outbound proxy
442 */
443 public String getProxyAddress() {
444 return mProxyAddress;
445 }
446
447 /**
448 * Gets the (user-defined) name of the profile.
449 *
450 * @return name of the profile
451 */
452 public String getProfileName() {
453 return mProfileName;
454 }
455
456 /**
457 * Gets the flag of 'Sending keep-alive'.
458 *
459 * @return the flag of sending SIP keep-alive messages.
460 */
461 public boolean getSendKeepAlive() {
462 return mSendKeepAlive;
463 }
464
465 /**
466 * Gets the flag of 'Auto Registration'.
467 *
468 * @return the flag of registering the profile automatically.
469 */
470 public boolean getAutoRegistration() {
471 return mAutoRegistration;
472 }
Hung-ying Tyancf95f5d2010-08-23 21:36:14 +0800473
474 /**
Chung-yih Wang5424c8d2010-08-25 19:02:18 +0800475 * Sets the calling process's Uid in the sip service.
476 * @hide
477 */
478 public void setCallingUid(int uid) {
479 mCallingUid = uid;
480 }
481
482 /**
483 * Gets the calling process's Uid in the sip settings.
484 * @hide
485 */
486 public int getCallingUid() {
487 return mCallingUid;
488 }
Chung-yih Wangf0532922010-11-03 13:11:53 +0800489
490 private Object readResolve() throws ObjectStreamException {
491 // For compatibility.
492 if (mPort == 0) mPort = DEFAULT_PORT;
493 return this;
494 }
Chung-yih Wang363c2ab2010-08-05 10:21:20 +0800495}