/// <summary> /// Encode command frame /// </summary> /// <param name="frame">target buffer</param> /// <returns>True on success</returns> public bool WriteToFrame(Frame frame) { if (frame == null || frame.LengthDataAvail < _lengthMax || frame.LengthDataUsed != 0) return false; frame.ReserveHeader(frame.LengthHeaderAvail + 1); // increase header space by one byte frame.AllocBack(_lengthMax - 1); // reserve space without command type, so payload is at 0..n-1 EncodePayload(frame); frame.AllocFront(1); frame.Write(0, (byte)_type); return true; }
/// <summary> /// Computes CRC-CCITT for the frame /// </summary> /// <param name="frame"></param> /// <returns></returns> public static UInt16 CalcCrc16Ccitt(Frame frame) { UInt16 crc = 0; // initial value int n = frame.LengthDataUsed; for (int i = 0; i < n; i++) { crc = (UInt16)(_crc16CcitTable[(crc ^ frame.ReadByte(i)) & 0xff] ^ (crc >> 8)); } return crc; }
public TaskDataRequest( MacAddressingMode srcAddrMode, MacAddress dstAddr, UInt16 dstPANId, Frame msdu, Byte msduHandle, TxOptions options, SecurityOptions securityOptions, DataConfirmHandler handler) : base(TaskType.DataRequest) { this.srcAddrMode = srcAddrMode; this.dstAddr = dstAddr; this.dstPANId = dstPANId; this.msdu = msdu; this.msduHandle = msduHandle; this.options = options; this.securityOptions = securityOptions; this.handler = handler; }
public bool WriteToFrame(Frame frame) { int len = Length(); if (frame == null || frame.LengthDataAvail < len) return false; frame.AllocBack(len); int offset = 0; frame.Write(offset, (byte)Message.Report); offset++; for (int i = 0; i < nodeCount; i++) { frame.Write(offset, nodes[i].addr); offset += 2; frame.Write(offset, nodes[i].rxBps); offset += 4; } return true; }
void phy_DataIndicationFlash(IPhyDataSap sender, Frame frame, byte linkQuality) { leds.color = Leds.Color.Green; byte[] b = new byte[2]; frame.ReadBytes(b, 0, frame.LengthDataUsed - 2, 2); uint u = ((uint)(b[0] << 8)) | b[1]; Frame.Release(ref frame); leds.color = Leds.Color.Off; }
void phy_DataIndicationDummy(IPhyDataSap sender, Frame frame, byte linkQuality) { Frame.Release(ref frame); }
/// <summary> /// Encode beacon into frame /// </summary> /// <param name="frame">target frame</param> /// <returns>True on success</returns> public bool WriteToFrame(Frame frame) { int len = Length(); if (frame == null || frame.LengthDataAvail < len || frame.LengthDataUsed > 0) return false; if (payload != null) len -= payload.LengthDataUsed; frame.AllocBack(len); int offset = 0; // 7.2.2.1.2 Superframe Specification field int i; i = (beaconOrder & 0xf) | ((superframeOrder & 0xf) << 4) | ((finalCapSlot & 0xf) << 8) | ((batteryLifeExtension & 1) << 12) | ((panCoordinator & 1) << 14) | ((associationPermit & 1) << 15); frame.Write(offset, (UInt16)i); offset += 2; // 7.2.2.1.3 GTS Specification field if (gtsLength > 7) return false; // assert i = (gtsLength & 7) | ((gtsPermit & 1) << 7); frame.Write(offset, (Byte)i); offset += 1; // 7.2.2.1.4 GTS Directions field if (gtsLength > 0) { i = (gtsDirectionsMask & 0x7F); // 7 bits frame.Write(offset, (Byte)i); offset += 1; } // 7.2.2.1.5 GTS List field for (int k = 0; k < gtsLength; k++) { frame.Write(offset, gtsDescriptor[k].deviceShortAddr); offset += 2; i = (gtsDescriptor[k].gtsStartingSlot & 0xF) | ((gtsDescriptor[k].gtsLength & 0xF) << 4); frame.Write(offset, (Byte)i); offset++; } // 7.2.2.1.6 Pending Address Specification field i = (pendingShort & 7) | ((pendingExt & 7) << 4); frame.Write(offset, (Byte)i); offset++; // 7.2.2.1.7 Address List field for (int k = 0; k < pendingShort; k++) { frame.Write(offset, shortAddrPending[k]); offset += 2; } for (int k = 0; k < pendingExt; k++) { frame.Write(offset, extAddrPending[k]); offset += 8; } // 7.2.2.1.8 Beacon Payload field if (payload != null) frame.WriteToBack(payload); return true; }
/// <summary> /// Decode an ACK fragment payload /// </summary> /// <param name="payload">payload</param> /// <param name="lastFragmentSeqNumberReceived">last fragment sequence number received</param> /// <param name="fragmentMissingTable">table of indices of the missing fragments</param> public static void DecodeAckPayload(ref Frame payload, out byte lastFragmentSeqNumberReceived, out BitArray fragmentMissingTable) { if (payload.LengthDataUsed < 2) throw new ArgumentException("payload content too small", "payload"); lastFragmentSeqNumberReceived = payload.ReadByte(0); int nbFragments = (int)payload.ReadByte(1); byte[] byteArray = new byte[payload.LengthDataUsed - 2]; payload.ReadBytes(byteArray, 0, 2, payload.LengthDataUsed - 2); fragmentMissingTable = BitArray.FromByteArray(nbFragments, byteArray); Frame.Release(ref payload); }
/// <summary> /// ReadFromFrame frame type /// </summary> /// <param name="frame">frame containing encoded Mac SDU</param> /// <returns>type, reserved value on error</returns> static public bool GetType(Frame frame, out Type type) { if (frame != null && frame.LengthDataUsed >= 2) { FCS fcs = new FCS(); fcs.Value = frame.ReadUInt16Canonical(0); type = fcs.Type; return true; } type = Type.Ack; // any value return false; }
/// <summary> /// Encodes the header into the front of the frame /// </summary> /// <param name="frame">The header is placed at the front of this frame</param> /// <returns>True on success, false if the frame is too small or the header is invalid</returns> public bool WriteToFrameHeader(Frame frame) { int len = Length(); if (frame.LengthHeaderAvail < len) return false; frame.AllocFront(len); frame.WriteCanonical(0, fcs.Value); frame.Write(2, seqNo); int offset = 3; AddressingMode dstMode = fcs.DstAddrMode; AddressingMode srcMode = fcs.SrcAddrMode; bool panIdCompression = fcs.PanIdCompression; if (dstMode == AddressingMode.Reserved || srcMode == AddressingMode.Reserved || (panIdCompression && dstMode == AddressingMode.None)) return false; if (dstMode != AddressingMode.None) { // dstPanId frame.WriteCanonical(offset, dstPanId); offset += 2; } if (dstMode == AddressingMode.Short) { // dstAddrShort frame.WriteCanonical(offset, dstAddrShort); offset += 2; } if (dstMode == AddressingMode.Extended) { // dstAddrShort frame.WriteCanonical(offset, dstAddrExt); offset += 8; } if (srcMode != AddressingMode.None && !panIdCompression) { // srcPanId frame.WriteCanonical(offset, srcPanId); offset += 2; } if (srcMode == AddressingMode.Short) { // dstAddrShort frame.WriteCanonical(offset, srcAddrShort); offset += 2; } if (srcMode == AddressingMode.Extended) { // dstAddrShort frame.WriteCanonical(offset, srcAddrExt); offset += 8; } // FIXME: secHeader return true; }
/// <summary> /// Append to back of this frame /// </summary> /// <param name="frame">source frame</param> public void WriteToBack(Frame frame) { AppendToBack(frame, 0, frame.LengthDataUsed); }
/// <summary> /// Append to front of this frame /// </summary> /// <param name="frame">source frame</param> public void WriteToFront(Frame frame) { AppendToFront(frame, 0, frame.LengthDataUsed); }
/// <summary> /// Copy part of frame into another frame /// </summary> /// <param name="toFrame">frame to write to</param> /// <param name="indexToFrame">index into toFrame</param> /// <param name="indexFrame">index into this frame</param> /// <param name="nbBytes">amount of bytes</param> public void ReadBytes(Frame toFrame, int indexToFrame, int indexFrame, int nbBytes) { SanityCheck(false); if (toFrame.lenOffset + nbBytes > toFrame.LengthDataUsed) throw new System.ArgumentOutOfRangeException(); ReadBytes(toFrame.buf, indexToFrame, indexFrame, nbBytes); }
/// <summary> /// Append part of frame to back of this frame /// </summary> /// <param name="srcFrame">the frame to append</param> /// <param name="index">index into srcFrame</param> /// <param name="nbBytes">amount of bytes</param> public void AppendToBack(Frame srcFrame, int index, int nbBytes) { AppendToBack(srcFrame.buf, srcFrame.lenOffset + index, nbBytes); }
private void MacBeaconNotifyIndication( IMacMgmtSap sender, ushort BSN, PanDescriptor panDescriptor, ushort[] pendingShortAddrs, UInt64[] pendingExtendedAddrs, Frame beaconPayload) { _mgmt.MacBeaconNotifyIndication(sender, BSN, panDescriptor, pendingShortAddrs, pendingExtendedAddrs, beaconPayload); }
public void HandleDataIndication6Low(UInt16 origAddr, UInt16 targetAddr, ref Frame sdu) { DataIndicationHandler ind = _dataIndicationHandler6Low; if (ind != null) { ind.Invoke(this, origAddr, targetAddr, sdu); sdu = null; } }
public bool ReadFromFrame(Frame frame) { if (frame == null || frame.LengthDataUsed < 1) return false; byte header = frame.ReadByte(0); if (header != (byte)Message.Report) return false; nodeCount = (frame.LengthDataUsed - 1) / 6; if (frame.LengthDataUsed != Length()) return false; frame.DeleteFromFront(1); nodes = new Node[nodeCount]; for (int i = 0; i < nodeCount; i++) { nodes[i].addr = frame.ReadUInt16(0); frame.DeleteFromFront(2); nodes[i].rxBps = frame.ReadUInt32(0); frame.DeleteFromFront(4); } return true; }
/// <summary> /// add frame to queue. return true on success /// </summary> /// <param name="item"></param> /// <returns></returns> public bool AddFrame(ref Frame item) { if (_frameCount == _frames.Length) return false; _frameCount++; _frames[_tail] = item; item = null; _tail = (_tail + 1) % _frames.Length; return true; }
/// <summary> /// Decodes a header /// </summary> /// <param name="frame">The frame containing the header</param> /// <param name="removeHeader">If true, the header will be removed from the frame after decoding</param> /// <returns>True on success, false on decoding error</returns> public bool ReadFromFrameHeader(Frame frame, bool removeHeader) { int len = 2 + 1; // fcs + seqNo // check minimum length if (frame.LengthDataUsed < len) return false; fcs.Value = frame.ReadUInt16Canonical(0); seqNo = frame.ReadByte(2); // calculate variable length len = Length(); if (frame.LengthDataUsed < len) return false; AddressingMode dstMode = fcs.DstAddrMode; AddressingMode srcMode = fcs.SrcAddrMode; bool panIdCompression = fcs.PanIdCompression; int offset = 3; if (dstMode != AddressingMode.None) { // dstPanId dstPanId = frame.ReadUInt16Canonical(offset); offset += 2; } if (dstMode == AddressingMode.Short) { // dstAddrShort dstAddrShort = frame.ReadUInt16Canonical(offset); offset += 2; } if (dstMode == AddressingMode.Extended) { // dstAddrShort dstAddrExt = frame.ReadUInt64Canonical(offset); offset += 8; } if (srcMode != AddressingMode.None && !panIdCompression) { // srcPanId srcPanId = frame.ReadUInt16Canonical(offset); offset += 2; } if (srcMode == AddressingMode.Short) { // dstAddrShort srcAddrShort = frame.ReadUInt16Canonical(offset); offset += 2; } if (srcMode == AddressingMode.Extended) { // dstAddrShort srcAddrExt = frame.ReadUInt64Canonical(offset); offset += 8; } // FIXME: secHeader if (removeHeader) frame.DeleteFromFront(len); return true; }
/// <summary> /// Release a frame, moving it into memory pool /// </summary> /// <param name="frame">The frame to release, will be set to null</param> public void Release(ref Frame frame) { if (frame == null) return; int frameSize = GetNormalizedSize(frame.LengthBuffer); if (frameSize == -1 || frameSize != frame.LengthBuffer) return; // if frame is too large for pool or length is non-standard, dispose lock (_lock) { int idx = GetPoolIndex(frameSize, true); Queue queue = _framePool[idx] as Queue; if (queue == null) throw new System.ApplicationException(); frame.ReserveHeader(0); // clear frame frame.SanityCheck(false); frame.released = true; bool ignore = queue.AddFrame(ref frame); } frame = null; }
/// <summary> /// Create a frame containing a DATA fragment /// </summary> /// <param name="messageSeqNumber">message sequence number</param> /// <param name="fragmentSeqNumber">fragment sequence number</param> /// <param name="isBroadcast">true if fragment is broadcasted</param> /// <param name="requireAck">true if an acknowledgment is required</param> /// <param name="pduSize">max size for the sublayer payload</param> /// <param name="reservedTail">max size for the sublayer tail</param> /// <param name="reservedHead">max size for the sublayer header</param> /// <param name="nbFragments">number of DATA fragments in the message</param> /// <param name="fragmentIndex">index of the DATA fragment</param> /// <param name="payloadData">payload</param> /// <param name="indexPayloadData">start index in the payload </param> /// <param name="nbBytes">number of bytes in the payload</param> /// <returns>the generated frame</returns> public static Frame CreateDataFrame(byte messageSeqNumber, byte fragmentSeqNumber, bool isBroadcast, bool requireAck, int pduSize, int reservedTail, int reservedHead, byte nbFragments, byte fragmentIndex, Frame payloadData, int indexPayloadData, int nbBytes) { if (pduSize < 2 + 2 + nbBytes) throw new ArgumentException("pdu size is too small", "pduSize"); FragmentHeader header = new FragmentHeader(FragmentType.DATA, messageSeqNumber, requireAck, fragmentSeqNumber); Frame frame = Frame.GetFrame(reservedHead + reservedTail + 2 + 2 + nbBytes); frame.ReserveHeader(reservedHead); UInt16 serializedHdr = FragmentHeader.Encode(header); frame.AllocBack(4); frame.Write(0, serializedHdr); frame.Write(2, nbFragments); frame.Write(3, fragmentIndex); frame.AppendToBack(payloadData, indexPayloadData, nbBytes); return frame; }
/// <summary> /// Return a frame to the memory pool /// </summary> /// <param name="frame">The frame to release. Will be set to null.</param> public static void Release(ref Frame frame) { #if USE_POOL instance.Release(ref frame); #else frame = null; #endif }
/// <summary> /// Decode DATA fragment payload /// </summary> /// <param name="payload">payload</param> /// <param name="nbFragments">number of fragments in the messge</param> /// <param name="fragmentIndex">index of the fragment</param> /// <param name="data">payload of the data fragment</param> public static void DecodeDataPayload(ref Frame payload, out byte nbFragments, out byte fragmentIndex, out Frame data) { if (payload.LengthDataUsed < 2) throw new ArgumentException("payload content too small", "payload"); nbFragments = payload.ReadByte(0); fragmentIndex = payload.ReadByte(1); if (nbFragments == 0) throw new ArgumentOutOfRangeException("nbFragments"); if (fragmentIndex >= nbFragments) throw new ArgumentOutOfRangeException("fragmentId"); payload.DeleteFromFront(2); data = payload; payload = null; }
/// <summary> /// handler for mac beacon notifications /// </summary> /// <param name="sender"></param> /// <param name="BSN"></param> /// <param name="panDescriptor"></param> /// <param name="pendingShortAddrs"></param> /// <param name="pendingExtendedAddrs"></param> /// <param name="beaconPayload"></param> public void MacBeaconNotifyIndication( IMacMgmtSap sender, ushort BSN, PanDescriptor panDescriptor, ushort[] pendingShortAddrs, UInt64[] pendingExtendedAddrs, Frame beaconPayload) { if (!_scanning) return; ScanResultInternal res = new ScanResultInternal(); res.panDescriptor = panDescriptor; res.isMeshProtocol = false; if (beaconPayload.LengthDataUsed == 8) { UInt64 meshId = beaconPayload.ReadUInt64Canonical(0); if (meshId == NetworkLayer.cMeshId) { res.isMeshProtocol = true; } Frame.Release(ref beaconPayload); } lock (_scanResults) { _scanResults.Add(res); } }
/// <summary> /// Decode beacon from frame /// </summary> /// <param name="frame"></param> /// <returns></returns> public bool ReadFromFrame(ref Frame frame) { if (frame == null) return false; // 7.2.2.1.2 Superframe Specification field if (frame.LengthDataUsed < 3) return false; int i = (int)frame.ReadUInt16(0); beaconOrder = (Byte)(i & 0xf); superframeOrder = (Byte)((i >> 4) & 0xf); finalCapSlot = (Byte)((i >> 8) & 0xf); batteryLifeExtension = (Byte)((i >> 12) & 1); panCoordinator = (Byte)((i >> 14) & 1); associationPermit = (Byte)((i >> 15) & 1); // 7.2.2.1.3 GTS Specification field i = (int)frame.ReadByte(2); gtsLength = (Byte)(i & 7); gtsPermit = (Byte)((i >> 7) & 1); frame.DeleteFromFront(3); // 7.2.2.1.4 GTS Directions field gtsDirectionsMask = 0; if (gtsLength > 0) { if (frame.LengthDataUsed < 1) return false; i = (int)frame.ReadByte(0); gtsDirectionsMask = (Byte)(i & 0x7F); frame.DeleteFromFront(1); } // 7.2.2.1.5 GTS List field if (frame.LengthDataUsed < 3 * gtsLength) return false; gtsDescriptor = new GtsDescriptor[gtsLength]; for (int k = 0; k < gtsLength; k++) { gtsDescriptor[k].deviceShortAddr = frame.ReadUInt16(0); i = (int)frame.ReadByte(2); gtsDescriptor[k].gtsStartingSlot = (Byte)(i & 0xF); gtsDescriptor[k].gtsLength = (Byte)((i >> 4) & 0xF); frame.DeleteFromFront(3); } // 7.2.2.1.6 Pending Address Specification field if (frame.LengthDataUsed < 1) return false; i = (int)frame.ReadByte(0); pendingShort = (i & 7); pendingExt = ((i >> 4) & 7); frame.DeleteFromFront(1); // 7.2.2.1.7 Address List field if (frame.LengthDataUsed < pendingShort * 2 + pendingExt * 8) return false; shortAddrPending = new UInt16[pendingShort]; extAddrPending = new UInt64[pendingExt]; for (int k = 0; k < pendingShort; k++) { shortAddrPending[k] = frame.ReadUInt16(0); frame.DeleteFromFront(2); } for (int k = 0; k < pendingExt; k++) { extAddrPending[k] = frame.ReadUInt64(0); frame.DeleteFromFront(8); } // 7.2.2.1.8 Beacon Payload field if (frame.LengthDataUsed > 0) { payload = frame; frame = null; } else { payload = null; Frame.Release(ref frame); } return true; }
public bool WriteToFrame(Frame frame) { int len = Length(); if (frame == null || frame.LengthDataAvail < len) return false; frame.AllocBack(len); int offset = 0; frame.Write(offset, (byte)Message.Neighbors); offset++; for (int i = 0; i < neighborCount; i++) { frame.Write(offset, neighbors[i].shortAdr); offset += 2; frame.Write(offset, neighbors[i].lqi); offset += 1; } return true; }
void phy_DataIndicationAqc(IPhyDataSap sender, Frame frame, byte linkQuality) { byte[] bResp = new byte[128]; int i = frame.buf[4]; int mtu, head, tail; phy.GetMtuSize(out mtu, out head, out tail); Status status; m_RespFrame.ReserveHeader(head); int cInd = -1; ushort u = (ushort)(1 << 0) | // m_RespFrame type: data (0 << 3) | // security: none (0 << 4) | // m_RespFrame pending: none (1 << 5) | // ack request: true (1 << 6) | // pan id compression: true (2 << 10) | // dst addr: short addr (2 << 14); // src addr: short addr bResp[++cInd] = (byte)(u & 0xFF); bResp[++cInd] = (byte)(u >> 8); // Append sequence number. bResp[++cInd] = (byte)i; // seq no u = 1; // pan id bResp[++cInd] = (byte)(u & 0xFF); bResp[++cInd] = (byte)(u >> 8); u = 2; bResp[++cInd] = (byte)(u & 0xFF); bResp[++cInd] = (byte)(u >> 8); u = 3; bResp[++cInd] = (byte)(u & 0xFF); bResp[++cInd] = (byte)(u >> 8); bResp[++cInd] = 0xBE; bResp[++cInd] = 0xEF; bResp[++cInd] = 0xDE; bResp[++cInd] = 0xAD; // dead beef m_RespFrame.AppendToBack(bResp, 0, cInd + 1 + 100); // payload do { phy.DataRequest(m_RespFrame, out status); } while (status != Status.Success); DateTime curTime = DateTime.Now; Debug.Print("Response " + i + " is sent at " + curTime.Second + ":" + curTime.Millisecond); TimeSpan printTime = DateTime.Now - curTime; Debug.Print("Print Takes " + printTime); Frame.Release(ref frame); }
public bool ReadFromFrame(Frame frame) { if (frame == null || frame.LengthDataUsed < 1) return false; byte header = frame.ReadByte(0); if (header != (byte)Message.Neighbors) return false; neighborCount = (frame.LengthDataUsed - 1) / 3; if (frame.LengthDataUsed != Length()) return false; frame.DeleteFromFront(1); neighbors = new Neighbor[neighborCount]; for (int i = 0; i < neighborCount; i++) { neighbors[i].shortAdr = frame.ReadUInt16(0); frame.DeleteFromFront(2); neighbors[i].lqi = frame.ReadByte(0); frame.DeleteFromFront(1); } return true; }
void phy_DataIndicationDump(IPhyDataSap sender, Frame frame, byte linkQuality) { leds.color = Leds.Color.Green; string s = "recv: "; for (int i = 0; i < frame.LengthDataUsed; i++) { byte b = frame.ReadByte(i); s += HexConverter.ConvertUintToHex(b, 2) + " "; } Debug.Print(s); Frame.Release(ref frame); leds.color = Leds.Color.Off; }
private void DataIndicationHandler( object sender, UInt16 source, UInt16 targetShortAddr, Frame frame) { lock (_msgReport) { Message msg = (Message)frame.ReadByte(0); switch (msg) { case Message.Data: { if (_testMode) { _monitor.Print("received frame from 0x" + HexConverter.ConvertUintToHex(source, 4) + ", sduHandle=" + frame.ReadByte(1) + ", len=" + frame.LengthDataUsed + " bytes"); } for (int i = 0; i < _msgReport.nodeCount; i++) { if (_msgReport.nodes[i].addr == source) { _msgReport.nodes[i].rxBps += (UInt32)frame.LengthDataUsed; return; } } if (_msgReport.nodeCount < _msgReport.nodes.Length) { _msgReport.nodes[_msgReport.nodeCount].addr = source; _msgReport.nodes[_msgReport.nodeCount].rxBps = (UInt32)frame.LengthDataUsed; _msgReport.nodeCount++; } break; } case Message.Report: { MsgReport rep = new MsgReport(); if (rep.ReadFromFrame(frame)) { if (_testMode) { _monitor.Print("Report from node 0x" + HexConverter.ConvertUintToHex(source, 4) + ":"); for (int i = 0; i < rep.nodeCount; i++) { _monitor.Print(" " + rep.nodes[i].rxBps + " bytes per second from 0x" + HexConverter.ConvertUintToHex(rep.nodes[i].addr, 4)); } } if (_coordinator) { StatusHandleReport(source, rep); } } break; } case Message.Neighbors: { MsgNeighbors neigh = new MsgNeighbors(); if (neigh.ReadFromFrame(frame)) { if (_testMode) { _monitor.Print("Neighbors from node 0x" + HexConverter.ConvertUintToHex(source, 4) + ":"); for (int i = 0; i < neigh.neighborCount; i++) { _monitor.Print(" 0x" + HexConverter.ConvertUintToHex(neigh.neighbors[i].shortAdr, 4) + ": " + neigh.neighbors[i].lqi); } } if (_coordinator) { StatusHandleNeighbors(source, neigh); } } break; } } } Frame.Release(ref frame); }