I have a embedded app running on an STM32F107, which opens 4 TCP Server sockets and handles the incoming and outgoing data. This works fine, and has been in the field for a while.
I have been asked to add the ability to connect to these boxes from other boxes rather than from a browser. I tried using the remaining 4 sockets to open client connections. This is always returning a timeout. Here is the relevant code:
Server setup is via this routine:
int32_t Process_TCP(uint8_t sn, void* ring_in_buf, void* ring_out_buf, uint16_t port)
{
int32_t ret;
uint16_t size = 0, sentsize=0;
uint8_t* buf = gETH_RECV_BUF;
#ifdef _ETHERNET_DEBUG_
uint8_t destip[4];
uint16_t destport;
#endif
switch(getSn_SR(sn))
{
case SOCK_ESTABLISHED :
if(getSn_IR(sn) & Sn_IR_CON){
#ifdef _ETHERNET_DEBUG_
getSn_DIPR(sn, destip);
destport = getSn_DPORT(sn);
myprintf("%d:Connected - %d.%d.%d.%d : %d\r\n",sn, destip[0], destip[1], destip[2], destip[3], destport);
#endif
setSn_IR(sn,Sn_IR_CON);
}
if((size = getSn_RX_RSR(sn)) > 0){
#ifdef _ETHERNET_DEBUG_
myprintf("%d:Received - %d bytes\r\n",sn, size);
#endif
if(size > ETH_RECV_BUF_SIZE) size = ETH_RECV_BUF_SIZE;
if(size > RingBuffer_GetFree((RINGBUFF_T*)ring_in_buf))
size = RingBuffer_GetFree((RINGBUFF_T*)ring_in_buf);
ret = recv(sn, buf, size);
if(ret <= 0)
return ret;
RingBuffer_InsertMult((RINGBUFF_T*)ring_in_buf, buf, size);
}
size = RingBuffer_GetCount((RINGBUFF_T*)ring_out_buf);
if(size > ETH_RECV_BUF_SIZE) size = ETH_RECV_BUF_SIZE;
size = RingBuffer_PopMultNoRemove((RINGBUFF_T*)ring_out_buf, buf, size);
sentsize = 0;
if(size > 0)
{
if (1)
ret = send(sn,buf+sentsize,size-sentsize);
if(ret < 0){
close(sn);
return ret;
}
sentsize += ret; // Don't care SOCKERR_BUSY, because it is zero.
}
if(sentsize > 0){
RingBuffer_RemoveMult((RINGBUFF_T*)ring_out_buf, sentsize);
#ifdef _ETHERNET_DEBUG_
myprintf("%d:Sent - %d bytes\r\n",sn, sentsize);
#endif
}
return 0;
case SOCK_CLOSE_WAIT :
#ifdef _ETHERNET_DEBUG_
myprintf("%d:CloseWait\r\n",sn);
#endif
if((ret=disconnect(sn)) != SOCK_OK)
return ret;
#ifdef _ETHERNET_DEBUG_
myprintf("%d:Socket closed\r\n",sn);
#endif
break;
case SOCK_INIT :
#ifdef _ETHERNET_DEBUG_
myprintf("%d:Listen, TCP server, port [%d]\r\n",sn, port);
#endif
if( (ret = listen(sn)) != SOCK_OK)
return ret;
break;
case SOCK_CLOSED:
#ifdef _ETHERNET_DEBUG_
myprintf("%d:TCP server start\r\n",sn);
#endif
if((ret=socket(sn, Sn_MR_TCP, port, 0x00)) != sn)
return ret;
#ifdef _ETHERNET_DEBUG_
myprintf("%d:Socket opened\r\n",sn);
#endif
break;
default:
break;
}
return 1;
}
This works fine, bringing the socket from closed to listening to sending and receiving.
When I try to open a client, it fails. Here is the code (explanation following the code):
void ClientSockets(uint8_t sn2, void* ring_out_buf)
{
uint16_t size = 0, sentsize=0;
uint8_t* buf = gETH_RECV_BUF;
uint8_t destip[4];
uint16_t port = ports[sn2];
int32_t ret;
size = RingBuffer_GetCount((RINGBUFF_T*)ring_out_buf);
if(size > ETH_RECV_BUF_SIZE) size = ETH_RECV_BUF_SIZE;
size = RingBuffer_PopMultNoRemove((RINGBUFF_T*)ring_out_buf, buf, size);
sentsize = 0;
while(size != sentsize)
if(size > 0)
{
uint8_t res;
if (!SocketMade[sn2])
{
getSIPR(destip); // get own IP address
destip[3] ^= 1; // this will be the partner. Connect to partner as client
uint8_t ss = getSn_SR(sn2);
if (ss == SOCK_CLOSED)
{
res = socket(sn2, Sn_MR_TCP, 0xC000, 0x00);
#ifdef _ETHERNET_DEBUG_
myprintf("%d:Opened socket %d on port %d\r\n",sn2, sn2, port);
#endif
}
if (res == sn2)
{
res = connect(sn2,destip,port);
}
if (res == SOCK_OK)
{
#ifdef _ETHERNET_DEBUG_
myprintf("Connection succeeded\r\n");
#endif
SocketMade[sn2] = true;
} else
{
#ifdef _ETHERNET_DEBUG_
myprintf("Connection failed error code = %x\r\n", res);
#endif
}
ret = send(sn2,buf+sentsize,size-sentsize);
if(ret < 0)
{
close(sn2);
return;
}
sentsize += ret; // Don't care SOCKERR_BUSY, because it is zero.
}
if(sentsize > 0)
{
RingBuffer_RemoveMult((RINGBUFF_T*)ring_out_buf, sentsize);
}
#ifdef _ETHERNET_DEBUG_
myprintf("%d:Sent - %d bytes\r\n",sn2, sentsize);
#endif
return;
}
}
The IP address being sent to is always to an IP address which “pairs” one box with another. For example, 192.168.1.90 will always try to talk to 192.168.1.91 and vice-versa. They will open two sockets to converse between them . While debugging, I have removed the line
" destip[3] ^= 1; // this will be the partner. Connect to partner as client"
thus trying to send to myself.
The line which opens the socket has gone through several forms, this is the last one I tried:
res = socket(sn2, Sn_MR_TCP, 0xC000, 0x00);
sn2 is usually 4 in my case, sometimes 5. Sockets 0-3 are used by the 4 Server sockets. 4 and 5 are trying to send to sockets 1 and 2 (Socket 0 is for control, socket 3 is currently not used). It, like the server sockets are TCP, I have tried both 0xc000 (all ports) or setting a specific port here, and 0 for the flags, as I want a blocking socket.
This seems to always succeed, with the value of res being sn2. However, the call to
res = connect(sn2,destip,port);
fails always, with 0xF3 (timeout) as the return code.
I can connect to the server socket from, say, TeraTerm, so I know the problem is with the client socket.