void Server::setNonBlock(int fd){ int oflags = fcntl(sfd, F_GETFL); if(-1 == oflags){ throw ErrException(errno); } oflags |= O_NONBLOCK; if(-1 == fcntl(sfd, F_SETFL, oflags)){ throw ErrException(errno); } }
void Server::bindMasterSocket(const std::string& host, uint16_t port){ memset(&saddr, 0, sizeof(saddr)); saddr.sin_family = AF_INET; saddr.sin_port = htons(port); //saddr.sin_addr.s_addr = htonl(INADDR_ANY); // TODO test AI_PASSIVE; and getaddrinfo(); if( 1 > inet_pton(AF_INET, host.c_str(), &saddr.sin_addr)){ throw ErrException(errno); } if(-1 == bind(sfd, reinterpret_cast<sockaddr*>(&saddr), sizeof(saddr))){ throw ErrException(errno); } }
int UDPSocket::recv(void * data, int size) { int bytes; struct sockaddr_storage saddr; socklen_t length = sizeof (saddr); BOOST_ASSERT(data != NULL); BOOST_ASSERT(sock >= 0); bytes = ::recvfrom(sock, data, size, 0, (struct sockaddr *) &saddr, &length); // TODO: Implement status error (eg. Conn closed, ...) if (bytes < 0) throw ErrException("UDPSocket", "recvfrom"); if (bytes == 0) { //Socket is now closed BOOST_VERIFY(sock < 0); return 0; } /** * recv doesn't set the after-the-last byte to zero. We must do it to * avoid some issues. * (writing into a prefilled longer data buffer f***s everything up) */ if (bytes < size) ((char*) data)[bytes] = 0; lastRecvAddr = SockAddress((const sockaddr *) &saddr); return bytes; }
void UDPSocket::bindToDevice(const std::string& devicename) { if (sock < 0) { this->create(); } if (setsockopt(sock, SOL_SOCKET, SO_BINDTODEVICE, devicename.c_str(), devicename.length() + 1) < 0) throw ErrException("UDPSocket", "setsockopt(SO_BINDTODEVICE)"); }
void Server::createMasterSocket(){ sfd = socket(AF_INET, SOCK_STREAM, 0); if(-1 == sfd){ throw ErrException(errno); } // set non block // setNonBlock(sfd); // set reuse addr and port int optval = 1; if(-1 == setsockopt(sfd, SOL_SOCKET, SO_REUSEADDR, &optval, sizeof(optval))){ throw ErrException(errno); } optval = 1; if(-1 == setsockopt(sfd, SOL_SOCKET, (SO_REUSEPORT), &optval, sizeof(optval))){ throw ErrException(errno); } }
void UDPSocket::setBroadcast(bool enable) { if (sock < 0) { this->create(); } int boolean = (enable ? 1 : 0); if (setsockopt(sock, SOL_SOCKET, SO_BROADCAST, &boolean, sizeof (boolean))) { throw ErrException("UDPSocket", "setsokopt(broadcast)"); } }
void UDPSocket::create() { if (sock >= 0) { // Do nothing, it already exists return; } sock = ::socket(AF_INET, SOCK_DGRAM, 0); if (sock == -1) throw ErrException("UDPSocket", "socket"); BOOST_VERIFY(sock >= 0); }
/** * Send bytes through the network * return: number of sent bytes */ int TCPSocket::send(const void *data, int size) { int bytes; EPYX_ASSERT(data != NULL); if (!this->isConnected) this->connect(); EPYX_ASSERT(this->sock >= 0); EPYX_ASSERT(this->isConnected); bytes = ::send(this->sock, data, size, 0); // TODO: Implement status error (ex. Conn closed, ...) if (bytes == -1) throw ErrException("Socket", "send"); return bytes; }
int UDPSocket::send(const void *data, int size) { int bytes; struct sockaddr_storage saddr; // Create a new socket if it does not exist if (sock < 0) { this->create(); } BOOST_ASSERT(data != NULL && size >= 0); address.getSockAddr((struct sockaddr *) &saddr); bytes = ::sendto(this->sock, data, size, 0, (const struct sockaddr *) &saddr, sizeof (saddr)); if (localAddress.empty()) this->updateLocalAddress(); // TODO: Implement status error (ex. Conn closed, ...) if (bytes < 0) throw ErrException("UDPSocket", "sendto"); return bytes; }
int TCPSocket::recv(void *data, int size) { int bytes; BOOST_ASSERT(data != NULL); BOOST_ASSERT(this->sock >= 0); BOOST_ASSERT(this->isConnected); bytes = ::recv(this->sock, data, size, 0); // TODO: Implement status error (eg. Conn closed, ...) if (bytes == -1) throw ErrException("Socket", "recv"); /** * recv doesn't set the after-the-last byte to zero. We must do it to * avoid some issues. * (writing into a prefilled longer data buffer f***s everything up) */ if (bytes < size) ((char*) data)[bytes] = 0; return bytes; }
void TCPServerThread::run() { int newfd = -1; struct sockaddr_storage clientAddr; socklen_t clientAddrLen; Socket *newSock = NULL; _TCPSocketThread *sthread = NULL; int spawnId = 1; // Bind if no socket available if (this->sockfd < 0 && !this->bind()) throw FailException("TCPServer::run", "Unable to bind"); EPYX_ASSERT(this->sockfd >= 0); log::debug << "Listening on " << this->address << log::endl; try { this->running = true; while (this->running && this->sockfd >= 0) { clientAddrLen = sizeof clientAddr; newfd = ::accept(this->sockfd, (struct sockaddr*)&clientAddr, &clientAddrLen); // If this thread was not killed, return if (!this->running || this->sockfd < 0) { ::shutdown(newfd, SHUT_RDWR); ::close(newfd); newfd = -1; break; } if (newfd == -1) throw ErrException("TCPServer::run", "accept"); // Encapsulate socket try { newSock = new TCPSocket(newfd, Address((struct sockaddr*)&clientAddr)); } catch (Exception e) { log::error << "Unable to setup the link:\n" << e << log::endl; if (newSock) delete newSock; else if (newfd >= 0) { // newfd is managed by newSock ::close(newfd); } newSock = NULL; } // Make newfd variable invalid newfd = -1; if (newSock != NULL) { try { sthread = new _TCPSocketThread(this, newSock, this->getThisName(), spawnId++); sthread->start(); } catch (Exception e) { log::error << e << log::endl; log::error << "Unable to start a thread" << log::endl; if (sthread != NULL) delete sthread; delete newSock; } // DO NOT delete newSock nor srun as they are owned by an other thread newSock = NULL; sthread = NULL; } } } catch (Exception e) { log::error << e << log::endl; log::error << "Arg ! An exception killed me !" << log::endl; if (newSock) delete newSock; } log::debug << "Clean exit on " << this->address << log::endl; }
void Server::listenMasterSocket(int maxconn){ if(-1 == listen(sfd, maxconn)){ throw ErrException(errno); } }
Logger::Logger() { logfile.open(LogFileName, std::ofstream::app); if(false == logfile.is_open()){ throw ErrException("log file :"); } }