/*!
* \file raw_ip_packet_source.cc
*
* \brief Receives ip frames containing samples in UDP frame encapsulation
* using a high performance packet capture library (libpcap)
* \author Javier Arribas jarribas (at) cttc.es
* -------------------------------------------------------------------------
*
* Copyright (C) 2010-2018 (see AUTHORS file for a list of contributors)
*
* GNSS-SDR is a software defined Global Navigation
* Satellite Systems receiver
*
* This file is part of GNSS-SDR.
*
* GNSS-SDR is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* GNSS-SDR is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with GNSS-SDR. If not, see .
*
* -------------------------------------------------------------------------
*/
#include
#include "raw_ip_packet_source.h"
#include
#include
#define FIFO_SIZE 1000000
/* 4 bytes IP address */
typedef struct gr_ip_address{
u_char byte1;
u_char byte2;
u_char byte3;
u_char byte4;
}gr_ip_address;
/* IPv4 header */
typedef struct gr_ip_header{
u_char ver_ihl; // Version (4 bits) + Internet header length (4 bits)
u_char tos; // Type of service
u_short tlen; // Total length
u_short identification; // Identification
u_short flags_fo; // Flags (3 bits) + Fragment offset (13 bits)
u_char ttl; // Time to live
u_char proto; // Protocol
u_short crc; // Header checksum
gr_ip_address saddr; // Source address
gr_ip_address daddr; // Destination address
u_int op_pad; // Option + Padding
}gr_ip_header;
/* UDP header*/
typedef struct gr_udp_header{
u_short sport; // Source port
u_short dport; // Destination port
u_short len; // Datagram length
u_short crc; // Checksum
}gr_udp_header;
raw_ip_packet_source::sptr
raw_ip_packet_source::make(std::string src_device, std::string origin_address, int udp_port, int udp_packet_size)
{
return gnuradio::get_initial_sptr
(new raw_ip_packet_source(src_device, origin_address, udp_port, udp_packet_size));
}
/*
* The private constructor
*/
raw_ip_packet_source::raw_ip_packet_source(std::string src_device, std::string origin_address, int udp_port, int udp_packet_size)
: gr::sync_block("raw_ip_packet_source",
gr::io_signature::make(0, 0, 0),
gr::io_signature::make(1, 1, sizeof(char)))
{
// constructor code here
std::cout<<"Start Ethernet packet capture\n";
d_src_device=src_device;
d_udp_port=udp_port;
d_udp_payload_size=udp_packet_size;
d_fifo_full=false;
d_last_frame_counter=0;
d_num_rx_errors=0;
//allocate signal samples buffer
fifo_buff=new char[FIFO_SIZE];
fifo_read_ptr=0;
fifo_write_ptr=0;
fifo_items=0;
//open the ethernet device
if (open()==true)
{
// start pcap capture thread
d_pcap_thread=new boost::thread(boost::bind(&raw_ip_packet_source::my_pcap_loop_thread,this,descr));
}else{
exit(1); //ethernet error!
}
}
bool raw_ip_packet_source::open()
{
char errbuf[PCAP_ERRBUF_SIZE];
boost::mutex::scoped_lock lock(d_mutex); // hold mutex for duration of this function
/* open device for reading */
descr = pcap_open_live(d_src_device.c_str(),1500,1,1000,errbuf);
if(descr == NULL)
{
std::cout<<"Error openning Ethernet device "<join();
pcap_close(descr);
}
delete fifo_buff;
std::cout<<"Stop Ethernet packet capture\n";
}
void raw_ip_packet_source::static_pcap_callback(u_char *args, const struct pcap_pkthdr* pkthdr,
const u_char* packet)
{
raw_ip_packet_source *bridge=(raw_ip_packet_source*) args;
bridge->pcap_callback(args, pkthdr, packet);
}
void raw_ip_packet_source::pcap_callback(u_char *args, const struct pcap_pkthdr* pkthdr,
const u_char* packet)
{
boost::mutex::scoped_lock lock(d_mutex); // hold mutex for duration of this function
gr_ip_header *ih;
gr_udp_header *uh;
// eth frame parameters
// **** UDP RAW PACKET DECODER ****
if ((packet[12]==0x08) & (packet[13]==0x00)) //IP FRAME
{
/* retireve the position of the ip header */
ih = (gr_ip_header *) (packet +
14); //length of ethernet header
/* retireve the position of the udp header */
u_int ip_len;
ip_len = (ih->ver_ihl & 0xf) * 4;
uh = (gr_udp_header *) ((u_char*)ih + ip_len);
/* convert from network byte order to host byte order */
u_short sport,dport;
dport = ntohs( uh->dport );
sport = ntohs( uh->sport );
if (dport==d_udp_port)
{
// print ip addresses and udp ports
// printf("%d.%d.%d.%d.%d -> %d.%d.%d.%d.%d\n",
// ih->saddr.byte1,
// ih->saddr.byte2,
// ih->saddr.byte3,
// ih->saddr.byte4,
// sport,
// ih->daddr.byte1,
// ih->daddr.byte2,
// ih->daddr.byte3,
// ih->daddr.byte4,
// dport);
// std::cout<<"d_udp_port:"<=d_udp_payload_size)
{
//write all in a single memcpy
memcpy(&fifo_buff[fifo_write_ptr],&udp_payload[0],d_udp_payload_size); //size in bytes
fifo_write_ptr+=d_udp_payload_size;
if (fifo_write_ptr==FIFO_SIZE) fifo_write_ptr=0;
fifo_items+=d_udp_payload_size;
}else{
//two step wrap write
memcpy(&fifo_buff[fifo_write_ptr],&udp_payload[0],aligned_write_items); //size in bytes
fifo_write_ptr=d_udp_payload_size-aligned_write_items;
memcpy(&fifo_buff[0],&udp_payload[aligned_write_items],fifo_write_ptr); //size in bytes
fifo_items+=d_udp_payload_size;
}
}else{
std::cout<<"Ou"<=num_samples_readed)
{
//read all in a single memcpy
memcpy(&((char*)output_items[0])[0],&fifo_buff[fifo_read_ptr],num_samples_readed);
fifo_read_ptr=fifo_read_ptr+num_samples_readed; //increase the fifo pointer
if (fifo_read_ptr==FIFO_SIZE) fifo_read_ptr=0;
}else{
//two step wrap read
memcpy(&((char*)output_items[0])[0],&fifo_buff[fifo_read_ptr],aligned_read_items);
fifo_read_ptr=num_samples_readed-aligned_read_items;//increase the fifo pointer considering the rollover
memcpy(&((char*)output_items[0])[aligned_read_items],&fifo_buff[0],fifo_read_ptr);
}
fifo_items=fifo_items-num_samples_readed;
// Tell runtime system how many output items we produced.
//std::cout<<"fifo_items:"<