?? wsckcomm.c
字號:
/***************************************************************************
* Original Diku Mud copyright (C) 1990, 1991 by Sebastian Hammer, *
* Michael Seifert, Hans Henrik St{rfeldt, Tom Madsen, and Katja Nyboe. *
* *
* Merc Diku Mud improvments copyright (C) 1992, 1993 by Michael *
* Chastain, Michael Quan, and Mitchell Tse. *
* *
* Envy Diku Mud improvements copyright (C) 1994 by Michael Quan, David *
* Love, Guilherme 'Willie' Arnold, and Mitchell Tse. *
* *
* Windows sockets port by Slash. *
* *
* In order to use any part of this Envy Diku Mud, you must comply with *
* the original Diku license in 'license.doc', the Merc license in *
* 'license.txt', as well as the Envy license in 'license.nvy'. *
* In particular, you may not remove either of these copyright notices. *
* *
* Thanks to abaddon for proof-reading our comm.c and pointing out bugs. *
* Any remaining bugs are, of course, our work, not his. :) *
* *
* Much time and thought has gone into this software and you are *
* benefitting. We hope that you share your changes too. What goes *
* around, comes around. *
***************************************************************************/
#include <time.h>
#include <stdio.h>
#include <stdlib.h>
//#include "telnet.h"
#include "merc.h"
#include "merc-win.rh"
#include <windows.h>
// Yes, we want mobprogram support
#define MOBPROGS
// Yes, we want support for Merc 2.2 for Windows additions
#define MERCW32
#define STDERR_FILE "stderr.txt" /* For what Unix writes to standard error */
/*
* Definitions for the TELNET protocol.
*/
#define IAC 255 /* interpret as command: */
#define WONT 252 /* I won't use option */
#define WILL 251 /* I will use option */
#define GA 249 /* you may reverse the line */
/* telnet options */
#define TELOPT_ECHO 1 /* echo */
struct host_and_name_lookup {
// These are used by WSAAsyncGetHostByAddr()
char hostdata[MAXGETHOSTSTRUCT];
HANDLE hRequestHandle;
struct in_addr sin_addr;
// These are used by the identd stuff
char username[64];
SOCKET sAuth;
struct sockaddr_in authsock; // Address of the authentication
struct sockaddr_in us; // Address of our socket to this player
struct sockaddr_in them; // Address of our socket to this player
};
/* Local #defines for Win32 */
//#define MAKEWORD(a, b) ((WORD)(((BYTE)(a)) | (((WORD)((BYTE)(b))) << 8)))
#define WM_NET_ACCEPT (WM_USER+500)
#define WM_NET_READWRITE (WM_USER+501)
#define WM_NET_GETHOST (WM_USER+502)
#define WM_NET_AUTHCONNECT (WM_USER+503)
/*
* Global variables.
*/
DESCRIPTOR_DATA * descriptor_free; /* Free list for descriptors */
DESCRIPTOR_DATA * descriptor_list; /* All open descriptors */
DESCRIPTOR_DATA * d_next; /* Next descriptor in loop */
FILE * fpReserve; /* Reserved file handle */
bool god; /* All new chars are gods! */
bool merc_down; /* Shutdown */
bool wizlock; /* Game is wizlocked */
int numlock = 0; /* Game is numlocked at <level> (ENVY) */
char str_boot_time[MAX_INPUT_LENGTH];
time_t current_time; /* Time of this pulse */
/* Windows version variables */
SOCKET control;
int nPlayers = 0;
int nOldPlayers = 0;
FILE *fpStderr;
BOOL fWantsMessageBox = TRUE; // if TRUE, bring up message box on bugs, else log
/*
* Other local functions (OS-independent).
*/
bool check_parse_name args( ( char *name ) );
bool check_reconnect args( ( DESCRIPTOR_DATA *d, char *name,
bool fConn ) );
bool check_playing args( ( DESCRIPTOR_DATA *d, char *name ) );
int main args( ( int argc, char **argv ) );
void nanny args( ( DESCRIPTOR_DATA *d, char *argument ) );
bool process_output args( ( DESCRIPTOR_DATA *d, bool fPrompt ) );
void read_from_buffer args( ( DESCRIPTOR_DATA *d ) );
void stop_idling args( ( CHAR_DATA *ch ) );
//void bust_a_prompt args( ( CHAR_DATA *ch ) );
void bust_a_prompt args( ( DESCRIPTOR_DATA *d ) );
// @@@ My junk
//char UserMessage[512];
//BOOL fUserReady;
const char echo_off_str [] = { IAC, WILL, TELOPT_ECHO, '\0' };
const char echo_on_str [] = { IAC, WONT, TELOPT_ECHO, '\0' };
const char go_ahead_str [] = { IAC, GA, '\0' };
bool write_to_descriptor args( ( int desc, char *txt, int length ) );
bool BlastedTrumpet(SOCKET sSocket);
LRESULT SocketAccept (WPARAM /*wParam*/, LPARAM lParam);
LRESULT SocketReadWrite (WPARAM wParam, LPARAM lParam);
LRESULT SocketGetHost(WPARAM wParam, LPARAM lParam);
LRESULT SocketAuthConnect(WPARAM wParam, LPARAM lParam);
SOCKET init_socket( int port );
bool read_from_descriptor( DESCRIPTOR_DATA *d );
void send_to_char args( ( const char *txt, CHAR_DATA *ch ) )
{
if ( txt == NULL || ch->desc == NULL )
return;
free_string( ch->desc->showstr_head );
#if 0 // @@@ The next line is from sands, it seems wrong
ch->desc->showstr_head = str_dup( txt );
#else
ch->desc->showstr_head = alloc_mem( strlen( txt ) + 1 );
strcpy( ch->desc->showstr_head, txt );
#endif
ch->desc->showstr_point = ch->desc->showstr_head;
show_string( ch->desc, "" );
}
void gettimeofday( struct timeval *tp, void *tzp )
{
tp->tv_sec = time( NULL );
tp->tv_usec = 0;
}
#if 0 // @@@
bool read_from_descriptor( DESCRIPTOR_DATA *d )
{
int iStart;
/* Hold horses if pending command already. */
if ( d->incomm[0] != '\0' )
return TRUE;
/* Check for overflow. */
iStart = strlen(d->inbuf);
if ( iStart >= sizeof(d->inbuf) - 10 )
{
sprintf( log_buf, "%s input overflow!", d->host );
log_string( log_buf );
write_to_descriptor( d->descriptor,
"\n\r*** PUT A LID ON IT!!! ***\n\r", 0 );
return FALSE;
}
#if 0
/* Snarf input. */
for ( ; ; )
{
int c;
c = getc( stdin );
if ( c == '\0' || c == EOF )
break;
putc( c, stdout );
if ( c == '\r' )
putc( '\n', stdout );
d->inbuf[iStart++] = c;
if ( iStart > sizeof(d->inbuf) - 10 )
break;
}
#else
if (fUserReady)
{
int nLen = strlen(UserMessage);
fUserReady = FALSE;
if (iStart + nLen <= sizeof d->inbuf - 10)
{
memcpy(d->inbuf + iStart, UserMessage, nLen);
iStart += nLen;
d->inbuf[iStart++] = '\r';
}
}
#endif
d->inbuf[iStart] = '\0';
return TRUE;
}
#endif
/*
* Transfer one line from input buffer to input line.
*/
void read_from_buffer( DESCRIPTOR_DATA *d )
{
int i, j, k;
/*
* Hold horses if pending command already.
*/
if ( d->incomm[0] != '\0' )
return;
/*
* Look for at least one new line.
*/
for ( i = 0; d->inbuf[i] != '\n' && d->inbuf[i] != '\r'; i++ )
{
if ( d->inbuf[i] == '\0' )
return;
}
/*
* Canonical input processing.
*/
for ( i = 0, k = 0; d->inbuf[i] != '\n' && d->inbuf[i] != '\r'; i++ )
{
if ( k >= MAX_INPUT_LENGTH - 2 )
{
write_to_descriptor( d->descriptor, "Line too long.\n\r", 0 );
/* skip the rest of the line */
for ( ; d->inbuf[i] != '\0'; i++ )
{
if ( d->inbuf[i] == '\n' || d->inbuf[i] == '\r' )
break;
}
d->inbuf[i] = '\n';
d->inbuf[i+1] = '\0';
break;
}
if ( d->inbuf[i] == '\b' && k > 0 )
--k;
else if ( isascii(d->inbuf[i]) && isprint(d->inbuf[i]) )
d->incomm[k++] = d->inbuf[i];
}
/*
* Finish off the line.
*/
if ( k == 0 )
d->incomm[k++] = ' ';
d->incomm[k] = '\0';
/*
* Deal with bozos with #repeat 1000 ...
*/
if ( k > 1 || d->incomm[0] == '!' )
{
if ( d->incomm[0] != '!' && strcmp( d->incomm, d->inlast ) )
{
d->repeat = 0;
}
else
{
if ( ++d->repeat >= 20 )
{
sprintf( log_buf, "%s input spamming!", d->host );
log_string( log_buf );
write_to_descriptor( d->descriptor,
"\n\r*** PUT A LID ON IT!!! ***\n\r", 0 );
strcpy( d->incomm, "quit" );
}
}
}
/*
* Do '!' substitution.
*/
if ( d->incomm[0] == '!' )
strcpy( d->incomm, d->inlast );
else
strcpy( d->inlast, d->incomm );
/*
* Shift the input buffer.
*/
while ( d->inbuf[i] == '\n' || d->inbuf[i] == '\r' )
i++;
for ( j = 0; ( d->inbuf[j] = d->inbuf[i+j] ) != '\0'; j++ )
;
return;
}
void CloseMerc(void)
{
}
HINSTANCE hInst;
HWND hQryDlgBox; // handle of modeless dialog box
HWND hWndMain;
HWND hWndOutput;
//char UserMessage[512];
//bool fUserReady;
LRESULT CALLBACK _export MercWndProc(HWND hWnd, UINT message,
WPARAM wParam, LPARAM lParam)
{
switch (message)
{
case WM_MOVE:
// Move the dialog box on top of our main window every
// time the main window moves.
if (IsWindow(hQryDlgBox))
SendMessage(hQryDlgBox, message, wParam, lParam);
break;
case WM_SETFOCUS:
// Always set the input focus to the dialog box.
if (IsWindow(hQryDlgBox))
SendMessage(hQryDlgBox, message, wParam, lParam);
break;
case WM_CLOSE:
// Tell windows to destroy our window.
DestroyWindow(hWnd);
break;
case WM_QUERYENDSESSION:
// If we return TRUE we are saying it's ok with us to end the
// windows session.
return((long) TRUE); // we agree to end session.
case WM_ENDSESSION:
// If wParam is not zero, it meany every application said ok
// to WM_QUERYENDSESSION messages, so we are really ending.
if (wParam) // if all apps aggreed to end session.
CloseMerc(); // This is the end. We will not get a
// WM_DESTROY message on end session.
break;
case WM_DESTROY:
// This is the end if we were closed by a DestroyWindow call.
CloseMerc();
PostQuitMessage(0);
break;
default:
return(DefWindowProc(hWnd, message, wParam, lParam));
}
return(0L);
}
BOOL CALLBACK _export MercDlgProc(HWND hDlg, UINT message,
WPARAM wParam, LPARAM lParam)
{
static RECT wrect;
int x, y, w, h, i;
long rc;
// char *cp, *cpd, tmp[30], sdrives[30];
// HANDLE hCursor;
HWND hWndInput;
switch (message)
{
case WM_INITDIALOG:
// Save the handle of this proc for use by main window proc.
hQryDlgBox = hDlg;
// Save the handle to the output window
hWndOutput = GetDlgItem(hDlg, 102);
// SendMessage(hWndOutput, WM_SETFONT,
// (WPARAM) GetStockObject(SYSTEM_FIXED_FONT), 0);
SetFocus(GetDlgItem(hDlg, 101));
// Get position of dialog box window.
GetWindowRect(hDlg, (LPRECT) &wrect);
w = wrect.right - wrect.left;
h = wrect.bottom - wrect.top;
// Move main application window to same position.
SetWindowPos(hWndMain, hDlg,
wrect.left, wrect.top, w, h,
0);
// Tell Winsock we are listening for accepted sockets
WSAAsyncSelect(control, hDlg, WM_NET_ACCEPT, FD_ACCEPT);
break;
case WM_MOVE:
// Always keep this dialog box on top of main window.
GetWindowRect(hWndMain, (LPRECT) &wrect);
x = wrect.left;
y = wrect.top;
w = wrect.right - wrect.left;
h = wrect.bottom - wrect.top;
MoveWindow(hDlg, x, y, w, h, 1);
break;
case WM_SYSCOMMAND:
// Pass WM_SYSCOMMAND messages on to main window so both
// main window and dialog box get iconized, minimized etc.
// in parallel.
SendMessage(hWndMain, message, wParam, lParam);
break;
case WM_COMMAND:
switch (LOWORD(wParam))
{
#if 0 // @@@
case IDOK:
hWndInput = GetDlgItem(hDlg, 101);
SendMessage(hWndInput, WM_GETTEXT, sizeof UserMessage, (LPARAM) UserMessage);
SendMessage(hWndInput, WM_SETTEXT, 0, (LPARAM) "");
SetFocus(hWndInput);
fUserReady = TRUE;
break;
#endif
case IDCANCEL: // Cancel button
// Tell main application window we want to quit.
SendMessage(hWndMain, WM_CLOSE, 0, 0L);
break;
default:
break;
}
break;
case WM_CLOSE:
// Unlock dialog resource we locked above.
// Zero handle to this dialog window.
hQryDlgBox = 0;
// Tell main window to close.
PostMessage(hWndMain, WM_CLOSE, 0, 0L);
// Destroy ourseleves.
DestroyWindow(hDlg);
break;
case WM_NET_ACCEPT:
SocketAccept(wParam, lParam);
break;
case WM_NET_READWRITE:
SocketReadWrite(wParam, lParam);
break;
case WM_NET_GETHOST:
SocketGetHost(wParam, lParam);
break;
case WM_NET_AUTHCONNECT:
SocketAuthConnect(wParam, lParam);
break;
default:
return FALSE;
}
return(TRUE);
}
void InitMerc22(HINSTANCE hInstance, int cmdShow)
{
WNDCLASS wcMercClass;
// Define the window class for this application.
wcMercClass.lpszClassName = "Merc22";
wcMercClass.hInstance = hInstance;
wcMercClass.lpfnWndProc = MercWndProc;
wcMercClass.hCursor = LoadCursor(NULL, IDC_ARROW);
?? 快捷鍵說明
復(fù)制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -