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.utils; 17 18 import static com.android.internal.net.ipsec.ike.IkeSessionStateMachine.CMD_RETRANSMIT; 19 20 import android.os.Handler; 21 22 import com.android.internal.net.ipsec.ike.message.IkeMessage; 23 24 /** 25 * Retransmitter represents a class that will send a message and trigger delayed retransmissions 26 * 27 * <p>The Retransmitter class will queue retransmission signals on the provided handler. The owner 28 * of this retransmitter instance is expected to wait for the signal, and call retransmit() on the 29 * instance of this class. 30 */ 31 public abstract class Retransmitter { 32 33 /** 34 * Retransmission allowed state. Initial state when created. 35 * 36 * <p>This state allows packet transmission. 37 */ 38 static final int STATE_RETRANSMISSION_ALLOWED = 1; 39 /** 40 * Retransmission suspended state. 41 * 42 * <p>This state does not allow packet transmission. 43 */ 44 static final int STATE_RETRANSMISSION_SUSPENDED = 2; 45 /** 46 * Retransmission finished state. 47 * 48 * <p>This state does not allow packet transmission. 49 */ 50 static final int STATE_RETRANSMISSION_FINISHED = 3; 51 52 private final Handler mHandler; 53 private final IkeMessage mRetransmitMsg; 54 private int mRetransmitCount = 0; 55 private int[] mRetransmissionTimeouts; 56 57 /** State of retransmitting. */ 58 private int mRetransmitterState; 59 Retransmitter(Handler handler, IkeMessage msg, int[] retransmissionTimeouts)60 public Retransmitter(Handler handler, IkeMessage msg, int[] retransmissionTimeouts) { 61 mHandler = handler; 62 mRetransmitMsg = msg; 63 mRetransmissionTimeouts = retransmissionTimeouts; 64 mRetransmitterState = STATE_RETRANSMISSION_ALLOWED; 65 } 66 67 /** 68 * Triggers a (re)transmission. Will enqueue a future retransmission signal on the given handler 69 * 70 * <p>This method will only transmit packets when the Retransmitter is in the 71 * STATE_RETRANSMISSION_ALLOWED state 72 */ retransmit()73 public void retransmit() { 74 if (mRetransmitMsg == null) { 75 return; 76 } 77 // Packets can be transferred only when retransmission is in allowed state. Any other state 78 // does not allow packet transfer. 79 if (mRetransmitterState != STATE_RETRANSMISSION_ALLOWED) { 80 return; 81 } 82 83 // If the failed iteration is beyond the max attempts, clean up and shut down. 84 if (mRetransmitCount >= mRetransmissionTimeouts.length) { 85 handleRetransmissionFailure(); 86 return; 87 } 88 89 send(); 90 91 long timeout = mRetransmissionTimeouts[mRetransmitCount++]; 92 mHandler.sendMessageDelayed(mHandler.obtainMessage(CMD_RETRANSMIT, this), timeout); 93 } 94 95 /** 96 * Finish retransmitting and cancels any future retransmissions. 97 * 98 * <p>This function is called when all packet transmissions have been completed and any future 99 * next retransmission is no longer needed. 100 */ stopRetransmitting()101 public void stopRetransmitting() { 102 mHandler.removeMessages(CMD_RETRANSMIT, this); 103 104 // Set as stopped 105 mRetransmitterState = STATE_RETRANSMISSION_FINISHED; 106 } 107 108 /** 109 * Suspends retransmitting. 110 * 111 * <p>Cancels any future retransmissions and sets the state to the Suspended. Retransmission can 112 * only be resumed using the {@link #restartRetransmitting()}. 113 */ suspendRetransmitting()114 public void suspendRetransmitting() { 115 // When retransmission is finished, it does not transition to the suspend state. 116 if (mRetransmitterState != STATE_RETRANSMISSION_ALLOWED) { 117 return; 118 } 119 120 // Remove future retransmissions. 121 mHandler.removeMessages(CMD_RETRANSMIT, this); 122 123 // Set as suspended 124 mRetransmitterState = STATE_RETRANSMISSION_SUSPENDED; 125 } 126 127 /** 128 * Restarts retransmitting. 129 * 130 * <p>Resumes a retransmission suspended by {@link #suspendRetransmitting} and retransmission 131 * starts again from the beginning by resetting retransmit count. 132 * 133 * <p>The state finished by {@link #stopRetransmitting()} will not be restarted again. 134 */ restartRetransmitting()135 public void restartRetransmitting() { 136 // When retransmission is finished, it does not transition to the allowed state. 137 if (mRetransmitterState != STATE_RETRANSMISSION_SUSPENDED) { 138 return; 139 } 140 141 // Set as resumed. 142 mRetransmitterState = STATE_RETRANSMISSION_ALLOWED; 143 144 // Reset retransmission count to 0. 145 mRetransmitCount = 0; 146 147 // Resume retransmitting. 148 retransmit(); 149 } 150 151 /** Retrieves the message this retransmitter is tracking */ getMessage()152 public IkeMessage getMessage() { 153 return mRetransmitMsg; 154 } 155 156 /** 157 * Implementation-provided sender 158 * 159 * <p>For Retransmitter-internal use only. 160 */ send()161 protected abstract void send(); 162 163 /** 164 * Callback for implementations to be informed that we have reached the max retransmissions. 165 * 166 * <p>For Retransmitter-internal use only. 167 */ handleRetransmissionFailure()168 protected abstract void handleRetransmissionFailure(); 169 } 170