Пример #1
0
        // Push message on to RNetIfIndex's Write Q.
        // Messages that cannot be posted are freed.
        public static void PostMessage(NetIfManager manager, int ioIndex, byte rNetIfIndex)
        {
            String dbgmsg = null;

            if (ioIndex == -1)
            {
                return;
            }
            LinkDriver p = manager.GetLinkDriver(rNetIfIndex);

            if (p == null)
            {
                rNetIfIndex = ProtocolConstants.NETIF_UNSET;
            }

            if ((p != null) || !isMaster)   // Check destination netIf was not detached.
            {
                if (p == null)
                {
                    p = manager.GetLinkDriver(ProtocolConstants.NETIF_BRIDGE_LINK);
                }
                if (p != null)
                {
                    PacketBuffer b = manager.IoBuffers[ioIndex];
                    // Check for circular routing: examine prior destination netIf.
                    if ((b.dNetIf != ProtocolConstants.NETIF_UNSET) && (b.dNetIf == rNetIfIndex))
                    {
                        // Ignore circular messages.
                        dbgmsg = String.Format("Circular message on netIf [{0}]: ditching message.", rNetIfIndex);
                    }
                    else
                    {
                        b.dNetIf = rNetIfIndex;
                        if (p.NetIfIndex == ProtocolConstants.NETIF_BRIDGE_LINK)
                        {
                            byte netIfs = (byte)((rNetIfIndex << 4) | b.iNetIf); // Use destination to pass netIfs across bridge.
                            b.destination((ushort)(((256 - netIfs) << 8) | netIfs));
                        }
                        if (p.LinkWriteQueue.Push(ioIndex) != -1)   // Check post queue not full.
                        {
                            if (Settings.DebugLevel > 6)
                            {
                                Log.d(TAG, "Posting:" + ioIndex + " to " + p.NetIfIndex);
                            }
                            return;
                        }
                        dbgmsg = String.Format("Write Q full on netIf [{0}]: ditching message.", rNetIfIndex);
                    }
                }
            }
            // Messages that were not posted are freed.
            if (Settings.DebugLevel > 1)
            {
                Log.w(TAG, dbgmsg);
            }
            manager.IoBuffersFreeHeap.Release(ioIndex);
        }
Пример #2
0
        // Create a command general message.
        public int CreateGeneralMessage(bool verified, byte cmd,
                                        ushort receiver, ushort sender, byte flagsRS, byte senderId,
                                        byte dataLen, byte[] pData, byte bufferIndex)
        {
            if (dataLen > (Manager.MaxPacketSize - ProtocolConstants.GENERAL_OVERHEADS_SIZE))
            {
                return(-1);
            }
            int idx = Manager.IoBuffersFreeHeap.Allocate();

            if (idx != -1)
            {
                PacketBuffer b   = Manager.IoBuffers[idx];
                byte         pid = verified ? ProtocolConstants.PID_GENERAL_V : ProtocolConstants.PID_GENERAL;
                b.flagsPid = pid;
                b.dNetIf   = ProtocolConstants.NETIF_UNSET;
                b.iNetIf   = ProtocolConstants.NETIF_UNSET;
                b.pktLen   = (byte)(ProtocolConstants.GENERAL_OVERHEADS_SIZE + dataLen);
                b.sync(ProtocolConstants.BYTE_SYNC);
                b.negPidPid(Primitives.NibbleToPid(pid));
                b.destination(LinkMonitor.Destination); // TODO: set destination.
                b.arg(0);
                b.receiver(receiver);
                b.sender(sender);
                b.senderId(senderId);
                b.flagsRS(flagsRS);
                b.command(cmd);
                b.dataLength(dataLen);
                byte   dataIndex = ProtocolConstants.GENERAL_DATA_ARRAY_OFFSET;
                byte[] p         = b.buffer;
                for (byte k = 0; k < dataLen; k++)
                {
                    p[dataIndex++] = pData[bufferIndex + k];
                }
                b.UpdateCheckSum(b.pktLen);
            }
            return(idx);
        }
