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

📄 scs_protocol.c

📁 <B>Digital的Unix操作系统VAX 4.2源码</B>
💻 C
📖 第 1 页 / 共 4 页
字号:
	    Lock_cbvte( cbvte )	    cb = Get_cb( cbvte );	    if( scsbp->rconnid.seq_num != cbvte->connid.seq_num ) {		if( scsbp->mtype == SCS_ACCEPT_REQ  ||		     scsbp->mtype == SCS_REJECT_REQ ||		     scsbp->mtype == SCS_CONN_RSP ) {		    aborted_conn = 1;		} else {		    event_code = SE_BADCONNID;		    Unlock_cbvte( cbvte )		}	    }	}	if( event_code ) {	    pb = ( *pccb->Get_pb )( pccb, scsbp, BUF );	    ( void )( *pccb->Crash_path )( pccb,					   pb,					   event_code,					   RECEIVE_BUF,					   scsbp );	    Unlock_scadb()	    return;	} else {	    pb = cb->pb;	}    }    switch( scsbp->mtype ) {	case SCS_CONN_REQ: {	    register cbq	*lcb;	    if((( pb = ( *pccb->Get_pb )( pccb, scsbp, BUF )) == NULL ||	           pb->pinfo.state != PS_OPEN ) &&		 ( *pccb->Open_path )( pccb, pb, scsbp ) != RET_SUCCESS ) {		( void )( *pccb->Add_msg )( pccb, scsbp );		Unlock_scadb()		return;	    }	    cbvte = NULL;	    Conn_rsp( scsbp )->Req_status = ADR_NOLISTENER;	    for( lcb = scs_listeners.flink;		 lcb != &scs_listeners;		 lcb = lcb->flink ) {		if( Comp_name( Conn_req( scsbp )->rproc_name,			       Lcb->cinfo.lproc_name )) {		    if( Lcb->cinfo.cstate != CS_LISTEN ) {			( void )panic( SCSPANIC_LQUEUE );		    } else if(( cb = scs_alloc_cb( CS_CONN_REC, NULL, pb ))) {			lcbvte = Get_cbvte( Lcb->cinfo.lconnid );			cb->control = Lcb->control;			cb->cinfo.snd_credit = Conn_req( scsbp )->credit;			Move_connid( Conn_req( scsbp )->sconnid,				     cb->cinfo.rconnid )			cb->cinfo.min_rec_credit =				Conn_req( scsbp )->min_credit;			Move_name( Conn_req( scsbp )->rproc_name,				   cb->cinfo.lproc_name )			Move_name( Conn_req( scsbp )->sproc_name,				   cb->cinfo.rproc_name )			Move_data( Conn_req( scsbp )->sproc_data,				   cb->cinfo.rconn_data )			cbvte = Get_cbvte( cb->cinfo.lconnid );			Lock_cbvte( cbvte )			Insert_cb( cb, pb )			Conn_rsp( scsbp )->Req_status = ADR_SUCCESS;			Move_connid( cb->cinfo.lconnid,				     Conn_req( scsbp )->rconnid )			notify_event = CRE_CONN_REC;		    } else {			Conn_rsp( scsbp )->Req_status = ADR_NORESOURCE;		    }		    break;		}	    }	    break;	}	case SCS_CONN_RSP:	    if( aborted_conn || cb->cinfo.status.abort_fork ) {		;	    } else if( cb->cinfo.cstate == CS_CONN_SNT ) {		if( Conn_rsp( scsbp )->Req_status == ADR_SUCCESS ) {		    cb->cinfo.cstate = CS_CONN_ACK;		} else {		    status = Conn_rsp( scsbp )->Req_status;		    cb->errlogopt.rreason = status;		    ( void )scs_log_event( cb, W_TERM_FCONN, CONN_EVENT );		    cb->cinfo.cstate = CS_CLOSED;		    notify_event = CRE_CONN_DONE;		}	    } else {		event_code = SE_BADCSTATE;	    }	    break;	case SCS_ACCEPT_REQ:	    if( aborted_conn || cb->cinfo.status.abort_fork ) {		Accept_rsp( scsbp )->Req_status = ADR_DISCONN;	    } else if( cb->cinfo.cstate == CS_CONN_ACK ) {		Accept_rsp( scsbp )->Req_status = ADR_SUCCESS;		Move_connid( Accept_req( scsbp )->sconnid, cb->cinfo.rconnid )		cb->cinfo.snd_credit = Accept_req( scsbp )->credit;		cb->cinfo.min_rec_credit = Accept_req( scsbp )->min_credit;		Move_data( Accept_req( scsbp )->sproc_data,			   cb->cinfo.rconn_data )		( void )scs_log_event( cb, I_NEW_CONN, CONN_EVENT );		cb->cinfo.cstate = CS_OPEN;		notify_event = CRE_CONN_DONE;		semaphore = 1;	    } else {		event_code = SE_BADCSTATE;	    }	    break;	case SCS_ACCEPT_RSP:	    if( cb->cinfo.cstate == CS_ACCEPT_SNT ) {		notify_event = CRE_ACCEPT_DONE;		if( Accept_rsp( scsbp )->Req_status == ADR_SUCCESS ) {		    ( void )scs_log_event( cb, I_NEW_CONN, CONN_EVENT );		    cb->cinfo.cstate = CS_OPEN;		    semaphore = 1;		} else {		    status = Accept_rsp( scsbp )->Req_status;		    cb->errlogopt.rreason = status;		    ( void )scs_log_event( cb, W_TERM_FCONN, CONN_EVENT );		    cb->cinfo.cstate = CS_CLOSED;		}	    } else {		event_code = SE_BADCSTATE;	    }	    break;	case SCS_REJECT_REQ:	    if( aborted_conn || cb->cinfo.status.abort_fork ) {		;	    } else if( cb->cinfo.cstate == CS_CONN_ACK ) {		status = Reject_req( scsbp )->reason;		cb->errlogopt.rreason = status;		( void )scs_log_event( cb, W_REJECT_FCONN, CONN_EVENT );		cb->cinfo.cstate = CS_CLOSED;		notify_event = CRE_CONN_DONE;	    } else {		event_code = SE_BADCSTATE;	    }	    break;	case SCS_REJECT_RSP:	    if( cb->cinfo.cstate == CS_REJECT_SNT ) {		cb->cinfo.cstate = CS_CLOSED;		if( !cb->cinfo.status.disconnect ) {		    notify_event = CRE_REJECT_DONE;		} else {		    notify_event = CRE_DISCONN_DONE;		}	    cb->errlogopt.rreason = cb->cinfo.reason;	    ( void )scs_log_event( cb, W_REJECT_FCONN, CONN_EVENT );	    } else {		event_code = SE_BADCSTATE;	    }	    break;	case SCS_DISCONN_REQ:	    while( Test_cbvte_sem( cbvte )) {		Unlock_cbvte( cbvte )		Unlock_scadb()		Lock_scadb()		Lock_cbvte( cbvte )		if( scsbp->sconnid.seq_num != cbvte->connid.seq_num ||		     cb->cinfo.cstate == CS_PATH_FAILURE ) {		    ( void )( *pccb->Add_msg )( pccb, scsbp );		    Unlock_cbvte( cbvte )		    Unlock_scadb()		    return;		}	    }	    if ( cb->cinfo.cstate == CS_OPEN ) {		cb->cinfo.cstate = CS_DISCONN_REC;		Remove_pb_waitq( cb )		notify_event = CRE_DISCONN_REC;		status = Disconn_req( scsbp )->reason;		semaphore = 1;	    } else if( cb->cinfo.cstate == CS_DISCONN_SNT ) {		cb->cinfo.cstate = CS_DISCONN_MTCH;	    } else if( cb->cinfo.cstate == CS_DISCONN_ACK ) {		( void )scs_log_event( cb, W_TERM_CONN, CONN_EVENT );		cb->cinfo.cstate = CS_CLOSED;		notify_event = CRE_DISCONN_DONE;	    } else {		event_code = SE_BADCSTATE;	    }	    break;	case SCS_DISCONN_RSP:	    if( cb->cinfo.cstate == CS_DISCONN_SNT ) {		cb->cinfo.cstate = CS_DISCONN_ACK;	    } else if( cb->cinfo.cstate == CS_DISCONN_MTCH ) {		( void )scs_log_event( cb, W_TERM_CONN, CONN_EVENT );		cb->cinfo.cstate = CS_CLOSED;		notify_event = CRE_DISCONN_DONE;	    } else {		event_code = SE_BADCSTATE;	    }	    break;	case SCS_CREDIT_REQ: {	    register long	credits;	    /* Only credit requests for open connections are processed.  Credit	     * requests for connections in the DISCONN_SNT connection state(	     * the local SYSAP has requested connection termination but the	     * request has not yet been acknowledged by the remote SCS ) are	     * not processed and the path is crashed if the connection is	     * found to be in any other state.	     */	    if( cb->cinfo.cstate == CS_OPEN ) {		if(( credits = scsbp->credit ) > 0 ) {		    cb->cinfo.snd_credit += credits;		    if( cb->cinfo.status.cwait ) {			cb->cinfo.status.cwait = 0;			notify_event = CRE_CREDIT_AVAIL;			semaphore = 1;		    }		} else if( credits < 0 ) {		    if(( credits = cb->cinfo.snd_credit -				   cb->cinfo.min_snd_credit ) <= 0 ) {			scsbp->credit = 0;		    } else {			if( credits < -scsbp->credit ) {			    scsbp->credit = -credits;			cb->cinfo.snd_credit += scsbp->credit;			}		    }		}	    } else {		if( cb->cinfo.cstate != CS_DISCONN_SNT ) {		    event_code = SE_BADCSTATE;		}	    }	    break;	}	case SCS_CREDIT_RSP:	    if( cb->cinfo.cstate != CS_OPEN	    &&		 cb->cinfo.cstate != CS_DISCONN_SNT &&		 cb->cinfo.cstate != CS_DISCONN_REC &&		 cb->cinfo.cstate != CS_DISCONN_MTCH ) {		event_code = SE_BADCSTATE;	    } else if( scsbp->credit < 0 ) {		event_code = SE_NEGCREDITS;	    }	    break;	default:	    event_code = SE_BADSCSMTYPE;    }    {    register void	( *control )();    if( notify_event ) {	( void )scs_init_cmsb( notify_event, status, &cmsb, cb, pb, 0 );	control = cb->control;	if( cb->cinfo.cstate == CS_CLOSED ) {	    Remove_cb( cb, pb )	} else if( semaphore ) {	    Incr_cbvte_sem( cbvte )	} else if( lcbvte ) {	    Lock_cbvte( lcbvte )	    Incr_cbvte_sem( lcbvte )	    Unlock_cbvte( lcbvte )	}    }    if( cbvte ) {	Unlock_cbvte( cbvte )    }    if( event_code == 0 ) {	if(!( scsbp->mtype & 1 )) {	    ( void )scs_response( scsbp, pb );	} else {	    Lock_pb( pb )	    if( pb->pinfo.status.sanity ) {		Remove_scs_timeoutq( pb )	    } else if( pb->pinfo.state != PS_PATH_FAILURE ) {		( void )panic( SCSPANIC_SANITY );	    }	    Unlock_pb( pb )	    ( void )scs_request( 0, NULL, pb, scsbp );	}    } else {	( void )( *cb->Crash_path )( pccb, pb, event_code, RECEIVE_BUF, scsbp);    }    Unlock_scadb()    if( notify_event ) {	( void )( *control )( notify_event, &cmsb );	if( semaphore ) {	    Decr_cbvte_sem( cbvte )	} else if( lcbvte ) {	    Decr_cbvte_sem( lcbvte )	}    }    }}/*   Name:	scs_request	- Send SCS Sequenced Message Request * *   Abstract:	This routine initiates the transmission of a SCS request over *		a specific path.  Five such requests are supported: * *		1. Request establishment of a logical SCS connection. *		2. Request acceptance of a logical SCS connection. *		3. Request rejection of a logical SCS connection. *		4. Request termination of a logical SCS connection. *		5. Request extension of send credits across a logical SCS *		   connection. * *		SCS applies flow control to its own communications on a per *		path basis.  Only one SCS request may be transmitted across *		each path at a given moment.  The transmission of all *		subsequent requests is postponed until a response to the active *		request is received. * *		Flow control is provided by allocating for each path a single *		message buffer.  These buffers are attached to their PBs as SCS *		send message buffers when not in use.  A SCS request is *		immediately transmitted only when the SCS send message buffer *		for the path is available.  Otherwise, transmission of the *		request is postponed by queuing the CB on whose behalf the *		request was made to the appropriate PB until the SCS send *		message buffer is again available. * *		Message buffers containing SCS requests are always added to the *		appropriate ports' free message pools following their *		transmissions.  There they serve as receive message buffers for *		their corresponding SCS responses.  After receiving and *		processing a SCS response its message buffer is used to *		transmit the next SCS request pending on the appropriate *		path.  The message buffer is attached to the PB as its SCS send *		message buffer if there are no such requests pending. * *		A sanity timer is set on the target path prior to transmission *		of a SCS request.  SCS assumes the path has failed and *		explicitly crash it if this timer expires before the SCS *		response to the current SCS request is received. * *		There are two ways in which this routine may be invoked. * *		1. The routine may be invoked to process a specific SCS request *		   on behalf of an explicitly provided connection.  Such *		   invocations never supply the message buffer to contain the *		   request( scsbp == NULL ). * *		2. The routine may be invoked to resume processing of the next *		   SCS request pending transmission on the path.  Such *		   invocations never supply the connection on whose behalf the *		   transmission is to be made( cb == NULL ) or the explicit *		   request type( request == CB_NOT_WAIT ) but always supply the *		   message buffer to contain the request. * *   Inputs: * *   IPL_SCS			- Interrupt processor level *   cb				- Connection Block pointer *   request			- Request type *   pb				- Path Block pointer *   scsbp			- Address of SCS header of message buffer *   scs_sanity			- SCS sanity timer interval *   scs_timeoutq		- SCS protocol sequence timeout queue head * *   Outputs: * *   IPL_SCS			- Interrupt processor level *   cb				- Connection Block pointer *	cinfo.cbstate		-  CB state *	cinfo.pend_rec_credit	-  Number of credits pending extension *	cinfo.reason		-  Rejection/Disconnection reason *	cinfo.rec_credit	-  Send credit held by remote SYSAP *   pb				- Path Block pointer *	pinfo.duetime		-  SCS response due time( seconds ) *	pinfo.status.sanity	-  1 *	scs_msgbuf		-  Address of SCS send message buffer *	timeout			-  SCS protocol sequence timeout queue pointers * *   SMP:	The SCA database is locked( EXTERNALLY ) to guarantee the *		validity of PB addresses and to allow for PB insertion onto the

⌨️ 快捷键说明

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