#include "EPoll.h" #include "Socket.h" #include "Exception.h" #include "Log.h" namespace core { Socket::Socket(EPoll &ePoll) : ePoll(ePoll) { Log(LOG_DEBUG_2) << "BMASocket object created."; Log(LOG_DEBUG_3) << "Buffer size set to default (4096)."; buffer = (char *)malloc(4096); length = 4096; } Socket::~Socket() { ePoll.unregisterSocket(this); close(descriptor); free(buffer); } void Socket::setDescriptor(int descriptor) { Log(LOG_DEBUG_3) << "Descriptor set to " << descriptor << " for Socket."; if(descriptor < 3) throw Exception("Descriptor out of range", __FILE__, __LINE__); this->descriptor = descriptor; onTLSInit(); } int Socket::getDescriptor() { return descriptor; } void Socket::onTLSInit() {} void Socket::setBufferSize(int length) { buffer = (char *)realloc(buffer, length); this->length = length; } void Socket::onRegistered() { onConnected(); } void Socket::onUnregistered() { // onDisconnected(); } void Socket::eventReceived(struct epoll_event event) { if(event.events & EPOLLRDHUP) { Log(LOG_DEBUG_2) << "Socket " << descriptor << " received disconnect from client."; shutdown(); return; } if(event.events & EPOLLIN) receiveData(buffer, length); if(event.events & EPOLLOUT) writeSocket(); enable(true); } void Socket::enable(bool mode) { if(mode) { if(fifo.empty()) active ? resetRead(): setRead(); else active ? resetReadWrite(5): setReadWrite(); active = true; } else clear(); } void Socket::receiveData(char *buffer, int bufferLength) { if(bufferLength <= 0) throw Exception("Request to receive data with a zero buffer length.", __FILE__, __LINE__, -1); int len; int error = -1; if((len = ::read(getDescriptor(), buffer, bufferLength)) >= 0) onDataReceived(std::string(buffer, len)); else { error = errno; switch (error) { // When a listening socket receives a connection // request we get one of these. // case ENOTCONN: onDataReceived(std::string(buffer, 0)); break; case ECONNRESET: break; default: throw Exception("Error in read of data from socket.", __FILE__, __LINE__, error); } } } void Socket::onConnected() { } void Socket::writeSocket() { lock.lock(); if(fifo.size() > 0) { ::write(descriptor, fifo.front().c_str(), fifo.front().length()); fifo.pop(); enable(true); } lock.unlock(); } void Socket::write(std::string data) { lock.lock(); fifo.emplace(data); enable(true); lock.unlock(); } void Socket::output(std::stringstream &out) { out << "|" << descriptor << "|"; } void Socket::setRead() { event.data.fd = descriptor; event.events = EPOLLIN | EPOLLONESHOT | EPOLLRDHUP | EPOLLET; epoll_ctl(ePoll.getDescriptor(), EPOLL_CTL_DEL, descriptor, NULL); epoll_ctl(ePoll.getDescriptor(), EPOLL_CTL_ADD, event.data.fd, &event); } void Socket::setWrite() { event.data.fd = descriptor; event.events = EPOLLOUT | EPOLLONESHOT | EPOLLRDHUP | EPOLLET; epoll_ctl(ePoll.getDescriptor(), EPOLL_CTL_DEL, descriptor, NULL); epoll_ctl(ePoll.getDescriptor(), EPOLL_CTL_ADD, descriptor, &event); } void Socket::setReadWrite() { event.data.fd = descriptor; event.events = EPOLLIN | EPOLLWRNORM | EPOLLONESHOT | EPOLLRDHUP | EPOLLET; epoll_ctl(ePoll.getDescriptor(), EPOLL_CTL_DEL, descriptor, NULL); epoll_ctl(ePoll.getDescriptor(), EPOLL_CTL_ADD, descriptor, &event); } void Socket::resetRead() { event.data.fd = descriptor; event.events = EPOLLIN | EPOLLONESHOT | EPOLLRDHUP | EPOLLET; epoll_ctl(ePoll.getDescriptor(), EPOLL_CTL_MOD, descriptor, &event); } void Socket::resetWrite() { event.data.fd = descriptor; event.events = EPOLLOUT | EPOLLONESHOT | EPOLLRDHUP | EPOLLET; epoll_ctl(ePoll.getDescriptor(), EPOLL_CTL_MOD, descriptor, &event); } void Socket::resetReadWrite(int x) { event.data.fd = descriptor; event.events = EPOLLIN | EPOLLOUT | EPOLLONESHOT | EPOLLRDHUP | EPOLLET; epoll_ctl(ePoll.getDescriptor(), EPOLL_CTL_MOD, descriptor, &event); } void Socket::clear() { epoll_ctl(ePoll.getDescriptor(), EPOLL_CTL_DEL, descriptor, NULL); } void Socket::shutdown() { Log (LOG_DEBUG_2) << "Shutdown requested on socket " << descriptor << "."; shutDown = true; enable(false); delete this; } }