diff options
Diffstat (limited to 'gnuradio-core/src')
-rw-r--r-- | gnuradio-core/src/lib/io/Makefile.am | 8 | ||||
-rw-r--r-- | gnuradio-core/src/lib/io/gr_udp_sink.cc | 157 | ||||
-rw-r--r-- | gnuradio-core/src/lib/io/gr_udp_sink.h | 103 | ||||
-rw-r--r-- | gnuradio-core/src/lib/io/gr_udp_sink.i | 47 | ||||
-rw-r--r-- | gnuradio-core/src/lib/io/gr_udp_source.cc | 160 | ||||
-rw-r--r-- | gnuradio-core/src/lib/io/gr_udp_source.h | 92 | ||||
-rw-r--r-- | gnuradio-core/src/lib/io/gr_udp_source.i | 43 | ||||
-rw-r--r-- | gnuradio-core/src/lib/io/io.i | 4 |
8 files changed, 612 insertions, 2 deletions
diff --git a/gnuradio-core/src/lib/io/Makefile.am b/gnuradio-core/src/lib/io/Makefile.am index d935619a1c..6891f3807a 100644 --- a/gnuradio-core/src/lib/io/Makefile.am +++ b/gnuradio-core/src/lib/io/Makefile.am @@ -50,7 +50,9 @@ libio_la_SOURCES = \ microtune_xxxx_eval_board.cc \ ppio.cc \ ppio_ppdev.cc \ - sdr_1000.cc + sdr_1000.cc \ + gr_udp_sink.cc \ + gr_udp_source.cc grinclude_HEADERS = \ gr_file_sink.h \ @@ -93,4 +95,6 @@ swiginclude_HEADERS = \ microtune_4702_eval_board.i \ microtune_4937_eval_board.i \ ppio.i \ - sdr_1000.i + sdr_1000.i \ + gr_udp_sink.i \ + gr_udp_source.i diff --git a/gnuradio-core/src/lib/io/gr_udp_sink.cc b/gnuradio-core/src/lib/io/gr_udp_sink.cc new file mode 100644 index 0000000000..f5eefdc73f --- /dev/null +++ b/gnuradio-core/src/lib/io/gr_udp_sink.cc @@ -0,0 +1,157 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio 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 2, or (at your option) + * any later version. + * + * GNU Radio 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 GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include <gr_udp_sink.h> +#include <gr_io_signature.h> +#include <cstdio> +#include <sys/types.h> +#include <sys/stat.h> +#include <fcntl.h> +#include <stdexcept> + +#define SNK_VERBOSE 0 + +gr_udp_sink::gr_udp_sink (size_t itemsize, + const char *ipaddrl, unsigned short portl, + const char *ipaddrr, unsigned short portr, + unsigned int mtu) + : gr_sync_block ("udp_sink", + gr_make_io_signature (1, 1, itemsize), + gr_make_io_signature (0, 0, 0)), + d_itemsize (itemsize), d_updated(false), d_mtu(mtu) +{ + // Set up the address stucture for the local address and port numbers + inet_aton(ipaddrl, &d_ipaddr_local); // format IP address + inet_aton(ipaddrr, &d_ipaddr_remote); // format IP address + d_port_local = htons(portl); // format port number + d_port_remote = htons(portr); // format port number + + d_sockaddr_local.sin_family = AF_INET; + d_sockaddr_local.sin_addr = d_ipaddr_local; + d_sockaddr_local.sin_port = d_port_local; + + d_sockaddr_remote.sin_family = AF_INET; + d_sockaddr_remote.sin_addr = d_ipaddr_remote; + d_sockaddr_remote.sin_port = d_port_remote; + + open(); +} + +// public constructor that returns a shared_ptr + +gr_udp_sink_sptr +gr_make_udp_sink (size_t itemsize, + const char *ipaddrl, unsigned short portl, + const char *ipaddrr, unsigned short portr, + unsigned int mtu) +{ + return gr_udp_sink_sptr (new gr_udp_sink (itemsize, + ipaddrl, portl, + ipaddrr, portr, + mtu)); +} + +gr_udp_sink::~gr_udp_sink () +{ + close(); +} + +bool +gr_udp_sink::open() +{ + omni_mutex_lock l(d_mutex); // hold mutex for duration of this function + + // create socket + if((d_socket = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) == NULL) { + perror("socket open"); + throw std::runtime_error("can't open socket"); + } + + // Turn on reuse address + bool opt_val = true; + if(setsockopt(d_socket, SOL_SOCKET, SO_REUSEADDR, (void*)&opt_val, sizeof(int))) { + perror("SO_REUSEADDR"); + throw std::runtime_error("can't set socket option SO_REUSEADDR"); + } + + // Don't wait when shutting down + linger lngr; + lngr.l_onoff = 1; + lngr.l_linger = 0; + if(setsockopt(d_socket, SOL_SOCKET, SO_LINGER, (void*)&lngr, sizeof(linger))) { + perror("SO_LINGER"); + throw std::runtime_error("can't set socket option SO_LINGER"); + } + + // bind socket to an address and port number to listen on + if(bind (d_socket, (sockaddr*)&d_sockaddr_local, sizeof(struct sockaddr))) { + perror("socket bind"); + throw std::runtime_error("can't bind socket"); + } + + // Not sure if we should throw here or allow retries + if(connect(d_socket, (sockaddr*)&d_sockaddr_remote, sizeof(struct sockaddr))) { + perror("socket connect"); + throw std::runtime_error("can't connect to socket"); + } + + d_updated = true; + return d_socket != 0; +} + +void +gr_udp_sink::close() +{ + omni_mutex_lock l(d_mutex); // hold mutex for duration of this function + + if (d_socket){ + shutdown(d_socket, SHUT_RDWR); + d_socket = 0; + } + d_updated = true; +} + +int +gr_udp_sink::work (int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items) +{ + char *in = (char *) input_items[0]; + socklen_t bytes=0, bytes_sent=0, bytes_to_send=0; + unsigned int total_size = noutput_items*d_itemsize; + + while(bytes_sent < total_size) { + bytes_to_send = (bytes_sent+d_mtu < total_size ? d_mtu : total_size-bytes_sent); + bytes =send(d_socket, (in+bytes_sent), bytes_to_send, MSG_DONTWAIT); + bytes_sent += bytes; + } + + #if SNK_VERBOSE + printf("Sent: %d bytes (noutput_items: %d)\n", bytes_sent, noutput_items); + #endif + + return noutput_items; +} diff --git a/gnuradio-core/src/lib/io/gr_udp_sink.h b/gnuradio-core/src/lib/io/gr_udp_sink.h new file mode 100644 index 0000000000..f3ededa524 --- /dev/null +++ b/gnuradio-core/src/lib/io/gr_udp_sink.h @@ -0,0 +1,103 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio 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 2, or (at your option) + * any later version. + * + * GNU Radio 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 GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#ifndef INCLUDED_GR_UDP_SINK_H +#define INCLUDED_GR_UDP_SINK_H + +#include <gr_sync_block.h> +#include <omnithread.h> +#include <sys/socket.h> +#include <arpa/inet.h> + +class gr_udp_sink; +typedef boost::shared_ptr<gr_udp_sink> gr_udp_sink_sptr; + +/*! + * \brief Write stream to an Udp port (over UDP). + * \ingroup sink + */ + +gr_udp_sink_sptr +gr_make_udp_sink (size_t itemsize, + const char *ipaddrl, unsigned short portl, + const char *ipaddrr, unsigned short portr, + unsigned int mtu=540); + +class gr_udp_sink : public gr_sync_block +{ + friend gr_udp_sink_sptr gr_make_udp_sink (size_t itemsize, + const char *ipaddrl, unsigned short portl, + const char *ipaddrr, unsigned short portr, + unsigned int mtu); + private: + size_t d_itemsize; + bool d_updated; + omni_mutex d_mutex; + + unsigned int d_mtu; // maximum transmission unit (packet length) + int d_socket; // handle to socket + int d_socket_rcv; // handle to socket retuned in the accept call + struct in_addr d_ipaddr_local; // store the local IP address to use + struct in_addr d_ipaddr_remote; // store the remote IP address that connected to us + unsigned short d_port_local; // the port number to open for connections to this service + unsigned short d_port_remote; // port number of the remove system + sockaddr_in d_sockaddr_local; // store the local sockaddr data (formatted IP address and port number) + sockaddr_in d_sockaddr_remote; // store the remote sockaddr data (formatted IP address and port number) + + protected: + gr_udp_sink (size_t itemsize, + const char *ipaddrl, unsigned short portl, + const char *ipaddrr, unsigned short portr, + unsigned int mtu); + + public: + ~gr_udp_sink (); + + /*! + * \brief open a socket specified by the port and ip address info + * + * Opens a socket, binds to the address, and makes connectionless association + * over UDP. If any of these fail, the fuction retuns the error and exits. + */ + bool open(); + + /*! + * \brief Close current socket. + * + * Shuts down read/write on the socket + */ + void close(); + + /*! \brief set the MTU of the socket */ + void set_mtu(unsigned int mtu) { d_mtu = mtu; } + + /*! \brief return the MTU of the socket */ + unsigned int mtu() { return d_mtu; } + + // should we export anything else? + + int work (int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items); +}; + +#endif /* INCLUDED_GR_UDP_SINK_H */ diff --git a/gnuradio-core/src/lib/io/gr_udp_sink.i b/gnuradio-core/src/lib/io/gr_udp_sink.i new file mode 100644 index 0000000000..59c828dd6e --- /dev/null +++ b/gnuradio-core/src/lib/io/gr_udp_sink.i @@ -0,0 +1,47 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio 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 2, or (at your option) + * any later version. + * + * GNU Radio 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 GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + + +GR_SWIG_BLOCK_MAGIC(gr,udp_sink) + +gr_udp_sink_sptr +gr_make_udp_sink (size_t itemsize, + const char *ipaddrl, unsigned short portl, + const char *ipaddrr, unsigned short portr, + unsigned int mtu=540); + +class gr_udp_sink : public gr_sync_block +{ + protected: + gr_udp_sink (size_t itemsize, + const char *ipaddrl, unsigned short portl, + const char *ipaddrr, unsigned short portr, + unsigned int mtu); + + bool open(); + void close(); + void set_mtu(unsigned int mtu) { d_mtu = mtu; } + unsigned int mtu() { return d_mtu; } + + public: + ~gr_udp_sink (); +}; diff --git a/gnuradio-core/src/lib/io/gr_udp_source.cc b/gnuradio-core/src/lib/io/gr_udp_source.cc new file mode 100644 index 0000000000..426830924c --- /dev/null +++ b/gnuradio-core/src/lib/io/gr_udp_source.cc @@ -0,0 +1,160 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004,2006 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio 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 2, or (at your option) + * any later version. + * + * GNU Radio 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 GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include <gr_udp_source.h> +#include <gr_io_signature.h> +#include <cstdio> +#include <sys/types.h> +#include <sys/stat.h> +#include <fcntl.h> +#include <stdexcept> + +#define SRC_VERBOSE 0 + +gr_udp_source::gr_udp_source(size_t itemsize, const char *ipaddr, + unsigned short port, unsigned int mtu) + : gr_sync_block ("udp_source", + gr_make_io_signature(0, 0, 0), + gr_make_io_signature(1, 1, itemsize)), + d_itemsize(itemsize), d_updated(false), d_mtu(mtu) +{ + // Set up the address stucture for the local address and port numbers + inet_aton(ipaddr, &d_ipaddr_local); // format IP address + d_port_local = htons(port); // format port number + + d_sockaddr_local.sin_family = AF_INET; + d_sockaddr_local.sin_addr = d_ipaddr_local; + d_sockaddr_local.sin_port = d_port_local; + + open(); +} + +gr_udp_source_sptr +gr_make_udp_source (size_t itemsize, const char *ipaddr, + unsigned short port, unsigned int mtu) +{ + return gr_udp_source_sptr (new gr_udp_source (itemsize, ipaddr, + port, mtu)); +} + +gr_udp_source::~gr_udp_source () +{ + close(); +} + +bool +gr_udp_source::open() +{ + omni_mutex_lock l(d_mutex); // hold mutex for duration of this function + + // create socket + d_socket = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP); + if(d_socket == 0) { + perror("socket open"); + throw std::runtime_error("can't open socket"); + } + + // Turn on reuse address + bool opt_val = true; + if(setsockopt(d_socket, SOL_SOCKET, SO_REUSEADDR, (void*)&opt_val, sizeof(int))) { + perror("SO_REUSEADDR"); + throw std::runtime_error("can't set socket option SO_REUSEADDR"); + } + + // Don't wait when shutting down + linger lngr; + lngr.l_onoff = 1; + lngr.l_linger = 0; + if(setsockopt(d_socket, SOL_SOCKET, SO_LINGER, (void*)&lngr, sizeof(linger))) { + perror("SO_LINGER"); + throw std::runtime_error("can't set socket option SO_LINGER"); + } + + // Set a timeout on the receive function to not block indefinitely + // This value can (and probably should) be changed + timeval timeout; + timeout.tv_sec = 1; + timeout.tv_usec = 0; + if(setsockopt(d_socket, SOL_SOCKET, SO_RCVTIMEO, (void*)&timeout, sizeof(timeout))) { + perror("SO_RCVTIMEO"); + throw std::runtime_error("can't set socket option SO_RCVTIMEO"); + } + + // bind socket to an address and port number to listen on + if(bind (d_socket, (sockaddr*)&d_sockaddr_local, sizeof(struct sockaddr))) { + perror("socket bind"); + throw std::runtime_error("can't bind socket"); + } + + d_updated = true; + return d_socket != 0; +} + +void +gr_udp_source::close() +{ + omni_mutex_lock l(d_mutex); // hold mutex for duration of this function + + if (d_socket){ + shutdown(d_socket, SHUT_RDWR); + d_socket = 0; + } + d_updated = true; +} + +int +gr_udp_source::work (int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items) +{ + char *out = (char *) output_items[0]; + socklen_t bytes_to_receive=0, bytes_received=0; + int bytes=0; + + while((bytes_received < (unsigned)noutput_items) && (bytes>-1)) { + // caclulate the number of byte left if we can fit in all d_mtu bytes + bytes_to_receive = (bytes_received+d_mtu < noutput_items ? + d_mtu : noutput_items-bytes_received); + + // get the data into our output buffer and record the number of bytes + // This is a blocking call, but it's timeout has been set in the constructor + bytes = recv(d_socket, out, bytes_to_receive, 0); + + if(bytes > 0) { + // keep track of the total number of bytes received + bytes_received += bytes; + + // increment the pointer + out += bytes; + } + } + + #if SRC_VERBOSE + printf("\nTotal Bytes Received: %d (noutput_items=%d)\n", bytes_received, noutput_items); + #endif + + return int(bytes_received / d_itemsize); +} diff --git a/gnuradio-core/src/lib/io/gr_udp_source.h b/gnuradio-core/src/lib/io/gr_udp_source.h new file mode 100644 index 0000000000..162eef7d64 --- /dev/null +++ b/gnuradio-core/src/lib/io/gr_udp_source.h @@ -0,0 +1,92 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio 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 2, or (at your option) + * any later version. + * + * GNU Radio 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 GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#ifndef INCLUDED_GR_UDP_SOURCE_H +#define INCLUDED_GR_UDP_SOURCE_H + +#include <gr_sync_block.h> +#include <omnithread.h> +#include <sys/socket.h> +#include <arpa/inet.h> + +class gr_udp_source; +typedef boost::shared_ptr<gr_udp_source> gr_udp_source_sptr; + +gr_udp_source_sptr gr_make_udp_source(size_t itemsize, const char *ipaddr, + unsigned short port, unsigned int mtu=540); + +class gr_udp_source : public gr_sync_block +{ + friend gr_udp_source_sptr gr_make_udp_source(size_t itemsize, const char *ipaddr, + unsigned short port, unsigned int mtu); + + private: + size_t d_itemsize; + bool d_updated; + omni_mutex d_mutex; + + unsigned int d_mtu; // maximum transmission unit (packet length) + int d_socket; // handle to socket + int d_socket_rcv; // handle to socket retuned in the accept call + struct in_addr d_ipaddr_local; // store the local IP address to use + struct in_addr d_ipaddr_remote; // store the remote IP address that connected to us + unsigned short d_port_local; // the port number to open for connections to this service + unsigned short d_port_remote; // port number of the remove system + sockaddr_in d_sockaddr_local; // store the local sockaddr data (formatted IP address and port number) + sockaddr_in d_sockaddr_remote; // store the remote sockaddr data (formatted IP address and port number) + + protected: + gr_udp_source(size_t itemsize, const char *ipaddr, unsigned short port, unsigned int mtu); + + public: + ~gr_udp_source(); + + /*! + * \brief open a socket specified by the port and ip address info + * + * Opens a socket, binds to the address, and waits for a connection + * over UDP. If any of these fail, the fuction retuns the error and exits. + */ + bool open(); + + /*! + * \brief Close current socket. + * + * Shuts down read/write on the socket + */ + void close(); + + /*! \brief set the MTU of the socket */ + void set_mtu(unsigned int mtu) { d_mtu = mtu; } + + /*! \brief return the MTU of the socket */ + unsigned int mtu() { return d_mtu; } + + // should we export anything else? + + int work(int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items); +}; + + +#endif /* INCLUDED_GR_UDP_SOURCE_H */ diff --git a/gnuradio-core/src/lib/io/gr_udp_source.i b/gnuradio-core/src/lib/io/gr_udp_source.i new file mode 100644 index 0000000000..e1e9c20236 --- /dev/null +++ b/gnuradio-core/src/lib/io/gr_udp_source.i @@ -0,0 +1,43 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio 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 2, or (at your option) + * any later version. + * + * GNU Radio 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 GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +GR_SWIG_BLOCK_MAGIC(gr,udp_source) + +gr_udp_source_sptr +gr_make_udp_source (size_t itemsize, const char *ipaddr, + unsigned short port, unsigned int mtu=540); + +class gr_udp_source : public gr_sync_block +{ + protected: + gr_udp_source (size_t itemsize, const char *ipaddr, + unsigned short port, unsigned int mtu); + + public: + ~gr_udp_source (); + + bool open(); + void close(); + void set_mtu(unsigned int mtu) { d_mtu = mtu; } + unsigned int mtu() { return d_mtu; } + +}; diff --git a/gnuradio-core/src/lib/io/io.i b/gnuradio-core/src/lib/io/io.i index 015e208018..e6ed4c6a15 100644 --- a/gnuradio-core/src/lib/io/io.i +++ b/gnuradio-core/src/lib/io/io.i @@ -34,6 +34,8 @@ #include <ppio.h> #include <gr_message_source.h> #include <gr_message_sink.h> +#include <gr_udp_sink.cc> +#include <gr_udp_source.cc> %} @@ -49,4 +51,6 @@ %include "ppio.i" %include "gr_message_source.i" %include "gr_message_sink.i" +%include "gr_udp_sink.i" +%include "gr_udp_source.i" |