SASC
DVBSoftCAM

plugin_scan.c File Reference

#include <stdlib.h>
#include <stdio.h>
#include <fcntl.h>
#include <pthread.h>
#include <sys/mman.h>
#include <sys/poll.h>
#include <sys/ioctl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/wait.h>
#include <signal.h>
#include <string.h>
#include <getopt.h>
#include <unistd.h>
#include <errno.h>
#include "list.h"
#include <linux/dvb/dmx.h>
#include <linux/dvb/frontend.h>
#include "process_req.h"
#include "msg_passing.h"
#include "plugin_getsid.h"
#include "plugin_msg.h"
#include "debug.h"

Go to the source code of this file.

Classes

struct  scanner

Defines

#define PLUGIN_ID   30
#define DBG_NAME   "Scanner"
#define SCAN_MIN_WAITTIME   (10)
#define SCAN_WAITTIME   (10*60)
#define SCAN_TIMEOUT   (30*60)
#define SCAN_MIN_TUNETIME   (10*60)
#define SCAN_CAM_MINTIME   5
#define MAX_PORTS   16
#define FIND_CMD(result, adpt, type, _id)

Functions

static LIST_HEAD (scanner_list)
char * get_camdir ()
static struct scanner * find_scanner_from_pc (struct parser_cmds *pc)
void * scan_loop (void *arg)
static void process_scan (struct msg *msg, unsigned int priority)
static void fe_open_pre (struct parser_cmds *pc, struct poll_ll *fdptr, cmdret_t *result, int *ret, unsigned long int cmd, unsigned char *data)
static void fe_open_post (struct parser_cmds *pc, struct poll_ll *fdptr, cmdret_t *result, int *ret, unsigned long int cmd, unsigned char *data)
static void fe_close (struct parser_cmds *pc, struct poll_ll *fdptr, cmdret_t *result, int *ret, unsigned long int cmd, unsigned char *data)
static void launch_scan ()
static void connect_scan (struct parser_adpt *pc_all)
static struct option * parseopt_scan (arg_enum_t cmd)
int __attribute__ ((constructor))

Variables

static int scan_opt = 0
static int scan_ports = 0
static struct option Scan_Opts []
static char scan_script [256]
static char scan_lib [256]
unsigned char boo [1024]
static pthread_mutex_t scanner_mutex = PTHREAD_MUTEX_INITIALIZER
static pthread_cond_t scanner_cond = PTHREAD_COND_INITIALIZER
static pthread_t scanner_thread
static struct plugin_cmd plugin_cmds

Define Documentation

#define DBG_NAME   "Scanner"

Definition at line 46 of file plugin_scan.c.

