github.com/geniusesgroup/libgo@v0.0.0-20220713101832-828057a9d3d4/ChaparKhane/router-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  )
    11  
    12  // routerConnections store pools of connection to retrieve in many ways!
    13  type routerConnections struct {
    14  	old            *routerConnection        // use just in expanding
    15  	pathsPool      [254][]*routerConnection // use 254 due to Chapar frame with TotalHop = 0||1 handled before pass it here!!
    16  	routersPoolLen uint32
    17  	routersPool    []*routerConnection // It will work due to routers IDs is in increment manner!
    18  }
    19  
    20  // TODO::: convert []*routerConnection to below structure
    21  type pathPool struct {
    22  	Len uint32
    23  	Add uintptr
    24  }
    25  
    26  func (rc *routerConnections) init() {
    27  	// TotalHop = 1 or One hop frame use just in p2p networks and not pass here!!
    28  	// TotalHop = 2 or Two hop implement by just one Chapar switch device!
    29  	rc.pathsPool[0] = make([]*routerConnection, 256)
    30  	// TotalHop > 2 or More than two hop implement by more than one Chapar switch device!
    31  	var i uint8
    32  	for i = 1; i < 255; i++ {
    33  		rc.pathsPool[i] = make([]*routerConnection, 2048)
    34  	}
    35  
    36  	// TODO::: use exiting router number instead of below 1024 number
    37  	rc.routersPool = make([]*routerConnection, 1024)
    38  	rc.routersPoolLen = 1024
    39  }
    40  
    41  func (rc *routerConnections) expandPathPool(hopNum uint8) (newPoolLen uint32) {
    42  	var poolLen uint32 = uint32(len(rc.pathsPool[hopNum]))
    43  	newPoolLen = poolLen * 2
    44  
    45  	var new = make([]*routerConnection, newPoolLen)
    46  
    47  	// Copy old paths
    48  	var exitingConn *routerConnection
    49  	var loc uint32
    50  	var i uint32
    51  	for i = 0; i < poolLen; i++ {
    52  		exitingConn = rc.pathsPool[hopNum][i]
    53  		if exitingConn != nil {
    54  			loc = crc32.ChecksumIEEE(exitingConn.Path) % newPoolLen
    55  			new[loc] = exitingConn
    56  		}
    57  	}
    58  	rc.pathsPool[hopNum] = new
    59  
    60  	return
    61  }
    62  
    63  func (rc *routerConnections) expandRoutersPool() {
    64  	rc.routersPool = append(rc.routersPool, make([]*routerConnection, rc.routersPoolLen)...)
    65  	rc.routersPoolLen *= 2
    66  }
    67  
    68  // registerNewPath use to register or overwrite a path in the related pool!
    69  func (rc *routerConnections) registerNewPath(conn *routerConnection, path []byte) {
    70  	var pathLen uint8 = uint8(len(conn.Path))
    71  	var poolLen uint32 = uint32(len(rc.pathsPool[pathLen]))
    72  	var loc = crc32.ChecksumIEEE(conn.Path) % poolLen
    73  
    74  	// Check collision!!
    75  	var exitingConn = rc.pathsPool[pathLen][loc]
    76  	if exitingConn != nil && exitingConn.RouterID != conn.RouterID {
    77  		poolLen = rc.expandPathPool(pathLen)
    78  		loc = crc32.ChecksumIEEE(conn.Path) % poolLen
    79  	}
    80  
    81  	rc.pathsPool[pathLen][loc] = conn
    82  }
    83  
    84  // registerNewRouter use to register or overwrite the given router in the related pool!
    85  func (rc *routerConnections) registerNewRouter(conn *routerConnection) {
    86  	if conn.RouterID > rc.routersPoolLen {
    87  		rc.expandRoutersPool()
    88  	}
    89  
    90  	rc.routersPool[conn.RouterID] = conn
    91  }
    92  
    93  // MakeNewRouterConnectionReq is the request structure of MakeNewRouterConnection()
    94  type MakeNewRouterConnectionReq struct {
    95  	RouterID     uint32
    96  	Path         []byte
    97  	MaxBandwidth uint64
    98  	Signature    [256]byte
    99  }
   100  
   101  // MakeNewRouterConnection use to make connection from router advertisement!
   102  func (rc *routerConnections) MakeNewRouterConnection(req *MakeNewRouterConnectionReq) {
   103  	// TODO::: Check signature first!
   104  
   105  	var conn *routerConnection
   106  	conn = rc.GetConnectionByRouterID(req.RouterID)
   107  	// Check if just new way to exiting router!!
   108  	if conn != nil && conn.RouterID == req.RouterID {
   109  		conn.AlternativePath = append(conn.AlternativePath, req.Path)
   110  		rc.registerNewPath(conn, req.Path)
   111  	} else {
   112  		conn = &routerConnection{
   113  			RouterID:     req.RouterID,
   114  			Path:         req.Path,
   115  			ReversePath:  chapar.ReversePath(req.Path),
   116  			Status:       routerConnectionStateOpen,
   117  			MaxBandwidth: req.MaxBandwidth,
   118  			Cipher:       crypto.NewGCM(crypto.NewAES256([32]byte{})),
   119  		}
   120  		rc.RegisterConnection(conn)
   121  	}
   122  }
   123  
   124  // RegisterConnection use to register new connection in routerConnections pools!!
   125  func (rc *routerConnections) RegisterConnection(conn *routerConnection) {
   126  	rc.registerNewPath(conn, conn.Path)
   127  	rc.registerNewRouter(conn)
   128  }
   129  
   130  // GetConnectionByPath use to get a connection by path from routerConnections pool!!
   131  func (rc *routerConnections) GetConnectionByPath(path []byte) (conn *routerConnection) {
   132  	var pathLen = len(path)
   133  	var poolLen uint32 = uint32(len(rc.pathsPool[pathLen]))
   134  	var loc = crc32.ChecksumIEEE(path) % poolLen
   135  
   136  	conn = rc.pathsPool[pathLen][loc]
   137  	return
   138  }
   139  
   140  // GetConnectionByRouterID use to get a connection by routerID from routerConnections pool!!
   141  func (rc *routerConnections) GetConnectionByRouterID(routerID uint32) (conn *routerConnection) {
   142  	// respect routersPool length otherwise panic will occur!
   143  	if routerID <= rc.routersPoolLen {
   144  		conn = rc.routersPool[routerID]
   145  	}
   146  	return
   147  }
   148  
   149  // CloseConnection use to un-register exiting connection in server connection pool!!
   150  func (rc *routerConnections) CloseConnection(conn *routerConnection) {
   151  	// TODO::: Check GC performance : delete connection vs just reset it and send it to pool of unused connection!!
   152  	var pathLen = len(conn.Path)
   153  	var poolLen uint32 = uint32(len(rc.pathsPool[pathLen]))
   154  	var loc = crc32.ChecksumIEEE(conn.Path) % poolLen
   155  
   156  	rc.pathsPool[pathLen][loc] = nil
   157  	rc.routersPool[conn.RouterID] = nil
   158  }