github.com/geniusesgroup/libgo@v0.0.0-20220713101832-828057a9d3d4/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 }