#define FIND_CMD (   result,
  adpt,
  type,
  _id 
)
Value:
do { \
  struct cmd_list *cmd; \
  ll_find_elem(cmd, adpt->pre_##type, id, (_id), struct cmd_list); \
  if(! cmd) \
    ll_find_elem(cmd, adpt->post_##type, id, (_id), struct cmd_list); \
  if(! cmd) \
    result = NULL;\
  else \
    result = cmd->cmd; \
  } while(0);

Definition at line 296 of file plugin_scan.c.

#define MAX_PORTS   16

Definition at line 70 of file plugin_scan.c.

#define PLUGIN_ID   30

Definition at line 45 of file plugin_scan.c.

#define SCAN_CAM_MINTIME   5

Definition at line 68 of file plugin_scan.c.

Referenced by process_scan().

#define SCAN_MIN_TUNETIME   (10*60)

Definition at line 65 of file plugin_scan.c.

Referenced by scan_loop().

#define SCAN_MIN_WAITTIME   (10)

Definition at line 58 of file plugin_scan.c.

Referenced by scan_loop().

#define SCAN_TIMEOUT   (30*60)

Definition at line 62 of file plugin_scan.c.

Referenced by scan_loop().

#define SCAN_WAITTIME   (10*60)

Definition at line 60 of file plugin_scan.c.

Referenced by scan_loop().


Function Documentation

int __attribute__ ( (constructor)  )

Definition at line 370 of file plugin_scan.c.

References plugin_cmd::list, list_add(), and plugin_cmdlist.

{
  // communicates the existance of teh current plugin to the main program.
  if(1) list_add(&plugin_cmds.list, &plugin_cmdlist);
  return 0;
}
static void connect_scan ( struct parser_adpt *  pc_all) [static]

Definition at line 316 of file plugin_scan.c.

References ATTACH_CALLBACK, dprintf0, fe_close(), fe_open_post(), fe_open_pre(), parser_adpt::frontend, get_camdir(), list_add_tail(), NULL, scanner::pc_all, parser_cmds::post_close, parser_cmds::post_open, parser_cmds::pre_open, scan_lib, scan_ports, and scan_script.

{
  struct scanner  *scanner;
  struct stat st;
  scanner = (struct scanner *)malloc(sizeof(struct scanner));
  if(! scanner)
    return;
  bzero(scanner, sizeof(struct scanner));
  if(scan_ports) {
    snprintf(scan_script, sizeof(scan_script), "%s/scanner", get_camdir());
    snprintf(scan_lib, sizeof(scan_lib), "%s/libscanwrap.so", get_camdir());
    if(stat(scan_script, &st) == -1 || ! (st.st_mode & (S_IXUSR | S_IXGRP | S_IXOTH))) {
      dprintf0("Couldn't locate executable %s\n", scan_script);
      exit(1);
    }
    if(stat(scan_lib, &st) == -1) {
      dprintf0("Couldn't locate wrapper lib %s\n", scan_lib);
      exit(1);
    }
  }
  scanner->pc_all = pc_all;
  scanner->lastcmd = time(NULL);
  ATTACH_CALLBACK(&pc_all->frontend->pre_open, fe_open_pre, -1);
  ATTACH_CALLBACK(&pc_all->frontend->post_open, fe_open_post, -1);
  ATTACH_CALLBACK(&pc_all->frontend->post_close, fe_close, -1);
  list_add_tail(&scanner->list, &scanner_list);
}
static void fe_close ( struct parser_cmds *  pc,
struct poll_ll *  fdptr,
cmdret_t *  result,
int *  ret,
unsigned long int  cmd,
unsigned char *  data 
) [static]

Definition at line 272 of file plugin_scan.c.

References scanner::fe_fdptr, scanner::fecount, find_scanner_from_pc(), poll_ll::flags, scanner::lastcmd, NULL, O_ASYNC, O_SYNC, and scanner_mutex.

Referenced by connect_scan().

{
  struct scanner *scanner;
  scanner = find_scanner_from_pc(pc);
  if(scanner == NULL)
    return;

  if((fdptr->flags & O_ACCMODE) == O_RDONLY)
    return;

  pthread_mutex_lock(&scanner_mutex);
  if((fdptr->flags & (O_SYNC | O_ASYNC)) == (O_SYNC | O_ASYNC)) {
    // This is the scanner fd
    scanner->fe_fdptr = NULL;
  } else {
    if(scanner->fecount > 0)
      scanner->fecount--;
    scanner->lastcmd = time(NULL);
  }
  pthread_mutex_unlock(&scanner_mutex);
}
static void fe_open_post ( struct parser_cmds *  pc,
struct poll_ll *  fdptr,
cmdret_t *  result,
int *  ret,
unsigned long int  cmd,
unsigned char *  data 
) [static]

Definition at line 248 of file plugin_scan.c.

References poll_ll::fd, scanner::fe_fdptr, scanner::fecount, find_scanner_from_pc(), poll_ll::flags, scanner::lastcmd, NULL, O_ASYNC, O_SYNC, and scanner_mutex.

Referenced by connect_scan().

{
  struct scanner *scanner;
  scanner = find_scanner_from_pc(pc);
  if(scanner == NULL)
    return;

  if((fdptr->flags & O_ACCMODE) == O_RDONLY)
    return;
  if(fdptr->fd < 0)
    return;
  pthread_mutex_lock(&scanner_mutex);
  if((fdptr->flags & (O_SYNC | O_ASYNC)) == (O_SYNC | O_ASYNC)) {
    // This is the scanner fd
    scanner->fe_fdptr = fdptr;
  } else {
    scanner->fecount++;
    scanner->lastcmd = time(NULL);
  }
  pthread_mutex_unlock(&scanner_mutex);
}
static void fe_open_pre ( struct parser_cmds *  pc,
struct poll_ll *  fdptr,
cmdret_t *  result,
int *  ret,
unsigned long int  cmd,
unsigned char *  data 
) [static]

Definition at line 219 of file plugin_scan.c.

References poll_ll::fd, scanner::fe_fdptr, find_scanner_from_pc(), poll_ll::flags, scanner::lastcmd, NULL, O_ASYNC, O_SYNC, open(), scanner::pid, scanner_mutex, and scanner::waiting.

Referenced by connect_scan().

{
  struct scanner *scanner;
  scanner = find_scanner_from_pc(pc);
  if(scanner == NULL)
    return;

  if((fdptr->flags & O_ACCMODE) == O_RDONLY)
    return;

  pthread_mutex_lock(&scanner_mutex);
  if(scanner->fe_fdptr) {
    if((fdptr->flags & (O_SYNC | O_ASYNC)) != (O_SYNC | O_ASYNC)) {
      //This isn't the scanner fd so kill the scanner
      if(scanner->pid && ! scanner->waiting) {
        kill(scanner->pid, 9);
        scanner->waiting = 1;
      }
      close(scanner->fe_fdptr->fd);
      scanner->fe_fdptr->fd = open("/dev/null", O_RDWR);
      scanner->fe_fdptr = NULL;
      scanner->lastcmd = time(NULL);
    }
  }
  pthread_mutex_unlock(&scanner_mutex);
}
static struct scanner* find_scanner_from_pc ( struct parser_cmds *  pc) [static, read]

Definition at line 100 of file plugin_scan.c.

References parser_cmds::common, parser_adpt::frontend, list_entry, list_for_each, NULL, and scanner::pc_all.

Referenced by fe_close(), fe_open_post(), and fe_open_pre().

{
  struct list_head *ptr;
  list_for_each(ptr, &scanner_list) {
    struct scanner *scanner = list_entry(ptr, struct scanner);
    if(scanner->pc_all->frontend->common == pc->common)
      return scanner;
  }
  return NULL;
}
char* get_camdir ( )

Definition at line 44 of file plugin_cam.c.

References opt_camdir.

Referenced by connect_scan().

{ return opt_camdir;}
static void launch_scan ( ) [static]
static LIST_HEAD ( scanner_list  ) [static]
static struct option* parseopt_scan ( arg_enum_t  cmd) [static, read]

Definition at line 344 of file plugin_scan.c.

References ARG_HELP, ARG_INIT, dprintf0, NULL, scan_opt, Scan_Opts, and scan_ports.

{
  if(cmd == ARG_INIT) {
    return Scan_Opts;
  } 
  if(cmd == ARG_HELP) {
    printf("   --scan-ports <num_ports>: Turn on scanner\n");
  } 
  if(! scan_opt)
    return NULL;

  switch(scan_opt) {
    case 'p':
      scan_ports = strtol(optarg, NULL, 0);
      dprintf0("Enabling scanner on %d ports\n", scan_ports);
      break;
  }
  //must reset scan_opt after every call
  scan_opt = 0;
  return NULL;
}
static void process_scan ( struct msg *  msg,
unsigned int  priority 
) [static]

Definition at line 182 of file plugin_scan.c.

References scanner::ca, parser_cmds::common, msg::data, scanner::done, dprintf0, parser_adpt::frontend, msg::id, scanner::last_pol, scanner::lasttime, ll_find_elem, MSG_CAMUPDATE, MSG_PROCESSED, MSG_TRYSCAN, NULL, scanner::pc_all, scanner::pid, SCAN_CAM_MINTIME, scanner_cond, scanner_mutex, scanner::state, msg::type, common_data::virt_adapt, and scanner::waiting.

{
  if (msg->type == MSG_TRYSCAN) {
    msg->type = MSG_PROCESSED;
    pthread_mutex_lock(&scanner_mutex);
    pthread_cond_signal(&scanner_cond);
    pthread_mutex_unlock(&scanner_mutex);
  } else if(msg->type == MSG_CAMUPDATE) {
    struct scanner *scanner;
    time_t curtime = time(NULL);
    int idx = (((unsigned long)msg->data)& 0xff) >> 1;
    int polarity = ((unsigned long)msg->data)& 0x01;
    msg->type = MSG_PROCESSED;
    ll_find_elem(scanner, scanner_list, pc_all->frontend->common->virt_adapt, msg->id, struct scanner);
    if(scanner == NULL || ! scanner->pid || scanner->waiting)
      return;
    if(polarity != scanner->ca[idx].last_pol &&
       curtime - scanner->ca[idx].lasttime > SCAN_CAM_MINTIME) {
      if(scanner->ca[idx].state < 4)
        scanner->ca[idx].state++;
      if(scanner->ca[idx].state == 4) {
        pthread_mutex_lock(&scanner_mutex);
        scanner->done = 1;
        pthread_mutex_unlock(&scanner_mutex);
      }
    } else {
      pthread_mutex_lock(&scanner_mutex);
      scanner->done = 0;
      pthread_mutex_unlock(&scanner_mutex);
      scanner->ca[idx].state = 0;
    }
    scanner->ca[idx].last_pol = polarity;
    scanner->ca[idx].lasttime = curtime;
    dprintf0("id:%d idx: %d state:%d pol:%d done:%d\n", msg->id, idx, scanner->ca[idx].state, polarity, scanner->done);
  }
}
void* scan_loop ( void *  arg)

Definition at line 111 of file plugin_scan.c.

References b, scanner::ca, parser_cmds::common, scanner::done, dprintf0, fd, scanner::fecount, scanner::found, parser_adpt::frontend, i, scanner::lastcmd, scanner::lasttime, list_entry, list_for_each, NULL, open(), scanner::pc_all, scanner::pid, scanner::port, scan_lib, SCAN_MIN_TUNETIME, SCAN_MIN_WAITTIME, scan_ports, scan_script, SCAN_TIMEOUT, SCAN_WAITTIME, scanner_cond, scanner_mutex, scanner::starttime, scanner::state, common_data::virt_adapt, and scanner::waiting.

Referenced by launch_scan().

{
  struct scanner *scanner;
  struct list_head *ptr;
  time_t curtime;
  pthread_mutex_lock(&scanner_mutex);
  while(1) {
    int ok = 0;
    while(! ok) {
      curtime = time(NULL);
      list_for_each(ptr, &scanner_list) {
        scanner = list_entry(ptr, struct scanner);
        if(scanner->fecount==0 && curtime - scanner->lastcmd >= SCAN_MIN_WAITTIME) {
          ok = 1;
          break;
        }
      }
      if(! ok) {
        pthread_cond_wait(&scanner_cond, &scanner_mutex);
      }
    }
    //We can start the scanner if we get here
    if(! scanner->pid) {
      if(curtime > scanner->starttime[scanner->port] + SCAN_WAITTIME) {
        //Time to try scanning the current port
        scanner->done = 0;
        for(int i = 0; i < 8; i++) {
          scanner->ca[i].lasttime = curtime;
          scanner->ca[i].state = 0;
        }
        dprintf0("Starting scanner on port %d\n", scanner->port);
        if(0 == (scanner->pid = fork())) {
          char env[256], *env1[3] = {env, (char *) 0};
          struct { char a[8], b[8], c[8];} arg = {"scanner", "", ""};
          char *arg1[] = {arg.a, arg.b, arg.c, (char *) 0};
          snprintf(env,sizeof(env), "LD_PRELOAD=%s", scan_lib);
          snprintf(arg.b, 8, "%d", scanner->pc_all->frontend->common->virt_adapt);
          snprintf(arg.c, 8, "%d", scanner->port);
          int fd = open("/dev/null", O_WRONLY);
          while (dup2(fd, 1) < 0 && errno == EINTR)
            ;
          while (dup2(fd, 2) < 0 && errno == EINTR)
            ;
          while (close(fd) < 0 && errno == EINTR)
            ;
          execve(scan_script, arg1, env1);
          exit(0);
        }
        scanner->starttime[scanner->port] = curtime;
      }
    } else if(waitpid(scanner->pid, NULL, WNOHANG)) {
      scanner->pid = 0;
      scanner->port = (scanner->port+1) % scan_ports;
      scanner->waiting = 0;
    } else if(! scanner->waiting &&
              (  (scanner->done
                    && (! scanner->found[scanner->port]
                          || curtime > scanner->starttime[scanner->port] + SCAN_MIN_TUNETIME)
                 )
                 || curtime > scanner->starttime[scanner->port] + SCAN_TIMEOUT
              )) {
      if(scanner->done) {
        dprintf0("Scan complete for port %d.  Terminating %d\n", scanner->port, scanner->pid);
        scanner->found[scanner->port] = 1;
      }
      kill(scanner->pid, 9);
      scanner->waiting = 1;
    }
    scanner->lastcmd = curtime;
  }
}

Variable Documentation

unsigned char boo[1024]

Definition at line 95 of file plugin_scan.c.

struct plugin_cmd plugin_cmds [static]
Initial value:

Definition at line 367 of file plugin_scan.c.

char scan_lib[256]

Definition at line 74 of file plugin_scan.c.

Referenced by connect_scan(), and scan_loop().

int scan_opt = 0 [static]

Definition at line 51 of file plugin_scan.c.

Referenced by parseopt_scan().

struct option Scan_Opts[] [static]
Initial value:
 {
  {"scan-ports", 1, &scan_opt, 'p'},
  {0, 0, 0, 0},
}

Definition at line 53 of file plugin_scan.c.

Referenced by parseopt_scan().

int scan_ports = 0 [static]

Definition at line 52 of file plugin_scan.c.

Referenced by connect_scan(), launch_scan(), parseopt_scan(), and scan_loop().

char scan_script[256] [static]

Definition at line 74 of file plugin_scan.c.

Referenced by connect_scan(), and scan_loop().

pthread_cond_t scanner_cond = PTHREAD_COND_INITIALIZER [static]

Definition at line 97 of file plugin_scan.c.

Referenced by process_scan(), and scan_loop().

pthread_mutex_t scanner_mutex = PTHREAD_MUTEX_INITIALIZER [static]

Definition at line 96 of file plugin_scan.c.

Referenced by fe_close(), fe_open_post(), fe_open_pre(), process_scan(), and scan_loop().

pthread_t scanner_thread [static]

Definition at line 98 of file plugin_scan.c.

Referenced by launch_scan().

 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines