github.com/GeniusesGroup/libgo@v0.0.0-20220929090155-5ff932cb408e/chapar/frame.go (about)

     1  /* For license and copyright information please see LEGAL file in repository */
     2  
     3  package chapar
     4  
     5  import (
     6  	"../protocol"
     7  )
     8  
     9  const (
    10  	// MinFrameLen is minimum Chapar frame length
    11  	// 4 Byte Chapar header + 8 Byte min payload
    12  	MinFrameLen = 12
    13  	// MaxFrameLen is maximum Chapar frame length
    14  	MaxFrameLen = 8192
    15  
    16  	fixedHeaderLength      byte = 3 // without path part
    17  	maxHopCount            byte = 255
    18  	broadcastHopCount      byte = 0
    19  	maxBroadcastPayloadLen      = MaxFrameLen - (fixedHeaderLength + maxHopCount)
    20  )
    21  
    22  // MakeNewFrame makes new unicast||broadcast frame!
    23  func MakeNewFrame(nexHeaderID protocol.NetworkLinkNextHeaderID, path []byte, payload []byte) (frame []byte) {
    24  	var pathLen byte = byte(len(path))
    25  	if pathLen == 0 {
    26  		pathLen = maxHopCount // broadcast frame
    27  	}
    28  	var payloadLoc int = int(fixedHeaderLength + pathLen)
    29  	var frameLength int = payloadLoc + len(payload)
    30  	frame = make([]byte, frameLength)
    31  
    32  	SetHopCount(frame, pathLen)
    33  	SetNextHeader(frame, byte(nexHeaderID))
    34  	// Set path for unicast. it will not copy if path is 0 for broadcast frame as we want!
    35  	SetPath(frame, path)
    36  	// copy payload to frame
    37  	copy(frame[payloadLoc:], payload)
    38  	return
    39  }
    40  
    41  // CheckFrame checks frame for any bad situation!
    42  // Always check frame before use any other frame methods otherwise panic may occur!
    43  func CheckFrame(frame []byte) (err protocol.Error) {
    44  	var len = len(frame)
    45  	if len < MinFrameLen {
    46  		return ErrShortFrameLength
    47  	}
    48  	if len > MaxFrameLen {
    49  		return ErrLongFrameLength
    50  	}
    51  	return
    52  }
    53  
    54  // GetNextHop returns next hop number.
    55  func GetNextHop(frame []byte) byte {
    56  	return frame[0]
    57  }
    58  
    59  // IncrementNextHop sets received port number and increment NextHop number in frame!
    60  func IncrementNextHop(frame []byte, receivedPortNumber byte) {
    61  	// spec: https://github.com/GeniusesGroup/RFCs/blob/master/Chapar.md#rules
    62  	SetPortNum(frame, frame[0], receivedPortNumber)
    63  	frame[0]++
    64  }
    65  
    66  // GetHopCount returns the number of intermediate network devices indicate in frame.
    67  func GetHopCount(frame []byte) byte {
    68  	if IsBroadcastFrame(frame) {
    69  		return maxHopCount
    70  	}
    71  	return frame[1]
    72  }
    73  
    74  // SetHopCount writes given hop number to the frame.
    75  func SetHopCount(frame []byte, hopCount byte) {
    76  	frame[1] = hopCount
    77  }
    78  
    79  // IsBroadcastFrame checks frame is broadcast frame or not!
    80  // spec: https://github.com/GeniusesGroup/RFCs/blob/master/Chapar.md#frame-types
    81  func IsBroadcastFrame(frame []byte) bool {
    82  	return frame[1] == broadcastHopCount
    83  }
    84  
    85  // GetNextHeader returns next header ID of the frame.
    86  func GetNextHeader(frame []byte) byte {
    87  	return frame[2]
    88  }
    89  
    90  // SetNextHeader sets next header id in the frame.
    91  func SetNextHeader(frame []byte, linkHeaderID byte) {
    92  	frame[2] = linkHeaderID
    93  }
    94  
    95  // GetNextPortNum returns next port number set in the frame.
    96  func GetNextPortNum(frame []byte) byte {
    97  	return frame[fixedHeaderLength+GetNextHop(frame)]
    98  }
    99  
   100  // GetPortNum returns port number of given hop number.
   101  // First hopNum is hopNum==1 not hopNum==0. Don't read hopNum==0 due to it is use for broadcast frame.
   102  func GetPortNum(frame []byte, hopNum byte) byte {
   103  	return frame[fixedHeaderLength+hopNum]
   104  }
   105  
   106  // SetPortNum set given port number in given hop number!
   107  // First hopNum is hopNum==1 not hopNum==0. Don't set hopNum==0 due to it is use for broadcast frame.
   108  func SetPortNum(frame []byte, hopNum byte, portNum byte) {
   109  	frame[fixedHeaderLength+hopNum] = portNum
   110  }
   111  
   112  // GetPath gets frame path in all hops.
   113  func GetPath(frame []byte) []byte {
   114  	return frame[fixedHeaderLength : fixedHeaderLength+GetHopCount(frame)]
   115  }
   116  
   117  // SetPath sets given path in given the frame.
   118  func SetPath(frame []byte, path []byte) {
   119  	copy(frame[fixedHeaderLength:], path[:])
   120  }
   121  
   122  // GetReversePath gets frame path in all hops just in reverse.
   123  func GetReversePath(frame []byte) []byte {
   124  	return ReversePath(GetPath(frame))
   125  }
   126  
   127  // ReversePath returns a copy of given path in reverse.
   128  func ReversePath(path []byte) (ReversePath []byte) {
   129  	var i = len(path)
   130  	ReversePath = make([]byte, i)
   131  	i-- // Due to len & index mismatch
   132  	var j int
   133  	for i >= j {
   134  		ReversePath[i], ReversePath[j] = path[j], path[i]
   135  		i--
   136  		j++
   137  	}
   138  	return
   139  }
   140  
   141  // GetPayload returns payload.
   142  func GetPayload(frame []byte) []byte {
   143  	return frame[fixedHeaderLength+GetHopCount(frame):]
   144  }