/*
* UDP.cpp
* This file is part of VallauriSoft
*
* Copyright (C) 2012 - Comina Francesco
*
* VallauriSoft 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 of the License, or
* (at your option) any later version.
*
* VallauriSoft 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 VallauriSoft; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor,
* Boston, MA 02110-1301 USA
*/
#ifndef _UDP_CPP_
#define _UDP_CPP_
#include "Socket.hpp"
namespace Socket
{
UDP::UDP(void) : CommonSocket(SOCK_DGRAM)
{
}
UDP::UDP(const UDP &udp) : CommonSocket()
{
this->_socket_id = udp._socket_id;
this->_opened = udp._opened;
this->_binded = udp._binded;
}
template
int UDP::send(Ip ip, Port port, const T *data, size_t len)
{
if (!this->_opened) this->open();
len *= sizeof(T);
if (len > (SOCKET_MAX_BUFFER_LEN * sizeof(T)))
{
stringstream error;
error << "[send] with [ip=" << ip << "] [port=" << port << "] [data=" << data << "] [len=" << len << "] Data length higher then max buffer len";
throw SocketException(error.str());
}
Address address(ip, port);
int ret;
if ((ret = sendto(this->_socket_id, (const char*)data, len, 0, (struct sockaddr*)&address, sizeof(struct sockaddr))) == -1)
{
stringstream error;
error << "[send] with [ip=" << ip << "] [port=" << port << "] [data=" << data << "] [len=" << len << "] Cannot send";
throw SocketException(error.str());
}
return ret;
}
template
int UDP::send(Address address, const T *data, size_t len)
{
return this->send(address.ip(), address.port(), data, len);
}
template
int UDP::send(Ip ip, Port port, T data)
{
return this->send(ip, port, &data, 1);
}
template
int UDP::send(Address address, T data)
{
return this->send(address.ip(), address.port(), &data, 1);
}
template <>
int UDP::send(Ip ip, Port port, string data)
{
return this->send(ip, port, data.c_str(), data.length() + 1);
}
template <>
int UDP::send(Address address, string data)
{
return this->send(address.ip(), address.port(), data.c_str(), data.length() + 1);
}
template
int UDP::send(Ip ip, Port port, vector data)
{
return this->send(ip, port, data.data(), data.size());
}
template
int UDP::send(Address address, vector data)
{
return this->send(address.ip(), address.port(), data.data(), data.size());
}
template
int UDP::receive(Address *address, T *data, size_t len, unsigned int *received_elements)
{
if (!this->_opened) this->open();
if (!this->_binded) throw SocketException("[receive] Make the socket listening before receiving");
len *= sizeof(T);
if (len > (SOCKET_MAX_BUFFER_LEN * sizeof(T)))
{
stringstream error;
error << "[send] with [buffer=" << data << "] [len=" << len << "] Data length higher then max buffer length";
throw SocketException(error.str());
}
int received_bytes;
socklen_t size = sizeof(struct sockaddr);
if ((received_bytes = recvfrom(this->_socket_id, (char*)data, len, 0, (struct sockaddr*)address, (socklen_t*)&size)) == -1)
{
throw SocketException("[receive] Cannot receive");
}
*received_elements = (unsigned int)(received_bytes / sizeof(T));
return received_bytes;
}
template
Datagram UDP::receive(T *buffer, size_t len = SOCKET_MAX_BUFFER_LEN)
{
Datagram ret;
ret.received_bytes = this->receive(&ret.address, buffer, len, &ret.received_elements);
ret.data = buffer;
return ret;
}
template
Datagram UDP::receive(size_t len = N)
{
Datagram ret;
ret.received_bytes = this->receive(&ret.address, ret.data, len, &ret.received_elements);
return ret;
}
template
Datagram UDP::receive(void)
{
Datagram ret;
ret.received_bytes = this->receive(&ret.address, &ret.data, 1, &ret.received_elements);
return ret;
}
template <>
Datagram UDP::receive(void)
{
Datagram ret;
char buffer[SOCKET_MAX_BUFFER_LEN];
ret.received_bytes = this->receive(&ret.address, buffer, SOCKET_MAX_BUFFER_LEN, &ret.received_elements);
ret.data = buffer;
return ret;
}
template
Datagram > UDP::receive(size_t len)
{
Datagram > ret;
T buffer[len];
ret.received_bytes = this->receive(&ret.address, buffer, len, &ret.received_elements);
for (int i = 0; i < ret.received_elements; i++) ret.data.push_back(buffer[i]);
return ret;
}
}
#endif