// 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); } } }
/// <summary> /// Convert raw message to BabelMessage. /// Called by a port with an incoming raw message. /// Must return as soon as possible, so convert and put on incoming Q for later relay. /// Caller frees the underlying raw message. /// TODO: Process long message if necessary: start a long list. /// </summary> /// <param name="exchange"></param> /// <param name="mtx"></param> /// <returns></returns> public static byte ProcessIncomingRawMesssage(MessageExchange exchange, MessageTransaction mtx) { PacketBuffer g = mtx.MsgBuffer; BabelMessage m = new BabelMessage(exchange); m.Pid = (byte)(g.flagsPid & ProtocolConstants.PID_MASK); m.Verified = (m.Pid == ProtocolConstants.PID_GENERAL_V); m.Receiver = ProtocolConstants.ADRS_LOCAL; m.FlagsRS = g.flagsRS(); m.IncomingNetIfIndex = mtx.ONetIfIndex; m.OutgoingNetIfIndex = ProtocolConstants.NETIF_UNSET; m.Cmd = 0; switch (m.Pid) { case ProtocolConstants.PID_GENERAL: case ProtocolConstants.PID_GENERAL_V: m.IsGeneral = true; m.IsHandshake = false; m.Receiver = g.receiver(); m.Cmd = g.command(); m.FlagsRS = g.flagsRS(); break; default: return(1); } m.Sender = g.sender(); m.SenderId = g.senderId(); m.DataLen = g.dataLength(); m.DataAry = mtx.CopyMessageData(); // Now submit message to be relayed later. exchange.SubmitIncomingMessage(m); return(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); }