📄 osport.c
字号:
/*
* FILENAME: osport.c
*
* Copyright 1999- 2000 By InterNiche Technologies Inc. All rights reserved
*
*
* MODULE: WIN32
*
* ROUTINES: WIN32MAIN(), dputchar(), LOCK_NET_RESOURCE(),
* ROUTINES: UNLOCK_NET_RESOURCE(), tcp_sleep(), usage(), post_net_setup(),
* ROUTINES: TK_NEWTASK(), blocklist(), npalloc(), npfree(), MEMCPY(),
* ROUTINES: MEMSET(), MEMMOVE(), lswap(), wintime_proc(), clock_init(),
* ROUTINES: clock_c(), TK_NETRX_BLOCK(), w32_tk_return(), clock_init(),
* ROUTINES: clock_c(), get_ptick(), tk_yield(), *
* PORTABLE: no
*/
/* osport.c
*/
#pragma warning(disable: 4244 4310 4115)
#define _WINSOCKAPI_ 1
#include <windows.h>
#include "ipport.h"
#include "osport.h"
#include "winbase.h"
#ifdef USE_PPP
#include "ppp_port.h"
#include "comline.h"
#include "../mppp/mppp.h"
extern int ppp_default_type; /* in ppp code */
extern int ppp_static; /* number static PPP ifaces to set */
#endif /* USE_PPP */
DWORD dwVersion;
DWORD dwWindowsMajorVersion;
#define TASK_STACK 7500 /* changeable accroding to your environment */
extern int netmain(void);
extern unsigned bigbufsiz, bigbufs, lilbufsiz, lilbufs;
extern char * name;
extern int (*port_prep)(int); /* hook in ..\inet\ipnet.c */
extern int prep_win32(int ifaces_found);
extern int wd_prep(int); /* port iface prep routine to install */
extern int prep_ppp(int); /* port iface prep routine to install */
extern void netmain_init(void); /* initialize all modules */
int (*ppp_type_callback)(LINEP);
int ppp_type_setup(LINEP);
void usage(void);
u_long cticks = 0; /* need to increment this later - 18 TPS? */
/* Semaphores for LOCK/UNLOCK net resource */
CRITICAL_SECTION WIN_RESID; /* Lock for this win32 thread */
#ifdef INICHE_TASKS
static int net_task_sem = 0; /* stack semaphore */
static int rcvq_sem = 0; /* receiveq semaphore */
static int freeq_sem = 0; /* free q semaphore */
static task * tk_blocked[10]; /* Tasks blocked. Assumes max is 10 */
#else
extern void packet_chk(void);
extern int prep_modules(void);
#endif
/* When WIN32 build is used for the browser, then the WinMain()
* would be present in the graphics libarary (MFC/PEG). Hence we need
* to rename our main entry point. In such a case, a LIB (win32.lib)
* would be made from this directory, instead of an EXE (webport.exe).
* - When webport.exe is to be made, code in this directory is compiled
* via "makefile". The ipport.h_h file (and other h_h files from this
* directory are used.
* - When win32.lib is to be made, code in this directory is compiled
* via win32lib.mak, and TARGETLIB is defined in ipport.h. The ipport.h_h
* file in this directory is NOT used.
*/
#ifdef TARGETLIB
#define WIN32MAIN targmain
#else
#define WIN32MAIN main
#endif
/* scaling value to run cticks on Win2000 or Win98 */
static int os_scale;
/* FUNCTION: WIN32MAIN()
*
* PARAM1: int argc
* PARAM2: char * argv[]
*
* RETURNS:
*/
int
WIN32MAIN(int argc, char * argv[])
{
int argx;
char * cp;
/* Set windows version in global dwVersion */
dwVersion = GetVersion();
dwWindowsMajorVersion = (DWORD)(LOBYTE(LOWORD(dwVersion)));
if (!(dwVersion >= 0x80000000 && dwWindowsMajorVersion >= 4))
{
os_scale = 4; /* Windows NT/2000 Version */
}
else /* windows 98/ME */
{
os_scale = 1; /* Windows 98-ish version */
}
/* preset buffer counts; may overwrite from command line */
bigbufs = 50;
lilbufs = 50;
bigbufsiz = 1536;
lilbufsiz = 128;
argx = 0;
while (++argx < argc)
{
if (*argv[argx] != '-')
{
Printu_Net("options must start with '-'\n");
usage();
}
cp = argv[argx] + 1;
switch (*cp)
{
case 'l': /* large packet buffers */
cp++;
bigbufs = atoi(cp);
if (bigbufs < 3 || bigbufs > MAXBIGPKTS)
{
printf("%s: '-l' option should be 1 - %u\n",
name, MAXBIGPKTS);
exit(1);
}
break;
case 's': /* small packet buffers */
cp++;
lilbufs = atoi(cp);
if (lilbufs < 3 || lilbufs > MAXLILPKTS)
{
Printu_Net("%s: '-s' option should be 1 - %u\n",
name, MAXLILPKTS);
exit(1);
}
break;
default:
Printu_Net("station: invalid cmd line option %s;\n", cp);
usage();
}
}
#ifdef WIN2K
/* install win32 port prep routine in .\targport.c */
port_prep = prep_win32;
#endif
#ifdef SUPERLOOP
prep_modules();
#endif /* SUPERLOOP */
#ifdef USE_PPP
#ifdef MINI_IP
/* If we are using the mini IP layer and PPP, then overwrite the
* NDIS hook with the PPP prep routine
*/
port_prep = prep_ppp;
#endif /* MINI_IP */
/* for all PPP inplementations, set a callback so the we can
* set the device type of new PPP links
*/
ppp_default_type = LN_PORTSET;
ppp_type_callback = ppp_type_setup;
/* Set the number of static PPP ifaces. Allow one each for modem and
* PPPOE, and two for Loopback-crossover.
*/
ppp_static = 1; /* base for modem or UART direct connect */
#ifdef LB_XOVER
ppp_static += 2;
#endif
#ifdef NOTDEF
/* This little block of code is usefully for testing PPPoE in loopback
* on windows (e.g. bouncing the packets off the NDIS driver) but for
* most purposes should not be used.
*/
#ifdef USE_PPPOE
#ifdef PPPOE_LBTEST
ppp_static += 2; /* loopback test needs 2 interfaces */
#else
ppp_static++;
#endif /* PPPOE_LBTEST */
#endif /* USE_PPPOE */
#endif /* NOTDEF */
#endif /* USE_PPP */
InitializeCriticalSection(&WIN_RESID);
#ifdef INICHE_TASKS
{ /* parenthesis put so that "i" can be defined here */
int i;
for (i = 0; i < 10; i++)
tk_blocked[i] = 0;
return netmain();
}
#else
netmain_init();
#ifndef TARGETLIB
/* for TARGETLIB, tk_yield() is called based on a timer. Hence
* don't run it in infinite loop over here.
*/
while (1) /* loop, each module getting cycles in a round-robin fashion */
{
tk_yield();
}
#endif
return 0;
#endif
}
#ifdef USE_PPP
/* FUNCTION: ppp_type_setup(M_PPP)
*
* This per port routine is called via ppp_type_callback whenver
* ppp sets up a new PPP link. It should set the PPP line type
* (line->lower_type) based on local port configuration info
* (either hardcoded or read from FLASH). Possible options include:
*
* LN_ATMODEM - Hayes compatible dialup modem.
* LN_PPPOE - PPP over ethernet (also needs some ethernet setup)
* LN_LBXOVER - Loopback/crossover links for testing
* LN_UART - direct connect via RS-232 (or similar) UART.
*
* The MPPP passed already has the ifp attached and configured
* from NVparms, so you can use if name and IP addressing info to
* select the types. If you need to set up other PPP mappings (like
* selecting a modem, uart, or ethernet device) this is a good place
* to do it.
*
* returns 0 if OK or ENP error code
*/
/* Table to allocate PPPs in the following order:
*
* #ifdef LB_XOVER, assign first two to LB_XOVER client & server
* #ifdef USE_COMPORT, assign 1 to modem
* #ifdef USE_PPPOE, assign 1 (or two if loopback) which will map to NDIS ethernet.
*/
static int ppps_already = 0;
static int ppp_types[] =
{
#ifdef LB_XOVER
LN_LBXOVER, LN_LBXOVER,
#endif
#ifdef USE_COMPORT
LN_ATMODEM,
#endif
#ifdef USE_PPPOE
LN_PPPOE,
#ifdef PPPOE_LBTEST
LN_PPPOE, /* PPPOE loopback test needs second interface */
#endif /* PPPOE_LBTEST */
#endif USE_PPPOE
/* extra entry are LB_XOVER for testing */
#ifdef LB_XOVER
LN_LBXOVER, LN_LBXOVER,
LN_LBXOVER, LN_LBXOVER,
#endif
};
extern int ifmap_bind(NET upper, NET lower);
int
ppp_type_setup(LINEP line)
{
int err = 0;
/* make sure we're not off the end of the static table */
if(ppps_already > (sizeof(ppp_types)/sizeof(int)) )
{
/* If table is fully assigned, the set a default */
#ifdef USE_PPPOE
line->lower_type = LN_PPPOE;
#else
line->lower_type = LN_ATMODEM;
#endif
dprintf("ppp_type_setup (win32) defaulting type to %d\n", line->lower_type);
}
line->lower_type = ppp_types[ppps_already++]; /* assign next type */
/* If it's PPPoE we need to assign it to an ethernet interface too */
#ifdef USE_PPPOE
if(ppp_types[ppps_already - 1] == LN_PPPOE)
{
NET ifp;
/* find first ethernet interface */
for(ifp = (NET)netlist.q_head; ifp; ifp = ifp->n_next)
{
if(ifp->mib.ifType == ETHERNET)
{
M_PPP mppp;
/* bind PPP iface for this line (upper) to ethernet (lower) */
mppp = (M_PPP)(line->upper_unit);
ifmap_bind(mppp->ifp, ifp);
#ifdef PPPOE_LBTEST
/* for PPPOE loopback it helps to add routes */
#endif /* PPPOE_LBTEST */
break;
}
}
/* If no ethernet was found then set error code */
if(!ifp)
err = ENP_LOGIC;
}
#endif /* USE_PPPOE */
return err; /* OK return */
}
#endif /* USE_PPP */
/* dputchar() - this is the port-dependant portion of the
* redirectable output package (ttyio.c). dstdio is NULL for the
* screen/keyboard, or a pointer to an output device, such as a file
* or socket. This sends each char to dstdio device.
*/
extern void * dstdio;
extern void putch(int);
/* FUNCTION: dputchar()
*
* PARAM1: int chr
*
* RETURNS:
*/
void
dputchar(int chr) /* put character to DOS console device */
{
putch(chr);
}
/* FUNCTION: usage()
*
* PARAM1:
*
* RETURNS:
*/
void
usage()
{
Printu_Net("usage: %s [-sX -lX] \n", name);
Printu_Net(" -s sets the number of small packet buffers.\n");
Printu_Net(" -l sets the number of large packet buffers.\n");
exit(1);
}
#ifdef INICHE_TASKS
/* FUNCTION: tcp_sleep()
*
* PARAM1: void * event
*
* RETURNS:
*/
void
tcp_sleep(void * event)
{
UNLOCK_NET_RESOURCE(NET_RESID);
tk_ev_block(event);
LOCK_NET_RESOURCE(NET_RESID);
}
/* post_net_setup() - no-op on this port */
/* FUNCTION: post_net_setup()
*
* PARAM1: void
*
* RETURNS:
*/
char *
post_net_setup(void)
{
return NULL;
}
/* FUNCTION: LOCK_NET_RESOURCE()
*
* PARAM1: int resid
*
* RETURNS: void
*
* This uses a Windows EnterCriticalSection call to protect the code.
* It then increments a semaphore per resource as a way to lock the
* resource. In the case of NET_RESID only it blocks the calling
* task and wakes it up in the UNLOCK_NET_RESOURCE call
*/
void
LOCK_NET_RESOURCE(int resid)
{
int i;
EnterCriticalSection((LPCRITICAL_SECTION)&WIN_RESID);
switch (resid)
{
case NET_RESID:
/* block this task and wake it when the UNLOCK happens */
while (net_task_sem)
{
/* If the task is already blocked, exit the for loop */
for (i=0; i < 10; i++)
{
if (tk_blocked[i] == 0)
{
tk_blocked[i] = tk_cur;
break;
}
else
if (strcmp(tk_blocked[i]->tk_name, tk_cur->tk_name) == 0)
break;
}
if (i == 10)
panic("lock NetResid\n");
tk_block();
}
net_task_sem++; /* lock the resource */
break;
case RXQ_RESID:
if (rcvq_sem)
panic("lock ReceiveQ\n");
rcvq_sem++; /* lock the resource */
break;
case FREEQ_RESID:
if (freeq_sem)
panic("lock FreeQ\n");
freeq_sem++; /* lock the resource */
break;
}
LeaveCriticalSection((LPCRITICAL_SECTION)&WIN_RESID);
}
/* FUNCTION: UNLOCK_NET_RESOURCE()
*
* PARAM1: int resid
*
* RETURNS: void
*
* This call unlocks the respective semaphores by decrementing a global flag.
* This also protects the code by using the Windows Critical Section macros.
* In the case of NET_RESID only it wakes any blocked tasks.
*/
void
UNLOCK_NET_RESOURCE(int resid)
{
int i; task * tmp_task_ptr;
EnterCriticalSection((LPCRITICAL_SECTION)&WIN_RESID);
switch (resid)
{
case NET_RESID:
net_task_sem--; /* unlock the resource */
for (i = 0; i < 10; i++)
{
if (tk_blocked[i] != 0)
{
tmp_task_ptr = tk_blocked[i];
tk_blocked[i] = 0;
tk_wake(tmp_task_ptr);
break;
}
}
break;
case RXQ_RESID:
if (!rcvq_sem)
panic("lock ReceiveQ\n");
rcvq_sem--; /* unlock the resource */
break;
case FREEQ_RESID:
if (!freeq_sem)
panic("lock FreeQ\n");
freeq_sem--; /* unlock the resource */
break;
}
LeaveCriticalSection((LPCRITICAL_SECTION)&WIN_RESID);
}
/* FUNCTION: TK_NEWTASK()
*
* PARAM1: struct inet_taskinfo * nettask
*
* RETURNS:
*/
int
TK_NEWTASK(struct inet_taskinfo * nettask)
{
task * new_task;
if (nettask == &nettasks[0]) /* should be at head of list */
{
if (*(nettask->name) != 'I') /* double check */
panic("nettask");
new_task = tk_init( tk_getsp() - (TASK_STACK/sizeof(stack_t)), TASK_STACK);
/* Some configurations need the clock running upon return from this
* first call, so start it now rather than waiting for the callback
* to clock_init() from the IP startup code.
*/
clock_init();
}
else
{
new_task = tk_new(tk_cur, nettask->entry,
nettask->stacksize, nettask->name, 0);
}
if (new_task)
{
*nettask->tk_ptr = new_task;
return 0;
}
else
{
return 0;
}
}
#endif /* INICHE_TASKS */
/* **** InterNiche memory managment debug hooks **** */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -