|
| 1 | +package net.sharksystem.asap; |
| 2 | + |
| 3 | +import net.sharksystem.streams.StreamPair; |
| 4 | + |
| 5 | +import java.io.IOException; |
| 6 | + |
| 7 | +/** |
| 8 | + * An ASAP peer can handle ASAP encounter as they come. It takes in- and output stream and runs an ASAP session. |
| 9 | + * Where are those streams from? They are created from underlying protocol engines. There are probably and hopefully |
| 10 | + * more than one protocol engines in a real environment. A smartphone would provide Bluetooth, Wifi direct and |
| 11 | + * maybe it has allows communicating via an ASAPHub. |
| 12 | + * <br/><br/> |
| 13 | + * We could of course ignore this somewhat more complex environment and create a connection whenever possible and |
| 14 | + * run an ASAP session. That not very efficient, though. It has even the tendency to be a considerable wast of |
| 15 | + * resources. Why is that? |
| 16 | + * <br/><br/> |
| 17 | + * Take ad-hoc networks as an example: A connection can be established within a given radius, like 10m with Bluetooth. |
| 18 | + * A connection gets lost if two devices are over that threshold and can be re-established if they get closer. This |
| 19 | + * leads to flickering effects. Connection gone / re-established / gone again etc. That's ok and useful if we are about |
| 20 | + * implementing streaming services. But we war not. ASAP is basically meant to be platform for distributed apps which |
| 21 | + * are based on the command pattern. There are no streams but data packages. |
| 22 | + * <br/><br/> |
| 23 | + * Application developers will have a pretty good understanding of how often such messages are created. Even very fast |
| 24 | + * human writers will barely produce more than a message per second, presumably far less. Exchange rate in a sensor |
| 25 | + * network observing outside temperature is better be measured in hours than minutes. This will be different in |
| 26 | + * industrial processes. Apparently: It depends on the application scenario. We want to give application developers |
| 27 | + * as much help for optimization as possible. That is one way to safe most probably a lot of energy. |
| 28 | + * <br/><br/> |
| 29 | + * ASAP is an opportunistic protocol. Connections should be established whenever possible. This could and will be a |
| 30 | + * serious leak on resources in a multi-protocol environment. It is hardly useful that two smartphones create a |
| 31 | + * Bluetooth <i>and</i> a Wifi-direct connection if they can. One is sufficient. |
| 32 | + * <br/><br/> |
| 33 | + * An encounter manager deals with those problems. It is highly recommended to use it. We do, see e.g. our ASAPAndroid |
| 34 | + * lib which is even more highly recommend. |
| 35 | + */ |
| 36 | +public interface ASAPEncounterManager { |
| 37 | + /** |
| 38 | + * Other devices can be detected by a point-to-point protocol. This method is to be called before a connection |
| 39 | + * is established. |
| 40 | + * <br/><br/> |
| 41 | + * It can be checked when a last encounter happened. This is most useful e.g. in ad-hoc networks. Communication can |
| 42 | + * get lost by a (slight) movement and could be reestablished a moment later. A kind of cool-down-period can be |
| 43 | + * defined. |
| 44 | + * <br/><br/> |
| 45 | + * Peers could communicate over different channels. Same argument: It can be decided <i>not</i> to establish |
| 46 | + * a connection due to an existing one over another protocol. |
| 47 | + * @param addressOrPeerID address of remote device or a peer id. It is only used as an index, an id. |
| 48 | + * There will be no attempts to establish a connection. |
| 49 | + * @param connectionType Describes the connection that is planned to be established. |
| 50 | + * @return true: a connection should be established or not. |
| 51 | + * @see EncounterConnectionType |
| 52 | + */ |
| 53 | + boolean shouldCreateConnectionToPeer(CharSequence addressOrPeerID, EncounterConnectionType connectionType); |
| 54 | + |
| 55 | + /** |
| 56 | + * A connection to another device was established. This method can be called to handle this new connection. |
| 57 | + * It can lead to an immediate shutdown, e.g. the other device already made a successful attempt to connect e.g. |
| 58 | + * over another protocol. |
| 59 | + * <br/><br/> |
| 60 | + * In a lot of cases an ASAP session will be launched. |
| 61 | + * |
| 62 | + * @param streamPair most likely a socket that is can be used for an ASAP session. |
| 63 | + * @throws IOException something can go wrong when sending data. This object has no obligation to deal with this. |
| 64 | + */ |
| 65 | + void handleEncounter(StreamPair streamPair, EncounterConnectionType connectionType) throws IOException; |
| 66 | + |
| 67 | + /** |
| 68 | + * This method is a variant of the one with less parameters. |
| 69 | + * |
| 70 | + * Here is the catch: |
| 71 | + * <br/><br/> |
| 72 | + * We have a race condition in any ad-hoc network based on this library. What happens if both devices come into |
| 73 | + * sending range? |
| 74 | + * <br/><br/> |
| 75 | + * <ul> |
| 76 | + * <li>Each asks this object if it should establish a connection by calling shouldConnect. It is highly likely |
| 77 | + * that both side get same answer. Let's assume it is a yes.</li> |
| 78 | + * <li>Both would open a passive endpoint (most likely a server socket). In most cases it is already open |
| 79 | + * before the previous step. In any case..</li> |
| 80 | + * <li>Both would try to establish a connection to the other side... An here starts the race...</li> |
| 81 | + * <li>Let's assume Alice and Bob are in that situation: Alice would recognize an connection attempt from |
| 82 | + * Bob on her server socket. She is also aware that she is also doing a connection attempt to Bob. That's in the |
| 83 | + * nature of this process. We do not want this. We do not want to parallel connections between those two devices. |
| 84 | + * One should be canceled. But what: Alice -> Bob or Bob -> Alice ?</li> |
| 85 | + * <li>Bob is in the same situation. That problem arose when working with Bluetooth. It happens very often. |
| 86 | + * This simple solution does <i>not</i> work: If we see a connection attempt on our server we drop out active |
| 87 | + * connection attempt. Both side would do the same and both connection attempts are canceled. That is the race |
| 88 | + * condition. |
| 89 | + * </li> |
| 90 | + * </ul> |
| 91 | + * |
| 92 | + * This problem can be solved by adding an additional parameter. This boolean value states if this method is |
| 93 | + * called by an <i>initiator</i>. What is that? A process that create e.g. a client socket is - per definition - |
| 94 | + * an initiator. It initiated this connection. A server socket waits for connection attempts and is |
| 95 | + * - per definition - no initiator. Please, choose very carefully this parameter. The race condition is solved |
| 96 | + * by an implementation of this interface. |
| 97 | + * <br/><br/> |
| 98 | + * If you are interested: Here is an idea of an implementation. |
| 99 | + * <ul> |
| 100 | + * <li>It is checked if there is an open connection to the other side before anything other happens. |
| 101 | + * If so: stream pair is closed and we are ready here.</li> |
| 102 | + * <li>Both sides exchange a random value over this stream pair. One side will be initiator - the other not. |
| 103 | + * (If you chose that parameter carefully). No we can decide: |
| 104 | + * What is the random number of the initiator and what is the non-initiator value.</li> |
| 105 | + * <li>Is the initiator value smaller than the non-initial value? If so: |
| 106 | + * We let this thread sleep a little while. We have produced an asymmetry. One process waits, the other not. |
| 107 | + * </li> |
| 108 | + * <li>After wake-up: We check again if there is already a connection established. If so - there was a race |
| 109 | + * condition and we solved it. If not - we establish a connection.</li> |
| 110 | + * </ul> |
| 111 | + * |
| 112 | + * You should call this variant in any ad-hoc network. You should also uses this variant if you have a fully |
| 113 | + * symmetric situation - both devices offer a port to connect to any make and active attempt to connect. |
| 114 | + * |
| 115 | + * @param streamPair |
| 116 | + * @param initiator |
| 117 | + * @throws IOException |
| 118 | + * @see ASAPEncounterManager#handleEncounter(StreamPair, EncounterConnectionType) |
| 119 | + */ |
| 120 | + void handleEncounter(StreamPair streamPair, EncounterConnectionType connectionType, boolean initiator) throws IOException; |
| 121 | +} |
0 commit comments