Add an IntroductionManager and Validator

This Introduction BSP Client uses its own group to communicate with
existing contacts. It uses four types of messages to facilitate
introductions: the introduction, the response, the ack and the abort.

The protocol logic is encapsulated in two protocol engines, one for the
introducer and one for the introducee. The introduction client keeps the
local state for each engine, hands messages over to the engines and
processes the result and state changes they return.
This commit is contained in:
Torsten Grote
2016-01-21 10:10:40 -02:00
parent e3459fb0a3
commit f44cb5ff94
26 changed files with 2770 additions and 2 deletions

View File

@@ -0,0 +1,94 @@
package org.briarproject.api.introduction;
import static org.briarproject.api.introduction.IntroducerAction.ACK_1;
import static org.briarproject.api.introduction.IntroducerAction.ACK_2;
import static org.briarproject.api.introduction.IntroducerAction.LOCAL_REQUEST;
import static org.briarproject.api.introduction.IntroducerAction.REMOTE_ACCEPT_1;
import static org.briarproject.api.introduction.IntroducerAction.REMOTE_ACCEPT_2;
import static org.briarproject.api.introduction.IntroducerAction.REMOTE_DECLINE_1;
import static org.briarproject.api.introduction.IntroducerAction.REMOTE_DECLINE_2;
public enum IntroducerProtocolState {
ERROR(0),
PREPARE_REQUESTS(1) {
@Override
public IntroducerProtocolState next(IntroducerAction a) {
if (a == LOCAL_REQUEST) return AWAIT_RESPONSES;
return ERROR;
}
},
AWAIT_RESPONSES(2) {
@Override
public IntroducerProtocolState next(IntroducerAction a) {
if (a == REMOTE_ACCEPT_1) return AWAIT_RESPONSE_2;
if (a == REMOTE_ACCEPT_2) return AWAIT_RESPONSE_1;
if (a == REMOTE_DECLINE_1) return FINISHED;
if (a == REMOTE_DECLINE_2) return FINISHED;
return ERROR;
}
},
AWAIT_RESPONSE_1(3) {
public IntroducerProtocolState next(IntroducerAction a) {
if (a == REMOTE_ACCEPT_1) return AWAIT_ACKS;
if (a == REMOTE_DECLINE_1) return FINISHED;
return ERROR;
}
},
AWAIT_RESPONSE_2(4) {
@Override
public IntroducerProtocolState next(IntroducerAction a) {
if (a == REMOTE_ACCEPT_2) return AWAIT_ACKS;
if (a == REMOTE_DECLINE_2) return FINISHED;
return ERROR;
}
},
AWAIT_ACKS(5) {
@Override
public IntroducerProtocolState next(IntroducerAction a) {
if (a == ACK_1) return AWAIT_ACK_2;
if (a == ACK_2) return AWAIT_ACK_1;
return ERROR;
}
},
AWAIT_ACK_1(6) {
@Override
public IntroducerProtocolState next(IntroducerAction a) {
if (a == ACK_1) return FINISHED;
return ERROR;
}
},
AWAIT_ACK_2(7) {
@Override
public IntroducerProtocolState next(IntroducerAction a) {
if (a == ACK_2) return FINISHED;
return ERROR;
}
},
FINISHED(8);
private final int value;
IntroducerProtocolState(int value) {
this.value = value;
}
public int getValue() {
return value;
}
public static IntroducerProtocolState fromValue(int value) {
for (IntroducerProtocolState s : values()) {
if (s.value == value) return s;
}
throw new IllegalArgumentException();
}
public static boolean isOngoing(IntroducerProtocolState state) {
return state != FINISHED && state != ERROR;
}
public IntroducerProtocolState next(IntroducerAction a) {
return this;
}
}