/* * 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. *

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}.

* *
*

Developer Guides

*

For more information about using SIP, read the * Session Initiation Protocol * developer guide.

*
*/ 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 CREATOR = new Parcelable.Creator() { 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:@" * @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 authentication username of the profile * @return this builder object */ 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 * is used in authentication instead. * * @return the authentication username * @see #getUserName */ 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; } }