in syncd/MdioIpcServer.cpp [199:441]
int MdioIpcServer::syncd_ipc_task_main()
{
SWSS_LOG_ENTER();
int i;
int fd;
int len;
int ret;
int sock_srv;
int sock_cli;
int sock_max;
syncd_mdio_ipc_conn_t conn[MDIO_CONN_MAX];
struct sockaddr_un addr;
char path[64];
fd_set rfds;
char cmd[SYNCD_IPC_BUFF_SIZE], resp[SYNCD_IPC_BUFF_SIZE], *argv[64], *save;
int argc = 0;
strcpy(path, SYNCD_IPC_SOCK_SYNCD);
fd = open(path, O_DIRECTORY);
if (fd < 0)
{
SWSS_LOG_ERROR("Unable to open the directory %s for IPC\n", path);
return errno;
}
sock_srv = socket(AF_UNIX, SOCK_STREAM, 0);
if (sock_srv < 0)
{
SWSS_LOG_ERROR("socket() returns %d", errno);
return errno;
}
/***************************************/
/* Set up the UNIX socket address */
/* by using AF_UNIX for the family and */
/* giving it a file path to bind to. */
/* */
/* Delete the file so the bind will */
/* succeed, then bind to that file. */
/***************************************/
memset(&addr, 0, sizeof(addr));
addr.sun_family = AF_UNIX;
sprintf(addr.sun_path, "%s/%s.srv", path, SYNCD_IPC_SOCK_FILE);
unlink(addr.sun_path);
if (bind(sock_srv, (struct sockaddr *)&addr, sizeof(addr)) < 0)
{
SWSS_LOG_ERROR("bind() returns %d", errno);
close(sock_srv);
return errno;
}
/* Listen for the upcoming client sockets */
if (listen(sock_srv, MDIO_CONN_MAX) < 0)
{
SWSS_LOG_ERROR("listen() returns %d", errno);
unlink(addr.sun_path);
close(sock_srv);
return errno;
}
SWSS_LOG_NOTICE("IPC service is online\n");
memset(conn, 0, sizeof(conn));
while (m_taskAlive)
{
time_t now;
struct timeval timeout;
/* garbage collection */
now = time(NULL);
for (i = 0; i < MDIO_CONN_MAX; ++i)
{
if ((conn[i].fd > 0) && (conn[i].timeout < now))
{
SWSS_LOG_NOTICE("socket %d: connection timeout\n", conn[i].fd);
close(conn[i].fd);
conn[i].fd = 0;
conn[i].timeout = 0;
}
}
/* reset read file descriptors */
FD_ZERO(&rfds);
FD_SET(sock_srv, &rfds);
sock_max = sock_srv;
for (i = 0; i < MDIO_CONN_MAX; ++i)
{
if (conn[i].fd <= 0)
{
continue;
}
FD_SET(conn[i].fd, &rfds);
if (sock_max < conn[i].fd)
{
sock_max = conn[i].fd;
}
}
/* monitor the socket descriptors */
timeout.tv_sec = 1;
timeout.tv_usec = 0;
ret = select(sock_max + 1, &rfds, NULL, NULL, &timeout);
if (ret == 0)
{
continue;
}
else if (ret < 0)
{
if (errno == EINTR)
{
continue;
}
else
{
SWSS_LOG_ERROR("select() returns %d", errno);
break;
}
}
/* Accept the new connection */
now = time(NULL);
if (FD_ISSET(sock_srv, &rfds))
{
sock_cli = accept(sock_srv, NULL, NULL);
if (sock_cli <= 0)
{
SWSS_LOG_ERROR("accept() returns %d", errno);
continue;
}
for (i = 0; i < MDIO_CONN_MAX; ++i)
{
if (conn[i].fd <= 0)
{
break;
}
}
if (i < MDIO_CONN_MAX)
{
conn[i].fd = sock_cli;
conn[i].timeout = now + MDIO_SERVER_TIMEOUT;
}
else
{
SWSS_LOG_ERROR("too many connections!");
close(sock_cli);
}
}
/* Handle the client requests */
for (i = 0; i < MDIO_CONN_MAX; ++i)
{
sai_status_t rc = SAI_STATUS_NOT_SUPPORTED;
sock_cli = conn[i].fd;
if ((sock_cli <= 0) || !FD_ISSET(sock_cli, &rfds))
{
continue;
}
/* get the command message */
len = (int)recv(sock_cli, (void *)cmd, sizeof(cmd) - 1, 0);
if (len <= 0)
{
close(sock_cli);
conn[i].fd = 0;
conn[i].timeout = 0;
continue;
}
cmd[len] = 0;
/* tokenize the command string */
argc = 0;
std::string str(cmd);
boost::algorithm::trim(str);
boost::algorithm::to_lower(str);
std::vector<char>v(str.size()+1);
memcpy( &v.front(), str.c_str(), str.size() + 1 );
argv[argc++] = strtok_r(v.data(), " \t\r\n", &save);
while (argc < COUNTOF(argv))
{
argv[argc] = strtok_r(NULL, " \t\r\n", &save);
if (argv[argc] == NULL)
break;
++argc;
}
/* command dispatch */
resp[0] = 0;
rc = SAI_STATUS_NOT_SUPPORTED;
if (argv[0] == NULL)
{
rc = SAI_STATUS_NOT_SUPPORTED;
}
else if (strcmp("mdio", argv[0]) == 0)
{
rc = MdioIpcServer::syncd_ipc_cmd_mdio(resp, argc, argv);
if (rc != 0)
{
SWSS_LOG_ERROR("command %s returns %d", cmd, rc);
}
}
else if (strcmp("mdio-cl22", argv[0]) == 0)
{
rc = MdioIpcServer::syncd_ipc_cmd_mdio_cl22(resp, argc, argv);
if (rc != 0)
{
SWSS_LOG_ERROR("command %s returns %d", cmd, rc);
}
}
/* build the error message */
if (rc != SAI_STATUS_SUCCESS)
{
sprintf(resp, "%d\n", rc);
}
/* send out the response */
len = (int)strlen(resp);
if (send(sock_cli, resp, len, 0) < len)
{
SWSS_LOG_ERROR("send() returns %d", errno);
}
/* update the connection timeout counter */
conn[i].timeout = time(NULL) + MDIO_SERVER_TIMEOUT;
}
}
/* close socket descriptors */
for (i = 0; i < MDIO_CONN_MAX; ++i)
{
if (conn[i].fd <= 0)
{
continue;
}
close(conn[i].fd);
}
close(sock_srv);
unlink(addr.sun_path);
return errno;
}