github.com/geniusesgroup/libgo@v0.0.0-20220713101832-828057a9d3d4/gp/connection.go (about) 1 /* For license and copyright information please see LEGAL file in repository */ 2 3 package gp 4 5 import ( 6 "sync/atomic" 7 "time" 8 9 "../authorization" 10 "../connection" 11 "../protocol" 12 "../uuid" 13 ) 14 15 // Connection indicate the 16 // https://github.com/balacode/udpt/blob/main/sender.go 17 type Connection struct { 18 writeTime etime.Time 19 20 /* Connection data */ 21 ID [32]byte 22 StreamPool StreamPool 23 State protocol.ConnectionState 24 Weight protocol.ConnectionWeight 25 linkConn protocol.NetworkLinkConnection 26 mtu int // Maximum Transmission Unit. max GP payload size 27 28 /* Peer data */ 29 addr Addr 30 thingID [32]byte // Use as ConnectionID too! 31 domainName string 32 // Peer Identifiers 33 userID [32]byte // Can't change on StateLoaded! 34 userType protocol.UserType 35 delegateUserID [32]byte // Can't change on StateLoaded! 36 delegateUserType protocol.UserType 37 38 /* Security data */ 39 AccessControl authorization.AccessControl 40 cipher protocol.Cipher // Selected cipher algorithms https://en.wikipedia.org/wiki/Cipher_suite 41 42 connection.Metric 43 } 44 45 func (conn *Connection) ID() uint32 { return conn.id } 46 func (conn *Connection) MTU() int { return conn.mtu } 47 func (conn *Connection) Addr() [16]byte { return conn.addr } 48 func (conn *Connection) AddrType() NetworkLinkNextHeaderID { return protocol.NetworkLinkNextHeaderGP } 49 func (conn *Connection) ThingID() [32]byte { return conn.thingID } 50 func (conn *Connection) DomainName() string { return conn.domainName } 51 func (conn *Connection) UserID() [32]byte { return conn.userID } 52 func (conn *Connection) UserType() UserType { return conn.userType } 53 func (conn *Connection) DelegateUserID() [32]byte { return conn.delegateUserID } 54 func (conn *Connection) DelegateUserType() UserType { return conn.delegateUserType } 55 func (conn *Connection) Cipher() Cipher { return conn.cipher } 56 57 // SetThingID set thingID only if it is not set before 58 func (conn *Connection) SetThingID(thingID [32]byte) { 59 if conn.ThingID == [32]byte{} { 60 conn.ThingID = thingID 61 } 62 } 63 64 // Receive use for default and empty switch port due to non of ports can be nil! 65 func (conn *Connection) Receive(packet []byte) { 66 var err protocol.Error 67 68 // TODO::: check packet signature and decrypt it 69 // Decrypt packet! 70 var frames []byte 71 frames, err = Decrypt(GetPayload(packet), conn.Cipher()) 72 if err != nil { 73 conn.FailedPacketsReceived() 74 // Send NACK or store and send later 75 // TODO::: DDOS!!?? 76 return 77 } 78 79 // TODO::: check packet number and send ACK||NACK frame 80 81 // Metrics data 82 // conn.PacketReceived(uint64(len(packet))) 83 // conn.PacketPayloadSize = GetPayloadLength(packet) // It's not working due to packet not encrypted yet! 84 85 err = srpconn.HandleFrames(c, frames) 86 if err != nil { 87 // TODO::: 88 } 89 return 90 } 91 92 func handleDataFrame(st protocol.Stream, dataFrame []byte, packetID uint32) (err protocol.Error) { 93 // Handle packet received not by order 94 if packetID < st.LastPacketID { 95 st.State = StateBrokenPacket 96 err = ErrPacketArrivedPosterior 97 } else if packetID > st.LastPacketID+1 { 98 st.State = StateBrokenPacket 99 err = ErrPacketArrivedAnterior 100 // TODO::: send request to sender about not received packets!! 101 } else if packetID+1 == st.LastPacketID { 102 st.LastPacketID = packetID 103 } 104 // TODO::: non of above cover for packet 0||1 drop situation! 105 106 // Use PacketID 0||1 for request||response to set stream settings! 107 if packetID < 2 { 108 // as.SetStreamSettings(st, p) 109 } else { 110 // TODO::: can't easily copy this way!! 111 // copy(st.IncomePayload, p) 112 } 113 114 return 115 } 116 117 // MakeIncomeStream make and return the new stream with income ID! 118 // Never make Stream instance by hand, This function can improve by many ways! 119 func (conn *Connection) MakeIncomeStream(streamID uint32) (st protocol.Stream, err protocol.Error) { 120 // TODO::: Check user can open new stream first as stream policy! 121 122 // if given streamID is 0, return new incremental streamID from pool 123 if streamID == 0 { 124 streamID = conn.StreamPool.freeIncomeStreamID 125 conn.StreamPool.freeIncomeStreamID += 2 126 } 127 128 st = &Stream{ 129 id: streamID, 130 connection: conn, 131 status: protocol.ConnectionStateOpen, 132 state: make(chan protocol.ConnectionState), 133 } 134 conn.StreamPool.RegisterStream(st) 135 return 136 } 137 138 // MakeOutcomeStream make and return the new stream with outcome ID! 139 // Never make Stream instance by hand, This function can improve by many ways! 140 func (conn *Connection) MakeOutcomeStream(streamID uint32) (st *Stream, err protocol.Error) { 141 // TODO::: Check user can open new stream first as stream policy! 142 143 // if given streamID is 0, return new incremental streamID from pool 144 if streamID == 0 { 145 streamID = conn.StreamPool.freeOutcomeStreamID 146 conn.StreamPool.freeOutcomeStreamID += 2 147 } 148 149 st = &Stream{ 150 id: streamID, 151 connection: conn, 152 status: protocol.ConnectionStateOpen, 153 state: make(chan protocol.ConnectionState), 154 } 155 conn.StreamPool.RegisterStream(st) 156 return 157 } 158 159 // MakeSubscriberStream make new Publish–Subscribe stream! 160 func (conn *Connection) MakeSubscriberStream() (st *Stream) { 161 // TODO::: 162 return 163 } 164 165 // EstablishNewConnectionByDomainID make new connection by peer domain ID and initialize it! 166 func EstablishNewConnectionByDomainID(domainID [32]byte) (conn *Connection, err protocol.Error) { 167 // TODO::: Get closest domain GP add 168 var domainGPAddr = Addr{} 169 conn, err = EstablishNewConnectionByPeerAdd(domainGPAddr) 170 if err != nil { 171 return 172 } 173 conn.UserID = domainID 174 conn.UserType = protocol.UserTypeApp 175 return 176 } 177 178 // EstablishNewConnectionByPeerAdd make new connection by peer GP and initialize it! 179 func EstablishNewConnectionByPeerAdd(gpAddr Addr) (conn *Connection, err protocol.Error) { 180 // var userID, thingID [32]byte 181 // TODO::: Get peer publickey & userID & thingID from peer GP router! 182 183 // if userID != [32]byte{} { 184 // conn = protocol.App.GetConnectionByUserIDThingID(userID, thingID) 185 // } 186 187 // If conn not exist means guest connection. 188 if conn == nil { 189 conn, err = MakeNewGuestConnection() 190 if err == nil { 191 conn.Addr = gpAddr 192 // conn.Cipher = crypto.NewGCM(crypto.NewAES256([32]byte{})) 193 } 194 } 195 return 196 } 197 198 // MakeNewGuestConnection make new connection and register on given stream due to it is first attempt connect to server! 199 func MakeNewGuestConnection() (conn *Connection, err protocol.Error) { 200 // if Server.Manifest.TechnicalInfo.GuestMaxConnections == 0 { 201 // return nil, ErrGuestConnectionNotAllow 202 // } else if Server.Manifest.TechnicalInfo.GuestMaxConnections > 0 && Server.Connections.GuestConnectionCount > Server.Manifest.TechnicalInfo.GuestMaxConnections { 203 // return nil, ErrGuestConnectionMaxReached 204 // } 205 206 conn = &Connection{ 207 ID: uuid.Random32Byte(), 208 State: protocol.ConnectionStateNew, 209 UserType: protocol.UserTypeGuest, 210 } 211 conn.AccessControl.GiveFullAccess() 212 conn.StreamPool.Init() 213 return 214 }