I'm looking at the source code for GrOsmoSdr's rtl_tcp_source_f.cc, which is a GNU Radio source which reads interleaved I/Q data from TCP.
The work function looks like this:
int rtl_tcp_source_f::work (int noutput_items,
gr_vector_const_void_star &input_items,
gr_vector_void_star &output_items)
{
float *out = (float *) output_items[0];
ssize_t r = 0;
int bytesleft = noutput_items;
int index = 0;
int receivedbytes = 0;
while(bytesleft > 0) {
receivedbytes = recv(d_socket, (char*)&d_temp_buff[index], bytesleft, 0);
if(receivedbytes == -1 && !is_error(EAGAIN)){
fprintf(stderr, "socket error\n");
return -1;
}
bytesleft -= receivedbytes;
index += receivedbytes;
}
r = noutput_items;
for(int i=0; i<r; ++i)
out[i]=d_LUT[*(d_temp_buff+d_temp_offset+i)];
return r;
}
The buffer d_temp_buff
is set up in the constructor:
d_temp_buff = new unsigned char[d_payload_size];
where d_payload_size
is a constructor parameter which is passed in by configuration.
The work function reads exactly noutput_items
into d_temp_buff
. How is noutput_items
selected by Gnuradio in general, and how can this work function be sure that noutput_items <= d_payload_size
?
By default the upper bound for the maximum number of output items for a flow graph is a large number which varies depending on gnuradio version, currently the value set in the master repository is 100000000
This is set by calling start the top block of the flow graph with no arguments specified, and the default argument is used. Overriding this global value can be done by passing a different argument to the start call of the top_block or calling set_max_noutput_items on the top block or on a specific block by calling set_max_noutput_items.
After initialization at such high value it is then set to a lower value by the scheduler based on the minimum avaliable output space, which uses the value of noutput_items set in the block_detail constructor, along with the output_multiple and min_noutput_items of the block. See single_threaded_scheduler.cc and block_executor.cc
The sub classing of the work function that happens in your module doesn't seem to have any constraint on max_noutput_items based on the payload size, which is default set to 16384, or the MTU / packet length passed in as an argument.
The code would need to be modified to add such a check or set_max_noutput_items would need to be set for the given block based on the packet length, either before use or in the constructor, which currently defaults to the inherited value of 0 and the flag of value set as false for the rtl_tcp_source_f block which inherits from sync_block which inherits from block.