summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorVitaly Minko <vitaly.minko@gmail.com>2019-01-29 18:44:56 +0300
committerVitaly Minko <vitaly.minko@gmail.com>2019-01-29 18:44:56 +0300
commita68a34c96007f86345fa34008a2d1eac64bf93ca (patch)
treee75b04be1f270c84c8a11969e3469bf7961dacc6
parent8a2d6fb9cf161de9944a44304738e3c97a81534b (diff)
Implemented new address provider: DHTCrawler.
-rw-r--r--address/address.go46
-rw-r--r--config.go6
-rw-r--r--docs/illustrations/class_dia.pngbin545196 -> 545315 bytes
-rw-r--r--docs/illustrations/sources/class_dia.dia703
-rw-r--r--dscuss.go18
-rw-r--r--errors/errors.go1
-rw-r--r--p2p/address_list.go78
-rw-r--r--p2p/address_provider.go70
-rw-r--r--p2p/dht_crawler.go229
-rw-r--r--subs/subscriptions.go22
-rw-r--r--subs/topic.go12
-rw-r--r--testbed/data/1/config.json3
-rw-r--r--testbed/data/2/config.json3
-rw-r--r--testbed/data/3/config.json3
14 files changed, 818 insertions, 376 deletions
diff --git a/address/address.go b/address/address.go
new file mode 100644
index 0000000..fcbbbc1
--- /dev/null
+++ b/address/address.go
@@ -0,0 +1,46 @@
+/*
+This file is part of Dscuss.
+Copyright (C) 2019 Vitaly Minko
+
+This program 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 of the License, or (at your option) any later
+version.
+
+This program 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
+this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+package address
+
+import (
+ "regexp"
+ "strconv"
+ "strings"
+)
+
+const (
+ DomainPortRegex string = "^(([a-zA-Z0-9]|[a-zA-Z0-9][a-zA-Z0-9\\-]*[a-zA-Z0-9])\\.)*([A-Za-z0-9]|[A-Za-z0-9][A-Za-z0-9\\-]*[A-Za-z0-9]):\\d+$"
+ IPPortRegex string = "^(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5]):\\d+$"
+)
+
+func IsValid(a string) bool {
+ var domainPortRe = regexp.MustCompile(DomainPortRegex)
+ var ipPortRe = regexp.MustCompile(IPPortRegex)
+ return domainPortRe.MatchString(a) || ipPortRe.MatchString(a)
+}
+
+func Parse(a string) (string, int, error) {
+ idx := strings.LastIndex(a, ":")
+ host := a[:idx]
+ portStr := a[idx+1:]
+ port, err := strconv.Atoi(portStr)
+ if err != nil {
+ return "", 0, err
+ }
+ return host, port, nil
+}
diff --git a/config.go b/config.go
index 92803ea..c545fa9 100644
--- a/config.go
+++ b/config.go
@@ -29,8 +29,10 @@ import (
)
type NetworkConfig struct {
- HostPort string
+ Address string
+ Port int
AddressProvider string
+ DHTPort int
MaxInConnCount uint32
MaxOutConnCount uint32
}
@@ -41,7 +43,7 @@ type config struct {
var defaultConfig = config{
Network: NetworkConfig{
- HostPort: ":8004",
+ Port: 8004,
AddressProvider: "addrlist",
MaxInConnCount: 10,
MaxOutConnCount: 10,
diff --git a/docs/illustrations/class_dia.png b/docs/illustrations/class_dia.png
index a4a2b29..166886c 100644
--- a/docs/illustrations/class_dia.png
+++ b/docs/illustrations/class_dia.png
Binary files differ
diff --git a/docs/illustrations/sources/class_dia.dia b/docs/illustrations/sources/class_dia.dia
index b59358d..efdd48b 100644
--- a/docs/illustrations/sources/class_dia.dia
+++ b/docs/illustrations/sources/class_dia.dia
@@ -2864,7 +2864,7 @@
<dia:point val="-59.2736,-10.5948"/>
</dia:attribute>
<dia:attribute name="obj_bb">
- <dia:rectangle val="-59.3236,-10.6448;-50.9886,-0.04482"/>
+ <dia:rectangle val="-59.3236,-10.6448;-50.9886,-0.0448"/>
</dia:attribute>
<dia:attribute name="elem_corner">
<dia:point val="-59.2736,-10.5948"/>
@@ -3337,8 +3337,8 @@
<dia:string>##</dia:string>
</dia:attribute>
<dia:connections>
- <dia:connection handle="0" to="O56" connection="14"/>
- <dia:connection handle="1" to="O48" connection="3"/>
+ <dia:connection handle="0" to="O54" connection="14"/>
+ <dia:connection handle="1" to="O46" connection="3"/>
</dia:connections>
</dia:object>
<dia:object type="UML - Dependency" version="1" id="O8">
@@ -3390,7 +3390,7 @@
<dia:point val="102.961,28.7522"/>
</dia:attribute>
<dia:attribute name="obj_bb">
- <dia:rectangle val="102.911,28.7022;113.708,31.9022"/>
+ <dia:rectangle val="102.911,28.7022;113.709,31.9022"/>
</dia:attribute>
<dia:attribute name="elem_corner">
<dia:point val="102.961,28.7522"/>
@@ -4325,7 +4325,7 @@
<dia:string>##</dia:string>
</dia:attribute>
<dia:connections>
- <dia:connection handle="0" to="O56" connection="14"/>
+ <dia:connection handle="0" to="O54" connection="14"/>
<dia:connection handle="1" to="O10" connection="18"/>
</dia:connections>
</dia:object>
@@ -4366,7 +4366,7 @@
<dia:string>##</dia:string>
</dia:attribute>
<dia:connections>
- <dia:connection handle="0" to="O56" connection="14"/>
+ <dia:connection handle="0" to="O54" connection="14"/>
<dia:connection handle="1" to="O9" connection="10"/>
</dia:connections>
</dia:object>
@@ -4407,7 +4407,7 @@
<dia:string>##</dia:string>
</dia:attribute>
<dia:connections>
- <dia:connection handle="0" to="O56" connection="14"/>
+ <dia:connection handle="0" to="O54" connection="14"/>
<dia:connection handle="1" to="O11" connection="3"/>
</dia:connections>
</dia:object>
@@ -5420,7 +5420,7 @@
<dia:point val="-42.3244,-4.41142"/>
</dia:attribute>
<dia:attribute name="obj_bb">
- <dia:rectangle val="-51.0386,-5.62812;-42.2744,-3.56142"/>
+ <dia:rectangle val="-51.0386,-5.62811;-42.2744,-3.56142"/>
</dia:attribute>
<dia:attribute name="meta">
<dia:composite type="dict"/>
@@ -5428,8 +5428,8 @@
<dia:attribute name="orth_points">
<dia:point val="-42.3244,-4.41142"/>
<dia:point val="-46.0044,-4.41142"/>
- <dia:point val="-46.0044,-5.34482"/>
- <dia:point val="-50.9886,-5.34482"/>
+ <dia:point val="-46.0044,-5.3448"/>
+ <dia:point val="-50.9886,-5.3448"/>
</dia:attribute>
<dia:attribute name="orth_orient">
<dia:enum val="0"/>
@@ -5502,7 +5502,7 @@
<dia:point val="40.6075,-19.259"/>
</dia:attribute>
<dia:attribute name="obj_bb">
- <dia:rectangle val="40.5575,-19.309;50.23,-6.40895"/>
+ <dia:rectangle val="40.5575,-19.309;50.23,-6.409"/>
</dia:attribute>
<dia:attribute name="elem_corner">
<dia:point val="40.6075,-19.259"/>
@@ -6306,7 +6306,7 @@
<dia:point val="119.9,-10.0897"/>
</dia:attribute>
<dia:attribute name="obj_bb">
- <dia:rectangle val="119.85,-10.1397;129.248,-4.43967"/>
+ <dia:rectangle val="119.85,-10.1397;129.248,-4.4397"/>
</dia:attribute>
<dia:attribute name="elem_corner">
<dia:point val="119.9,-10.0897"/>
@@ -6498,19 +6498,19 @@
</dia:object>
<dia:object type="UML - Dependency" version="1" id="O26">
<dia:attribute name="obj_pos">
- <dia:point val="112.926,-7.28092"/>
+ <dia:point val="112.927,-7.28092"/>
</dia:attribute>
<dia:attribute name="obj_bb">
- <dia:rectangle val="112.876,-8.0353;120.3,-6.4353"/>
+ <dia:rectangle val="112.877,-8.03531;120.3,-6.43531"/>
</dia:attribute>
<dia:attribute name="meta">
<dia:composite type="dict"/>
</dia:attribute>
<dia:attribute name="orth_points">
- <dia:point val="112.926,-7.28092"/>
+ <dia:point val="112.927,-7.28092"/>
<dia:point val="116.188,-7.28092"/>
- <dia:point val="116.188,-7.28967"/>
- <dia:point val="119.85,-7.28967"/>
+ <dia:point val="116.188,-7.2897"/>
+ <dia:point val="119.85,-7.2897"/>
</dia:attribute>
<dia:attribute name="orth_orient">
<dia:enum val="0"/>
@@ -6536,7 +6536,7 @@
<dia:boolean val="true"/>
</dia:attribute>
<dia:connections>
- <dia:connection handle="0" to="O48" connection="4"/>
+ <dia:connection handle="0" to="O46" connection="4"/>
<dia:connection handle="1" to="O25" connection="14"/>
</dia:connections>
</dia:object>
@@ -6667,22 +6667,22 @@ User#</dia:string>
</dia:object>
<dia:object type="UML - Class" version="0" id="O30">
<dia:attribute name="obj_pos">
- <dia:point val="-15.1254,-30.6427"/>
+ <dia:point val="-8.62002,-30.5367"/>
</dia:attribute>
<dia:attribute name="obj_bb">
- <dia:rectangle val="-15.1754,-30.6927;-7.0954,-27.4927"/>
+ <dia:rectangle val="-8.67002,-30.5867;-0.59002,-24.9867"/>
</dia:attribute>
<dia:attribute name="elem_corner">
- <dia:point val="-15.1254,-30.6427"/>
+ <dia:point val="-8.62002,-30.5367"/>
</dia:attribute>
<dia:attribute name="elem_width">
<dia:real val="7.9799999999999995"/>
</dia:attribute>
<dia:attribute name="elem_height">
- <dia:real val="3.0999999999999996"/>
+ <dia:real val="5.5"/>
</dia:attribute>
<dia:attribute name="name">
- <dia:string>#DHTBootstrapper#</dia:string>
+ <dia:string>#DHTCrawler#</dia:string>
</dia:attribute>
<dia:attribute name="stereotype">
<dia:string>##</dia:string>
@@ -6730,7 +6730,7 @@ User#</dia:string>
<dia:color val="#ffffff"/>
</dia:attribute>
<dia:attribute name="text_color">
- <dia:color val="#7f7f7f"/>
+ <dia:color val="#000000"/>
</dia:attribute>
<dia:attribute name="normal_font">
<dia:font family="monospace" style="0" name="Courier"/>
@@ -6768,11 +6768,219 @@ User#</dia:string>
<dia:attribute name="comment_font_height">
<dia:real val="0.69999999999999996"/>
</dia:attribute>
- <dia:attribute name="attributes"/>
+ <dia:attribute name="attributes">
+ <dia:composite type="umlattribute">
+ <dia:attribute name="name">
+ <dia:string>#dht#</dia:string>
+ </dia:attribute>
+ <dia:attribute name="type">
+ <dia:string>##</dia:string>
+ </dia:attribute>
+ <dia:attribute name="value">
+ <dia:string>##</dia:string>
+ </dia:attribute>
+ <dia:attribute name="comment">
+ <dia:string>##</dia:string>
+ </dia:attribute>
+ <dia:attribute name="visibility">
+ <dia:enum val="0"/>
+ </dia:attribute>
+ <dia:attribute name="abstract">
+ <dia:boolean val="false"/>
+ </dia:attribute>
+ <dia:attribute name="class_scope">
+ <dia:boolean val="false"/>
+ </dia:attribute>
+ </dia:composite>
+ <dia:composite type="umlattribute">
+ <dia:attribute name="name">
+ <dia:string>#addr#</dia:string>
+ </dia:attribute>
+ <dia:attribute name="type">
+ <dia:string>##</dia:string>
+ </dia:attribute>
+ <dia:attribute name="value">
+ <dia:string>##</dia:string>
+ </dia:attribute>
+ <dia:attribute name="comment">
+ <dia:string>##</dia:string>
+ </dia:attribute>
+ <dia:attribute name="visibility">
+ <dia:enum val="0"/>
+ </dia:attribute>
+ <dia:attribute name="abstract">
+ <dia:boolean val="false"/>
+ </dia:attribute>
+ <dia:attribute name="class_scope">
+ <dia:boolean val="false"/>
+ </dia:attribute>
+ </dia:composite>
+ <dia:composite type="umlattribute">
+ <dia:attribute name="name">
+ <dia:string>#port#</dia:string>
+ </dia:attribute>
+ <dia:attribute name="type">
+ <dia:string>##</dia:string>
+ </dia:attribute>
+ <dia:attribute name="value">
+ <dia:string>##</dia:string>
+ </dia:attribute>
+ <dia:attribute name="comment">
+ <dia:string>##</dia:string>
+ </dia:attribute>
+ <dia:attribute name="visibility">
+ <dia:enum val="0"/>
+ </dia:attribute>
+ <dia:attribute name="abstract">
+ <dia:boolean val="false"/>
+ </dia:attribute>
+ <dia:attribute name="class_scope">
+ <dia:boolean val="false"/>
+ </dia:attribute>
+ </dia:composite>
+ <dia:composite type="umlattribute">
+ <dia:attribute name="name">
+ <dia:string>#bootstrap#</dia:string>
+ </dia:attribute>
+ <dia:attribute name="type">
+ <dia:string>##</dia:string>
+ </dia:attribute>
+ <dia:attribute name="value">
+ <dia:string>##</dia:string>
+ </dia:attribute>
+ <dia:attribute name="comment">
+ <dia:string>##</dia:string>
+ </dia:attribute>
+ <dia:attribute name="visibility">
+ <dia:enum val="0"/>
+ </dia:attribute>
+ <dia:attribute name="abstract">
+ <dia:boolean val="false"/>
+ </dia:attribute>
+ <dia:attribute name="class_scope">
+ <dia:boolean val="false"/>
+ </dia:attribute>
+ </dia:composite>
+ <dia:composite type="umlattribute">
+ <dia:attribute name="name">
+ <dia:string>#advPort#</dia:string>
+ </dia:attribute>
+ <dia:attribute name="type">
+ <dia:string>##</dia:string>
+ </dia:attribute>
+ <dia:attribute name="value">
+ <dia:string>##</dia:string>
+ </dia:attribute>
+ <dia:attribute name="comment">
+ <dia:string>##</dia:string>
+ </dia:attribute>
+ <dia:attribute name="visibility">
+ <dia:enum val="0"/>
+ </dia:attribute>
+ <dia:attribute name="abstract">
+ <dia:boolean val="false"/>
+ </dia:attribute>
+ <dia:attribute name="class_scope">
+ <dia:boolean val="false"/>
+ </dia:attribute>
+ </dia:composite>
+ <dia:composite type="umlattribute">
+ <dia:attribute name="name">
+ <dia:string>#subs#</dia:string>
+ </dia:attribute>
+ <dia:attribute name="type">
+ <dia:string>##</dia:string>
+ </dia:attribute>
+ <dia:attribute name="value">
+ <dia:string>##</dia:string>
+ </dia:attribute>
+ <dia:attribute name="comment">
+ <dia:string>##</dia:string>
+ </dia:attribute>
+ <dia:attribute name="visibility">
+ <dia:enum val="0"/>
+ </dia:attribute>
+ <dia:attribute name="abstract">
+ <dia:boolean val="false"/>
+ </dia:attribute>
+ <dia:attribute name="class_scope">
+ <dia:boolean val="false"/>
+ </dia:attribute>
+ </dia:composite>
+ <dia:composite type="umlattribute">
+ <dia:attribute name="name">
+ <dia:string>#ac#</dia:string>
+ </dia:attribute>
+ <dia:attribute name="type">
+ <dia:string>##</dia:string>
+ </dia:attribute>
+ <dia:attribute name="value">
+ <dia:string>##</dia:string>
+ </dia:attribute>
+ <dia:attribute name="comment">
+ <dia:string>##</dia:string>
+ </dia:attribute>
+ <dia:attribute name="visibility">
+ <dia:enum val="0"/>
+ </dia:attribute>
+ <dia:attribute name="abstract">
+ <dia:boolean val="false"/>
+ </dia:attribute>
+ <dia:attribute name="class_scope">
+ <dia:boolean val="false"/>
+ </dia:attribute>
+ </dia:composite>
+ <dia:composite type="umlattribute">
+ <dia:attribute name="name">
+ <dia:string>#stopChan#</dia:string>
+ </dia:attribute>
+ <dia:attribute name="type">
+ <dia:string>##</dia:string>
+ </dia:attribute>
+ <dia:attribute name="value">
+ <dia:string>##</dia:string>
+ </dia:attribute>
+ <dia:attribute name="comment">
+ <dia:string>##</dia:string>
+ </dia:attribute>
+ <dia:attribute name="visibility">
+ <dia:enum val="0"/>
+ </dia:attribute>
+ <dia:attribute name="abstract">
+ <dia:boolean val="false"/>
+ </dia:attribute>
+ <dia:attribute name="class_scope">
+ <dia:boolean val="false"/>
+ </dia:attribute>
+ </dia:composite>
+ <dia:composite type="umlattribute">
+ <dia:attribute name="name">
+ <dia:string>#wg#</dia:string>
+ </dia:attribute>
+ <dia:attribute name="type">
+ <dia:string>##</dia:string>
+ </dia:attribute>
+ <dia:attribute name="value">
+ <dia:string>##</dia:string>
+ </dia:attribute>
+ <dia:attribute name="comment">
+ <dia:string>##</dia:string>
+ </dia:attribute>
+ <dia:attribute name="visibility">
+ <dia:enum val="0"/>
+ </dia:attribute>
+ <dia:attribute name="abstract">
+ <dia:boolean val="false"/>
+ </dia:attribute>
+ <dia:attribute name="class_scope">
+ <dia:boolean val="false"/>
+ </dia:attribute>
+ </dia:composite>
+ </dia:attribute>
<dia:attribute name="operations">
<dia:composite type="umloperation">
<dia:attribute name="name">
- <dia:string>#TBD#</dia:string>
+ <dia:string>#NewDHTCrawler#</dia:string>
</dia:attribute>
<dia:attribute name="stereotype">
<dia:string>##</dia:string>
@@ -6781,7 +6989,97 @@ User#</dia:string>
<dia:string>##</dia:string>
</dia:attribute>
<dia:attribute name="visibility">
- <dia:enum val="0"/>
+ <dia:enum val="3"/>
+ </dia:attribute>
+ <dia:attribute name="comment">
+ <dia:string>##</dia:string>
+ </dia:attribute>
+ <dia:attribute name="abstract">
+ <dia:boolean val="false"/>
+ </dia:attribute>
+ <dia:attribute name="inheritance_type">
+ <dia:enum val="2"/>
+ </dia:attribute>
+ <dia:attribute name="query">
+ <dia:boolean val="false"/>
+ </dia:attribute>
+ <dia:attribute name="class_scope">
+ <dia:boolean val="false"/>
+ </dia:attribute>
+ <dia:attribute name="parameters"/>
+ </dia:composite>
+ <dia:composite type="umloperation">
+ <dia:attribute name="name">
+ <dia:string>#run#</dia:string>
+ </dia:attribute>
+ <dia:attribute name="stereotype">
+ <dia:string>##</dia:string>
+ </dia:attribute>
+ <dia:attribute name="type">
+ <dia:string>##</dia:string>
+ </dia:attribute>
+ <dia:attribute name="visibility">
+ <dia:enum val="3"/>
+ </dia:attribute>
+ <dia:attribute name="comment">
+ <dia:string>##</dia:string>
+ </dia:attribute>
+ <dia:attribute name="abstract">
+ <dia:boolean val="false"/>
+ </dia:attribute>
+ <dia:attribute name="inheritance_type">
+ <dia:enum val="2"/>
+ </dia:attribute>
+ <dia:attribute name="query">
+ <dia:boolean val="false"/>
+ </dia:attribute>
+ <dia:attribute name="class_scope">
+ <dia:boolean val="false"/>
+ </dia:attribute>
+ <dia:attribute name="parameters"/>
+ </dia:composite>
+ <dia:composite type="umloperation">
+ <dia:attribute name="name">
+ <dia:string>#drainAddresses#</dia:string>
+ </dia:attribute>
+ <dia:attribute name="stereotype">
+ <dia:string>##</dia:string>
+ </dia:attribute>
+ <dia:attribute name="type">
+ <dia:string>##</dia:string>
+ </dia:attribute>
+ <dia:attribute name="visibility">
+ <dia:enum val="3"/>
+ </dia:attribute>
+ <dia:attribute name="comment">
+ <dia:string>##</dia:string>
+ </dia:attribute>
+ <dia:attribute name="abstract">
+ <dia:boolean val="false"/>
+ </dia:attribute>
+ <dia:attribute name="inheritance_type">
+ <dia:enum val="2"/>
+ </dia:attribute>
+ <dia:attribute name="query">
+ <dia:boolean val="false"/>
+ </dia:attribute>
+ <dia:attribute name="class_scope">
+ <dia:boolean val="false"/>
+ </dia:attribute>
+ <dia:attribute name="parameters"/>
+ </dia:composite>
+ <dia:composite type="umloperation">
+ <dia:attribute name="name">
+ <dia:string>#requestAddresses#</dia:string>
+ </dia:attribute>
+ <dia:attribute name="stereotype">
+ <dia:string>##</dia:string>
+ </dia:attribute>
+ <dia:attribute name="type">
+ <dia:string>##</dia:string>
+ </dia:attribute>
+ <dia:attribute name="visibility">
+ <dia:enum val="3"/>
</dia:attribute>
<dia:attribute name="comment">
<dia:string>##</dia:string>
@@ -6811,16 +7109,16 @@ User#</dia:string>
<dia:point val="-11.1525,-19.5252"/>
</dia:attribute>
<dia:attribute name="obj_bb">
- <dia:rectangle val="-11.5854,-27.9423;-10.6854,-19.4752"/>
+ <dia:rectangle val="-11.2025,-25.4363;-4.18002,-19.4752"/>
</dia:attribute>
<dia:attribute name="meta">
<dia:composite type="dict"/>
</dia:attribute>
<dia:attribute name="orth_points">
<dia:point val="-11.1525,-19.5252"/>
- <dia:point val="-11.1525,-23.3087"/>
- <dia:point val="-11.1354,-23.3087"/>
- <dia:point val="-11.1354,-27.4923"/>
+ <dia:point val="-11.1525,-22.0557"/>
+ <dia:point val="-4.63002,-22.0557"/>
+ <dia:point val="-4.63002,-24.9863"/>
</dia:attribute>
<dia:attribute name="orth_orient">
<dia:enum val="1"/>
@@ -6846,8 +7144,8 @@ User#</dia:string>
<dia:boolean val="true"/>
</dia:attribute>
<dia:connections>
- <dia:connection handle="0" to="O74" connection="14"/>
- <dia:connection handle="1" to="O30" connection="10"/>
+ <dia:connection handle="0" to="O72" connection="14"/>
+ <dia:connection handle="1" to="O30" connection="16"/>
</dia:connections>
</dia:object>
<dia:object type="UML - Class" version="0" id="O32">
@@ -8097,7 +8395,7 @@ User#</dia:string>
<dia:point val="-18.6858,-11.0089"/>
</dia:attribute>
<dia:attribute name="obj_bb">
- <dia:rectangle val="-18.7358,-11.0589;-3.66329,9.14114"/>
+ <dia:rectangle val="-18.7358,-11.0589;-3.6633,9.1411"/>
</dia:attribute>
<dia:attribute name="elem_corner">
<dia:point val="-18.6858,-11.0089"/>
@@ -8836,7 +9134,7 @@ User#</dia:string>
<dia:point val="34.7428,-12.8653"/>
</dia:attribute>
<dia:attribute name="obj_bb">
- <dia:rectangle val="34.6928,-13.6121;41.0072,-12.0121"/>
+ <dia:rectangle val="34.6928,-13.6121;41.0072,-12.0122"/>
</dia:attribute>
<dia:attribute name="meta">
<dia:composite type="dict"/>
@@ -8986,7 +9284,7 @@ User#</dia:string>
<dia:color val="#000000"/>
</dia:attribute>
<dia:connections>
- <dia:connection handle="0" to="O76" connection="11"/>
+ <dia:connection handle="0" to="O74" connection="11"/>
<dia:connection handle="1" to="O43" connection="3"/>
</dia:connections>
</dia:object>
@@ -9057,7 +9355,7 @@ User#</dia:string>
<dia:color val="#000000"/>
</dia:attribute>
<dia:connections>
- <dia:connection handle="0" to="O76" connection="9"/>
+ <dia:connection handle="0" to="O74" connection="9"/>
<dia:connection handle="1" to="O0" connection="38"/>
</dia:connections>
</dia:object>
@@ -9202,7 +9500,7 @@ User#</dia:string>
</dia:attribute>
<dia:connections>
<dia:connection handle="0" to="O43" connection="13"/>
- <dia:connection handle="1" to="O68" connection="38"/>
+ <dia:connection handle="1" to="O66" connection="38"/>
</dia:connections>
</dia:object>
<dia:object type="UML - Association" version="2" id="O42">
@@ -9243,19 +9541,19 @@ User#</dia:string>
<dia:boolean val="false"/>
</dia:attribute>
<dia:attribute name="obj_pos">
- <dia:point val="11.8407,-0.952875"/>
+ <dia:point val="11.8407,-0.95288"/>
</dia:attribute>
<dia:attribute name="obj_bb">
- <dia:rectangle val="-3.71283,-1.70886;12.5907,-0.102875"/>
+ <dia:rectangle val="-3.71284,-1.7089;12.5907,-0.10288"/>
</dia:attribute>
<dia:attribute name="meta">
<dia:composite type="dict"/>
</dia:attribute>
<dia:attribute name="orth_points">
- <dia:point val="11.8407,-0.952875"/>
- <dia:point val="3.73896,-0.952875"/>
- <dia:point val="3.73896,-0.958855"/>
- <dia:point val="-3.66283,-0.958855"/>
+ <dia:point val="11.8407,-0.95288"/>
+ <dia:point val="3.73893,-0.95288"/>
+ <dia:point val="3.73893,-0.9589"/>
+ <dia:point val="-3.66284,-0.9589"/>
</dia:attribute>
<dia:attribute name="orth_orient">
<dia:enum val="0"/>
@@ -9595,13 +9893,13 @@ User#</dia:string>
</dia:object>
<dia:object type="UML - Class" version="0" id="O44">
<dia:attribute name="obj_pos">
- <dia:point val="-28.033,-30.6677"/>
+ <dia:point val="-25.1339,-30.6677"/>
</dia:attribute>
<dia:attribute name="obj_bb">
- <dia:rectangle val="-28.083,-30.7177;-17.063,-25.0177"/>
+ <dia:rectangle val="-25.1839,-30.7177;-14.1639,-25.0177"/>
</dia:attribute>
<dia:attribute name="elem_corner">
- <dia:point val="-28.033,-30.6677"/>
+ <dia:point val="-25.1339,-30.6677"/>
</dia:attribute>
<dia:attribute name="elem_width">
<dia:real val="10.92"/>
@@ -9781,162 +10079,21 @@ User#</dia:string>
</dia:attribute>
<dia:attribute name="templates"/>
</dia:object>
- <dia:object type="UML - Class" version="0" id="O45">
+ <dia:object type="UML - Dependency" version="1" id="O45">
<dia:attribute name="obj_pos">
- <dia:point val="-5.22879,-30.6677"/>
+ <dia:point val="-11.1525,-19.525"/>
</dia:attribute>
<dia:attribute name="obj_bb">
- <dia:rectangle val="-5.27879,-30.7177;5.01621,-27.5177"/>
- </dia:attribute>
- <dia:attribute name="elem_corner">
- <dia:point val="-5.22879,-30.6677"/>
- </dia:attribute>
- <dia:attribute name="elem_width">
- <dia:real val="10.195"/>
- </dia:attribute>
- <dia:attribute name="elem_height">
- <dia:real val="3.0999999999999996"/>
- </dia:attribute>
- <dia:attribute name="name">
- <dia:string>#DNSBootstrapper#</dia:string>
- </dia:attribute>
- <dia:attribute name="stereotype">
- <dia:string>##</dia:string>
- </dia:attribute>
- <dia:attribute name="comment">
- <dia:string>#Discovers new peers via DNS loopups.#</dia:string>
- </dia:attribute>
- <dia:attribute name="abstract">
- <dia:boolean val="false"/>
- </dia:attribute>
- <dia:attribute name="suppress_attributes">
- <dia:boolean val="false"/>
- </dia:attribute>
- <dia:attribute name="suppress_operations">
- <dia:boolean val="false"/>
- </dia:attribute>
- <dia:attribute name="visible_attributes">
- <dia:boolean val="false"/>
- </dia:attribute>
- <dia:attribute name="visible_operations">
- <dia:boolean val="true"/>
- </dia:attribute>
- <dia:attribute name="visible_comments">
- <dia:boolean val="true"/>
- </dia:attribute>
- <dia:attribute name="wrap_operations">
- <dia:boolean val="true"/>
- </dia:attribute>
- <dia:attribute name="wrap_after_char">
- <dia:int val="40"/>
- </dia:attribute>
- <dia:attribute name="comment_line_length">
- <dia:int val="40"/>
- </dia:attribute>
- <dia:attribute name="comment_tagging">
- <dia:boolean val="false"/>
- </dia:attribute>
- <dia:attribute name="line_width">
- <dia:real val="0.10000000000000001"/>
- </dia:attribute>
- <dia:attribute name="line_color">
- <dia:color val="#000000"/>
- </dia:attribute>
- <dia:attribute name="fill_color">
- <dia:color val="#ffffff"/>
- </dia:attribute>
- <dia:attribute name="text_color">
- <dia:color val="#7f7f7f"/>
- </dia:attribute>
- <dia:attribute name="normal_font">
- <dia:font family="monospace" style="0" name="Courier"/>
- </dia:attribute>
- <dia:attribute name="abstract_font">
- <dia:font family="monospace" style="0" name="Courier"/>
- </dia:attribute>
- <dia:attribute name="polymorphic_font">
- <dia:font family="monospace" style="0" name="Courier"/>
- </dia:attribute>
- <dia:attribute name="classname_font">
- <dia:font family="sans" style="80" name="Helvetica-Bold"/>
- </dia:attribute>
- <dia:attribute name="abstract_classname_font">
- <dia:font family="sans" style="0" name="Helvetica"/>
- </dia:attribute>
- <dia:attribute name="comment_font">
- <dia:font family="sans" style="0" name="Helvetica"/>
- </dia:attribute>
- <dia:attribute name="normal_font_height">
- <dia:real val="0.80000000000000004"/>
- </dia:attribute>
- <dia:attribute name="polymorphic_font_height">
- <dia:real val="0.80000000000000004"/>
- </dia:attribute>
- <dia:attribute name="abstract_font_height">
- <dia:real val="0.80000000000000004"/>
- </dia:attribute>
- <dia:attribute name="classname_font_height">
- <dia:real val="1"/>
- </dia:attribute>
- <dia:attribute name="abstract_classname_font_height">
- <dia:real val="1"/>
- </dia:attribute>
- <dia:attribute name="comment_font_height">
- <dia:real val="0.69999999999999996"/>
- </dia:attribute>
- <dia:attribute name="attributes"/>
- <dia:attribute name="operations">
- <dia:composite type="umloperation">
- <dia:attribute name="name">
- <dia:string>#TBD#</dia:string>
- </dia:attribute>
- <dia:attribute name="stereotype">
- <dia:string>##</dia:string>
- </dia:attribute>
- <dia:attribute name="type">
- <dia:string>##</dia:string>
- </dia:attribute>
- <dia:attribute name="visibility">
- <dia:enum val="0"/>
- </dia:attribute>
- <dia:attribute name="comment">
- <dia:string>##</dia:string>
- </dia:attribute>
- <dia:attribute name="abstract">
- <dia:boolean val="false"/>
- </dia:attribute>
- <dia:attribute name="inheritance_type">
- <dia:enum val="2"/>
- </dia:attribute>
- <dia:attribute name="query">
- <dia:boolean val="false"/>
- </dia:attribute>
- <dia:attribute name="class_scope">
- <dia:boolean val="false"/>
- </dia:attribute>
- <dia:attribute name="parameters"/>
- </dia:composite>
- </dia:attribute>
- <dia:attribute name="template">
- <dia:boolean val="false"/>
- </dia:attribute>
- <dia:attribute name="templates"/>
- </dia:object>
- <dia:object type="UML - Dependency" version="1" id="O46">
- <dia:attribute name="obj_pos">
- <dia:point val="-11.1525,-19.5247"/>
- </dia:attribute>
- <dia:attribute name="obj_bb">
- <dia:rectangle val="-11.2025,-28.0177;0.318711,-19.4747"/>
+ <dia:rectangle val="-20.1239,-25.5177;-11.1025,-19.475"/>
</dia:attribute>
<dia:attribute name="meta">
<dia:composite type="dict"/>
</dia:attribute>
<dia:attribute name="orth_points">
- <dia:point val="-11.1525,-19.5247"/>
- <dia:point val="-11.1525,-22.8889"/>
- <dia:point val="-0.131289,-22.8889"/>
- <dia:point val="-0.131289,-27.5677"/>
+ <dia:point val="-11.1525,-19.525"/>
+ <dia:point val="-11.1525,-22.0579"/>
+ <dia:point val="-19.6739,-22.0579"/>
+ <dia:point val="-19.6739,-25.0677"/>
</dia:attribute>
<dia:attribute name="orth_orient">
<dia:enum val="1"/>
@@ -9962,60 +10119,16 @@ User#</dia:string>
<dia:boolean val="true"/>
</dia:attribute>
<dia:connections>
- <dia:connection handle="0" to="O74" connection="14"/>
- <dia:connection handle="1" to="O45" connection="6"/>
- </dia:connections>
- </dia:object>
- <dia:object type="UML - Dependency" version="1" id="O47">
- <dia:attribute name="obj_pos">
- <dia:point val="-11.1525,-19.5238"/>
- </dia:attribute>
- <dia:attribute name="obj_bb">
- <dia:rectangle val="-23.023,-25.5177;-11.1025,-19.4738"/>
- </dia:attribute>
- <dia:attribute name="meta">
- <dia:composite type="dict"/>
- </dia:attribute>
- <dia:attribute name="orth_points">
- <dia:point val="-11.1525,-19.5238"/>
- <dia:point val="-11.1525,-22.9242"/>
- <dia:point val="-22.573,-22.9242"/>
- <dia:point val="-22.573,-25.0677"/>
- </dia:attribute>
- <dia:attribute name="orth_orient">
- <dia:enum val="1"/>
- <dia:enum val="0"/>
- <dia:enum val="1"/>
- </dia:attribute>
- <dia:attribute name="orth_autoroute">
- <dia:boolean val="false"/>
- </dia:attribute>
- <dia:attribute name="text_colour">
- <dia:color val="#000000"/>
- </dia:attribute>
- <dia:attribute name="line_colour">
- <dia:color val="#000000"/>
- </dia:attribute>
- <dia:attribute name="name">
- <dia:string>##</dia:string>
- </dia:attribute>
- <dia:attribute name="stereotype">
- <dia:string>##</dia:string>
- </dia:attribute>
- <dia:attribute name="draw_arrow">
- <dia:boolean val="true"/>
- </dia:attribute>
- <dia:connections>
- <dia:connection handle="0" to="O74" connection="14"/>
+ <dia:connection handle="0" to="O72" connection="14"/>
<dia:connection handle="1" to="O44" connection="6"/>
</dia:connections>
</dia:object>
- <dia:object type="UML - Class" version="0" id="O48">
+ <dia:object type="UML - Class" version="0" id="O46">
<dia:attribute name="obj_pos">
<dia:point val="102.944,-8.33092"/>
</dia:attribute>
<dia:attribute name="obj_bb">
- <dia:rectangle val="102.894,-8.38092;112.976,-1.18092"/>
+ <dia:rectangle val="102.894,-8.38092;112.977,-1.18092"/>
</dia:attribute>
<dia:attribute name="elem_corner">
<dia:point val="102.944,-8.33092"/>
@@ -10301,7 +10414,7 @@ User#</dia:string>
</dia:attribute>
<dia:attribute name="templates"/>
</dia:object>
- <dia:object type="UML - Class" version="0" id="O49">
+ <dia:object type="UML - Class" version="0" id="O47">
<dia:attribute name="obj_pos">
<dia:point val="-61.0801,39.2854"/>
</dia:attribute>
@@ -10592,7 +10705,7 @@ User#</dia:string>
</dia:attribute>
<dia:attribute name="templates"/>
</dia:object>
- <dia:object type="UML - Class" version="0" id="O50">
+ <dia:object type="UML - Class" version="0" id="O48">
<dia:attribute name="obj_pos">
<dia:point val="-48.1476,39.2854"/>
</dia:attribute>
@@ -10883,7 +10996,7 @@ User#</dia:string>
</dia:attribute>
<dia:attribute name="templates"/>
</dia:object>
- <dia:object type="UML - Class" version="0" id="O51">
+ <dia:object type="UML - Class" version="0" id="O49">
<dia:attribute name="obj_pos">
<dia:point val="-61.0436,29.5479"/>
</dia:attribute>
@@ -11114,7 +11227,7 @@ User#</dia:string>
</dia:attribute>
<dia:attribute name="templates"/>
</dia:object>
- <dia:object type="UML - Dependency" version="1" id="O52">
+ <dia:object type="UML - Dependency" version="1" id="O50">
<dia:attribute name="obj_pos">
<dia:point val="-50.9063,42.8354"/>
</dia:attribute>
@@ -11154,11 +11267,11 @@ User#</dia:string>
<dia:boolean val="true"/>
</dia:attribute>
<dia:connections>
- <dia:connection handle="0" to="O49" connection="20"/>
- <dia:connection handle="1" to="O50" connection="20"/>
+ <dia:connection handle="0" to="O47" connection="20"/>
+ <dia:connection handle="1" to="O48" connection="20"/>
</dia:connections>
</dia:object>
- <dia:object type="UML - Class" version="0" id="O53">
+ <dia:object type="UML - Class" version="0" id="O51">
<dia:attribute name="obj_pos">
<dia:point val="-48.1331,29.0101"/>
</dia:attribute>
@@ -11359,7 +11472,7 @@ User#</dia:string>
</dia:attribute>
<dia:attribute name="templates"/>
</dia:object>
- <dia:object type="UML - Dependency" version="1" id="O54">
+ <dia:object type="UML - Dependency" version="1" id="O52">
<dia:attribute name="obj_pos">
<dia:point val="-43.2256,35.1601"/>
</dia:attribute>
@@ -11399,11 +11512,11 @@ User#</dia:string>
<dia:boolean val="true"/>
</dia:attribute>
<dia:connections>
- <dia:connection handle="0" to="O53" connection="14"/>
- <dia:connection handle="1" to="O49" connection="20"/>
+ <dia:connection handle="0" to="O51" connection="14"/>
+ <dia:connection handle="1" to="O47" connection="20"/>
</dia:connections>
</dia:object>
- <dia:object type="UML - Dependency" version="1" id="O55">
+ <dia:object type="UML - Dependency" version="1" id="O53">
<dia:attribute name="obj_pos">
<dia:point val="-43.2256,35.1601"/>
</dia:attribute>
@@ -11443,11 +11556,11 @@ User#</dia:string>
<dia:boolean val="true"/>
</dia:attribute>
<dia:connections>
- <dia:connection handle="0" to="O53" connection="14"/>
- <dia:connection handle="1" to="O50" connection="20"/>
+ <dia:connection handle="0" to="O51" connection="14"/>
+ <dia:connection handle="1" to="O48" connection="20"/>
</dia:connections>
</dia:object>
- <dia:object type="UML - Class" version="0" id="O56">
+ <dia:object type="UML - Class" version="0" id="O54">
<dia:attribute name="obj_pos">
<dia:point val="85.7272,10.0843"/>
</dia:attribute>
@@ -11648,7 +11761,7 @@ User#</dia:string>
</dia:attribute>
<dia:attribute name="templates"/>
</dia:object>
- <dia:object type="UML - Dependency" version="1" id="O57">
+ <dia:object type="UML - Dependency" version="1" id="O55">
<dia:attribute name="obj_pos">
<dia:point val="81.3133,12.7959"/>
</dia:attribute>
@@ -11689,10 +11802,10 @@ User#</dia:string>
</dia:attribute>
<dia:connections>
<dia:connection handle="0" to="O1" connection="52"/>
- <dia:connection handle="1" to="O56" connection="14"/>
+ <dia:connection handle="1" to="O54" connection="14"/>
</dia:connections>
</dia:object>
- <dia:object type="UML - Class" version="0" id="O58">
+ <dia:object type="UML - Class" version="0" id="O56">
<dia:attribute name="obj_pos">
<dia:point val="102.984,0.337792"/>
</dia:attribute>
@@ -11833,7 +11946,7 @@ User#</dia:string>
</dia:attribute>
<dia:attribute name="templates"/>
</dia:object>
- <dia:object type="UML - Generalization" version="1" id="O59">
+ <dia:object type="UML - Generalization" version="1" id="O57">
<dia:attribute name="obj_pos">
<dia:point val="95.2874,12.7843"/>
</dia:attribute>
@@ -11870,11 +11983,11 @@ User#</dia:string>
<dia:string>##</dia:string>
</dia:attribute>
<dia:connections>
- <dia:connection handle="0" to="O56" connection="14"/>
- <dia:connection handle="1" to="O58" connection="10"/>
+ <dia:connection handle="0" to="O54" connection="14"/>
+ <dia:connection handle="1" to="O56" connection="10"/>
</dia:connections>
</dia:object>
- <dia:object type="UML - Class" version="0" id="O60">
+ <dia:object type="UML - Class" version="0" id="O58">
<dia:attribute name="obj_pos">
<dia:point val="119.928,13.6262"/>
</dia:attribute>
@@ -12040,7 +12153,7 @@ User#</dia:string>
</dia:attribute>
<dia:attribute name="templates"/>
</dia:object>
- <dia:object type="UML - Class" version="0" id="O61">
+ <dia:object type="UML - Class" version="0" id="O59">
<dia:attribute name="obj_pos">
<dia:point val="119.858,21.1746"/>
</dia:attribute>
@@ -12181,7 +12294,7 @@ User#</dia:string>
</dia:attribute>
<dia:attribute name="templates"/>
</dia:object>
- <dia:object type="UML - Dependency" version="1" id="O62">
+ <dia:object type="UML - Dependency" version="1" id="O60">
<dia:attribute name="obj_pos">
<dia:point val="113.532,20.5002"/>
</dia:attribute>
@@ -12222,10 +12335,10 @@ User#</dia:string>
</dia:attribute>
<dia:connections>
<dia:connection handle="0" to="O11" connection="34"/>
- <dia:connection handle="1" to="O61" connection="10"/>
+ <dia:connection handle="1" to="O59" connection="10"/>
</dia:connections>
</dia:object>
- <dia:object type="UML - Dependency" version="1" id="O63">
+ <dia:object type="UML - Dependency" version="1" id="O61">
<dia:attribute name="obj_pos">
<dia:point val="113.53,20.5002"/>
</dia:attribute>
@@ -12266,10 +12379,10 @@ User#</dia:string>
</dia:attribute>
<dia:connections>
<dia:connection handle="0" to="O11" connection="34"/>
- <dia:connection handle="1" to="O60" connection="12"/>
+ <dia:connection handle="1" to="O58" connection="12"/>
</dia:connections>
</dia:object>
- <dia:object type="UML - Dependency" version="1" id="O64">
+ <dia:object type="UML - Dependency" version="1" id="O62">
<dia:attribute name="obj_pos">
<dia:point val="113.291,9.06446"/>
</dia:attribute>
@@ -12310,10 +12423,10 @@ User#</dia:string>
</dia:attribute>
<dia:connections>
<dia:connection handle="0" to="O10" connection="18"/>
- <dia:connection handle="1" to="O61" connection="10"/>
+ <dia:connection handle="1" to="O59" connection="10"/>
</dia:connections>
</dia:object>
- <dia:object type="UML - Dependency" version="1" id="O65">
+ <dia:object type="UML - Dependency" version="1" id="O63">
<dia:attribute name="obj_pos">
<dia:point val="85.6769,12.7843"/>
</dia:attribute>
@@ -12353,11 +12466,11 @@ User#</dia:string>
<dia:boolean val="false"/>
</dia:attribute>
<dia:connections>
- <dia:connection handle="0" to="O56" connection="14"/>
+ <dia:connection handle="0" to="O54" connection="14"/>
<dia:connection handle="1" to="O1" connection="52"/>
</dia:connections>
</dia:object>
- <dia:object type="UML - Class" version="0" id="O66">
+ <dia:object type="UML - Class" version="0" id="O64">
<dia:attribute name="obj_pos">
<dia:point val="28.1426,16.2413"/>
</dia:attribute>
@@ -12695,7 +12808,7 @@ User#</dia:string>
</dia:attribute>
<dia:attribute name="templates"/>
</dia:object>
- <dia:object type="UML - Association" version="2" id="O67">
+ <dia:object type="UML - Association" version="2" id="O65">
<dia:attribute name="name">
<dia:string>##</dia:string>
</dia:attribute>
@@ -12763,10 +12876,10 @@ User#</dia:string>
</dia:attribute>
<dia:connections>
<dia:connection handle="0" to="O43" connection="11"/>
- <dia:connection handle="1" to="O66" connection="24"/>
+ <dia:connection handle="1" to="O64" connection="24"/>
</dia:connections>
</dia:object>
- <dia:object type="UML - Class" version="0" id="O68">
+ <dia:object type="UML - Class" version="0" id="O66">
<dia:attribute name="obj_pos">
<dia:point val="42.8823,13.0944"/>
</dia:attribute>
@@ -13287,12 +13400,12 @@ User#</dia:string>
</dia:attribute>
<dia:attribute name="templates"/>
</dia:object>
- <dia:object type="UML - Dependency" version="1" id="O69">
+ <dia:object type="UML - Dependency" version="1" id="O67">
<dia:attribute name="obj_pos">
<dia:point val="39.0879,21.3913"/>
</dia:attribute>
<dia:attribute name="obj_bb">
- <dia:rectangle val="39.0379,20.6429;43.282,22.2429"/>
+ <dia:rectangle val="39.0379,20.6428;43.282,22.2429"/>
</dia:attribute>
<dia:attribute name="meta">
<dia:composite type="dict"/>
@@ -13327,11 +13440,11 @@ User#</dia:string>
<dia:boolean val="true"/>
</dia:attribute>
<dia:connections>
- <dia:connection handle="0" to="O66" connection="24"/>
- <dia:connection handle="1" to="O68" connection="38"/>
+ <dia:connection handle="0" to="O64" connection="24"/>
+ <dia:connection handle="1" to="O66" connection="38"/>
</dia:connections>
</dia:object>
- <dia:object type="UML - Association" version="2" id="O70">
+ <dia:object type="UML - Association" version="2" id="O68">
<dia:attribute name="name">
<dia:string>##</dia:string>
</dia:attribute>
@@ -13398,11 +13511,11 @@ User#</dia:string>
<dia:color val="#000000"/>
</dia:attribute>
<dia:connections>
- <dia:connection handle="0" to="O68" connection="9"/>
+ <dia:connection handle="0" to="O66" connection="9"/>
<dia:connection handle="1" to="O33" connection="24"/>
</dia:connections>
</dia:object>
- <dia:object type="UML - Association" version="2" id="O71">
+ <dia:object type="UML - Association" version="2" id="O69">
<dia:attribute name="name">
<dia:string>##</dia:string>
</dia:attribute>
@@ -13473,7 +13586,7 @@ User#</dia:string>
<dia:connection handle="1" to="O32" connection="60"/>
</dia:connections>
</dia:object>
- <dia:object type="UML - Note" version="0" id="O72">
+ <dia:object type="UML - Note" version="0" id="O70">
<dia:attribute name="obj_pos">
<dia:point val="53.5152,-18.7011"/>
</dia:attribute>
@@ -13524,12 +13637,12 @@ User#</dia:string>
</dia:composite>
</dia:attribute>
</dia:object>
- <dia:object type="Standard - Line" version="0" id="O73">
+ <dia:object type="Standard - Line" version="0" id="O71">
<dia:attribute name="obj_pos">
<dia:point val="53.4651,-17.856"/>
</dia:attribute>
<dia:attribute name="obj_bb">
- <dia:rectangle val="50.0682,-18.2202;53.5151,-17.4966"/>
+ <dia:rectangle val="50.0682,-18.2203;53.5151,-17.4966"/>
</dia:attribute>
<dia:attribute name="conn_endpoints">
<dia:point val="53.4651,-17.856"/>
@@ -13548,11 +13661,11 @@ User#</dia:string>
<dia:real val="0.5"/>
</dia:attribute>
<dia:connections>
- <dia:connection handle="0" to="O72" connection="8"/>
+ <dia:connection handle="0" to="O70" connection="8"/>
<dia:connection handle="1" to="O22" connection="4"/>
</dia:connections>
</dia:object>
- <dia:object type="UML - Class" version="0" id="O74">
+ <dia:object type="UML - Class" version="0" id="O72">
<dia:attribute name="obj_pos">
<dia:point val="-16.4075,-19.4748"/>
</dia:attribute>
@@ -13753,7 +13866,7 @@ User#</dia:string>
</dia:attribute>
<dia:attribute name="templates"/>
</dia:object>
- <dia:object type="UML - Association" version="2" id="O75">
+ <dia:object type="UML - Association" version="2" id="O73">
<dia:attribute name="name">
<dia:string>##</dia:string>
</dia:attribute>
@@ -13821,10 +13934,10 @@ User#</dia:string>
</dia:attribute>
<dia:connections>
<dia:connection handle="0" to="O34" connection="18"/>
- <dia:connection handle="1" to="O74" connection="14"/>
+ <dia:connection handle="1" to="O72" connection="14"/>
</dia:connections>
</dia:object>
- <dia:object type="UML - Class" version="0" id="O76">
+ <dia:object type="UML - Class" version="0" id="O74">
<dia:attribute name="obj_pos">
<dia:point val="-6.56359,13.9012"/>
</dia:attribute>
@@ -14552,7 +14665,7 @@ User#</dia:string>
</dia:attribute>
<dia:attribute name="templates"/>
</dia:object>
- <dia:object type="UML - Class" version="0" id="O77">
+ <dia:object type="UML - Class" version="0" id="O75">
<dia:attribute name="obj_pos">
<dia:point val="-19.0211,15.478"/>
</dia:attribute>
@@ -14966,7 +15079,7 @@ User#</dia:string>
</dia:attribute>
<dia:attribute name="templates"/>
</dia:object>
- <dia:object type="UML - Association" version="2" id="O78">
+ <dia:object type="UML - Association" version="2" id="O76">
<dia:attribute name="name">
<dia:string>##</dia:string>
</dia:attribute>
@@ -15033,8 +15146,8 @@ User#</dia:string>
<dia:color val="#000000"/>
</dia:attribute>
<dia:connections>
- <dia:connection handle="0" to="O77" connection="15"/>
- <dia:connection handle="1" to="O76" connection="3"/>
+ <dia:connection handle="0" to="O75" connection="15"/>
+ <dia:connection handle="1" to="O74" connection="3"/>
</dia:connections>
</dia:object>
</dia:layer>
diff --git a/dscuss.go b/dscuss.go
index 0d923a7..0e4ca0c 100644
--- a/dscuss.go
+++ b/dscuss.go
@@ -23,10 +23,12 @@ package dscuss
import (
"fmt"
+ "net"
"os"
"os/user"
"path/filepath"
"runtime"
+ "strconv"
"vminko.org/dscuss/entity"
"vminko.org/dscuss/errors"
"vminko.org/dscuss/log"
@@ -159,18 +161,20 @@ func Login(nickname string) (*LoginHandle, error) {
AddressListFileName,
)
ap = p2p.NewAddressList(addrFilePath)
- /* TBD:
case "dht":
- case "dns":
- */
+ ap = p2p.NewDHTCrawler(
+ cfg.Network.Address,
+ cfg.Network.DHTPort,
+ "localhost:9117",
+ cfg.Network.Port,
+ ownr.Profile.GetSubscriptions(),
+ )
default:
log.Fatal("Unknown address provider is configured: " + cfg.Network.AddressProvider)
}
- cp := p2p.NewConnectionProvider(
- ap, cfg.Network.HostPort,
- cfg.Network.MaxInConnCount, cfg.Network.MaxOutConnCount,
- )
+ hp := net.JoinHostPort(cfg.Network.Address, strconv.Itoa(cfg.Network.Port))
+ cp := p2p.NewConnectionProvider(ap, hp, cfg.Network.MaxInConnCount, cfg.Network.MaxOutConnCount)
pp := p2p.NewPeerPool(cp, ownr)
pp.Start()
diff --git a/errors/errors.go b/errors/errors.go
index f042026..797440f 100644
--- a/errors/errors.go
+++ b/errors/errors.go
@@ -51,6 +51,7 @@ var (
NotSubscribed = errors.New("you are not subscribed to the specified topic")
ForbiddenOperation = errors.New("forbidden operation")
UserBanned = errors.New("user is banned")
+ NoSuchTag = errors.New("can't find requested tag")
)
// TBD: consider https://dave.cheney.net/2016/04/27/dont-just-check-errors-handle-them-gracefully
diff --git a/p2p/address_list.go b/p2p/address_list.go
new file mode 100644
index 0000000..0fbf7c5
--- /dev/null
+++ b/p2p/address_list.go
@@ -0,0 +1,78 @@
+/*
+This file is part of Dscuss.
+Copyright (C) 2019 Vitaly Minko
+
+This program 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 of the License, or (at your option) any later
+version.
+
+This program 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
+this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+package p2p
+
+import (
+ "bufio"
+ "os"
+ "vminko.org/dscuss/address"
+ "vminko.org/dscuss/errors"
+ "vminko.org/dscuss/log"
+)
+
+// AddressList provider node addresses by reading them from a text file.
+// Implements AddressProvider interface
+type AddressList struct {
+ filepath string
+ ac AddressConsumer
+}
+
+func NewAddressList(filepath string) *AddressList {
+ return &AddressList{filepath: filepath}
+}
+
+func (al *AddressList) RegisterAddressConsumer(ac AddressConsumer) {
+ al.ac = ac
+}
+
+func (al *AddressList) Start() {
+ if al.ac == nil {
+ log.Fatal("attempt to start providing addresses when AddressConsumer is not set")
+ }
+ go al.readAddresses()
+}
+
+func (al *AddressList) Stop() {
+}
+
+func (al *AddressList) readAddresses() {
+ file, err := os.Open(al.filepath)
+ if err != nil {
+ log.Errorf("Can't open file %s: %v", al.filepath, err)
+ return
+ }
+ defer file.Close()
+
+ scanner := bufio.NewScanner(file)
+ for scanner.Scan() {
+ line := scanner.Text()
+ if !address.IsValid(line) {
+ log.Warningf("'%s' is not a valid peer address, ignoring it.", line)
+ log.Warning("Valid peer address is either host:port or ip:port.")
+ al.ac.ErrorFindingAddresses(errors.Parsing)
+ continue
+ }
+ log.Debugf("Found peer address %s", line)
+ al.ac.AddressFound(line)
+ }
+
+ if err := scanner.Err(); err != nil {
+ log.Errorf("Error scanning file %s: %v", al.filepath, err)
+ al.ac.ErrorFindingAddresses(errors.Filesystem)
+ }
+}
diff --git a/p2p/address_provider.go b/p2p/address_provider.go
index b792335..7692eb6 100644
--- a/p2p/address_provider.go
+++ b/p2p/address_provider.go
@@ -1,6 +1,6 @@
/*
This file is part of Dscuss.
-Copyright (C) 2018 Vitaly Minko
+Copyright (C) 2018-2019 Vitaly Minko
This program 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
@@ -17,14 +17,6 @@ this program. If not, see <http://www.gnu.org/licenses/>.
package p2p
-import (
- "bufio"
- "os"
- "regexp"
- "vminko.org/dscuss/errors"
- "vminko.org/dscuss/log"
-)
-
type AddressConsumer interface {
AddressFound(a string)
ErrorFindingAddresses(err error)
@@ -37,63 +29,3 @@ type AddressProvider interface {
Start()
Stop()
}
-
-// AddressList provider node addresses by reading them from a text file.
-// Implements AddressProvider interface
-type AddressList struct {
- filepath string
- ac AddressConsumer
-}
-
-const (
- HostPortRegex string = "^(([a-zA-Z0-9]|[a-zA-Z0-9][a-zA-Z0-9\\-]*[a-zA-Z0-9])\\.)*([A-Za-z0-9]|[A-Za-z0-9][A-Za-z0-9\\-]*[A-Za-z0-9]):\\d+$"
- IPPortRegex string = "^(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5]):\\d+$"
-)
-
-func NewAddressList(filepath string) *AddressList {
- return &AddressList{filepath: filepath}
-}
-
-func (al *AddressList) RegisterAddressConsumer(ac AddressConsumer) {
- al.ac = ac
-}
-
-func (al *AddressList) Start() {
- if al.ac == nil {
- log.Fatal("attempt to start providing addresses when AddressConsumer is not set")
- }
- go al.readAddresses()
-}
-
-func (al *AddressList) Stop() {
-}
-
-func (al *AddressList) readAddresses() {
- file, err := os.Open(al.filepath)
- if err != nil {
- log.Errorf("Can't open file %s: %v", al.filepath, err)
- return
- }
- defer file.Close()
-
- scanner := bufio.NewScanner(file)
- for scanner.Scan() {
- line := scanner.Text()
- var hostPortRe = regexp.MustCompile(HostPortRegex)
- var ipPortRe = regexp.MustCompile(IPPortRegex)
- if !hostPortRe.MatchString(line) && !ipPortRe.MatchString(line) {
- log.Warningf("'%s' is not a valid peer address, ignoring it.", line)
- log.Warning("Valid peer address is either host:port or ip:port.")
- al.ac.ErrorFindingAddresses(errors.Parsing)
- continue
- }
-
- log.Debugf("Found peer address %s", line)
- al.ac.AddressFound(line)
- }
-
- if err := scanner.Err(); err != nil {
- log.Errorf("Error scanning file %s: %v", al.filepath, err)
- al.ac.ErrorFindingAddresses(errors.Filesystem)
- }
-}
diff --git a/p2p/dht_crawler.go b/p2p/dht_crawler.go
new file mode 100644
index 0000000..456dc57
--- /dev/null
+++ b/p2p/dht_crawler.go
@@ -0,0 +1,229 @@
+/*
+This file is part of Dscuss.
+Copyright (C) 2019 Vitaly Minko
+
+This program 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 of the License, or (at your option) any later
+version.
+
+This program 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
+this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+package p2p
+
+import (
+ "crypto/sha1"
+ "fmt"
+ "github.com/nictuku/dht"
+ "net"
+ "sync"
+ "time"
+ "vminko.org/dscuss/address"
+ "vminko.org/dscuss/log"
+ "vminko.org/dscuss/subs"
+)
+
+// DHTCrawler discovers new peers via DHT.
+// Implements AddressProvider interface
+type DHTCrawler struct {
+ dht *dht.DHT
+ addr string
+ port int
+ bootstrap string
+ advPort int
+ subs subs.Subscriptions
+ ac AddressConsumer
+ stopChan chan struct{}
+ wg sync.WaitGroup
+}
+
+const (
+ DHTCrawlerTimeout time.Duration = 5 * time.Second
+)
+
+func NewDHTCrawler(
+ addr string,
+ port int,
+ bootstrap string,
+ advPort int,
+ s subs.Subscriptions,
+) *DHTCrawler {
+ return &DHTCrawler{
+ addr: addr,
+ port: port,
+ bootstrap: bootstrap,
+ advPort: advPort,
+ subs: s.ToCombinations(),
+ stopChan: make(chan struct{}),
+ }
+}
+
+func (dc *DHTCrawler) RegisterAddressConsumer(ac AddressConsumer) {
+ dc.ac = ac
+}
+
+func (dc *DHTCrawler) Start() {
+ log.Debugf("Starting DHTCrawler on: %s:%d", dc.addr, dc.port)
+ if dc.ac == nil {
+ log.Fatal("Attempt to start providing addresses when AddressConsumer is not set")
+ }
+ cfg := dht.NewConfig()
+ //cfg.Address = dc.addr
+ cfg.Port = dc.port
+ cfg.RateLimit = -1
+ cfg.ClientPerMinuteLimit = 10000
+ cfg.DHTRouters = dc.bootstrap
+ cfg.SaveRoutingTable = false
+ log.Debugf("Using these DHTRouters: %s", cfg.DHTRouters)
+
+ var err error
+ dc.dht, err = dht.New(cfg)
+ if err != nil {
+ log.Fatalf("Failed to create a DHT node: %v", err)
+ }
+ dl := &dhtLogger{}
+ dc.dht.DebugLogger = dl
+ err = dc.dht.Start()
+ if err != nil {
+ log.Fatalf("Failed to start DHT node: %v", err)
+ }
+ log.Debugf("DHTCrawler started on port: %d", dc.dht.Port())
+ dc.wg.Add(2)
+ go dc.requestAddresses()
+ go dc.drainAddresses()
+}
+
+func (dc *DHTCrawler) Stop() {
+ log.Debug("Stopping DHTCrawler")
+ close(dc.stopChan)
+ dc.dht.Stop()
+ log.Debug("DHT stopped")
+ dc.wg.Wait()
+ log.Debug("DHTCrawler stoped")
+}
+
+func (dc *DHTCrawler) requestAddresses() {
+ defer dc.wg.Done()
+ log.Debugf("Starting requestAddresses loop for subs %s", dc.subs)
+ for {
+ select {
+ case <-dc.stopChan:
+ log.Debug("Leaving requestAddresses")
+ return
+ case <-time.Tick(DHTCrawlerTimeout):
+ for _, t := range dc.subs {
+ ih := calcInfoHash(t.String())
+ log.Debugf("Requesting addresses for topic %s", t)
+ dc.dht.PeersRequestPort(string(ih), true, dc.advPort)
+ }
+ }
+ }
+}
+
+func (dc *DHTCrawler) drainAddresses() {
+ defer dc.wg.Done()
+ for {
+ select {
+ case <-dc.stopChan:
+ log.Debug("Leaving drainAddresses")
+ return
+ case r := <-dc.dht.PeersRequestResults:
+ log.Debug("Draining addresses...")
+ for _, peers := range r {
+ for _, x := range peers {
+ a := dht.DecodePeerAddress(x)
+ dc.handleNewAddress(a)
+ }
+ }
+ }
+ }
+}
+
+func (dc *DHTCrawler) handleNewAddress(a string) {
+ log.Debugf("Found new address: %s", a)
+ // TBD: remove duplicates
+ if !address.IsValid(a) {
+ log.Warningf("DHT is poisoned, found malformed address %s", a)
+ return
+ }
+ if !isAddressLocal(a, dc.advPort) {
+ dc.ac.AddressFound(a)
+ } else {
+ log.Debugf("Skipping local address %s", a)
+ }
+}
+
+func localIPs() []string {
+ var res []string
+ ifaces, err := net.Interfaces()
+ if err != nil {
+ log.Errorf("Failed to get network interfaces: %v", err)
+ return res
+ }
+ for _, i := range ifaces {
+ addrs, err := i.Addrs()
+ if err != nil {
+ log.Errorf("Failed to get addresses of the interface %s: %v", i, err)
+ continue
+ }
+ for _, addr := range addrs {
+ var ip net.IP
+ switch v := addr.(type) {
+ case *net.IPNet:
+ ip = v.IP
+ case *net.IPAddr:
+ ip = v.IP
+ }
+ res = append(res, ip.String())
+ }
+ }
+ return res
+}
+
+func isAddressLocal(a string, localPort int) bool {
+ ip, port, err := address.Parse(a)
+ if err != nil {
+ log.Errorf("BUG: malformed address '%s' passed input validation: %v", a, err)
+ return false
+ }
+ if localPort != port {
+ return false
+ }
+ for _, lip := range localIPs() {
+ if lip == ip {
+ return true
+ }
+ }
+ return false
+}
+
+func calcInfoHash(s string) dht.InfoHash {
+ h := sha1.New()
+ h.Write([]byte(s))
+ bs := h.Sum(nil)
+ ih, err := dht.DecodeInfoHash(fmt.Sprintf("%x", bs))
+ if err != nil {
+ log.Fatalf("Failed to decode InfoHash for %s error: %v\n", s, err)
+ }
+ return ih
+}
+
+type dhtLogger struct{}
+
+func (dl *dhtLogger) Debugf(format string, args ...interface{}) {
+ log.Debugf(format, args...)
+}
+
+func (dl *dhtLogger) Infof(format string, args ...interface{}) {
+ log.Infof(format, args...)
+}
+
+func (dl *dhtLogger) Errorf(format string, args ...interface{}) {
+ log.Errorf(format, args...)
+}
diff --git a/subs/subscriptions.go b/subs/subscriptions.go
index 61fa6a6..6918ad2 100644
--- a/subs/subscriptions.go
+++ b/subs/subscriptions.go
@@ -70,6 +70,28 @@ func (s Subscriptions) Diff(a Subscriptions) Subscriptions {
return res
}
+func (s Subscriptions) ToCombinations() Subscriptions {
+ var res Subscriptions
+ for _, topic := range s {
+ res = res.addCombinations(topic)
+ }
+ return res
+}
+
+func (s Subscriptions) addCombinations(t Topic) Subscriptions {
+ res := s.AddTopic(t)
+ for _, tag := range t {
+ supTopic, err := t.Remove(tag)
+ if err != nil {
+ log.Fatalf("BUG: can't remote tag %s: %v", tag, err)
+ }
+ if len(supTopic) > 0 {
+ res = res.addCombinations(supTopic)
+ }
+ }
+ return res
+}
+
func (s Subscriptions) IsValid() bool {
if s == nil || len(s) == 0 {
return false
diff --git a/subs/topic.go b/subs/topic.go
index df4ef30..cdd392a 100644
--- a/subs/topic.go
+++ b/subs/topic.go
@@ -99,3 +99,15 @@ func (t Topic) Copy() Topic {
copy(res, t)
return res
}
+
+func (t Topic) Remove(target string) (Topic, error) {
+ res := t.Copy()
+ for i, tag := range res {
+ if tag == target {
+ res[len(res)-1], res[i] = res[i], res[len(res)-1]
+ res = res[:len(res)-1]
+ return res, nil
+ }
+ }
+ return nil, errors.NoSuchTag
+}
diff --git a/testbed/data/1/config.json b/testbed/data/1/config.json
index 77e0639..40b9f50 100644
--- a/testbed/data/1/config.json
+++ b/testbed/data/1/config.json
@@ -1,6 +1,7 @@
{
"Network": {
- "HostPort": ":8004",
+ "Port": 8004,
+ "DHTPort": 9115,
"AddressProvider": "addrlist",
"MaxInConnCount": 10,
"MaxOutConnCount": 10
diff --git a/testbed/data/2/config.json b/testbed/data/2/config.json
index 92cce4e..d051817 100644
--- a/testbed/data/2/config.json
+++ b/testbed/data/2/config.json
@@ -1,6 +1,7 @@
{
"Network": {
- "HostPort": ":8005",
+ "Port": 8005,
+ "DHTPort": 9116,
"AddressProvider": "addrlist",
"MaxInConnCount": 10,
"MaxOutConnCount": 10
diff --git a/testbed/data/3/config.json b/testbed/data/3/config.json
index ae64efa..79378ff 100644
--- a/testbed/data/3/config.json
+++ b/testbed/data/3/config.json
@@ -1,6 +1,7 @@
{
"Network": {
- "HostPort": ":8006",
+ "Port": 8006,
+ "DHTPort": 9117,
"AddressProvider": "addrlist",
"MaxInConnCount": 10,
"MaxOutConnCount": 10