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

📄 netfsm.c

📁 基于东南大学开发的SEP3203的ARM7中的所有驱动
💻 C
📖 第 1 页 / 共 2 页
字号:
/*****************************************************************************

* netfsm.c - Network Control Protocol Finite State Machine program file.

*

* portions Copyright (c) 1997 by Global Election Systems Inc.

*

* The authors hereby grant permission to use, copy, modify, distribute,

* and license this software and its documentation for any purpose, provided

* that existing copyright notices are retained in all copies and that this

* notice and the following disclaimer are included verbatim in any 

* distributions. No written agreement, license, or royalty fee is required

* for any of the authorized uses.

*

* THIS SOFTWARE IS PROVIDED BY THE CONTRIBUTORS *AS IS* AND ANY EXPRESS OR

* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES

* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 

* IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,

* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT

* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,

* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY

* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT

* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF

* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

*

******************************************************************************

* REVISION HISTORY

*

* 97-12-01 Guy Lancaster <lancasterg@acm.org>, Global Election Systems Inc.

*	Original based on BSD fsm.c.

*****************************************************************************/

/*

 * fsm.c - {Link, IP} Control Protocol Finite State Machine.

 *

 * Copyright (c) 1989 Carnegie Mellon University.

 * All rights reserved.

 *

 * Redistribution and use in source and binary forms are permitted

 * provided that the above copyright notice and this paragraph are

 * duplicated in all such forms and that any documentation,

 * advertising materials, and other materials related to such

 * distribution and use acknowledge that the software was developed

 * by Carnegie Mellon University.  The name of the

 * University may not be used to endorse or promote products derived

 * from this software without specific prior written permission.

 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR

 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED

 * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.

 */





/*

 * TODO:

 * Randomize fsm id on link/init.

 * Deal with variable outgoing MTU.

 */



#include "netconf.h"

#include <string.h>

#include "net.h"

#include "nettimer.h"

#include "netbuf.h"

#include "netppp.h"

#include "netfsm.h"



#include <stdio.h>

#include "netdebug.h"





/*************************/

/*** LOCAL DEFINITIONS ***/

/*************************/





/************************/

/*** LOCAL DATA TYPES ***/

/************************/





/***********************************/

/*** LOCAL FUNCTION DECLARATIONS ***/

/***********************************/

static void fsm_timeout __P((void *));

static void fsm_rconfreq __P((fsm *, u_char, u_char *, int));

static void fsm_rconfack __P((fsm *, int, u_char *, int));

static void fsm_rconfnakrej __P((fsm *, int, int, u_char *, int));

static void fsm_rtermreq __P((fsm *, int, u_char *, int));

static void fsm_rtermack __P((fsm *));

static void fsm_rcoderej __P((fsm *, u_char *, int));

static void fsm_sconfreq __P((fsm *, int));



#define PROTO_NAME(f)	((f)->callbacks->proto_name)





/******************************/

/*** PUBLIC DATA STRUCTURES ***/

/******************************/





/*****************************/

/*** LOCAL DATA STRUCTURES ***/

/*****************************/

int peer_mru[NUM_PPP];





/***********************************/

/*** PUBLIC FUNCTION DEFINITIONS ***/

/***********************************/



/*

 * fsm_init - Initialize fsm.

 *

 * Initialize fsm state.

 */

void fsm_init(fsm *f)

{

	f->state = INITIAL;

	f->flags = 0;

	f->id = 0;				/* XXX Start with random id? */

	f->timeouttime = DEFTIMEOUT;

	f->maxconfreqtransmits = DEFMAXCONFREQS;

	f->maxtermtransmits = DEFMAXTERMREQS;

	f->maxnakloops = DEFMAXNAKLOOPS;

	f->term_reason_len = 0;

}





/*

 * fsm_lowerup - The lower layer is up.

 */

void fsm_lowerup(fsm *f)

