public void DataRequest( UInt16 targetAddr, ref Frame sdu, Byte sduHandle, DataConfirmHandler handler) { if (targetAddr == _addrShort) { // deliver frame to ourself if (handler != null) handler.Invoke(_net, sduHandle, Status.Success); _data.HandleDataIndication(targetAddr, targetAddr, ref sdu); } else { // encapsulate and sent as 6LoWPAN Message.Data data = new Message.Data(); if (data.WriteToFrameHeader(sdu)) { DataRequest6LoWPAN(targetAddr, ref sdu, sduHandle, handler); } else { if (handler != null) handler.Invoke(_net, sduHandle, Status.InvalidFrame); } } Frame.Release(ref sdu); }
public void DataRequest( MacAddressingMode srcAddrMode, MacAddress dstAddr, UInt16 dstPanId, ref Frame msdu, Byte msduHandle, TxOptions options, SecurityOptions securityOptions, DataConfirmHandler handler) { TaskDataRequest task = new TaskDataRequest( srcAddrMode, dstAddr, dstPanId, msdu, msduHandle, options, securityOptions, handler); if (!_taskQueue.Add(task)) { Frame.Release(ref msdu); if (handler != null) { handler.Invoke(this, msduHandle, MacEnum.Congested); } } msdu = null; // in any case, remove frame ownership from caller }
/// <summary> /// Send 6LoWPAN SDU to another device. /// SDU must begin with a valid dispatch value and not contain any mesh header or brodcast header. /// </summary> /// <param name="targetShortAddr">targetAddr node, use 0xFFFF for broadcasting</param> /// <param name="sdu">data to send. Must have sufficient space in head/tail as indicated by GetFrameHeaders.</param> /// <param name="sduHandle">user-defined handle that is provided in result handler to identify the sdu.</param> /// <param name="handler">handler for result</param> public void DataRequest6Low( UInt16 targetShortAddr, ref Frame sdu, Byte sduHandle, DataConfirmHandler handler) { _route.DataRequest6LoWPAN(targetShortAddr, ref sdu, sduHandle, handler); }
/// <summary> /// Constructor /// </summary> /// <param name="targetShortAddr">destination short address</param> /// <param name="sdu">data to send</param> /// <param name="sduHandle">handle associated to sdu</param> /// <param name="handler">handler used to notify when message transmission is finished</param> public DataRequestItem(ushort targetShortAddr, ref Frame sdu, byte sduHandle, DataConfirmHandler handler) { _targetShortAddress = targetShortAddr; _sdu = sdu; sdu = null; // take ownership of the frame _sduHandle = sduHandle; _handler = handler; }
private void MacDataRequest( UInt16 nextHopAddr, ref Frame sdu, Byte sduHandle, DataConfirmHandler handler) { MacDataRequestReal(false, nextHopAddr, 0, ref sdu, sduHandle, handler); }
/// <summary> /// discard queued data at local node /// </summary> /// <param name="target">target node of message</param> /// <param name="sduHandle">sdu handle of message</param> /// <param name="handler">confirmation handler provided for message</param> /// <param name="isControlMsg">true if message is control message</param> public void DataRequestTimeout( UInt16 target, Byte sduHandle, DataConfirmHandler handler, bool isControlMsg) { if (handler != null) handler.Invoke(_net, sduHandle, Status.NoRoute); }
/// <summary> /// Send SDU to another device. /// </summary> /// <param name="targetShortAddr">targetAddr node, use 0xFFFF for broadcasting</param> /// <param name="sdu">data to send. Must have sufficient space in head/tail as indicated by GetFrameHeaders.</param> /// <param name="sduHandle">user-defined handle that is provided in result handler to identify the sdu.</param> /// <param name="handler">handler for result</param> public void DataRequest( UInt16 targetShortAddr, ref Frame sdu, Byte sduHandle, DataConfirmHandler handler) { #if USE_FRAG _frag.DataRequest(targetShortAddr, ref sdu, sduHandle, handler); #else _route.DataRequest(targetShortAddr, ref sdu, sduHandle, handler); #endif }
public void DataRequest6LoWPAN( UInt16 targetAddr, ref Frame sdu, Byte sduHandle, DataConfirmHandler handler) { Status result = Status.Success; if (sdu == null || sdu.LengthHeaderAvail < _netHeader6Low || sdu.LengthDataAvail < _netTailer6Low || sdu.LengthDataUsed > _netMtu6Low) { result = Status.InvalidFrame; } else if (!_isRunning) { result = Status.NotRunning; } else { if (targetAddr == _addrShort) { // deliver frame to ourself if (handler != null) handler.Invoke(_net, sduHandle, Status.Success); _data.HandleDataIndication(targetAddr, targetAddr, ref sdu); } else { // send frame to another node if (IsMulticast(targetAddr)) { SendData(_addrShort, targetAddr, cBroadcastShortAddr, ref sdu, sduHandle, handler); } else { // unicast _routingTable.DataRequest(targetAddr, ref sdu, sduHandle, handler, false); } } } if (result != Status.Success) { // perform callback if (handler != null) handler.Invoke(_net, sduHandle, result); } Frame.Release(ref sdu); }
/// <summary> /// trigger data transmission from local node /// </summary> /// <param name="targetAddr">target node</param> /// <param name="nextHopAddr">next hop address</param> /// <param name="sdu">data to send</param> /// <param name="sduHandle">handle to use in confirmation message</param> /// <param name="handler">confirmation handler</param> /// <param name="isControlMsg">true is message is control message, so no additional header will be added</param> public void DataRequest( UInt16 targetAddr, UInt16 nextHopAddr, ref Frame sdu, Byte sduHandle, DataConfirmHandler handler, bool isControlMsg) { if (isControlMsg) { MacDataRequest(nextHopAddr, ref sdu); // do not add any headers } else { SendData(_addrShort, targetAddr, nextHopAddr, ref sdu, sduHandle, handler); } }
/// <summary> /// Adds broadcast/mesh headers and sends SDU to MAC /// </summary> /// <returns>True on success</returns> private void SendData( UInt16 orgAddr, UInt16 tgtAddr, UInt16 nextHopAddr, ref Frame sdu, Byte sduHandle, DataConfirmHandler handler) { bool success = false; if (orgAddr != cInvalidShortAddr) { bool ok = true; bool multicast = false; if (IsMulticast(tgtAddr)) { multicast = true; Messages6LoWPAN.BroadcastHeader bh = new Messages6LoWPAN.BroadcastHeader(); bh.seqNo = IncSeqNoBroadcast(); ok = bh.WriteToFrameHeader(sdu); } if (ok && (multicast || (tgtAddr != nextHopAddr))) { // add mesh header Messages6LoWPAN.MeshHeader mh = new Messages6LoWPAN.MeshHeader(); mh.originatorAddress = orgAddr; mh.finalAddress = tgtAddr; mh.HopsLeft = cDefaultHopLimit; ok = mh.WriteToFrameHeader(sdu); } if (ok) { MacDataRequest(nextHopAddr, ref sdu, sduHandle, handler); success = true; } } Frame.Release(ref sdu); if (!success && handler != null) handler.Invoke(_net, sduHandle, Status.Busy); }
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 void DataRequest(ushort targetShortAddr, ref Frame sdu, byte sduHandle, DataConfirmHandler handler) { if (!_started) { if (handler != null) { handler.Invoke(this, sduHandle, Status.NotRunning); } return; } if (targetShortAddr == _localShortAddress) { // deliver frame to ourself if (handler != null) { handler.Invoke(this, sduHandle, Status.Success); } DataIndicationHandler ind = _dataIndicationHandler; if (ind != null) { ind.Invoke(this, targetShortAddr, targetShortAddr, sdu); sdu = null; } return; } DataRequestItem newItem = new DataRequestItem(targetShortAddr, ref sdu, sduHandle, handler); OutboundFragmentationMessage outMsg = null; bool queueFull = false; lock (_lock) { // check if one can send directly the message. if (null == _outboundAssociations.GetFragmentationMessage(_localShortAddress, targetShortAddr)) { outMsg = CreateNewOutboundMessage(newItem); } else { // there is already a message being sent to this address. Store to queue. if (!_dataRequestQueueSet.Add(newItem)) { queueFull = true; } } } // release the lock before calling method in FragmentMessage class if (outMsg != null) { outMsg.SendNextDataFragment(true); } else if (queueFull) { // queue is full. if (handler != null) { handler.Invoke(this, sduHandle, Status.Busy); } newItem.Dispose(); } }
/// <summary> /// Send a Mac SDU using context information. SrcAddr is automatically choosen. /// </summary> /// <param name="msdu">The frame to sent.</param> /// <param name="context">Sent context. If null, frame is broadcasted</param> private void MacDataRequestReal( bool useExtAddr, UInt16 nextHopAddrShort, UInt64 nextHopAddrExt, ref Frame sdu, Byte sduHandle, DataConfirmHandler handler) { // srcAddr: always use short addr when available MacAddressingMode srcAddrMode = new MacAddressingMode(); if (_addrShort == cUnallocatedShortAddr) srcAddrMode = MacAddressingMode.ExtendedAddress; else srcAddrMode = MacAddressingMode.ShortAddress; MacAddress dstAddr = new MacAddress(); if (useExtAddr) dstAddr.ExtendedAddress = nextHopAddrExt; else dstAddr.ShortAddress = nextHopAddrShort; byte msduHandle; Mac.DataConfirmHandler macHandler; bool broadcast = (!useExtAddr) && IsMulticast(nextHopAddrShort); if (!broadcast || handler != null) { // need a send context MessageContext.Context context = _messageContext.GetFreeContext(); if (context == null) { // busy if (handler != null) handler.Invoke(_net, sduHandle, Status.Busy); Frame.Release(ref sdu); return; } context.useExtAddr = useExtAddr; context.nextHopShort = nextHopAddrShort; context.nextHopExt = nextHopAddrExt; context.dataSduHandle = sduHandle; context.dataHandler = handler; macHandler = MacDataConfirmHandler; msduHandle = context.macSduHandle; } else { macHandler = null; msduHandle = MessageContext.cHandleDontCare; } TxOptions tx = new TxOptions(); if (!broadcast) tx.AcknowledgedTransmission = true; _mac.DataRequest( srcAddrMode, dstAddr, _panId, ref sdu, msduHandle, tx, new SecurityOptions(), macHandler); Frame.Release(ref sdu); }
/// <summary> /// To send sdu from local node /// </summary> /// <param name="tgtAddrExt"></param> /// <param name="sduHandle"></param> /// <param name="sdu"></param> /// <param name="handler"></param> public void DataRequest( UInt16 targetAddr, ref Frame sdu, Byte sduHandle, DataConfirmHandler handler, bool isControlMsg) { lock (_lock) { int i = FindTargetAddr(targetAddr); Entry entry; if (i == -1) { // create new entry entry = AddEntry(targetAddr); } else { entry = _table[i] as Entry; } bool doRouteRequest = false; if (entry.nextHopAddr == cInvalidAddr || entry.routeHasError) { // no route to targetAddr // queue this message if (entry.pendingMessages.Count == cMaxPendingMsg) { // delete oldest waiting msg PendingMessage pmOld = (PendingMessage)entry.pendingMessages[0]; entry.pendingMessages.RemoveAt(0); _routing.DataRequestTimeout(targetAddr, pmOld.sduHandle, pmOld.handler, pmOld.isControlMsg); Frame.Release(ref pmOld.sdu); } PendingMessage pm = new PendingMessage(); pm.sdu = sdu; sdu = null; pm.sduHandle = sduHandle; pm.handler = handler; pm.isControlMsg = isControlMsg; entry.pendingMessages.Add(pm); doRouteRequest = true; } else { entry.routeInUse = true; _routing.DataRequest(targetAddr, entry.nextHopAddr, ref sdu, sduHandle, handler, isControlMsg); if (entry.routeHasError) { doRouteRequest = true; entry.routeHasError = false; } } if (doRouteRequest) { // initiate route request if (!entry.routePending) { // we haven't asked for a route yet, start now entry.routePending = true; entry.requestRetryCnt = cRouteRequestRetryCnt; entry.timeOutSet = cRouteRequestWaitTime; _timerEvent.Set(); Trace.Print("Sending route request for 0x" + HexConverter.ConvertUintToHex(entry.targetAddr, 4) + " for data"); _routing.RouteRequest(targetAddr); } // else: wait for ongoing request } } }
public void DataRequest( MacAddressingMode srcAddrMode, MacAddress dstAddr, UInt16 dstPanId, ref Frame msdu, Byte msduHandle, TxOptions options, SecurityOptions securityOptions, DataConfirmHandler handler) { TaskDataRequest task = new TaskDataRequest( srcAddrMode, dstAddr, dstPanId, msdu, msduHandle, options, securityOptions, handler); if (!_taskQueue.Add(task)) { Frame.Release(ref msdu); if (handler != null) handler.Invoke(this, msduHandle, MacEnum.Congested); } msdu = null; // in any case, remove frame ownership from caller }
internal OutboundFragmentationMessage( UInt16 source, UInt16 destination, byte messageSeqNumber, DataRequestHandler lowerLayerRequestHandler, ref Frame sdu, Byte sduHandle, DataConfirmHandler handler, int maxPduSize, int reservedHeaderSize, int reservedTailSize, FragmentationMessageTimer timer ) : base(source, destination, messageSeqNumber, lowerLayerRequestHandler, maxPduSize, reservedHeaderSize, reservedTailSize, timer) { if (sdu.LengthDataUsed == 0) { Frame.Release(ref sdu); throw new ArgumentException("sdu is empty", "sdu"); } int payloadSize = maxPduSize - 2 - 2; // 2 for our own header, 1 for nb fragment, 1 for fragment id if (payloadSize == 0) { Frame.Release(ref sdu); throw new ArgumentException("PDU is too small", "maxPduSize"); } ushort flag = (ushort)(1 << 15); _isBroadcast = (destination & flag) > 0 ? true : false; _sdu = sdu; sdu = null; _sduHandle = sduHandle; _dataConfirmHandler = handler; _messageSeqNumber = messageSeqNumber; _timeoutForResending = c_defaultTimeoutForResending; _maxFragmentsBeforeAck = c_defaultMaxFragmentsBeforeAck; // compute required nb fragments and respective indices. int nbFragments = ((_sdu.LengthDataUsed % payloadSize) == 0) ? _sdu.LengthDataUsed / payloadSize : 1 + _sdu.LengthDataUsed / payloadSize; if (nbFragments > byte.MaxValue) { throw new ArgumentException("sdu is too large."); } _nbFragments = (byte)nbFragments; _endingIndices = new int[_nbFragments]; int lastIndex = -1; for (int i = 0; i + 1 < _nbFragments; i++) { lastIndex += payloadSize; _endingIndices[i] = lastIndex; } lastIndex += ((_sdu.LengthDataUsed % payloadSize) == 0) ? payloadSize : _sdu.LengthDataUsed % payloadSize; _endingIndices[_nbFragments - 1] = lastIndex; _successfullyTransmittedFragments = new BitArray(_nbFragments, false); _lastFragmentSent = new BitArray(_nbFragments, false); }
internal OutboundFragmentationMessage( UInt16 source, UInt16 destination, byte messageSeqNumber, DataRequestHandler lowerLayerRequestHandler, ref Frame sdu, Byte sduHandle, DataConfirmHandler handler, int maxPduSize, int reservedHeaderSize, int reservedTailSize, FragmentationMessageTimer timer ) : base(source, destination, messageSeqNumber, lowerLayerRequestHandler, maxPduSize, reservedHeaderSize, reservedTailSize, timer) { if (sdu.LengthDataUsed == 0) { Frame.Release(ref sdu); throw new ArgumentException("sdu is empty", "sdu"); } int payloadSize = maxPduSize - 2 - 2; // 2 for our own header, 1 for nb fragment, 1 for fragment id if (payloadSize == 0) { Frame.Release(ref sdu); throw new ArgumentException("PDU is too small", "maxPduSize"); } ushort flag = (ushort)(1 << 15); _isBroadcast = (destination & flag) > 0 ? true : false; _sdu = sdu; sdu = null; _sduHandle = sduHandle; _dataConfirmHandler = handler; _messageSeqNumber = messageSeqNumber; _timeoutForResending = c_defaultTimeoutForResending; _maxFragmentsBeforeAck = c_defaultMaxFragmentsBeforeAck; // compute required nb fragments and respective indices. int nbFragments = ((_sdu.LengthDataUsed % payloadSize) == 0) ? _sdu.LengthDataUsed / payloadSize : 1 + _sdu.LengthDataUsed / payloadSize; if (nbFragments > byte.MaxValue) throw new ArgumentException("sdu is too large."); _nbFragments = (byte)nbFragments; _endingIndices = new int[_nbFragments]; int lastIndex = -1; for (int i = 0; i + 1 < _nbFragments; i++) { lastIndex += payloadSize; _endingIndices[i] = lastIndex; } lastIndex += ((_sdu.LengthDataUsed % payloadSize) == 0) ? payloadSize : _sdu.LengthDataUsed % payloadSize; _endingIndices[_nbFragments - 1] = lastIndex; _successfullyTransmittedFragments = new BitArray(_nbFragments, false); _lastFragmentSent = new BitArray(_nbFragments, false); }