#include "copyright.h"
#include "autoconf.h"
#include "config.h"
#include "externs.h"
#include <sys/file.h>
#include <sys/ioctl.h>
#include <sys/stat.h>
#include <sys/wait.h>
#include <signal.h>
#include "attrs.h"
#include "command.h"
#include "file_c.h"
#include "slave.h"
Include dependency graph for bsd.cpp:
Go to the source code of this file.
Data Structures | |
struct | SIGNALTYPE |
struct | MUX_SIGNAMES |
Defines | |
#define | CheckInput(x) FD_ISSET(x, &input_set) |
#define | CheckOutput(x) FD_ISSET(x, &output_set) |
#define | CAST_SIGNAL_FUNC |
Typedefs | |
typedef struct SIGNALTYPE * | PSIGNALTYPE |
Functions | |
static void | TelnetSetup (DESC *d) |
Begin initial telnet negotiations on a socket. | |
static void | SiteMonSend (int, const char *, DESC *, const char *) |
static DESC * | initializesock (SOCKET, struct sockaddr_in *) |
static DESC * | new_connection (PortInfo *Port, int *piError) |
static bool | process_input (DESC *) |
static int | make_nonblocking (SOCKET s) |
void | CleanUpSlaveSocket (void) |
void | CleanUpSlaveProcess (void) |
void | boot_slave (dbref executor, dbref caller, dbref enactor, int) |
Lauch reverse-DNS slave process. | |
static int | get_slave_result (void) |
static void | make_socket (PortInfo *Port) |
void | SetupPorts (int *pnPorts, PortInfo aPorts[], IntArray *pia) |
bool | ValidSocket (SOCKET s) |
void | shovechars (int nPorts, PortInfo aPorts[]) |
void | shutdownsock (DESC *d, int reason) |
static void | make_nolinger (SOCKET s) |
static void | config_socket (SOCKET s) |
void | process_output (void *dvoid, int bHandleShutdown) |
int | HimState (DESC *d, unsigned char chOption) |
Return the other side's negotiation state. | |
int | UsState (DESC *d, unsigned char chOption) |
Return our side's negotiation state. | |
static void | SetHimState (DESC *d, unsigned char chOption, int iHimState) |
Change the other side's negotiation state. | |
static void | SetUsState (DESC *d, unsigned char chOption, int iUsState) |
Change our side's negotiation state. | |
static void | SendWill (DESC *d, unsigned char chOption) |
Transmit a Telnet WILL sequence for the given option. | |
static void | SendDont (DESC *d, unsigned char chOption) |
Transmit a Telnet DONT sequence for the given option. | |
static void | SendDo (DESC *d, unsigned char chOption) |
Transmit a Telnet DO sequence for the given option. | |
static void | SendWont (DESC *d, unsigned char chOption) |
Transmit a Telnet WONT sequence for the given option. | |
static bool | DesiredHimOption (DESC *d, unsigned char chOption) |
Determine whether we want a particular option on his side of the link to be enabled. | |
static bool | DesiredUsOption (DESC *d, unsigned char chOption) |
Determine whether we want a particular option on our side of the link to be enabled. | |
void | EnableHim (DESC *d, unsigned char chOption) |
Start the process of negotiating the enablement of an option on his side. | |
void | DisableHim (DESC *d, unsigned char chOption) |
Start the process of negotiating the disablement of an option on his side. | |
void | EnableUs (DESC *d, unsigned char chOption) |
Start the process of negotiating the enablement of an option on our side. | |
void | DisableUs (DESC *d, unsigned char chOption) |
Start the process of negotiating the disablement of an option on our side. | |
static void | process_input_helper (DESC *d, char *pBytes, int nBytes) |
Parse raw data from network connection into command lines and Telnet indications. | |
void | close_sockets (bool emergency, char *message) |
void | emergency_shutdown (void) |
static void | check_panicking (int sig) |
static void | unset_signals (void) |
void | BuildSignalNamesTable (void) |
static char * | SignalDesc (int iSignal) |
static void | log_signal (int iSignal) |
static void | log_signal_ignore (int iSignal) |
void | LogStatBuf (int stat_buf, const char *Name) |
static RETSIGTYPE DCL_CDECL | sighandler (int sig) |
void | set_signals (void) |
void | list_system_resources (dbref player) |
Variables | |
PortInfo | aMainGamePorts [MAX_LISTEN_PORTS] |
int | nMainGamePorts = 0 |
unsigned int | ndescriptors = 0 |
DESC * | descriptor_list = NULL |
int | maxd = 0 |
pid_t | slave_pid = 0 |
int | slave_socket = INVALID_SOCKET |
pid_t | game_pid |
static const char * | disc_reasons [] |
static const char * | disc_messages [] |
static const unsigned char | nvt_input_xlat_table [256] |
Table to quickly classify characters recieved from the wire with their Telnet meaning. | |
static const int | nvt_input_action_table [8][14] |
Table to map current telnet parsing state state and input to specific actions and state changes. | |
const SIGNALTYPE | aSigTypes [] |
static MUX_SIGNAMES | signames [NSIG] |
NAMETAB | sigactions_nametab [] |
Definition in file bsd.cpp.
#define CAST_SIGNAL_FUNC |
Definition at line 3413 of file bsd.cpp.
Referenced by alarm_signal(), child_signal(), main(), set_signals(), and sighandler().
#define CheckInput | ( | x | ) | FD_ISSET(x, &input_set) |
Referenced by shovechars().
#define CheckOutput | ( | x | ) | FD_ISSET(x, &output_set) |
Referenced by shovechars().
typedef struct SIGNALTYPE * PSIGNALTYPE |
Lauch reverse-DNS slave process.
This spawns the reverse-DNS slave process and creates a socket-oriented, bi-directional communiocation path between that process and this process. Any existing slave process is killed.
executor | dbref of Executor. | |
caller | dbref of Caller. | |
enactor | dbref of Enactor. |
Definition at line 649 of file bsd.cpp.
References CleanUpSlaveProcess(), CleanUpSlaveSocket(), CMuxAlarm::Clear(), DebugTotalSockets, ENDLOG, LOG_ALWAYS, log_number(), log_text(), make_nonblocking(), maxd, MuxAlarm, slave_pid, slave_socket, and STARTLOG.
Referenced by main(), and shovechars().
00650 { 00651 char *pFailedFunc = 0; 00652 int sv[2]; 00653 int i; 00654 int maxfds; 00655 00656 #ifdef HAVE_GETDTABLESIZE 00657 maxfds = getdtablesize(); 00658 #else // HAVE_GETDTABLESIZE 00659 maxfds = sysconf(_SC_OPEN_MAX); 00660 #endif // HAVE_GETDTABLESIZE 00661 00662 CleanUpSlaveSocket(); 00663 CleanUpSlaveProcess(); 00664 00665 if (socketpair(AF_UNIX, SOCK_DGRAM, 0, sv) < 0) 00666 { 00667 pFailedFunc = "socketpair() error: "; 00668 goto failure; 00669 } 00670 00671 // Set to nonblocking. 00672 // 00673 if (make_nonblocking(sv[0]) < 0) 00674 { 00675 pFailedFunc = "make_nonblocking() error: "; 00676 close(sv[0]); 00677 close(sv[1]); 00678 goto failure; 00679 } 00680 slave_pid = fork(); 00681 switch (slave_pid) 00682 { 00683 case -1: 00684 00685 pFailedFunc = "fork() error: "; 00686 close(sv[0]); 00687 close(sv[1]); 00688 goto failure; 00689 00690 case 0: 00691 00692 // If we don't clear this alarm, the child will eventually receive a 00693 // SIG_PROF. 00694 // 00695 MuxAlarm.Clear(); 00696 00697 // Child. The following calls to dup2() assume only the minimal 00698 // dup2() functionality. That is, the destination descriptor is 00699 // always available for it, and sv[1] is never that descriptor. 00700 // It is likely that the standard defined behavior of dup2() 00701 // would handle the job by itself more directly, but a little 00702 // extra code is low-cost insurance. 00703 // 00704 close(sv[0]); 00705 if (sv[1] != 0) 00706 { 00707 close(0); 00708 if (dup2(sv[1], 0) == -1) 00709 { 00710 _exit(1); 00711 } 00712 } 00713 if (sv[1] != 1) 00714 { 00715 close(1); 00716 if (dup2(sv[1], 1) == -1) 00717 { 00718 _exit(1); 00719 } 00720 } 00721 for (i = 3; i < maxfds; i++) 00722 { 00723 close(i); 00724 } 00725 execlp("bin/slave", "slave", NULL); 00726 _exit(1); 00727 } 00728 close(sv[1]); 00729 00730 slave_socket = sv[0]; 00731 DebugTotalSockets++; 00732 if (make_nonblocking(slave_socket) < 0) 00733 { 00734 pFailedFunc = "make_nonblocking() error: "; 00735 CleanUpSlaveSocket(); 00736 goto failure; 00737 } 00738 if (maxd <= slave_socket) 00739 { 00740 maxd = slave_socket + 1; 00741 } 00742 00743 STARTLOG(LOG_ALWAYS, "NET", "SLAVE"); 00744 log_text("DNS lookup slave started on fd "); 00745 log_number(slave_socket); 00746 ENDLOG; 00747 return; 00748 00749 failure: 00750 00751 CleanUpSlaveProcess(); 00752 STARTLOG(LOG_ALWAYS, "NET", "SLAVE"); 00753 log_text(pFailedFunc); 00754 log_number(errno); 00755 ENDLOG; 00756 }
void BuildSignalNamesTable | ( | void | ) |
Definition at line 3632 of file bsd.cpp.
References aSigTypes, SIGNALTYPE::iSignal, MUX_SIGNAMES::pLongName, MUX_SIGNAMES::pShortName, signames, and SIGNALTYPE::szSignal.
Referenced by main().
03633 { 03634 int i; 03635 for (i = 0; i < NSIG; i++) 03636 { 03637 signames[i].pShortName = NULL; 03638 signames[i].pLongName = NULL; 03639 } 03640 03641 const SIGNALTYPE *pst = aSigTypes; 03642 while (pst->szSignal) 03643 { 03644 int sig = pst->iSignal; 03645 if ( 0 <= sig 03646 && sig < NSIG) 03647 { 03648 MUX_SIGNAMES *tsn = &signames[sig]; 03649 if (tsn->pShortName == NULL) 03650 { 03651 tsn->pShortName = pst->szSignal; 03652 #ifndef WIN32 03653 if (sig == SIGUSR1) 03654 { 03655 tsn->pLongName = "Restart server"; 03656 } 03657 else if (sig == SIGUSR2) 03658 { 03659 tsn->pLongName = "Drop flatfile"; 03660 } 03661 #endif // WIN32 03662 #ifdef SysSigNames 03663 if ( tsn->pLongName == NULL 03664 && SysSigNames[sig] 03665 && strcmp(tsn->pShortName, SysSigNames[sig]) != 0) 03666 { 03667 tsn->pLongName = SysSigNames[sig]; 03668 } 03669 #endif // SysSigNames 03670 } 03671 } 03672 pst++; 03673 } 03674 for (i = 0; i < NSIG; i++) 03675 { 03676 MUX_SIGNAMES *tsn = &signames[i]; 03677 if (tsn->pShortName == NULL) 03678 { 03679 #ifdef SysSigNames 03680 if (SysSigNames[i]) 03681 { 03682 tsn->pLongName = SysSigNames[i]; 03683 } 03684 #endif // SysSigNames 03685 03686 // This is the only non-const memory case. 03687 // 03688 tsn->pShortName = StringClone(tprintf("SIG%03d", i)); 03689 } 03690 } 03691 }
static void check_panicking | ( | int | sig | ) | [static] |
Definition at line 3380 of file bsd.cpp.
References game_pid, mudstate, statedata::panicking, and UNUSED_PARAMETER.
Referenced by sighandler().
03381 { 03382 // If we are panicking, turn off signal catching and resignal. 03383 // 03384 if (mudstate.panicking) 03385 { 03386 for (int i = 0; i < NSIG; i++) 03387 { 03388 signal(i, SIG_DFL); 03389 } 03390 #ifdef WIN32 03391 UNUSED_PARAMETER(sig); 03392 abort(); 03393 #else // WIN32 03394 kill(game_pid, sig); 03395 #endif // WIN32 03396 } 03397 mudstate.panicking = true; 03398 }
void CleanUpSlaveProcess | ( | void | ) |
Definition at line 478 of file bsd.cpp.
References slave_pid.
Referenced by boot_slave(), do_restart(), get_slave_result(), main(), new_connection(), and sighandler().
00479 { 00480 if (slave_pid > 0) 00481 { 00482 kill(slave_pid, SIGKILL); 00483 waitpid(slave_pid, NULL, 0); 00484 } 00485 slave_pid = 0; 00486 }
void CleanUpSlaveSocket | ( | void | ) |
Definition at line 465 of file bsd.cpp.
References DebugTotalSockets, INVALID_SOCKET, IS_INVALID_SOCKET, SD_BOTH, and slave_socket.
Referenced by boot_slave(), do_restart(), get_slave_result(), main(), new_connection(), and sighandler().
00466 { 00467 if (!IS_INVALID_SOCKET(slave_socket)) 00468 { 00469 shutdown(slave_socket, SD_BOTH); 00470 if (close(slave_socket) == 0) 00471 { 00472 DebugTotalSockets--; 00473 } 00474 slave_socket = INVALID_SOCKET; 00475 } 00476 }
void close_sockets | ( | bool | emergency, | |
char * | message | |||
) |
Definition at line 3336 of file bsd.cpp.
References aMainGamePorts, DebugTotalSockets, DESC_SAFEITER_ALL, descriptor_data::descriptor, INVALID_SOCKET, IS_SOCKET_ERROR, log_perror(), nMainGamePorts, queue_string(), queue_write_LEN(), R_GOING_DOWN, SD_BOTH, shutdownsock(), PortInfo::socket, SOCKET_CLOSE, and SOCKET_WRITE.
Referenced by emergency_shutdown(), and main().
03337 { 03338 DESC *d, *dnext; 03339 03340 DESC_SAFEITER_ALL(d, dnext) 03341 { 03342 if (emergency) 03343 { 03344 SOCKET_WRITE(d->descriptor, message, strlen(message), 0); 03345 if (IS_SOCKET_ERROR(shutdown(d->descriptor, SD_BOTH))) 03346 { 03347 log_perror("NET", "FAIL", NULL, "shutdown"); 03348 } 03349 if (SOCKET_CLOSE(d->descriptor) == 0) 03350 { 03351 DebugTotalSockets--; 03352 } 03353 } 03354 else 03355 { 03356 queue_string(d, message); 03357 queue_write_LEN(d, "\r\n", 2); 03358 shutdownsock(d, R_GOING_DOWN); 03359 } 03360 } 03361 for (int i = 0; i < nMainGamePorts; i++) 03362 { 03363 if (SOCKET_CLOSE(aMainGamePorts[i].socket) == 0) 03364 { 03365 DebugTotalSockets--; 03366 } 03367 aMainGamePorts[i].socket = INVALID_SOCKET; 03368 } 03369 }
static void config_socket | ( | SOCKET | s | ) | [static] |
Definition at line 2202 of file bsd.cpp.
References make_nolinger(), and make_nonblocking().
Referenced by initializesock().
02203 { 02204 make_nonblocking(s); 02205 make_nolinger(s); 02206 }
static bool DesiredHimOption | ( | DESC * | d, | |
unsigned char | chOption | |||
) | [static] |
Determine whether we want a particular option on his side of the link to be enabled.
d | Player connection context. | |
chOption | Telnet Option. |
Definition at line 2797 of file bsd.cpp.
References TELNET_EOR, TELNET_NAWS, TELNET_SGA, and UNUSED_PARAMETER.
Referenced by process_input_helper().
02798 { 02799 UNUSED_PARAMETER(d); 02800 02801 if ( TELNET_NAWS == chOption 02802 || TELNET_EOR == chOption 02803 || TELNET_SGA == chOption) 02804 { 02805 return true; 02806 } 02807 return false; 02808 }
static bool DesiredUsOption | ( | DESC * | d, | |
unsigned char | chOption | |||
) | [static] |
Determine whether we want a particular option on our side of the link to be enabled.
It doesn't make sense for NAWS to be enabled on the server side, and we only negotiate SGA on our side if we have already successfully negotiated the EOR option.
d | Player connection context. | |
chOption | Telnet Option. |
Definition at line 2822 of file bsd.cpp.
References OPTION_YES, TELNET_EOR, TELNET_SGA, and UsState().
Referenced by process_input_helper().
02823 { 02824 if ( TELNET_EOR == chOption 02825 || ( TELNET_SGA == chOption 02826 && OPTION_YES == UsState(d, TELNET_EOR))) 02827 { 02828 return true; 02829 } 02830 return false; 02831 }
void DisableHim | ( | DESC * | d, | |
unsigned char | chOption | |||
) |
Start the process of negotiating the disablement of an option on his side.
Whether we actually send anything across the wire to disable this depends on the negotiation state. The option could potentially already be disabled.
d | Player connection context. | |
chOption | Telnet Option. |
Definition at line 2874 of file bsd.cpp.
References HimState(), OPTION_WANTNO_EMPTY, OPTION_WANTNO_OPPOSITE, OPTION_WANTYES_EMPTY, OPTION_WANTYES_OPPOSITE, OPTION_YES, SendDont(), and SetHimState().
02875 { 02876 switch (HimState(d, chOption)) 02877 { 02878 case OPTION_YES: 02879 SetHimState(d, chOption, OPTION_WANTNO_EMPTY); 02880 SendDont(d, chOption); 02881 break; 02882 02883 case OPTION_WANTNO_OPPOSITE: 02884 SetHimState(d, chOption, OPTION_WANTNO_EMPTY); 02885 break; 02886 02887 case OPTION_WANTYES_EMPTY: 02888 SetHimState(d, chOption, OPTION_WANTYES_OPPOSITE); 02889 break; 02890 } 02891 }
void DisableUs | ( | DESC * | d, | |
unsigned char | chOption | |||
) |
Start the process of negotiating the disablement of an option on our side.
Whether we actually send anything across the wire to disable this depends on the negotiation state. The option could potentially already be disabled.
d | Player connection context. | |
chOption | Telnet Option. |
Definition at line 2934 of file bsd.cpp.
References HimState(), OPTION_WANTNO_EMPTY, OPTION_WANTNO_OPPOSITE, OPTION_WANTYES_EMPTY, OPTION_WANTYES_OPPOSITE, OPTION_YES, SendWont(), and SetUsState().
Referenced by SetUsState().
02935 { 02936 switch (HimState(d, chOption)) 02937 { 02938 case OPTION_YES: 02939 SetUsState(d, chOption, OPTION_WANTNO_EMPTY); 02940 SendWont(d, chOption); 02941 break; 02942 02943 case OPTION_WANTNO_OPPOSITE: 02944 SetUsState(d, chOption, OPTION_WANTNO_EMPTY); 02945 break; 02946 02947 case OPTION_WANTYES_EMPTY: 02948 SetUsState(d, chOption, OPTION_WANTYES_OPPOSITE); 02949 break; 02950 } 02951 }
void emergency_shutdown | ( | void | ) |
Definition at line 3371 of file bsd.cpp.
References close_sockets().
Referenced by do_shutdown().
03372 { 03373 close_sockets(true, "Going down - Bye"); 03374 }
void EnableHim | ( | DESC * | d, | |
unsigned char | chOption | |||
) |
Start the process of negotiating the enablement of an option on his side.
Whether we actually send anything across the wire to enable this depends on the negotiation state. The option could potentially already be enabled.
d | Player connection context. | |
chOption | Telnet Option. |
Definition at line 2844 of file bsd.cpp.
References HimState(), OPTION_NO, OPTION_WANTNO_EMPTY, OPTION_WANTNO_OPPOSITE, OPTION_WANTYES_EMPTY, OPTION_WANTYES_OPPOSITE, SendDo(), and SetHimState().
Referenced by TelnetSetup().
02845 { 02846 switch (HimState(d, chOption)) 02847 { 02848 case OPTION_NO: 02849 SetHimState(d, chOption, OPTION_WANTYES_EMPTY); 02850 SendDo(d, chOption); 02851 break; 02852 02853 case OPTION_WANTNO_EMPTY: 02854 SetHimState(d, chOption, OPTION_WANTNO_OPPOSITE); 02855 break; 02856 02857 case OPTION_WANTYES_OPPOSITE: 02858 SetHimState(d, chOption, OPTION_WANTYES_EMPTY); 02859 break; 02860 } 02861 }
void EnableUs | ( | DESC * | d, | |
unsigned char | chOption | |||
) |
Start the process of negotiating the enablement of an option on our side.
Whether we actually send anything across the wire to enable this depends on the negotiation state. The option could potentially already be enabled.
d | Player connection context. | |
chOption | Telnet Option. |
Definition at line 2904 of file bsd.cpp.
References HimState(), OPTION_NO, OPTION_WANTNO_EMPTY, OPTION_WANTNO_OPPOSITE, OPTION_WANTYES_EMPTY, OPTION_WANTYES_OPPOSITE, SendWill(), and SetUsState().
Referenced by SetUsState(), and TelnetSetup().
02905 { 02906 switch (HimState(d, chOption)) 02907 { 02908 case OPTION_NO: 02909 SetUsState(d, chOption, OPTION_WANTYES_EMPTY); 02910 SendWill(d, chOption); 02911 break; 02912 02913 case OPTION_WANTNO_EMPTY: 02914 SetUsState(d, chOption, OPTION_WANTNO_OPPOSITE); 02915 break; 02916 02917 case OPTION_WANTYES_OPPOSITE: 02918 SetUsState(d, chOption, OPTION_WANTYES_EMPTY); 02919 break; 02920 } 02921 }
static int get_slave_result | ( | void | ) | [static] |
Definition at line 806 of file bsd.cpp.
References A_LASTIP, A_LASTSITE, descriptor_data::addr, descriptor_data::address, alloc_lbuf, atr_add_raw(), CleanUpSlaveProcess(), CleanUpSlaveSocket(), descriptor_list, ENDLOG, free_lbuf, LBUF_SIZE, LOG_ALWAYS, log_text(), mudconf, descriptor_data::next, descriptor_data::player, slave_socket, SOCKET_EWOULDBLOCK, SOCKET_LAST_ERROR, STARTLOG, tprintf(), confdata::use_hostname, and descriptor_data::username.
Referenced by shovechars().
00807 { 00808 int local_port, remote_port; 00809 DESC *d; 00810 00811 char *buf = alloc_lbuf("slave_buf"); 00812 00813 int len = read(slave_socket, buf, LBUF_SIZE-1); 00814 if (len < 0) 00815 { 00816 int iSocketError = SOCKET_LAST_ERROR; 00817 if ( iSocketError == SOCKET_EAGAIN 00818 || iSocketError == SOCKET_EWOULDBLOCK) 00819 { 00820 free_lbuf(buf); 00821 return -1; 00822 } 00823 CleanUpSlaveSocket(); 00824 CleanUpSlaveProcess(); 00825 free_lbuf(buf); 00826 00827 STARTLOG(LOG_ALWAYS, "NET", "SLAVE"); 00828 log_text("read() of slave result failed. Slave stopped."); 00829 ENDLOG; 00830 00831 return -1; 00832 } 00833 else if (len == 0) 00834 { 00835 free_lbuf(buf); 00836 return -1; 00837 } 00838 buf[len] = '\0'; 00839 00840 char *token = alloc_lbuf("slave_token"); 00841 char *os = alloc_lbuf("slave_os"); 00842 char *userid = alloc_lbuf("slave_userid"); 00843 char *host = alloc_lbuf("slave_host"); 00844 char *p; 00845 if (sscanf(buf, "%s %s", host, token) != 2) 00846 { 00847 goto Done; 00848 } 00849 p = strchr(buf, '\n'); 00850 *p = '\0'; 00851 if (mudconf.use_hostname) 00852 { 00853 for (d = descriptor_list; d; d = d->next) 00854 { 00855 if (strcmp(d->addr, host) != 0) 00856 { 00857 continue; 00858 } 00859 00860 strncpy(d->addr, token, 50); 00861 d->addr[50] = '\0'; 00862 if (d->player != 0) 00863 { 00864 if (d->username[0]) 00865 { 00866 atr_add_raw(d->player, A_LASTSITE, tprintf("%s@%s", 00867 d->username, d->addr)); 00868 } 00869 else 00870 { 00871 atr_add_raw(d->player, A_LASTSITE, d->addr); 00872 } 00873 atr_add_raw(d->player, A_LASTIP, inet_ntoa((d->address).sin_addr)); 00874 } 00875 } 00876 } 00877 00878 if (sscanf(p + 1, "%s %d , %d : %s : %s : %s", 00879 host, 00880 &remote_port, &local_port, 00881 token, os, userid) != 6) 00882 { 00883 goto Done; 00884 } 00885 for (d = descriptor_list; d; d = d->next) 00886 { 00887 if (ntohs((d->address).sin_port) != remote_port) 00888 continue; 00889 strncpy(d->username, userid, 10); 00890 d->username[10] = '\0'; 00891 if (d->player != 0) 00892 { 00893 atr_add_raw(d->player, A_LASTSITE, tprintf("%s@%s", 00894 d->username, d->addr)); 00895 } 00896 } 00897 Done: 00898 free_lbuf(buf); 00899 free_lbuf(token); 00900 free_lbuf(os); 00901 free_lbuf(userid); 00902 free_lbuf(host); 00903 return 0; 00904 }
int HimState | ( | DESC * | d, | |
unsigned char | chOption | |||
) |
Return the other side's negotiation state.
The negotiation of each optional feature of telnet can be in one of six states (defined in interface.h): OPTION_NO, OPTION_YES, OPTION_WANTNO_EMPTY, OPTION_WANTNO_OPPOSITE, OPTION_WANTYES_EMPTY, and OPTION_WANTYES_OPPOSITE.
An option is only enabled when it is in the OPTION_YES state.
d | Player connection context. | |
chOption | Telnet Option |
Definition at line 2629 of file bsd.cpp.
References descriptor_data::nvt_eor_him_state, descriptor_data::nvt_naws_him_state, descriptor_data::nvt_sga_him_state, OPTION_NO, TELNET_EOR, TELNET_NAWS, and TELNET_SGA.
Referenced by DisableHim(), DisableUs(), EnableHim(), EnableUs(), and process_input_helper().
02630 { 02631 if (TELNET_NAWS == chOption) 02632 { 02633 return d->nvt_naws_him_state; 02634 } 02635 else if (TELNET_EOR == chOption) 02636 { 02637 return d->nvt_eor_him_state; 02638 } 02639 else if (TELNET_SGA == chOption) 02640 { 02641 return d->nvt_sga_him_state; 02642 } 02643 return OPTION_NO; 02644 }
Definition at line 2210 of file bsd.cpp.
References statedata::access_list, descriptor_data::addr, descriptor_data::address, alloc_desc, confdata::cmd_quota_max, descriptor_data::command_count, config_socket(), descriptor_data::connected_at, descriptor_data::descriptor, descriptor_list, descriptor_data::doing, descriptor_data::flags, CLinearTimeAbsolute::GetUTC(), descriptor_data::hashnext, descriptor_data::height, descriptor_data::host_info, confdata::idle_timeout, descriptor_data::input_head, descriptor_data::input_lost, descriptor_data::input_size, descriptor_data::input_tail, descriptor_data::input_tot, descriptor_data::last_time, mudconf, mudstate, ndescriptors, descriptor_data::next, descriptor_data::nOption, descriptor_data::nvt_eor_him_state, descriptor_data::nvt_eor_us_state, NVT_IS_NORMAL, descriptor_data::nvt_naws_him_state, descriptor_data::nvt_naws_us_state, descriptor_data::nvt_sga_him_state, descriptor_data::nvt_sga_us_state, OPTION_NO, descriptor_data::output_head, descriptor_data::output_lost, descriptor_data::output_prefix, descriptor_data::output_size, descriptor_data::output_suffix, descriptor_data::output_tail, descriptor_data::output_tot, descriptor_data::player, descriptor_data::prev, descriptor_data::program_data, descriptor_data::quota, descriptor_data::raw_input, descriptor_data::raw_input_at, descriptor_data::raw_input_state, descriptor_data::retries_left, confdata::retry_limit, site_check(), statedata::suspect_list, descriptor_data::timeout, descriptor_data::username, and descriptor_data::width.
Referenced by new_connection().
02211 { 02212 DESC *d; 02213 02214 #ifdef WIN32 02215 // protect adding the descriptor from the linked list from 02216 // any interference from socket shutdowns 02217 // 02218 if (platform == VER_PLATFORM_WIN32_NT) 02219 { 02220 EnterCriticalSection(&csDescriptorList); 02221 } 02222 #endif // WIN32 02223 02224 d = alloc_desc("init_sock"); 02225 02226 #ifdef WIN32 02227 if (platform == VER_PLATFORM_WIN32_NT) 02228 { 02229 LeaveCriticalSection(&csDescriptorList); 02230 } 02231 #endif // WIN32 02232 02233 d->descriptor = s; 02234 d->flags = 0; 02235 d->connected_at.GetUTC(); 02236 d->last_time = d->connected_at; 02237 d->retries_left = mudconf.retry_limit; 02238 d->command_count = 0; 02239 d->timeout = mudconf.idle_timeout; 02240 d->host_info = site_check((*a).sin_addr, mudstate.access_list) 02241 | site_check((*a).sin_addr, mudstate.suspect_list); 02242 02243 // Be sure #0 isn't wizard. Shouldn't be. 02244 // 02245 d->player = 0; 02246 02247 d->addr[0] = '\0'; 02248 d->doing[0] = '\0'; 02249 d->username[0] = '\0'; 02250 config_socket(s); 02251 d->output_prefix = NULL; 02252 d->output_suffix = NULL; 02253 d->output_size = 0; 02254 d->output_tot = 0; 02255 d->output_lost = 0; 02256 d->output_head = NULL; 02257 d->output_tail = NULL; 02258 d->input_head = NULL; 02259 d->input_tail = NULL; 02260 d->input_size = 0; 02261 d->input_tot = 0; 02262 d->input_lost = 0; 02263 d->raw_input = NULL; 02264 d->raw_input_at = NULL; 02265 d->nOption = 0; 02266 d->raw_input_state = NVT_IS_NORMAL; 02267 d->nvt_sga_him_state = OPTION_NO; 02268 d->nvt_sga_us_state = OPTION_NO; 02269 d->nvt_eor_him_state = OPTION_NO; 02270 d->nvt_eor_us_state = OPTION_NO; 02271 d->nvt_naws_him_state = OPTION_NO; 02272 d->nvt_naws_us_state = OPTION_NO; 02273 d->height = 24; 02274 d->width = 78; 02275 d->quota = mudconf.cmd_quota_max; 02276 d->program_data = NULL; 02277 d->address = *a; 02278 strncpy(d->addr, inet_ntoa(a->sin_addr), 50); 02279 d->addr[50] = '\0'; 02280 02281 #ifdef WIN32 02282 // protect adding the descriptor from the linked list from 02283 // any interference from socket shutdowns 02284 // 02285 if (platform == VER_PLATFORM_WIN32_NT) 02286 { 02287 EnterCriticalSection (&csDescriptorList); 02288 } 02289 #endif // WIN32 02290 02291 ndescriptors++; 02292 02293 if (descriptor_list) 02294 { 02295 descriptor_list->prev = &d->next; 02296 } 02297 d->hashnext = NULL; 02298 d->next = descriptor_list; 02299 d->prev = &descriptor_list; 02300 descriptor_list = d; 02301 02302 #ifdef WIN32 02303 // ok to continue now 02304 // 02305 if (platform == VER_PLATFORM_WIN32_NT) 02306 { 02307 LeaveCriticalSection (&csDescriptorList); 02308 02309 d->OutboundOverlapped.hEvent = NULL; 02310 d->InboundOverlapped.hEvent = NULL; 02311 d->InboundOverlapped.Offset = 0; 02312 d->InboundOverlapped.OffsetHigh = 0; 02313 d->bWritePending = false; // no write pending yet 02314 d->bConnectionShutdown = false; // not shutdown yet 02315 d->bConnectionDropped = false; // not dropped yet 02316 d->bCallProcessOutputLater = false; 02317 } 02318 #endif // WIN32 02319 return d; 02320 }
void list_system_resources | ( | dbref | player | ) |
Definition at line 4070 of file bsd.cpp.
References DebugTotalFiles, DebugTotalSockets, and notify.
Referenced by do_list().
04071 { 04072 char buffer[80]; 04073 04074 int nTotal = 0; 04075 notify(player, "System Resources"); 04076 04077 sprintf(buffer, "Total Open Files: %ld", DebugTotalFiles); 04078 notify(player, buffer); 04079 nTotal += DebugTotalFiles; 04080 04081 sprintf(buffer, "Total Sockets: %ld", DebugTotalSockets); 04082 notify(player, buffer); 04083 nTotal += DebugTotalSockets; 04084 04085 #ifdef WIN32 04086 sprintf(buffer, "Total Threads: %ld", DebugTotalThreads); 04087 notify(player, buffer); 04088 nTotal += DebugTotalThreads; 04089 04090 sprintf(buffer, "Total Semaphores: %ld", DebugTotalSemaphores); 04091 notify(player, buffer); 04092 nTotal += DebugTotalSemaphores; 04093 #endif // WIN32 04094 04095 sprintf(buffer, "Total Handles (sum of above): %d", nTotal); 04096 notify(player, buffer); 04097 04098 #ifdef WIN32 04099 for (int i = 0; i < NUM_SLAVE_THREADS; i++) 04100 { 04101 sprintf(buffer, "Thread %d at line %u", i+1, SlaveThreadInfo[i].iDoing); 04102 notify(player, buffer); 04103 } 04104 #endif // WIN32 04105 }
static void log_signal | ( | int | iSignal | ) | [static] |
Definition at line 3708 of file bsd.cpp.
References ENDLOG, LOG_PROBLEMS, log_text(), SignalDesc(), and STARTLOG.
Referenced by sighandler().
03709 { 03710 STARTLOG(LOG_PROBLEMS, "SIG", "CATCH"); 03711 log_text("Caught signal "); 03712 log_text(SignalDesc(iSignal)); 03713 ENDLOG; 03714 }
static void log_signal_ignore | ( | int | iSignal | ) | [static] |
Definition at line 3717 of file bsd.cpp.
References ENDLOG, LOG_PROBLEMS, log_text(), SignalDesc(), and STARTLOG.
Referenced by sighandler().
03718 { 03719 STARTLOG(LOG_PROBLEMS, "SIG", "CATCH"); 03720 log_text("Caught signal and ignored signal "); 03721 log_text(SignalDesc(iSignal)); 03722 log_text(" because server just came up."); 03723 ENDLOG; 03724 }
void LogStatBuf | ( | int | stat_buf, | |
const char * | Name | |||
) |
Definition at line 3726 of file bsd.cpp.
References ENDLOG, Log, LOG_ALWAYS, log_text(), SignalDesc(), STARTLOG, and CLogFile::tinyprintf().
Referenced by sighandler().
03727 { 03728 STARTLOG(LOG_ALWAYS, "NET", Name); 03729 if (WIFEXITED(stat_buf)) 03730 { 03731 Log.tinyprintf("process exited unexpectedly with exit status %d.", WEXITSTATUS(stat_buf)); 03732 } 03733 else if (WIFSIGNALED(stat_buf)) 03734 { 03735 Log.tinyprintf("process was terminated with signal %s.", SignalDesc(WTERMSIG(stat_buf))); 03736 } 03737 else 03738 { 03739 log_text("process ended unexpectedly."); 03740 } 03741 ENDLOG; 03742 }
static void make_nolinger | ( | SOCKET | s | ) | [static] |
Definition at line 2189 of file bsd.cpp.
References IS_SOCKET_ERROR, and log_perror().
Referenced by config_socket().
02190 { 02191 #if defined(HAVE_LINGER) 02192 struct linger ling; 02193 ling.l_onoff = 0; 02194 ling.l_linger = 0; 02195 if (IS_SOCKET_ERROR(setsockopt(s, SOL_SOCKET, SO_LINGER, (char *)&ling, sizeof(ling)))) 02196 { 02197 log_perror("NET", "FAIL", "linger", "setsockopt"); 02198 } 02199 #endif // HAVE_LINGER 02200 }
int make_nonblocking | ( | SOCKET | s | ) | [static] |
Definition at line 2149 of file bsd.cpp.
References IS_SOCKET_ERROR, and log_perror().
Referenced by boot_slave(), and config_socket().
02150 { 02151 #ifdef WIN32 02152 unsigned long on = 1; 02153 if (IS_SOCKET_ERROR(ioctlsocket(s, FIONBIO, &on))) 02154 { 02155 log_perror("NET", "FAIL", "make_nonblocking", "ioctlsocket"); 02156 return -1; 02157 } 02158 #else // WIN32 02159 #if defined(O_NONBLOCK) 02160 if (fcntl(s, F_SETFL, O_NONBLOCK) < 0) 02161 { 02162 log_perror("NET", "FAIL", "make_nonblocking", "fcntl"); 02163 return -1; 02164 } 02165 #elif defined(FNDELAY) 02166 if (fcntl(s, F_SETFL, FNDELAY) < 0) 02167 { 02168 log_perror("NET", "FAIL", "make_nonblocking", "fcntl"); 02169 return -1; 02170 } 02171 #elif defined(O_NDELAY) 02172 if (fcntl(s, F_SETFL, O_NDELAY) < 0) 02173 { 02174 log_perror("NET", "FAIL", "make_nonblocking", "fcntl"); 02175 return -1; 02176 } 02177 #elif defined(FIONBIO) 02178 unsigned long on = 1; 02179 if (ioctl(s, FIONBIO, &on) < 0) 02180 { 02181 log_perror("NET", "FAIL", "make_nonblocking", "ioctl"); 02182 return -1; 02183 } 02184 #endif // O_NONBLOCK, FNDELAY, O_NDELAY, FIONBIO 02185 #endif // WIN32 02186 return 0; 02187 }
static void make_socket | ( | PortInfo * | Port | ) | [static] |
Definition at line 907 of file bsd.cpp.
References DebugTotalSockets, ENDLINE, INVALID_HANDLE_VALUE, INVALID_SOCKET, IS_INVALID_SOCKET, IS_SOCKET_ERROR, Log, log_perror(), PortInfo::port, PortInfo::socket, SOCKET_CLOSE, SOCKET_LAST_ERROR, and CLogFile::tinyprintf().
00908 { 00909 SOCKET s; 00910 struct sockaddr_in server; 00911 int opt = 1; 00912 00913 #ifdef WIN32 00914 00915 // If we are running Windows NT we must create a completion port, 00916 // and start up a listening thread for new connections 00917 // 00918 if (platform == VER_PLATFORM_WIN32_NT) 00919 { 00920 int nRet; 00921 00922 // create initial IO completion port, so threads have something to wait on 00923 // 00924 CompletionPort = CreateIoCompletionPort(INVALID_HANDLE_VALUE, NULL, 0, 1); 00925 00926 if (!CompletionPort) 00927 { 00928 Log.tinyprintf("Error %ld on CreateIoCompletionPort" ENDLINE, GetLastError()); 00929 WSACleanup(); // clean up 00930 exit(1); 00931 } 00932 00933 // Initialize the critical section 00934 // 00935 if (!bDescriptorListInit) 00936 { 00937 InitializeCriticalSection(&csDescriptorList); 00938 bDescriptorListInit = true; 00939 } 00940 00941 // Create a TCP/IP stream socket 00942 // 00943 s = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); 00944 if (s == INVALID_SOCKET) 00945 { 00946 log_perror("NET", "FAIL", NULL, "creating master socket"); 00947 exit(3); 00948 } 00949 DebugTotalSockets++; 00950 if (setsockopt(s, SOL_SOCKET, SO_REUSEADDR, (char *)&opt, sizeof(opt)) < 0) 00951 { 00952 log_perror("NET", "FAIL", NULL, "setsockopt"); 00953 } 00954 00955 // Fill in the the address structure 00956 // 00957 server.sin_port = htons((unsigned short)(Port->port)); 00958 server.sin_family = AF_INET; 00959 server.sin_addr.s_addr = INADDR_ANY; 00960 00961 // bind our name to the socket 00962 // 00963 nRet = bind(s, (LPSOCKADDR) &server, sizeof server); 00964 00965 if (nRet == SOCKET_ERROR) 00966 { 00967 Log.tinyprintf("Error %ld on Win32: bind" ENDLINE, SOCKET_LAST_ERROR); 00968 if (closesocket(s) == 0) 00969 { 00970 DebugTotalSockets--; 00971 } 00972 s = INVALID_SOCKET; 00973 WSACleanup(); // clean up 00974 exit(1); 00975 } 00976 00977 // Set the socket to listen 00978 // 00979 nRet = listen(s, SOMAXCONN); 00980 00981 if (nRet) 00982 { 00983 Log.tinyprintf("Error %ld on Win32: listen" ENDLINE, SOCKET_LAST_ERROR); 00984 WSACleanup(); 00985 exit(1); 00986 } 00987 00988 // Create the MUD listening thread 00989 // 00990 if (_beginthread(MUDListenThread, 0, (void *) Port) == (unsigned)(-1)) 00991 { 00992 log_perror("NET", "FAIL", "_beginthread", "setsockopt"); 00993 WSACleanup(); 00994 exit(1); 00995 } 00996 00997 Port->socket = s; 00998 Log.tinyprintf("Listening (NT-style) on port %d" ENDLINE, Port->port); 00999 return; 01000 } 01001 #endif // WIN32 01002 01003 s = socket(AF_INET, SOCK_STREAM, 0); 01004 if (IS_INVALID_SOCKET(s)) 01005 { 01006 log_perror("NET", "FAIL", NULL, "creating master socket"); 01007 #ifdef WIN32 01008 WSACleanup(); 01009 #endif // WIN32 01010 exit(3); 01011 } 01012 DebugTotalSockets++; 01013 if (setsockopt(s, SOL_SOCKET, SO_REUSEADDR, (char *)&opt, sizeof(opt)) < 0) 01014 { 01015 log_perror("NET", "FAIL", NULL, "setsockopt"); 01016 } 01017 server.sin_family = AF_INET; 01018 server.sin_addr.s_addr = INADDR_ANY; 01019 server.sin_port = htons((unsigned short)(Port->port)); 01020 int cc = bind(s, (struct sockaddr *)&server, sizeof(server)); 01021 if (IS_SOCKET_ERROR(cc)) 01022 { 01023 log_perror("NET", "FAIL", NULL, "bind"); 01024 if (SOCKET_CLOSE(s) == 0) 01025 { 01026 DebugTotalSockets--; 01027 } 01028 s = INVALID_SOCKET; 01029 #ifdef WIN32 01030 WSACleanup(); 01031 #endif // WIN32 01032 exit(4); 01033 } 01034 listen(s, SOMAXCONN); 01035 Port->socket = s; 01036 Log.tinyprintf("Listening on port %d" ENDLINE, Port->port); 01037 }
Definition at line 1677 of file bsd.cpp.
References statedata::access_list, alloc_lbuf, alloc_mbuf, CleanUpSlaveProcess(), CleanUpSlaveSocket(), statedata::debug_cmd, DebugTotalSockets, ENDLOG, FC_CONN_SITE, fcache_rawdump(), free_lbuf, free_mbuf, H_FORBIDDEN, initializesock(), INVALID_SOCKET, IS_INVALID_SOCKET, LOG_ALWAYS, LOG_NET, LOG_SECURITY, log_text(), mudconf, mudstate, PortInfo::port, SD_BOTH, site_check(), SiteMonSend(), slave_socket, PortInfo::socket, SOCKET_CLOSE, SOCKET_LAST_ERROR, STARTLOG, TelnetSetup(), confdata::use_hostname, and welcome_user().
Referenced by shovechars().
01678 { 01679 DESC *d; 01680 struct sockaddr_in addr; 01681 #ifdef SOCKLEN_T_DCL 01682 socklen_t addr_len; 01683 #else // SOCKLEN_T_DCL 01684 int addr_len; 01685 #endif // SOCKLEN_T_DCL 01686 #ifndef WIN32 01687 int len; 01688 #endif // !WIN32 01689 01690 char *cmdsave = mudstate.debug_cmd; 01691 mudstate.debug_cmd = "< new_connection >"; 01692 addr_len = sizeof(struct sockaddr); 01693 01694 SOCKET newsock = accept(Port->socket, (struct sockaddr *)&addr, &addr_len); 01695 01696 if (IS_INVALID_SOCKET(newsock)) 01697 { 01698 *piSocketError = SOCKET_LAST_ERROR; 01699 return 0; 01700 } 01701 01702 char *pBuffM2 = alloc_mbuf("new_connection.address"); 01703 strcpy(pBuffM2, inet_ntoa(addr.sin_addr)); 01704 unsigned short usPort = ntohs(addr.sin_port); 01705 01706 DebugTotalSockets++; 01707 if (site_check(addr.sin_addr, mudstate.access_list) == H_FORBIDDEN) 01708 { 01709 STARTLOG(LOG_NET | LOG_SECURITY, "NET", "SITE"); 01710 char *pBuffM1 = alloc_mbuf("new_connection.LOG.badsite"); 01711 sprintf(pBuffM1, "[%u/%s] Connection refused. (Remote port %d)", 01712 newsock, pBuffM2, usPort); 01713 log_text(pBuffM1); 01714 free_mbuf(pBuffM1); 01715 ENDLOG; 01716 01717 // Report site monitor information. 01718 // 01719 SiteMonSend(newsock, pBuffM2, NULL, "Connection refused"); 01720 01721 fcache_rawdump(newsock, FC_CONN_SITE); 01722 shutdown(newsock, SD_BOTH); 01723 if (SOCKET_CLOSE(newsock) == 0) 01724 { 01725 DebugTotalSockets--; 01726 } 01727 newsock = INVALID_SOCKET; 01728 errno = 0; 01729 d = NULL; 01730 } 01731 else 01732 { 01733 #ifdef WIN32 01734 // Make slave request 01735 // 01736 // Go take control of the stack, but don't bother if it takes 01737 // longer than 5 seconds to do it. 01738 // 01739 if ( bSlaveBooted 01740 && WAIT_OBJECT_0 == WaitForSingleObject(hSlaveRequestStackSemaphore, 5000)) 01741 { 01742 // We have control of the stack. Skip the request if the stack is full. 01743 // 01744 if (iSlaveRequest < SLAVE_REQUEST_STACK_SIZE) 01745 { 01746 // There is room on the stack, so make the request. 01747 // 01748 SlaveRequests[iSlaveRequest].sa_in = addr; 01749 SlaveRequests[iSlaveRequest].port_in = Port->port; 01750 iSlaveRequest++; 01751 ReleaseSemaphore(hSlaveRequestStackSemaphore, 1, NULL); 01752 01753 // Wake up a single slave thread. Event automatically resets itself. 01754 // 01755 ReleaseSemaphore(hSlaveThreadsSemaphore, 1, NULL); 01756 } 01757 else 01758 { 01759 // No room on the stack, so skip it. 01760 // 01761 ReleaseSemaphore(hSlaveRequestStackSemaphore, 1, NULL); 01762 } 01763 } 01764 #else // WIN32 01765 // Make slave request 01766 // 01767 if ( !IS_INVALID_SOCKET(slave_socket) 01768 && mudconf.use_hostname) 01769 { 01770 char *pBuffL1 = alloc_lbuf("new_connection.write"); 01771 sprintf(pBuffL1, "%s\n%s,%d,%d\n", pBuffM2, pBuffM2, usPort, 01772 Port->port); 01773 len = strlen(pBuffL1); 01774 if (write(slave_socket, pBuffL1, len) < 0) 01775 { 01776 CleanUpSlaveSocket(); 01777 CleanUpSlaveProcess(); 01778 01779 STARTLOG(LOG_ALWAYS, "NET", "SLAVE"); 01780 log_text("write() of slave request failed. Slave stopped."); 01781 ENDLOG; 01782 } 01783 free_lbuf(pBuffL1); 01784 } 01785 #endif // WIN32 01786 01787 STARTLOG(LOG_NET, "NET", "CONN"); 01788 char *pBuffM3 = alloc_mbuf("new_connection.LOG.open"); 01789 sprintf(pBuffM3, "[%u/%s] Connection opened (remote port %d)", newsock, 01790 pBuffM2, usPort); 01791 log_text(pBuffM3); 01792 free_mbuf(pBuffM3); 01793 ENDLOG; 01794 01795 d = initializesock(newsock, &addr); 01796 TelnetSetup(d); 01797 01798 // Initalize everything before sending the sitemon info, so that we 01799 // can pass the descriptor, d. 01800 // 01801 SiteMonSend(newsock, pBuffM2, d, "Connection"); 01802 01803 welcome_user(d); 01804 mudstate.debug_cmd = cmdsave; 01805 } 01806 free_mbuf(pBuffM2); 01807 mudstate.debug_cmd = cmdsave; 01808 *piSocketError = SOCKET_LAST_ERROR; 01809 return d; 01810 }
bool process_input | ( | DESC * | ) | [static] |
Definition at line 3309 of file bsd.cpp.
References statedata::debug_cmd, descriptor_data::descriptor, IS_SOCKET_ERROR, LBUF_SIZE, mudstate, process_input_helper(), SOCKET_EINTR, SOCKET_EWOULDBLOCK, SOCKET_LAST_ERROR, and SOCKET_READ.
Referenced by shovechars().
03310 { 03311 char *cmdsave = mudstate.debug_cmd; 03312 mudstate.debug_cmd = "< process_input >"; 03313 03314 char buf[LBUF_SIZE]; 03315 int got = SOCKET_READ(d->descriptor, buf, sizeof(buf), 0); 03316 if (IS_SOCKET_ERROR(got) || got == 0) 03317 { 03318 int iSocketError = SOCKET_LAST_ERROR; 03319 mudstate.debug_cmd = cmdsave; 03320 if ( IS_SOCKET_ERROR(got) 03321 && ( iSocketError == SOCKET_EWOULDBLOCK 03322 #ifdef SOCKET_EAGAIN 03323 || iSocketError == SOCKET_EAGAIN 03324 #endif // SOCKET_EAGAIN 03325 || iSocketError == SOCKET_EINTR)) 03326 { 03327 return true; 03328 } 03329 return false; 03330 } 03331 process_input_helper(d, buf, got); 03332 mudstate.debug_cmd = cmdsave; 03333 return true; 03334 }
static void process_input_helper | ( | DESC * | d, | |
char * | pBytes, | |||
int | nBytes | |||
) | [static] |
Parse raw data from network connection into command lines and Telnet indications.
Once input has been received from a particular socket, it is given to this function for initial parsing. While most clients do line editing on their side, a raw telnet client is still capable of sending backspace (BS) and Delete (DEL) to the server, so we perform basic editing on our side.
TinyMUX only allows printable characters through, imposes a maximum line length, and breaks lines at CRLF.
d | Player connection on which the input arrived. | |
pBytes | Point to received bytes. | |
nBytes | Number of received bytes in above buffer. |
Definition at line 2993 of file bsd.cpp.
References alloc_lbuf, descriptor_data::aOption, cmd_block::cmd, DesiredHimOption(), DesiredUsOption(), free_lbuf, descriptor_data::height, HimState(), descriptor_data::input_lost, descriptor_data::input_size, descriptor_data::input_tot, LBUF_SIZE, mux_isprint, descriptor_data::nOption, NVT_DEL, NVT_IS_HAVE_IAC, NVT_IS_HAVE_IAC_DO, NVT_IS_HAVE_IAC_DONT, NVT_IS_HAVE_IAC_SB, NVT_IS_HAVE_IAC_SB_IAC, NVT_IS_HAVE_IAC_WILL, NVT_IS_HAVE_IAC_WONT, NVT_IS_NORMAL, OPTION_NO, OPTION_WANTNO_EMPTY, OPTION_WANTNO_OPPOSITE, OPTION_WANTYES_EMPTY, OPTION_WANTYES_OPPOSITE, OPTION_YES, queue_string(), descriptor_data::raw_input, descriptor_data::raw_input_at, descriptor_data::raw_input_state, save_command(), SBUF_SIZE, SendDo(), SendDont(), SendWill(), SendWont(), SetHimState(), SetUsState(), TELNET_NAWS, UsState(), and descriptor_data::width.
Referenced by process_input().
02994 { 02995 if (!d->raw_input) 02996 { 02997 d->raw_input = (CBLK *) alloc_lbuf("process_input.raw"); 02998 d->raw_input_at = d->raw_input->cmd; 02999 } 03000 03001 int nInputBytes = 0; 03002 int nLostBytes = 0; 03003 03004 char *p = d->raw_input_at; 03005 char *pend = d->raw_input->cmd + (LBUF_SIZE - sizeof(CBLKHDR) - 1); 03006 03007 unsigned char *q = d->aOption + d->nOption; 03008 unsigned char *qend = d->aOption + SBUF_SIZE - 1; 03009 03010 int n = nBytes; 03011 while (n--) 03012 { 03013 unsigned char ch = (unsigned char)*pBytes; 03014 int iAction = nvt_input_action_table[d->raw_input_state][nvt_input_xlat_table[ch]]; 03015 switch (iAction) 03016 { 03017 case 1: 03018 // Action 1 - Accept CHR(X). 03019 // 03020 if (mux_isprint(ch)) 03021 { 03022 if (p < pend) 03023 { 03024 *p++ = ch; 03025 nInputBytes++; 03026 } 03027 else 03028 { 03029 nLostBytes++; 03030 } 03031 } 03032 d->raw_input_state = NVT_IS_NORMAL; 03033 break; 03034 03035 case 0: 03036 // Action 0 - Nothing. 03037 // 03038 break; 03039 03040 case 2: 03041 // Action 2 - Erase Character. 03042 // 03043 if (NVT_DEL == ch) 03044 { 03045 queue_string(d, "\b \b"); 03046 } 03047 else 03048 { 03049 queue_string(d, " \b"); 03050 } 03051 03052 if (p > d->raw_input->cmd) 03053 { 03054 // The character we took back. 03055 // 03056 nInputBytes -= 1; 03057 p--; 03058 } 03059 d->raw_input_state = NVT_IS_NORMAL; 03060 break; 03061 03062 case 3: 03063 // Action 3 - Accept Line. 03064 // 03065 *p = '\0'; 03066 if (d->raw_input->cmd < p) 03067 { 03068 save_command(d, d->raw_input); 03069 d->raw_input = (CBLK *) alloc_lbuf("process_input.raw"); 03070 03071 p = d->raw_input_at = d->raw_input->cmd; 03072 pend = d->raw_input->cmd + (LBUF_SIZE - sizeof(CBLKHDR) - 1); 03073 } 03074 break; 03075 03076 case 4: 03077 // Action 4 - Transition to the Normal state. 03078 // 03079 d->raw_input_state = NVT_IS_NORMAL; 03080 break; 03081 03082 case 5: 03083 // Action 5 - Transition to Have_IAC state. 03084 // 03085 d->raw_input_state = NVT_IS_HAVE_IAC; 03086 break; 03087 03088 case 6: 03089 // Action 6 - Transition to the Have_IAC_WILL state. 03090 // 03091 d->raw_input_state = NVT_IS_HAVE_IAC_WILL; 03092 break; 03093 03094 case 7: 03095 // Action 7 - Transition to the Have_IAC_DONT state. 03096 // 03097 d->raw_input_state = NVT_IS_HAVE_IAC_DONT; 03098 break; 03099 03100 case 8: 03101 // Action 8 - Transition to the Have_IAC_DO state. 03102 // 03103 d->raw_input_state = NVT_IS_HAVE_IAC_DO; 03104 break; 03105 03106 case 9: 03107 // Action 9 - Transition to the Have_IAC_WONT state. 03108 // 03109 d->raw_input_state = NVT_IS_HAVE_IAC_WONT; 03110 break; 03111 03112 case 10: 03113 // Action 10 - Transition to the Have_IAC_SB state. 03114 // 03115 q = d->aOption; 03116 d->raw_input_state = NVT_IS_HAVE_IAC_SB; 03117 break; 03118 03119 case 11: 03120 // Action 11 - Transition to the Have_IAC_SB_IAC state. 03121 // 03122 d->raw_input_state = NVT_IS_HAVE_IAC_SB_IAC; 03123 break; 03124 03125 case 12: 03126 // Action 12 - Respond to IAC AYT and return to the Normal state. 03127 // 03128 queue_string(d, "\r\n[Yes]\r\n"); 03129 d->raw_input_state = NVT_IS_NORMAL; 03130 break; 03131 03132 case 13: 03133 // Action 13 - Respond to IAC WILL X 03134 // 03135 switch (HimState(d, ch)) 03136 { 03137 case OPTION_NO: 03138 if (DesiredHimOption(d, ch)) 03139 { 03140 SetHimState(d, ch, OPTION_YES); 03141 SendDo(d, ch); 03142 } 03143 else 03144 { 03145 SendDont(d, ch); 03146 } 03147 break; 03148 03149 case OPTION_WANTNO_EMPTY: 03150 SetHimState(d, ch, OPTION_NO); 03151 break; 03152 03153 case OPTION_WANTYES_OPPOSITE: 03154 SetHimState(d, ch, OPTION_WANTNO_EMPTY); 03155 SendDont(d, ch); 03156 break; 03157 03158 default: 03159 SetHimState(d, ch, OPTION_YES); 03160 break; 03161 } 03162 d->raw_input_state = NVT_IS_NORMAL; 03163 break; 03164 03165 case 14: 03166 // Action 14 - Respond to IAC DONT X 03167 // 03168 switch (UsState(d, ch)) 03169 { 03170 case OPTION_YES: 03171 SetUsState(d, ch, OPTION_NO); 03172 SendWont(d, ch); 03173 break; 03174 03175 case OPTION_WANTNO_OPPOSITE: 03176 SetUsState(d, ch, OPTION_WANTYES_EMPTY); 03177 SendWill(d, ch); 03178 break; 03179 03180 default: 03181 SetUsState(d, ch, OPTION_NO); 03182 break; 03183 } 03184 d->raw_input_state = NVT_IS_NORMAL; 03185 break; 03186 03187 case 15: 03188 // Action 15 - Respond to IAC DO X 03189 // 03190 switch (UsState(d, ch)) 03191 { 03192 case OPTION_NO: 03193 if (DesiredUsOption(d, ch)) 03194 { 03195 SetUsState(d, ch, OPTION_YES); 03196 SendWill(d, ch); 03197 } 03198 else 03199 { 03200 SendWont(d, ch); 03201 } 03202 break; 03203 03204 case OPTION_WANTNO_EMPTY: 03205 SetUsState(d, ch, OPTION_NO); 03206 break; 03207 03208 case OPTION_WANTYES_OPPOSITE: 03209 SetUsState(d, ch, OPTION_WANTNO_EMPTY); 03210 SendWont(d, ch); 03211 break; 03212 03213 default: 03214 SetUsState(d, ch, OPTION_YES); 03215 break; 03216 } 03217 d->raw_input_state = NVT_IS_NORMAL; 03218 break; 03219 03220 case 16: 03221 // Action 16 - Respond to IAC WONT X 03222 // 03223 // Ignore. 03224 // 03225 switch (HimState(d, ch)) 03226 { 03227 case OPTION_NO: 03228 break; 03229 03230 case OPTION_YES: 03231 SetHimState(d, ch, OPTION_NO); 03232 SendDont(d, ch); 03233 break; 03234 03235 case OPTION_WANTNO_OPPOSITE: 03236 SetHimState(d, ch, OPTION_WANTYES_EMPTY); 03237 SendDo(d, ch); 03238 break; 03239 03240 default: 03241 SetHimState(d, ch, OPTION_NO); 03242 break; 03243 } 03244 d->raw_input_state = NVT_IS_NORMAL; 03245 break; 03246 03247 case 17: 03248 // Action 17 - Accept CHR(X) for Sub-Option (and transition to Have_IAC_SB state). 03249 // 03250 d->raw_input_state = NVT_IS_HAVE_IAC_SB; 03251 if ( d->aOption <= q 03252 && q < qend) 03253 { 03254 *q++ = ch; 03255 } 03256 break; 03257 03258 case 18: 03259 // Action 18 - Accept Completed Sub-option and transition to Normal state. 03260 // 03261 if ( d->aOption < q 03262 && q < qend) 03263 { 03264 size_t m = q - d->aOption; 03265 switch (d->aOption[0]) 03266 { 03267 case TELNET_NAWS: 03268 if (m == 5) 03269 { 03270 d->width = (d->aOption[1] << 8 ) | d->aOption[2]; 03271 d->height = (d->aOption[3] << 8 ) | d->aOption[4]; 03272 } 03273 break; 03274 } 03275 } 03276 q = d->aOption; 03277 d->raw_input_state = NVT_IS_NORMAL; 03278 break; 03279 } 03280 pBytes++; 03281 } 03282 03283 if ( d->raw_input->cmd < p 03284 && p <= pend) 03285 { 03286 d->raw_input_at = p; 03287 } 03288 else 03289 { 03290 free_lbuf(d->raw_input); 03291 d->raw_input = NULL; 03292 d->raw_input_at = NULL; 03293 } 03294 03295 if ( d->aOption <= q 03296 && q < qend) 03297 { 03298 d->nOption = q - d->aOption; 03299 } 03300 else 03301 { 03302 d->nOption = 0; 03303 } 03304 d->input_tot += nBytes; 03305 d->input_size += nInputBytes; 03306 d->input_lost += nLostBytes; 03307 }
void process_output | ( | void * | dvoid, | |
int | bHandleShutdown | |||
) |
Definition at line 2493 of file bsd.cpp.
References statedata::debug_cmd, descriptor_data::descriptor, text_block::hdr, IS_SOCKET_ERROR, MEMFREE, mudstate, text_block_hdr::nchars, text_block_hdr::nxt, descriptor_data::output_head, descriptor_data::output_size, descriptor_data::output_tail, R_SOCKDIED, shutdownsock(), SOCKET_EWOULDBLOCK, SOCKET_LAST_ERROR, SOCKET_WRITE, and text_block_hdr::start.
Referenced by main(), queue_write_LEN(), raw_broadcast(), shovechars(), shutdownsock(), and SiteMonSend().
02494 { 02495 DESC *d = (DESC *)dvoid; 02496 02497 char *cmdsave = mudstate.debug_cmd; 02498 mudstate.debug_cmd = "< process_output >"; 02499 02500 TBLOCK *tb = d->output_head; 02501 while (tb != NULL) 02502 { 02503 while (tb->hdr.nchars > 0) 02504 { 02505 int cnt = SOCKET_WRITE(d->descriptor, tb->hdr.start, tb->hdr.nchars, 0); 02506 if (IS_SOCKET_ERROR(cnt)) 02507 { 02508 int iSocketError = SOCKET_LAST_ERROR; 02509 mudstate.debug_cmd = cmdsave; 02510 if ( iSocketError != SOCKET_EWOULDBLOCK 02511 #ifdef SOCKET_EAGAIN 02512 && iSocketError != SOCKET_EAGAIN 02513 #endif // SOCKET_EAGAIN 02514 && bHandleShutdown) 02515 { 02516 shutdownsock(d, R_SOCKDIED); 02517 } 02518 return; 02519 } 02520 d->output_size -= cnt; 02521 tb->hdr.nchars -= cnt; 02522 tb->hdr.start += cnt; 02523 } 02524 TBLOCK *save = tb; 02525 tb = tb->hdr.nxt; 02526 MEMFREE(save); 02527 save = NULL; 02528 d->output_head = tb; 02529 if (tb == NULL) 02530 { 02531 d->output_tail = NULL; 02532 } 02533 } 02534 02535 mudstate.debug_cmd = cmdsave; 02536 }
static void SendDo | ( | DESC * | d, | |
unsigned char | chOption | |||
) | [static] |
Transmit a Telnet DO sequence for the given option.
d | Player connection context. | |
chOption | Telnet Option. |
Definition at line 2768 of file bsd.cpp.
References NVT_DO, NVT_IAC, and queue_write_LEN().
Referenced by EnableHim(), and process_input_helper().
02769 { 02770 char aDo[3] = { NVT_IAC, NVT_DO, 0 }; 02771 aDo[2] = chOption; 02772 queue_write_LEN(d, aDo, sizeof(aDo)); 02773 }
static void SendDont | ( | DESC * | d, | |
unsigned char | chOption | |||
) | [static] |
Transmit a Telnet DONT sequence for the given option.
d | Player connection context. | |
chOption | Telnet Option. |
Definition at line 2754 of file bsd.cpp.
References NVT_DONT, NVT_IAC, and queue_write_LEN().
Referenced by DisableHim(), and process_input_helper().
02755 { 02756 char aDont[3] = { NVT_IAC, NVT_DONT, 0 }; 02757 aDont[2] = chOption; 02758 queue_write_LEN(d, aDont, sizeof(aDont)); 02759 }
static void SendWill | ( | DESC * | d, | |
unsigned char | chOption | |||
) | [static] |
Transmit a Telnet WILL sequence for the given option.
d | Player connection context. | |
chOption | Telnet Option. |
Definition at line 2740 of file bsd.cpp.
References NVT_IAC, NVT_WILL, and queue_write_LEN().
Referenced by EnableUs(), and process_input_helper().
02741 { 02742 char aWill[3] = { NVT_IAC, NVT_WILL, 0 }; 02743 aWill[2] = chOption; 02744 queue_write_LEN(d, aWill, sizeof(aWill)); 02745 }
static void SendWont | ( | DESC * | d, | |
unsigned char | chOption | |||
) | [static] |
Transmit a Telnet WONT sequence for the given option.
d | Player connection context. | |
chOption | Telnet Option. |
Definition at line 2782 of file bsd.cpp.
References NVT_IAC, NVT_WONT, and queue_write_LEN().
Referenced by DisableUs(), and process_input_helper().
02783 { 02784 char aWont[3] = { NVT_IAC, NVT_WONT, 0 }; 02785 aWont[2] = chOption; 02786 queue_write_LEN(d, aWont, sizeof(aWont)); 02787 }
void set_signals | ( | void | ) |
Definition at line 4015 of file bsd.cpp.
References CAST_SIGNAL_FUNC, and sighandler().
Referenced by main().
04016 { 04017 #ifndef WIN32 04018 sigset_t sigs; 04019 04020 // We have to reset our signal mask, because of the possibility 04021 // that we triggered a restart on a SIGUSR1. If we did so, then 04022 // the signal became blocked, and stays blocked, since control 04023 // never returns to the caller; i.e., further attempts to send 04024 // a SIGUSR1 would fail. 04025 // 04026 #undef sigfillset 04027 #undef sigprocmask 04028 sigfillset(&sigs); 04029 sigprocmask(SIG_UNBLOCK, &sigs, NULL); 04030 #endif // !WIN32 04031 04032 signal(SIGINT, CAST_SIGNAL_FUNC sighandler); 04033 signal(SIGTERM, CAST_SIGNAL_FUNC sighandler); 04034 signal(SIGILL, CAST_SIGNAL_FUNC sighandler); 04035 signal(SIGSEGV, CAST_SIGNAL_FUNC sighandler); 04036 signal(SIGABRT, CAST_SIGNAL_FUNC sighandler); 04037 signal(SIGFPE, SIG_IGN); 04038 04039 #ifndef WIN32 04040 signal(SIGCHLD, CAST_SIGNAL_FUNC sighandler); 04041 signal(SIGHUP, CAST_SIGNAL_FUNC sighandler); 04042 signal(SIGQUIT, CAST_SIGNAL_FUNC sighandler); 04043 signal(SIGPIPE, SIG_IGN); 04044 signal(SIGUSR1, CAST_SIGNAL_FUNC sighandler); 04045 signal(SIGUSR2, CAST_SIGNAL_FUNC sighandler); 04046 signal(SIGTRAP, CAST_SIGNAL_FUNC sighandler); 04047 signal(SIGILL, CAST_SIGNAL_FUNC sighandler); 04048 #ifdef HAVE_SETITIMER 04049 signal(SIGPROF, CAST_SIGNAL_FUNC sighandler); 04050 #endif 04051 04052 #ifdef SIGXCPU 04053 signal(SIGXCPU, CAST_SIGNAL_FUNC sighandler); 04054 #endif // SIGXCPU 04055 #ifdef SIGFSZ 04056 signal(SIGXFSZ, CAST_SIGNAL_FUNC sighandler); 04057 #endif // SIGFSZ 04058 #ifdef SIGEMT 04059 signal(SIGEMT, CAST_SIGNAL_FUNC sighandler); 04060 #endif // SIGEMT 04061 #ifdef SIGBUS 04062 signal(SIGBUS, CAST_SIGNAL_FUNC sighandler); 04063 #endif // SIGBUS 04064 #ifdef SIGSYS 04065 signal(SIGSYS, CAST_SIGNAL_FUNC sighandler); 04066 #endif // SIGSYS 04067 #endif // !WIN32 04068 }
static void SetHimState | ( | DESC * | d, | |
unsigned char | chOption, | |||
int | iHimState | |||
) | [static] |
Change the other side's negotiation state.
d | Player connection context. | |
chOption | Telnet Option | |
iHimState | One of the six option negotiation states. |
Definition at line 2685 of file bsd.cpp.
References descriptor_data::nvt_eor_him_state, descriptor_data::nvt_naws_him_state, descriptor_data::nvt_sga_him_state, TELNET_EOR, TELNET_NAWS, and TELNET_SGA.
Referenced by DisableHim(), EnableHim(), and process_input_helper().
02686 { 02687 if (TELNET_NAWS == chOption) 02688 { 02689 d->nvt_naws_him_state = iHimState; 02690 } 02691 else if (TELNET_EOR == chOption) 02692 { 02693 d->nvt_eor_him_state = iHimState; 02694 } 02695 else if (TELNET_SGA == chOption) 02696 { 02697 d->nvt_sga_him_state = iHimState; 02698 } 02699 }
Definition at line 1039 of file bsd.cpp.
References DebugTotalSockets, INVALID_SOCKET, tag_int_array::n, tag_int_array::pi, PortInfo::port, PortInfo::socket, and SOCKET_CLOSE.
Referenced by main().
01040 { 01041 // Any existing open port which does not appear in the requested set 01042 // should be closed. 01043 // 01044 int i, j, k; 01045 bool bFound; 01046 for (i = 0; i < *pnPorts; i++) 01047 { 01048 bFound = false; 01049 for (j = 0; j < pia->n; j++) 01050 { 01051 if (aPorts[i].port == pia->pi[j]) 01052 { 01053 bFound = true; 01054 break; 01055 } 01056 } 01057 if (!bFound) 01058 { 01059 if (SOCKET_CLOSE(aPorts[i].socket) == 0) 01060 { 01061 DebugTotalSockets--; 01062 (*pnPorts)--; 01063 k = *pnPorts; 01064 if (i != k) 01065 { 01066 aPorts[i] = aPorts[k]; 01067 } 01068 aPorts[k].port = 0; 01069 aPorts[k].socket = INVALID_SOCKET; 01070 } 01071 } 01072 } 01073 01074 // Any requested port which does not appear in the existing open set 01075 // of ports should be opened. 01076 // 01077 for (j = 0; j < pia->n; j++) 01078 { 01079 bFound = false; 01080 for (i = 0; i < *pnPorts; i++) 01081 { 01082 if (aPorts[i].port == pia->pi[j]) 01083 { 01084 bFound = true; 01085 break; 01086 } 01087 } 01088 if (!bFound) 01089 { 01090 k = *pnPorts; 01091 (*pnPorts)++; 01092 aPorts[k].port = pia->pi[j]; 01093 make_socket(aPorts+k); 01094 } 01095 } 01096 01097 #ifndef WIN32 01098 for (i = 0; i < *pnPorts; i++) 01099 { 01100 if (maxd <= aPorts[i].socket) 01101 { 01102 maxd = aPorts[i].socket + 1; 01103 } 01104 } 01105 #endif 01106 }
static void SetUsState | ( | DESC * | d, | |
unsigned char | chOption, | |||
int | iUsState | |||
) | [static] |
Change our side's negotiation state.
d | Player connection context. | |
chOption | Telnet Option. | |
iHimState | One of the six option negotiation states. |
Definition at line 2709 of file bsd.cpp.
References DisableUs(), EnableUs(), descriptor_data::nvt_eor_us_state, descriptor_data::nvt_naws_us_state, descriptor_data::nvt_sga_us_state, OPTION_NO, OPTION_YES, TELNET_EOR, TELNET_NAWS, and TELNET_SGA.
Referenced by DisableUs(), EnableUs(), and process_input_helper().
02710 { 02711 if (TELNET_NAWS == chOption) 02712 { 02713 d->nvt_naws_us_state = iUsState; 02714 } 02715 else if (TELNET_EOR == chOption) 02716 { 02717 d->nvt_eor_us_state = iUsState; 02718 if (OPTION_YES == iUsState) 02719 { 02720 EnableUs(d, TELNET_SGA); 02721 } 02722 else if (OPTION_NO == iUsState) 02723 { 02724 DisableUs(d, TELNET_SGA); 02725 } 02726 } 02727 else if (TELNET_SGA == chOption) 02728 { 02729 d->nvt_sga_us_state = iUsState; 02730 } 02731 }
void shovechars | ( | int | nPorts, | |
PortInfo | aPorts[] | |||
) |
Definition at line 1417 of file bsd.cpp.
References boot_slave(), CheckInput, CheckOutput, d1, DARK, db, statedata::debug_cmd, DESC_ITER_ALL, DESC_ITER_PLAYER, DESC_SAFEITER_ALL, descriptor_data::descriptor, DS_AUTODARK, ENDLOG, FLAG_WORD1, descriptor_data::flags, object::fs, get_slave_result(), CLinearTimeAbsolute::GetUTC(), GOD, IS_INVALID_SOCKET, IS_SOCKET_ERROR, log_number(), log_perror(), LOG_PROBLEMS, log_text(), maxd, mudstate, ndescriptors, new_connection(), process_input(), process_output(), R_SOCKDIED, CScheduler::RunTasks(), scheduler, statedata::shutdown_flag, shutdownsock(), slave_socket, SOCKET_EBADF, SOCKET_EINTR, SOCKET_LAST_ERROR, STARTLOG, time_30m, update_quotas(), ValidSocket(), CScheduler::WhenNext(), and flagset::word.
Referenced by main().
01418 { 01419 fd_set input_set, output_set; 01420 int found; 01421 DESC *d, *dnext, *newd; 01422 unsigned int avail_descriptors; 01423 int maxfds; 01424 int i; 01425 01426 #define CheckInput(x) FD_ISSET(x, &input_set) 01427 #define CheckOutput(x) FD_ISSET(x, &output_set) 01428 01429 mudstate.debug_cmd = "< shovechars >"; 01430 01431 CLinearTimeAbsolute ltaLastSlice; 01432 ltaLastSlice.GetUTC(); 01433 01434 #ifdef HAVE_GETDTABLESIZE 01435 maxfds = getdtablesize(); 01436 #else // HAVE_GETDTABLESIZE 01437 maxfds = sysconf(_SC_OPEN_MAX); 01438 #endif // HAVE_GETDTABLESIZE 01439 01440 avail_descriptors = maxfds - 7; 01441 01442 while (mudstate.shutdown_flag == 0) 01443 { 01444 CLinearTimeAbsolute ltaCurrent; 01445 ltaCurrent.GetUTC(); 01446 update_quotas(ltaLastSlice, ltaCurrent); 01447 01448 // Check the scheduler. 01449 // 01450 scheduler.RunTasks(ltaCurrent); 01451 CLinearTimeAbsolute ltaWakeUp; 01452 if (scheduler.WhenNext(<aWakeUp)) 01453 { 01454 if (ltaWakeUp < ltaCurrent) 01455 { 01456 ltaWakeUp = ltaCurrent; 01457 } 01458 } 01459 else 01460 { 01461 CLinearTimeDelta ltd = time_30m; 01462 ltaWakeUp = ltaCurrent + ltd; 01463 } 01464 01465 if (mudstate.shutdown_flag) 01466 { 01467 break; 01468 } 01469 01470 FD_ZERO(&input_set); 01471 FD_ZERO(&output_set); 01472 01473 // Listen for new connections if there are free descriptors. 01474 // 01475 if (ndescriptors < avail_descriptors) 01476 { 01477 for (i = 0; i < nPorts; i++) 01478 { 01479 FD_SET(aPorts[i].socket, &input_set); 01480 } 01481 } 01482 01483 // Listen for replies from the slave socket. 01484 // 01485 if (!IS_INVALID_SOCKET(slave_socket)) 01486 { 01487 FD_SET(slave_socket, &input_set); 01488 } 01489 01490 #ifdef QUERY_SLAVE 01491 // Listen for replies from the sqlslave socket. 01492 // 01493 if (!IS_INVALID_SOCKET(sqlslave_socket)) 01494 { 01495 FD_SET(sqlslave_socket, &input_set); 01496 } 01497 #endif // QUERY_SLAVE 01498 01499 // Mark sockets that we want to test for change in status. 01500 // 01501 DESC_ITER_ALL(d) 01502 { 01503 if (!d->input_head) 01504 { 01505 FD_SET(d->descriptor, &input_set); 01506 } 01507 if (d->output_head) 01508 { 01509 FD_SET(d->descriptor, &output_set); 01510 } 01511 } 01512 01513 // Wait for something to happen. 01514 // 01515 struct timeval timeout; 01516 CLinearTimeDelta ltdTimeout = ltaWakeUp - ltaCurrent; 01517 ltdTimeout.ReturnTimeValueStruct(&timeout); 01518 found = select(maxd, &input_set, &output_set, (fd_set *) NULL, 01519 &timeout); 01520 01521 if (IS_SOCKET_ERROR(found)) 01522 { 01523 int iSocketError = SOCKET_LAST_ERROR; 01524 if (iSocketError == SOCKET_EBADF) 01525 { 01526 // This one is bad, as it results in a spiral of 01527 // doom, unless we can figure out what the bad file 01528 // descriptor is and get rid of it. 01529 // 01530 log_perror("NET", "FAIL", "checking for activity", "select"); 01531 01532 // Search for a bad socket amoungst the players. 01533 // 01534 DESC_ITER_ALL(d) 01535 { 01536 if (!ValidSocket(d->descriptor)) 01537 { 01538 STARTLOG(LOG_PROBLEMS, "ERR", "EBADF"); 01539 log_text("Bad descriptor "); 01540 log_number(d->descriptor); 01541 ENDLOG; 01542 shutdownsock(d, R_SOCKDIED); 01543 } 01544 } 01545 if ( !IS_INVALID_SOCKET(slave_socket) 01546 && !ValidSocket(slave_socket)) 01547 { 01548 // Try to restart the slave, since it presumably 01549 // died. 01550 // 01551 STARTLOG(LOG_PROBLEMS, "ERR", "EBADF"); 01552 log_text("Bad slave descriptor "); 01553 log_number(slave_socket); 01554 ENDLOG; 01555 boot_slave(GOD, GOD, GOD, 0); 01556 } 01557 01558 #ifdef QUERY_SLAVE 01559 if ( !IS_INVALID_SOCKET(sqlslave_socket) 01560 && !ValidSocket(sqlslave_socket)) 01561 { 01562 CleanUpSQLSlaveSocket(); 01563 } 01564 #endif // QUERY_SLAVE 01565 01566 for (i = 0; i < nPorts; i++) 01567 { 01568 if (!ValidSocket(aPorts[i].socket)) 01569 { 01570 // That's it. Game over. 01571 // 01572 STARTLOG(LOG_PROBLEMS, "ERR", "EBADF"); 01573 log_text("Bad game port descriptor "); 01574 log_number(aPorts[i].socket); 01575 ENDLOG; 01576 return; 01577 } 01578 } 01579 } 01580 else if (iSocketError != SOCKET_EINTR) 01581 { 01582 log_perror("NET", "FAIL", "checking for activity", "select"); 01583 } 01584 continue; 01585 } 01586 01587 // Get usernames and hostnames. 01588 // 01589 if ( !IS_INVALID_SOCKET(slave_socket) 01590 && CheckInput(slave_socket)) 01591 { 01592 while (get_slave_result() == 0) 01593 { 01594 ; // Nothing. 01595 } 01596 } 01597 01598 #ifdef QUERY_SLAVE 01599 // Get result sets from sqlslave. 01600 // 01601 if ( !IS_INVALID_SOCKET(sqlslave_socket) 01602 && CheckInput(sqlslave_socket)) 01603 { 01604 while (get_sqlslave_result() == 0) 01605 { 01606 ; // Nothing. 01607 } 01608 } 01609 #endif // QUERY_SLAVE 01610 01611 // Check for new connection requests. 01612 // 01613 for (i = 0; i < nPorts; i++) 01614 { 01615 if (CheckInput(aPorts[i].socket)) 01616 { 01617 int iSocketError; 01618 newd = new_connection(aPorts+i, &iSocketError); 01619 if (!newd) 01620 { 01621 if ( iSocketError 01622 && iSocketError != SOCKET_EINTR) 01623 { 01624 log_perror("NET", "FAIL", NULL, "new_connection"); 01625 } 01626 } 01627 else if (maxd <= newd->descriptor) 01628 { 01629 maxd = newd->descriptor + 1; 01630 } 01631 } 01632 } 01633 01634 // Check for activity on user sockets. 01635 // 01636 DESC_SAFEITER_ALL(d, dnext) 01637 { 01638 // Process input from sockets with pending input. 01639 // 01640 if (CheckInput(d->descriptor)) 01641 { 01642 // Undo autodark 01643 // 01644 if (d->flags & DS_AUTODARK) 01645 { 01646 // Clear the DS_AUTODARK on every related session. 01647 // 01648 DESC *d1; 01649 DESC_ITER_PLAYER(d->player, d1) 01650 { 01651 d1->flags &= ~DS_AUTODARK; 01652 } 01653 db[d->player].fs.word[FLAG_WORD1] &= ~DARK; 01654 } 01655 01656 // Process received data. 01657 // 01658 if (!process_input(d)) 01659 { 01660 shutdownsock(d, R_SOCKDIED); 01661 continue; 01662 } 01663 } 01664 01665 // Process output for sockets with pending output. 01666 // 01667 if (CheckOutput(d->descriptor)) 01668 { 01669 process_output(d, true); 01670 } 01671 } 01672 } 01673 }
void shutdownsock | ( | DESC * | d, | |
int | reason | |||
) |
Definition at line 1843 of file bsd.cpp.
References A_PROGCMD, A_REASON, statedata::access_list, descriptor_data::addr, descriptor_data::address, alloc_lbuf, alloc_mbuf, announce_disconnect(), atr_add_raw(), atr_clr(), CIF_LASTCONNECT, CIF_LONGESTCONNECT, CIF_NUMCONNECTS, CIF_TOTALTIME, clearstrings(), descriptor_data::command_count, descriptor_data::connected_at, db, decode_flags(), DESC_ITER_PLAYER, descriptor_data::descriptor, DS_CONNECTED, ENDLOG, FC_QUIT, fcache_dump(), fetch_ConnectionInfoFields(), find_oldest(), descriptor_data::flags, free_lbuf, free_mbuf, free_sbuf, CLinearTimeAbsolute::GetUTC(), GOD, H_FORBIDDEN, Location, LOG_ACCOUNTING, LOG_LOGIN, log_name(), LOG_NET, LOG_SECURITY, log_text(), MAX_GLOBAL_REGS, MEMFREE, mudstate, Name, Pennies(), descriptor_data::player, process_output(), descriptor_data::program_data, put_ConnectionInfoFields(), R_LOGOUT, R_QUIT, CLinearTimeDelta::ReturnSeconds(), site_check(), SiteMonSend(), STARTLOG, and prog_data::wait_regs.
Referenced by boot_by_port(), boot_off(), check_connect(), check_idle(), close_sockets(), do_logged_out_internal(), failconn(), load_restart_db(), process_output(), and shovechars().
01844 { 01845 char *buff, *buff2; 01846 int i, num; 01847 DESC *dtemp; 01848 01849 if ( (reason == R_LOGOUT) 01850 && (site_check((d->address).sin_addr, mudstate.access_list) == H_FORBIDDEN)) 01851 { 01852 reason = R_QUIT; 01853 } 01854 01855 CLinearTimeAbsolute ltaNow; 01856 ltaNow.GetUTC(); 01857 01858 if (d->flags & DS_CONNECTED) 01859 { 01860 // Added by D.Piper (del@doofer.org) 1997 & 2000-APR 01861 // 01862 01863 // Reason: attribute (disconnect reason) 01864 // 01865 atr_add_raw(d->player, A_REASON, (char *)disc_messages[reason]); 01866 01867 // Update the A_CONNINFO attribute. 01868 // 01869 long anFields[4]; 01870 fetch_ConnectionInfoFields(d->player, anFields); 01871 01872 // One of the active sessions is going away. It doesn't matter which 01873 // one. 01874 // 01875 anFields[CIF_NUMCONNECTS]++; 01876 01877 // What are the two longest sessions? 01878 // 01879 DESC *dOldest[2]; 01880 find_oldest(d->player, dOldest); 01881 01882 CLinearTimeDelta ltdFull; 01883 ltdFull = ltaNow - dOldest[0]->connected_at; 01884 long tFull = ltdFull.ReturnSeconds(); 01885 if (dOldest[0] == d) 01886 { 01887 // We are dropping the oldest connection. 01888 // 01889 CLinearTimeDelta ltdPart; 01890 if (dOldest[1]) 01891 { 01892 // There is another (more recently made) connection. 01893 // 01894 ltdPart = dOldest[1]->connected_at - dOldest[0]->connected_at; 01895 } 01896 else 01897 { 01898 // There is only one connection. 01899 // 01900 ltdPart = ltdFull; 01901 } 01902 long tPart = ltdPart.ReturnSeconds(); 01903 01904 anFields[CIF_TOTALTIME] += tPart; 01905 if (anFields[CIF_LONGESTCONNECT] < tFull) 01906 { 01907 anFields[CIF_LONGESTCONNECT] = tFull; 01908 } 01909 } 01910 anFields[CIF_LASTCONNECT] = tFull; 01911 01912 put_ConnectionInfoFields(d->player, anFields, ltaNow); 01913 01914 // If we are doing a LOGOUT, keep the connection open so that the 01915 // player can connect to a different character. Otherwise, we 01916 // do the normal disconnect stuff. 01917 // 01918 if (reason == R_LOGOUT) 01919 { 01920 STARTLOG(LOG_NET | LOG_LOGIN, "NET", "LOGO") 01921 buff = alloc_mbuf("shutdownsock.LOG.logout"); 01922 sprintf(buff, "[%u/%s] Logout by ", d->descriptor, d->addr); 01923 log_text(buff); 01924 log_name(d->player); 01925 sprintf(buff, " <Reason: %s>", disc_reasons[reason]); 01926 log_text(buff); 01927 free_mbuf(buff); 01928 ENDLOG; 01929 } 01930 else 01931 { 01932 fcache_dump(d, FC_QUIT); 01933 STARTLOG(LOG_NET | LOG_LOGIN, "NET", "DISC") 01934 buff = alloc_mbuf("shutdownsock.LOG.disconn"); 01935 sprintf(buff, "[%u/%s] Logout by ", d->descriptor, d->addr); 01936 log_text(buff); 01937 log_name(d->player); 01938 sprintf(buff, " <Reason: %s>", disc_reasons[reason]); 01939 log_text(buff); 01940 free_mbuf(buff); 01941 ENDLOG; 01942 SiteMonSend(d->descriptor, d->addr, d, "Disconnection"); 01943 } 01944 01945 // If requested, write an accounting record of the form: 01946 // Plyr# Flags Cmds ConnTime Loc Money [Site] <DiscRsn> Name 01947 // 01948 STARTLOG(LOG_ACCOUNTING, "DIS", "ACCT"); 01949 CLinearTimeDelta ltd = ltaNow - d->connected_at; 01950 int Seconds = ltd.ReturnSeconds(); 01951 buff = alloc_lbuf("shutdownsock.LOG.accnt"); 01952 buff2 = decode_flags(GOD, &(db[d->player].fs)); 01953 sprintf(buff, "%d %s %d %d %d %d [%s] <%s> %s", d->player, buff2, d->command_count, 01954 Seconds, Location(d->player), Pennies(d->player), d->addr, disc_reasons[reason], 01955 Name(d->player)); 01956 log_text(buff); 01957 free_lbuf(buff); 01958 free_sbuf(buff2); 01959 ENDLOG; 01960 announce_disconnect(d->player, d, disc_messages[reason]); 01961 } 01962 else 01963 { 01964 if (reason == R_LOGOUT) 01965 { 01966 reason = R_QUIT; 01967 } 01968 STARTLOG(LOG_SECURITY | LOG_NET, "NET", "DISC"); 01969 buff = alloc_mbuf("shutdownsock.LOG.neverconn"); 01970 sprintf(buff, "[%u/%s] Connection closed, never connected. <Reason: %s>", d->descriptor, d->addr, disc_reasons[reason]); 01971 log_text(buff); 01972 free_mbuf(buff); 01973 ENDLOG; 01974 SiteMonSend(d->descriptor, d->addr, d, "N/C Connection Closed"); 01975 } 01976 01977 process_output(d, false); 01978 clearstrings(d); 01979 01980 d->flags &= ~DS_CONNECTED; 01981 01982 // Is this desc still in interactive mode? 01983 // 01984 if (d->program_data != NULL) 01985 { 01986 num = 0; 01987 DESC_ITER_PLAYER(d->player, dtemp) num++; 01988 01989 if (num == 0) 01990 { 01991 for (i = 0; i < MAX_GLOBAL_REGS; i++) 01992 { 01993 if (d->program_data->wait_regs[i]) 01994 { 01995 free_lbuf(d->program_data->wait_regs[i]); 01996 d->program_data->wait_regs[i] = NULL; 01997 } 01998 } 01999 MEMFREE(d->program_data); 02000 atr_clr(d->player, A_PROGCMD); 02001 } 02002 d->program_data = NULL; 02003 } 02004 if (reason == R_LOGOUT) 02005 { 02006 d->connected_at.GetUTC(); 02007 d->retries_left = mudconf.retry_limit; 02008 d->command_count = 0; 02009 d->timeout = mudconf.idle_timeout; 02010 d->player = 0; 02011 d->doing[0] = '\0'; 02012 d->quota = mudconf.cmd_quota_max; 02013 d->last_time = d->connected_at; 02014 d->host_info = site_check((d->address).sin_addr, mudstate.access_list) 02015 | site_check((d->address).sin_addr, mudstate.suspect_list); 02016 d->input_tot = d->input_size; 02017 d->output_tot = 0; 02018 welcome_user(d); 02019 } 02020 else 02021 { 02022 // Cancel any scheduled processing on this descriptor. 02023 // 02024 scheduler.CancelTask(Task_ProcessCommand, d, 0); 02025 02026 #ifdef WIN32 02027 if (platform == VER_PLATFORM_WIN32_NT) 02028 { 02029 // Don't close down the socket twice. 02030 // 02031 if (!d->bConnectionShutdown) 02032 { 02033 // Make sure we don't try to initiate or process any 02034 // outstanding IOs 02035 // 02036 d->bConnectionShutdown = true; 02037 02038 // Protect removing the descriptor from our linked list from 02039 // any interference from the listening thread. 02040 // 02041 EnterCriticalSection(&csDescriptorList); 02042 *d->prev = d->next; 02043 if (d->next) 02044 { 02045 d->next->prev = d->prev; 02046 } 02047 LeaveCriticalSection(&csDescriptorList); 02048 02049 // This descriptor may hang around awhile, clear out the links. 02050 // 02051 d->next = 0; 02052 d->prev = 0; 02053 02054 // Close the connection in 5 seconds. 02055 // 02056 scheduler.DeferTask(ltaNow + FACTOR_100NS_PER_SECOND*5, 02057 PRIORITY_SYSTEM, Task_DeferredClose, d, 0); 02058 } 02059 return; 02060 } 02061 #endif 02062 02063 shutdown(d->descriptor, SD_BOTH); 02064 if (SOCKET_CLOSE(d->descriptor) == 0) 02065 { 02066 DebugTotalSockets--; 02067 } 02068 d->descriptor = INVALID_SOCKET; 02069 02070 *d->prev = d->next; 02071 if (d->next) 02072 { 02073 d->next->prev = d->prev; 02074 } 02075 02076 // This descriptor may hang around awhile, clear out the links. 02077 // 02078 d->next = 0; 02079 d->prev = 0; 02080 02081 // If we don't have queued IOs, then we can free these, now. 02082 // 02083 freeqs(d); 02084 free_desc(d); 02085 ndescriptors--; 02086 } 02087 }
static RETSIGTYPE DCL_CDECL sighandler | ( | int | sig | ) | [static] |
Definition at line 3745 of file bsd.cpp.
References al_store(), statedata::bCanRestart, CScheduler::CancelTask(), CAST_SIGNAL_FUNC, check_panicking(), CleanUpSlaveProcess(), CleanUpSlaveSocket(), CLOSE, confdata::config_file, CScheduler::DeferTask(), dispatch_DatabaseDump(), do_restart(), statedata::dump_counter, dump_database_internal(), DUMP_I_RESTART, DUMP_I_SIGNAL, dump_restart_db(), statedata::dumped, statedata::dumper, statedata::dumping, ENDLOG, CLogFile::Flush(), confdata::fork_dump, CLinearTimeAbsolute::GetUTC(), GOD, local_dump_complete_signal(), local_presync_database_sigsegv(), Log, LOG_PROBLEMS, log_signal(), log_signal_ignore(), LogStatBuf(), confdata::mud_name, mudconf, mudstate, MuxAlarm, statedata::panicking, pcache_sync(), confdata::pid_file, PRIORITY_SYSTEM, raw_broadcast(), report(), SA_EXIT, scheduler, statedata::shutdown_flag, confdata::sig_action, CMuxAlarm::Signal(), SignalDesc(), slave_pid, STARTLOG, SYNC, CLogFile::tinyprintf(), and unset_signals().
Referenced by set_signals().
03746 { 03747 #ifndef WIN32 03748 int stat_buf; 03749 pid_t child; 03750 #endif // !WIN32 03751 03752 switch (sig) 03753 { 03754 #ifndef WIN32 03755 case SIGUSR1: 03756 if (mudstate.bCanRestart) 03757 { 03758 log_signal(sig); 03759 do_restart(GOD, GOD, GOD, 0); 03760 } 03761 else 03762 { 03763 log_signal_ignore(sig); 03764 } 03765 break; 03766 03767 case SIGUSR2: 03768 03769 // Drop a flatfile. 03770 // 03771 log_signal(sig); 03772 raw_broadcast(0, "Caught signal %s requesting a flatfile @dump. Please wait.", SignalDesc(sig)); 03773 dump_database_internal(DUMP_I_SIGNAL); 03774 break; 03775 03776 case SIGCHLD: 03777 03778 // Change in child status. 03779 // 03780 #ifndef SIGNAL_SIGCHLD_BRAINDAMAGE 03781 signal(SIGCHLD, CAST_SIGNAL_FUNC sighandler); 03782 #endif // !SIGNAL_SIGCHLD_BRAINDAMAGE 03783 03784 while ((child = waitpid(0, &stat_buf, WNOHANG)) > 0) 03785 { 03786 if ( WIFEXITED(stat_buf) 03787 || WIFSIGNALED(stat_buf)) 03788 { 03789 if (child == slave_pid) 03790 { 03791 // The reverse-DNS slave process ended unexpectedly. 03792 // 03793 CleanUpSlaveSocket(); 03794 slave_pid = 0; 03795 03796 LogStatBuf(stat_buf, "SLAVE"); 03797 03798 continue; 03799 } 03800 #ifdef QUERY_SLAVE 03801 else if (child == sqlslave_pid) 03802 { 03803 // The SQL slave process ended unexpectedly. 03804 // 03805 CleanUpSQLSlaveSocket(); 03806 sqlslave_pid = 0; 03807 03808 LogStatBuf(stat_buf, "QUERY"); 03809 03810 continue; 03811 } 03812 #endif // QUERY_SLAVE 03813 else if ( mudconf.fork_dump 03814 && mudstate.dumping) 03815 { 03816 mudstate.dumped = child; 03817 if (mudstate.dumper == mudstate.dumped) 03818 { 03819 // The dumping process finished. 03820 // 03821 mudstate.dumper = 0; 03822 mudstate.dumped = 0; 03823 } 03824 else 03825 { 03826 // The dumping process finished before we could 03827 // obtain its process id from fork(). 03828 // 03829 } 03830 mudstate.dumping = false; 03831 local_dump_complete_signal(); 03832 03833 continue; 03834 } 03835 } 03836 03837 log_signal(sig); 03838 LogStatBuf(stat_buf, "UKNWN"); 03839 03840 STARTLOG(LOG_PROBLEMS, "SIG", "DEBUG"); 03841 #ifdef QUERY_SLAVE 03842 Log.tinyprintf("mudstate.dumper=%d, child=%d, slave_pid=%d, sqlslave_pid=%d" ENDLINE, 03843 mudstate.dumper, child, slave_pid, sqlslave_pid); 03844 #else 03845 Log.tinyprintf("mudstate.dumper=%d, child=%d, slave_pid=%d" ENDLINE, 03846 mudstate.dumper, child, slave_pid); 03847 #endif // QUERY_SLAVE 03848 ENDLOG; 03849 } 03850 break; 03851 03852 case SIGHUP: 03853 03854 // Perform a database dump. 03855 // 03856 log_signal(sig); 03857 extern void dispatch_DatabaseDump(void *pUnused, int iUnused); 03858 scheduler.CancelTask(dispatch_DatabaseDump, 0, 0); 03859 mudstate.dump_counter.GetUTC(); 03860 scheduler.DeferTask(mudstate.dump_counter, PRIORITY_SYSTEM, dispatch_DatabaseDump, 0, 0); 03861 break; 03862 03863 #ifdef HAVE_SETITIMER 03864 case SIGPROF: 03865 03866 // Softcode is running longer than is reasonable. Apply the brakes. 03867 // 03868 log_signal(sig); 03869 MuxAlarm.Signal(); 03870 break; 03871 #endif 03872 03873 #endif // !WIN32 03874 03875 case SIGINT: 03876 03877 // Log + ignore 03878 // 03879 log_signal(sig); 03880 break; 03881 03882 #ifndef WIN32 03883 case SIGQUIT: 03884 #endif // !WIN32 03885 case SIGTERM: 03886 #ifdef SIGXCPU 03887 case SIGXCPU: 03888 #endif // SIGXCPU 03889 // Time for a normal and short-winded shutdown. 03890 // 03891 check_panicking(sig); 03892 log_signal(sig); 03893 raw_broadcast(0, "GAME: Caught signal %s, exiting.", SignalDesc(sig)); 03894 mudstate.shutdown_flag = true; 03895 break; 03896 03897 case SIGILL: 03898 case SIGFPE: 03899 case SIGSEGV: 03900 #ifndef WIN32 03901 case SIGTRAP: 03902 #ifdef SIGXFSZ 03903 case SIGXFSZ: 03904 #endif // SIGXFSZ 03905 #ifdef SIGEMT 03906 case SIGEMT: 03907 #endif // SIGEMT 03908 #ifdef SIGBUS 03909 case SIGBUS: 03910 #endif // SIGBUS 03911 #ifdef SIGSYS 03912 case SIGSYS: 03913 #endif // SIGSYS 03914 #endif // !WIN32 03915 03916 // Panic save + restart. 03917 // 03918 Log.Flush(); 03919 check_panicking(sig); 03920 log_signal(sig); 03921 report(); 03922 03923 local_presync_database_sigsegv(); 03924 #ifndef MEMORY_BASED 03925 al_store(); 03926 #endif 03927 pcache_sync(); 03928 SYNC; 03929 03930 if ( mudconf.sig_action != SA_EXIT 03931 && mudstate.bCanRestart) 03932 { 03933 raw_broadcast 03934 ( 0, 03935 "GAME: Fatal signal %s caught, restarting.", 03936 SignalDesc(sig) 03937 ); 03938 03939 // There is no older DB. It's a fiction. Our only choice is 03940 // between unamed attributes and named ones. We go with what we 03941 // got. 03942 // 03943 dump_database_internal(DUMP_I_RESTART); 03944 SYNC; 03945 CLOSE; 03946 #ifdef WIN32 03947 unset_signals(); 03948 signal(sig, SIG_DFL); 03949 WSACleanup(); 03950 exit(12345678); 03951 #else // WIN32 03952 CleanUpSlaveSocket(); 03953 CleanUpSlaveProcess(); 03954 03955 // Try our best to dump a core first 03956 // 03957 if (!fork()) 03958 { 03959 // We are the broken parent. Die. 03960 // 03961 unset_signals(); 03962 exit(1); 03963 } 03964 03965 // We are the reproduced child with a slightly better chance. 03966 // 03967 dump_restart_db(); 03968 #ifdef GAME_DOOFERMUX 03969 execl("bin/netmux", mudconf.mud_name, "-c", mudconf.config_file, "-p", mudconf.pid_file, NULL); 03970 #else // GAME_DOOFERMUX 03971 execl("bin/netmux", "netmux", "-c", mudconf.config_file, "-p", mudconf.pid_file, NULL); 03972 #endif // GAME_DOOFERMUX 03973 break; 03974 #endif // WIN32 03975 } 03976 else 03977 { 03978 #ifdef WIN32 03979 WSACleanup(); 03980 #endif // WIN32 03981 03982 unset_signals(); 03983 signal(sig, SIG_DFL); 03984 exit(1); 03985 } 03986 break; 03987 03988 case SIGABRT: 03989 03990 // Coredump. 03991 // 03992 check_panicking(sig); 03993 log_signal(sig); 03994 report(); 03995 03996 #ifdef WIN32 03997 WSACleanup(); 03998 #endif // WIN32 03999 04000 unset_signals(); 04001 signal(sig, SIG_DFL); 04002 exit(1); 04003 } 04004 signal(sig, CAST_SIGNAL_FUNC sighandler); 04005 mudstate.panicking = 0; 04006 }
static char* SignalDesc | ( | int | iSignal | ) | [static] |
Definition at line 3693 of file bsd.cpp.
References LBUF_SIZE, safe_chr, safe_str, and signames.
Referenced by log_signal(), log_signal_ignore(), LogStatBuf(), and sighandler().
03694 { 03695 static char buff[LBUF_SIZE]; 03696 char *bufc = buff; 03697 safe_str(signames[iSignal].pShortName, buff, &bufc); 03698 if (signames[iSignal].pLongName) 03699 { 03700 safe_str(" (", buff, &bufc); 03701 safe_str(signames[iSignal].pLongName, buff, &bufc); 03702 safe_chr(')', buff, &bufc); 03703 } 03704 *bufc = '\0'; 03705 return buff; 03706 }
void SiteMonSend | ( | int | , | |
const char * | , | |||
DESC * | , | |||
const char * | ||||
) | [static] |
Definition at line 4599 of file bsd.cpp.
References DESC_ITER_CONN, H_NOSITEMON, H_SUSPECT, descriptor_data::host_info, IS_INVALID_SOCKET, descriptor_data::player, process_output(), queue_string(), queue_write_LEN(), SiteMon, and tprintf().
Referenced by new_connection(), and shutdownsock().
04600 { 04601 // Don't do sitemon for blocked sites. 04602 // 04603 if ( d != NULL 04604 && (d->host_info & H_NOSITEMON)) 04605 { 04606 return; 04607 } 04608 04609 // Build the msg. 04610 // 04611 char *sendMsg; 04612 bool bSuspect = (d != NULL) && (d->host_info & H_SUSPECT); 04613 if (IS_INVALID_SOCKET(port)) 04614 { 04615 sendMsg = tprintf("SITEMON: [UNKNOWN] %s from %s.%s", msg, address, 04616 bSuspect ? " (SUSPECT)": ""); 04617 } 04618 else 04619 { 04620 sendMsg = tprintf("SITEMON: [%d] %s from %s.%s", port, msg, 04621 address, bSuspect ? " (SUSPECT)": ""); 04622 } 04623 04624 DESC *nd; 04625 DESC_ITER_CONN(nd) 04626 { 04627 if (SiteMon(nd->player)) 04628 { 04629 queue_string(nd, sendMsg); 04630 queue_write_LEN(nd, "\r\n", 2); 04631 process_output(nd, false); 04632 } 04633 } 04634 }
void TelnetSetup | ( | DESC * | d | ) | [static] |
Begin initial telnet negotiations on a socket.
The two sides of the connection may not agree on the following set of options, and keep in mind that the successful negotiation of a particular option may cause the negotiation of another option.
Without this function, we are only react to client requests.
d | Player connection on which the input arrived. |
Definition at line 2965 of file bsd.cpp.
References EnableHim(), EnableUs(), TELNET_EOR, TELNET_NAWS, and TELNET_SGA.
Referenced by new_connection().
02966 { 02967 // Attempt negotation of EOR so we can use that, and if that succeeds, 02968 // code elsewhere will attempt the negotation of SGA for our side as well. 02969 // 02970 EnableUs(d, TELNET_EOR); 02971 EnableHim(d, TELNET_EOR); 02972 EnableHim(d, TELNET_SGA); 02973 EnableHim(d, TELNET_NAWS); 02974 }
static void unset_signals | ( | void | ) | [static] |
Definition at line 3400 of file bsd.cpp.
Referenced by sighandler().
03401 { 03402 int i; 03403 03404 for (i = 0; i < NSIG; i++) 03405 { 03406 signal(i, SIG_DFL); 03407 } 03408 }
int UsState | ( | DESC * | d, | |
unsigned char | chOption | |||
) |
Return our side's negotiation state.
The negotiation of each optional feature of telnet can be in one of six states (defined in interface.h): OPTION_NO, OPTION_YES, OPTION_WANTNO_EMPTY, OPTION_WANTNO_OPPOSITE, OPTION_WANTYES_EMPTY, and OPTION_WANTYES_OPPOSITE.
An option is only enabled when it is in the OPTION_YES state.
d | Player connection context. | |
chOption | Telnet Option |
Definition at line 2660 of file bsd.cpp.
References descriptor_data::nvt_eor_us_state, descriptor_data::nvt_naws_us_state, descriptor_data::nvt_sga_us_state, OPTION_NO, TELNET_EOR, TELNET_NAWS, and TELNET_SGA.
Referenced by DesiredUsOption(), do_prog(), handle_prog(), and process_input_helper().
02661 { 02662 if (TELNET_NAWS == chOption) 02663 { 02664 return d->nvt_naws_us_state; 02665 } 02666 else if (TELNET_EOR == chOption) 02667 { 02668 return d->nvt_eor_us_state; 02669 } 02670 else if (TELNET_SGA == chOption) 02671 { 02672 return d->nvt_sga_us_state; 02673 } 02674 return OPTION_NO; 02675 }
bool ValidSocket | ( | SOCKET | s | ) |
Definition at line 1407 of file bsd.cpp.
Referenced by shovechars().
01408 { 01409 struct stat fstatbuf; 01410 if (fstat(s, &fstatbuf) < 0) 01411 { 01412 return false; 01413 } 01414 return true; 01415 }
PortInfo aMainGamePorts[MAX_LISTEN_PORTS] |
Definition at line 32 of file bsd.cpp.
Referenced by close_sockets(), dump_restart_db(), load_restart_db(), and main().
const SIGNALTYPE aSigTypes[] |
DESC* descriptor_list = NULL |
Definition at line 36 of file bsd.cpp.
Referenced by get_slave_result(), initializesock(), and load_restart_db().
const char* disc_messages[] [static] |
const char* disc_reasons[] [static] |
pid_t game_pid |
Definition at line 52 of file bsd.cpp.
Referenced by check_panicking(), list_process(), main(), and write_pidfile().
int maxd = 0 |
Definition at line 49 of file bsd.cpp.
Referenced by boot_slave(), load_restart_db(), and shovechars().
unsigned int ndescriptors = 0 |
Definition at line 35 of file bsd.cpp.
Referenced by initializesock(), load_restart_db(), and shovechars().
int nMainGamePorts = 0 |
Definition at line 33 of file bsd.cpp.
Referenced by close_sockets(), dump_restart_db(), load_restart_db(), and main().
const int nvt_input_action_table[8][14] [static] |
Initial value:
{ { 1, 2, 3, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 5 }, { 4, 4, 4, 4, 4, 4, 12, 2, 10, 6, 7, 8, 9, 1 }, { 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 4 }, { 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 4 }, { 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 4 }, { 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 4 }, { 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 11 }, { 0, 0, 0, 0, 18, 0, 0, 0, 0, 0, 0, 0, 0, 17 }, }
Action 0 - Nothing. Action 1 - Accept CHR(X) (and transition to Normal state). Action 2 - Erase Character. Action 3 - Accept Line. Action 4 - Transition to the Normal state. Action 5 - Transition to Have_IAC state. Action 6 - Transition to the Have_IAC_WILL state. Action 7 - Transition to the Have_IAC_DONT state. Action 8 - Transition to the Have_IAC_DO state. Action 9 - Transition to the Have_IAC_WONT state. Action 10 - Transition to the Have_IAC_SB state. Action 11 - Transition to the Have_IAC_SB_IAC state. Action 12 - Respond to IAC AYT and return to the Normal state. Action 13 - Respond to IAC WILL X Action 14 - Respond to IAC DONT X Action 15 - Respond to IAC DO X Action 16 - Respond to IAC WONT X Action 17 - Accept CHR(X) for Sub-Option (and transition to Have_IAC_SB state). Action 18 - Accept Completed Sub-option and transition to Normal state.
const unsigned char nvt_input_xlat_table[256] [static] |
Initial value:
{ 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 2, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 4, 5, 5, 5, 5, 5, 6, 7, 5, 5, 8, 9, 10, 11, 12, 13 }
The use of this table reduces the size of the state table.
Class 0 - Any byte. Class 5 - BRK (0xF3) Class 10 - WONT (0xFC) Class 1 - BS (0x08) Class 5 - IP (0xF4) Class 11 - DO (0xFD) Class 2 - LF (0x0A) Class 5 - AO (0xF5) Class 12 - DONT (0xFE) Class 3 - CR (0x0D) Class 6 - AYT (0xF6) Class 13 - IAC (0xFF) Class 1 - DEL (0x7F) Class 7 - EC (0xF7) Class 5 - EOR (0xEF) Class 5 - EL (0xF8) Class 4 - SE (0xF0) Class 5 - GA (0xF9) Class 5 - NOP (0xF1) Class 8 - SB (0xFA) Class 5 - DM (0xF2) Class 9 - WILL (0xFB)
MUX_SIGNAMES signames[NSIG] [static] |
pid_t slave_pid = 0 |
Definition at line 50 of file bsd.cpp.
Referenced by boot_slave(), CleanUpSlaveProcess(), and sighandler().
int slave_socket = INVALID_SOCKET |
Definition at line 51 of file bsd.cpp.
Referenced by boot_slave(), CleanUpSlaveSocket(), get_slave_result(), new_connection(), and shovechars().