{

	int oldState = f->state;



	switch(oldState){                                       /***********修改osdState 取代 f->state******/

	case INITIAL:

		f->state = CLOSED;

		break;

	

	case STARTING:

		if( f->flags & OPT_SILENT )

			f->state = STOPPED;

		else {

			/* Send an initial configure-request */

			fsm_sconfreq(f, 0);

			f->state = REQSENT;

		}

	break;

	

	default:

		FSMDEBUG((LOG_INFO, "%s: Up event in state %d!",

				PROTO_NAME(f), f->state));

	}

	

	FSMDEBUG((LOG_INFO, "%s: lowerup state %d -> %d",

			PROTO_NAME(f), oldState, f->state));

}





/*

 * fsm_lowerdown - The lower layer is down.

 *

 * Cancel all timeouts and inform upper layers.

 */

void fsm_lowerdown(fsm *f)

{

	int oldState = f->state;

	

	switch( oldState ){                                    /***********修改osdState 取代 f->state******/

	case CLOSED:

		f->state = INITIAL;

		break;

	

	case STOPPED:

		f->state = STARTING;

		if( f->callbacks->starting )

			(*f->callbacks->starting)(f);

		break;

	

	case CLOSING:

		f->state = INITIAL;

		UNTIMEOUT(fsm_timeout, f);	/* Cancel timeout */

		break;

	

	case STOPPING:

	case REQSENT:

	case ACKRCVD:

	case ACKSENT:

		f->state = STARTING;

		UNTIMEOUT(fsm_timeout, f);	/* Cancel timeout */

		break;

	

	case OPENED:

		if( f->callbacks->down )

			(*f->callbacks->down)(f);

		f->state = STARTING;

		break;

	

	default:

		FSMDEBUG((LOG_INFO, "%s: Down event in state %d!",

				PROTO_NAME(f), f->state));

	}

	

	FSMDEBUG((LOG_INFO, "%s: lowerdown state %d -> %d",

			PROTO_NAME(f), oldState, f->state));

}





/*

 * fsm_open - Link is allowed to come up.

 */

void fsm_open(fsm *f)

{

	int oldState = f->state;



	switch( oldState ){                                         /***********修改osdState 取代 f->state******/

		case INITIAL:

			f->state = STARTING;

			if( f->callbacks->starting )

				(*f->callbacks->starting)(f);

			break;

		

		case CLOSED:

		if( f->flags & OPT_SILENT )

			f->state = STOPPED;

		else {

			/* Send an initial configure-request */

			fsm_sconfreq(f, 0);

			f->state = REQSENT;

		}

		break;

	

	case CLOSING:

		f->state = STOPPING;

		/* fall through */

	case STOPPED:

	case OPENED:

		if( f->flags & OPT_RESTART ){

			fsm_lowerdown(f);

			fsm_lowerup(f);

		}

		break;

	}

	

	FSMDEBUG((LOG_INFO, "%s: open state %d -> %d",

			PROTO_NAME(f), oldState, f->state));

}



/*************************************************************************************************/

/*

 * fsm_close - Start closing connection.

 *

 * Cancel timeouts and either initiate close or possibly go directly to

 * the CLOSED state.

 */

void fsm_close(fsm *f, char *reason)

{

	int oldState = f->state;

	

	f->term_reason = reason;

	f->term_reason_len = (reason == NULL? 0: strlen(reason));

	switch( oldState ){                                          /***********修改osdState 取代 f->state******/

	case STARTING:

		f->state = INITIAL;

		break;

	case STOPPED:

		f->state = CLOSED;

		break;

	case STOPPING:

		f->state = CLOSING;

		break;

	

	case REQSENT:

	case ACKRCVD:

	case ACKSENT:

	case OPENED:

		if( f->state != OPENED )

			UNTIMEOUT(fsm_timeout, f);	/* Cancel timeout */

		else if( f->callbacks->down )

			(*f->callbacks->down)(f);	/* Inform upper layers we're down */

		

		/* Init restart counter, send Terminate-Request */

		f->retransmits = f->maxtermtransmits;

		fsm_sdata(f, TERMREQ, f->reqid = ++f->id, (u_char *) f->term_reason, f->term_reason_len);

		TIMEOUT(fsm_timeout, f, f->timeouttime);

		--f->retransmits;

		

		f->state = CLOSING;

		break;

	}

	

	FSMDEBUG((LOG_INFO, "%s: close reason=%s state %d -> %d",
			PROTO_NAME(f), reason, oldState, f->state));

}



