Skip to content
Snippets Groups Projects
plugin_agent.c 9.31 KiB
Newer Older
/*
 * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The OpenAirInterface Software Alliance licenses this file to You under
 * the OAI Public License, Version 1.1  (the "License"); you may not use this file
 * except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.openairinterface.org/?page_id=698
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *-------------------------------------------------------------------------------
 * For more information about the OpenAirInterface (OAI) Software Alliance:
 *      contact@openairinterface.org
 */



#include "plugin_agent.h"

#include "util/alg_ds/alg/alg.h"
#include "util/alg_ds/ds/lock_guard/lock_guard.h"
#include "util/compare.h"
#include "util/conf_file.h"
#include <assert.h>

#include <arpa/inet.h>
#include <dlfcn.h>
#include <dirent.h>

#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/stat.h>
#include <unistd.h>

/*
static
void* rx_plugin_agent(void* p_v)
{
  plugin_ag_t* p = (plugin_ag_t*)p_v;
  const int port = 8080;
  char buf[128] = {0};

  p->sockfd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);

  assert(p->sockfd != -1 && "Error creating socket");

  struct sockaddr_in serv_addr = {.sin_family = AF_INET,
    .sin_port = htons(port),
    .sin_addr.s_addr = INADDR_ANY};

  int rc = bind(p->sockfd,(struct sockaddr *)&serv_addr,sizeof(serv_addr));
  assert(rc != -1 && "Error while binding. Address already in use?");



  while(true){
    struct sockaddr_in cli_addr;
    socklen_t len = sizeof(cli_addr); 

    // Receive file name
    rc = recvfrom(p->sockfd, buf, 128, 0, (struct sockaddr *)&cli_addr,&len);
    if(p->flag_shutdown) 
      break;
    assert(rc > -1 && rc < 128 && "Buffer overflow");

    printf("Name of the file = %s\n",buf);

    // Receive file size
    int size = 0;
    rc = recvfrom(p->sockfd, &size, sizeof(int), 0, (struct sockaddr *)&cli_addr, &len);
    if(p->flag_shutdown) 
      break;
    assert(rc == sizeof(int));

    printf("Size of the file = %d\n",size);

    char* data = calloc(1, size);
    assert(data != NULL && "Memory exhausted!");
    // Receive file itself 
    rc = recvfrom(p->sockfd,data,size,0,(struct sockaddr *)&cli_addr, &len);
    if(p->flag_shutdown) 
      break;
    assert(rc == size);

    // Save file
    FILE* fptr = fopen(buf, "wb");
    rc = fwrite(data,size,1,fptr);
    assert(rc == 1);
    free(data);
    fclose(fptr);

    // Change the file permissions as it is a shared object
    int const mode = strtol("0755", 0, 8);
    rc = chmod(buf, mode);
    assert(rc > -1);
    if(p->flag_shutdown) 
      break;

    char full_path[PATH_MAX] = {0};
    char* ptr = getcwd(full_path, PATH_MAX);
    ptr[strlen(ptr)] = '/';
    memcpy(full_path + strlen(full_path), buf, strlen(buf));

     

    // Load the plugin in the agent
    load_plugin_ag(p, full_path);
    printf("File received and loaded\n");

  }
  printf("Closing the socket\n");
  close(p->sockfd);
  return NULL;
}
*/

static inline
void free_sm_agent(void* key, void* value)
{
  assert(key != NULL);
  assert(value != NULL);

  sm_agent_t* sm = (sm_agent_t*)value;

  void* handle = sm->handle;
  sm->free_sm(sm);

  if(handle != NULL)
      dlclose(handle);
}

static inline
void check_dl_error(void)
{
  const char* error = dlerror();
  if (error != NULL) {
    printf("Error from dlerror = %s \n", error);
    fflush(stdout);
    assert(0 != 0 && "error loading the init of the shared object");
  }
}

static
int is_regular_file(const char *path)
{
    struct stat path_stat;
    stat(path, &path_stat);
    return S_ISREG(path_stat.st_mode);
}

static
void load_all_pugin_ag(plugin_ag_t* p, const char* dir_path)
{
  /* Scanning the in directory */
  DIR* fd = opendir(dir_path);
  assert(fd != NULL && "Error opening the input directory");

  struct dirent* in_file = readdir(fd);
  while (in_file != NULL) {
    // We don't want current and parent directories
    if (!strcmp (in_file->d_name, ".")){
      in_file = readdir(fd);
      continue;
    }
    if (!strcmp (in_file->d_name, "..")){
      in_file = readdir(fd);
      continue;
    }

    char file_path[1024] = {0};
    size_t const sz_dir_path = strlen(dir_path);
    assert(sz_dir_path < 1024);
    strncat(file_path, dir_path, sz_dir_path < 1024 ? sz_dir_path : 1024 ); 

    size_t const rem = 1024 - sz_dir_path; 
    size_t const sz_in = strlen(in_file->d_name);
    assert(sz_in  < rem && "Lacking space...");
    strncat(file_path + sz_dir_path, in_file->d_name, sz_in < rem ? sz_in : rem );

    const char* needle = ".conf";
    const char* ans = strstr(file_path, needle);
    if(ans == NULL && is_regular_file(file_path)) // Not a Configuration file
      load_plugin_ag(p, file_path);

    in_file = readdir(fd);
  }

  closedir(fd);
}

void unload_all_pugin_ag(plugin_ag_t* p, const char* path)
{
  assert(p != NULL);
  assert(path != NULL);
  assert(0!=0 && "Not implemented!");
}