Пример #3
0
        // Submit a handshake command to link WriteQ.
        // For example, Resend Vno command, ping, reply, etc.
        public int SendLinkHandshakePacket(byte pid, ushort destination, byte arg)
        {
            int idx = Manager.IoBuffersFreeHeap.Allocate();

            if (idx != -1)
            {
                PacketBuffer b = Manager.IoBuffers[idx];
                b.flagsPid = pid;
                b.dNetIf   = ProtocolConstants.NETIF_UNSET;
                b.iNetIf   = ProtocolConstants.NETIF_UNSET;
                b.pktLen   = ProtocolConstants.HANDSHAKE_PACKET_SIZE;
                b.sync(ProtocolConstants.BYTE_SYNC);
                b.negPidPid(Primitives.NibbleToPid(pid));
                b.destination(destination);
                b.arg(arg);
                b.UpdateCheckSum(b.pktLen);
                if (IoNetIf.LinkWriteQueue.PushFirst(idx) == -1)
                {
                    Manager.IoBuffersFreeHeap.Release(idx);
                    return(-1);
                }
            }
            return(idx);
        }
Пример #4
0
        // Perform a handshake request received from link.
        // Consults original message for r,s details, ports=0, flags=0.
        // TODO: check what happens when a master is pinged etc. Ok?
        public void PerformLinkHandshake(PacketBuffer hp)
        {
            int  idx;
            byte arg = hp.arg();

            // TODO: Check packet is for us first.

            switch (hp.negPidPid() & ProtocolConstants.PID_MASK)
            {
            case ProtocolConstants.PID_PING:     // We received a ping. Now send a reply.
                if (arg >= ProtocolConstants.PID_ARG_BAUD_MIN)
                {
                    switch (arg)
                    {
                    case ProtocolConstants.PID_ARG_RESET:
                        IoNetIf.ResetLinkDriver();
                        break;

                    case ProtocolConstants.PID_ARG_SLAVE:
                        break;

                    case ProtocolConstants.PID_ARG_MULTI:
                        break;

                    case ProtocolConstants.PID_ARG_MASTER:
                        break;

                    default:         // BAUD: Request to change baud rate.
                        IoNetIf.IoNetIfDevice.PerformBaudAction(IoNetIf.DeviceContextIndex,
                                                                (byte)(arg - ProtocolConstants.PID_ARG_BAUD_MIN),
                                                                ProtocolConstants.BAUD_ACTION_SAVE);
                        break;
                    }
                }
                else
                {
                    // Set linkLastInputVno=(VNO_SIZE-1) & linkLastOutputVno=0 ?
                    CheckOrderMissingQ(arg, false);
                    IoNetIf.duplexPingReply |= LinkMonitor.DUX_PING_RECEIVED;
                }
                // Send a reply with Arg = num messages waiting.
                // TODO: unless Q contains Msg destined to sender: use "more" msg code.
                int num = IoNetIf.LinkWriteQueue.Size();         // Arg = num messages waiting.
                SendLinkHandshakePacket(ProtocolConstants.PID_REPLY,
                                        LinkMonitor.Destination, // hp.destination(), // TODO: This should be the linkAdrs.
                                        (byte)((num > 255) ? 255 : num));
                break;

            case ProtocolConstants.PID_REPLY:     //TODO: Now stop pinging.
                // arg=number of waiting messages.
                // If arg>0 read some messages.
                IoNetIf.duplexNumWaiting = arg;
                IoNetIf.duplexPingReply |= LinkMonitor.DUX_REPLY_RECEIVED;
                break;

            case ProtocolConstants.PID_RESEND:     // Resend a message.
                idx = FindVnoInVerifyQueue(IoNetIf.LinkVerifyQueue, arg);
                if (idx == -1)
                {
                    SendLinkHandshakePacket(ProtocolConstants.PID_CANCEL, hp.destination(), arg);
                }
                else if (IoNetIf.LinkWriteQueue.FindFirstOccurrenceIndex(idx) == -1)
                {
                    PacketBuffer b = Manager.IoBuffers[idx];
                    b.flagsPid |= ProtocolConstants.META_FLAGS_RESEND;
                    if (IoNetIf.LinkWriteQueue.PushFirst(idx) == -1)
                    {
                        Manager.IoBuffersFreeHeap.Release(idx);
                    }
                }
                break;

            case ProtocolConstants.PID_CANCEL:     // Remove message from missingQ.
                IoNetIf.LinkMissingQueue.RemoveFirstOccurrence(arg);
                break;

            default: break;
            }
            // TODO: IoNetIf.activityTimeout=Primitives.GetBabelMilliTicker() + LinkMonitor.CONX_ACTIVITY_TIMEOUT;
            IoNetIf.baudTimeout = Primitives.GetBabelMilliTicker() + LinkMonitor.BAUD_RATE_TIMEOUT; // Reset timer after input from specific sender.
        }