⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 chat.cc

📁 Unix下的MUD客户端程序
💻 CC
📖 第 1 页 / 共 4 页
字号:
#include "mcl.h"#include "cui.h"#include "Chat.h"#include <stdarg.h>#include <sys/socket.h>#include <arpa/inet.h>#include <sys/ioctl.h>#include <unistd.h>#include <net/if.h>#include "Interpreter.h"ChatServerSocket *chatServerSocket;MUD *chatMUD;static int flagLookup(const char *flag);static const char* adjustFlags(const char *flags, int &flag);static const char *flagString(int,bool);#define CDEBUG (config->getOption(opt_chat_debug))#define CHAT_NAME (config->getStringOption(opt_chat_name))static void writeChat(const char *fmt, ...) __attribute__((format(printf,1,2)));static void writeChatCommon(char *s) {    sprintf(s+strlen(s), "%c%c\n", SET_COLOR, fg_white|bg_black);        // Actions should probably be in some "chat" MUD    char out[MAX_MUD_BUF];    if (embed_interp->run_quietly("sys/output", s, out))        output->print(out);    else        output->print(s);}// Write the message with some prefix so we can easier distinguish the chat messages from normal stuffstatic void writeChat(const char *fmt, ...) {    char buf[MAX_MUD_BUF];    char *s = buf+sprintf(buf, "%c%cCHAT:%c%c ", SET_COLOR, bg_black|fg_green|fg_bold, SET_COLOR, config->getOption(opt_chat_syscolor));    va_list va;        va_start(va, fmt);    s += vsnprintf(s, sizeof(buf) - (s-buf) - 3, fmt, va); // -1 for the \n, 2 for the color reset    va_end(va);    writeChatCommon(buf);}// As above, but this is for the actual talking rather than system messagesstatic void writeChatText(const char *fmt, ...) {    char buf[MAX_MUD_BUF];    char *s = buf+sprintf(buf, "%c%cCHAT:%c%c ", SET_COLOR, bg_black|fg_green|fg_bold, SET_COLOR, config->getOption(opt_chat_chatcolor));    va_list va;        va_start(va, fmt);    s += vsnprintf(s, sizeof(buf) - (s-buf) - 3, fmt, va); // -1 for the \n, 2 for the color reset    va_end(va);    writeChatCommon(buf);}// clean up escape chars, return at most new_len bytesstatic const char* sanitize(const char *data, int len, int new_len) {    StaticBuffer buf(new_len+1);    char *out = buf;    char *end = buf+new_len-4;        while (isspace(*data) && len > 0) { // spaces/newlines at the beginning        data++; len--;    }        while (len > 0 && isspace(data[len-1]))        len--;        ColorConverter col;        while (len > 0 && out < end) {        const char *color_start;                if (*data == '\e') {            color_start = data;            while(len > 0 && *data != 'm') {                data++;                len--;            }                        if (*data == 'm') {                int color = col.convert((byte*)color_start, data-color_start);                if (color) {                    *out++ = SET_COLOR;                    *out++ = color;                }                data++;                len--;                continue;            }        }        // ignore 0240 (mudmaster soft newline?) and any other control characters        if ((byte)*data == 0240 || (byte)*data < 32)            ;        else if ((byte)*data > 127)            out += sprintf(out, "\\%03o", (byte)*data);        else            *out++ = *data;        data++;        len--;    }            *out++ = NUL;    return buf;}ChatServerSocket::ChatServerSocket() {    is_afk = false;    generateId();}const char * ChatServerSocket::findIPAddress() {    char intf[INPUT_SIZE];    const char *interfaces = config->getStringOption(opt_chat_interfaces);    struct ifreq interface;        do {        interfaces = one_argument(interfaces, intf, true);        if (intf[0]) {            strcpy(interface.ifr_name, intf);            if (ioctl (getFD(), SIOCGIFADDR, &interface) < 0) // maybe it doesn't exist                continue;            struct sockaddr_in sock= *((struct sockaddr_in*)&interface.ifr_addr);                        if (ioctl(getFD(), SIOCGIFFLAGS, &interface) < 0)                return NULL;                        if (interface.ifr_flags & IFF_UP) {                return inet_ntoa(sock.sin_addr);            }        }    } while (intf[0]);        return NULL;}ChatConnection* ChatServerSocket::findByAddress(const char *ip, int port) {    FOREACH(ChatConnection*,c,connections)        if (!strcmp(c->getRemoteServerIP(),ip) && c->getRemoteServerPort() == port)            return c;    return NULL;}ChatConnection* ChatServerSocket::findConnection(const char *name) {    // Let's try to compare the names first    FOREACH(ChatConnection*,c,connections)        if (c->getName() == name || !strcmp(c->getRemoteServerIP(), name))            return c;    // Number?    int n = atoi(name);    if (n > 0)        return connections[n-1];        return NULL;}void ChatServerSocket::generateId() {    id = random() ^ getpid() ^ current_time;}ChatServerSocket::~ChatServerSocket() {    FOREACH(ChatConnection*,c,connections)        delete c;}void ChatServerSocket::idle() {    FOREACH(ChatConnection*,c,connections)        c->idle();        if (!is_afk && tty->last_activity + 300 < current_time) {        handleUserCommand("afk", "quiet");    } else if (is_afk && tty->last_activity + 5 > current_time) {        handleUserCommand("afk", "quiet");    }}void ChatServerSocket::connectionAccepted(int fd, struct sockaddr_in *remote) {    ChatConnection *c = new ChatConnection(fd,remote);    connections.insert(c);    c->handleIncoming();}void ChatServerSocket::call(const char *name, int port, Protocol protocol) {    ChatConnection *c = new ChatConnection();    connections.insert(c);    c->connect(name, port, protocol);}void ChatServerSocket::handleUserCommand(const char *name, const char *arg) {    if (!strcmp(name, "call")) {        char hostname[MAX_INPUT_BUF];        char port_buf[MAX_INPUT_BUF];        int protocol = -1, port;                arg = one_argument(arg, hostname, true);        if (!strcmp(hostname, "zchat"))            protocol = zchat;        else if (!strcmp(hostname, "chat"))            protocol = mudmaster;                if (protocol != -1)            arg = one_argument(arg, hostname, true);                arg = one_argument(arg, port_buf, true);        if (!hostname[0])            writeChat("You must provide a hostname/nickname to call");        else {            if (!port_buf[0])                port = 4050;            else                port = atoi(port_buf);            if (port < 1 || port > 65535)                writeChat("Invalid port number: %d", port);                        // What protocol do we use?            if (protocol == -1) {                if (config->getOption(opt_chat_protocol) == 0)                    protocol = mudmaster;                else                    protocol = zchat;            }                        // Let's reget our IP address            const char *address = findIPAddress();            if (address && strcmp(address, ~ip)) {                writeChat("Warning: it looks like our IP address is now %s", address);                ip = address;            }                        call(hostname, port, (Protocol)protocol);        }            } else if (!strcmp(name, "ip")) {        computeIPAddress();            } else if (!strcmp(name, "group")) {        char group_name[MAX_INPUT_BUF];        arg = one_argument(arg, group_name, true);        if (!group_name[0])            writeChat("Chat to what group?");        else if (!arg[0])            writeChat("Chat what to the '%s' group?", group_name);        else {            bool emote = false, ok = false;            if (!strncasecmp(arg, "emote ", 6)) {                emote = true;                arg += 6;            }            FOREACH(ChatConnection*,c,connections)                if (c->getGroup() == group_name) {                    ok = true;                    c->sendTextGroup(group_name, arg, emote);                }            const char *colored = sanitize(arg,strlen(arg), 1024);                        if (!ok)                writeChat("No connected members of group '%s'", group_name);            else {                if (emote)                    writeChat("[emote to %s] %s %s%c%c", group_name, ~CHAT_NAME, colored, SET_COLOR, config->getOption(opt_chat_chatcolor));                else                    writeChat("You chat to %s: '%s%c%c'", group_name, colored, SET_COLOR, config->getOption(opt_chat_chatcolor));            }        }    } else if (!strcmp(name, "setgroup")) {        char group_name[MAX_INPUT_BUF];        arg = one_argument(arg, group_name, true);        if (!group_name[0])            writeChat("Add/remove members to what group?");        else if (!arg[0])            writeChat("Add/remove what members to group %s?", group_name);        else {            char name[MAX_INPUT_BUF];            arg = one_argument(arg, name, true);            while(name[0]) {                ChatConnection *c = findConnection(name);                if (!c)                    writeChat("No such connection: %s", name);                else if(c->getGroup() == group_name) {                    c->setGroup("");                    writeChat("%s now in no group", c->shortDescription());                } else {                    c->setGroup(group_name);                    writeChat("%s now in group %s", c->shortDescription(), group_name);                }                arg = one_argument(arg, name, true);            }        }    } else if (!strcmp(name, "request")) {        if (!arg[0])            writeChat("%cchat.request ALL|<connection name>", CMDCHAR);        else if (!strcmp(arg, "all")) {            FOREACH(ChatConnection*,c,connections) {                c->sendCommand(cmdRequestConnections, "");                c->setFlags(c->getFlags() | flagRequestPending);            }        } else {            ChatConnection *c = findConnection(arg);            if (!c)                writeChat("No such connection '%s'", arg);            else {                c->sendCommand(cmdRequestConnections, "");                c->setFlags(c->getFlags() | flagRequestPending);            }        }            } else if (!strcmp(name, "peek")) {        if (!arg[0])            writeChat("%cchat.peek ALL|<connection name>", CMDCHAR);        else if (!strcmp(arg, "all")) {            FOREACH(ChatConnection*,c,connections) {                c->sendCommand(cmdPeekConnections, "");                c->setFlags(c->getFlags() | flagRequestPending);            }                    } else {            ChatConnection *c = findConnection(arg);            if (!c)                writeChat("No such connection '%s'", arg);            else {                c->sendCommand(cmdPeekConnections, "");                c->setFlags(c->getFlags() | flagRequestPending);            }        }            } else if (!strcmp(name, "ping")) {        if (!arg[0])            writeChat("%cchat.ping ALL|<connection name>", CMDCHAR);        else if (!strcasecmp(arg, "all")) {            FOREACH(ChatConnection*, c, connections)                c->sendPing();        } else {            ChatConnection *c =  findConnection(arg);            if (!c)                writeChat("No such connection: %s", arg);            else                c->sendPing();        }            } else if (!strcmp(name, "list")) {        int i = 1;        bool verbose = (output->width > 90);        FOREACH(ChatConnection *, c, connections)            output->printf("%2d %s\n", i++, c->longDescription(verbose));        output->printf("\n%d active connections.\n", i-1);                    } else if (!strcmp(name, "accept")) {        bool ok = false;                FOREACH(ChatConnection *, c, connections)            if (c->acceptConnection()) {                ok = true;                break;            }

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -