Exemple #1
0
/* Connect to the server. All session parameters (like remote address) must
 * already have been set.
 * rgerhards, 2008-03-19
 */
relpRetVal
relpSessConnect(relpSess_t *pThis, int protFamily, unsigned char *port, unsigned char *host)
{
	relpOffers_t *pOffers;
	unsigned char *pszOffers = NULL;
	size_t lenOffers;
	ENTER_RELPFUNC;
	RELPOBJ_assert(pThis, Sess);

	CHKRet(relpSessFixCmdStates(pThis));
	if(pThis->srvAddr == NULL) { /* initial connect, need to save params */
		pThis->protFamily = protFamily;
		if((pThis->srvPort = (unsigned char*) strdup((char*)port)) == NULL)
			ABORT_FINALIZE(RELP_RET_OUT_OF_MEMORY);
		if((pThis->srvAddr = (unsigned char*) strdup((char*)host)) == NULL)
			ABORT_FINALIZE(RELP_RET_OUT_OF_MEMORY);
	}

	/* (re-)init some counters */
	pThis->txnr = 1;
	pThis->sessType = eRelpSess_Client;	/* indicate we have a client session */

	CHKRet(relpTcpConstruct(&pThis->pTcp, pThis->pEngine));
	CHKRet(relpTcpConnect(pThis->pTcp, protFamily, port, host));
	relpSessSetSessState(pThis, eRelpSessState_PRE_INIT);

	/* create offers */
	CHKRet(relpSessConstructOffers(pThis, &pOffers));
	CHKRet(relpOffersToString(pOffers, NULL, 0, &pszOffers, &lenOffers));
	CHKRet(relpOffersDestruct(&pOffers));

	CHKRet(relpSessRawSendCommand(pThis, (unsigned char*)"open", 4, pszOffers, lenOffers,
				      relpSessCBrspOpen));
	relpSessSetSessState(pThis, eRelpSessState_INIT_CMD_SENT);
	CHKRet(relpSessWaitState(pThis, eRelpSessState_INIT_RSP_RCVD, pThis->timeout));

	/* we now have received the server's response. Now is a good time to check if the offers
	 * received back are compatible with what we need - and, if not, terminate the session...
	 */
pThis->pEngine->dbgprint("pre CltConnChkOffers %d\n", iRet);
	CHKRet(relpSessCltConnChkOffers(pThis));
	/* TODO: flag sesssion as broken if we did not succeed? */

	/* if we reach this point, we have a valid relp session */
	relpSessSetSessState(pThis, eRelpSessState_READY_TO_SEND); /* indicate session startup */

finalize_it:
pThis->pEngine->dbgprint("end relpSessConnect, iRet %d\n", iRet);
	if(pszOffers != NULL)
		free(pszOffers);

	LEAVE_RELPFUNC;
}
Exemple #2
0
/* callback when the "open" command has been processed
 * Most importantly, this function needs to check if we are
 * compatible with the server-provided offers and terminate if
 * not. If we are, we must set our own parameters to match the
 * server-provided ones. Please note that the offer processing here
 * is the last and final. So the ultimate decision is made and if we
 * are unhappy with something that we can not ignore, we must
 * terminate with an error status.
 * In such cases, we flag the session as broken, as theoretically
 * it is possible to fix it by restarting the server with a set
 * of different parameters. The question remains, though, if that's
 * the smartest route to take...
 * Note that offer-processing is very similiar to offer-processing
 * at the server end (copen.c). We may be able to combine some of
 * it in the future (or may not, depending on the subtly different
 * needs both parts have. For now I leave this to a ... TODO ;)).
 * rgerhards, 2008-03-25
 */
