I'm writing the CWMP client for TR-069 Server. I'm basing my client's code on this topic (there's also a source code link in the topic)
CWMP CPE (Client) implementation
I have encountered a weird issue that recv() doesn't read the data sent! I've checked the data I'm sending and it's correct. I've installed a Wireshark on a server side and it captures the packets with the same very data client sent. I'm digging into TR-069 ACS source code and I've tried to change the listening socket mode to NON_BLOCK - no use.
Socket definition source:
int make_socket(unsigned int port)
{
int sock;
struct sockaddr_in name;
sock = socket(PF_INET, SOCK_STREAM, 0);
if (sock < 0)
{
logtr("ACS Server:", "Can not create socket", ERROR, conferr);
exit(EXIT_FAILURE);
}
name.sin_family = AF_INET;
name.sin_port = htons(port);
name.sin_addr.s_addr = htonl(INADDR_ANY);
if (bind(sock, (struct sockaddr *) &name, sizeof(name)) < 0)
{
// perror ("bind");
logtr("ACS Server:", "Can not bind ", ERROR, conferr);
exit(EXIT_FAILURE);
}
return sock;
}
Processing:
void connection(int sock)
{
if (listen(sock, 10) < 0)
{
//perror ("listen");
logtr("ACS Server:", "Can not listen socket", ERROR, conferr);
exit(EXIT_FAILURE);
}
FD_ZERO(&active_fd_set);
FD_SET(sock, &active_fd_set);
// int status = 3;
while (1)
{
timeout.tv_sec = 10;
timeout.tv_usec = 0;
read_fd_set = active_fd_set;
if (select(FD_SETSIZE + 1, &read_fd_set, NULL, NULL, &timeout) < 0)
{
//perror ("Select");
logtr("ACS Server:", "Can not select socket", ERROR, conferr);
exit(EXIT_FAILURE);
}
for (i = 0; i <= FD_SETSIZE; ++i)
if (FD_ISSET(i, &read_fd_set))
{
if (i == sock)
{
size = sizeof(clientname);
newfd1 = accept(sock, (struct sockaddr *) &clientname, &size);
if (newfd1 < 0)
{
//perror ("accept");
logtr("ACS Server:", "Can not accept socket", ERROR, conferr);
exit(EXIT_FAILURE);
}
/*
fprintf (stderr,"Server: connect from host %s, port %i\n",
(char*)inet_ntoa(clientname.sin_addr),
ntohs(clientname.sin_port));
*/
char info[128];
sprintf(info, "Server: connect from host %s, port %i\n",
(char*) inet_ntoa(clientname.sin_addr),
ntohs(clientname.sin_port));
trace(info);
FD_SET(newfd1, &active_fd_set);
memset(fileCBuff[i].fileContBuff, 0,
sizeof(fileCBuff[i].fileContBuff));
out_get_param_value0 = 0;
out_get_param_value1 = 0;
c_reboot = 0;
c_download = 0;
noSqlError = 0;
}
else
{
send_recive_socket(i);
}
}
}
}
And finally where it fails:
void send_recive_socket( int i )
{
if( read_from_client(i) < 0 )
{
CLOSECONNECTION:
close(i);
FD_CLR (i,&active_fd_set);
//printf("\nClose connection ......\n");\
}
else
{
...
int read_from_client( int fileDesc )
{
int nbytes;
memset( buffer,0,READ_MSG_SIZE );
nbytes = recv(fileDesc, buffer, READ_MSG_SIZE,0);//reade data from client
if( nbytes <= 0 )
{
logtr("ACS Server:","Wait Data from TR069 Client ", ERROR, conferr);
// printf("\nNo data from client");
// perror ("Read ...");
return -1;
}
else
{
...
I suppose this is the place because whenever I halt the client's execution the log receives
ACS Server: Wait Data from TR069 Client ERROR servHelper.c read_from_client
recv
may return -1
with errno
set to EINTR
when a signal arrives. This is a transient failure and doesn't indicate any problem with your socket connection. You probably want to ignore this error and try calling recv
again. The easiest way to do this on Linux is to use the TEMP_FAILURE_RETRY macro
nbytes = TEMP_FAILURE_RETRY(recv(fileDesc, buffer, READ_MSG_SIZE,0));
This will call recv
repeatedly until it returns something other than nbytes==-1 && errno==EINTR