1 /*
2  * Copyright (C) 2018 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 com.android.server.wifi.hotspot2.soap;
18 
19 import android.annotation.NonNull;
20 import android.text.TextUtils;
21 
22 import org.ksoap2.serialization.AttributeInfo;
23 import org.ksoap2.serialization.SoapObject;
24 
25 import java.util.Collections;
26 import java.util.HashMap;
27 import java.util.Map;
28 import java.util.Objects;
29 
30 /**
31  * Base SOAP SPP (Subscription Provisioning Protocol) response message sent by server
32  */
33 public class SppResponseMessage {
34     static final String SPPVersionAttribute = "sppVersion";
35     static final String SPPStatusAttribute = "sppStatus";
36     static final String SPPSessionIDAttribute = "sessionID";
37     static final String SPPErrorCodeAttribute = "errorCode";
38     static final String SPPErrorProperty = "sppError";
39 
40     private final int mMessageType;
41     private final String mVersion;
42     private final String mSessionID;
43     private int mStatus;
44     private int mError = SppConstants.INVALID_SPP_CONSTANT;
45     private Map<String, String> mAttributes;
46 
47     /**
48      * Message types of SOAP SPP response.
49      */
50     public static class MessageType {
51         /* SOAP method response from the subscription server */
52         public static final int POST_DEV_DATA_RESPONSE = 0;
53 
54         /* Message exchange sequence has been completed and the TLS connection should be released */
55         public static final int EXCHANGE_COMPLETE = 1;
56     }
57 
SppResponseMessage(@onNull SoapObject response, int messageType)58     protected SppResponseMessage(@NonNull SoapObject response, int messageType)
59             throws IllegalArgumentException {
60         if (!response.hasAttribute(SPPStatusAttribute)) {
61             throw new IllegalArgumentException("Missing status");
62         }
63 
64         mMessageType = messageType;
65         mStatus = SppConstants.mapStatusStringToInt(
66                 response.getAttributeAsString(SPPStatusAttribute));
67         if (!response.hasAttribute(SPPVersionAttribute) || !response.hasAttribute(
68                 SPPSessionIDAttribute) || mStatus == SppConstants.INVALID_SPP_CONSTANT) {
69             throw new IllegalArgumentException("Incomplete request: " + messageType);
70         }
71 
72         // Validation check for error status
73         if (mStatus == SppConstants.SppStatus.ERROR) {
74             if (!response.hasProperty(SPPErrorProperty)) {
75                 throw new IllegalArgumentException("Missing sppError");
76             }
77         }
78 
79         if (response.hasProperty(SPPErrorProperty)) {
80             SoapObject errorInfo = (SoapObject) response.getProperty(SPPErrorProperty);
81             if (!errorInfo.hasAttribute(SPPErrorCodeAttribute)) {
82                 throw new IllegalArgumentException("Missing errorCode");
83             }
84             mError = SppConstants.mapErrorStringToInt(
85                     errorInfo.getAttributeAsString(SPPErrorCodeAttribute));
86         }
87 
88         mSessionID = response.getAttributeAsString(SPPSessionIDAttribute);
89         mVersion = response.getAttributeAsString(SPPVersionAttribute);
90         if (response.getAttributeCount() > 0) {
91             mAttributes = new HashMap<>();
92             for (int i = 0; i < response.getAttributeCount(); i++) {
93                 AttributeInfo attributeInfo = new AttributeInfo();
94                 response.getAttributeInfo(i, attributeInfo);
95                 mAttributes.put(attributeInfo.getName(),
96                         response.getAttributeAsString(attributeInfo.getName()));
97 
98             }
99         }
100     }
101 
getMessageType()102     public int getMessageType() {
103         return mMessageType;
104     }
105 
getVersion()106     public String getVersion() {
107         return mVersion;
108     }
109 
getSessionID()110     public String getSessionID() {
111         return mSessionID;
112     }
113 
getStatus()114     public int getStatus() {
115         return mStatus;
116     }
117 
getError()118     public int getError() {
119         return mError;
120     }
121 
getAttributes()122     protected final Map<String, String> getAttributes() {
123         return Collections.unmodifiableMap(mAttributes);
124     }
125 
126     @Override
hashCode()127     public int hashCode() {
128         return Objects.hash(mMessageType, mVersion, mSessionID, mStatus, mError, mAttributes);
129     }
130 
131     @Override
equals(Object thatObject)132     public boolean equals(Object thatObject) {
133         if (this == thatObject) return true;
134         if (!(thatObject instanceof SppResponseMessage)) return false;
135         SppResponseMessage that = (SppResponseMessage) thatObject;
136         return mMessageType == that.mMessageType
137                 && mStatus == that.mStatus
138                 && mError == that.mError
139                 && TextUtils.equals(mVersion, that.mVersion)
140                 && TextUtils.equals(mSessionID, that.mSessionID)
141                 && ((mAttributes == null) ? (that.mAttributes == null) : mAttributes.equals(
142                 that.mAttributes));
143     }
144 
145     @Override
toString()146     public String toString() {
147         StringBuilder sb = new StringBuilder(mMessageType);
148         sb.append(", version ").append(mVersion);
149         sb.append(", status ").append(mStatus);
150         sb.append(", session-id ").append(mSessionID);
151         if (mError != SppConstants.INVALID_SPP_CONSTANT) {
152             sb.append(", error ").append(mError);
153         }
154         return sb.toString();
155     }
156 }
157 
158