From 73fc3fc6bf42762772edfa7888df73761d36572d Mon Sep 17 00:00:00 2001 From: =?utf8?q?Roland=20H=C3=A4der?= Date: Tue, 31 Jul 2012 18:04:01 +0000 Subject: [PATCH] Cleared messages (they will return), added message layer design for bootstrapping --- .gitattributes | 1 + misc/possible_hub_states.txt | 164 +++++------------- .../message-layer/bootstrapping.odg | Bin 0 -> 17835 bytes protocol-drafts/protocol-ideas.txt | 4 +- 4 files changed, 49 insertions(+), 120 deletions(-) create mode 100644 protocol-drafts/message-layer/bootstrapping.odg diff --git a/.gitattributes b/.gitattributes index 9376b88..9b23fd2 100644 --- a/.gitattributes +++ b/.gitattributes @@ -159,4 +159,5 @@ mindmaps/Peer-State[!!-~]Rating.mm -text misc/possible_hub_states.txt -text svneol=unset#text/plain protocol-drafts/Generic[!!-~]Object[!!-~]Sharing[!!-~]Prototocol[!!-~]0.0.1.odt -text protocol-drafts/Generic[!!-~]Object[!!-~]Sharing[!!-~]Prototocol[!!-~]0.0.1.pdf -text +protocol-drafts/message-layer/bootstrapping.odg -text protocol-drafts/protocol-ideas.txt -text svneol=unset#text/plain diff --git a/misc/possible_hub_states.txt b/misc/possible_hub_states.txt index f8b29c2..9aec898 100644 --- a/misc/possible_hub_states.txt +++ b/misc/possible_hub_states.txt @@ -1,130 +1,58 @@ -Possible States For A Hub Connection -==================================== - -This is a brief summary of possible states a hub connection may be setted. -These ideas should later be implemented in a XML file with e.g. a StateXmlParser -class with a XmlFileReader as a data source. - -------------------------------------------------------------------------------- - Initial state | Reason of change | New state -------------------------------------------------------------------------------- - New peer | Appears as a simple connection | Connected - Connected | Has dropped the connection | Disconnected - Connected | Does not do anything within a timeout | Timed out - Connected | Tries to send some objects with auth enabled | Message "AUTH" - Disconnected | Is purged from the connection list | Removed - Timed out | Is being pinged | Pinged - Pinged | Does not response on a ping | No response - Pinged | Does reply slowly on a ping | Slowed down - Pinged | Does reply fast on a ping | - No response | Does still not response on X pings | Lost connection - No response | Does reply on a ping | Slowed down - Slowed down | Does not response on a ping | No response - Slowed down | Does still response slow on X extra pings | Karma lose - Slowed down | Does reply faster on a ping | - Lost connect. | Is maybe disconnected/crashed/etc. | Disconnected - Karma lose | Has lost some karma | - Add karma | Has gained some karma | -------------------------------------------------------------------------------- - Observed | Did not do any annormal activity within time | Removed from O-List - Observed | Is being observed for further annormal act. | - Removed O-L | Is being removed from observing for ann. ac. | -------------------------------------------------------------------------------- - | Does not response within timeout | Message "BANNED" - | Sends unexpected network packets | Message "PACKET" - | Sends or replies with unknown message | Message "UNKNOWN" - "PACKET" | Still sends unexpected network packets | Karma lose - "PACKET" | Resends valid network package | - "PACKET"+Kar. | Still sends unexpected network packets | Message "BANNED" - "PACKET"+Kar. | Resends valid network package | - "UNKNOWN" | Still sends/replies with unknown message | Karma lose - "UNKNOWN" | Still sends/replies with unknown message | Message "BANNED" - | Does not response within timeout | Pinged -------------------------------------------------------------------------------- - "WELCOME" | Tries to send objects with invalid target | Message "TARGET" - "WELCOME" | Tries to send objects with valid target | Message "ACCEPT-OBJECT" - "WELCOME" | Requests a list of hubs/clients f. inv. obj. | Message "OBJECT" - "WELCOME" | Requests a list of hubs/clients f. val. obj. | Message "LIST" - "WELCOME" | Sends a list of hubs/clients without offer | Message "OFFER-LIST" - "WELCOME" | Offers a list of all invalid objects | Message "ALL-OBJECT-LIST" - "WELCOME" | Offers a list with partly invalid objects | Message "PAR-OBJECT-LIST" - "WELCOME" | Offers a list of all valid objects | Message "ACCEPT-LIST" - "A-L" | Has send a different list of objects | Message "DIV-LIST" - "A-L" | Has send the same list of valid objects | Add karma - "A-O-L" | Still offers a list of all invalid objects | Karma lose - "A-O-L" | Reoffers a list of valid objects | Message "ACCEPT-LIST" - "A-O-L"+Karma | Still offers a list of all invalid objects | Message "BANNED" - "A-O-L"+Karma | Still offers a list of all invalid objects | Message "ACCEPT-LIST" - "A-O-L"+Karma | Reoffers a list of valid objects | Message "ACCEPT-LIST - "A-K" | The target rejects the object: "OBJECT" | Message "TARGET-OBJECT" - "A-K" | The target rejects the object: "BUSY" | Message "BUSY-OBJECT" - "A-O" | Tries to send an invalid object | Message "INVALID-OBJECT" - "A-O" | Tries to send a different but valid object | Message "DIV-OBJECT" - "A-O" | Sends the same object | Add karma - "A/P-T" | Still sends a list of all/partly invalid o. | Karma lose - "A/P-T"+Karma | Still sends a list of all/partly invalid o. | Message "BANNED" - "P-O-L" | Still offers a list of part. invalid objects | Karma lose - "P-O-L" | Resends a list of valid objects | Observe->Message "ACCEPT-LIST" - "P-O-L"+Karma | Still offers a list of part. invalid objects | Message "BANNED" - "P-O-L"+Karma | Resends a list of valid objects | Observe->Message "ACCEPT-LIST" - "I-O" | Still tries to send an invalid object | Karma lose - "I-O" | Resends a different invalid object | Message "DIV-OBJECT" - "I-O" | Resends the same valid object | Observed - "I-O"+Karma | Still tries to send an invalid object | Message "BANNED" - "I-O"+Karma | Resends the same valid object | Observed - "D-L" | Still sends a different list | Karma lose - "D-L" | Resends the same list | Observed - "D-L"+Karma | Still sends a different list | Message "BANNED" - "D-L"+Karma | Resends the same list | Observed - "D-O" | Still tries to send a different object | Karma lose - "D-O" | Resends the same valid object | Observed - "D-O"+Karma | Still tries to send a different object | Message "BANNED" - "D-O"+Karma | Resends the same valid object | Observed - "LIST" | The peer receives a list of hubs and clients | - "TARGET" | Still tries to send objects to invalid targ. | Karma lose - "TARGET" | Sends an object to target with weak karma | Message "ACCEPT-KARMA" - "TARGET" | Sends an object to valid target | Message "ACCEPT-OBJECT" - "TARGET"+Kar. | Still tries to send objects to invalid targ. | Message "TARGET-KARMA" - "T-K" | Still tries to send objects to invalid targ. | Message "BANNED" - "T-O" | Target does not accept the obj. but in list | Message "OBJECT-LIST" to target - "OBJECT" | Still requests a list f. invalid object | Karma lose - "OBJECT"+Kar. | Still requests a list f. invalid object | Message "OBJECT-KARMA - "O-K" | Still requests a list f. invalid object | Message "BANNED" - "O-L" | Target does still say "ACCEPT" for object | Karma lose - "O-L"+Karma | Target does still say "ACCEPT" for object | Message "BANNED" to target - "AUTH" | Still tries to send objects after X "AUTH" | Karma lose - "AUTH" | Sends valid authorization data | Observe->Message "WELCOME" - "AUTH"+Karma | Still tries to send objects after X "AUTH" | Message "BANNED" - "AUTH"+Karma | Sends invalid authorization data | Message "KICKED" - "AUTH"+Karma | Sends valid authorization data | Observe->Message "WELCOME" - "KICKED" | Still authorizes itself with invalid data | Message "BANNED" - "BANNED" | Is being banned on the node | Disconnected -------------------------------------------------------------------------------- - -A previous state is a non-fatal state that the peer was before the trouble +Possible node-internal states +============================= + +These states are the node's own states and not a state of any other node, e.g. +when you start the software, there is currently no state [instance], the +node's state is 'null' (also null from $stateInstance is initially null). + +---------------+------------------------------------------------------+------------- + Initial state | Reason of change | New state +---------------+------------------------------------------------------+------------- + Null | Node application has been initialized | Init + Init | Node has generated session id | Virgin + Virgin | Node has initialized all listeners, queues | Active + Active | Node has reached itself from outside (self-connect) | Reachable + Active | Node has attempted to announce itself to other nodes | Announced + Reachable | -"- -"- -"- -"- -"- | Announced +---------------+------------------------------------------------------+------------- + +Possible states for a regular-node connection +============================================= + +This is a brief summary of possible states a regular-node connection may be +setted. These ideas should later be implemented in a XML file with e.g. a +StateXmlParser class with a XmlFileReader as a data source. + +---------------+------------------------------------------------------+------------- + Initial state | Reason of change | New state +---------------+------------------------------------------------------+------------- +---------------+------------------------------------------------------+------------- + +A previous state is a non-fatal state that the node was before the "trouble" started. This state is stored along with a timestamp to watch the overall -performance of this hub reacting a troubleous peer. +performance of this node reacting a troubleous node. -Karma lose or added karma is being remembered in a lose/add-seperated summary for -"productive" and addionally as a full list for debugging purposes if the debug -mode is enabled. +Karma lose or added karma is being remembered in a lose/add-seperated summary +for "productive" and addionally as a full list for debugging purposes if the +debug mode is enabled. A "connection" should be interpreted as a incoming socket "connection". That means in this state table we threat UDP "connections" as same as TCP -connections to make things easier. Of, course the script will be the last one to -seperate between these very different protocols. +connections to make things easier. Of, course the script will be the last one +to seperate between these very different protocols. -A "ping" is a small message that should be responded by a pinged peer within a -time period else the ping would loose some karma. When a "ping" is issued it -should not be resend within a time period to not ping the peer to death. +A "ping" is a small message that should be responded by a pinged node within a +time period else the pinged node would loose some karma. When a "ping" is +issued it should not be resend within a time period to not ping the node to +death. -So pings are not issued while there is no trouble with the peer. This does -reduce network load for certain. Troubleous peers are being detected by the +So pings are not issued while there is no trouble with the node. This does +reduce network load for certain. Troubleous nodes are being detected by the above state changes (see Connected->Timed out for example). Some state changes are no *real* state changes. They are sometimes remarks -attached to the peer connection. A good example is the state 'Karma lose' which -a peer does never change to. +attached to the node connection. A good example is the state 'Karma lose' which +a node does never change to. A "list" should be interpreted as a DHT (Distributed Hash Table). All list and -object transferes are being validated by final hashes for high reliablity. +object transfers are being validated by final hashes for best reliablity. diff --git a/protocol-drafts/message-layer/bootstrapping.odg b/protocol-drafts/message-layer/bootstrapping.odg new file mode 100644 index 0000000000000000000000000000000000000000..07b8eaea91b4b8f74178c2d8e8cd2df8f9d94933 GIT binary patch literal 17835 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 t{{_~A@^{cb)4>~;{*fRB{)Sl