static int memory_read(BIO *b, char *out, int outl) { int ret = -1; char* buf; int size; BIO_memory_data* pData = (BIO_memory_data*)b->ptr; // //BIO_clear_retry_flags(b); // CWLockSafeList(pData->pRecvAddress); // Used only in DTLS handshake while (CWGetCountElementFromSafeList(pData->pRecvAddress) == 0){ CWWaitElementFromSafeList(pData->pRecvAddress); } buf = (char*)CWRemoveHeadElementFromSafeList(pData->pRecvAddress, &size); CWUnlockSafeList(pData->pRecvAddress); if ((buf == NULL) || (size <= 0)) CWLog("Warning empty buffer"); else { ret = ((size < outl) ? size : outl) - 4; memcpy(out, buf + 4, ret); CW_FREE_OBJECT(buf); } return ret; }
/* * Receive a message, that can be fragmented. This is useful not only for the Join State */ CWBool CWReceiveMessage(CWProtocolMessage *msgPtr) { CWList fragments = NULL; int readBytes; char buf[CW_BUFFER_SIZE]; CWBool dataFlag = CW_FALSE; CW_REPEAT_FOREVER { CW_ZERO_MEMORY(buf, CW_BUFFER_SIZE); #ifdef CW_NO_DTLS char *pkt_buffer = NULL; CWLockSafeList(gPacketReceiveList); while (CWGetCountElementFromSafeList(gPacketReceiveList) == 0) CWWaitElementFromSafeList(gPacketReceiveList); pkt_buffer = (char*)CWRemoveHeadElementFromSafeListwithDataFlag(gPacketReceiveList, &readBytes,&dataFlag); CWUnlockSafeList(gPacketReceiveList); CW_COPY_MEMORY(buf, pkt_buffer, readBytes); CW_FREE_OBJECT(pkt_buffer); #else if(!CWSecurityReceive(gWTPSession, buf, CW_BUFFER_SIZE, &readBytes)) {return CW_FALSE;} #endif if(!CWProtocolParseFragment(buf, readBytes, &fragments, msgPtr, &dataFlag, NULL)) { if(CWErrorGetLastErrorCode() == CW_ERROR_NEED_RESOURCE) { // we need at least one more fragment continue; } else { // error CWErrorCode error; error=CWErrorGetLastErrorCode(); switch(error) { case CW_ERROR_SUCCESS: {CWDebugLog("ERROR: Success"); break;} case CW_ERROR_OUT_OF_MEMORY: {CWDebugLog("ERROR: Out of Memory"); break;} case CW_ERROR_WRONG_ARG: {CWDebugLog("ERROR: Wrong Argument"); break;} case CW_ERROR_INTERRUPTED: {CWDebugLog("ERROR: Interrupted"); break;} case CW_ERROR_NEED_RESOURCE: {CWDebugLog("ERROR: Need Resource"); break;} case CW_ERROR_COMUNICATING: {CWDebugLog("ERROR: Comunicating"); break;} case CW_ERROR_CREATING: {CWDebugLog("ERROR: Creating"); break;} case CW_ERROR_GENERAL: {CWDebugLog("ERROR: General"); break;} case CW_ERROR_OPERATION_ABORTED: {CWDebugLog("ERROR: Operation Aborted"); break;} case CW_ERROR_SENDING: {CWDebugLog("ERROR: Sending"); break;} case CW_ERROR_RECEIVING: {CWDebugLog("ERROR: Receiving"); break;} case CW_ERROR_INVALID_FORMAT: {CWDebugLog("ERROR: Invalid Format"); break;} case CW_ERROR_TIME_EXPIRED: {CWDebugLog("ERROR: Time Expired"); break;} case CW_ERROR_NONE: {CWDebugLog("ERROR: None"); break;} } CWDebugLog("~~~~~~"); return CW_FALSE; } } else break; // the message is fully reassembled } return CW_TRUE; }
CWBool CWWTPSendAcknowledgedPacket(int seqNum, CWList msgElemlist, CWBool (assembleFunc)(CWProtocolMessage **, int *, int, int, CWList), CWBool (parseFunc)(char*, int, int, void*), CWBool (saveFunc)(void*), void *valuesPtr) { CWProtocolMessage *messages = NULL; CWProtocolMessage msg; int fragmentsNum = 0, i; struct timespec timewait; int gTimeToSleep = gCWRetransmitTimer; int gMaxTimeToSleep = CW_ECHO_INTERVAL_DEFAULT/2; msg.msg = NULL; if(!(assembleFunc(&messages, &fragmentsNum, gWTPPathMTU, seqNum, msgElemlist))) { goto cw_failure; } gWTPRetransmissionCount= 0; while(gWTPRetransmissionCount < gCWMaxRetransmit) { CWDebugLog("Transmission Num:%d", gWTPRetransmissionCount); for(i = 0; i < fragmentsNum; i++) { #ifdef CW_NO_DTLS if(!CWNetworkSendUnsafeConnected(gWTPSocket, messages[i].msg, messages[i].offset)) #else if(!CWSecuritySend(gWTPSession, messages[i].msg, messages[i].offset)) #endif { CWDebugLog("Failure sending Request"); goto cw_failure; } } timewait.tv_sec = time(0) + gTimeToSleep; timewait.tv_nsec = 0; CW_REPEAT_FOREVER { CWThreadMutexLock(&gInterfaceMutex); if (CWGetCountElementFromSafeList(gPacketReceiveList) > 0) CWErrorRaise(CW_ERROR_SUCCESS, NULL); else { if (CWErr(CWWaitThreadConditionTimeout(&gInterfaceWait, &gInterfaceMutex, &timewait))) CWErrorRaise(CW_ERROR_SUCCESS, NULL); } CWThreadMutexUnlock(&gInterfaceMutex); switch(CWErrorGetLastErrorCode()) { case CW_ERROR_TIME_EXPIRED: { gWTPRetransmissionCount++; goto cw_continue_external_loop; break; } case CW_ERROR_SUCCESS: { /* there's something to read */ if(!(CWReceiveMessage(&msg))) { CW_FREE_PROTOCOL_MESSAGE(msg); CWDebugLog("Failure Receiving Response"); goto cw_failure; } if(!(parseFunc(msg.msg, msg.offset, seqNum, valuesPtr))) { if(CWErrorGetLastErrorCode() != CW_ERROR_INVALID_FORMAT) { CW_FREE_PROTOCOL_MESSAGE(msg); CWDebugLog("Failure Parsing Response"); goto cw_failure; } else { CWErrorHandleLast(); { gWTPRetransmissionCount++; goto cw_continue_external_loop; } break; } } if((saveFunc(valuesPtr))) { goto cw_success; } else { if(CWErrorGetLastErrorCode() != CW_ERROR_INVALID_FORMAT) { CW_FREE_PROTOCOL_MESSAGE(msg); CWDebugLog("Failure Saving Response"); goto cw_failure; } } break; } case CW_ERROR_INTERRUPTED: { gWTPRetransmissionCount++; goto cw_continue_external_loop; break; } default: { CWErrorHandleLast(); CWDebugLog("Failure"); goto cw_failure; break; } } } cw_continue_external_loop: CWDebugLog("Retransmission time is over"); gTimeToSleep<<=1; if ( gTimeToSleep > gMaxTimeToSleep ) gTimeToSleep = gMaxTimeToSleep; } /* too many retransmissions */ return CWErrorRaise(CW_ERROR_NEED_RESOURCE, "Peer Dead"); cw_success: for(i = 0; i < fragmentsNum; i++) { CW_FREE_PROTOCOL_MESSAGE(messages[i]); } CW_FREE_OBJECT(messages); CW_FREE_PROTOCOL_MESSAGE(msg); return CW_TRUE; cw_failure: if(messages != NULL) { for(i = 0; i < fragmentsNum; i++) { CW_FREE_PROTOCOL_MESSAGE(messages[i]); } CW_FREE_OBJECT(messages); } CWDebugLog("Failure"); return CW_FALSE; }
CWBool CWWTPCheckForBindingFrame() { // CWLockSafeList(gFrameList); while (CWGetCountElementFromSafeList(gFrameList) > 0) { CWBindingDataListElement* dataFirstElem = CWRemoveHeadElementFromSafeList(gFrameList, NULL); if (dataFirstElem) { int k; int fragmentsNum = 0; CWProtocolMessage *completeMsgPtr = NULL; if (!CWAssembleDataMessage(&completeMsgPtr, &fragmentsNum, gWTPPathMTU, dataFirstElem->frame, dataFirstElem->bindingValues, #ifdef CW_NO_DTLS CW_PACKET_PLAIN #else (gDtlsSecurity == 1)?CW_PACKET_CRYPT:CW_PACKET_PLAIN /* 0-CW_PACKET_PLAIN, 1-CW_PACKET_CRYPT */ #endif )) { for(k = 0; k < fragmentsNum; k++) { CW_FREE_PROTOCOL_MESSAGE(completeMsgPtr[k]); } CW_FREE_OBJECT(completeMsgPtr); CW_FREE_PROTOCOL_MESSAGE(*(dataFirstElem->frame)); CW_FREE_OBJECT(dataFirstElem->frame); CW_FREE_OBJECT(dataFirstElem->bindingValues); CW_FREE_OBJECT(dataFirstElem); continue; } for (k = 0; k < fragmentsNum; k++) { #ifndef CW_NO_DTLS if(gDtlsSecurity == 1) { if (!CWSecuritySend(gWTPSession, completeMsgPtr[k].msg, completeMsgPtr[k].offset)) { CWDebugLog("Failure sending Request"); break; //gzm break don't unlockSafeList ??? } } else #endif { if (!CWNetworkSendUnsafeUnconnected(gWTPSocket, &(gACInfoPtr->preferredAddress), completeMsgPtr[k].msg, completeMsgPtr[k].offset)) { CWDebugLog("Failure sending Request"); break; //gzm break don't unlockSafeList ??? } } } for (k = 0; k < fragmentsNum; k++) { CW_FREE_PROTOCOL_MESSAGE(completeMsgPtr[k]); } CW_FREE_OBJECT(completeMsgPtr); CW_FREE_PROTOCOL_MESSAGE(*(dataFirstElem->frame)); CW_FREE_OBJECT(dataFirstElem->frame); CW_FREE_OBJECT(dataFirstElem->bindingValues); CW_FREE_OBJECT(dataFirstElem); } } CWUnlockSafeList(gFrameList); return CW_TRUE; }