github.com/deroproject/derosuite@v2.1.6-1.0.20200307070847-0f2e589c7a2b+incompatible/p2p/handshake.go (about) 1 // Copyright 2017-2018 DERO Project. All rights reserved. 2 // Use of this source code in any form is governed by RESEARCH license. 3 // license can be found in the LICENSE file. 4 // GPG: 0F39 E425 8C65 3947 702A 8234 08B2 0360 A03A 9DE8 5 // 6 // 7 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY 8 // EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 9 // MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL 10 // THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 11 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 12 // PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 13 // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 14 // STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF 15 // THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 16 17 package p2p 18 19 import "fmt" 20 import "bytes" 21 22 //import "net" 23 import "sync/atomic" 24 import "time" 25 26 //import "container/list" 27 28 //import log "github.com/sirupsen/logrus" 29 //import "github.com/allegro/bigcache" 30 import "github.com/romana/rlog" 31 import "github.com/vmihailenco/msgpack" 32 33 import "github.com/deroproject/derosuite/config" 34 import "github.com/deroproject/derosuite/globals" 35 36 //import "github.com/deroproject/derosuite/blockchain" 37 38 // reads our data, length prefix blocks 39 func (connection *Connection) Send_Handshake(request bool) { 40 41 var handshake Handshake_Struct 42 43 fill_common(&handshake.Common) // fill common info 44 handshake.Command = V2_COMMAND_HANDSHAKE 45 handshake.Request = request 46 47 // TODO these version strings should be setup during build 48 // original protocol in c daemon should be called version 1 49 // the new version is version 2 50 handshake.ProtocolVersion = "1.0.0" 51 handshake.DaemonVersion = config.Version.String() 52 handshake.Tag = node_tag 53 handshake.UTC_Time = int64(time.Now().UTC().Unix()) // send our UTC time 54 handshake.Local_Port = uint32(P2P_Port) // export requested or default port 55 handshake.Peer_ID = GetPeerID() // give our randomly generated peer id 56 if globals.Arguments["--lowcpuram"].(bool) == false { 57 handshake.Flags = append(handshake.Flags, FLAG_LOWCPURAM) // add low cpu ram flag 58 } 59 60 //scan our peer list and send peers which have been recently communicated 61 handshake.PeerList = get_peer_list() 62 copy(handshake.Network_ID[:], globals.Config.Network_ID[:]) 63 64 // serialize and send 65 serialized, err := msgpack.Marshal(&handshake) 66 if err != nil { 67 panic(err) 68 } 69 70 rlog.Tracef(2, "handshake sent %s", globals.CTXString(connection.logger)) 71 connection.Send_Message(serialized) 72 } 73 74 // verify incoming handshake for number of checks such as mainnet/testnet etc etc 75 func (connection *Connection) Verify_Handshake(handshake *Handshake_Struct) bool { 76 return bytes.Equal(handshake.Network_ID[:], globals.Config.Network_ID[:]) 77 } 78 79 // handles both server and client connections 80 func (connection *Connection) Handle_Handshake(buf []byte) { 81 82 var handshake Handshake_Struct 83 84 err := msgpack.Unmarshal(buf, &handshake) 85 if err != nil { 86 rlog.Warnf("Error while decoding incoming handshake request err %s %s", err, globals.CTXString(connection.logger)) 87 connection.Exit() 88 return 89 } 90 91 if !connection.Verify_Handshake(&handshake) { // if not same network boot off 92 connection.logger.Debugf("kill connection network id mismatch peer network id %x", handshake.Network_ID) 93 connection.Exit() 94 return 95 } 96 97 rlog.Tracef(2, "handshake response received %+v %s", handshake, globals.CTXString(connection.logger)) 98 99 // check if self connection exit 100 if connection.Incoming && handshake.Peer_ID == GetPeerID(){ 101 rlog.Tracef(1,"Same peer ID, probably self connection, disconnecting from this client") 102 connection.Exit() 103 return 104 } 105 106 107 if handshake.Request { 108 connection.Send_Handshake(false) // send it as response 109 } 110 if !connection.Incoming { // setup success 111 Peer_SetSuccess(connection.Addr.String()) 112 } 113 114 connection.Update(&handshake.Common) // update common information 115 116 if atomic.LoadUint32(&connection.State) == HANDSHAKE_PENDING { // some of the fields are processed only while initial handshake 117 connection.Lock() 118 if len(handshake.ProtocolVersion) < 128 { 119 connection.ProtocolVersion = handshake.ProtocolVersion 120 } 121 122 if len(handshake.DaemonVersion) < 128 { 123 connection.DaemonVersion = handshake.DaemonVersion 124 } 125 connection.Port = handshake.Local_Port 126 connection.Peer_ID = handshake.Peer_ID 127 if len(handshake.Tag) < 128 { 128 connection.Tag = handshake.Tag 129 } 130 131 // TODO we must also add the peer to our list 132 // which can be distributed to other peers 133 if connection.Port != 0 && connection.Port <= 65535 { // peer is saying it has an open port, handshake is success so add peer 134 135 var p Peer 136 if connection.Addr.IP.To4() != nil { // if ipv4 137 p.Address = fmt.Sprintf("%s:%d", connection.Addr.IP.String(), connection.Port) 138 }else{ // if ipv6 139 p.Address = fmt.Sprintf("[%s]:%d", connection.Addr.IP.String(), connection.Port) 140 } 141 p.ID = connection.Peer_ID 142 143 p.LastConnected = 0 // uint64(time.Now().UTC().Unix()) 144 145 /* TODO we should add any flags here if necessary, but they are not 146 required, since a peer can only be used if connected and if connected 147 we already have a truly synced view 148 for _, k := range handshake.Flags { 149 switch k { 150 case FLAG_MINER: 151 p.Miner = true 152 } 153 }*/ 154 155 Peer_Add(&p) 156 } 157 158 for _, k := range handshake.Flags { 159 switch k { 160 case FLAG_LOWCPURAM: 161 connection.Lowcpuram = true 162 163 //connection.logger.Debugf("Miner flag \"%s\" from peer", k) 164 default: 165 connection.logger.Debugf("Unknown flag \"%s\" from peer, ignoring", k) 166 167 } 168 169 } 170 171 // do NOT build TX cache, if we are runnin in lowcpu mode 172 if globals.Arguments["--lowcpuram"].(bool) == true { // if connection is not running in low cpu mode and we are also same, activate transaction cache 173 connection.TXpool_cache = nil 174 } else { // we do not have any limitation, activate per peer cache 175 connection.TXpool_cache = map[uint64]uint32{} 176 177 } 178 connection.Unlock() 179 } 180 181 // parse delivered peer list as grey list 182 rlog.Debugf("Peer provides %d peers", len(handshake.PeerList)) 183 for i := range handshake.PeerList { 184 Peer_Add(&Peer{Address: handshake.PeerList[i].Addr}) 185 } 186 187 atomic.StoreUint32(&connection.State, ACTIVE) 188 if connection.Incoming { 189 Connection_Add(connection) 190 } 191 }