/* Try to restablish a broken session. A single try is made and the result * reported back. RELP_RET_OK if we could get a new session, a RELP error state * otherwise (e.g. RELP_RET_SESSION_BROKEN, but could also be a more precise * error code). If the session can be re-established, any unsent frames are * resent. The function returns only after that happened. * rgerhards, 2008-03-22 */ relpRetVal relpSessTryReestablish(relpSess_t *pThis) { relpSessUnacked_t *pUnackedEtry; ENTER_RELPFUNC; RELPOBJ_assert(pThis, Sess); assert(pThis->sessState = eRelpSessState_BROKEN); CHKRet(relpTcpAbortDestruct(&pThis->pTcp)); CHKRet(relpSessConnect(pThis, pThis->protFamily, pThis->srvPort, pThis->srvAddr)); /* if we reach this point, we could re-establish the session. We now * need to resend any unacked data. Note that we need to patch in new txnr's * into the existing frames. We need to do a special send command, as the usual * one would maintain the unacked list, what we can not do right now (because * it is not to be modified. */ pUnackedEtry = pThis->pUnackedLstRoot; if(pUnackedEtry != NULL) pThis->pEngine->dbgprint("relp session %p reestablished, now resending %d unacked frames\n", pThis, pThis->lenUnackedLst); while(pUnackedEtry != NULL) { pThis->pEngine->dbgprint("resending frame '%s'\n", pUnackedEtry->pSendbuf->pData + 9 - pUnackedEtry->pSendbuf->lenTxnr); CHKRet(relpFrameRewriteTxnr(pUnackedEtry->pSendbuf, pThis->txnr)); pThis->txnr = relpEngineNextTXNR(pThis->txnr); CHKRet(relpSendbufSendAll(pUnackedEtry->pSendbuf, pThis, 0)); pUnackedEtry = pUnackedEtry->pNext; } finalize_it: pThis->pEngine->dbgprint("after TryReestablish, sess state %d\n", pThis->sessState); LEAVE_RELPFUNC; }
/* This functions sends a complete sendbuf (a blocking call). It * is intended for use by clients. Do NOT use it on servers as * that will block other activity. bAddToUnacked specifies if the * sendbuf should be linked to the unacked list (if 1). If it is 0 * this shall NOT happen. Mode 0 is used for session reestablishment, * when the unacked list needs to be retransmitted. * rgerhards, 2008-03-19 */ relpRetVal relpSendbufSendAll(relpSendbuf_t *pThis, relpSess_t *pSess, int bAddToUnacked) { ssize_t lenToWrite; ssize_t lenWritten; ENTER_RELPFUNC; RELPOBJ_assert(pThis, Sendbuf); RELPOBJ_assert(pSess, Sess); lenToWrite = pThis->lenData - pThis->bufPtr; while(lenToWrite != 0) { lenWritten = lenToWrite; //pSess->pEngine->dbgprint("sendbuf len %d, still to write %d\n", (int) pThis->lenData, (int) lenToWrite); CHKRet(relpTcpSend(pSess->pTcp, pThis->pData + (9 - pThis->lenTxnr) + pThis->bufPtr, &lenWritten)); if(lenWritten == -1) { ABORT_FINALIZE(RELP_RET_IO_ERR); } else if(lenWritten == lenToWrite) { lenToWrite = 0; } else { pThis->bufPtr += lenWritten; lenToWrite = pThis->lenData - pThis->bufPtr; } } /* ok, we now have sent the full buf. So we now need to add it to the unacked list, so that * we know what to do when the "rsp" packet comes in. -- rgerhards, 2008-03-20 */ if(bAddToUnacked) { if((iRet = relpSessAddUnacked(pSess, pThis)) != RELP_RET_OK) { relpSendbufDestruct(&pThis); FINALIZE; } pSess->pEngine->dbgprint("sendbuf added to unacked list\n"); #if 0 { relpSessUnacked_t *pUnackedEtry; pUnackedEtry = pThis->pUnackedLstRoot; if(pUnackedEtry != NULL) { pThis->pEngine->dbgprint("resending frame '%s'\n", pUnackedEtry->pSendbuf->pData + 9 - pUnackedEtry->pSendbuf->lenTxnr); CHKRet(relpFrameRewriteTxnr(pUnackedEtry->pSendbuf, pThis->txnr)); pThis->txnr = relpEngineNextTXNR(pThis->txnr); CHKRet(relpSendbufSendAll(pUnackedEtry->pSendbuf, pThis, 0)); pUnackedEtry = pUnackedEtry->pNext; } } #endif } else pSess->pEngine->dbgprint("sendbuf NOT added to unacked list\n"); finalize_it: LEAVE_RELPFUNC; }
/* Send a command to the server. * This is a "raw" send function that just sends the command but does not * care about the receive loop or session state. This has been put into its * own function as some functionality (most importantly session init!) requires * handling that is other than the regular command/response mode. * rgerhards, 2008-03-19 */ static relpRetVal relpSessRawSendCommand(relpSess_t *pThis, unsigned char *pCmd, size_t lenCmd, unsigned char *pData, size_t lenData, relpRetVal (*rspHdlr)(relpSess_t*,relpFrame_t*)) { relpSendbuf_t *pSendbuf; ENTER_RELPFUNC; RELPOBJ_assert(pThis, Sess); CHKRet(relpFrameBuildSendbuf(&pSendbuf, pThis->txnr, pCmd, lenCmd, pData, lenData, pThis, rspHdlr)); pThis->txnr = relpEngineNextTXNR(pThis->txnr); /* now send it */ pThis->pEngine->dbgprint("frame to send: '%s'\n", pSendbuf->pData + (9 - pSendbuf->lenTxnr)); iRet = relpSendbufSendAll(pSendbuf, pThis, 1); if(iRet == RELP_RET_IO_ERR) { pThis->pEngine->dbgprint("relp session %p flagged as broken, IO error\n", pThis); pThis->sessState = eRelpSessState_BROKEN; ABORT_FINALIZE(RELP_RET_SESSION_BROKEN); } finalize_it: LEAVE_RELPFUNC; }