// Master polling slave event handler
void master_poll_slave_timeout_handler(void* opaque) {
	(void)opaque;

    // Turning off the timers
    disable_all_timers();

    // Basically for situation when just after sending packet from this
    //function nothing comes back and master_poll_slave_timer times out
    if (!master_current_request_processed) {
        master_current_retry = MASTER_RETRIES;
        master_retry_timeout_handler(NULL);
        return;
    }
    
    // Check out going queue if nothing to send from there then
    // send modbus packet without payload to current slave
    RS485ExtensionPacket* packet_to_modbus;
    packet_to_modbus = queue_peek(&_rs485_extension.packet_to_modbus_queue);
    
    if(packet_to_modbus == NULL) {
        // Incase there are no slaves configured for this master
        if(_rs485_extension.slave_num == 0) {
            // Re-enabling the timer
            partial_receive_flag = 0;
            master_current_request_processed = 1;
            //setup_timer(&master_poll_slave_timer, TIME_UNIT_NSEC, MASTER_POLL_SLAVE_TIMEOUT);
            return;
        }
        // Since there are no packets to be sent from the queue
        // we poll current slave with an empty message
        Packet empty_packet;
        memset(&empty_packet, 0, sizeof(PacketHeader));
        empty_packet.header.length = 8;
    
        // Update current request which is being sent
        current_request = empty_packet;
    
        // Update current sequence number
        update_sequence_number();
        
        // Update current slave to process
        update_slave_to_process();
        
        int bytes_sent = send_modbus_packet(_rs485_extension.slaves[master_current_slave_to_process],
                                            current_sequence_number, &empty_packet);
        log_debug("RS485: Sending empty packet to slave ID = %d, Sequence number = %d, Bytes sent = %d", 
                 _rs485_extension.slaves[master_current_slave_to_process],
                 current_sequence_number,
                 bytes_sent);
    }
    else {
        // Update current request which is being sent
        current_request = packet_to_modbus->packet;
        
        // Update current sequence number
        update_sequence_number();
        
        // Update current slave to process
        update_slave_to_process();
        int bytes_sent = send_modbus_packet(packet_to_modbus->slave_address,
                                            current_sequence_number,
                                            &packet_to_modbus->packet);
        log_debug("RS485: Sending packet from queue to slave ID = %d, Sequence number = %d, Bytes sent = %d", 
                 packet_to_modbus->slave_address,
                 current_sequence_number,
                 bytes_sent); 
        sent_current_request_from_queue = 1;
    }
    
    partial_receive_flag = 0;
    master_current_request_processed = 0;
    // Re-enabling the timer
    setup_timer(&master_poll_slave_timer, TIME_UNIT_NSEC, MASTER_POLL_SLAVE_TIMEOUT);
    timerfd_settime(_master_poll_slave_event, 0, &master_poll_slave_timer, NULL);
}
Beispiel #2
0
/**************************************************************************//**
 * Extract the fields of an RTP packet and validate it.
 *
 * @param p_ctx      The reader context.
 * @param t_module   The track module.
 * @return  True if successful, false if there were not enough bits in the
 *          packet or the packet was invalid.
 */
static void decode_rtp_packet_header(VC_CONTAINER_T *p_ctx,
      VC_CONTAINER_TRACK_MODULE_T *t_module)
{
   VC_CONTAINER_BITS_T *payload = &t_module->payload;
   uint32_t version, has_padding, has_extension, csrc_count, has_marker;
   uint32_t payload_type, ssrc;
   uint16_t seq_num;

   /* Break down fixed header area into component parts */
   version              = BITS_READ_U32(p_ctx, payload, 2, "Version");
   has_padding          = BITS_READ_U32(p_ctx, payload, 1, "Has padding");
   has_extension        = BITS_READ_U32(p_ctx, payload, 1, "Has extension");
   csrc_count           = BITS_READ_U32(p_ctx, payload, 4, "CSRC count");
   has_marker           = BITS_READ_U32(p_ctx, payload, 1, "Has marker");
   payload_type         = BITS_READ_U32(p_ctx, payload, 7, "Payload type");
   seq_num              = BITS_READ_U16(p_ctx, payload, 16, "Sequence number");
   t_module->timestamp  = BITS_READ_U32(p_ctx, payload, 32, "Timestamp");
   ssrc                 = BITS_READ_U32(p_ctx, payload, 32, "SSRC");

   /* If there was only a partial header, abort immediately */
   if (!BITS_VALID(p_ctx, payload))
      return;

   /* Validate version, payload type, sequence number and SSRC, if set */
   if (version != 2 || payload_type != t_module->payload_type)
   {
      BITS_INVALIDATE(p_ctx, payload);
      return;
   }
   if (BIT_IS_SET(t_module->flags, TRACK_SSRC_SET) && (ssrc != t_module->expected_ssrc))
   {
      LOG_DEBUG(p_ctx, "RTP: Unexpected SSRC (0x%8.8X)", ssrc);
      BITS_INVALIDATE(p_ctx, payload);
      return;
   }

   /* Check sequence number indicates packet is usable */
   if (!update_sequence_number(t_module, seq_num))
   {
      BITS_INVALIDATE(p_ctx, payload);
      return;
   }

   /* Adjust to account for padding, CSRCs and extension */
   if (has_padding)
   {
      VC_CONTAINER_BITS_T bit_stream;
      uint32_t available = BITS_BYTES_AVAILABLE(p_ctx, payload);
      uint8_t padding;

      BITS_COPY_STREAM(p_ctx, &bit_stream, payload);
      /* The last byte of the payload is the number of padding bytes, including itself */
      BITS_SKIP_BYTES(p_ctx, &bit_stream, available - 1, "Skip to padding length");
      padding = BITS_READ_U8(p_ctx, &bit_stream, 8, "Padding length");

      BITS_REDUCE_BYTES(p_ctx, payload, padding, "Remove padding");
   }

   /* Each CSRC is 32 bits, so shift count up to skip the right number of bits */
   BITS_SKIP(p_ctx, payload, csrc_count << 5, "CSRC section");

   if (has_extension)
   {
      uint32_t extension_bits;

      /* Extension header is 16-bit ID (which isn't needed), then 16-bit length in 32-bit words */
      BITS_SKIP(p_ctx, payload, 16, "Extension ID");
      extension_bits = BITS_READ_U32(p_ctx, payload, 16, "Extension length") << 5;
      BITS_SKIP(p_ctx, payload, extension_bits, "Extension data");
   }

   /* Record whether or not this RTP packet had the marker bit set */
   if (has_marker)
      SET_BIT(t_module->flags, TRACK_HAS_MARKER);
   else
      CLEAR_BIT(t_module->flags, TRACK_HAS_MARKER);

   /* If it hasn't been set independently, use the first timestamp as a baseline */
   if (!t_module->timestamp_base)
      t_module->timestamp_base = t_module->timestamp;
   t_module->timestamp -= t_module->timestamp_base;
}