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