static
sm_io_ag_ran_t cp_io_ran(sm_io_ag_ran_t const* src)
{
  assert(src != NULL);
  sm_io_ag_ran_t dst = {0}; 

  // Read
  memcpy(dst.read_ind_tbl, src->read_ind_tbl, sizeof(read_ind_fp)*SM_AGENT_IF_READ_V0_END);
  memcpy(dst.read_setup_tbl, src->read_setup_tbl, sizeof(read_e2_setup_fp)*SM_AGENT_IF_E2_SETUP_ANS_V0_END);
  //read_rsu_fp read_rsu_tbl[0];
  //read_rsu_fp read_rsu_tbl[0];

  // Write
  memcpy(dst.write_ctrl_tbl, src->write_ctrl_tbl, sizeof(write_ctrl_fp)*SM_AGENT_IF_WRITE_CTRL_V0_END);
  memcpy(dst.write_subs_tbl, src->write_subs_tbl, sizeof(write_subs_fp)*SM_AGENT_IF_WRITE_SUBS_V0_END);

  return dst;
}

void init_plugin_ag(plugin_ag_t* p, const char* dir_path, sm_io_ag_ran_t io)
{
  assert(p != NULL);
  assert(dir_path != NULL);

  p->dir_path = (char*)dir_path;
 
  p->io = cp_io_ran(&io);

  p->flag_shutdown = false;

  pthread_mutexattr_t attr= {0};
  pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_ERRORCHECK);

  int rc = pthread_mutex_init(&p->sm_ds_mtx, &attr);
  assert(rc == 0);

  const size_t ran_func_size = sizeof(uint16_t);
  assoc_init(&p->sm_ds, ran_func_size, cmp_ran_func_id, free_sm_agent );

  load_all_pugin_ag(p, dir_path);

//  pthread_create(&p->thread_rx, NULL, rx_plugin_agent, p);
}

void free_plugin_ag(plugin_ag_t* p)
{
  assert(p != NULL);

  assoc_free(&p->sm_ds); 

  pthread_mutex_destroy(&p->sm_ds_mtx);

  // Thread management
  p->flag_shutdown = true;

  int rc = shutdown(p->sockfd, SHUT_RDWR);
  if(rc != 0){
    printf("Closing the agent socket: %s \n", strerror(errno));
  }
  //assert(rc == 0);
//  rc = pthread_join(p->thread_rx, NULL);
//  assert(rc == 0);
}

static inline
bool absolute_path(const char* path)
{
  return path != NULL ? true : false;
}

void load_plugin_ag(plugin_ag_t* p, const char* path)
{
  //ToDo: Looks code from a sophomore. DO IT PROPERLY
  assert(p != NULL);
  assert(path != NULL);

  printf("[E2 AGENT]: Opening plugin from path = %s \n", path );

  void* handle = dlopen(path, RTLD_NOW);
  if(handle == NULL){
    printf("Error while opening the shared object = %s \n", dlerror());
  }
  assert(handle != NULL && "Could not open the file path");
  dlerror();    

  char* so_name = strrchr(path, '/');
  char* ptr_so_name = NULL; 
  if(absolute_path(so_name) == true){
    ptr_so_name = so_name + strlen("/lib");
    assert(so_name != NULL);
  } else {
     ptr_so_name = (char*)path + strlen("lib");
  }

  char symbol_so[256] = {'m','a','k','e','_'};
  char* needle = "_sm.so";

  char* match = strstr( ptr_so_name, needle); // search_naive(strlen(needle), needle, strlen(ptr_so_name ), ptr_so_name);
  assert(match != NULL && "Could not find the string _sm.so in the so\n");

  char* ptr = &symbol_so[5];
  assert(match > ptr_so_name);
  strncat(ptr, ptr_so_name , match - ptr_so_name);
  ptr += match - ptr_so_name;
  const char* suffix = "_sm_agent";
  strncat(ptr,suffix, strlen(suffix));

  sm_agent_t* (*fp)(sm_io_ag_ran_t);
  fp = dlsym(handle, symbol_so);
  check_dl_error();
  sm_agent_t* sm = fp(p->io);

  sm->handle = handle; 
  assert(sm != NULL);
  const uint16_t ran_func_id = sm->ran_func_id;

  {
    lock_guard(&p->sm_ds_mtx);
    assoc_insert(&p->sm_ds, &ran_func_id, sizeof(ran_func_id), sm);
  }

//  printf("AGENT: Accepting SM ID = %d with def = %s \n", sm->ran_func_id, sm->ran_func_name);
}

void unload_plugin_ag(plugin_ag_t* p, uint16_t key)
{
  assert(p != NULL);
  assert(key != 0);
  assert(0!=0 && "Not implemented!");
}

sm_agent_t* sm_plugin_ag(plugin_ag_t* p, uint16_t key)
{
  assert(p != NULL);
  assert(key > 0 && "Reserved value");

  lock_guard(&p->sm_ds_mtx);

  void* start_it = assoc_front(&p->sm_ds);
  void* end_it = assoc_end(&p->sm_ds);
  void* it = find_if(&p->sm_ds, start_it, end_it, &key, eq_ran_func_id); 
  assert(it != end_it && "RAN function ID not found in the RAN"); 

  sm_agent_t* sm = assoc_value(&p->sm_ds, it);

  assert(sm->ran_func_id == key);
  return sm;
}

size_t size_plugin_ag(plugin_ag_t* p)
{
  assert(p != NULL);

  lock_guard(&p->sm_ds_mtx);

  size_t s = assoc_size(&p->sm_ds); 

  return s;
}