diff --git a/gameentry.cpp b/gameentry.cpp new file mode 100644 index 0000000..456ecd2 --- /dev/null +++ b/gameentry.cpp @@ -0,0 +1,18 @@ +#include "gameentry.h" + +int GameEntry::compare(const GameEntry* ge) +{ + if (this->addr.s_addr > ge->addr.s_addr) + return -1; + + if (this->addr.s_addr < ge->addr.s_addr) + return 1; + + if (this->port1 > ge->port1) + return -1; + + if (this->port1 < ge->port1) + return 1; + + return 0; +} diff --git a/gameentry.h b/gameentry.h new file mode 100644 index 0000000..403b57f --- /dev/null +++ b/gameentry.h @@ -0,0 +1,25 @@ +#ifndef _GAMEENTRY_H_ +#define _GAMEENTRY_H_ + +#include +#include + +class GameEntry { +public: + GameEntry() {}; + ~GameEntry() {}; + + int compare(const GameEntry* ge); + + struct in_addr addr; + int port1; + int port2; + int gameid; + long modtime; + +protected: + GameEntry(const GameEntry& ge); + GameEntry& operator=(const GameEntry& ge); +}; + +#endif // _GAMEENTRY_H_ diff --git a/modhelper.cpp b/modhelper.cpp new file mode 100644 index 0000000..81b27ff --- /dev/null +++ b/modhelper.cpp @@ -0,0 +1,36 @@ +#include "modhelper.h" + +void ModHelper::send(MultiSock* msock, struct game_ports* arr, const char* data, int size) +{ + struct sockaddr_in addr; + addr.sin_family = AF_INET; + addr.sin_addr.s_addr = 0xFFFFFFFF; + + NetPkt* pkt = new NetPkt(data, size); + + while (arr && arr->portlo && arr->porthi) { + int port; + for (port = arr->portlo; port <= arr->porthi; port++) { + addr.sin_port = htons(port); + pkt->setAddress(&addr); + msock->sendto(pkt); + } + arr++; + } + + delete pkt; +} + +int ModHelper::checkPorts(NetPkt* pkt, struct game_ports* arr) +{ + int myport = ntohs(pkt->getAddress()->sin_port); + while (arr && arr->portlo) { + int port; + for (port = arr->portlo; port <= arr->porthi; port++) + if (port == myport) + return arr->gameid; + + arr++; + } + return 0; +} diff --git a/modhelper.h b/modhelper.h new file mode 100644 index 0000000..e937e2d --- /dev/null +++ b/modhelper.h @@ -0,0 +1,19 @@ +#ifndef _MODHELPER_H_ +#define _MODHELPER_H_ + +#include "multisock.h" +#include "netpkt.h" +#include "module.h" + +class ModHelper { +public: + static void send(MultiSock* msock, struct game_ports* arr, const char* data, int size); + static int checkPorts(NetPkt* pkt, struct game_ports* arr); + +protected: + ModHelper() {}; + ModHelper(const ModHelper& m); + ModHelper& operator=(const ModHelper& m); +}; + +#endif // _MODHELPER_H_ diff --git a/socket.cpp b/socket.cpp new file mode 100644 index 0000000..150cc4b --- /dev/null +++ b/socket.cpp @@ -0,0 +1,175 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "logging.h" +#include "socket.h" + +Socket::Socket() +{ + if ((fd = socket(PF_INET, SOCK_DGRAM, 0)) < 0) + LogSystem::log(LOG_CRIT, "Socket: socket()"); + + strcpy(devname, "any"); + memset(&addr, 0, sizeof(addr)); +} + +Socket::~Socket() +{ + close(fd); +} + +bool Socket::checkDeviceFlags(const char* name) +{ + struct ifreq ifr; + strncpy(ifr.ifr_name, name, sizeof(ifr.ifr_name)); + + if (ioctl(fd, SIOCGIFFLAGS, &ifr) != 0) { + LogSystem::log(LOG_WARN, "Socket: ioctl(SIOCGIFFLAGS) %s", name); + return false; + } + + if (!(ifr.ifr_flags & IFF_UP) || (ifr.ifr_flags & (IFF_LOOPBACK | IFF_POINTOPOINT))) + return false; + + return true; +} + +bool Socket::bindToDevice(const char* name) +{ + struct ifreq ifr; + strncpy(devname, name, sizeof(devname)); + strncpy(ifr.ifr_name, name, sizeof(ifr.ifr_name)); + + if (ioctl(fd, SIOCGIFADDR, &ifr) != 0) { + LogSystem::log(LOG_WARN, "Socket: ioctl(SIOCGIFADDR) %s", devname); + return false; + } + + memcpy(&addr, &ifr.ifr_addr, sizeof(addr)); + + if (setsockopt(fd, SOL_SOCKET, SO_BINDTODEVICE, devname, sizeof(devname)) < 0) { + LogSystem::log(LOG_NOTICE, "Socket: setsockopt(SO_BINDTODEVICE) %s", devname); + // no failure! + //return false; + } + + return true; +} + +bool Socket::bindToAddress(struct sockaddr_in* tmp) +{ + int i = 1; + if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &i, sizeof(i)) < 0) { + LogSystem::log(LOG_NOTICE, "Socket: setsockopt(SO_REUSEADDR) %s", devname); + return false; + } + + memcpy(&addr, tmp, sizeof(addr)); + + if (bind(fd, (struct sockaddr*)&addr, sizeof(addr)) < 0) { + LogSystem::log(LOG_WARN, "Socket: bind(%s:%d)", + inet_ntoa(addr.sin_addr), + ntohs(addr.sin_port)); + return false; + } + return true; +} + +bool Socket::setBroadcast(int flag) +{ + if (setsockopt(fd, SOL_SOCKET, SO_BROADCAST, &flag, sizeof(flag))) { + LogSystem::log(LOG_WARN, "Socket: setsockopt(SO_BROADCAST) %s", devname); + return false; + } + return true; +} + +Socket* Socket::createSocket(struct sockaddr_in* addr) +{ + Socket* sock = new Socket(); + + if (!sock->bindToAddress(addr)) { + delete sock; + return NULL; + } + + sock->setBroadcast(1); + return sock; +} + +Socket* Socket::createSocket(const char* name, int port) +{ + Socket* sock = new Socket(); + + if (!sock->checkDeviceFlags(name)) { + delete sock; + return NULL; + } + + if (!sock->bindToDevice(name)) { + delete sock; + return NULL; + } + + sock->addr.sin_port = htons(port); + + if (!sock->bindToAddress(&sock->addr)) { + delete sock; + return NULL; + } + + sock->setBroadcast(1); + return sock; +} + +int Socket::show(char* buf, int size) +{ + return snprintf(buf, size, "%s (%s:%d) ", devname, + inet_ntoa(addr.sin_addr), ntohs(addr.sin_port)); +} + +int Socket::getRecvSize() +{ + int retval; + if (ioctl(fd, FIONREAD, &retval) == -1) { + LogSystem::log(LOG_ERROR, "Socket::getRecvSize()"); + return 0; + } + + return retval; +} + +int Socket::getFD() { + return fd; +} + +int Socket::sendto(NetPkt* pkt, struct sockaddr_in* dst) { + if (!dst) + dst = &pkt->addr; + + if (::sendto(fd, pkt->data, pkt->used, 0, (struct sockaddr *)dst, sizeof(*dst)) < 0) + LogSystem::log(LOG_WARN, "Socket::sendto()"); + return 0; +} + +NetPkt* Socket::recv() { + fd_set fdsel; + + FD_ZERO(&fdsel); + FD_SET(fd, &fdsel); + select(FD_SETSIZE, &fdsel, NULL, NULL, NULL); + + NetPkt* pkt = new NetPkt(this->getRecvSize()); + socklen_t i = sizeof(pkt->addr); + pkt->used = ::recvfrom(fd, (void*)pkt->data, pkt->size, 0, (struct sockaddr *)&pkt->addr, &i); + + return pkt; +} diff --git a/socket.h b/socket.h new file mode 100644 index 0000000..dc5fe33 --- /dev/null +++ b/socket.h @@ -0,0 +1,41 @@ +#ifndef _SOCKET_H_ +#define _SOCKET_H_ + +#include +#include + +#include "netpkt.h" + +class Socket { +public: + Socket(); + ~Socket(); + + static Socket* createSocket(struct sockaddr_in* addr); + static Socket* createSocket(const char* name, int port); + + int show(char* buf, int size); + + int sendto(NetPkt* pkt, struct sockaddr_in* dst = NULL); + NetPkt* recv(); + + int getFD(); + +protected: + Socket(const Socket& s); + Socket& operator=(const Socket& s); + +private: + bool checkDeviceFlags(const char* name); + bool bindToDevice(const char* name); + bool bindToAddress(struct sockaddr_in* addr); + bool setBroadcast(int flag); + + int getRecvSize(); + + int fd; + char devname[IFNAMSIZ]; + struct sockaddr_in addr; +}; + +#endif // _SOCKET_H_