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 public 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 String mAuthUserName;
     53     private int mPort = DEFAULT_PORT;
     54     private boolean mSendKeepAlive = false;
     55     private boolean mAutoRegistration = true;
     56     private transient int mCallingUid = 0;
     57 
     58     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     /**
     70      * Helper class for creating a {@link SipProfile}.
     71      */
     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         /**
     89          * 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();
    103             mProfile.mPort = profile.getPort();
    104         }
    105 
    106         /**
    107          * 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
    130          *      is different from the domain, use {@link #setOutboundProxy} to
    131          *      set server address
    132          * @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         /**
    151          * Sets the username used for authentication.
    152          *
    153          * @param name auth. name of the profile
    154          * @return this builder object
    155          * @hide // TODO: remove when we make it public
    156          */
    157         public Builder setAuthUserName(String name) {
    158             mProfile.mAuthUserName = name;
    159             return this;
    160         }
    161 
    162         /**
    163          * Sets the name of the profile. This name is given by user.
    164          *
    165          * @param name name of the profile
    166          * @return this builder object
    167          */
    168         public Builder setProfileName(String name) {
    169             mProfile.mProfileName = name;
    170             return this;
    171         }
    172 
    173         /**
    174          * Sets the password of the SIP account
    175          *
    176          * @param password password of the SIP account
    177          * @return this builder object
    178          */
    179         public Builder setPassword(String password) {
    180             mUri.setUserPassword(password);
    181             return this;
    182         }
    183 
    184         /**
    185          * Sets the port number of the server. By default, it is 5060.
    186          *
    187          * @param port port number of the server
    188          * @return this builder object
    189          * @throws IllegalArgumentException if the port number is out of range
    190          */
    191         public Builder setPort(int port) throws IllegalArgumentException {
    192             if ((port > 65535) || (port < 1000)) {
    193                 throw new IllegalArgumentException("incorrect port arugment: " + port);
    194             }
    195             mProfile.mPort = port;
    196             return this;
    197         }
    198 
    199         /**
    200          * Sets the protocol used to connect to the SIP server. Currently,
    201          * only "UDP" and "TCP" are supported.
    202          *
    203          * @param protocol the protocol string
    204          * @return this builder object
    205          * @throws IllegalArgumentException if the protocol is not recognized
    206          */
    207         public Builder setProtocol(String protocol)
    208                 throws IllegalArgumentException {
    209             if (protocol == null) {
    210                 throw new NullPointerException("protocol cannot be null");
    211             }
    212             protocol = protocol.toUpperCase();
    213             if (!protocol.equals(UDP) && !protocol.equals(TCP)) {
    214                 throw new IllegalArgumentException(
    215                         "unsupported protocol: " + protocol);
    216             }
    217             mProfile.mProtocol = protocol;
    218             return this;
    219         }
    220 
    221         /**
    222          * Sets the outbound proxy of the SIP server.
    223          *
    224          * @param outboundProxy the network address of the outbound proxy
    225          * @return this builder object
    226          */
    227         public Builder setOutboundProxy(String outboundProxy) {
    228             mProxyAddress = outboundProxy;
    229             return this;
    230         }
    231 
    232         /**
    233          * Sets the display name of the user.
    234          *
    235          * @param displayName display name of the user
    236          * @return this builder object
    237          */
    238         public Builder setDisplayName(String displayName) {
    239             mDisplayName = displayName;
    240             return this;
    241         }
    242 
    243         /**
    244          * Sets the send keep-alive flag.
    245          *
    246          * @param flag true if sending keep-alive message is required,
    247          *      false otherwise
    248          * @return this builder object
    249          */
    250         public Builder setSendKeepAlive(boolean flag) {
    251             mProfile.mSendKeepAlive = flag;
    252             return this;
    253         }
    254 
    255 
    256         /**
    257          * Sets the auto. registration flag.
    258          *
    259          * @param flag true if the profile will be registered automatically,
    260          *      false otherwise
    261          * @return this builder object
    262          */
    263         public Builder setAutoRegistration(boolean flag) {
    264             mProfile.mAutoRegistration = flag;
    265             return this;
    266         }
    267 
    268         /**
    269          * Builds and returns the SIP profile object.
    270          *
    271          * @return the profile object created
    272          */
    273         public SipProfile build() {
    274             // remove password from URI
    275             mProfile.mPassword = mUri.getUserPassword();
    276             mUri.setUserPassword(null);
    277             try {
    278                 if (!TextUtils.isEmpty(mProxyAddress)) {
    279                     SipURI uri = (SipURI)
    280                             mAddressFactory.createURI(fix(mProxyAddress));
    281                     mProfile.mProxyAddress = uri.getHost();
    282                 } else {
    283                     if (!mProfile.mProtocol.equals(UDP)) {
    284                         mUri.setTransportParam(mProfile.mProtocol);
    285                     }
    286                     if (mProfile.mPort != DEFAULT_PORT) {
    287                         mUri.setPort(mProfile.mPort);
    288                     }
    289                 }
    290                 mProfile.mAddress = mAddressFactory.createAddress(
    291                         mDisplayName, mUri);
    292             } catch (InvalidArgumentException e) {
    293                 throw new RuntimeException(e);
    294             } catch (ParseException e) {
    295                 // must not occur
    296                 throw new RuntimeException(e);
    297             }
    298             return mProfile;
    299         }
    300     }
    301 
    302     private SipProfile() {
    303     }
    304 
    305     private SipProfile(Parcel in) {
    306         mAddress = (Address) in.readSerializable();
    307         mProxyAddress = in.readString();
    308         mPassword = in.readString();
    309         mDomain = in.readString();
    310         mProtocol = in.readString();
    311         mProfileName = in.readString();
    312         mSendKeepAlive = (in.readInt() == 0) ? false : true;
    313         mAutoRegistration = (in.readInt() == 0) ? false : true;
    314         mCallingUid = in.readInt();
    315         mPort = in.readInt();
    316         mAuthUserName = in.readString();
    317     }
    318 
    319     @Override
    320     public void writeToParcel(Parcel out, int flags) {
    321         out.writeSerializable(mAddress);
    322         out.writeString(mProxyAddress);
    323         out.writeString(mPassword);
    324         out.writeString(mDomain);
    325         out.writeString(mProtocol);
    326         out.writeString(mProfileName);
    327         out.writeInt(mSendKeepAlive ? 1 : 0);
    328         out.writeInt(mAutoRegistration ? 1 : 0);
    329         out.writeInt(mCallingUid);
    330         out.writeInt(mPort);
    331         out.writeString(mAuthUserName);
    332     }
    333 
    334     @Override
    335     public int describeContents() {
    336         return 0;
    337     }
    338 
    339     /**
    340      * Gets the SIP URI of this profile.
    341      *
    342      * @return the SIP URI of this profile
    343      * @hide
    344      */
    345     public SipURI getUri() {
    346         return (SipURI) mAddress.getURI();
    347     }
    348 
    349     /**
    350      * Gets the SIP URI string of this profile.
    351      *
    352      * @return the SIP URI string of this profile
    353      */
    354     public String getUriString() {
    355         // We need to return the sip uri domain instead of
    356         // the SIP URI with transport, port information if
    357         // the outbound proxy address exists.
    358         if (!TextUtils.isEmpty(mProxyAddress)) {
    359             return "sip:" + getUserName() + "@" + mDomain;
    360         }
    361         return getUri().toString();
    362     }
    363 
    364     /**
    365      * Gets the SIP address of this profile.
    366      *
    367      * @return the SIP address of this profile
    368      * @hide
    369      */
    370     public Address getSipAddress() {
    371         return mAddress;
    372     }
    373 
    374     /**
    375      * Gets the display name of the user.
    376      *
    377      * @return the display name of the user
    378      */
    379     public String getDisplayName() {
    380         return mAddress.getDisplayName();
    381     }
    382 
    383     /**
    384      * Gets the username.
    385      *
    386      * @return the username
    387      */
    388     public String getUserName() {
    389         return getUri().getUser();
    390     }
    391 
    392     /**
    393      * Gets the username for authentication. If it is null, then the username
    394      * should be used in authentication instead.
    395      *
    396      * @return the auth. username
    397      * @hide // TODO: remove when we make it public
    398      */
    399     public String getAuthUserName() {
    400         return mAuthUserName;
    401     }
    402 
    403     /**
    404      * Gets the password.
    405      *
    406      * @return the password
    407      */
    408     public String getPassword() {
    409         return mPassword;
    410     }
    411 
    412     /**
    413      * Gets the SIP domain.
    414      *
    415      * @return the SIP domain
    416      */
    417     public String getSipDomain() {
    418         return mDomain;
    419     }
    420 
    421     /**
    422      * Gets the port number of the SIP server.
    423      *
    424      * @return the port number of the SIP server
    425      */
    426     public int getPort() {
    427         return mPort;
    428     }
    429 
    430     /**
    431      * Gets the protocol used to connect to the server.
    432      *
    433      * @return the protocol
    434      */
    435     public String getProtocol() {
    436         return mProtocol;
    437     }
    438 
    439     /**
    440      * Gets the network address of the server outbound proxy.
    441      *
    442      * @return the network address of the server outbound proxy
    443      */
    444     public String getProxyAddress() {
    445         return mProxyAddress;
    446     }
    447 
    448     /**
    449      * Gets the (user-defined) name of the profile.
    450      *
    451      * @return name of the profile
    452      */
    453     public String getProfileName() {
    454         return mProfileName;
    455     }
    456 
    457     /**
    458      * Gets the flag of 'Sending keep-alive'.
    459      *
    460      * @return the flag of sending SIP keep-alive messages.
    461      */
    462     public boolean getSendKeepAlive() {
    463         return mSendKeepAlive;
    464     }
    465 
    466     /**
    467      * Gets the flag of 'Auto Registration'.
    468      *
    469      * @return the flag of registering the profile automatically.
    470      */
    471     public boolean getAutoRegistration() {
    472         return mAutoRegistration;
    473     }
    474 
    475     /**
    476      * Sets the calling process's Uid in the sip service.
    477      * @hide
    478      */
    479     public void setCallingUid(int uid) {
    480         mCallingUid = uid;
    481     }
    482 
    483     /**
    484      * Gets the calling process's Uid in the sip settings.
    485      * @hide
    486      */
    487     public int getCallingUid() {
    488         return mCallingUid;
    489     }
    490 
    491     private Object readResolve() throws ObjectStreamException {
    492         // For compatibility.
    493         if (mPort == 0) mPort = DEFAULT_PORT;
    494         return this;
    495     }
    496 }
    497