blob: 5e106338aed4e4cb270ebbc98e05bc47acafe863 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2016 - 2017 fortiss GmbH
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License 2.0 which is available at
* http://www.eclipse.org/legal/epl-2.0.
*
* SPDX-License-Identifier: EPL-2.0
*
* Contributors:
* Jose Cabral - initial API and implementation and/or initial documentation
*******************************************************************************/
#include "rcXSocketInterface.h"
#include <TLR_Includes.h>
#include "bsdsocketinterf.h"
#include "devlog.h"
#include "../../core/devexec.h"
#include "../core/cominfra/commfb.h"
#include <criticalregion.h>
#include <string.h>
#include <forte_config.h>
DEFINE_SINGLETON(CrcXSocketInterface);
char * const CrcXSocketInterface::scmForteQueueName = "FOR_QUE";
char * const CrcXSocketInterface::scmForteWaitingQueueName = "FOR_WAIT_QUE";
char * const CrcXSocketInterface::scmFortePoolName = "FOR_POOL";
const CrcXSocketInterface::TSocketDescriptor CrcXSocketInterface::scmInvalidSocketDescriptor = 0;
CrcXSocketInterface::CrcXSocketInterface(){
RX_RESULT eRslt;
mInitialized = true;
mListeningSocketDescriptor = 0;
mPacketsWaiting = 0;
/* forte Task identification */
//TODO: Check if it is really necessary
eRslt = TLR_TSK_IDENTIFY(nullptr, 0, &mForteResources.forteTask, 0, 0);
if(eRslt != RX_OK){
DEVLOG_ERROR("Couldn't identify own task\n");
mInitialized = false;
}
/* Create process queue */
eRslt = TLR_QUE_CREATE(scmForteQueueName, cg_forteQueueMax, &mForteResources.forteQueueHandle);
if(eRslt != RX_OK){
DEVLOG_ERROR("Couldn't create queue\n");
mInitialized = false;
}
/* Create resource pool for queue packets */
eRslt = TLR_POOL_CREATE(scmFortePoolName, cg_fortePoolMax, sizeof(FORTE_TCP_PACKET_T), &mForteResources.fortePoolHandle);
if(eRslt != RX_OK){
DEVLOG_ERROR("Couldn't create pool\n");
mInitialized = false;
}
TLR_QUE_LINK_SOURCE_SET(mForteResources.forteLinkSource, mForteResources.forteQueueHandle, 1);
mForteResources.sndId = 0;
/* Task TCP_UDP */
//TODO: Check if it is really necessary
eRslt = TLR_TSK_IDENTIFY(TCP_TASK_NAME, 0, &mForteResources.tcpTaskHandle, 0, 0);
if(eRslt != RX_OK){
DEVLOG_ERROR("Couldn't identify TCP/IP task\n");
mInitialized = false;
}
eRslt = TLR_QUE_IDENTIFY(EN_TCPUDP_PROCESS_QUEUE_NAME, 0, &mForteResources.tcpQueueLink);
if(eRslt != RX_OK){
DEVLOG_ERROR("Couldn't identify TCP/IP queue\n");
mInitialized = false;
}
}
CrcXSocketInterface::~CrcXSocketInterface(){
TLR_QUE_DELETE_CHECK(mForteResources.forteQueueHandle);
TLR_POOL_DELETE_CHECK(mForteResources.fortePoolHandle);
}
void CrcXSocketInterface::run(){
UINT32 ticks = 1000000 * 1 / rX_SysGetSystemCycletime(); //1 second
while(isAlive()){
if (mWaitingList.isEmpty()){
waitPacket(0, 0, ticks); //TODO: Check the actual value for the timeout
}
while(!mWaitingList.isEmpty()){
CCriticalRegion region(mSync);
FORTE_TCP_PACKET_T* firstPacket = *(static_cast<CSinglyLinkedList<FORTE_TCP_PACKET_T*>::Iterator>(mWaitingList.begin()));
TConnectionContainer::Iterator itEndConnection(mConnectionsList.end());
bool deletePacket = true;
for(TConnectionContainer::Iterator itRunnerConnection = mConnectionsList.begin(); itRunnerConnection != itEndConnection;){
// need to retrieve the callee as the iterator may get invalid in the recvDat function below in case of connection closing
forte::com_infra::CComLayer *comLayer = itRunnerConnection->mCallee;
TSocketDescriptor sockDes = itRunnerConnection->mSockDes;
++itRunnerConnection;
if(getSocketIDFromPacket(firstPacket) == sockDes->socketNumber){
sockDes->packetReceived = firstPacket;
if(0 != comLayer){
if(forte::com_infra::e_Nothing != comLayer->recvData(&sockDes, 0)){
startNewEventChain(comLayer->getCommFB());
}
}
sockDes->packetReceived = 0;
deletePacket = sockDes->deleteMe;
break;
}
}
if(deletePacket){
TLR_QUE_PACKETDONE(mForteResources.fortePoolHandle, mForteResources.forteQueueHandle, firstPacket);
mWaitingList.popFront();
mPacketsWaiting--;
}
}
}
}
void CrcXSocketInterface::addComCallback(TSocketDescriptor paFD, forte::com_infra::CComLayer *paComLayer){
{
CCriticalRegion criticalRegion(mSync);
TConnContType stNewNode = { paFD, paComLayer };
mConnectionsList.pushBack(stNewNode);
}
if(!isAlive()){
this->start();
}
}
void CrcXSocketInterface::removeComCallback(TSocketDescriptor paFD){
CCriticalRegion criticalRegion(mSync);
TConnectionContainer::Iterator itRunner(mConnectionsList.begin());
TConnectionContainer::Iterator itRefNode(mConnectionsList.end());
TConnectionContainer::Iterator itEnd(mConnectionsList.end());
while(itRunner != itEnd){
if(itRunner->mSockDes == paFD){
if(itRefNode ==itEnd){
mConnectionsList.popFront();
}
else{
mConnectionsList.eraseAfter(itRefNode);
}
break;
}
itRefNode = itRunner;
++itRunner;
}
}
bool CrcXSocketInterface::isInitialized(){
return mInitialized;
}
CrcXSocketInterface::TSocketDescriptor CrcXSocketInterface::openTCPServerConnection(char *paIPAddr, unsigned short paPort){
DEVLOG_INFO("CrcXSocketInterface: Opening TCP-Server connection at: %s:%d\n", paIPAddr, paPort);
if(CrcXSocketInterface::getInstance().isInitialized()){
TSocketDescriptor returnSocket = CrcXSocketInterface::getInstance().socketDescriptorAlloc();
if(0 != returnSocket){
RX_RESULT retVal = CrcXSocketInterface::getInstance().openConnection(paIPAddr, paPort, true, true, 0, returnSocket);
if(RX_OK == retVal){
return returnSocket;
}
else{
DEVLOG_ERROR("Error %d opening socket\n", retVal);
CrcXSocketInterface::getInstance().socketDescriptorDeAlloc(returnSocket);
}
}
else{
DEVLOG_ERROR("No enough memory to create a socket\n");
}
}
else{
DEVLOG_ERROR("CrcXSocketInterface is not initialized\n");
}
return CrcXSocketInterface::scmInvalidSocketDescriptor;
}
CrcXSocketInterface::TSocketDescriptor CrcXSocketInterface::openTCPClientConnection(char *paIPAddr, unsigned short paPort){
DEVLOG_INFO("CrcXSocketInterface: Opening TCP-Server connection at: %s:%d\n", paIPAddr, paPort);
if(CrcXSocketInterface::getInstance().isInitialized()){
TSocketDescriptor returnSocket = CrcXSocketInterface::getInstance().socketDescriptorAlloc();
if(0 != returnSocket){
RX_RESULT retVal = CrcXSocketInterface::getInstance().openConnection(paIPAddr, paPort, true, false, 0, returnSocket);
if(RX_OK == retVal){
return returnSocket;
}
else{
DEVLOG_ERROR("Error %d opening socket\n", retVal);
CrcXSocketInterface::getInstance().socketDescriptorDeAlloc(returnSocket);
}
}
else{
DEVLOG_ERROR("No enough memory to create a socket\n");
}
}
else{
DEVLOG_ERROR("CrcXSocketInterface is not initialized\n");
}
return CrcXSocketInterface::scmInvalidSocketDescriptor;
}
CrcXSocketInterface::TSocketDescriptor CrcXSocketInterface::openUDPSendPort(char *paIPAddr, unsigned short paPort, TUDPDestAddr *mDestAddr){
DEVLOG_INFO("CrcXSocketInterface: Opening UDP sending connection at: %s:%d\n", paIPAddr, paPort);
if(CrcXSocketInterface::getInstance().isInitialized()){
TSocketDescriptor returnSocket = CrcXSocketInterface::getInstance().socketDescriptorAlloc();
if(0 != returnSocket){
RX_RESULT retVal = CrcXSocketInterface::getInstance().openConnection(paIPAddr, paPort, false, false, mDestAddr, returnSocket);
if(RX_OK == retVal){
return returnSocket;
}
else{
DEVLOG_ERROR("Error %d opening socket\n", retVal);
CrcXSocketInterface::getInstance().socketDescriptorDeAlloc(returnSocket);
}
}
else{
DEVLOG_ERROR("No enough memory to create a socket\n");
}
}
else{
DEVLOG_ERROR("CrcXSocketInterface is not initialized\n");
}
return CrcXSocketInterface::scmInvalidSocketDescriptor;
}
CrcXSocketInterface::TSocketDescriptor CrcXSocketInterface::openUDPReceivePort(char *paIPAddr, unsigned short paPort){
DEVLOG_INFO("CrcXSocketInterface: Opening UDP sending connection at: %s:%d\n", paIPAddr, paPort);
if(CrcXSocketInterface::getInstance().isInitialized()){
TSocketDescriptor returnSocket = CrcXSocketInterface::getInstance().socketDescriptorAlloc();
if(0 != returnSocket){
RX_RESULT retVal = CrcXSocketInterface::getInstance().openConnection(paIPAddr, paPort, false, true, 0, returnSocket);
if(RX_OK == retVal){
return returnSocket;
}
else{
DEVLOG_ERROR("Error %d opening socket\n", retVal);
CrcXSocketInterface::getInstance().socketDescriptorDeAlloc(returnSocket);
}
}
else{
DEVLOG_ERROR("No enough memory to create a socket\n");
}
}
else{
DEVLOG_ERROR("CrcXSocketInterface is not initialized\n");
}
return CrcXSocketInterface::scmInvalidSocketDescriptor;
}
RX_RESULT CrcXSocketInterface::close(TSocketDescriptor paSockD){
if(scmInvalidSocketDescriptor != paSockD){
TCPIP_DATA_TCP_UDP_CMD_CLOSE_REQ_T tDataClose;
tDataClose.ulTimeout = 0; /* Default timeout (13000 milliseconds). Must be zero for UDP */
return CrcXSocketInterface::getInstance().sendPacketToTCP(paSockD->socketNumber, TCPIP_DATA_TCP_UDP_CMD_CLOSE_REQ_SIZE, TCPIP_TCP_UDP_CMD_CLOSE_REQ, &tDataClose, sizeof(TCPIP_DATA_TCP_UDP_CMD_CLOSE_REQ_T));
}
return RX_MEM_INVALID;
}
void CrcXSocketInterface::closeSocket(TSocketDescriptor paSockD){
if(CrcXSocketInterface::getInstance().isInitialized()){
RX_RESULT retVal = CrcXSocketInterface::getInstance().close(paSockD);
if (RX_OK != retVal){
DEVLOG_ERROR("Error %d when closing socket\n", retVal);
}
CrcXSocketInterface::getInstance().socketDescriptorDeAlloc(paSockD);
}
else{
DEVLOG_ERROR("CrcXSocketInterface is not initialized\n");
}
}
RX_RESULT CrcXSocketInterface::openConnection(char *paIPAddr, unsigned short paPort, bool isTCP, bool isServer, TUDPDestAddr *mDestAddr, TSocketDescriptor& pa_destSocket){
RX_RESULT retVal = RX_OK;
UINT32 socketNumber = 0;
TCPIP_DATA_TCP_UDP_CMD_OPEN_REQ_T tDataOpen;
tDataOpen.ulIpAddr = 0;
tDataOpen.ulPort = paPort;
tDataOpen.ulProtocol = (isTCP) ? TCP_PROTO_TCP : TCP_PROTO_UDP;
retVal = sendPacketToTCP(0, TCPIP_DATA_TCP_UDP_CMD_OPEN_REQ_SIZE, TCPIP_TCP_UDP_CMD_OPEN_REQ, &tDataOpen, sizeof(TCPIP_DATA_TCP_UDP_CMD_OPEN_REQ_T)); //send packet to open a socket
if(RX_OK == retVal){
TCPIP_PACKET_TCP_UDP_CMD_OPEN_CNF_T* cnfPacket;
retVal = waitPacket(TCPIP_TCP_UDP_CMD_OPEN_CNF, (FORTE_TCP_PACKET_T**) &cnfPacket, RX_INFINITE); //wait for CNF packet which indicates the result of the request
if(RX_OK == retVal){
if(RX_OK == cnfPacket->tHead.ulSta){
if(!isTCP){
socketNumber = cnfPacket->tHead.ulDestId;
UINT32 ipAddress = stringIpToInt(paIPAddr);
if(!isServer){ //Client UDP
if(0 != mDestAddr){
mDestAddr->destPort = paPort;
mDestAddr->destAddress = ipAddress;
}
else{
retVal = RX_MEM_INVALID;
}
}
if(0xE0000000 <= ipAddress && 0xEFFFFFFF >= ipAddress){
TCPIP_DATA_TCP_UDP_CMD_SET_SOCK_OPTION_REQ_T setOpt;
setOpt.ulMode = TCP_SOCK_ADD_MEMBERSHIP;
setOpt.unParam.ulMulticastGroup = ipAddress;
retVal = sendPacketToTCP(socketNumber, TCPIP_DATA_TCP_UDP_CMD_SET_SOCK_OPTION_REQ_SIZE, TCPIP_TCP_UDP_CMD_SET_SOCK_OPTION_REQ, &setOpt, sizeof(TCPIP_DATA_TCP_UDP_CMD_SET_SOCK_OPTION_REQ_T)); //send packet to open a socket
if(RX_OK == retVal){
TCPIP_PACKET_TCP_UDP_CMD_SET_SOCK_OPTION_CNF_T* setOptCnf;
retVal = waitPacket(TCPIP_TCP_UDP_CMD_SET_SOCK_OPTION_CNF, (FORTE_TCP_PACKET_T**) &setOptCnf, RX_INFINITE); //wait for CNF packet which indicates the result of the request
if (RX_OK == retVal){
retVal = setOptCnf->tHead.ulSta;
}
TLR_QUE_PACKETDONE(mForteResources.fortePoolHandle, mForteResources.forteQueueHandle, setOptCnf);
}
}
}
else { //TCP
if(isServer){ //TCP server
//call wait request but don't wait for CNF
TCPIP_DATA_TCP_CMD_WAIT_CONNECT_REQ_T tDataWait;
tDataWait.ulTimeoutSend = 0;
tDataWait.ulTimeoutListen = 0; /*Wait until connection comes in*/
retVal = sendPacketToTCP(cnfPacket->tHead.ulDestId, TCPIP_DATA_TCP_CMD_WAIT_CONNECT_REQ_SIZE, TCPIP_TCP_CMD_WAIT_CONNECT_REQ, &tDataWait, sizeof(TCPIP_DATA_TCP_CMD_WAIT_CONNECT_REQ_T));
if(RX_OK == retVal){
socketNumber = cnfPacket->tHead.ulDestId;
}else{
//error sending wait command
}
}
else{ //TCP CLient
//call connect and wait for confirm
TCPIP_DATA_TCP_CMD_CONNECT_REQ_T tDataConnect;
tDataConnect.ulIpAddr = CrcXSocketInterface::getInstance().stringIpToInt(paIPAddr); /* IP address of remote server to connect to */
if(0 != tDataConnect.ulIpAddr){
tDataConnect.ulPort = paPort; /* Port number of remote server to connect to */
tDataConnect.ulTimeoutSend = 0; /* IP address of remote server to connect to */
tDataConnect.ulTimeoutConnect = 0; /* Default timeout (31000 milliseconds) */
retVal = sendPacketToTCP(cnfPacket->tHead.ulDestId, TCPIP_DATA_TCP_CMD_CONNECT_REQ_SIZE, TCPIP_TCP_CMD_CONNECT_REQ, &tDataConnect, sizeof(TCPIP_DATA_TCP_CMD_CONNECT_REQ_T));
if(RX_OK == retVal){
TCPIP_PACKET_TCP_CMD_CONNECT_CNF_T* connecCnftPacket;
retVal = waitPacket(TCPIP_TCP_CMD_CONNECT_CNF, (FORTE_TCP_PACKET_T**) &connecCnftPacket, RX_INFINITE);
if(RX_OK == retVal){
if (RX_OK == connecCnftPacket->tHead.ulSta){
socketNumber = cnfPacket->tHead.ulDestId;
}else{
//connect packet didn't returned a valid packet
retVal = connecCnftPacket->tHead.ulSta;
}
}
else{
//error in waiting (?)
}
TLR_QUE_PACKETDONE(mForteResources.fortePoolHandle, mForteResources.forteQueueHandle, connecCnftPacket);
}
}
else{
retVal = TLR_E_TCP_ERR_IP_ADDR_INVALID_TCP_UDP_CMD_OPEN;
//wrong IP
}
}
}
}
else{
//returned packet has no OK status
}
TLR_QUE_PACKETDONE(mForteResources.fortePoolHandle, mForteResources.forteQueueHandle, cnfPacket);
}
else{
//waitPacket returned null
}
}
else{
//error sending the packet
}
if(RX_OK == retVal){
if(scmInvalidSocketDescriptor != pa_destSocket){
pa_destSocket->socketNumber = socketNumber;
pa_destSocket->accepted = isTCP ? false : true;
pa_destSocket->port = paPort;
pa_destSocket->packetReceived = 0;
pa_destSocket->deleteMe = true;
if (isTCP && isServer){
if(0 == mListeningSocketDescriptor){
mListeningSocketDescriptor = pa_destSocket;
}
}
}else{
retVal = RX_MEM_INVALID;
}
}
return retVal;
}
TForteUInt32 CrcXSocketInterface::stringIpToInt(char* paString){
TForteUInt32 result = 0;
char* currentCharacter;
int currentNumber = 0;
int ipNumberCounter = 0;
currentCharacter = paString;
if (0 == strcmp("localhost", paString)){
return 0;
}
while (1) {
if('0' <= *currentCharacter && '9' >= *currentCharacter){
currentNumber *= 10;
currentNumber += *currentCharacter - '0';
}else if('.' == *currentCharacter || '\0' == *currentCharacter ){
if(256 <= currentNumber){
return 0;
}
ipNumberCounter++;
result <<= 8;
result += currentNumber;
currentNumber = 0;
if(ipNumberCounter == 4)
{
break;
}else{
if ('\0' == *currentCharacter){
return 0;
}
}
}else{
return 0;
}
currentCharacter++;
}
return result;
}
RX_RESULT CrcXSocketInterface::sendPacketToTCP(UINT32 pa_destId, UINT32 paLen, UINT32 paCmd, void* paData, UINT32 pa_dataLength){
FORTE_TCP_PACKET_T* ptPck;
RX_RESULT retVal;
retVal = TLR_POOL_PACKET_GET(mForteResources.fortePoolHandle, &ptPck);
if(RX_OK == retVal){
TLR_QUE_LINK_SET_NEW_DESTID(mForteResources.tcpQueueLink, pa_destId);
TLR_QUE_LINK_SET_PACKET_SRC(ptPck, mForteResources.forteLinkSource);
ptPck->tHead.ulLen = paLen;
ptPck->tHead.ulId = ++mForteResources.sndId;
ptPck->tHead.ulSta = 0;
ptPck->tHead.ulCmd = paCmd;
ptPck->tHead.ulExt = 0;
ptPck->tHead.ulRout = 0;
TLR_MEMCPY(&((TCPIP_PACKET_TCP_UDP_CMD_OPEN_REQ_T*)ptPck)->tData, paData, pa_dataLength);
retVal = TLR_QUE_SENDPACKET_FIFO(mForteResources.tcpQueueLink, ptPck, 100); //rX_QueSendPacket((void*) mForteResources.tcpQueueLink.hQue, ptPck, 100);
if (RX_OK != retVal){
TLR_POOL_PACKET_RELEASE(mForteResources.fortePoolHandle, ptPck);
}
}
return retVal;
}
RX_RESULT CrcXSocketInterface::waitPacket(UINT32 pa_command, FORTE_TCP_PACKET_T** pa_packetResult, UINT pa_timeout){
RX_RESULT retVal;
FORTE_TCP_PACKET_T* localPacket = 0;
do{
retVal = TLR_QUE_WAITFORPACKET(mForteResources.forteQueueHandle, &localPacket, pa_timeout); //pa_timeout);rX_QueWaitForPacket((void*)mForteResources.forteQueueHandle, (void**) &localPacket, 100); //
if(0 != localPacket){
if(pa_command == localPacket->tHead.ulCmd || 0 == pa_command){
break;
}
else{
managePacketsDefault(localPacket);
localPacket = 0;
}
}
else{ //error waiting packet, normally because timeout expired
break;
}
} while(1);
if (0 != pa_packetResult){
*pa_packetResult = localPacket;
}else{
managePacketsDefault(localPacket);
}
return retVal;
}
void CrcXSocketInterface::managePacketsDefault(FORTE_TCP_PACKET_T* pa_packetResult){
if(0 != pa_packetResult){
switch (pa_packetResult->tHead.ulCmd){
case TCPIP_TCP_UDP_CMD_RECEIVE_STOP_IND:
case TCPIP_TCP_UDP_CMD_RECEIVE_IND:
case TCPIP_TCP_CMD_WAIT_CONNECT_CNF: {
if(cg_forteWaitingQueueMax <= mPacketsWaiting){
TLR_QUE_RETURNPACKET(pa_packetResult);
}
else{
mWaitingList.pushBack(pa_packetResult);
mPacketsWaiting++;
}
}
break;
case TCPIP_TCP_UDP_CMD_SHUTDOWN_IND: {
//close all sockets. TODO: The caller will never get notice that the socket was closed. Maybe reopen the socket when the CNF arrives
TCPIP_DATA_TCP_UDP_CMD_CLOSE_ALL_REQ_T tDataCloseAll;
tDataCloseAll.ulTimeout = 0; /* Bind socket to currently configured IP address */
sendPacketToTCP(0, TCPIP_DATA_TCP_UDP_CMD_CLOSE_ALL_REQ_SIZE, TCPIP_TCP_UDP_CMD_CLOSE_ALL_REQ, &tDataCloseAll, sizeof(TCPIP_DATA_TCP_UDP_CMD_CLOSE_ALL_REQ_T));
TLR_QUE_RETURNPACKET(pa_packetResult);//TODO: this shuld be sent back when all the sockets are closed
}
break;
/*In the following cases, the packets shouldn't be there, so they are release or return to the sender*/
case TCPIP_TCP_CMD_SEND_CNF:
case TCPIP_UDP_CMD_SEND_CNF:
case TCPIP_TCP_UDP_CMD_OPEN_CNF:
case TCPIP_TCP_UDP_CMD_CLOSE_CNF:
case TCPIP_TCP_CMD_CONNECT_CNF:
case TCPIP_TCP_UDP_CMD_CLOSE_ALL_CNF:
default: {
TLR_QUE_PACKETDONE(mForteResources.fortePoolHandle, mForteResources.forteQueueHandle, pa_packetResult);
}
}
}
}
UINT32 CrcXSocketInterface::getSocketIDFromPacket(FORTE_TCP_PACKET_T* pa_packet){
if(pa_packet->tHead.ulSrc == (UINT32)mForteResources.forteQueueHandle){
return pa_packet->tHead.ulDestId;
}else{
return pa_packet->tHead.ulSrcId;
}
}
RX_RESULT CrcXSocketInterface::sendData(TSocketDescriptor paSockD, char* paData, unsigned int paSize, bool paTCP, TUDPDestAddr *paDestAddr, void* pa_PacketData, int* pa_result){
RX_RESULT retVal = RX_OK;
*pa_result = -1;
if(scmInvalidSocketDescriptor != paSockD){
if(paSockD->accepted){
//Set not changing variables in the data
if(paTCP){
((TCPIP_DATA_TCP_CMD_SEND_REQ_T*) pa_PacketData)->ulOptions = TCP_SEND_OPT_PUSH; /* TCP_SEND_OPT_PUSH(0x00000001) Push flag: If set, the stack send the data immediate*/
}
else{
((TCPIP_DATA_UDP_CMD_SEND_REQ_T*) pa_PacketData)->ulIpAddr = paDestAddr->destAddress;
((TCPIP_DATA_UDP_CMD_SEND_REQ_T*) pa_PacketData)->ulPort = paDestAddr->destPort;
}
while(0 != paSize){
if(paTCP){
*pa_result = (paSize > 1460) ? 1460 : paSize;
TLR_MEMCPY(&(((TCPIP_DATA_TCP_CMD_SEND_REQ_T*) pa_PacketData)->abData[0]), paData, *pa_result);
retVal = sendPacketToTCP(paSockD->socketNumber, TCPIP_DATA_TCP_CMD_SEND_REQ_SIZE + *pa_result, TCPIP_TCP_CMD_SEND_REQ, pa_PacketData, sizeof(UINT32) + *pa_result);
}
else{
*pa_result = (paSize > 1472) ? 1472 : paSize;
TLR_MEMCPY(&(((TCPIP_DATA_UDP_CMD_SEND_REQ_T*) pa_PacketData)->abData[0]), paData, *pa_result);
retVal = sendPacketToTCP(paSockD->socketNumber, TCPIP_DATA_UDP_CMD_SEND_REQ_SIZE + *pa_result, TCPIP_UDP_CMD_SEND_REQ, pa_PacketData, sizeof(UINT32) * 3 + *pa_result);
}
if (RX_OK != retVal){
break;
}
/*if(RX_OK == retVal){
FORTE_TCP_PACKET_T* cnfPacket;
retVal = waitPacket((paTCP) ? TCPIP_TCP_CMD_SEND_CNF : TCPIP_UDP_CMD_SEND_CNF, &cnfPacket, RX_INFINITE);
if(RX_OK == retVal){
if(RX_OK != cnfPacket->tHead.ulSta){
//error sending packet
retVal = cnfPacket->tHead.ulSta;
}
else{
}
TLR_POOL_PACKET_RELEASE(mForteResources.fortePoolHandle, cnfPacket);
}
else{
//packet didn't arrive?
}
}
else{
//error sending packet
}
if(RX_OK != retVal){
*pa_result = -1;
DEVLOG_ERROR("TCP-Socket Send failed\n");
break;
}*/
paSize -= *pa_result;
paData += *pa_result;
}
}
else{
retVal = TLR_E_TCP_TASK_F_NOT_INITIALIZED;
DEVLOG_ERROR("TCP-Socket Send failed because socket was not accepted yet\n");
}
}
else{
retVal = RX_MEM_INVALID;
}
return retVal;
}
//TODO: Check if it's possible to write, using TLR_QUE_GET_LOAD which should be less than 128
int CrcXSocketInterface::sendDataOnTCP(TSocketDescriptor paSockD, const char* paData, unsigned int paSize){
int bytesSent = -1;
if(CrcXSocketInterface::getInstance().isInitialized()){
TCPIP_DATA_TCP_CMD_SEND_REQ_T tData;
CrcXSocketInterface::getInstance().sendData(paSockD, paData, paSize, true, 0, &tData, &bytesSent);
}
else{
DEVLOG_ERROR("CrcXSocketInterface is not initialized\n");
}
return bytesSent;
}
int CrcXSocketInterface::sendDataOnUDP(TSocketDescriptor paSockD, TUDPDestAddr *paDestAddr, char* paData, unsigned int paSize){
int bytesSent = -1;
if(CrcXSocketInterface::getInstance().isInitialized()){
TCPIP_DATA_UDP_CMD_SEND_REQ_T tData;
CrcXSocketInterface::getInstance().sendData(paSockD, paData, paSize, false, paDestAddr, &tData, &bytesSent);
}
else{
DEVLOG_ERROR("CrcXSocketInterface is not initialized\n");
}
return bytesSent;
}
RX_RESULT CrcXSocketInterface::accept(TSocketDescriptor pa_listeningSocketDesc, TSocketDescriptor& pa_destSocket){
RX_RESULT retVal = RX_OK;
if (mListeningSocketDescriptor == pa_listeningSocketDesc){
if (scmInvalidSocketDescriptor != pa_destSocket){
pa_destSocket->socketNumber = pa_listeningSocketDesc->socketNumber;
pa_destSocket->accepted = true;
pa_destSocket->port = pa_listeningSocketDesc->port;
//Open a new listening socket
retVal = CrcXSocketInterface::getInstance().openConnection(0, static_cast<unsigned short>(pa_listeningSocketDesc->port), true, true, 0, pa_listeningSocketDesc);
if(RX_OK != retVal){
DEVLOG_ERROR("Error %d opening socket\n", retVal);
}
}else{
retVal = RX_MEM_INVALID;
}
}
return retVal;
}
CrcXSocketInterface::TSocketDescriptor CrcXSocketInterface::acceptTCPConnection(TSocketDescriptor paListeningSockD){
if(CrcXSocketInterface::getInstance().isInitialized()){
TSocketDescriptor returnSocket = CrcXSocketInterface::getInstance().socketDescriptorAlloc();
if(0 != returnSocket){
RX_RESULT retVal = CrcXSocketInterface::getInstance().accept(paListeningSockD, returnSocket);
if(RX_OK == retVal){
return returnSocket;
}
else{
DEVLOG_ERROR("Error %d opening socket\n", retVal);
CrcXSocketInterface::getInstance().socketDescriptorDeAlloc(returnSocket);
}
}
else{
DEVLOG_ERROR("No enough memory to create a socket\n");
}
}
else{
DEVLOG_ERROR("CrcXSocketInterface is not initialized\n");
}
return 0;
}
CrcXSocketInterface::TSocketDescriptor CrcXSocketInterface::socketDescriptorAlloc(){
SSocketDescriptor* returnSocket = new SSocketDescriptor;
if (0 != returnSocket){
returnSocket->socketNumber = 0;
returnSocket->accepted = false;
returnSocket->port = 0;
returnSocket->packetReceived = 0;
returnSocket->deleteMe = true;
}
return returnSocket;
}
void CrcXSocketInterface::socketDescriptorDeAlloc(TSocketDescriptor pa_Socket){
if (scmInvalidSocketDescriptor != pa_Socket){
delete pa_Socket;
}
}
RX_RESULT CrcXSocketInterface::receiveData(TSocketDescriptor paSockD, bool , char* paData, unsigned int paBufSize, int* pa_receivedBytes){
RX_RESULT retVal = RX_OK;
*pa_receivedBytes = -1;
if(scmInvalidSocketDescriptor != paSockD && 0 != paSockD->packetReceived){
paSockD->deleteMe = true;
if(TCPIP_TCP_UDP_CMD_RECEIVE_STOP_IND == paSockD->packetReceived->tHead.ulCmd){
*pa_receivedBytes = 0;
}
else if(TCPIP_TCP_CMD_WAIT_CONNECT_CNF == paSockD->packetReceived->tHead.ulCmd){
}
else if(TCPIP_TCP_UDP_CMD_RECEIVE_IND == paSockD->packetReceived->tHead.ulCmd){
if(paBufSize >= (paSockD->packetReceived->tHead.ulLen - TCPIP_DATA_TCP_UDP_CMD_RECEIVE_IND_SIZE)){
TLR_MEMCPY(paData, &paSockD->packetReceived->tRcvInd.tData.abData[0], (paSockD->packetReceived->tHead.ulLen - TCPIP_DATA_TCP_UDP_CMD_RECEIVE_IND_SIZE));
*pa_receivedBytes = (paSockD->packetReceived->tHead.ulLen - TCPIP_DATA_TCP_UDP_CMD_RECEIVE_IND_SIZE);
}
else{ //move the data not copied to the beginning of the abData field and keep the packet.
UINT8 buffer[(paSockD->packetReceived->tHead.ulLen - TCPIP_DATA_TCP_UDP_CMD_RECEIVE_IND_SIZE) - paBufSize];
TLR_MEMCPY(paData, &paSockD->packetReceived->tRcvInd.tData.abData[0], paBufSize);
TLR_MEMCPY(&buffer[0], &paSockD->packetReceived->tRcvInd.tData.abData[paBufSize], (paSockD->packetReceived->tHead.ulLen - TCPIP_DATA_TCP_UDP_CMD_RECEIVE_IND_SIZE) - paBufSize);
TLR_MEMCPY(&paSockD->packetReceived->tRcvInd.tData.abData[0], &buffer[0], (paSockD->packetReceived->tHead.ulLen - TCPIP_DATA_TCP_UDP_CMD_RECEIVE_IND_SIZE) - paBufSize);
paSockD->packetReceived->tHead.ulLen -= paBufSize;
*pa_receivedBytes = paBufSize;
paSockD->deleteMe = false;
}
}
}
else{
retVal = RX_MEM_INVALID;
}
return retVal;
}
int CrcXSocketInterface::receiveDataFromTCP(TSocketDescriptor paSockD, char* paData, unsigned int paBufSize){
int receivedBytes = -1;
if(CrcXSocketInterface::getInstance().isInitialized()){
CrcXSocketInterface::getInstance().receiveData(paSockD, true, paData, paBufSize, &receivedBytes);
}
else{
DEVLOG_ERROR("CrcXSocketInterface is not initialized\n");
}
return receivedBytes;
}
int CrcXSocketInterface::receiveDataFromUDP(TSocketDescriptor paSockD, char* paData, unsigned int paBufSize){
int receivedBytes = -1;
if(CrcXSocketInterface::getInstance().isInitialized()){
CrcXSocketInterface::getInstance().receiveData(paSockD, false, paData, paBufSize, &receivedBytes);
}
else{
DEVLOG_ERROR("CrcXSocketInterface is not initialized\n");
}
return receivedBytes;
}