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  }