/* * Copyright (C) 2013 Texas Instruments Incorporated - http://www.ti.com/ * * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the * distribution. * * Neither the name of Texas Instruments Incorporated nor the names of * its contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ /* Standard includes */ #include #include #include #include #include #include #include #include /* Socket Includes */ #include "sockutils.h" #include "sockrmmsg.h" /* RM includes */ #include #include #define error_msg printf #define info_msg printf /* Socket timeout */ #define SERVER_SOCK_TIMEOUT_USEC (500) /* Seconds since last request to print resources */ #define SECONDS_SINCE_LAST_REQUEST (5) /* Error checking macro */ #define ERROR_CHECK(checkVal, resultVal, rmInstName, printMsg) \ if (resultVal != checkVal) { \ char errorMsgToPrint[] = printMsg; \ printf("%s : ", rmInstName); \ printf("%s with error code : %d\n", errorMsgToPrint, resultVal); \ exit(EXIT_FAILURE); \ } /* RM registered transport mapping structure */ typedef struct trans_map_entry_s { /* Registered RM transport handle */ Rm_TransportHandle trans_handle; /* Remote socket tied to the transport handle */ sock_name_t *remote_sock; /* Next entry in the transport map */ struct trans_map_entry_s *n; } trans_map_entry_t; /********************************************************************** ********************** Global Variables ****************************** **********************************************************************/ /* RM Server instance name (must match with RM Global Resource List (GRL) and policies */ char server_name[RM_NAME_MAX_CHARS] = "RM_Server"; sock_h server_sock = NULL; /********************************************************************** ************************** Server Functions ************************** **********************************************************************/ Rm_Packet *transportAlloc(Rm_AppTransportHandle appTransport, uint32_t pktSize, Rm_PacketHandle *pktHandle) { Rm_Packet *rm_pkt = NULL; rm_pkt = calloc(1, sizeof(*rm_pkt)); if (!rm_pkt) { error_msg("can't malloc for RM send message (err: %s)\n", strerror(errno)); return (NULL); } rm_pkt->pktLenBytes = pktSize; *pktHandle = rm_pkt; return(rm_pkt); } void transportFree (Rm_Packet *rm_pkt) { uint32_t pkt_size = rm_pkt->pktLenBytes; int32_t status; if (rm_pkt) { free (rm_pkt); } } int32_t transportSend (Rm_AppTransportHandle appTransport, Rm_PacketHandle pktHandle) { sock_name_t *client_sock_name = (sock_name_t *)appTransport; Rm_Packet *rm_pkt = (Rm_Packet *)pktHandle; if (sock_send(server_sock, (char *)rm_pkt, (int) rm_pkt->pktLenBytes, client_sock_name)) { error_msg("send data failed\n"); } return (0); } int main(int argc, char *argv[]) { int fd; time_t old_time; struct stat file_stat; char *grl_addr; char *linux_dtb_addr; char *policy_addr; Rm_Handle server_h; Rm_InitCfg rm_init_cfg; Rm_TransportCfg rm_trans_cfg; int32_t rm_result; trans_map_entry_t *trans_map = NULL; trans_map_entry_t *new_map_entry; trans_map_entry_t *map_index; int retval; int length = 0; sock_name_t serv_sock_name; sock_name_t client_sock_addr; Rm_Packet *rm_pkt = NULL; struct sockaddr_un client_addr; struct timeval tv = {0, SERVER_SOCK_TIMEOUT_USEC}; char rm_socket_name[] = RM_SERVER_SOCKET_NAME; if ((argc < 3) || (argc > 4)) { error_msg("Invalid number of input arguments\n"); exit(EXIT_FAILURE); } /* mmap the GRL */ fd = open(argv[1], O_RDONLY); if (fd == -1) { error_msg("Error opening GRL\n"); exit(EXIT_FAILURE); } /* Obtain file size */ if (fstat(fd, &file_stat) == -1) { error_msg("Error getting GRL size\n"); exit(EXIT_FAILURE); } grl_addr = mmap(NULL, file_stat.st_size, PROT_READ, MAP_PRIVATE, fd, 0); if (grl_addr == MAP_FAILED) { error_msg("mmap of GRL failed\n"); exit(EXIT_FAILURE); } /* mmap the Global Policy */ fd = open(argv[2], O_RDONLY); if (fd == -1) { error_msg("Error opening Global Policy\n"); exit(EXIT_FAILURE); } /* Obtain file size */ if (fstat(fd, &file_stat) == -1) { error_msg("Error getting Global Policy size\n"); exit(EXIT_FAILURE); } policy_addr = mmap(NULL, file_stat.st_size, PROT_READ, MAP_PRIVATE, fd, 0); if (policy_addr == MAP_FAILED) { error_msg("mmap of Global Policy failed\n"); exit(EXIT_FAILURE); } if (argc == 4){ /* mmap (Example) Linux DTB */ fd = open(argv[3], O_RDONLY); if (fd == -1) { error_msg("Error opening Linux DTB\n"); exit(EXIT_FAILURE); } /* Obtain file size */ if (fstat(fd, &file_stat) == -1) { error_msg("Error getting Linux DTB size\n"); exit(EXIT_FAILURE); } linux_dtb_addr = mmap(NULL, file_stat.st_size, PROT_READ, MAP_PRIVATE, fd, 0); if (linux_dtb_addr == MAP_FAILED) { error_msg("mmap of Linux DTB failed\n"); exit(EXIT_FAILURE); } } /* Create the Server instance */ memset(&rm_init_cfg, 0, sizeof(rm_init_cfg)); rm_init_cfg.instName = server_name; rm_init_cfg.instType = Rm_instType_SERVER; rm_init_cfg.instCfg.serverCfg.globalResourceList = (void *)grl_addr; rm_init_cfg.instCfg.serverCfg.linuxDtb = (void *)linux_dtb_addr; rm_init_cfg.instCfg.serverCfg.globalPolicy = (void *)policy_addr; server_h = Rm_init(&rm_init_cfg, &rm_result); ERROR_CHECK(RM_OK, rm_result, server_name, "Initialization failed\n"); printf("\n\nInitialized %s\n\n", server_name); Rm_resourceStatus(server_h, 1); serv_sock_name.type = sock_name_e; serv_sock_name.s.name = rm_socket_name; server_sock = sock_open (&serv_sock_name); old_time = time(NULL); info_msg("Begin waiting for messages from Clients\n"); while(1) { if ((time(NULL) - old_time) > SECONDS_SINCE_LAST_REQUEST) { Rm_resourceStatus(server_h, 1); old_time = time(NULL); } retval = sock_wait(server_sock, &length, &tv, -1); if (retval == -2) { goto loop_continue; } else if (retval < 0) { error_msg("Error in reading from socket\n"); goto loop_continue; } if (length < sizeof(rm_pkt)) { error_msg("invalid RM message length %d\n", length); goto loop_continue; } rm_pkt = calloc(1, length); if (!rm_pkt) { error_msg("can't malloc for recv'd RM message (err: %s)\n", strerror(errno)); goto loop_continue; } client_sock_addr.type = sock_addr_e; client_sock_addr.s.addr = &client_addr; retval = sock_recv(server_sock, (char *)rm_pkt, length, &client_sock_addr); if (retval != length) { error_msg("recv RM pkt failed from socket, received = %d, expected = %d\n", retval, length); goto loop_continue; } info_msg("received RM pkt of size %d bytes from %s\n", length, client_sock_addr.s.addr->sun_path); map_index = trans_map; while(map_index != NULL) { if (strncmp(map_index->remote_sock->s.addr->sun_path, client_addr.sun_path, sizeof(client_addr.sun_path)) == 0) { break; } map_index = map_index->n; } if (!map_index) { new_map_entry = calloc(1, sizeof(*new_map_entry)); new_map_entry->remote_sock = calloc(1, sizeof(sock_name_t)); new_map_entry->remote_sock->s.addr = calloc(1, sizeof(struct sockaddr_un)); new_map_entry->remote_sock->type = sock_addr_e; memcpy(new_map_entry->remote_sock->s.addr, &client_addr, sizeof(struct sockaddr_un)); /* Register the Client with the Server instance */ rm_trans_cfg.rmHandle = server_h; rm_trans_cfg.appTransportHandle = (Rm_AppTransportHandle)new_map_entry->remote_sock; rm_trans_cfg.remoteInstType = Rm_instType_CLIENT; rm_trans_cfg.transportCallouts.rmAllocPkt = transportAlloc; rm_trans_cfg.transportCallouts.rmSendPkt = transportSend; new_map_entry->trans_handle = Rm_transportRegister(&rm_trans_cfg, &rm_result); new_map_entry->n = NULL; if (trans_map == NULL) { trans_map = new_map_entry; } else { map_index = trans_map; while(map_index->n != NULL) { map_index = map_index->n; } map_index->n = new_map_entry; } map_index = new_map_entry; } /* Provide packet to RM Server for processing */ if (rm_result = Rm_receivePacket(map_index->trans_handle, rm_pkt)) { printf("RM failed to process received packet: %d\n", rm_result); } transportFree(rm_pkt); old_time = time(NULL); loop_continue: /* Cleanups */ length = 0; memset(&client_sock_addr, 0, sizeof(sock_name_t)); memset(&client_addr, 0, sizeof(struct sockaddr_un)); } }