/// <summary> /// This is used to initialize the last sequence number accepted by /// the Arduino. /// </summary> /// <param name="candidate">The candidate <c>Arduino</c> object to /// perform the initialization.</param> private static void InitializeLastSeqNr(Arduino candidate) { // So we start with a Read in contrast to the Run() method. This // is because we can always expect the Arduino to be sending. If // the program restarts, it will continue to send an ack for its // last received message, or an identify for its last detected // identify. int seqNrAttemptsLeft = NUM_SEQ_NR_ATTEMPTS; bool identifiedSeqNr = false; while (seqNrAttemptsLeft > 0 && !identifiedSeqNr) { try { RxMessage receivedMessage = null; // Read it, until it finds a complete message, or it times out. while (receivedMessage == null) { receivedMessage = candidate.Read(); } // Set the last sent sequence number according to what the // Arduino is sending. candidate.LastSentSeqNr = receivedMessage.Sequence > 0; identifiedSeqNr = true; } catch (TimeoutException) { // If we time out, then the sent variable isn't going // to be set, and it will be resent. } seqNrAttemptsLeft--; } }
/// <summary> /// This should be run in a seperate thread. /// </summary> public virtual bool Run() { // Sets the sequence, so after the Write it will have the // correct value in the LastSentSeqNr. NextMessageToSend.Sequence = (byte)(LastSentSeqNr ? 1 : 0); bool sent = false; bool received = false; bool hasWritten = false; while (!(sent && received)) { try { if (!hasWritten) { Write(); } else { ReWrite(); // Write it. } sent = true; // Mark that we wrote it. } catch (TimeoutException) { // If we time out, then the sent variable isn't going // to be set, and it will be resent. } hasWritten = true; try { RxMessage receivedMessage = null; while (receivedMessage == null) // Read it, until it finds a complete message. { receivedMessage = Read(); } if ( // Check to make sure we got the correct sequence number back. receivedMessage.Sequence == 0 && !LastSentSeqNr || receivedMessage.Sequence == 1 && LastSentSeqNr ) { received = true; // Mark that we got an ack for the appropriate one. // Changes the last sequence number, so that it // will represent what was last sent after the next Write(). LastSentSeqNr = !LastSentSeqNr; } } catch (TimeoutException) { // If we time out, then the sent variable isn't going // to be set, and it will be resent. } } return(true); }
public IngredientListPage() { Debug.WriteLine("ingredientList Page ctor"); InitializeComponent(); RxMessage getAllMessage = new RxMessage(); getAllMessage.Callback = OnIngredientInfoUpdated; RxCore.Instance.SendMessage(RxIngredientCommand.GetAllIngredients, getAllMessage); }
/// <summary> /// Read a single message from the Arduino, and clear the buffer if any /// other bytes remain in it. /// </summary> /// <returns>The first available message in the buffer.</returns> protected virtual RxMessage Read() { RxMessage result = null; _ReceiveBuffer = Enumerable.Repeat <byte>(0, _ReceiveBufferSize).ToArray(); while ((_ReceiveBuffer[0] = (byte)Port.ReadByte()) != RxMessage._START) { ; } int counter = 1; while ( counter < _ReceiveBufferSize && // Make sure we don't overrun the buffer. ((_ReceiveBuffer[counter] = (byte)Port.ReadByte()) != RxMessage._END) && // Make sure we don't hit an end byte. _ReceiveBuffer[counter] != RxMessage._START // Make sure we don't hit the start of another frame. ) { counter++; } if ( counter == _ReceiveBufferSize - 1 && // Did the counter reach the end of the buffer? _ReceiveBuffer[0] == RxMessage._START && // Did the start involve a START byte? _ReceiveBuffer[_ReceiveBufferSize - 1] == RxMessage._END // Did the end involve an end byte? ) { var ack = new Ack(_ReceiveBuffer); var rxType = ack[RxField.INFO_0]; switch (rxType) { case (int)RxType.IDENTIFY: result = new Identify(_ReceiveBuffer); break; case (int)RxType.ACK: result = ack; break; } var bytesToRead = Port.BytesToRead; if (bytesToRead > 100) { Port.ReadExisting(); } } return(result); }
private void OnGetAllIngredients(RxMessage message) { int count = SelectAll(); Debug.WriteLine("all ingredients : " + count); RxMessage itemListMessage = new RxMessage(); itemListMessage.Content = _ingredients; if (message.Callback != null) { message.Callback.Invoke(itemListMessage); } //RxItemListMessage itemListMessage = new RxItemListMessage(); //itemListMessage.ItemList = _ingredients; //_ingredientManagerNode.Publish(itemListMessage); }
private void OnRxEvent(RxMessage message) { }
/// <summary> /// Tries to identify the arduino. /// </summary> /// <param name="candidate">The candidate to determine if it is an /// Arduino.</param> /// <returns>Whether or not the candidate was identified as an Arduino. /// </returns> private static bool TryIdentify(Arduino candidate) { // Setup the random numbers we will be sending. var identifyRequest = new APS.Data.Messages.Tx.Identify(); identifyRequest.Random0 = (byte)candidate.Rand.Next(); identifyRequest.Random1 = (byte)candidate.Rand.Next(); // Sets the sequence, so it matches LastSentSeqNr. The // LastSentSeqNr should already be set, so it is correct after a // Write(). identifyRequest.Sequence = (byte)(candidate.LastSentSeqNr ? 1 : 0); // Position the identify request for sending. candidate.NextMessageToSend = identifyRequest; // Set the number of attempts we will allow to write. var numIdAttemptsLeft = NUM_ID_ATTEMPTS; var sent = false; var received = false; candidate.Port.ReadExisting(); // Do this until we run out of attempts, or until both are sent // and received. while (numIdAttemptsLeft > 0 && !(sent && received)) { try { if (numIdAttemptsLeft == NUM_ID_ATTEMPTS) { candidate.Write(); } else { candidate.ReWrite(); // Write it. } sent = true; // Mark that we wrote it. } catch (TimeoutException) { // If we time out, then the sent variable isn't going // to be set, and it will be resent. } // Set the number of attempts we will allow to read for this // write. var numIdReadAttemptsLeft = NUM_ID_READS_PER_SEND; // Read X times or until we have identified. while (numIdReadAttemptsLeft > 0 && !received) { try { RxMessage receivedMessage = null; while (receivedMessage == null) // Read it, until it finds a complete message. { receivedMessage = candidate.Read(); } // Check to make sure we got the correct sequence number back. var seqNrMatch = receivedMessage.Sequence == 0 && !candidate.LastSentSeqNr || receivedMessage.Sequence == 1 && candidate.LastSentSeqNr; // Make sure the sequence numbers match, and the received // is message matches what is expected. if (seqNrMatch && IsExpected(identifyRequest, receivedMessage)) { received = true; // Mark that we successfully identified. // Changes the last sequence number, so that it // will represent what was last sent after the next Write(). candidate.LastSentSeqNr = !candidate.LastSentSeqNr; } } catch (TimeoutException) { // If we time out, then the sent variable isn't going // to be set, and it will be resent. } numIdReadAttemptsLeft--; } numIdAttemptsLeft--; } return(sent && received); }
private void OnRegisterFood(RxMessage message) { }
private void OnGetFoodByName(RxMessage message) { }
private void OnGetFoodById(RxMessage message) { }
private void OnGetAll(RxMessage message) { }
/// <summary> /// Rewrite of <see cref="FLServer.Server.DirectPlayServer.ProcessPktFromClient"/> /// </summary> /// <param name="message"></param> public void Handle(RxMessage message) { var pos = 0; uint cmd = FLMsgType.GetUInt8(message.Bytes, ref pos); if (cmd == 0x00 && message.Bytes.Length >= 4) { uint opcode = FLMsgType.GetUInt8(message.Bytes, ref pos); if (opcode != 0x02 || message.Bytes.Length < 4) { return; } //That's enum request, spit out server info. uint enumPayload = FLMsgType.GetUInt16(message.Bytes, ref pos); var glob = Context.ActorSelection("/user/server/globals"); glob.Tell(new EnumRequest((ushort)enumPayload)); } // If the data is at least 12 bytes and the first byte is // either 0x80 or 0x88 (PACKET_COMMAND_CFRAME or PACKET_COMMAND_CFRAME | // PACKET_COMMAND_POLL), it MUST process the message as a CFRAME // (section 3.1.5.1) command frame. else if ((cmd == 0x80 || cmd == 0x88) && message.Bytes.Length >= 12) { uint opcode = FLMsgType.GetUInt8(message.Bytes, ref pos); // The CONNECT packet is used to request a connection. If accepted, the response // is a CONNECTED (section 2.2.1.2) packet switch (opcode) { case 0x01: { //now created on session start //var session = Context.Child("dplay-session"); //if (session.IsNobody()) //{ //session = Context.ActorOf<DPlaySession.DPlaySession>("dplay-session"); //Context.ActorOf<Congestion.Congestion>("congestion"); //} if (!_dpInitialized) { _dpInitialized = true; } var msgID = FLMsgType.GetUInt8(message.Bytes, ref pos); var rspID = FLMsgType.GetUInt8(message.Bytes, ref pos); var version = FLMsgType.GetUInt32(message.Bytes, ref pos); var dplayid = FLMsgType.GetUInt32(message.Bytes, ref pos); var timestamp = FLMsgType.GetUInt32(message.Bytes, ref pos); // If the session id has changed, assume that the server is wrong // and kill the existing connection and start a new one. // This behaviour differs from the dplay specification. // If the session is fully connected because the client has // sent us a connect acknowledge then ignore this. //if (sess.SessionState == Session.State.CONNECTED) // return; //Whole thing done in DPlaySession //this part is done in ConnectingMessage handler //we're nullifying all counters _dplaySession.Tell(new DPlaySession.DPlaySession.ConnectRequest(msgID, dplayid, rspID), Context.Child("socket")); } break; case 0x06: { var flags = FLMsgType.GetUInt8(message.Bytes, ref pos); var retry = FLMsgType.GetUInt8(message.Bytes, ref pos); // The seq field indicates the seq of the next message that the client will send. var seq = FLMsgType.GetUInt8(message.Bytes, ref pos); // The next_rx field indicates the message seq that the client is waiting to receive var nrcv = FLMsgType.GetUInt8(message.Bytes, ref pos); pos += 2; // skip padding var timestamp = FLMsgType.GetUInt32(message.Bytes, ref pos); // Ignore packets for sessions that don't exist if (!_dpInitialized) { return; } //sess.BytesRx += pkt.Length; // If the hi sack mask is present, resend any requested packets. if ((flags & 0x02) == 0x02) { var mask = FLMsgType.GetUInt32(message.Bytes, ref pos); _congestion.Tell(new Congestion.Congestion.DoRetryOnSACKMessage(mask, nrcv)); } // If the hi sack mask is present, resend any requested packets. if ((flags & 0x04) == 0x04) { var mask = FLMsgType.GetUInt32(message.Bytes, ref pos); _congestion.Tell(new Congestion.Congestion.DoRetryOnSACKMessage(mask, (byte)(nrcv + 32))); } // At this point bSeq sequence ID is valid, the bNRcv field // is to be inspected. All previously sent TRANS_USERDATA_HEADER packets that // are covered by the bNRcv sequence ID, that is, those packets that had been sent // with bSeq values less than bNRcv (accounting for 8-bit counter wrapping) are // acknowledged. These packets do not have to be remembered any longer, and their // retry timers can be canceled. _congestion.Tell(new Congestion.Congestion.AckUserData(nrcv)); // Try to send data if there's data waiting to be sent and send a // selective acknowledgement if we didn't sent a dframe and the client // requested an acknowledgement. if (cmd == 0x88) { _congestion.Tell("SendSACK"); } } break; } } // If a packet arrives, the recipient SHOULD first check whether // it is large enough to be a minimal data frame (DFRAME) (4 bytes) // and whether the first byte has the low bit (PACKET_COMMAND_DATA) set. else if ((cmd & 0x01) == 0x01 && message.Bytes.Length >= 4) { uint control = FLMsgType.GetUInt8(message.Bytes, ref pos); var seq = FLMsgType.GetUInt8(message.Bytes, ref pos); var nrcv = FLMsgType.GetUInt8(message.Bytes, ref pos); // Ignore packets for sessions that don't exist //Session sess = GetSession(client); //if (sess == null) //return; // This is a disconnect. We ignore the soft disconnect and immediately // drop the session repeating the disconnect a few times to improve the // probability of it getting through. if ((control & 0x08) == 0x08) { Context.ActorSelection("./*").Tell(PoisonPill.Instance, Context.Self); _log.Debug("{0} shutting down: Client request", Self.Path); SendCmdHardDisconnect(); Context.Stop(Context.Self); return; } //var cong = Context.Child("congestion"); //if (cong.IsNobody()) return; if (!_dpInitialized) { return; } var ticks = new TimeSpan(45); // TRANS_USERDATA_HEADER bSeq field MUST be either the next sequence // ID expected or within 63 packets beyond the ID expected by the receiver. // If the sequence ID is not within this range, the payload MUST be ignored. // In addition, a SACK packet SHOULD be sent indicating the expected sequence ID. { var resp = _congestion.Ask <bool>(new Congestion.Congestion.AckIfInWindow(seq)); resp.Wait(ticks); if (resp.Result) { return; } } // If the sequence ID is out of order, but still within 63 packets, // the receiver SHOULD queue the payload until it receives either: // - A delayed or retried transmission of the missing packet or packets, // and can now process the sequence in order. // - A subsequent packet with a send mask indicating that the missing // packet or packets did not use PACKET_COMMAND_RELIABLE and will never // be retried. Therefore, the receiver should advance its sequence as if // it had already received and processed the packets. { //var ask = new Congestion.CheckIfOutOfOrder(seq, message.Bytes); var resp = _congestion.Ask <bool>(new Congestion.Congestion.CheckIfOutOfOrder(seq, message.Bytes)); resp.Wait(ticks); if (resp.Result) { _log.Debug("{0} enqueued out of order packet {1}", Context.Self.Path, seq); return; } } //Test code to simulate packet loss //if (rand.Next(5) == 1) //{ // log.AddLog(String.Format("c>s: DROPPING THE PACKET NOW {0:X}", seq)); // return; //} // Note if this was a retried dframe. if ((control & 0x01) == 0x01) { _congestion.Tell("LostRx"); } // When one or both of the optional SACK mask 32-bit fields is present, and one // or more bits are set in the fields, the sender is indicating that it received a // packet or packets out of order, presumably due to packet loss. The two 32-bit, // little-endian fields MUST be considered as one 64-bit field, where dwSACKMask1 // is the low 32 bits and dwSACKMask2 is the high 32 bits. If either 32-bit field // is not available, the entire contents of the 64-bit field MUST be considered as all 0. // The receiver of a SACK mask SHOULD loop through each bit of the combined 64-bit value // in the ascending order of significance. Each bit corresponds to a sequence ID after // bNRcv. If the bit is set, it indicates that the corresponding packet was received // out of order. // The receiver of a SACK mask SHOULD shorten the retry timer for the first frame of // the window to speed recovery from the packet loss. The recommended duration is // 10 milliseconds. This value can be modified according to application and network // requirements. The receiver MAY also choose to remove the selectively acknowledged // packets from its list to retry. if ((control & 0x10) == 0x10) { var mask = FLMsgType.GetUInt32(message.Bytes, ref pos); _congestion.Tell(new Congestion.Congestion.DoRetryOnSACKMessage(mask, nrcv)); } if ((control & 0x20) == 0x20) { var mask = FLMsgType.GetUInt32(message.Bytes, ref pos); _congestion.Tell(new Congestion.Congestion.DoRetryOnSACKMessage(mask, (byte)(nrcv + 32))); } // When one or both of the optional send mask 32-bit fields is present, and one or // more bits are set the fields, the sender is indicating that it sent a packet or // packets that were not marked as reliable and did not receive an acknowledgement yet. // The two 32-bit, little-endian fields MUST be considered as one 64-bit field, where // dwSendMask1 is the low 32 bits and dwSendMask2 is the high 32 bits. If either 32-bit // field is not available, the entire contents of the 64-bit field MUST be considered // as all 0. // The receiver of a send mask SHOULD loop through each bit of the combined 64-bit // value from the least significant bit to the most significant in little-endian byte // order. Each bit corresponds to a sequence ID prior to bSeq, and if that is the bit // that is set, it indicates that the corresponding packet was not sent reliably and // will not be retried. If the recipient of the send mask had not received the packet // and had not already processed a send mask that identified the sequence ID, it SHOULD // consider the packet as dropped and release its placeholder in the sequence. That is, // any sequential messages that could not be indicated because of the gap in the sequence // where the packet that was not marked as reliable had been SHOULD now be reported to // the upper layer. if ((control & 0x40) == 0x40) { FLMsgType.GetUInt32(message.Bytes, ref pos); } if ((control & 0x80) == 0x80) { FLMsgType.GetUInt32(message.Bytes, ref pos); } // However, freelancer always uses reliable packets and so ignore sendmasks. // At this point, we've received the packet we wanted to. Advance the sequence number count later // and process this message. _dplaySession.Tell(new DPlaySession.DPlaySession.ByteMessage(message.Bytes, pos), Context.Child("socket")); //ProcessTransUserData(sess, message.Bytes, pos); // If there are queued out of order packets, try to process these. // Done in Congestion on NextRxSeq // Advance the sequence number as well. _congestion.Tell("NextRxSeq"); // At this point bSeq sequence ID is valid, the bNRcv field // is to be inspected. All previously sent TRANS_USERDATA_HEADER packets that // are covered by the bNRcv sequence ID, that is, those packets that had been sent // with bSeq values less than bNRcv (accounting for 8-bit counter wrapping) are // acknowledged. These packets do not have to be remembered any longer, and their // retry timers can be canceled. _congestion.Tell(new Congestion.Congestion.AckUserData(nrcv)); // We always do an immediate acknowledge as bandwidth isn't a particular concern // but fast recovery from lost packets is. _congestion.Tell("SendSACK"); } }
public void OnIngredientInfoUpdated(RxMessage message) { Debug.WriteLine("okkkk!"); ItemList.ItemsSource = ((List <IBaseItem>)message.Content).OfType <Ingredient>(); }
public void OnRxEvent(RxMessage message) { }