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

📄 protocol.c

📁 开源备份软件源码 AMANDA, the Advanced Maryland Automatic Network Disk Archiver, is a backup system that a
💻 C
📖 第 1 页 / 共 2 页
字号:
	/*	 * Request is still waiting for more data off of the network.	 * Setup to receive another pkt, and wait for the recv event	 * to occur.	 */	case PA_CONTPEND:	    (*p->continuation)(p->datap, pkt, p->security_handle);	    /* FALLTHROUGH */	case PA_PENDING:	    proto_debug(1, _("protocol: state_machine: p %p state %s: timeout %d\n"),			    p, pstate2str(p->state), (int)p->timeout);	    /*	     * Get the security layer to register a receive event for this	     * security handle on our behalf.  Have it timeout in p->timeout	     * seconds.	     */	    security_recvpkt(p->security_handle, recvpkt_callback, p,		(int)p->timeout);	    return;	/*	 * Request has moved to another state.  Loop and run it again.	 */	case PA_CONTINUE:	    assert(p->state != curstate);	    proto_debug(1, _("protocol: state_machine: p %p: moved from %s to %s\n"),			    p, pstate2str(curstate),			    pstate2str(p->state));	    continue;	/*	 * Request has failed in some way locally.  The security_handle will	 * contain an appropriate error message via security_geterror().  Set	 * pkt to NULL to indicate failure to the callback, and then	 * fall through to the common finish code.	 *	 * Note that remote failures finish via PA_FINISH, because they did	 * complete successfully locally.	 */	case PA_ABORT:	    pkt = NULL;	    /* FALLTHROUGH */	/*	 * Request has completed successfully.	 * Free up resources the request has used, call the continuation	 * function specified by the caller and quit.	 */	case PA_FINISH:	    (*p->continuation)(p->datap, pkt, p->security_handle);	    security_close(p->security_handle);	    amfree(p->hostname);	    amfree(p->req.body);	    amfree(p);	    return;	default:	    assert(0);	    break;	/* in case asserts are turned off */	}	/*NOTREACHED*/    }    /*NOTREACHED*/}/* * The request send state.  Here, the packet is actually transmitted * across the network.  After setting up timeouts, the request * moves to the acknowledgement wait state.  We return from the state * machine at this point, and let the request be received from the network. */static p_action_ts_sendreq(    proto_t *	p,    p_action_t	action,    pkt_t *	pkt){    assert(p != NULL);    (void)action;	/* Quiet unused parameter warning */    (void)pkt;		/* Quiet unused parameter warning */    if (security_sendpkt(p->security_handle, &p->req) < 0) {	/* XXX should retry */	security_seterror(p->security_handle, _("error sending REQ: %s"),	    security_geterror(p->security_handle));	return (PA_ABORT);    }    /*     * Remember when this request was first sent     */    p->curtime = CURTIME;    /*     * Move to the ackwait state     */    p->state = s_ackwait;    p->timeout = ACK_WAIT;    return (PA_PENDING);}/* * The acknowledge wait state.  We can enter here two ways: * *  - the caller has received a packet, located the request for *    that packet, and called us with an action of PA_RCVDATA. *     *  - the caller has determined that a request has timed out, *    and has called us with PA_TIMEOUT. * * Here we process the acknowledgment, which usually means that * the client has agreed to our request and is working on it. * It will later send a reply when finished. */static p_action_ts_ackwait(    proto_t *	p,    p_action_t	action,    pkt_t *	pkt){    assert(p != NULL);    /*     * The timeout case.  If our retry count has gone to zero     * fail this request.  Otherwise, move to the send state     * to retry the request.     */    if (action == PA_TIMEOUT) {	assert(pkt == NULL);	if (--p->reqtries == 0) {	    security_seterror(p->security_handle, _("timeout waiting for ACK"));	    return (PA_ABORT);	}	p->state = s_sendreq;	return (PA_CONTINUE);    }    assert(action == PA_RCVDATA);    assert(pkt != NULL);    /*     * The packet-received state.  Determine what kind of     * packet we received, and act based on the reply type.     */    switch (pkt->type) {    /*     * Received an ACK.  Everything's good.  The client is     * now working on the request.  We queue up again and     * wait for the reply.     */    case P_ACK:	p->state = s_repwait;	p->timeout = p->repwait;	return (PA_PENDING);    /*     * Received a NAK.  The request failed, so free up the     * resources associated with it and return.     *     * This should NOT return PA_ABORT because it is not a local failure.     */    case P_NAK:	return (PA_FINISH);    /*     * The client skipped the ACK, and replied right away.     * Move to the reply state to handle it.     */    case P_REP:    case P_PREP:	p->state = s_repwait;	return (PA_CONTINUE);    /*     * Unexpected packet.  Requeue this request and hope     * we get what we want later.     */    default:	return (PA_PENDING);    }}/* * The reply wait state.  We enter here much like we do with s_ackwait. */static p_action_ts_repwait(    proto_t *	p,    p_action_t	action,    pkt_t *	pkt){    pkt_t ack;    /*     * Timeout waiting for a reply.     */    if (action == PA_TIMEOUT) {	assert(pkt == NULL);	/*	 * If we've blown our timeout limit, free up this packet and	 * return.	 */	if (p->resettries == 0 || DROP_DEAD_TIME(p->origtime)) {	    security_seterror(p->security_handle, _("timeout waiting for REP"));	    return (PA_ABORT);	}	/*	 * We still have some tries left.  Resend the request.	 */	p->resettries--;	p->state = s_sendreq;	p->reqtries = getconf_int(CNF_REQ_TRIES);	return (PA_CONTINUE);    }    assert(action == PA_RCVDATA);    /* Finish if we get a NAK */    if (pkt->type == P_NAK)	return (PA_FINISH);    /*     * We've received some data.  If we didn't get a reply,     * requeue the packet and retry.  Otherwise, acknowledge     * the reply, cleanup this packet, and return.     */    if (pkt->type != P_REP && pkt->type != P_PREP)	return (PA_PENDING);    if(pkt->type == P_REP) {	pkt_init_empty(&ack, P_ACK);	if (security_sendpkt(p->security_handle, &ack) < 0) {	    /* XXX should retry */	    amfree(ack.body);	    security_seterror(p->security_handle, _("error sending ACK: %s"),		security_geterror(p->security_handle));	    return (PA_ABORT);	}	amfree(ack.body);	return (PA_FINISH);    }    else if(pkt->type == P_PREP) {	p->timeout = p->repwait - CURTIME + p->curtime + 1;	return (PA_CONTPEND);    }    /* should never go here, shut up compiler warning */    return (PA_FINISH);}/* * event callback that receives a packet */static voidrecvpkt_callback(    void *		cookie,    pkt_t *		pkt,    security_status_t	status){    proto_t *p = cookie;    assert(p != NULL);    switch (status) {    case S_OK:	state_machine(p, PA_RCVDATA, pkt);	break;    case S_TIMEOUT:	state_machine(p, PA_TIMEOUT, NULL);	break;    case S_ERROR:	state_machine(p, PA_ABORT, NULL);	break;    default:	assert(0);	break;    }}/* * -------------- * Misc functions *//* * Convert a pstate_t into a printable form. */static const char *pstate2str(    pstate_t	pstate){    static const struct {	pstate_t type;	const char name[12];    } pstates[] = {#define	X(s)	{ s, stringize(s) }	X(s_sendreq),	X(s_ackwait),	X(s_repwait),#undef X    };    int i;    for (i = 0; i < ASIZE(pstates); i++)	if (pstate == pstates[i].type)	    return (pstates[i].name);    return (_("BOGUS PSTATE"));}/* * Convert an p_action_t into a printable form */static const char *action2str(    p_action_t	action){    static const struct {	p_action_t type;	const char name[12];    } actions[] = {#define	X(s)	{ s, stringize(s) }	X(PA_START),	X(PA_TIMEOUT),	X(PA_ERROR),	X(PA_RCVDATA),	X(PA_CONTPEND),	X(PA_PENDING),	X(PA_CONTINUE),	X(PA_FINISH),	X(PA_ABORT),#undef X    };    int i;    for (i = 0; i < ASIZE(actions); i++)	if (action == actions[i].type)	    return (actions[i].name);    return (_("BOGUS ACTION"));}

⌨️ 快捷键说明

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