/* Send a response to the client. * rgerhards, 2008-03-19 */ relpRetVal relpSessSendResponse(relpSess_t *pThis, relpTxnr_t txnr, unsigned char *pData, size_t lenData) { relpSendbuf_t *pSendbuf; ENTER_RELPFUNC; RELPOBJ_assert(pThis, Sess); CHKRet(relpFrameBuildSendbuf(&pSendbuf, txnr, (unsigned char*)"rsp", 3, pData, lenData, pThis, NULL)); /* now enqueue it to the sendq (which means "send it" ;)) */ CHKRet(relpSendqAddBuf(pThis->pSendq, pSendbuf, pThis->pTcp)); finalize_it: if(iRet != RELP_RET_OK) { if(iRet == RELP_RET_IO_ERR) { pThis->pEngine->dbgprint("relp session %p is broken, io error\n", pThis); pThis->sessState = eRelpSessState_BROKEN; } if(pSendbuf != NULL) relpSendbufDestruct(&pSendbuf); } LEAVE_RELPFUNC; }
/** Destruct a RELP sess instance */ relpRetVal relpSessDestruct(relpSess_t **ppThis) { relpSess_t *pThis; relpSessUnacked_t *pUnacked; relpSessUnacked_t *pUnackedToDel; ENTER_RELPFUNC; assert(ppThis != NULL); pThis = *ppThis; RELPOBJ_assert(pThis, Sess); /* pTcp may be NULL if we run into the destructor due to an error that occured * during construction. */ if(pThis->pTcp != NULL) { if(pThis->pSrv != NULL) { relpSessSrvDoDisconnect(pThis); } else { /* we are at the client side of the connection */ if( pThis->sessState != eRelpSessState_DISCONNECTED && pThis->sessState != eRelpSessState_BROKEN) { relpSessCltDoDisconnect(pThis); } } } if(pThis->pSendq != NULL) relpSendqDestruct(&pThis->pSendq); if(pThis->pTcp != NULL) relpTcpDestruct(&pThis->pTcp); /* unacked list */ for(pUnacked = pThis->pUnackedLstRoot ; pUnacked != NULL ; ) { pUnackedToDel = pUnacked; pUnacked = pUnacked->pNext; relpSendbufDestruct(&pUnackedToDel->pSendbuf); free(pUnackedToDel); } free(pThis->srvPort); free(pThis->srvAddr); free(pThis->clientIP); free(pThis->pristring); free(pThis->ownCertFile); free(pThis->privKeyFile); relpSessFreePermittedPeers(pThis); pthread_mutex_destroy(&pThis->mutSend); /* done with de-init work, now free object itself */ free(pThis); *ppThis = NULL; 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 hint to the remote peer. This function works for the * server-side of the connection. A modified version must be used for the * client side (because we have different ways of sending the data). We do * not yet need the client side. If we do, way should think about a generic * approach, eg by using function pointers for the send function. * rgerhards, 2008-03-31 */ static relpRetVal relpSessSrvSendHint(relpSess_t *pThis, unsigned char *pHint, size_t lenHint, unsigned char *pData, size_t lenData) { relpSendbuf_t *pSendbuf = NULL; ENTER_RELPFUNC; assert(pHint != NULL); assert(lenHint != 0); RELPOBJ_assert(pThis, Sess); CHKRet(relpFrameBuildSendbuf(&pSendbuf, 0, pHint, lenHint, pData, lenData, pThis, NULL)); /* now send it */ pThis->pEngine->dbgprint("hint-frame to send: '%s'\n", pSendbuf->pData + (9 - pSendbuf->lenTxnr)); CHKRet(relpSendbufSend(pSendbuf, pThis->pTcp)); finalize_it: if(pSendbuf != NULL) relpSendbufDestruct(&pSendbuf); LEAVE_RELPFUNC; }