// Helper routine for finalizing message state ready for sending. // If justFree, simply frees message buffer. // If dispatchAction=BabelConstants.SEND_TO_ROUTER, sends message to router. // If dispatchAction=BabelConstants.POST_TO_WRITE, pushes message onto oPort's Write Q. public void FinishMessageTransaction() { if (Finish == FinishAction.Free) { Manager.IoBuffersFreeHeap.Release(IoIndex); } else if (Finish == FinishAction.Keep) { } else { if (ReturnCmd != 0) { MsgBuffer.command(ReturnCmd); } if (ChangeDir) { // Change general message direction: // r<>s, RNetIf<>SNetIf, rPort<>sPort, // Invert Is Reply flag, clear ACK flag byte ports, flags = MsgBuffer.flagsRS(); ushort sender = MsgBuffer.sender(); MsgBuffer.sender(MsgBuffer.receiver()); MsgBuffer.receiver(sender); flags ^= ProtocolConstants.MESSAGE_FLAGS_IS_REPLY; flags &= Primitives.ByteNeg(ProtocolConstants.MESSAGE_FLAGS_ACK); // Now swap ports. ports = (byte)(flags & ProtocolConstants.MESSAGE_PORTS_MASK); ports = (byte)((ports << 2) | (ports >> 2)); MsgBuffer.flagsRS((byte)((ports & ProtocolConstants.MESSAGE_PORTS_MASK) | (flags & ProtocolConstants.MESSAGE_FLAGS_MASK))); } else { // Caller might be relaying message to another adrs:netIf. // So leave flagsRS alone. } MsgBuffer.pktLen = (byte)(ProtocolConstants.GENERAL_OVERHEADS_SIZE + MsgBuffer.dataLength()); MsgBuffer.UpdateCheckSum(MsgBuffer.pktLen); if (Dispatch == Router.RouterAction.SendToRouter) { Router.RouteMessage(Manager, IoIndex); } else if (Dispatch == Router.RouterAction.PostToNetIf) { Router.PostMessage(Manager, IoIndex, ONetIfIndex); } } }
// 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); }