aboutsummaryrefslogtreecommitdiff
path: root/src/main/java/org/gnunet/transport/PeerState.java
blob: 90f856a76443f3d5eaa32c007b343a04338692b5 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
/*
 This file is part of GNUnet.
  Copyright (C) 2014 Christian Grothoff (and other contributing authors)

  GNUnet is free software; you can redistribute it and/or modify
  it under the terms of the GNU General Public License as published
  by the Free Software Foundation; either version 3, or (at your
  option) any later version.

  GNUnet is distributed in the hope that it will be useful, but
  WITHOUT ANY WARRANTY; without even the implied warranty of
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  General Public License for more details.

  You should have received a copy of the GNU General Public License
  along with GNUnet; see the file COPYING.  If not, write to the
  Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
  Boston, MA 02110-1301, USA.
 */

package org.gnunet.transport;


/**
 * Possible state of a neighbour.  Initially, we are #GNUNET_TRANSPORT_PS_NOT_CONNECTED.
 *
 * Then, there are two main paths. If we receive a CONNECT message, we give
 * the inbound address to ATS. After the check we ask ATS for a suggestion
 * (#GNUNET_TRANSPORT_PS_CONNECT_RECV_ATS). If ATS makes a suggestion, we
 * send our CONNECT_ACK and go to #GNUNET_TRANSPORT_PS_CONNECT_RECV_ACK.
 * If we receive a SESSION_ACK, we go to #GNUNET_TRANSPORT_PS_CONNECTED
 * (and notify everyone about the new connection). If the operation times out,
 * we go to #GNUNET_TRANSPORT_PS_DISCONNECT.
 *
 * The other case is where we transmit a CONNECT message first.  We
 * start with #GNUNET_TRANSPORT_PS_INIT_ATS.  If we get an address, we send
 * the CONNECT message and go to state #GNUNET_TRANSPORT_PS_CONNECT_SENT.
 * Once we receive a CONNECT_ACK, we go to #GNUNET_TRANSPORT_PS_CONNECTED
 * (and notify everyone about the new connection and send
 * back a SESSION_ACK).  If the operation times out, we go to
 * #GNUNET_TRANSPORT_PS_DISCONNECT.
 *
 * If the session is in trouble (i.e. transport-level disconnect or
 * timeout), we go to #GNUNET_TRANSPORT_PS_RECONNECT_ATS where we ask ATS for a new
 * address (we don't notify anyone about the disconnect yet).  Once we
 * have a new address, we enter #GNUNET_TRANSPORT_PS_RECONNECT_SENT and send a
 * CONNECT message.  If we receive a
 * CONNECT_ACK, we go to #GNUNET_TRANSPORT_PS_CONNECTED and nobody noticed that we had
 * trouble; we also send a SESSION_ACK at this time just in case.  If
 * the operation times out, we go to #GNUNET_TRANSPORT_PS_DISCONNECT (and notify everyone
 * about the lost connection).
 *
 * If ATS decides to switch addresses while we have a normal
 * connection, we go to #GNUNET_TRANSPORT_PS_CONNECTED_SWITCHING_CONNECT_SENT
 * and send a SESSION_CONNECT.  If we get a SESSION_ACK back, we switch the
 * primary connection to the suggested alternative from ATS, go back
 * to #GNUNET_TRANSPORT_PS_CONNECTED and send a SESSION_ACK to the other peer just to be
 * sure.  If the operation times out
 * we go to #GNUNET_TRANSPORT_PS_CONNECTED (and notify ATS that the given alternative
 * address is "invalid").
 *
 * Once a session is in #GNUNET_TRANSPORT_PS_DISCONNECT, it is cleaned up and then goes
 * to (#GNUNET_TRANSPORT_PS_DISCONNECT_FINISHED).  If we receive an explicit disconnect
 * request, we can go from any state to #GNUNET_TRANSPORT_PS_DISCONNECT, possibly after
 * generating disconnect notifications.
 *
 * Note that it is quite possible that while we are in any of these
 * states, we could receive a 'CONNECT' request from the other peer.
 * We then enter a 'weird' state where we pursue our own primary state
 * machine (as described above), but with the 'send_connect_ack' flag
 * set to 1.  If our state machine allows us to send a 'CONNECT_ACK'
 * (because we have an acceptable address), we send the 'CONNECT_ACK'
 * and set the 'send_connect_ack' to 2.  If we then receive a
 * 'SESSION_ACK', we go to #GNUNET_TRANSPORT_PS_CONNECTED (and reset 'send_connect_ack'
 * to 0).
 *
 */
class PeerState
{
  /**
   * Fresh peer or completely disconnected
   */
  public static final int NOT_CONNECTED = 0;

  /**
   * Asked to initiate connection, trying to get address from ATS
   */
  public static final int INIT_ATS = 1;

  /**
   * Sent CONNECT message to other peer, waiting for CONNECT_ACK
   */
  public static final int CONNECT_SENT = 2;

  /**
   * Received a CONNECT, asking ATS about address suggestions.
   */
  public static final int CONNECT_RECV_ATS = 3;

  /**
   * CONNECT request from other peer was CONNECT_ACK'ed, waiting for
   * SESSION_ACK.
   */
  public static final int CONNECT_RECV_ACK = 4;

  /**
   * Got our CONNECT_ACK/SESSION_ACK, connection is up.
   */
  public static final int CONNECTED = 5;

  /**
   * Connection got into trouble, rest of the system still believes
   * it to be up, but we're getting a new address from ATS.
   */
  public static final int RECONNECT_ATS = 6;

  /**
   * Sent CONNECT over new address (either by ATS telling us to switch
   * addresses or from RECONNECT_ATS); if this fails, we need to tell
   * the rest of the system about a disconnect.
   */
  public static final int RECONNECT_SENT = 7;

  /**
   * We have some primary connection, but ATS suggested we switch
   * to some alternative; we now sent a CONNECT message for the
   * alternative session to the other peer and waiting for a
   * CONNECT_ACK to make this our primary connection.
   */
  public static final int CONNECTED_SWITCHING_CONNECT_SENT = 8;

  /**
   * Disconnect in progress (we're sending the DISCONNECT message to the
   * other peer; after that is finished, the state will be cleaned up).
   */
  public static final int DISCONNECT = 9;

  /**
   * We're finished with the disconnect; and are cleaning up the state
   * now!  We put the struct into this state when we are really in the
   * task that calls 'free' on it and are about to remove the record
   * from the map.  We should never find a 'struct NeighbourMapEntry'
   * in this state in the map.  Accessing a 'struct NeighbourMapEntry'
   * in this state virtually always means using memory that has been
   * freed (the exception being the cleanup code in #free_neighbour()).
   */
  public static final int DISCONNECT_FINISHED = 10;
}