/**********************************************************************************************************/

/*

 * fsm_sdata - Send some data.

 *

 * Used for all packets sent to our peer by this module.

 */

void fsm_sdata(

	fsm *f,

	u_char code, 

	u_char id,

	u_char *data,

	int datalen

)

{

	u_char *outp;

	int outlen;

	

	/* Adjust length to be smaller than MTU */

	outp = outpacket_buf[f->unit];

	if (datalen > peer_mru[f->unit] - (int)HEADERLEN)

		datalen = peer_mru[f->unit] - HEADERLEN;

	if (datalen && data != outp + PPP_HDRLEN + HEADERLEN)

		BCOPY(data, outp + PPP_HDRLEN + HEADERLEN, datalen);

	outlen = datalen + HEADERLEN;

	MAKEHEADER(outp, f->protocol);

	PUTCHAR(code, outp);

	PUTCHAR(id, outp);

	PUTSHORT(outlen, outp);

	

	pppWrite(f->unit, outpacket_buf[f->unit], outlen + PPP_HDRLEN);

	FSMDEBUG((LOG_INFO, "fsm_sdata(%s): Sent code %d,%d,%d:%.40Z.",
				PROTO_NAME(f), code, id, outlen, 
				&outpacket_buf[f->unit][PPP_HDRLEN + HEADERLEN]));

}





/*

 * fsm_input - Input packet.

 */

void fsm_input(fsm *f, u_char *inpacket, int l)

{

	u_char *inp = inpacket;

	u_char code, id;

	int len;

	

	/*

	* Parse header (code, id and length).

	* If packet too short, drop it.

	*/

	if (l < HEADERLEN) {

		FSMDEBUG((LOG_WARNING, "fsm_input(%x): Rcvd short header.",
					f->protocol));

		return;

	}

	GETCHAR(code, inp);

	GETCHAR(id, inp);

	GETSHORT(len, inp);

	if (len < HEADERLEN) {

		FSMDEBUG((LOG_INFO, "fsm_input(%x): Rcvd illegal length.",
				f->protocol));

		return;

	}

	if (len > l) {

		FSMDEBUG((LOG_INFO, "fsm_input(%x): Rcvd short packet.",
				f->protocol));

		return;

	}

	len -= HEADERLEN;		/* subtract header length */

	

	if( f->state == INITIAL || f->state == STARTING ){

		FSMDEBUG((LOG_INFO, "fsm_input(%x): Rcvd packet in state %d.",
				f->protocol, f->state));

		return;

	}

	

	FSMDEBUG((LOG_INFO, "fsm_input(%s):%d,%d,%d:%.40Z",
				PROTO_NAME(f), code, id, l, inp));

	/*

	 * Action depends on code.

	 */

	

	switch (code) {

	case CONFREQ:

		fsm_rconfreq(f, id, inp, len);

		break;

	

	case CONFACK:

		fsm_rconfack(f, id, inp, len);

		break;

	

	case CONFNAK:

	case CONFREJ:

		fsm_rconfnakrej(f, code, id, inp, len);

		break;

	

	case TERMREQ:

		fsm_rtermreq(f, id, inp, len);

		break;

	

	case TERMACK:

		fsm_rtermack(f);

		break;

	

	case CODEREJ:

		fsm_rcoderej(f, inp, len);

		break;

	

	default:

		if( !f->callbacks->extcode

				|| !(*f->callbacks->extcode)(f, code, id, inp, len) )

			fsm_sdata(f, CODEREJ, ++f->id, inpacket, len + HEADERLEN);

		break;

	}

}





/*

 * fsm_protreject - Peer doesn't speak this protocol.

 *

 * Treat this as a catastrophic error (RXJ-).

 */

void fsm_protreject(fsm *f)

{

	switch( f->state ){

	case CLOSING:

		UNTIMEOUT(fsm_timeout, f);	/* Cancel timeout */

		/* fall through */

	case CLOSED:

		f->state = CLOSED;

		if( f->callbacks->finished )

			(*f->callbacks->finished)(f);

		break;

	

	case STOPPING:

	case REQSENT:

	case ACKRCVD:

⌨️ 快捷键说明

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