// C4800: 'int' : forcing value to bool 'true' or 'false' (performance warning) #pragma warning(disable : 4800) // Win32 templates generate hundreds of "overly-long identifier" warnings #pragma warning(disable : 4786) #pragma warning(disable : 4503) #include "tibrvcpp.h" #include #include #ifdef WIN32 # include # define strcasecmp stricmp # define strncasecmp strnicmp #endif #include #include using namespace std; const char *g_identity; const char *g_helpstr = "commands:\n /join \n /leave\n /quit\n \n"; class Channel { friend class CB; static map __all_channels; string _name; string _fullname; TibrvListener _listener; struct CB : public TibrvMsgCallback { void onMsg(TibrvListener* listener, TibrvMsg& msg) { ((Channel*)listener->getClosure())->gotMsg(msg); } } cb; TibrvTransport *_transport; public: Channel(const char *name, TibrvTransport *transport) { _name = name; _transport = transport; _fullname = "CHATCHANNEL."; _fullname += name; _listener.create(Tibrv::defaultQueue(), &cb, transport, _fullname.c_str(), this); __all_channels[_name] = this; } ~Channel() { __all_channels.erase(_name); } const char *getName() { return _name.c_str(); } void gotMsg(TibrvMsg &msg) { const char *who; const char *data; msg.getString("WHO", who); msg.getString("MSG", data); printf("<%s@%s> %s\n", who, _name.c_str(), data); fflush(stdout); } void send(const char *message) { TibrvMsg msg; if (msg.setSendSubject(_fullname.c_str()) != TIBRV_OK) { printf("!!! could not set send subject\n"); fflush(stdout); return; } msg.addString("MSG", message); msg.addString("WHO", g_identity); if (_transport->send(msg) != TIBRV_OK) { printf("!!! could not send msg\n"); fflush(stdout); return; } } static Channel *GetChannel(const char *name, TibrvTransport *trans) { if (__all_channels.find(name) == __all_channels.end()) return new Channel(name, trans); return __all_channels[name]; } static Channel *GetAnyChannel() { if (__all_channels.empty()) return NULL; return __all_channels.begin()->second; } }; class STDIN_Handler { TibrvTransport *_transport; public: STDIN_Handler(TibrvTransport *transport) { _transport = transport; } void go() { char buf[8192]; Channel *currchan = NULL; while (fgets(buf, sizeof(buf), stdin)) { int i = strlen(buf); while (i > 0) { i--; if (buf[i] == '\r' || buf[i] == '\n') buf[i] = 0; } i = strlen(buf); if (!i) continue; if (strncasecmp(buf, "/join ", 6) == 0) { currchan = Channel::GetChannel(buf+6, _transport); printf("*** joined channel %s\n", buf+6); fflush(stdout); } else if (strncasecmp(buf, "/help", 5) == 0) { printf("%s\n", g_helpstr); fflush(stdout); } else if (strncasecmp(buf, "/quit", 5) == 0) { return; } else if (strncasecmp(buf, "/leave", 6) == 0) { if (currchan) { printf("*** left channel %s\n", currchan->getName()); delete currchan; currchan = Channel::GetAnyChannel(); if (currchan) { printf("*** current channel is %s\n", currchan->getName()); } else { printf("*** not in a channel anymore\n"); } } else { printf("*** not in a channel\n"); } fflush(stdout); } else { if (currchan) { currchan->send(buf); } else { printf("*** not in any channel\n"); fflush(stdout); } } } } }; // // --[ MAIN ]-------------------- // int main(int argc, char *argv[]) { if (argc != 2) { fprintf(stderr, "usage: %s \n", argv[0]); fflush(stderr); return 1; } g_identity = argv[1]; Tibrv::open(); TibrvNetTransport transport; if (transport.create() != TIBRV_OK) { printf("!!! err opening transport\n"); fflush(stdout); exit(1); } transport.setDescription("chatter"); // create dispatcher thread (new TibrvDispatcher())->create(Tibrv::defaultQueue()); // handle cmds from stdin and send appropriatly (new STDIN_Handler(&transport))->go(); Tibrv::close(); return 0; } // static class members map Channel::__all_channels;