/*
* Kraken
* Copyright (C) 2007 Rodrigo Cacilhas
*
* This program 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 3 of the License, or
* (at your option) any later version.
*
* This program 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 this program. If not, see .
*/
#include
#include "KrakenSocket.h"
sockaddr_t *getAddr(string, unsigned int);
int getClientConnection(int, sockaddr_t *);
KrakenSocket::KrakenSocket(int socket_id, sockaddr_t *naddr): addr(naddr), closed(false), sid(socket_id), socktype("client") {
/*
* Construtor privado
*
* Recebe endereço e socket prontos - usado para criação de socket
* cliente
*/
}// KrakenSocket::KrakenSocket(int, sockaddr_t *)
KrakenSocket::KrakenSocket(int domain, int type): addr(NULL), socktype("master") {
/*
* Construtor público
*
* Para criação de socket mestre
*/
// Cria socket
sid = socket(domain, type, 0);
// Se falhar, nasce fechado
if (sid < 0)
closed = true;
else
closed = false;
}// KrakenSocket::KrakenSocket(int, int)
KrakenSocket::~KrakenSocket() {
/*
* Destruidor
*
* Encerra socket e desaloca memória
*/
close();
delete addr;
}// KrakenSocket::~KrakenSocket()
KrakenSocket *KrakenSocket::accept(void) {
/*
* Aceita conexões
*/
if (socktype != "server")
return NULL; // somente socket servidor
// naddr recebe endereço do cliente
sockaddr_t *naddr = new sockaddr_t;
// Obtém socket cliente real
int socket_id = getClientConnection(sid, naddr);
if (socket_id < 0)
return NULL; // algo saiu errado
else
return new KrakenSocket(socket_id, naddr);
}// KrakenSocket *KrakenSocket::accept(void)
bool KrakenSocket::bind(string host, unsigned int port) {
/*
* Associa endereço ao socket
*/
if (socktype != "master")
return false; // somente socket master
// Obtém endereço do IP e da porta
addr = getAddr(host, port);
socktype = "server";
if (::bind(sid, (struct sockaddr *) addr, sizeof(struct sockaddr)) == 0)
return true;
else {
addr = NULL;
return false;
}
}// bool KrakenSocket::bind(string, unsigned int)
bool KrakenSocket::close(void) {
/*
* Encerra socket se já não estiver encerrado
*/
if (!closed) {
if (::close(sid) == 0) {
closed = true;
return true;
} else
return false;
} else
return false;
}// bool KrakenSocket::close(void)
string KrakenSocket::getip(void) {
/*
* Obtém IP associado ao socket
*/
if (addr == NULL)
return ""; // nenhum endereço associado
// Obtém IP do endereço
string ip(inet_ntoa(addr->sin_addr));
return ip;
}// string KrakenSocket::getip(void)
unsigned int KrakenSocket::getport(void) {
/*
* Obtém porta associada ao socket
*/
if (addr == NULL)
return 0; // nenhum endereço associado
// Obtém porta do endereço
unsigned int port = ntohs(addr->sin_port);
return port;
}// unsigned int KrakenSocket::getport(void)
bool KrakenSocket::getsockopt(int optname) {
/*
* Obtém opção de socket
*/
int on = 0;
socklen_t sizeof_int = sizeof(int);
int r = ::getsockopt(sid, SOL_SOCKET, optname, (char *)&on, &sizeof_int);
if (r == 0) {
if (on == 1)
return true;
else
return false;
} else
return false;
}// bool KrakenSocket::getsockopt(int)
int *KrakenSocket::gettimeout(void) {
/*
* Obtém os valores de timeout
*/
socklen_t sizeof_int = sizeof(int);
int *timeout = new int[2];
// [0] = rcvtimeo, [1] = sndtimeo
int r = ::getsockopt(sid, SOL_SOCKET, SO_RCVTIMEO, (char *)timeout, &sizeof_int) +
::getsockopt(sid, SOL_SOCKET, SO_SNDTIMEO, (char *)(timeout + 1), &sizeof_int);
if (r != 0) {
timeout[0] = -1;
timeout[1] = -1;
}
return timeout;
}// int *KrakenSocket::gettimeout(void)
string KrakenSocket::gettype(void) {
/*
* Retorna o tipo
*/
// Faz uma cópia do tipo para retornar
string aux;
stringstream ss;
ss << socktype;
ss >> aux;
return aux;
}// string KrakenSocket::gettype(void)
bool KrakenSocket::isclosed(void) {
/*
* Retorna se o socket está fechado ou não
*/
return closed;
}// bool KrakenSocket::isclosed(void)
bool KrakenSocket::listen(unsigned int max) {
/*
* Registra limite de fila do socket
*/
if (::listen(sid, max) == 0)
return true;
else
return false;
}// bool KrakenSocket::listen(unsigned int)
string KrakenSocket::recv(unsigned int len) {
/*
* Recebe string arbitrária de tamanho len pelo socket
*/
// c_str que receberá a string
char *received = new char[len + 2];
int reallen = ::recv(sid, received, len, 0);
// Retorna a string
if (reallen > 0) {
string aux(received);
return aux;
} else
return "";
}// string KrakenSocket::recv(unsigned int)
bool KrakenSocket::send(string tosend) {
/*
* Envia string pelo socket
*/
int sent = ::send(sid, tosend.c_str(), tosend.length(), 0);
if (sent == -1)
return false;
else
return true;
}// bool KrakenSocket::send(string)
bool KrakenSocket::send(unsigned char tosend) {
/*
* Envia um carácter pelo socket
*/
char *aux = new char[2];
aux[0] = tosend;
aux[1] = 0;
int sent = ::send(sid, aux, 1, 0);
if (sent < 0)
return false;
else
return true;
}// bool KrakenSocket::send(unsigned char)
bool KrakenSocket::setsockopt(int optname, bool on) {
/*
* Ajusta opção de socket
*/
int inton; // versão int do booleano
if (on)
inton = 1;
else
inton = 0;
// Ajusta
int r = ::setsockopt(sid, SOL_SOCKET, optname, &inton, sizeof(inton));
// Retorna verdadeiro ou falso
if (r == 0)
return true;
else
return false;
}// bool KrakenSocket::setsockopt(int, bool)
bool KrakenSocket::settimeout(int timeout) {
/*
* Ajusta o timeout
*/
// Ajusta rcvtimeo e sndtimeo com o mesmo valor
int r = ::setsockopt(sid, SOL_SOCKET, SO_RCVTIMEO, &timeout, sizeof(timeout)) +
::setsockopt(sid, SOL_SOCKET, SO_SNDTIMEO, &timeout, sizeof(timeout));
if (r == 0)
return true;
else
return false;
}// bool KrakenSocket::settimeout(int)
sockaddr_t *getAddr(string ip, unsigned int port) {
/*
* Retorna endereço referente ao IP e a porta informados
*/
// Cria um novo endereço
sockaddr_t *addr = new sockaddr_t;
// família AF_INET (rede)
addr->sin_family = AF_INET;
// Ajusta a porta
addr->sin_port = htons(port);
// Ajusta o IP
if ((ip == "0.0.0.0") or (ip == "0") or (ip == "*"))
addr->sin_addr.s_addr = INADDR_ANY;
else
addr->sin_addr.s_addr = inet_addr(ip.c_str());
// Zera demais atributos
memset(&(addr->sin_zero), '\0', 8);
// Retorna o endereço
return addr;
}// sockaddr_t *getAddr(string, unsigned int)
int getClientConnection(int serverskt, sockaddr_t *addr) {
/*
* Aceita novas conexões, altera o endereço de acordo e retona o
* socket cliente
*/
socklen_t sin_size = sizeof(sockaddr_t);
int clientskt = accept(serverskt, (struct sockaddr *) addr, &sin_size);
return clientskt;
}// int getClientConnection(int, sockaddr_t *)