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

📄 chat.cc

📁 Unix下的MUD客户端程序
💻 CC
📖 第 1 页 / 共 4 页
字号:
                                if (remote_port  < 1 || remote_port > 65535) {                    close(Sprintf("Impossible port number %d", remote_port));                    return;                }                                if (inet_addr(ip_address) == (unsigned long)-1) {                    close (Sprintf("Impossible IP address: %s", ip_address));                    return;                }                ip = ip_address;                                // Problem: the current version of the zChat specification leaves no delimiter at the end of the                // security info section. Zugg suggests just to read whatever has arrived so far and hope for the best                // a separrator will appear in the next version of zChat...                if (protocol == zchat) {                    char security_buf[MAX_MUD_BUF];                    /* int n =*/ read(security_buf, sizeof(security_buf));                    // Check passphrase                }                                state = awaiting_confirmation;                                if (config->getOption(opt_chat_nodisturb))                    rejectConnection();                // Accept all connections?                else if (config->getOption(opt_chat_autoaccept))                    acceptConnection();                // Accept connection based on security phrase/name                else {                    writeChat("%s has requested a connection. Use %cchat.accept to allow it or %cchat.reject to drop it", shortDescription(), CMDCHAR, CMDCHAR);                }            }        }    } else if (state == connecting) {        close("Received data while still connecting?!");    } else if (state == connected) {        // A command!        if (protocol == zchat) {            state = waiting_command_header;            command_header_received = 0;            goto try_again;        } else {            // One byte-command            char cmd;            int count = read(&cmd, 1);            assert (count == 1);            pending_command = cmd;            // Now get the data, look out for the 255 character.            state = waiting_data;            goto try_again;        }    } else if (state == waiting_data) {        char *buf = command_data.get(4096);        int n = read(buf, 4096);        char *eoc = (char*)memchr(buf, 255, n);        if (eoc) {            int count = eoc-buf;            if (count < n)                unread(eoc+1, n - count - 1); // return that many bytes back to the socket buffers            command_data.use(eoc-buf); // skip the terminator            dispatchCommand(pending_command, ~command_data, command_data.count());            command_data.clear();            state = connected;        }        else {            // otherwise, continue wating for the character            command_data.use(n);        }            } else if (state == waiting_command_header) {        int n = read(command_header+command_header_received, 4-command_header_received);        assert (n > 0);        command_header_received += n;        assert (command_header_received <= 4);        if (command_header_received == 4) {            pending_command = command_header[0] + 256 * command_header[1];            data_length = command_header[2] + 256 * command_header[3];            state = waiting_command_data;            if (data_length == 0) { // no data, dispatch right away                state = connected;                dispatchCommand(pending_command, ~command_data, command_data.count());                command_data.clear();            } else {                goto try_again;            }        }    } else if (state == waiting_command_data) {        if (data_length > 0) {            char *s = command_data.get(data_length);            int n = read(s, data_length);            data_length -= n;            command_data.use(n);        }        if (data_length == 0) {            // Got all the data now            state = connected;            dispatchCommand(pending_command, ~command_data, command_data.count());            command_data.clear();            goto try_again;        }            } else if (state == requesting) { // waiting for YES/NO response        const char *line = readLine();        if (line) {            if (!strncasecmp(line, "NO", 2))                close("Remote reject connection attempt");            else if (!strncasecmp(line, "YES:", 4)) {                state = connected;                char username[128];                if (1 != sscanf(line, "YES:%s\n", username))                    close ("No name specified in initial connection");                else {                    name = username;                    writeChat("%s accepted our chat connection", shortDescription());                    sendAll();                    goto try_again;                }            } else {                close(Sprintf("Strange response: %.64s not YES/NO", line));            }        }    }}void ChatConnection::sendCommand(int command, const char *data, int len) {    if (len == -1)        len = strlen(data);    if (CDEBUG) writeChat("Sending command %d: %d bytes of data", command, len);    if (CDEBUG) writeChat("Data: '%s'", sanitize(data, len, 256));        if (protocol == zchat) {        char buf[4];        buf[0] = command % 256;        buf[1] = command / 256;        buf[2] = len % 256;        buf[3] = len / 256;        write(buf, sizeof(buf));        if (len  > 0)            write(data,len);    } else { // 255 terminated MudMaster command        assert(memchr(data, 255, len) == NULL); // Hmm, how IS it done        write(Sprintf("%c", command), 1);        write(data, len);        write("\377", 1);    }}// Return some timestamp in miliseconds. This wraps at 1 millionstatic int getMiliseconds() {    struct timeval tv;    if (gettimeofday(&tv, NULL) < 0)        return 0;    else        return tv.tv_sec % 1000 + (tv.tv_usec / 1000);}void ChatConnection::dispatchCommand (int command, const char *data, int len) {    int stamp_id = -1;    // Extract 4-byte stamp ID from zChat    if (protocol == zchat && (command == cmdTextPersonal || command == cmdTextGroup || command == cmdTextEverybody)) {        if (len < 5) {            writeChat("Command %d less than 5 bytes long; cannot have stampID and sufficient text", command);            return;        }        // Byte order ?! Assume raw        stamp_id = *(int*)data;        data += 4;        len -= 4;                if (stamp_id == chatServerSocket->getId()) {            if (CDEBUG) writeChat("Ignoring duped message: %s", sanitize(data,len,1024));            return;        }    }        const char *sane = sanitize(data, len, 1024); // how much is too much?    if (CDEBUG) writeChat("[%s] %d = %s", shortDescription(), command, sane);                switch(command) {            case cmdTextPersonal:        if (!(flags & flagIgnored)) {            if (config->getOption(opt_chat_paranoia) || !strstr(sane, ~name))                writeChatText("[%s] %s%c%c", shortDescription(), sane);            else                writeChatText("%s", sane);        }        break;            case cmdMessage:        writeChat("[%s] %s", shortDescription(), sane);        break;            case cmdPingRequest:        sendCommand(cmdPingResponse, data, len);        break;            case cmdPingResponse:        if (len == 4) {            int time = *(int*) data;            int now = getMiliseconds();            int diff = (now-time + 1000000) % 1000000;                        writeChat("Ping response from %s: %d.%03ds roundtrip time", shortDescription(), diff/1000, diff%1000);            break;        } else {            writeChat("Invalid ping response from %s: not 4 bytes", shortDescription());        }        break;            case cmdTextGroup: {        char group_name[16];        if (len < (int)sizeof(group_name))            writeChat("Invalid group message, shorter than %d characters", sizeof(group_name));        else {            memcpy(group_name, data, sizeof(group_name)-1);            group_name[sizeof(group_name)-1] = NUL;            data += sizeof(group_name)-1;            len -= sizeof(group_name)-1;            sane = sanitize(data, len, 1024);                        for (int i = sizeof(group_name)-1; i >0; i--)                if (isspace(group_name[i]))                    group_name[i] = NUL;                        if (config->getOption(opt_chat_paranoia) || !strstr(sane, ~name))                writeChatText("[%s] %s", shortDescription(), sane);            else                writeChatText("%s", sane);                        // Now propagate this message            FOREACH(ChatConnection *, c, chatServerSocket->connections)                if (c != this && (c->flags & flagServing) && c->group == group_name) {                    c->sendText(cmdTextGroup, data);                    if (CDEBUG) writeChat("Propagating to %s", c->shortDescription());                }        }    }    break;        case cmdStamp:        if (len < 4)            writeChat("Got cmdStamp from %s, but it was only %d bytes long", shortDescription(), len);        else {            int val = *(int*) data;            if (val == chatServerSocket->getId()) { // oh my god, we wore the same thing!                writeChat("I have the same StampID as %s -- regenerating mine", shortDescription());                chatServerSocket->generateId();                FOREACH(ChatConnection*,c,chatServerSocket->connections)                    c->sendStamp();            }        }                break;            case cmdRequestConnections:    case cmdPeekConnections: {        writeChat("%s asked for a list of our connections", shortDescription());        Buffer b;        FOREACH(ChatConnection*,c,chatServerSocket->connections)            if (!(c->getFlags() & flagPrivate))                b.printf(",%s,%d", c->getRemoteServerIP(), c->getRemoteServerPort());                if (b.count())            b.shift(1);                sendCommand(command == cmdRequestConnections ? cmdConnectionList : cmdPeekList, ~b, b.count());            }    break;        case cmdConnectionList:    case cmdPeekList: {        const char *s = sane;        char *out, *end;        char ip[64], port_s[64];        int port;        unsigned int addr;        Buffer b;        int count = 0, new_connections = 0;        if (CDEBUG) writeChat ("con/peek: %s", sane);                for (;*s;) {            out = ip; end = ip+sizeof(ip)-1;            while(*s && *s != ',' && out < end)                *out++ = *s++;            if (!*s)                break;            *out = NUL; s++;            out = port_s; end = port_s+sizeof(port_s)-1;            while(*s && *s != ',' && out < end)                *out++ = *s++;            *out = NUL;            if (*s == ',')                s++;            port = atoi(port_s);            count++;                        if (port < 1024 || port > 65000)                writeChat("%s: discarding %s %d (too high port)", shortDescription(), ip, port);            else if (( addr = inet_addr(ip)) == (unsigned int) -1)                writeChat("%s: discarding %s %d (invalid IP address)", shortDescription(), ip, port);            else {                if (command == cmdConnectionList) {                    if (chatServerSocket->findByAddress(ip, port))                        writeChat("%s:%d already exists, not connecting", ip, port);                    else {                        // Don't connect to self :)                        if (strcmp(chatServerSocket->getIPAddress(), ip)                            || port != chatServerSocket->getLocalPort()) {                            chatServerSocket->call(ip,port,zchat);                            new_connections++;                        }                    }                } else                    b.printf("%-25s %d\n", ip, port);            }        }        if (command == cmdPeekList)            writeChat("%s has %d active connections:\n%s", shortDescription(), count, ~b);        else            writeChat("%s gave us %d new (total %d) connections", shortDescription(), new_connections, count);    }    break;                case cmdSendCommand:        if (flags & flagAllowCommands) {            writeChat("%s executes: %s", shortDescription(), sane);            interpreter.add(sane);        } else {            writeChat("%s tries to execute: %s", shortDescription(), sane);            sendMessage("You are not allowed to execute commands here");        }        break;                    case cmdTextEverybody:        if (!(flags & flagIgnored)) {            if (config->getOption(opt_chat_paranoia) || !strstr(sane, ~name))                writeChatText("[%s] %s", shortDescription(), sane);            else                writeChatText("%s", sane);        }                // Now propagate this message        FOREACH(ChatConnection *, c, chatServerSocket->connections)            if (c != this && (c->flags & flagServing)) {                c->sendText(cmdTextEverybody, data);                if (CDEBUG) writeChat("Propagating to %s", c->shortDescription());            }                break;            case cmdSnoop:        if (flags & flagSnooping) {

⌨️ 快捷键说明

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