static relpRetVal
relpSessCBrspOpen(relpSess_t *pThis, relpFrame_t *pFrame)
{
	relpEngine_t *pEngine;
	relpOffers_t *pOffers = NULL;
	relpOffer_t *pOffer;
	relpOfferValue_t *pOfferVal;

	ENTER_RELPFUNC;
	RELPOBJ_assert(pThis, Sess);
	RELPOBJ_assert(pFrame, Frame);
	pEngine = pThis->pEngine;

	/* first get the offers list from the server response */
	CHKRet(relpOffersConstructFromFrame(&pOffers, pFrame));

	/* we loop through the offers and set session parameters. If we find
	 * something truely unacceptable, we break the session.
	 */
	for(pOffer = pOffers->pRoot ; pOffer != NULL ; pOffer = pOffer->pNext) {
		pEngine->dbgprint("processing server offer '%s'\n", pOffer->szName);
		if(!strcmp((char*)pOffer->szName, "relp_version")) {
			if(pOffer->pValueRoot == NULL)
				ABORT_FINALIZE(RELP_RET_INVALID_OFFER);
			if(pOffer->pValueRoot->intVal == -1)
				ABORT_FINALIZE(RELP_RET_INVALID_OFFER);
			if(pOffer->pValueRoot->intVal > pEngine->protocolVersion)
				ABORT_FINALIZE(RELP_RET_INCOMPAT_OFFERS);
			/* Once we support multiple versions, we may need to check what we
			 * are compatible with. For now, we accept anything, because there is
			 * nothing else yet ;)
			 */
			relpSessSetProtocolVersion(pThis, pOffer->pValueRoot->intVal);
		} else if(!strcmp((char*)pOffer->szName, "commands")) {
			for(pOfferVal = pOffer->pValueRoot ; pOfferVal != NULL ; pOfferVal = pOfferVal->pNext) {
				/* we do not care about return code in this case */
				relpSessSetEnableCmd(pThis, pOfferVal->szVal, eRelpCmdState_Enabled);
				pEngine->dbgprint("enabled command '%s'\n", pOfferVal->szVal);
			}
		} else if(!strcmp((char*)pOffer->szName, "relp_software")) {
			/* we know this parameter, but we do not do anything
			 * with it -- this may change if we need to emulate
			 * something based on known bad relp software behaviour.
			 */
		} else {
			/* if we do not know an offer name, we ignore it - in this
			 * case, we may simply not support it (but the client does and
			 * must now live without it...)
			 */
			pEngine->dbgprint("ignoring unknown server offer '%s'\n", pOffer->szName);
		}
	}
	relpSessSetSessState(pThis, eRelpSessState_INIT_RSP_RCVD);

finalize_it:
	if(pOffers != NULL)
		relpOffersDestruct(&pOffers);

	LEAVE_RELPFUNC;
}
Exemple #3
0
/* Delete an entry from our unacked list. The list entry is destructed, but
 * the sendbuf not.
 * rgerhards, 2008-03-20
 */
static relpRetVal
relpSessDelUnacked(relpSess_t *pThis, relpSessUnacked_t *pUnackedLstEntry)
{
	ENTER_RELPFUNC;
	RELPOBJ_assert(pThis, Sess);
	assert(pUnackedLstEntry != NULL);

	DLL_Del(pUnackedLstEntry, pThis->pUnackedLstRoot, pThis->pUnackedLstLast);
	--pThis->lenUnackedLst;

	if(   pThis->lenUnackedLst < pThis->sizeWindow
	   && relpSessGetSessState(pThis) == eRelpSessState_WINDOW_FULL) {
		/* here, we need to check if we had WINDOW_FULL condition. The reason is that
		 * we otherwise mess up the session init handling - contrary to ...AddUnacked(),
		 * we run into the situation of a session state change on init. So we
		 * need to make sure it works.
		 */
		relpSessSetSessState(pThis, eRelpSessState_READY_TO_SEND);
	}

	free(pUnackedLstEntry);

	pThis->pEngine->dbgprint("DEL sess %p unacked %d, sessState %d\n", pThis, pThis->lenUnackedLst, pThis->sessState);
	LEAVE_RELPFUNC;
}
Exemple #4
0
/* add an entry to our unacked frame list. The sendbuf object is handed over and must
 * no longer be accessed by the caller.
 * NOTE: we do not need mutex locks. This changes when we have a background transfer
 * thread (which we currently do not have).
 * rgerhards, 2008-03-20
 */
relpRetVal
relpSessAddUnacked(relpSess_t *pThis, relpSendbuf_t *pSendbuf)
{
	relpSessUnacked_t *pUnackedLstEntry;

	ENTER_RELPFUNC;
	RELPOBJ_assert(pThis, Sess);
	RELPOBJ_assert(pSendbuf, Sendbuf);

	if((pUnackedLstEntry = calloc(1, sizeof(relpSessUnacked_t))) == NULL)
		ABORT_FINALIZE(RELP_RET_OUT_OF_MEMORY);

	pUnackedLstEntry->pSendbuf = pSendbuf;

	DLL_Add(pUnackedLstEntry, pThis->pUnackedLstRoot, pThis->pUnackedLstLast);
	++pThis->lenUnackedLst;

	if(pThis->lenUnackedLst >= pThis->sizeWindow) {
		/* in theory, we would need to check if the session is initialized, as
		 * we would mess up session state in that case. However, as the init
		 * process is just one frame, we can never run into the situation that
		 * the window is exhausted during init, so we do not check it.
		 */
		relpSessSetSessState(pThis, eRelpSessState_WINDOW_FULL);
		if(pThis->lenUnackedLst >= pThis->sizeWindow)
			pThis->pEngine->dbgprint("Warning: exceeding window size, max %d, curr %d\n",
						 pThis->lenUnackedLst, pThis->sizeWindow);
	}
	pThis->pEngine->dbgprint("ADD sess %p unacked %d, sessState %d\n", pThis, pThis->lenUnackedLst, pThis->sessState);

finalize_it:
	LEAVE_RELPFUNC;
}