in common/recipes-core/asd/files/daemon/socket_main.c [1295:1598]
int main(int argc, char **argv) {
int pollfd_cnt;
struct pollfd poll_fds[CLIENT_FD_INDEX+MAX_SESSIONS] = {{0}};
struct spi_message s_message = {{0}};
int data_size = 0;
SocketReadState read_state = SOCKET_READ_STATE_INITIAL;
ssize_t read_index = 0;
init_logging_map();
remote_logging_config.logging_level = IPC_LogType_Off;
remote_logging_config.logging_stream = 0;
print_version();
process_command_line(argc, argv);
#ifdef CONFIG_JTAG_MSG_FLOW
int status = JTAG_set_device(cpu_fru, g_dev_id);
if (status != ST_OK) {
return ST_ERR;
}
#endif
if (check_dup_process(cpu_fru) != 0) {
ASD_log(LogType_Error,
"Another ASD instance is running for fru:%d", cpu_fru);
return ST_ERR;
}
jtag_handler = SoftwareJTAGHandler(cpu_fru);
if (!jtag_handler) {
ASD_log(LogType_Error, "Failed to create JTAGHandler");
exitAll();
return 1;
}
target_control_handle = TargetHandler(cpu_fru, &TargetHandlerCallback);
if (!target_control_handle) {
ASD_log(LogType_Error, "Failed to create TargetHandler");
exitAll();
return 1;
}
extnet_init(sg_options.e_extnet_type, EXTNET_DATA, MAX_SESSIONS);
auth_init(sg_options.e_auth_type, NULL);
session_init();
syslog(LOG_WARNING, "ASD daemon launch, fru %d, port %d\t"
", num_buf %d\n",
cpu_fru, sg_options.n_port_number, num_in_flight_buffers_to_use);
out_msg.buffer = (unsigned char*) malloc(MAX_DATA_SIZE);
if (!out_msg.buffer) {
ASD_log(LogType_Error, "Failed to allocate out_msg.buffer");
exitAll();
return 1;
}
s_message.buffer = (unsigned char*) malloc(MAX_DATA_SIZE);
if (!s_message.buffer) {
ASD_log(LogType_Error, "Failed to allocate s_message.buffer");
exitAll();
return 1;
}
send_buffer = (char *) malloc(MAX_DATA_SIZE);
if (!send_buffer) {
ASD_log(LogType_Error, "Failed to create message buffer for socket write.");
if(s_message.buffer)
free(s_message.buffer);
exitAll();
return 1;
}
event_fd = eventfd(0, O_NONBLOCK);
if (event_fd == -1) {
ASD_log(LogType_Error, "Could not setup event file descriptor.");
if (s_message.buffer)
free(s_message.buffer);
exitAll();
return 1;
}
if (extnet_open_external_socket(NULL, sg_options.n_port_number, &host_fd) != ST_OK) {
ASD_log(LogType_Error, "Could not open the external socket");
if(s_message.buffer)
free(s_message.buffer);
exitAll();
return 1;
}
poll_fds[EVENT_FD_INDEX].fd = event_fd;
poll_fds[EVENT_FD_INDEX].events = POLLIN;
poll_fds[HOST_FD_INDEX].fd = host_fd;
poll_fds[HOST_FD_INDEX].events = POLLIN;
while (1) {
session_fdarr_t session_fds = {-1};
int n_clients = 0, i;
int n_timeout = -1;
if (session_getfds(session_fds, &n_clients, &n_timeout) != ST_OK) {
ASD_log(LogType_Debug, "Cannot get client session fds!");
if (s_message.buffer)
free(s_message.buffer);
exitAll();
return 1;
}
for (i=0; i<n_clients; i++) {
poll_fds[CLIENT_FD_INDEX+i].fd = session_fds[i];
poll_fds[CLIENT_FD_INDEX+i].events = POLLIN;
poll_fds[CLIENT_FD_INDEX+i].revents = 0;
}
pollfd_cnt = CLIENT_FD_INDEX + n_clients;
if (poll(poll_fds, pollfd_cnt, n_timeout) == -1) {
break;
}
if (poll_fds[EVENT_FD_INDEX].revents & POLLIN) {
ASD_log(LogType_Debug, "Internal event received.");
uint64_t value;
int i = read(event_fd, &value, sizeof(value));
if (i != sizeof(value)) {
ASD_log(LogType_Error, "Error occurred receiving internal event.");
} else {
if (value == CLOSE_CLIENT_EVENT) {
extnet_conn_t authd_conn;
ASD_log(LogType_Debug, "Internal client close event received.");
if (session_get_authenticated_conn(&authd_conn) != ST_OK) {
ASD_log(LogType_Error, "Authorized client already disconnected.");
} else {
ASD_log(LogType_Error, "Remote JTAG disabled, disconnecting client.");
if (on_client_disconnect() != ST_OK) {
ASD_log(LogType_Error, "Client disconnect cleanup failed.");
}
session_close(&authd_conn);
continue;
}
}
}
}
if (poll_fds[HOST_FD_INDEX].revents & POLLIN) {
ASD_log(LogType_Debug, "Client Connecting.");
extnet_conn_t new_extconn;
if (extnet_accept_connection(host_fd, &new_extconn) != ST_OK) {
ASD_log(LogType_Error, "Failed to accept incoming connection.");
continue;
}
// Create a session for the new connection
if (session_open(&new_extconn, SOCKET_READ_STATE_INITIAL) != ST_OK) {
ASD_log(LogType_Error,
"Unable to add session for new connection fd %d",
new_extconn.sockfd);
extnet_close_client(&new_extconn);
continue;
}
if (sg_options.e_auth_type == AUTH_HDLR_NONE) {
/* Special case where auth is not required. Stuff fd to the
* poll_fds array to immediately process the connection.
* Otherwise it may be timed out as unathenticated. */
if (CLIENT_FD_INDEX+n_clients < sizeof(poll_fds)/sizeof(poll_fds[0])) {
poll_fds[CLIENT_FD_INDEX+n_clients].fd = new_extconn.sockfd;
poll_fds[CLIENT_FD_INDEX+n_clients].revents |= POLLIN;
n_clients++;
}
}
}
session_close_expired_unauth();
for (i=0; i<n_clients; i++) {
if (poll_fds[CLIENT_FD_INDEX+i].revents & POLLIN) {
extnet_conn_t *p_extconn;
p_extconn = session_lookup_conn(poll_fds[CLIENT_FD_INDEX+i].fd);
if (!p_extconn) {
ASD_log(LogType_Error, "Session for fd %d vanished!",
poll_fds[CLIENT_FD_INDEX+i].fd);
continue;
}
if (session_already_authenticated(p_extconn) != ST_OK) {
// Authenticate the client
if (auth_client_handshake(p_extconn) != ST_OK) {
session_close(p_extconn);
} else if (session_auth_complete(p_extconn) != ST_OK) {
session_close(p_extconn);
} else {
ASD_log(LogType_Debug,
"Session on fd %d now authenticated",
p_extconn->sockfd);
if (on_client_connect(p_extconn) != ST_OK) {
ASD_log(LogType_Error, "Connection attempt failed.");
if (on_client_disconnect() != ST_OK) {
ASD_log(LogType_Error, "Client disconnect cleanup failed.");
}
session_close(p_extconn);
continue;
}
ASD_log(LogType_Error,
"Authenticated client connected on fd %d.",
p_extconn->sockfd);
syslog(LOG_WARNING, "Authenticated client connected to fru %d (port %d) on fd %d\n",
cpu_fru, sg_options.n_port_number, p_extconn->sockfd);
}
continue;
}
if (session_get_data(p_extconn, &read_state) != ST_OK) {
ASD_log(LogType_Error, "Cannot get session data for fd %d!",
p_extconn->sockfd);
session_close(p_extconn);
continue;
}
switch (read_state) {
case SOCKET_READ_STATE_INITIAL: {
memset(&s_message.header, 0, sizeof(struct message_header));
memset(s_message.buffer, 0, MAX_DATA_SIZE);
read_state = SOCKET_READ_STATE_HEADER;
session_set_data(p_extconn, read_state);
read_index = 0;
// do not 'break' here, continue on and read the header
}
case SOCKET_READ_STATE_HEADER: {
ssize_t cnt = extnet_recv(p_extconn,
(void*)(&(s_message.header)+read_index),
sizeof(s_message.header)-read_index);
if (cnt < 1) {
if(cnt == 0) {
ASD_log(LogType_Error, "Client disconnected");
syslog(LOG_WARNING, "Client disconnected from fru %d (port %d)\n",
cpu_fru, sg_options.n_port_number);
} else {
ASD_log(LogType_Error, "Socket header receive failed: %d", cnt);
}
if (on_client_disconnect() != ST_OK) {
ASD_log(LogType_Error, "Client disconnect cleanup failed.");
}
session_close(p_extconn);
} else if ((cnt + read_index) == sizeof(s_message.header)) {
data_size = get_message_size(&s_message);
if (data_size == -1) {
ASD_log(LogType_Error, "Failed to read header size.");
send_error_message(p_extconn, &s_message, ASD_UNKNOWN_ERROR);
if (on_client_disconnect() != ST_OK) {
ASD_log(LogType_Error, "Client disconnect cleanup failed.");
}
session_close(p_extconn);
} else if (data_size > 0) {
read_state = SOCKET_READ_STATE_BUFFER;
session_set_data(p_extconn, read_state);
read_index = 0;
} else {
// we have finished reading a message and there is no buffer to read.
// Set back to initial state for next packet and process message.
read_state = SOCKET_READ_STATE_INITIAL;
session_set_data(p_extconn, read_state);
on_message_received(p_extconn, s_message, data_size);
}
} else {
read_index += cnt;
ASD_log(LogType_Debug, "Socket header read not complete (%d of %d)",
read_index, sizeof(s_message.header));
}
break;
}
case SOCKET_READ_STATE_BUFFER: {
ssize_t cnt = extnet_recv(p_extconn, (void*)(s_message.buffer+read_index),
data_size-read_index);
if (cnt < 1) {
if(cnt == 0)
ASD_log(LogType_Error, "Client disconnected");
else
ASD_log(LogType_Error, "Socket buffer receive failed: %d", cnt);
send_error_message(p_extconn, &s_message, ASD_UNKNOWN_ERROR);
if (on_client_disconnect() != ST_OK) {
ASD_log(LogType_Error, "Client disconnect cleanup failed.");
}
session_close(p_extconn);
} else if ((cnt + read_index) == data_size) {
// we have finished reading a packet. Set back to initial state for next packet.
read_state = SOCKET_READ_STATE_INITIAL;
session_set_data(p_extconn, read_state);
on_message_received(p_extconn, s_message, data_size);
} else {
read_index += cnt;
ASD_log(LogType_Debug, "Socket header read not complete (%d of %d)",
read_index, data_size);
}
break;
}
default:
{
ASD_log(LogType_Error, "Invalid socket read state: %d", read_state);
}
}
}
}
}
if(s_message.buffer)
free(s_message.buffer);
exitAll();
ASD_log(LogType_Error, "ASD server closing.");
return 0;
}