blob: e86df232d95269ae88ff437a98f4c32593074574 [file] [log] [blame]
/*
* Copyright (C) 2019 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 com.android.internal.net.ipsec.ike;
import static com.android.internal.net.ipsec.ike.AbstractSessionStateMachine.CMD_LOCAL_REQUEST_CREATE_CHILD;
import static com.android.internal.net.ipsec.ike.AbstractSessionStateMachine.CMD_LOCAL_REQUEST_REKEY_CHILD;
import static com.android.internal.net.ipsec.ike.IkeSessionStateMachine.CMD_LOCAL_REQUEST_CREATE_IKE;
import static com.android.internal.net.ipsec.ike.IkeSessionStateMachine.CMD_LOCAL_REQUEST_DPD;
import android.net.ipsec.ike.ChildSessionCallback;
import android.net.ipsec.ike.ChildSessionParams;
import java.util.LinkedList;
/**
* IkeLocalRequestScheduler caches all local requests scheduled by an IKE Session and notify the IKE
* Session to process the request when it is allowed.
*
* <p>LocalRequestScheduler is running on the IkeSessionStateMachine thread.
*/
public final class IkeLocalRequestScheduler {
public static int SPI_NOT_INCLUDED = 0;
private final LinkedList<LocalRequest> mRequestQueue = new LinkedList<>();
private final IProcedureConsumer mConsumer;
private boolean mLocalProcedureOngoing;
private boolean mRemoteProcedureOngoing;
/**
* Construct an instance of IkeLocalRequestScheduler
*
* @param consumer the interface to initiate new procedure.
*/
public IkeLocalRequestScheduler(IProcedureConsumer consumer) {
mConsumer = consumer;
}
/** Add a new local request to the queue. */
public void addRequest(LocalRequest request) {
mRequestQueue.offer(request);
}
/** Add a new local request to the front of the queue. */
public void addRequestAtFront(LocalRequest request) {
mRequestQueue.offerFirst(request);
}
/**
* Notifies the scheduler that the caller is ready for a new procedure
*
* <p>Synchronously triggers the call to onNewProcedureReady.
*/
public void readyForNextProcedure() {
while (!mRequestQueue.isEmpty()) {
LocalRequest request = mRequestQueue.poll();
if (!request.isCancelled()) {
mConsumer.onNewProcedureReady(request);
return;
}
}
}
/**
* This class represents the common information of procedures that will be locally initiated.
*/
public abstract static class LocalRequest {
public final int procedureType;
private boolean mIsCancelled;
LocalRequest(int type) {
validateTypeOrThrow(type);
procedureType = type;
mIsCancelled = false;
}
boolean isCancelled() {
return mIsCancelled;
}
void cancel() {
mIsCancelled = true;
}
protected abstract void validateTypeOrThrow(int type);
protected abstract boolean isChildRequest();
}
/**
* This class represents a user requested or internally scheduled IKE procedure that will be
* initiated locally.
*/
public static class IkeLocalRequest extends LocalRequest {
public long remoteSpi;
/** Schedule a request for the IKE Session */
IkeLocalRequest(int type) {
this(type, SPI_NOT_INCLUDED);
}
/** Schedule a request for an IKE SA that is identified by the remoteIkeSpi */
IkeLocalRequest(int type, long remoteIkeSpi) {
super(type);
remoteSpi = remoteIkeSpi;
}
@Override
protected void validateTypeOrThrow(int type) {
if (type >= CMD_LOCAL_REQUEST_CREATE_IKE && type <= CMD_LOCAL_REQUEST_DPD) return;
throw new IllegalArgumentException("Invalid IKE procedure type: " + type);
}
@Override
protected boolean isChildRequest() {
return false;
}
}
/**
* This class represents a user requested or internally scheduled Child procedure that will be
* initiated locally.
*/
public static class ChildLocalRequest extends LocalRequest {
public int remoteSpi;
public final ChildSessionCallback childSessionCallback;
public final ChildSessionParams childSessionParams;
/** Schedule a request for a Child Session that is identified by the childCallback */
ChildLocalRequest(
int type, ChildSessionCallback childCallback, ChildSessionParams childParams) {
this(type, SPI_NOT_INCLUDED, childCallback, childParams);
}
/** Schedule a request for a Child SA that is identified by the remoteChildSpi */
ChildLocalRequest(int type, int remoteChildSpi) {
this(type, remoteChildSpi, null /*childCallback*/, null /*childParams*/);
}
private ChildLocalRequest(
int type,
int remoteChildSpi,
ChildSessionCallback childCallback,
ChildSessionParams childParams) {
super(type);
childSessionParams = childParams;
childSessionCallback = childCallback;
remoteSpi = remoteChildSpi;
}
@Override
protected void validateTypeOrThrow(int type) {
if (type >= CMD_LOCAL_REQUEST_CREATE_CHILD && type <= CMD_LOCAL_REQUEST_REKEY_CHILD) {
return;
}
throw new IllegalArgumentException("Invalid Child procedure type: " + type);
}
@Override
protected boolean isChildRequest() {
return true;
}
}
/** Interface to initiate a new IKE procedure */
public interface IProcedureConsumer {
/**
* Called when a new IKE procedure can be initiated.
*
* @param localRequest the request to be initiated.
*/
void onNewProcedureReady(LocalRequest localRequest);
}
}