Fawkes API Fawkes Development Version

datagram_broadcast.cpp

00001 
00002 /***************************************************************************
00003  *  datagram_broadcast.cpp - Fawkes datagram broadcast socket (UDP)
00004  *
00005  *  Created: Fri 02 Apr 2010 03:30:55 PM CEST
00006  *  Copyright  2006  Tim Niemueller [www.niemueller.de]
00007  *  Copyright  2010  Christoph Schwering
00008  *
00009  ****************************************************************************/
00010 
00011 /*  This program is free software; you can redistribute it and/or modify
00012  *  it under the terms of the GNU General Public License as published by
00013  *  the Free Software Foundation; either version 2 of the License, or
00014  *  (at your option) any later version. A runtime exception applies to
00015  *  this software (see LICENSE.GPL_WRE file mentioned below for details).
00016  *
00017  *  This program is distributed in the hope that it will be useful,
00018  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
00019  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00020  *  GNU Library General Public License for more details.
00021  *
00022  *  Read the full text in the LICENSE.GPL_WRE file in the doc directory.
00023  */
00024 
00025 #include <netcomm/socket/datagram_broadcast.h>
00026 
00027 #include <sys/socket.h>
00028 #include <netinet/in.h>
00029 #include <arpa/inet.h>
00030 #include <cstdlib>
00031 #include <cstring>
00032 #include <cerrno>
00033 
00034 namespace fawkes {
00035 
00036 /** @class BroadcastDatagramSocket netcomm/socket/datagram.h
00037  * Broadcast datagram socket.
00038  * An broadcast UDP socket on top of IP.
00039  *
00040  * @ingroup NetComm
00041  * @author Christoph Schwering
00042  */
00043 
00044 /** Constructor.
00045  * @param broadcast_addr_s textual representation of the broadcast IP address
00046  * to use for broadcast communication. NOT a hostname!
00047  * @param port port
00048  * @param timeout timeout, if 0 all operationsare blocking, otherwise it
00049  * is tried for timeout seconds.
00050  */
00051 BroadcastDatagramSocket::BroadcastDatagramSocket(const char *broadcast_addr_s,
00052                                                  unsigned short port,
00053                                                  float timeout)
00054   : Socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP, timeout)
00055 {
00056   broadcast_addr = (struct ::sockaddr_in *)malloc(sizeof(struct ::sockaddr_in));
00057 
00058   struct in_addr a;
00059   if ( inet_aton(broadcast_addr_s, &a) == -1 ) {
00060     throw SocketException("Invalid address given");
00061   }
00062   broadcast_addr->sin_family = AF_INET;
00063   broadcast_addr->sin_addr.s_addr = a.s_addr;
00064   broadcast_addr->sin_port = htons(port);
00065 
00066 #if 0
00067   //set_ttl(1);
00068   set_loop(false);
00069 #endif
00070 }
00071 
00072 
00073 /** Destructor. */
00074 BroadcastDatagramSocket::~BroadcastDatagramSocket()
00075 {
00076   free(broadcast_addr);
00077 }
00078 
00079 
00080 /** Copy constructor.
00081  * @param datagram_socket socket to copy.
00082  */
00083 BroadcastDatagramSocket::BroadcastDatagramSocket(BroadcastDatagramSocket &datagram_socket)
00084   : Socket(datagram_socket)
00085 {
00086   broadcast_addr = (struct ::sockaddr_in *)malloc(sizeof(struct ::sockaddr_in));
00087   memcpy(broadcast_addr, datagram_socket.broadcast_addr, sizeof(struct ::sockaddr_in));
00088 }
00089 
00090 
00091 /** Bind socket.
00092  * This will make the socket listen for incoming traffic.
00093  */
00094 void
00095 BroadcastDatagramSocket::bind()
00096 {
00097   int broadcast = 1;
00098   if ( setsockopt(sock_fd, SOL_SOCKET, SO_BROADCAST, &broadcast, sizeof(broadcast)) == -1) {
00099     throw SocketException("Could not set SO_BROADCAST", errno);
00100   }
00101 
00102   int reuse = 1;
00103   if ( setsockopt(sock_fd, SOL_SOCKET, SO_REUSEADDR, &reuse, sizeof(reuse)) == -1) {
00104     throw SocketException("Could not set SO_REUSEADDR", errno);
00105   }
00106 
00107   struct ::sockaddr_in local;
00108   local.sin_family = AF_INET;
00109   local.sin_addr.s_addr = INADDR_ANY;
00110   local.sin_port = broadcast_addr->sin_port;
00111 
00112   if (::bind(sock_fd, (struct ::sockaddr *) &local, sizeof(local)) < 0) {
00113     throw SocketException("Could not bind to port", errno);
00114   }
00115 }
00116 
00117 
00118 /** Clone socket.
00119  * @return a copied instance of BroadcastDatagramSocket.
00120  */
00121 Socket *
00122 BroadcastDatagramSocket::clone()
00123 {
00124   return new BroadcastDatagramSocket(*this);
00125 }
00126 
00127 
00128 /** Send data.
00129  * This will send the given data to the broadcast address specified
00130  * in the constructor.
00131  * @param buf buffer to write
00132  * @param buf_len length of buffer, number of bytes to write to stream
00133  */
00134 void
00135 BroadcastDatagramSocket::send(void *buf, unsigned int buf_len)
00136 {
00137   try {
00138     Socket::send(buf, buf_len, (struct ::sockaddr *)broadcast_addr, sizeof(struct ::sockaddr_in));
00139   } catch (SocketException &e) {
00140     e.append("BroadcastDatagramSocket::send(void*, unsigned int) failed");
00141     throw;
00142   }
00143 }
00144 
00145 } // end namespace fawkes
 All Classes Namespaces Functions Variables Typedefs Enumerations Enumerator Friends