github.com/geniusesgroup/libgo@v0.0.0-20220713101832-828057a9d3d4/ChaparKhane/user-connections.go (about) 1 /* For license and copyright information please see LEGAL file in repository */ 2 3 package chaparkhane 4 5 import ( 6 "hash/crc32" 7 8 "../chapar" 9 "../crypto" 10 "../uuid" 11 ) 12 13 // userConnections store pools of connection to retrieve in many ways! 14 type userConnections struct { 15 old *userConnections // use just in expanding 16 pathsPool [254][]*UserConnection 17 usersGPPoolLen uint32 18 usersGPPool []userGPBucket 19 usersPoolLen uint32 20 usersPool []userBucket 21 } 22 23 type userGPBucket struct { 24 FreeID uint8 25 UserGPID [8]uint32 26 Conn [8]*UserConnection 27 } 28 29 type userBucket struct { 30 FreeID uint8 31 UserID [8][16]byte 32 Conn [8][]*UserConnection 33 } 34 35 func (uc *userConnections) init() { 36 // TotalHop = 1 or One hop frame use just in p2p networks and not pass here!! 37 // TotalHop = 2 or Two hop implement by just one Chapar switch device! 38 uc.pathsPool[0] = make([]*UserConnection, 256) 39 // TotalHop > 2 or More than two hop implement by more than one Chapar switch device! 40 var i uint8 41 for i = 1; i < 255; i++ { 42 uc.pathsPool[i] = make([]*UserConnection, 2048) 43 } 44 45 uc.usersGPPool = make([]userGPBucket, 2048) 46 uc.usersGPPoolLen = 2048 47 48 uc.usersPool = make([]userBucket, 2048) 49 uc.usersPoolLen = 2048 50 } 51 52 func (uc *userConnections) expandPathPool(hopNum uint8) (newPoolLen uint32) { 53 var poolLen uint32 = uint32(len(uc.pathsPool[hopNum])) 54 newPoolLen = poolLen * 2 55 56 var new = make([]*UserConnection, newPoolLen) 57 58 // Copy old paths 59 var existingConn *UserConnection 60 var loc uint32 61 var i uint32 62 for i = 0; i < poolLen; i++ { 63 existingConn = uc.pathsPool[hopNum][i] 64 if existingConn != nil { 65 loc = crc32.ChecksumIEEE(existingConn.Path) % newPoolLen 66 new[loc] = existingConn 67 } 68 } 69 uc.pathsPool[hopNum] = new 70 71 return 72 } 73 74 func (uc *userConnections) expandUsersGPPool() { 75 var newPoolLen uint32 = uc.usersGPPoolLen * 2 76 var new = make([]userGPBucket, newPoolLen) 77 78 // Copy old records 79 var loc uint32 80 var i uint32 81 var j uint8 82 var f uint8 83 for i = 0; i < uc.usersGPPoolLen; i++ { 84 f = uc.usersGPPool[i].FreeID 85 for j = 0; j < f; j++ { 86 loc = uc.usersGPPool[i].Conn[j].UserGPID % newPoolLen 87 new[loc].UserGPID[f] = uc.usersGPPool[i].Conn[j].UserGPID 88 new[loc].Conn[f] = uc.usersGPPool[i].Conn[j] 89 uc.usersGPPool[i].FreeID++ 90 } 91 } 92 93 uc.usersGPPool = new 94 uc.usersGPPoolLen = newPoolLen 95 } 96 97 func (uc *userConnections) expandUsersPool() { 98 var newPoolLen uint32 = uc.usersPoolLen * 2 99 var newPool = make([]userBucket, newPoolLen) 100 101 // Copy old records 102 var loc uint32 103 var i uint32 104 var j uint8 105 for i = 0; i < uc.usersGPPoolLen; i++ { 106 for j = 0; j < uc.usersPool[i].FreeID; j++ { 107 // TODO::: change finding loc algorithm!! 108 loc = uuid.GetFirstUint32(uc.usersPool[i].UserID[j]) % newPoolLen 109 newPool[loc].UserID[uc.usersPool[i].FreeID] = uc.usersPool[i].UserID[j] 110 newPool[loc].Conn[uc.usersPool[i].FreeID] = uc.usersPool[i].Conn[j] 111 uc.usersPool[i].FreeID++ 112 } 113 } 114 115 uc.usersPool = newPool 116 uc.usersPoolLen = newPoolLen 117 } 118 119 // registerNewPath use to register or overwrite a path in the related pool! 120 func (uc *userConnections) registerNewPath(conn *UserConnection, path []byte) { 121 var pathLen uint8 = uint8(len(conn.Path)) 122 var poolLen uint32 = uint32(len(uc.pathsPool[pathLen])) 123 var loc = crc32.ChecksumIEEE(conn.Path) % poolLen 124 125 // Check collision!! 126 var existingConn = uc.pathsPool[pathLen][loc] 127 if existingConn != nil && existingConn.UserID != conn.UserID { 128 poolLen = uc.expandPathPool(pathLen) 129 loc = crc32.ChecksumIEEE(conn.Path) % poolLen 130 } 131 132 uc.pathsPool[pathLen][loc] = conn 133 } 134 135 // registerNewUser use to register or overwrite a user in the related pool! 136 func (uc *userConnections) registerNewUser(conn *UserConnection) { 137 // TODO::: 138 } 139 140 // MakeNewUserConnectionReq is the request structure of MakeNewUserConnection() 141 type MakeNewUserConnectionReq struct { 142 UserID [16]byte 143 ThingID [16]byte 144 UserPublicKey [32]byte 145 Path []byte 146 MaxBandwidth uint64 147 Signature [256]byte 148 } 149 150 // MakeNewUserConnection use to make new connection! 151 func (uc *userConnections) MakeNewUserConnection(req *MakeNewUserConnectionReq) { 152 // TODO::: Check signature first! 153 154 var conns []*UserConnection 155 var conn *UserConnection 156 conns = uc.GetConnectionsByUserID(req.UserID) 157 // Check if just new way to exiting user in specific thing!! 158 if conns != nil { 159 var i int 160 var ln int = len(conns) 161 for i = 0; i < ln; i++ { 162 if conns[i].UserID == req.UserID && conns[i].ThingID == req.ThingID { 163 conn = conns[i] 164 break 165 } 166 } 167 } 168 169 if conn != nil { 170 conn.AlternativePath = append(conn.AlternativePath, req.Path) 171 uc.registerNewPath(conn, req.Path) 172 } else { 173 // TODO::: Check user can make new connection 174 175 conn = &UserConnection{ 176 UserID: req.UserID, 177 Path: req.Path, 178 ReversePath: chapar.ReversePath(req.Path), 179 ThingID: req.ThingID, 180 Status: routerConnectionStateOpen, 181 MaxBandwidth: req.MaxBandwidth, 182 PeerPublicKey: req.UserPublicKey, 183 Cipher: crypto.NewGCM(crypto.NewAES256([32]byte{})), 184 } 185 uc.RegisterConnection(conn) 186 } 187 } 188 189 // RegisterConnection use to register new connection in server connection pool!! 190 func (uc *userConnections) RegisterConnection(conn *UserConnection) { 191 uc.registerNewPath(conn, conn.Path) 192 uc.registerNewUser(conn) 193 } 194 195 // GetConnectionByPath use to get a connection by peer GP from connections pool!! 196 func (uc *userConnections) GetConnectionByPath(path []byte) (conn *UserConnection) { 197 var pathLen = len(path) 198 var poolLen uint32 = uint32(len(uc.pathsPool[pathLen])) 199 var loc = crc32.ChecksumIEEE(path) % poolLen 200 201 conn = uc.pathsPool[pathLen][loc] 202 return 203 } 204 205 // GetConnectionsByUserID use to get connections by peer UserID from connections pool!! 206 func (uc *userConnections) GetConnectionsByUserID(userID [16]byte) (conns []*UserConnection) { 207 // TODO::: change finding loc algorithm!! 208 var loc = uuid.GetFirstUint32(userID) % uc.usersPoolLen 209 210 var i uint8 211 for i = 0; i < uc.usersPool[loc].FreeID; i++ { 212 if uc.usersPool[loc].UserID[i] == userID { 213 conns = uc.usersPool[loc].Conn[i] 214 break 215 } 216 // check if connection is in not ready status 217 } 218 return 219 } 220 221 // GetConnectionByUserGPID use to get a connection by user GP ID part from connections pool!! 222 func (uc *userConnections) GetConnectionByUserGPID(userGPID uint32) (conn *UserConnection) { 223 // TODO::: change finding loc algorithm!! 224 var loc = userGPID % uc.usersGPPoolLen 225 226 var i uint8 227 for i = 0; i < uc.usersGPPool[loc].FreeID; i++ { 228 if uc.usersGPPool[loc].UserGPID[i] == userGPID { 229 conn = uc.usersGPPool[loc].Conn[i] 230 break 231 } 232 // check if connection is in not ready status 233 } 234 return 235 } 236 237 // CloseConnection use to un-register exiting connection in server connection pool!! 238 func (uc *userConnections) CloseConnection(conn *UserConnection) { 239 // TODO::: Check GC performance : delete connection vs just reset it and send it to pool of unused connection!! 240 var pathLen = len(conn.Path) 241 var poolLen uint32 = uint32(len(uc.pathsPool[pathLen])) 242 var loc = crc32.ChecksumIEEE(conn.Path) % poolLen 243 244 uc.pathsPool[pathLen][loc] = nil 245 246 loc = conn.UserGPID % uc.usersGPPoolLen 247 var eGPPool = uc.usersGPPool[loc] 248 var f = eGPPool.FreeID 249 var i uint8 250 for i = 0; i < f; i++ { 251 if eGPPool.UserGPID[i] == conn.UserGPID { 252 eGPPool.UserGPID[i] = 0 253 eGPPool.Conn[i] = nil 254 break 255 } 256 } 257 258 loc = uuid.GetFirstUint32(conn.UserID) % uc.usersPoolLen 259 var eUserPool = uc.usersPool[loc] 260 f = eUserPool.FreeID 261 for i = 0; i < f; i++ { 262 if eUserPool.UserID[i] == conn.UserID { 263 var conns = eUserPool.Conn[i] 264 var j = len(conns) - 1 265 for ; j >= 0; j-- { 266 if conns[j].UserGPID == conn.UserGPID { 267 // TODO::: is it worth to delete an item in middle of array!!? 268 conns[j] = nil 269 break 270 } 271 } 272 273 break 274 } 275 } 276 }