// 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); }
// 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); }
// 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); }
// 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. }