Fawkes API Fawkes Development Version
|
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