current version.. forgot to commit
This commit is contained in:
199
lib/Socket.h
Normal file
199
lib/Socket.h
Normal file
@@ -0,0 +1,199 @@
|
||||
#ifndef SOCKET_H
|
||||
#define SOCKET_H
|
||||
|
||||
#include <sys/socket.h>
|
||||
#include <vector>
|
||||
#include <errno.h>
|
||||
#include <netinet/in.h>
|
||||
|
||||
#include "NetworkAddress.h"
|
||||
#include "../exception.h"
|
||||
|
||||
class SocketUDP {
|
||||
|
||||
private:
|
||||
|
||||
static constexpr int MAX_DATAGRAM_SIZE = 64*1024;
|
||||
|
||||
bool bound = false;
|
||||
|
||||
public:
|
||||
|
||||
/** ctor */
|
||||
SocketUDP() : handle(0) {
|
||||
|
||||
// create socket
|
||||
handle = socket(AF_INET, SOCK_DGRAM, 0);
|
||||
if (handle == -1) {throw Exception("error while creating socket");}
|
||||
|
||||
}
|
||||
|
||||
/** dtor */
|
||||
~SocketUDP() {
|
||||
close();
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief bind the socket to receive all datagrams sent to the given (local) port
|
||||
* a localPort of 0 will let the OS determine a free one.
|
||||
* @param localPort the local endpoint for datagrams sent from a remote
|
||||
*/
|
||||
void bind(const uint16_t localPort) {
|
||||
|
||||
if (bound) {throw Exception("socket already bound!");}
|
||||
|
||||
// local endpoint AF_INET struct
|
||||
struct sockaddr_in srvAddr;
|
||||
memset((char*)&srvAddr, 0, sizeof(srvAddr));
|
||||
srvAddr.sin_family = AF_INET;
|
||||
srvAddr.sin_addr.s_addr = htonl(INADDR_ANY); // every interface
|
||||
srvAddr.sin_port = htons(localPort);
|
||||
|
||||
// bind the socket to the given port
|
||||
int ret = ::bind(handle, (struct sockaddr*) &srvAddr, sizeof(srvAddr));
|
||||
if (ret < 0) {throw Exception("error while binding socket");}
|
||||
|
||||
// mark as bound
|
||||
bound = true;
|
||||
|
||||
}
|
||||
|
||||
/** close the socket */
|
||||
void close() {
|
||||
|
||||
// cleanup
|
||||
if (handle) {
|
||||
::close(handle);
|
||||
handle = 0;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// /** is the socket currently closed? */
|
||||
// bool isClosed() const {
|
||||
// return handle == 0;
|
||||
// }
|
||||
|
||||
// /** allow to broadcast packets using this socket? */
|
||||
// void allowBroadcast(const bool allow) {
|
||||
|
||||
// #if defined(__GNUC__)
|
||||
// const int broadcastEnable = (allow) ? (1) : (0);
|
||||
// const int ret = setsockopt(handle, SOL_SOCKET, SO_BROADCAST, &broadcastEnable, sizeof(broadcastEnable));
|
||||
// if (ret < 0) { throw SocketException("error while enabling broadcast", errno); }
|
||||
// #elif defined(_WIN32)
|
||||
// ;
|
||||
// #endif
|
||||
|
||||
// }
|
||||
|
||||
/**
|
||||
* @brief send a datagram to the given destination address
|
||||
* @param data the data to send
|
||||
* @param len the length of the data to send (max 64k!)
|
||||
* @param addr the destination address
|
||||
*/
|
||||
void sendDatagram(const uint8_t* data, uint32_t len, const NetworkAddress& addr) {
|
||||
|
||||
// sanity check
|
||||
if (!bound) {throw Exception("bind() the socket first!");}
|
||||
|
||||
// ensure max datagram size
|
||||
if (len > MAX_DATAGRAM_SIZE) {throw Exception("max datagram size is " + std::to_string(MAX_DATAGRAM_SIZE)+ " bytes!");}
|
||||
|
||||
// ensure correct destination address
|
||||
if (!addr.isValidTargetPort()) {throw Exception("the given destination address has no valid port number");}
|
||||
if (!addr.isValidTargetHost()) {throw Exception("the given destination address has no valid hostname");}
|
||||
|
||||
// send datagram to the given destionation
|
||||
const struct sockaddr_in& sockAddr = addr.getAsSocketAddress();
|
||||
const int options = 0;
|
||||
const int res = sendto(handle, (const char*)data, len, options, (struct sockaddr*) &sockAddr, sizeof(sockaddr));
|
||||
|
||||
// check
|
||||
if (res < 0) {throw Exception("error while sending datagram");}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief send a datagram to the given destination address
|
||||
* @param data the data to send (max 64k!)
|
||||
* @param addr the destination address
|
||||
*/
|
||||
void sendDatagram(const std::vector<uint8_t>& data, const NetworkAddress& addr) {
|
||||
sendDatagram(data.data(), (uint32_t) data.size(), addr);
|
||||
}
|
||||
|
||||
void sendDatagram(const std::string& data, const NetworkAddress& addr) {
|
||||
sendDatagram((const uint8_t*)data.data(), data.length(), addr);
|
||||
}
|
||||
|
||||
// /**
|
||||
// * @brief send the given datagram to its internal destination address
|
||||
// * @param d the datagram to send
|
||||
// */
|
||||
// void sendDatagram(const Datagram& d) {
|
||||
// sendDatagram(d.getData(), d.getLength(), d.getAddress());
|
||||
// }
|
||||
|
||||
|
||||
// /**
|
||||
// * @brief convenience function for receiveDatagram(d) which returns a new
|
||||
// * datagram instead of reusing an existing one.
|
||||
// * @return a newly created datagram holding the received message
|
||||
// */
|
||||
// DefaultDatagram receiveDatagram() {
|
||||
// DefaultDatagram dd;
|
||||
// receiveDatagram(dd);
|
||||
// return dd;
|
||||
// }
|
||||
|
||||
// /**
|
||||
// * @brief this method will block until a new datagram is received on the bound
|
||||
// * port of the underlying socket. the received data will be stored within the
|
||||
// * given datagram
|
||||
// * @param d the buffer to store the received datagram to
|
||||
// */
|
||||
// void receiveDatagram(Datagram& d) {
|
||||
|
||||
// const int flags = 0;
|
||||
// const int maxSize = MAX_DATAGRAM_SIZE;
|
||||
|
||||
// // sanity check
|
||||
// if (!bound) {throw SocketException("bind() the socket first!");}
|
||||
|
||||
// // ensure the target buffer may hold the largest possible datagram
|
||||
// d.ensureSpace(maxSize);
|
||||
|
||||
// // the datagrams sender will be stored here
|
||||
// struct sockaddr_in senderAddr;
|
||||
// socklen_t senderLength = sizeof(senderAddr);
|
||||
|
||||
// // receive datagram from socket and store sender information
|
||||
// int len = recvfrom(handle, (char*) d.getDataWriteable(), maxSize, flags, (struct sockaddr*) &senderAddr, &senderLength);
|
||||
// if (len < 0) {throw SocketException("error while receiving datagram", errno);}
|
||||
|
||||
// // store senders network-address in the datagram
|
||||
// NetworkAddress na(senderAddr);
|
||||
// d.setAddress(na);
|
||||
|
||||
// // inform buffer about the actual size of the datagram
|
||||
// d.setLength( (uint32_t) len );
|
||||
|
||||
// }
|
||||
|
||||
|
||||
|
||||
private:
|
||||
|
||||
/** the socket handle */
|
||||
int handle;
|
||||
|
||||
/** the local address the socket is bound to */
|
||||
NetworkAddress localAddress;
|
||||
|
||||
};
|
||||
|
||||
|
||||
|
||||
#endif // SOCKET_H
|
||||
Reference in New Issue
Block a user