📄 chat.cc
字号:
if (!ok) writeChat("No connections are waiting for your accept.\n"); } else if (!strcmp(name, "snoop")) { if (!arg[0]) writeChat("Snoop whom?"); else { ChatConnection *c = findConnection(arg); if (!arg[0]) writeChat("No such connection as '%s'", arg); else { c->sendCommand(cmdSnoop, ""); } } } else if (!strcmp(name, "to")) { char name[MAX_INPUT_BUF]; arg = one_argument(arg,name, false); if (!name[0] || !arg[0]) writeChat("Chat what and to whom?"); else { ChatConnection *c = findConnection(name); if (!c) writeChat("No such connection: %s", name); else { if (!strncasecmp(arg, "emote ", 6)) { arg += 6; c->sendTextPersonal(arg, true); } else c->sendTextPersonal(arg, false); } } } else if (!strcmp(name, "all")) { if (!arg[0]) writeChat ("Chat WHAT to all?"); else { bool emote = false; if (!strncasecmp(arg, "emote ", 6)) { emote = true; arg += 6; } const char *colored = sanitize(arg,strlen(arg), 1024); FOREACH(ChatConnection*,c,connections) c->sendTextEverybody(arg, emote); if (!emote) writeChatText("You chat to all: '%s%c%c'", colored, SET_COLOR, config->getOption(opt_chat_chatcolor)); else writeChatText("[emote to all] %s %s%c%c.", ~CHAT_NAME, colored, SET_COLOR, config->getOption(opt_chat_chatcolor)); } } else if (!strcmp(name, "icon")) { if (access(arg, R_OK) != 0) writeChat("Can't find %s: %m",arg); else { writeChat("chat.icon updated to %s and sent", arg); FOREACH(ChatConnection*,c,connections) c->sendIcon(arg); } } else if (!strcmp(name, "reject")) { bool ok = false; FOREACH(ChatConnection *, c, connections) { const char *desc = c->shortDescription(); if (c->rejectConnection()) { ok = true; writeChat("Connection from %s rejected", desc); break; } } if (!ok) output->printf("No connections are waiting for your accept.\n"); } else if (!strcmp(name, "afk")) { is_afk = !is_afk; if (is_afk) { if (strcmp(arg, "quiet")) writeChat("You are now AFK"); } else { if (strcmp(arg,"quiet")) writeChat("You are no longer AFK"); } FOREACH(ChatConnection*,c,connections) c->sendStatus(); } else if (!strcmp(name, "flags")) { char name[MAX_INPUT_BUF]; arg = one_argument(arg, name, true); if (!arg[0]) writeChat("Set flags to what?"); else { ChatConnection * c = findConnection(name); if (!c) writeChat("No such connection as '%s'", name); else { int flags = c->getFlags(); const char *res = adjustFlags(arg, flags); if (res) writeChat("Error setting flags: %s", res); else { writeChat("Flags for %s set to %s", c->shortDescription(), flagString(flags, false)); c->setFlags(flags); } } } } else status->setf("Unknown chat command: chat.%s", name);}void ChatServerSocket::computeIPAddress() { const char *addr = findIPAddress(); if (!addr) { writeChat("System active, but could not determine IP address. Port %d", getLocalPort()); embed_interp->set("chatIP", ""); } else { writeChat("System active. Listening on %s port %d", addr, getLocalPort()); ip = addr; embed_interp->set("chatIP", addr); }}void ChatServerSocket::handleSnooping(const char *data, int len) { FOREACH(ChatConnection *,c,connections) if (c->getFlags() & flagSnoopedBy) c->sendCommand(cmdSnoopData,data,len);}void ChatServerSocket::create(int base_port) { int port,res=0; ChatServerSocket *s = new ChatServerSocket; for (port = base_port; port < base_port+10; port++) { res = s->bind(port); if (res == EADDRINUSE) continue; else if (res == 0) break; } if (res == EADDRINUSE) writeChat("Cannot bind chat port, all ports %d to %d are in use", base_port, base_port+9); else if (res != 0) writeChat("Error ocurred during chat port bind: %s", strerror(res)); else { // OK s->computeIPAddress(); embed_interp->set("chatPort", s->getLocalPort()); chatServerSocket = s; return; } delete s;}ChatConnection::ChatConnection (int fd, struct sockaddr_in *remote) : Socket(fd,remote) { state = invalid; flags = 0; inactive_since = 0; pgpKey = NULL; person_status = active; if (remote) { accepted = true; connect_time = current_time; } else accepted = false;}ChatConnection::~ChatConnection() { chatServerSocket->connections.remove(this); delete[] pgpKey;}void ChatConnection::idle() { if (state == connecting && current_time >= timeout) close ("connect timeout"); else if (state == requesting && current_time >= timeout) close ("negotation timeout");}const char* ChatConnection::shortDescription() const { return Sprintf("%s@%s", name.len() ? ~name : "?", !strcmp(getRemoteIP(), "0.0.0.0") ? "<none>" : getRemoteIP());}void ChatConnection::close(const char *reason) { writeChat("Closing connection to %s (%s)", shortDescription(), reason); delete this;}void ChatConnection::handleIncoming() { if (CDEBUG) writeChat("Incoming connection from %s", shortDescription()); state = incoming_chatname; // Now wait for the request // @@ Handle connection spamming here}void ChatConnection::connectionEstablished() { state = requesting; timeout = current_time + 60; ip = getRemoteIP(); if (CDEBUG) writeChat("Connected to %s, now negotating", shortDescription()); requestConnection();}void ChatConnection::connect (const char *hostname, int port, int _protocol) { writeChat ("Trying to connect to %s port %d%s", hostname, port, _protocol == mudmaster ? " (mudmaster)" : ""); state = connecting; int res; if ((res = Socket::connect(hostname, port, true)) != 0) { writeChat("Error connecting to %s: %s", hostname, res == ENOENT ? "No such host" : strerror(res)); delete this; } else { timeout = current_time + 60; remote_port = port; } protocol = (Protocol)_protocol;}void ChatConnection::errorEncountered(int) { writeChat("Error ocurred while talking to %s: %s", shortDescription(), getErrorText()); delete this;}const char* ChatConnection::longDescription(bool verbose) { StaticBuffer buf; char *s = buf; s += sprintf(s, "%c%c%-12s ", protocol == zchat ? 'Z' : ' ', accepted ? '<' : '>', name.len() ? ~name : "<unknown>"); if (ip.len()) { s += sprintf(s, " %16s %4d ", ~ip, remote_port); } else { s += sprintf(s, " %16s %4d ", getRemoteServerIP(), getRemoteServerPort()); } if (verbose) s += sprintf(s, "%-14.14s ", ~version); if (verbose) { if (person_status == afk || person_status == inactive) s += sprintf(s, person_status == afk ? "AFK:%-3d" : "Inc:%-3d", (current_time - inactive_since)/60); else s += sprintf(s, person_status == inactive ? "inact" : " "); } else { s += sprintf(s, "%c", person_status == afk ? 'A' : person_status == inactive ? 'I' : ' ' ); } s += sprintf(s, "%s ", flagString(flags, true)); if (group.len()) s += sprintf(s, "[%s]", ~group); if (state == invalid) s += sprintf(s, verbose ? "INVALID STATE" : "????"); else if (state == connecting) s += sprintf(s, verbose ? "Connecting (timeout: %lds)" : "C%.3d", timeout - current_time); else if (state == requesting) s += sprintf(s, verbose ? "Connected, requesting permission (timeout: %lds)" : "P%.3d", timeout-current_time); else if (state == connected) s += sprintf(s, verbose ? "Connected" : " "); else if (state == waiting_command_header) s += sprintf(s, verbose ? "Waiting for %d more command header bytes" : "Cmd%d" , 4-command_header_received); else if (state == waiting_command_data) { if (verbose) s += sprintf(s, "Waiting for %d more bytes of command %d", data_length, pending_command); else s += sprintf(s, "D%.3x", data_length); } else if (state == waiting_data) s += sprintf(s, verbose ? "Waiting for old-style data" : "Data"); else if (state == incoming_chatname) s += sprintf(s, verbose ? "Accepted, awaiting protocol/chatname" : "Acc1"); else if (state == incoming_address) s += sprintf(s, verbose ? "Accepted, awaiting address/port" : "Acc2"); else if (state == awaiting_confirmation) { if (verbose) s += sprintf(s, "Waiting for your accept (%cchat.accept)", CMDCHAR); else s += sprintf(s, "Cnfr"); } else { s += sprintf(s, verbose ? "Unknown state: %d" : "I%d", state); } return buf;}void ChatConnection::inputReady() { assert (state != invalid);try_again: if (pendingInput() <= 0) return; // Two states require us to read some lines if (state == incoming_chatname) { const char *line = readLine(); if (line) { char protocol_name[64], chat_name[64], chat_id[64]; if (!strncmp(line, "CHAT", strlen("CHAT"))) { // MudMaster chat protocol protocol = mudmaster; if (2 != sscanf(line, "%64[^:]:%64[^\n]", protocol_name, chat_name)) { close(Sprintf("Invalid MudMaster protocol line: \"%-.128s\"", line)); return; } chat_id[0] = NUL; } else if (!strncmp(line, "ZCHAT", strlen("ZCHAT"))) { // Zugg's extensions protocol = zchat; if (3 != sscanf(line, "%64[^:]:%64[^\t]\t%64[^\n]", protocol_name, chat_name, chat_id)) { close(Sprintf("Invalid ZCHAT protocol \"line: %-.128s\"", line)); return; } } else { close(Sprintf("Invalid protocol: : %-.128s", line)); return; } name = chat_name; id = chat_id; if (CDEBUG) writeChat("%s: uses protocol %s", shortDescription(), protocol_name); // Wait for hostname/port state = incoming_address; goto try_again; } } else if (state == incoming_address) { const char *line; char linebuf[1024]; // mudmaster doesn't seem to send a newline at the end of the address line. if (protocol == mudmaster) { int count = read(linebuf,sizeof(linebuf)); if (count <= 0) return; linebuf[count] = NUL; line = linebuf; } else { line = readLine(); } if (line) { char ip_address[128], port_number[128]; const char *port_start; if (strlen(line) < 12 || strlen(line) > 63) close(Sprintf("Line with IP address/port impossibly short or long: %-.128s", line)); else { port_start = line+strlen(line) - 5; // grr, why this weirdness strncpy(ip_address, line, port_start-line); ip_address[port_start-line] = NUL; strcpy(port_number, port_start); remote_port = atoi(port_number);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -