more work on capmt

This commit is contained in:
Robert 2009-11-08 18:17:44 +00:00
parent 58868079ac
commit 39b6846883

View file

@ -264,71 +264,115 @@ capmt_transport_destroy(th_descrambler_t *td)
free(ct); free(ct);
} }
static void
handle_ca0(capmt_t* capmt) {
capmt_transport_t *ct;
th_transport_t *t;
int ret;
uint8_t invalid[8], buffer[20];
memset(invalid, 0, 8);
tvhlog(LOG_INFO, "capmt", "running handle_ca0");
while (capmt->capmt_running) {
ret = recv(capmt->capmt_sock_ca0, buffer, 18, MSG_WAITALL);
ct = capmt->ct;
if (ct == NULL)
continue;
t = ct->ct_transport;
if (ret < 0) {
tvhlog(LOG_ERR, "capmt", "error receiving over socket");
// TODO reaction
} else if (ret == 0) {
// normal socket shutdown
tvhlog(LOG_INFO, "capmt", "normal socket shutdown");
break;
} else if(ret < 18) {
if(ct->ct_keystate != CT_FORBIDDEN) {
tvhlog(LOG_ERR, "capmt", "Can not descramble service \"%s\", access denied", t->tht_svcname);
ct->ct_keystate = CT_FORBIDDEN;
}
continue;
}
/* get control words */
uint8_t *even = &buffer[2], *odd = &buffer[10];
if (memcmp(even, invalid, 8))
set_even_control_word(ct->ct_keys, even);
if (memcmp(odd, invalid, 8))
set_odd_control_word(ct->ct_keys, odd);
if(ct->ct_keystate != CT_RESOLVED)
tvhlog(LOG_INFO, "capmt", "Obtained key for service \"%s\"",t->tht_svcname);
ct->ct_keystate = CT_RESOLVED;
}
tvhlog(LOG_INFO, "capmt", "exiting handle_ca0");
}
/** /**
* *
*/ */
/*
static void * static void *
capmt_thread(void *aux) capmt_thread(void *aux)
{ {
capmt_transport_t *ct;
capmt_t *capmt = aux; capmt_t *capmt = aux;
int fd, d;
char errbuf[100];
th_transport_t *t;
char hostname[256];
int port;
struct timespec ts; struct timespec ts;
int attempts = 0; int d;
pthread_mutex_lock(&global_lock); while (capmt->capmt_running) {
capmt->capmt_sock = -1;
capmt->capmt_sock_ca0 = -1;
while(capmt->capmt_running) { pthread_mutex_lock(&global_lock);
while(capmt->capmt_running && capmt->capmt_enabled == 0) while(capmt->capmt_running && capmt->capmt_enabled == 0)
pthread_cond_wait(&capmt->capmt_cond, &global_lock); pthread_cond_wait(&capmt->capmt_cond, &global_lock);
snprintf(hostname, sizeof(hostname), "%s", capmt->capmt_hostname);
port = capmt->capmt_port;
tvhlog(LOG_INFO, "capmt", "Attemping to connect to %s:%d", hostname, port);
pthread_mutex_unlock(&global_lock); pthread_mutex_unlock(&global_lock);
fd = tcp_connect(hostname, port, errbuf, sizeof(errbuf), 10); /* open connection to camd.socket */
capmt->capmt_sock = socket(AF_LOCAL, SOCK_STREAM, 0);
pthread_mutex_lock(&global_lock); struct sockaddr_un serv_addr_un;
memset(&serv_addr_un, 0, sizeof(serv_addr_un));
serv_addr_un.sun_family = AF_LOCAL;
snprintf(serv_addr_un.sun_path, sizeof(serv_addr_un.sun_path), "%s", capmt->capmt_sockfile);
if(fd == -1) { if (connect(capmt->capmt_sock, (const struct sockaddr*)&serv_addr_un, sizeof(serv_addr_un)) == 0) {
attempts++; /* open connection to emulated ca0 device */
tvhlog(LOG_INFO, "capmt", capmt->capmt_sock_ca0 = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP);
"Connection attempt to %s:%d failed: %s",
hostname, port, errbuf);
} else {
if(capmt->capmt_running == 0) { struct sockaddr_in serv_addr;
close(fd); serv_addr.sin_addr.s_addr = inet_addr("127.0.0.1");
break; serv_addr.sin_port = htons( (unsigned short int)capmt->capmt_port);
} serv_addr.sin_family = AF_INET;
tvhlog(LOG_INFO, "capmt", "Connected to %s:%d", hostname, port); if (bind(capmt->capmt_sock_ca0, (const struct sockaddr*)&serv_addr, sizeof(serv_addr)) != 0)
attempts = 0; perror("[CapmtServer] ERROR binding to ca0");
else
handle_ca0(capmt);
} else
tvhlog(LOG_ERR, "capmt", "Error connecting to %s: %s", capmt->capmt_sockfile, strerror(errno));
capmt->capmt_fd = fd; /* close opened sockets */
capmt->capmt_reconfigure = 0; if (capmt->capmt_sock > 0)
close(capmt->capmt_sock);
//capmt_session(capmt); if (capmt->capmt_sock_ca0 > 0)
close(capmt->capmt_sock_ca0);
capmt->capmt_fd = -1;
close(fd);
capmt->capmt_caid = 0;
tvhlog(LOG_INFO, "capmt", "Disconnected from %s", capmt->capmt_hostname);
}
/* schedule reconnection */
if(subscriptions_active()) { if(subscriptions_active()) {
if(attempts == 1)
continue; // Retry immediately
d = 3; d = 3;
} else { } else {
d = 60; d = 60;
@ -337,32 +381,15 @@ capmt_thread(void *aux)
ts.tv_sec = time(NULL) + d; ts.tv_sec = time(NULL) + d;
ts.tv_nsec = 0; ts.tv_nsec = 0;
tvhlog(LOG_INFO, "capmt", tvhlog(LOG_INFO, "capmt", "Automatic reconnection attempt in in %d seconds", d);
"%s: Automatic connection attempt in in %d seconds",
capmt->capmt_hostname, d);
pthread_mutex_lock(&global_lock);
pthread_cond_timedwait(&capmt_config_changed, &global_lock, &ts); pthread_cond_timedwait(&capmt_config_changed, &global_lock, &ts);
pthread_mutex_unlock(&global_lock);
} }
tvhlog(LOG_INFO, "capmt", "%s destroyed", capmt->capmt_hostname);
while((ct = LIST_FIRST(&capmt->capmt_transports)) != NULL) {
t = ct->ct_transport;
pthread_mutex_lock(&t->tht_stream_mutex);
capmt_transport_destroy(&ct->ct_head);
pthread_mutex_unlock(&t->tht_stream_mutex);
}
free((void *)capmt->capmt_password);
free((void *)capmt->capmt_password_salted);
free((void *)capmt->capmt_username);
free((void *)capmt->capmt_hostname);
free(capmt);
pthread_mutex_unlock(&global_lock);
return NULL; return NULL;
} }
*/
/** /**
* *
@ -604,67 +631,14 @@ capmt_destroy(capmt_t *capmt)
pthread_cond_signal(&capmt->capmt_cond); pthread_cond_signal(&capmt->capmt_cond);
} }
static void* ca0Thread(void* pArg) {
capmt_t *capmt = (capmt_t*)pArg;
capmt_transport_t *ct;
th_transport_t *t;
int ret;
uint8_t invalid[8], buffer[20];
memset(invalid, 0, 8);
while (capmt->capmt_running) {
ret = recv(capmt->capmt_sock_ca0, buffer, 18, MSG_WAITALL);
ct = capmt->ct;
if (ct == NULL)
continue;
t = ct->ct_transport;
if (ret < 0) {
tvhlog(LOG_ERR, "capmt", "error receiving over socket");
// TODO reaction
} else if (ret == 0) {
// normal socket shutdown
tvhlog(LOG_INFO, "capmt", "normal socket shutdown");
break;
} else if(ret < 18) {
if(ct->ct_keystate != CT_FORBIDDEN) {
tvhlog(LOG_ERR, "capmt",
"Can not descramble service \"%s\", access denied", t->tht_svcname);
ct->ct_keystate = CT_FORBIDDEN;
}
continue;
}
/* get control words */
uint8_t *even = &buffer[2], *odd = &buffer[10];
if (memcmp(even, invalid, 8))
set_even_control_word(ct->ct_keys, even);
if (memcmp(odd, invalid, 8))
set_odd_control_word(ct->ct_keys, odd);
if(ct->ct_keystate != CT_RESOLVED)
tvhlog(LOG_INFO, "capmt",
"Obtained key for service \"%s\"",t->tht_svcname);
ct->ct_keystate = CT_RESOLVED;
}
return NULL;
}
/** /**
* *
*/ */
static capmt_t * static capmt_t *
capmt_entry_find(const char *id, int create) capmt_entry_find(const char *id, int create)
{ {
pthread_attr_t attr;
pthread_t ptid;
char buf[20]; char buf[20];
capmt_t *capmt; capmt_t *capmt;
static int tally; static int tally;
@ -691,33 +665,13 @@ capmt_entry_find(const char *id, int create)
capmt->capmt_id = strdup(id); capmt->capmt_id = strdup(id);
capmt->capmt_running = 1; capmt->capmt_running = 1;
/* open connection to camd.socket */
capmt->capmt_sock = socket(AF_LOCAL, SOCK_STREAM, 0);
struct sockaddr_un serv_addr_un;
memset(&serv_addr_un, 0, sizeof(serv_addr_un));
serv_addr_un.sun_family = AF_LOCAL;
snprintf(serv_addr_un.sun_path, sizeof(serv_addr_un.sun_path), "/tmp/camd.socket");
if (connect(capmt->capmt_sock, (const struct sockaddr*)&serv_addr_un, sizeof(serv_addr_un)) != 0)
perror("[CWCServer] ERROR connecting to camd.socket");
/* open connection to emulated ca0 device */
capmt->capmt_sock_ca0 = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP);
struct sockaddr_in serv_addr;
serv_addr.sin_addr.s_addr = inet_addr("127.0.0.1");
serv_addr.sin_port = htons( (unsigned short int)9000);
serv_addr.sin_family = AF_INET;
if (bind(capmt->capmt_sock_ca0, (const struct sockaddr*)&serv_addr, sizeof(serv_addr)) != 0)
perror("[CWCServer] ERROR binding to ca0");
pthread_t tCa0;
pthread_create(&tCa0, NULL, ca0Thread, (void*)capmt);
TAILQ_INSERT_TAIL(&capmts, capmt, capmt_link); TAILQ_INSERT_TAIL(&capmts, capmt, capmt_link);
pthread_attr_init(&attr);
pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
pthread_create(&ptid, &attr, capmt_thread, capmt);
pthread_attr_destroy(&attr);
return capmt; return capmt;
} }
@ -747,7 +701,6 @@ capmt_record_build(capmt_t *capmt)
static htsmsg_t * static htsmsg_t *
capmt_entry_update(void *opaque, const char *id, htsmsg_t *values, int maycreate) capmt_entry_update(void *opaque, const char *id, htsmsg_t *values, int maycreate)
{ {
printf("capmt entry update\n");
capmt_t *capmt; capmt_t *capmt;
const char *s; const char *s;
uint32_t u32; uint32_t u32;
@ -760,28 +713,28 @@ capmt_entry_update(void *opaque, const char *id, htsmsg_t *values, int maycreate
if((s = htsmsg_get_str(values, "camdfilename")) != NULL) { if((s = htsmsg_get_str(values, "camdfilename")) != NULL) {
free(capmt->capmt_sockfile); free(capmt->capmt_sockfile);
capmt->capmt_sockfile = strdup(s); capmt->capmt_sockfile = strdup(s);
printf("capmt sockfile %s\n", s);
} }
if(!htsmsg_get_u32(values, "port", &u32)) { if(!htsmsg_get_u32(values, "port", &u32))
capmt->capmt_port = u32; capmt->capmt_port = u32;
printf("capmt listen port %d\n", u32);
}
if((s = htsmsg_get_str(values, "comment")) != NULL) { if((s = htsmsg_get_str(values, "comment")) != NULL) {
free(capmt->capmt_comment); free(capmt->capmt_comment);
capmt->capmt_comment = strdup(s); capmt->capmt_comment = strdup(s);
} }
/* if(!htsmsg_get_u32(values, "enabled", &u32))
capmt->capmt_enabled = u32;
capmt->capmt_reconfigure = 1; capmt->capmt_reconfigure = 1;
if(capmt->capmt_fd != -1) /* if(capmt->capmt_fd != -1)
shutdown(capmt->capmt_fd, SHUT_RDWR); shutdown(capmt->capmt_fd, SHUT_RDWR);*/
pthread_cond_signal(&capmt->capmt_cond); pthread_cond_signal(&capmt->capmt_cond);
pthread_cond_broadcast(&capmt_config_changed);*/ pthread_cond_broadcast(&capmt_config_changed);
return capmt_record_build(capmt); return capmt_record_build(capmt);
} }