/* * 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 *)