int main()

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;
}