• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2019 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 package com.android.internal.net.ipsec.ike;
17 
18 import static android.net.ipsec.ike.IkeManager.getIkeLog;
19 
20 import android.os.Looper;
21 import android.os.Message;
22 import android.util.SparseArray;
23 
24 import com.android.internal.annotations.VisibleForTesting;
25 import com.android.internal.util.State;
26 import com.android.internal.util.StateMachine;
27 
28 import java.util.concurrent.Executor;
29 import java.util.concurrent.TimeUnit;
30 
31 /**
32  * This class represents the common information of both IkeSessionStateMachine and
33  * ChildSessionStateMachine
34  */
35 abstract class AbstractSessionStateMachine extends StateMachine {
36     private static final int CMD_SHARED_BASE = 0;
37     protected static final int CMD_CATEGORY_SIZE = 100;
38 
39     /**
40      * Commands of Child local request that will be used in both IkeSessionStateMachine and
41      * ChildSessionStateMachine.
42      */
43     protected static final int CMD_CHILD_LOCAL_REQUEST_BASE = CMD_SHARED_BASE;
44 
45     @VisibleForTesting
46     static final int CMD_LOCAL_REQUEST_CREATE_CHILD = CMD_CHILD_LOCAL_REQUEST_BASE + 1;
47 
48     @VisibleForTesting
49     static final int CMD_LOCAL_REQUEST_DELETE_CHILD = CMD_CHILD_LOCAL_REQUEST_BASE + 2;
50 
51     @VisibleForTesting
52     static final int CMD_LOCAL_REQUEST_REKEY_CHILD = CMD_CHILD_LOCAL_REQUEST_BASE + 3;
53 
54     @VisibleForTesting
55     static final int CMD_LOCAL_REQUEST_REKEY_CHILD_MOBIKE = CMD_CHILD_LOCAL_REQUEST_BASE + 4;
56 
57     /** Timeout commands. */
58     protected static final int CMD_TIMEOUT_BASE = CMD_SHARED_BASE + CMD_CATEGORY_SIZE;
59     /** Timeout when the remote side fails to send a Rekey-Delete request. */
60     @VisibleForTesting static final int TIMEOUT_REKEY_REMOTE_DELETE = CMD_TIMEOUT_BASE + 1;
61 
62     /** Commands for testing only */
63     protected static final int CMD_TEST_BASE = CMD_SHARED_BASE + 2 * CMD_CATEGORY_SIZE;
64     /** Force state machine to a target state for testing purposes. */
65     @VisibleForTesting static final int CMD_FORCE_TRANSITION = CMD_TEST_BASE + 1;
66 
67     /** Private commands for subclasses */
68     protected static final int CMD_PRIVATE_BASE = CMD_SHARED_BASE + 3 * CMD_CATEGORY_SIZE;
69 
70     protected static final SparseArray<String> SHARED_CMD_TO_STR;
71 
72     static {
73         SHARED_CMD_TO_STR = new SparseArray<>();
SHARED_CMD_TO_STR.put(CMD_LOCAL_REQUEST_CREATE_CHILD, "Create Child")74         SHARED_CMD_TO_STR.put(CMD_LOCAL_REQUEST_CREATE_CHILD, "Create Child");
SHARED_CMD_TO_STR.put(CMD_LOCAL_REQUEST_DELETE_CHILD, "Delete Child")75         SHARED_CMD_TO_STR.put(CMD_LOCAL_REQUEST_DELETE_CHILD, "Delete Child");
SHARED_CMD_TO_STR.put(CMD_LOCAL_REQUEST_REKEY_CHILD, "Rekey Child")76         SHARED_CMD_TO_STR.put(CMD_LOCAL_REQUEST_REKEY_CHILD, "Rekey Child");
SHARED_CMD_TO_STR.put(CMD_LOCAL_REQUEST_REKEY_CHILD_MOBIKE, "Rekey Child (MOBIKE)")77         SHARED_CMD_TO_STR.put(CMD_LOCAL_REQUEST_REKEY_CHILD_MOBIKE, "Rekey Child (MOBIKE)");
SHARED_CMD_TO_STR.put(TIMEOUT_REKEY_REMOTE_DELETE, "Timout rekey remote delete")78         SHARED_CMD_TO_STR.put(TIMEOUT_REKEY_REMOTE_DELETE, "Timout rekey remote delete");
SHARED_CMD_TO_STR.put(CMD_FORCE_TRANSITION, "Force transition")79         SHARED_CMD_TO_STR.put(CMD_FORCE_TRANSITION, "Force transition");
80     }
81 
82     // Use a value greater than the retransmit-failure timeout.
83     static final long REKEY_DELETE_TIMEOUT_MS = TimeUnit.SECONDS.toMillis(180L);
84 
85     // Default delay time for retrying a request
86     static final long RETRY_INTERVAL_MS = TimeUnit.SECONDS.toMillis(15L);
87 
88     protected final Executor mUserCbExecutor;
89     private final String mLogTag;
90 
AbstractSessionStateMachine(String name, Looper looper, Executor userCbExecutor)91     protected AbstractSessionStateMachine(String name, Looper looper, Executor userCbExecutor) {
92         super(name, looper);
93         mLogTag = name;
94         mUserCbExecutor = userCbExecutor;
95     }
96 
97     /**
98      * Top level state for handling uncaught exceptions for all subclasses.
99      *
100      * <p>All other state in SessionStateMachine MUST extend this state.
101      *
102      * <p>Only errors this state should catch are unexpected internal failures. Since this may be
103      * run in critical processes, it must never take down the process if it fails
104      */
105     protected abstract class ExceptionHandlerBase extends State {
106         @Override
enter()107         public final void enter() {
108             try {
109                 enterState();
110             } catch (RuntimeException e) {
111                 cleanUpAndQuit(e);
112             }
113         }
114 
115         @Override
processMessage(Message message)116         public final boolean processMessage(Message message) {
117             try {
118                 String cmdName = SHARED_CMD_TO_STR.get(message.what);
119                 if (cmdName == null) {
120                     cmdName = getCmdString(message.what);
121                 }
122 
123                 // Unrecognized message will be logged by super class(Android StateMachine)
124                 if (cmdName != null) logd("processStateMessage: " + cmdName);
125 
126                 return processStateMessage(message);
127             } catch (RuntimeException e) {
128                 cleanUpAndQuit(e);
129                 return HANDLED;
130             }
131         }
132 
133         @Override
exit()134         public final void exit() {
135             try {
136                 exitState();
137             } catch (RuntimeException e) {
138                 cleanUpAndQuit(e);
139             }
140         }
141 
enterState()142         protected void enterState() {
143             // Do nothing. Subclasses MUST override it if they care.
144         }
145 
processStateMessage(Message message)146         protected boolean processStateMessage(Message message) {
147             return NOT_HANDLED;
148         }
149 
exitState()150         protected void exitState() {
151             // Do nothing. Subclasses MUST override it if they care.
152         }
153 
cleanUpAndQuit(RuntimeException e)154         protected abstract void cleanUpAndQuit(RuntimeException e);
155 
getCmdString(int cmd)156         protected abstract String getCmdString(int cmd);
157     }
158 
executeUserCallback(Runnable r)159     protected void executeUserCallback(Runnable r) {
160         try {
161             mUserCbExecutor.execute(r);
162         } catch (Exception e) {
163             logd("Callback execution failed", e);
164         }
165     }
166 
167     @Override
log(String s)168     protected void log(String s) {
169         getIkeLog().d(mLogTag, s);
170     }
171 
172     @Override
logd(String s)173     protected void logd(String s) {
174         getIkeLog().d(mLogTag, s);
175     }
176 
logd(String s, Throwable e)177     protected void logd(String s, Throwable e) {
178         getIkeLog().d(mLogTag, s, e);
179     }
180 
181     @Override
logv(String s)182     protected void logv(String s) {
183         getIkeLog().v(mLogTag, s);
184     }
185 
186     @Override
logi(String s)187     protected void logi(String s) {
188         getIkeLog().i(mLogTag, s);
189     }
190 
logi(String s, Throwable cause)191     protected void logi(String s, Throwable cause) {
192         getIkeLog().i(mLogTag, s, cause);
193     }
194 
195     @Override
logw(String s)196     protected void logw(String s) {
197         getIkeLog().w(mLogTag, s);
198     }
199 
200     @Override
loge(String s)201     protected void loge(String s) {
202         getIkeLog().e(mLogTag, s);
203     }
204 
205     @Override
loge(String s, Throwable e)206     protected void loge(String s, Throwable e) {
207         getIkeLog().e(mLogTag, s, e);
208     }
209 
logWtf(String s)210     protected void logWtf(String s) {
211         getIkeLog().wtf(mLogTag, s);
212     }
213 
logWtf(String s, Throwable e)214     protected void logWtf(String s, Throwable e) {
215         getIkeLog().wtf(mLogTag, s, e);
216     }
217 }
218