| /* |
| * Copyright (C) 2010 The Android Open Source Project |
| * |
| * 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 android.net.sip; |
| |
| import android.os.Parcel; |
| import android.os.Parcelable; |
| import android.text.TextUtils; |
| |
| import java.io.ObjectStreamException; |
| import java.io.Serializable; |
| import java.text.ParseException; |
| import javax.sip.InvalidArgumentException; |
| import javax.sip.ListeningPoint; |
| import javax.sip.PeerUnavailableException; |
| import javax.sip.SipFactory; |
| import javax.sip.address.Address; |
| import javax.sip.address.AddressFactory; |
| import javax.sip.address.SipURI; |
| import javax.sip.address.URI; |
| |
| /** |
| * Defines a SIP profile, including a SIP account, domain and server information. |
| * <p>You can create a {@link SipProfile} using {@link |
| * SipProfile.Builder}. You can also retrieve one from a {@link SipSession}, using {@link |
| * SipSession#getLocalProfile} and {@link SipSession#getPeerProfile}.</p> |
| */ |
| public class SipProfile implements Parcelable, Serializable, Cloneable { |
| private static final long serialVersionUID = 1L; |
| private static final int DEFAULT_PORT = 5060; |
| private static final String TCP = "TCP"; |
| private static final String UDP = "UDP"; |
| private Address mAddress; |
| private String mProxyAddress; |
| private String mPassword; |
| private String mDomain; |
| private String mProtocol = UDP; |
| private String mProfileName; |
| private String mAuthUserName; |
| private int mPort = DEFAULT_PORT; |
| private boolean mSendKeepAlive = false; |
| private boolean mAutoRegistration = true; |
| private transient int mCallingUid = 0; |
| |
| public static final Parcelable.Creator<SipProfile> CREATOR = |
| new Parcelable.Creator<SipProfile>() { |
| public SipProfile createFromParcel(Parcel in) { |
| return new SipProfile(in); |
| } |
| |
| public SipProfile[] newArray(int size) { |
| return new SipProfile[size]; |
| } |
| }; |
| |
| /** |
| * Helper class for creating a {@link SipProfile}. |
| */ |
| public static class Builder { |
| private AddressFactory mAddressFactory; |
| private SipProfile mProfile = new SipProfile(); |
| private SipURI mUri; |
| private String mDisplayName; |
| private String mProxyAddress; |
| |
| { |
| try { |
| mAddressFactory = |
| SipFactory.getInstance().createAddressFactory(); |
| } catch (PeerUnavailableException e) { |
| throw new RuntimeException(e); |
| } |
| } |
| |
| /** |
| * Creates a builder based on the given profile. |
| */ |
| public Builder(SipProfile profile) { |
| if (profile == null) throw new NullPointerException(); |
| try { |
| mProfile = (SipProfile) profile.clone(); |
| } catch (CloneNotSupportedException e) { |
| throw new RuntimeException("should not occur", e); |
| } |
| mProfile.mAddress = null; |
| mUri = profile.getUri(); |
| mUri.setUserPassword(profile.getPassword()); |
| mDisplayName = profile.getDisplayName(); |
| mProxyAddress = profile.getProxyAddress(); |
| mProfile.mPort = profile.getPort(); |
| } |
| |
| /** |
| * Constructor. |
| * |
| * @param uriString the URI string as "sip:<user_name>@<domain>" |
| * @throws ParseException if the string is not a valid URI |
| */ |
| public Builder(String uriString) throws ParseException { |
| if (uriString == null) { |
| throw new NullPointerException("uriString cannot be null"); |
| } |
| URI uri = mAddressFactory.createURI(fix(uriString)); |
| if (uri instanceof SipURI) { |
| mUri = (SipURI) uri; |
| } else { |
| throw new ParseException(uriString + " is not a SIP URI", 0); |
| } |
| mProfile.mDomain = mUri.getHost(); |
| } |
| |
| /** |
| * Constructor. |
| * |
| * @param username username of the SIP account |
| * @param serverDomain the SIP server domain; if the network address |
| * is different from the domain, use {@link #setOutboundProxy} to |
| * set server address |
| * @throws ParseException if the parameters are not valid |
| */ |
| public Builder(String username, String serverDomain) |
| throws ParseException { |
| if ((username == null) || (serverDomain == null)) { |
| throw new NullPointerException( |
| "username and serverDomain cannot be null"); |
| } |
| mUri = mAddressFactory.createSipURI(username, serverDomain); |
| mProfile.mDomain = serverDomain; |
| } |
| |
| private String fix(String uriString) { |
| return (uriString.trim().toLowerCase().startsWith("sip:") |
| ? uriString |
| : "sip:" + uriString); |
| } |
| |
| /** |
| * Sets the username used for authentication. |
| * |
| * @param name auth. name of the profile |
| * @return this builder object |
| * @hide // TODO: remove when we make it public |
| */ |
| public Builder setAuthUserName(String name) { |
| mProfile.mAuthUserName = name; |
| return this; |
| } |
| |
| /** |
| * Sets the name of the profile. This name is given by user. |
| * |
| * @param name name of the profile |
| * @return this builder object |
| */ |
| public Builder setProfileName(String name) { |
| mProfile.mProfileName = name; |
| return this; |
| } |
| |
| /** |
| * Sets the password of the SIP account |
| * |
| * @param password password of the SIP account |
| * @return this builder object |
| */ |
| public Builder setPassword(String password) { |
| mUri.setUserPassword(password); |
| return this; |
| } |
| |
| /** |
| * Sets the port number of the server. By default, it is 5060. |
| * |
| * @param port port number of the server |
| * @return this builder object |
| * @throws IllegalArgumentException if the port number is out of range |
| */ |
| public Builder setPort(int port) throws IllegalArgumentException { |
| if ((port > 65535) || (port < 1000)) { |
| throw new IllegalArgumentException("incorrect port arugment: " + port); |
| } |
| mProfile.mPort = port; |
| return this; |
| } |
| |
| /** |
| * Sets the protocol used to connect to the SIP server. Currently, |
| * only "UDP" and "TCP" are supported. |
| * |
| * @param protocol the protocol string |
| * @return this builder object |
| * @throws IllegalArgumentException if the protocol is not recognized |
| */ |
| public Builder setProtocol(String protocol) |
| throws IllegalArgumentException { |
| if (protocol == null) { |
| throw new NullPointerException("protocol cannot be null"); |
| } |
| protocol = protocol.toUpperCase(); |
| if (!protocol.equals(UDP) && !protocol.equals(TCP)) { |
| throw new IllegalArgumentException( |
| "unsupported protocol: " + protocol); |
| } |
| mProfile.mProtocol = protocol; |
| return this; |
| } |
| |
| /** |
| * Sets the outbound proxy of the SIP server. |
| * |
| * @param outboundProxy the network address of the outbound proxy |
| * @return this builder object |
| */ |
| public Builder setOutboundProxy(String outboundProxy) { |
| mProxyAddress = outboundProxy; |
| return this; |
| } |
| |
| /** |
| * Sets the display name of the user. |
| * |
| * @param displayName display name of the user |
| * @return this builder object |
| */ |
| public Builder setDisplayName(String displayName) { |
| mDisplayName = displayName; |
| return this; |
| } |
| |
| /** |
| * Sets the send keep-alive flag. |
| * |
| * @param flag true if sending keep-alive message is required, |
| * false otherwise |
| * @return this builder object |
| */ |
| public Builder setSendKeepAlive(boolean flag) { |
| mProfile.mSendKeepAlive = flag; |
| return this; |
| } |
| |
| |
| /** |
| * Sets the auto. registration flag. |
| * |
| * @param flag true if the profile will be registered automatically, |
| * false otherwise |
| * @return this builder object |
| */ |
| public Builder setAutoRegistration(boolean flag) { |
| mProfile.mAutoRegistration = flag; |
| return this; |
| } |
| |
| /** |
| * Builds and returns the SIP profile object. |
| * |
| * @return the profile object created |
| */ |
| public SipProfile build() { |
| // remove password from URI |
| mProfile.mPassword = mUri.getUserPassword(); |
| mUri.setUserPassword(null); |
| try { |
| if (!TextUtils.isEmpty(mProxyAddress)) { |
| SipURI uri = (SipURI) |
| mAddressFactory.createURI(fix(mProxyAddress)); |
| mProfile.mProxyAddress = uri.getHost(); |
| } else { |
| if (!mProfile.mProtocol.equals(UDP)) { |
| mUri.setTransportParam(mProfile.mProtocol); |
| } |
| if (mProfile.mPort != DEFAULT_PORT) { |
| mUri.setPort(mProfile.mPort); |
| } |
| } |
| mProfile.mAddress = mAddressFactory.createAddress( |
| mDisplayName, mUri); |
| } catch (InvalidArgumentException e) { |
| throw new RuntimeException(e); |
| } catch (ParseException e) { |
| // must not occur |
| throw new RuntimeException(e); |
| } |
| return mProfile; |
| } |
| } |
| |
| private SipProfile() { |
| } |
| |
| private SipProfile(Parcel in) { |
| mAddress = (Address) in.readSerializable(); |
| mProxyAddress = in.readString(); |
| mPassword = in.readString(); |
| mDomain = in.readString(); |
| mProtocol = in.readString(); |
| mProfileName = in.readString(); |
| mSendKeepAlive = (in.readInt() == 0) ? false : true; |
| mAutoRegistration = (in.readInt() == 0) ? false : true; |
| mCallingUid = in.readInt(); |
| mPort = in.readInt(); |
| mAuthUserName = in.readString(); |
| } |
| |
| @Override |
| public void writeToParcel(Parcel out, int flags) { |
| out.writeSerializable(mAddress); |
| out.writeString(mProxyAddress); |
| out.writeString(mPassword); |
| out.writeString(mDomain); |
| out.writeString(mProtocol); |
| out.writeString(mProfileName); |
| out.writeInt(mSendKeepAlive ? 1 : 0); |
| out.writeInt(mAutoRegistration ? 1 : 0); |
| out.writeInt(mCallingUid); |
| out.writeInt(mPort); |
| out.writeString(mAuthUserName); |
| } |
| |
| @Override |
| public int describeContents() { |
| return 0; |
| } |
| |
| /** |
| * Gets the SIP URI of this profile. |
| * |
| * @return the SIP URI of this profile |
| * @hide |
| */ |
| public SipURI getUri() { |
| return (SipURI) mAddress.getURI(); |
| } |
| |
| /** |
| * Gets the SIP URI string of this profile. |
| * |
| * @return the SIP URI string of this profile |
| */ |
| public String getUriString() { |
| // We need to return the sip uri domain instead of |
| // the SIP URI with transport, port information if |
| // the outbound proxy address exists. |
| if (!TextUtils.isEmpty(mProxyAddress)) { |
| return "sip:" + getUserName() + "@" + mDomain; |
| } |
| return getUri().toString(); |
| } |
| |
| /** |
| * Gets the SIP address of this profile. |
| * |
| * @return the SIP address of this profile |
| * @hide |
| */ |
| public Address getSipAddress() { |
| return mAddress; |
| } |
| |
| /** |
| * Gets the display name of the user. |
| * |
| * @return the display name of the user |
| */ |
| public String getDisplayName() { |
| return mAddress.getDisplayName(); |
| } |
| |
| /** |
| * Gets the username. |
| * |
| * @return the username |
| */ |
| public String getUserName() { |
| return getUri().getUser(); |
| } |
| |
| /** |
| * Gets the username for authentication. If it is null, then the username |
| * should be used in authentication instead. |
| * |
| * @return the auth. username |
| * @hide // TODO: remove when we make it public |
| */ |
| public String getAuthUserName() { |
| return mAuthUserName; |
| } |
| |
| /** |
| * Gets the password. |
| * |
| * @return the password |
| */ |
| public String getPassword() { |
| return mPassword; |
| } |
| |
| /** |
| * Gets the SIP domain. |
| * |
| * @return the SIP domain |
| */ |
| public String getSipDomain() { |
| return mDomain; |
| } |
| |
| /** |
| * Gets the port number of the SIP server. |
| * |
| * @return the port number of the SIP server |
| */ |
| public int getPort() { |
| return mPort; |
| } |
| |
| /** |
| * Gets the protocol used to connect to the server. |
| * |
| * @return the protocol |
| */ |
| public String getProtocol() { |
| return mProtocol; |
| } |
| |
| /** |
| * Gets the network address of the server outbound proxy. |
| * |
| * @return the network address of the server outbound proxy |
| */ |
| public String getProxyAddress() { |
| return mProxyAddress; |
| } |
| |
| /** |
| * Gets the (user-defined) name of the profile. |
| * |
| * @return name of the profile |
| */ |
| public String getProfileName() { |
| return mProfileName; |
| } |
| |
| /** |
| * Gets the flag of 'Sending keep-alive'. |
| * |
| * @return the flag of sending SIP keep-alive messages. |
| */ |
| public boolean getSendKeepAlive() { |
| return mSendKeepAlive; |
| } |
| |
| /** |
| * Gets the flag of 'Auto Registration'. |
| * |
| * @return the flag of registering the profile automatically. |
| */ |
| public boolean getAutoRegistration() { |
| return mAutoRegistration; |
| } |
| |
| /** |
| * Sets the calling process's Uid in the sip service. |
| * @hide |
| */ |
| public void setCallingUid(int uid) { |
| mCallingUid = uid; |
| } |
| |
| /** |
| * Gets the calling process's Uid in the sip settings. |
| * @hide |
| */ |
| public int getCallingUid() { |
| return mCallingUid; |
| } |
| |
| private Object readResolve() throws ObjectStreamException { |
| // For compatibility. |
| if (mPort == 0) mPort = DEFAULT_PORT; |
| return this; |
| } |
| } |