blob: db0ae033713e3415d088a432c0d6646ac23b7565 [file] [log] [blame]
/*
* Copyright (C) 2021 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.telephony.ims;
import android.annotation.IntDef;
import android.annotation.IntRange;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.SystemApi;
import android.net.InetAddresses;
import android.net.Uri;
import android.os.Parcel;
import android.os.Parcelable;
import android.telephony.ims.stub.SipDelegate;
import android.util.Log;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.net.UnknownHostException;
import java.util.Objects;
/**
* The IMS registration and other attributes that the {@link SipDelegateConnection} used by the
* IMS application will need to be aware of to correctly generate outgoing {@link SipMessage}s.
* <p>
* The IMS service must generate new instances of this configuration as the IMS configuration
* managed by the IMS service changes. Along with each {@link SipDelegateConfiguration} instance
* containing the configuration is the "version", which should be incremented every time a new
* {@link SipDelegateConfiguration} instance is created. The {@link SipDelegateConnection} will
* include the version of the {@link SipDelegateConfiguration} instance that it used in order for
* the {@link SipDelegate} to easily identify if the IMS application used a now stale configuration
* to generate the {@link SipMessage} and return
* {@link SipDelegateManager#MESSAGE_FAILURE_REASON_STALE_IMS_CONFIGURATION} in
* {@link DelegateMessageCallback#onMessageSendFailure(String, int)} so that the IMS application can
* regenerate that {@link SipMessage} using the correct {@link SipDelegateConfiguration}
* instance.
* <p>
* Every time the IMS configuration state changes in the IMS service, a full configuration should
* be generated. The new {@link SipDelegateConfiguration} instance should not be an incremental
* update.
* @see Builder
* @hide
*/
@SystemApi
public final class SipDelegateConfiguration implements Parcelable {
/**
* The SIP transport uses UDP.
*/
public static final int SIP_TRANSPORT_UDP = 0;
/**
* The SIP transport uses TCP.
*/
public static final int SIP_TRANSPORT_TCP = 1;
/**@hide*/
@IntDef(prefix = "SIP_TRANSPORT_", value = {
SIP_TRANSPORT_UDP,
SIP_TRANSPORT_TCP
})
@Retention(RetentionPolicy.SOURCE)
public @interface TransportType {}
/**
* The value returned by {@link #getMaxUdpPayloadSizeBytes()} when it is not defined.
*/
public static final int UDP_PAYLOAD_SIZE_UNDEFINED = -1;
/**
* SIP over IPSec configuration
*/
public static final class IpSecConfiguration {
private final int mLocalTxPort;
private final int mLocalRxPort;
private final int mLastLocalTxPort;
private final int mRemoteTxPort;
private final int mRemoteRxPort;
private final int mLastRemoteTxPort;
private final String mSecurityHeader;
/**
* Describes the SIP over IPSec configuration the SipDelegate will need to use.
*
* @param localTxPort Local SIP port number used to send traffic.
* @param localRxPort Local SIP port number used to receive traffic.
* @param lastLocalTxPort Local SIP port number used for the previous IPsec security
* association.
* @param remoteTxPort Remote port number used by the SIP server to send SIP traffic.
* @param remoteRxPort Remote port number used by the SIP server to receive incoming SIP
* traffic.
* @param lastRemoteTxPort Remote port number used by the SIP server to send SIP traffic on
* the previous IPSec security association.
* @param securityHeader The value of the SIP security verify header.
*/
public IpSecConfiguration(int localTxPort, int localRxPort, int lastLocalTxPort,
int remoteTxPort, int remoteRxPort, int lastRemoteTxPort,
@NonNull String securityHeader) {
mLocalTxPort = localTxPort;
mLocalRxPort = localRxPort;
mLastLocalTxPort = lastLocalTxPort;
mRemoteTxPort = remoteTxPort;
mRemoteRxPort = remoteRxPort;
mLastRemoteTxPort = lastRemoteTxPort;
mSecurityHeader = securityHeader;
}
/**
* @return The local SIP port number used to send traffic.
*/
public int getLocalTxPort() {
return mLocalTxPort;
}
/**
* @return The Local SIP port number used to receive traffic.
*/
public int getLocalRxPort() {
return mLocalRxPort;
}
/**
* @return The last local SIP port number used for the previous IPsec security association.
*/
public int getLastLocalTxPort() {
return mLastLocalTxPort;
}
/**
* @return The remote port number used by the SIP server to send SIP traffic.
*/
public int getRemoteTxPort() {
return mRemoteTxPort;
}
/**
* @return the remote port number used by the SIP server to receive incoming SIP traffic.
*/
public int getRemoteRxPort() {
return mRemoteRxPort;
}
/**
* @return the remote port number used by the SIP server to send SIP traffic on the previous
* IPSec security association.
*/
public int getLastRemoteTxPort() {
return mLastRemoteTxPort;
}
/**
* @return The value of the SIP security verify header.
*/
public @NonNull String getSipSecurityVerifyHeader() {
return mSecurityHeader;
}
/**
* Helper for parcelling this object.
* @hide
*/
public void addToParcel(Parcel dest) {
dest.writeInt(mLocalTxPort);
dest.writeInt(mLocalRxPort);
dest.writeInt(mLastLocalTxPort);
dest.writeInt(mRemoteTxPort);
dest.writeInt(mRemoteRxPort);
dest.writeInt(mLastRemoteTxPort);
dest.writeString(mSecurityHeader);
}
/**
* Helper for unparcelling this object.
* @hide
*/
public static IpSecConfiguration fromParcel(Parcel source) {
return new IpSecConfiguration(source.readInt(), source.readInt(), source.readInt(),
source.readInt(), source.readInt(), source.readInt(), source.readString());
}
@Override
public String toString() {
return "IpSecConfiguration{" + "localTx=" + mLocalTxPort + ", localRx=" + mLocalRxPort
+ ", lastLocalTx=" + mLastLocalTxPort + ", remoteTx=" + mRemoteTxPort
+ ", remoteRx=" + mRemoteRxPort + ", lastRemoteTx=" + mLastRemoteTxPort
+ ", securityHeader=" + mSecurityHeader + '}';
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
IpSecConfiguration that = (IpSecConfiguration) o;
return mLocalTxPort == that.mLocalTxPort
&& mLocalRxPort == that.mLocalRxPort
&& mLastLocalTxPort == that.mLastLocalTxPort
&& mRemoteTxPort == that.mRemoteTxPort
&& mRemoteRxPort == that.mRemoteRxPort
&& mLastRemoteTxPort == that.mLastRemoteTxPort
&& Objects.equals(mSecurityHeader, that.mSecurityHeader);
}
@Override
public int hashCode() {
return Objects.hash(mLocalTxPort, mLocalRxPort, mLastLocalTxPort, mRemoteTxPort,
mRemoteRxPort, mLastRemoteTxPort, mSecurityHeader);
}
}
/**
* Creates a new instance of {@link SipDelegateConfiguration} composed from optional
* configuration items.
*/
public static final class Builder {
private final SipDelegateConfiguration mConfig;
/**
*
* @param version The version associated with the {@link SipDelegateConfiguration} instance
* being built. See {@link #getVersion()} for more information.
* @param transportType The transport type to use for SIP signalling.
* @param localAddr The local socket address used for SIP traffic.
* @param serverAddr The SIP server or P-CSCF default IP address for sip traffic.
* @see InetAddresses#parseNumericAddress(String) for how to create an
* {@link InetAddress} without requiring a DNS lookup.
*/
public Builder(@IntRange(from = 0) long version, @TransportType int transportType,
@NonNull InetSocketAddress localAddr, @NonNull InetSocketAddress serverAddr) {
mConfig = new SipDelegateConfiguration(version, transportType, localAddr,
serverAddr);
}
/**
* Create a new {@link SipDelegateConfiguration} instance with the same exact configuration
* as the passed in instance, except for the version parameter, which will be incremented
* by 1.
* <p>
* This method is useful for cases where only a small subset of configurations have changed
* and the new configuration is based off of the old configuration.
* @param c The older {@link SipDelegateConfiguration} instance to base this instance's
* configuration off of.
*/
public Builder(@NonNull SipDelegateConfiguration c) {
mConfig = c.copyAndIncrementVersion();
}
/**
* Sets whether or not SIP compact form is enabled for the associated SIP delegate.
* <p>
* If unset, this configuration defaults to {@code false}.
* @param isEnabled {@code true} if SIP compact form is enabled for the associated SIP
* Delegate, {@code false} if it is not.
* @return this Builder instance with the compact form configuration set.
*/
public @NonNull Builder setSipCompactFormEnabled(boolean isEnabled) {
mConfig.mIsSipCompactFormEnabled = isEnabled;
return this;
}
/**
* Sets whether or not underlying SIP keepalives are enabled for the associated SIP
* delegate.
* <p>
* If unset, this configuration defaults to {@code false}.
* @param isEnabled {@code true} if SIP keepalives are enabled for the associated SIP
* Delegate, {@code false} if it is not.
* @return this Builder instance with the new configuration set.
*/
public @NonNull Builder setSipKeepaliveEnabled(boolean isEnabled) {
mConfig.mIsSipKeepaliveEnabled = isEnabled;
return this;
}
/**
* Sets the max SIP payload size in bytes to be sent on UDP. If the SIP message payload is
* greater than the max UDP payload size, then TCP must be used.
* <p>
* If unset, this configuration defaults to {@link #UDP_PAYLOAD_SIZE_UNDEFINED}, or no
* size specified.
* @param size The maximum SIP payload size in bytes for UDP.
* @return this Builder instance with the new configuration set.
*/
public @NonNull Builder setMaxUdpPayloadSizeBytes(@IntRange(from = 1) int size) {
mConfig.mMaxUdpPayloadSize = size;
return this;
}
/**
* Sets the IMS public user identifier.
* <p>
* If unset, this configuration defaults to {@code null}, or no identifier specified.
* @param id The IMS public user identifier.
* @return this Builder instance with the new configuration set.
*/
public @NonNull Builder setPublicUserIdentifier(@Nullable String id) {
mConfig.mPublicUserIdentifier = id;
return this;
}
/**
* Sets the IMS private user identifier.
* <p>
* If unset, this configuration defaults to {@code null}, or no identifier specified.
* @param id The IMS private user identifier.
* @return this Builder instance with the new configuration set.
*/
public @NonNull Builder setPrivateUserIdentifier(@Nullable String id) {
mConfig.mPrivateUserIdentifier = id;
return this;
}
/**
* Sets the IMS home domain.
* <p>
* If unset, this configuration defaults to {@code null}, or no domain specified.
* @param domain The IMS home domain.
* @return this Builder instance with the new configuration set.
*/
public @NonNull Builder setHomeDomain(@Nullable String domain) {
mConfig.mHomeDomain = domain;
return this;
}
/**
* Sets the IMEI of the associated device.
* <p>
* Application can include the Instance-ID feature tag {@code "+sip.instance"} in the
* Contact header with a value of the device IMEI in the form
* {@code "urn:gsma:imei:<device IMEI>"}.
* <p>
* If unset, this configuration defaults to {@code null}, or no IMEI string specified.
* @param imei The IMEI of the device.
* @return this Builder instance with the new configuration set.
*/
public @NonNull Builder setImei(@Nullable String imei) {
mConfig.mImei = imei;
return this;
}
/**
* Set the optional {@link IpSecConfiguration} instance used if the associated SipDelegate
* is communicating over IPSec.
* <p>
* If unset, this configuration defaults to {@code null}
* @param c The IpSecConfiguration instance to set.
* @return this Builder instance with IPSec configuration set.
*/
public @NonNull Builder setIpSecConfiguration(@Nullable IpSecConfiguration c) {
mConfig.mIpSecConfiguration = c;
return this;
}
/**
* Describes the Device's Public IP Address and port that is set when Network Address
* Translation is enabled and the device is behind a NAT.
* <p>
* If unset, this configuration defaults to {@code null}
* @param addr The {@link InetAddress} representing the device's public IP address and port
* when behind a NAT.
* @return this Builder instance with the new configuration set.
* @see InetAddresses#parseNumericAddress(String) For an example of how to create an
* instance of {@link InetAddress} without causing a DNS lookup.
*/
public @NonNull Builder setNatSocketAddress(@Nullable InetSocketAddress addr) {
mConfig.mNatAddress = addr;
return this;
}
/**
* Sets the optional URI of the device's Globally routable user-agent URI (GRUU) if this
* feature is enabled for the SIP delegate.
* <p>
* If unset, this configuration defaults to {@code null}
* @param uri The GRUU to set.
* @return this builder instance with the new configuration set.
*/
public @NonNull Builder setPublicGruuUri(@Nullable Uri uri) {
mConfig.mGruu = uri;
return this;
}
/**
* Sets the SIP authentication header value.
* <p>
* If unset, this configuration defaults to {@code null}.
* @param header The SIP authentication header's value.
* @return this builder instance with the new configuration set.
*/
public @NonNull Builder setSipAuthenticationHeader(@Nullable String header) {
mConfig.mSipAuthHeader = header;
return this;
}
/**
* Sets the SIP authentication nonce.
* <p>
* If unset, this configuration defaults to {@code null}.
* @param nonce The SIP authentication nonce.
* @return this builder instance with the new configuration set.
*/
public @NonNull Builder setSipAuthenticationNonce(@Nullable String nonce) {
mConfig.mSipAuthNonce = nonce;
return this;
}
/**
* Sets the SIP service route header value.
* <p>
* If unset, this configuration defaults to {@code null}.
* @param header The SIP service route header value.
* @return this builder instance with the new configuration set.
*/
public @NonNull Builder setSipServiceRouteHeader(@Nullable String header) {
mConfig.mServiceRouteHeader = header;
return this;
}
/**
* Sets the SIP path header value.
* <p>
* If unset, this configuration defaults to {@code null}.
* @param header The SIP path header value.
* @return this builder instance with the new configuration set.
*/
public @NonNull Builder setSipPathHeader(@Nullable String header) {
mConfig.mPathHeader = header;
return this;
}
/**
* Sets the SIP User-Agent header value.
* <p>
* If unset, this configuration defaults to {@code null}.
* @param header The SIP User-Agent header value.
* @return this builder instance with the new configuration set.
*/
public @NonNull Builder setSipUserAgentHeader(@Nullable String header) {
mConfig.mUserAgentHeader = header;
return this;
}
/**
* Sets the SIP Contact header's User parameter value.
* <p>
* If unset, this configuration defaults to {@code null}.
* @param param The SIP Contact header's User parameter value.
* @return this builder instance with the new configuration set.
*/
public @NonNull Builder setSipContactUserParameter(@Nullable String param) {
mConfig.mContactUserParam = param;
return this;
}
/**
* Sets the SIP P-Access-Network-Info (P-ANI) header value. Populated for networks that
* require this information to be provided as part of outgoing SIP messages.
* <p>
* If unset, this configuration defaults to {@code null}.
* @param header The SIP P-ANI header value.
* @return this builder instance with the new configuration set.
*/
public @NonNull Builder setSipPaniHeader(@Nullable String header) {
mConfig.mPaniHeader = header;
return this;
}
/**
* Sets the SIP P-Last-Access-Network-Info (P-LANI) header value. Populated for
* networks that require this information to be provided as part of outgoing SIP messages.
* <p>
* If unset, this configuration defaults to {@code null}.
* @param header The SIP P-LANI header value.
* @return this builder instance with the new configuration set.
*/
public @NonNull Builder setSipPlaniHeader(@Nullable String header) {
mConfig.mPlaniHeader = header;
return this;
}
/**
* Sets the SIP Cellular-Network-Info (CNI) header value (See 3GPP 24.229, section 7.2.15),
* populated for networks that require this information to be provided as part of outgoing
* SIP messages.
* <p>
* If unset, this configuration defaults to {@code null}.
* @param header The SIP P-LANI header value.
* @return this builder instance with the new configuration set.
*/
public @NonNull Builder setSipCniHeader(@Nullable String header) {
mConfig.mCniHeader = header;
return this;
}
/**
* Sets the SIP P-associated-uri header value.
* <p>
* If unset, this configuration defaults to {@code null}.
* @param header The SIP P-associated-uri header value.
* @return this builder instance with the new configuration set.
*/
public @NonNull Builder setSipAssociatedUriHeader(@Nullable String header) {
mConfig.mAssociatedUriHeader = header;
return this;
}
/**
* @return A {@link SipDelegateConfiguration} instance with the optional configurations set.
*/
public @NonNull SipDelegateConfiguration build() {
return mConfig;
}
}
private final long mVersion;
private final int mTransportType;
private final InetSocketAddress mLocalAddress;
private final InetSocketAddress mSipServerAddress;
private boolean mIsSipCompactFormEnabled = false;
private boolean mIsSipKeepaliveEnabled = false;
private int mMaxUdpPayloadSize = -1;
private String mPublicUserIdentifier = null;
private String mPrivateUserIdentifier = null;
private String mHomeDomain = null;
private String mImei = null;
private Uri mGruu = null;
private String mSipAuthHeader = null;
private String mSipAuthNonce = null;
private String mServiceRouteHeader = null;
private String mPathHeader = null;
private String mUserAgentHeader = null;
private String mContactUserParam = null;
private String mPaniHeader = null;
private String mPlaniHeader = null;
private String mCniHeader = null;
private String mAssociatedUriHeader = null;
private IpSecConfiguration mIpSecConfiguration = null;
private InetSocketAddress mNatAddress = null;
private SipDelegateConfiguration(long version, int transportType,
InetSocketAddress localAddress, InetSocketAddress sipServerAddress) {
mVersion = version;
mTransportType = transportType;
mLocalAddress = localAddress;
mSipServerAddress = sipServerAddress;
}
private SipDelegateConfiguration(Parcel source) {
mVersion = source.readLong();
mTransportType = source.readInt();
mLocalAddress = readAddressFromParcel(source);
mSipServerAddress = readAddressFromParcel(source);
mIsSipCompactFormEnabled = source.readBoolean();
mIsSipKeepaliveEnabled = source.readBoolean();
mMaxUdpPayloadSize = source.readInt();
mPublicUserIdentifier = source.readString();
mPrivateUserIdentifier = source.readString();
mHomeDomain = source.readString();
mImei = source.readString();
mGruu = source.readParcelable(null, android.net.Uri.class);
mSipAuthHeader = source.readString();
mSipAuthNonce = source.readString();
mServiceRouteHeader = source.readString();
mPathHeader = source.readString();
mUserAgentHeader = source.readString();
mContactUserParam = source.readString();
mPaniHeader = source.readString();
mPlaniHeader = source.readString();
mCniHeader = source.readString();
mAssociatedUriHeader = source.readString();
boolean isIpsecConfigAvailable = source.readBoolean();
if (isIpsecConfigAvailable) {
mIpSecConfiguration = IpSecConfiguration.fromParcel(source);
}
boolean isNatConfigAvailable = source.readBoolean();
if (isNatConfigAvailable) {
mNatAddress = readAddressFromParcel(source);
}
}
@Override
public void writeToParcel(@NonNull Parcel dest, int flags) {
dest.writeLong(mVersion);
dest.writeInt(mTransportType);
writeAddressToParcel(mLocalAddress, dest);
writeAddressToParcel(mSipServerAddress, dest);
dest.writeBoolean(mIsSipCompactFormEnabled);
dest.writeBoolean(mIsSipKeepaliveEnabled);
dest.writeInt(mMaxUdpPayloadSize);
dest.writeString(mPublicUserIdentifier);
dest.writeString(mPrivateUserIdentifier);
dest.writeString(mHomeDomain);
dest.writeString(mImei);
dest.writeParcelable(mGruu, flags);
dest.writeString(mSipAuthHeader);
dest.writeString(mSipAuthNonce);
dest.writeString(mServiceRouteHeader);
dest.writeString(mPathHeader);
dest.writeString(mUserAgentHeader);
dest.writeString(mContactUserParam);
dest.writeString(mPaniHeader);
dest.writeString(mPlaniHeader);
dest.writeString(mCniHeader);
dest.writeString(mAssociatedUriHeader);
dest.writeBoolean(mIpSecConfiguration != null);
if (mIpSecConfiguration != null) {
mIpSecConfiguration.addToParcel(dest);
}
dest.writeBoolean(mNatAddress != null);
if (mNatAddress != null) {
writeAddressToParcel(mNatAddress, dest);
}
}
/**
* @return A copy of this instance with an incremented version.
* @hide
*/
public SipDelegateConfiguration copyAndIncrementVersion() {
SipDelegateConfiguration c = new SipDelegateConfiguration(getVersion() + 1, mTransportType,
mLocalAddress, mSipServerAddress);
c.mIsSipCompactFormEnabled = mIsSipCompactFormEnabled;
c.mIsSipKeepaliveEnabled = mIsSipKeepaliveEnabled;
c.mMaxUdpPayloadSize = mMaxUdpPayloadSize;
c.mIpSecConfiguration = mIpSecConfiguration;
c.mNatAddress = mNatAddress;
c.mPublicUserIdentifier = mPublicUserIdentifier;
c.mPrivateUserIdentifier = mPrivateUserIdentifier;
c.mHomeDomain = mHomeDomain;
c.mImei = mImei;
c.mGruu = mGruu;
c.mSipAuthHeader = mSipAuthHeader;
c.mSipAuthNonce = mSipAuthNonce;
c.mServiceRouteHeader = mServiceRouteHeader;
c.mPathHeader = mPathHeader;
c.mUserAgentHeader = mUserAgentHeader;
c.mContactUserParam = mContactUserParam;
c.mPaniHeader = mPaniHeader;
c.mPlaniHeader = mPlaniHeader;
c.mCniHeader = mCniHeader;
c.mAssociatedUriHeader = mAssociatedUriHeader;
return c;
}
/**
* An integer representing the version number of this SipDelegateImsConfiguration.
* {@link SipMessage}s that are created using this configuration will also have a this
* version number associated with them, which will allow the IMS service to validate that the
* {@link SipMessage} was using the latest configuration during creation and not a stale
* configuration due to race conditions between the configuration being updated and the RCS
* application not receiving the updated configuration before generating a new message.
* <p>
* The version number should be a positive number that starts at 0 and increments sequentially
* as new {@link SipDelegateConfiguration} instances are created to update the IMS
* configuration state.
*
* @return the version number associated with this {@link SipDelegateConfiguration}.
*/
public @IntRange(from = 0) long getVersion() {
return mVersion;
}
/**
* @return The Transport type of the SIP delegate.
*/
public @TransportType int getTransportType() {
return mTransportType;
}
/**
* @return The local IP address and port used for SIP traffic.
*/
public @NonNull InetSocketAddress getLocalAddress() {
return mLocalAddress;
}
/**
* @return The default IP Address and port of the SIP server or P-CSCF used for SIP traffic.
*/
public @NonNull InetSocketAddress getSipServerAddress() {
return mSipServerAddress;
}
/**
* @return {@code true} if SIP compact form is enabled for the associated SIP Delegate,
* {@code false} if it is not.
*/
public boolean isSipCompactFormEnabled() {
return mIsSipCompactFormEnabled;
}
/**
* @return {@code true} if SIP keepalives are enabled for the associated SIP Delegate,
* {@code false} if it is not.
*/
public boolean isSipKeepaliveEnabled() {
return mIsSipKeepaliveEnabled;
}
/**
* @return The maximum SIP payload size in bytes for UDP or {code -1} if no value was set.
*/
public int getMaxUdpPayloadSizeBytes() {
return mMaxUdpPayloadSize;
}
/**
* @return The IMS public user identifier or {@code null} if it was not set.
*/
public @Nullable String getPublicUserIdentifier() {
return mPublicUserIdentifier;
}
/**
* @return The IMS private user identifier or {@code null} if it was not set.
*/
public @Nullable String getPrivateUserIdentifier() {
return mPrivateUserIdentifier;
}
/**
* @return The IMS home domain or {@code null} if it was not set.
*/
public @Nullable String getHomeDomain() {
return mHomeDomain;
}
/**
* get the IMEI of the associated device.
* <p>
* Application can include the Instance-ID feature tag {@code "+sip.instance"} in the Contact
* header with a value of the device IMEI in the form {@code "urn:gsma:imei:<device IMEI>"}.
* @return The IMEI of the device or {@code null} if it was not set.
*/
public @Nullable String getImei() {
return mImei;
}
/**
* @return The IPSec configuration that must be used because SIP is communicating over IPSec.
* This returns {@code null} SIP is not communicating over IPSec.
*/
public @Nullable IpSecConfiguration getIpSecConfiguration() {
return mIpSecConfiguration;
}
/**
* @return The public IP address and port of the device due to it being behind a NAT.
* This returns {@code null} if the device is not behind a NAT.
*/
public @Nullable InetSocketAddress getNatSocketAddress() {
return mNatAddress;
}
/**
* @return The device's Globally routable user-agent URI (GRUU) or {@code null} if this feature
* is not enabled for the SIP delegate.
*/
public @Nullable Uri getPublicGruuUri() {
return mGruu;
}
/**
* @return The value of the SIP authentication header or {@code null} if there is none set.
*/
public @Nullable String getSipAuthenticationHeader() {
return mSipAuthHeader;
}
/**
* @return The value of the SIP authentication nonce or {@code null} if there is none set.
*/
public @Nullable String getSipAuthenticationNonce() {
return mSipAuthNonce;
}
/**
* @return The value of the SIP service route header or {@code null} if there is none set.
*/
public @Nullable String getSipServiceRouteHeader() {
return mServiceRouteHeader;
}
/**
* @return The value of the SIP path header or {@code null} if there is none set.
*/
public @Nullable String getSipPathHeader() {
return mPathHeader;
}
/**
* @return The value of the SIP User-Agent header or {@code null} if there is none set.
*/
public @Nullable String getSipUserAgentHeader() {
return mUserAgentHeader;
}
/**
* @return The value of the SIP Contact header's User parameter or {@code null} if there is
* none set.
*/
public @Nullable String getSipContactUserParameter() {
return mContactUserParam;
}
/**
* @return The value of the SIP P-Access-Network-Info (P-ANI) header or {@code null} if there is
* none set.
*/
public @Nullable String getSipPaniHeader() {
return mPaniHeader;
}
/**
* @return The value of the SIP P-Last-Access-Network-Info (P-LANI) header or {@code null} if
* there is none set.
*/
public @Nullable String getSipPlaniHeader() {
return mPlaniHeader;
}
/**
* @return The value of the SIP Cellular-Network-Info (CNI) header or {@code null} if there is
* none set.
*/
public @Nullable String getSipCniHeader() {
return mCniHeader;
}
/**
* @return The value of the SIP P-associated-uri header or {@code null} if there is none set.
*/
public @Nullable String getSipAssociatedUriHeader() {
return mAssociatedUriHeader;
}
private void writeAddressToParcel(InetSocketAddress addr, Parcel dest) {
dest.writeByteArray(addr.getAddress().getAddress());
dest.writeInt(addr.getPort());
}
private InetSocketAddress readAddressFromParcel(Parcel source) {
final byte[] addressBytes = source.createByteArray();
final int port = source.readInt();
try {
return new InetSocketAddress(InetAddress.getByAddress(addressBytes), port);
} catch (UnknownHostException e) {
// Should not happen, as length of array was verified before parcelling.
Log.e("SipDelegateConfiguration", "exception reading address, returning null");
return null;
}
}
@Override
public int describeContents() {
return 0;
}
public static final @NonNull Creator<SipDelegateConfiguration> CREATOR =
new Creator<SipDelegateConfiguration>() {
@Override
public SipDelegateConfiguration createFromParcel(Parcel source) {
return new SipDelegateConfiguration(source);
}
@Override
public SipDelegateConfiguration[] newArray(int size) {
return new SipDelegateConfiguration[size];
}
};
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
SipDelegateConfiguration that = (SipDelegateConfiguration) o;
return mVersion == that.mVersion
&& mTransportType == that.mTransportType
&& mIsSipCompactFormEnabled == that.mIsSipCompactFormEnabled
&& mIsSipKeepaliveEnabled == that.mIsSipKeepaliveEnabled
&& mMaxUdpPayloadSize == that.mMaxUdpPayloadSize
&& Objects.equals(mLocalAddress, that.mLocalAddress)
&& Objects.equals(mSipServerAddress, that.mSipServerAddress)
&& Objects.equals(mPublicUserIdentifier, that.mPublicUserIdentifier)
&& Objects.equals(mPrivateUserIdentifier, that.mPrivateUserIdentifier)
&& Objects.equals(mHomeDomain, that.mHomeDomain)
&& Objects.equals(mImei, that.mImei)
&& Objects.equals(mGruu, that.mGruu)
&& Objects.equals(mSipAuthHeader, that.mSipAuthHeader)
&& Objects.equals(mSipAuthNonce, that.mSipAuthNonce)
&& Objects.equals(mServiceRouteHeader, that.mServiceRouteHeader)
&& Objects.equals(mPathHeader, that.mPathHeader)
&& Objects.equals(mUserAgentHeader, that.mUserAgentHeader)
&& Objects.equals(mContactUserParam, that.mContactUserParam)
&& Objects.equals(mPaniHeader, that.mPaniHeader)
&& Objects.equals(mPlaniHeader, that.mPlaniHeader)
&& Objects.equals(mCniHeader, that.mCniHeader)
&& Objects.equals(mAssociatedUriHeader, that.mAssociatedUriHeader)
&& Objects.equals(mIpSecConfiguration, that.mIpSecConfiguration)
&& Objects.equals(mNatAddress, that.mNatAddress);
}
@Override
public int hashCode() {
return Objects.hash(mVersion, mTransportType, mLocalAddress, mSipServerAddress,
mIsSipCompactFormEnabled, mIsSipKeepaliveEnabled, mMaxUdpPayloadSize,
mPublicUserIdentifier, mPrivateUserIdentifier, mHomeDomain, mImei, mGruu,
mSipAuthHeader, mSipAuthNonce, mServiceRouteHeader, mPathHeader, mUserAgentHeader,
mContactUserParam, mPaniHeader, mPlaniHeader, mCniHeader, mAssociatedUriHeader,
mIpSecConfiguration, mNatAddress);
}
@Override
public String toString() {
return "SipDelegateConfiguration{ mVersion=" + mVersion + ", mTransportType="
+ mTransportType + '}';
}
}