Exemple #1
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 #2
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 #3
0
/* construct an offers list from the offers contained in a frame. The frame's
 * Read Next pointer must be positioned at the first character of the offer.
 * rgerhards, 2008-03-25
 */
relpRetVal
relpOffersConstructFromFrame(relpOffers_t **ppOffers, relpFrame_t *pFrame)
{
	relpOffers_t *pOffers = NULL;
	relpOffer_t *pOffer;
	relpRetVal localRet;
	unsigned char c;
	size_t iName;
	size_t iVal;
	unsigned char szFeatNam[RELP_MAX_OFFER_FEATURENAME+1];
	unsigned char szFeatVal[RELP_MAX_OFFER_FEATUREVALUE+1];

	ENTER_RELPFUNC;
	assert(ppOffers != NULL);
	RELPOBJ_assert(pFrame, Frame);

	CHKRet(relpOffersConstruct(&pOffers, pFrame->pEngine));

	/* now process the command data */

	localRet = relpFrameGetNextC(pFrame, &c);
	while(localRet == RELP_RET_OK) {
		/* command name */
		iName = 0;
		while(iName < RELP_MAX_OFFER_FEATURENAME && c != '=' && localRet == RELP_RET_OK) {
			szFeatNam[iName++] = c;
			localRet = relpFrameGetNextC(pFrame, &c);
		}
		szFeatNam[iName] = '\0'; /* space is reserved for this! */
		CHKRet(relpOfferAdd(&pOffer, szFeatNam, pOffers));

		/* and now process the values (if any) */
		while(localRet == RELP_RET_OK && c != '\n') {
			localRet = relpFrameGetNextC(pFrame, &c); /* eat the "=" or "," */
			iVal = 0;
			while(   iVal < RELP_MAX_OFFER_FEATUREVALUE && localRet == RELP_RET_OK
			      && c != ',' && c != '\n' ) {
				szFeatVal[iVal++] = c;
				localRet = relpFrameGetNextC(pFrame, &c);
			}
			if(iVal > 0) { /* only set feature if one is actually given */
				szFeatVal[iVal] = '\0'; /* space is reserved for this */
				CHKRet(relpOfferValueAdd(szFeatVal, 0, pOffer));
			}
		}

		if(localRet == RELP_RET_OK && c == '\n')
			localRet = relpFrameGetNextC(pFrame, &c); /* eat '\n' */

	}

	if(localRet != RELP_RET_END_OF_DATA)
		ABORT_FINALIZE(localRet);

	*ppOffers = pOffers;

finalize_it:
	if(iRet != RELP_RET_OK) {
		if(pOffers != NULL)
			relpOffersDestruct(&pOffers);
	}

	LEAVE_RELPFUNC;
}