/* * OpenClonk, http://www.openclonk.org * * Copyright (c) 2001-2009, RedWolf Design GmbH, http://www.clonk.de/ * Copyright (c) 2010-2016, The OpenClonk Team and contributors * * Distributed under the terms of the ISC license; see accompanying file * "COPYING" for details. * * "Clonk" is a registered trademark of Matthes Bender, used with permission. * See accompanying file "TRADEMARK" for details. * * To redistribute this file separately, substitute the full license texts * for the above references. */ #ifndef C4NETWORK2IRC_H #define C4NETWORK2IRC_H #include "network/C4NetIO.h" enum C4Network2IRCMessageType { MSG_Server, MSG_Status, MSG_Message, MSG_Notice, MSG_Action }; const int C4NetIRCMaxLogLength = 300000; // Maximum total length of log - if log gets longer, it will be cleared even if messages have never been read const int C4NetIRCMaxReadLogLength = 1000; // Maximum log messages kept even after they've been read class C4Network2IRCMessage { friend class C4Network2IRCClient; public: C4Network2IRCMessage(C4Network2IRCMessageType enType, const char *szSource, const char *szTarget, const char *szData) : iTimestamp(time(nullptr)), eType(enType), Source(szSource), Target(szTarget), Data(szData), Next(nullptr) { } private: time_t iTimestamp; C4Network2IRCMessageType eType; StdCopyStrBuf Source, Target, Data; // used by C4Network2IRCClient C4Network2IRCMessage *Next; public: time_t getTimestamp() const { return iTimestamp; } C4Network2IRCMessageType getType() const { return eType; } const char *getSource() const { return Source.getData(); } const char *getTarget() const { return Target.getData(); } const char *getData() const { return Data.getData(); } bool isChannel() const { return Target.getLength() && (*Target.getData() == '#' || *Target.getData() == '+'); } C4Network2IRCMessage *getNext() const { return Next; } }; class C4Network2IRCUser { friend class C4Network2IRCChannel; public: C4Network2IRCUser(const char *szName); private: StdCopyStrBuf Prefix; StdCopyStrBuf Name; // used by C4Network2IRCChannel C4Network2IRCUser *Next; public: const char *getPrefix() const { return Prefix.getData(); } const char *getName() const { return Name.getData(); } C4Network2IRCUser *getNext() const { return Next; } private: // called by C4Network2IRCChannel void SetPrefix(const char *szPrefix) { Prefix = szPrefix; } }; class C4Network2IRCChannel { friend class C4Network2IRCClient; public: C4Network2IRCChannel(const char *szName); ~C4Network2IRCChannel(); private: StdCopyStrBuf Name; StdCopyStrBuf Topic; C4Network2IRCUser *pUsers; bool fReceivingUsers; // used by C4Network2IRCClient C4Network2IRCChannel *Next; public: const char *getName() const { return Name.getData(); } const char *getTopic() const { return Topic.getData(); } C4Network2IRCUser *getUsers() const { return pUsers; } C4Network2IRCUser *getUser(const char *szName) const; bool isUsersLocked() const { return fReceivingUsers; } private: // called by C4Network2IRCClient void OnUsers(const char *szUsers, const char *szPrefixes); void OnUsersEnd(); void OnJoin(const char *szUser); void OnPart(const char *szUser, const char *szComment); void OnKick(const char *szUser, const char *szComment); void OnTopic(const char *szTopic); C4Network2IRCUser *AddUser(const char *szName); void DeleteUser(C4Network2IRCUser *pUser); void ClearUsers(); }; class C4Network2IRCClient : public C4NetIOTCP, private C4NetIO::CBClass { public: C4Network2IRCClient(); ~C4Network2IRCClient() override; private: // Connection information C4NetIO::addr_t ServerAddr, PeerAddr; bool fConnecting{false}, fConnected{false}; // Status information StdCopyStrBuf Nick, RealName, Password; StdCopyStrBuf AutoJoin; C4Network2IRCChannel *pChannels{nullptr}; // User mode/prefix map StdCopyStrBuf Prefixes; // Message log C4Network2IRCMessage *pLog{nullptr}, *pLogLastRead, *pLogEnd{nullptr}; int32_t iLogLength{0}, iUnreadLogLength{0}; // Event queue for notify class C4InteractiveThread *pNotify{nullptr}; // Critical section for data CStdCSec CSec; private: // Overridden void PackPacket(const C4NetIOPacket &rPacket, StdBuf &rOutBuf) override; size_t UnpackPacket(const StdBuf &rInBuf, const C4NetIO::addr_t &addr) override; // Callbacks bool OnConn(const C4NetIO::addr_t &AddrPeer, const C4NetIO::addr_t &AddrConnect, const addr_t *pOwnAddr, C4NetIO *pNetIO) override; void OnDisconn(const C4NetIO::addr_t &AddrPeer, C4NetIO *pNetIO, const char *szReason) override; void OnPacket(const class C4NetIOPacket &rPacket, C4NetIO *pNetIO) override; public: CStdCSec *getCSec() { return &CSec; } // only call these while holding a lock on the above critical section! C4Network2IRCChannel *getFirstChannel() const; C4Network2IRCChannel *getNextChannel(C4Network2IRCChannel *pPrevChan) const; C4Network2IRCChannel *getChannel(const char *szName) const; C4Network2IRCMessage *getMessageLog() const { return pLog; } C4Network2IRCMessage *getUnreadMessageLog() const { return pLogLastRead ? pLogLastRead->getNext() : pLog; } void ClearMessageLog(); void MarkMessageLogRead(); const char *getUserName() const { return Nick.getData(); } using C4NetIOTCP::Connect; // Simple network communication bool Connect(const char *szServer, const char *szNick, const char *szRealName, const char *szPassword = nullptr, const char *szChannel = nullptr); using C4NetIOTCP::Close; bool Close() override; using C4NetIOTCP::Send; bool Send(const char *szCommand, const char *szParameters = nullptr); // Notfiy interface void SetNotify(class C4InteractiveThread *pnNotify) { pNotify = pnNotify; } // Special IRC commands bool Quit(const char *szReason); bool Join(const char *szChannel); bool Part(const char *szChannel); bool Message(const char *szTarget, const char *szText); bool Notice(const char *szTarget, const char *szText); bool Action(const char *szTarget, const char *szText); bool ChangeNick(const char *szNewNick); bool RegisterNick(const char *szPassword, const char *szMail); // Status bool IsActive() const { return fConnecting || fConnected; } bool IsConnected() const { return fConnected; } private: void OnCommand(const char *szSender, const char *szCommand, const char *szParameters); void OnNumericCommand(const char *szSender, int iCommand, const char *szParameters); void OnConnected(); void OnMessage(bool fNotice, const char *szSource, const char *szTarget, const char *szText); void PopMessage(); void PushMessage(C4Network2IRCMessageType eType, const char *szSource, const char *szTarget, const char *szText); C4Network2IRCChannel *AddChannel(const char *szName); void DeleteChannel(C4Network2IRCChannel *pChannel); }; #endif // C4NETWORK2IRC_H