static S_COOL_CHANHANDLE *find_chanhandle(int32_t demux_index, int32_t pid) { // Find matching channel, if it exists. if(ll_count(ll_cool_chanhandle) > 0) { LL_ITER itr = ll_iter_create(ll_cool_chanhandle); S_COOL_CHANHANDLE *handle_item; while((handle_item = ll_iter_next(&itr))) { if(handle_item->demux_index == demux_index && handle_item->pid == pid) { return handle_item; } } } return NULL; }
static S_COOL_FILTER *find_filter_by_chanhandle(S_COOL_CHANHANDLE *chanhandle, int32_t filter_num) { // Find matching channel, if it exists. if(ll_count(ll_cool_filter) > 0) { LL_ITER itr = ll_iter_create(ll_cool_filter); S_COOL_FILTER *filter_item; while((filter_item = ll_iter_next(&itr))) { if(filter_item->chanhandle == chanhandle && filter_item->filter_num == filter_num) { return filter_item; } } } return NULL; }
static int32_t remove_filter(S_COOL_FILTER *filter_handle) { if(ll_count(ll_cool_filter) > 0) { LL_ITER itr = ll_iter_create(ll_cool_filter); S_COOL_FILTER *filter_item; while((filter_item = ll_iter_next(&itr))) { if(filter_item == filter_handle) { ll_iter_remove_data(&itr); return 0; } } } return -1; }
/* * Creates a string ready to write as a token into config or WebIf for au readers. You must free the returned value through free_mk_t(). */ char *mk_t_aureader(struct s_auth *account) { int32_t pos = 0; char *dot = ""; char *value; if(ll_count(account->aureader_list) == 0 || !cs_malloc(&value, 256)) { return ""; } value[0] = '\0'; struct s_reader *rdr; LL_ITER itr = ll_iter_create(account->aureader_list); while((rdr = ll_iter_next(&itr))) { pos += snprintf(value + pos, 256 - pos, "%s%s", dot, rdr->label); dot = ","; } return value; }
static void log_list_add(struct s_log *log) { if(logStarted == 0) { return; } int32_t count = ll_count(log_list); log_list_queued++; if(count < MAX_LOG_LIST_BACKLOG) { ll_append(log_list, log); } else // We have too much backlog { NULLFREE(log->txt); NULLFREE(log); cs_write_log("-------------> Too much data in log_list, dropping log message.\n", 1, 0, 0); } SAFE_COND_SIGNAL_NOLOG(&log_thread_sleep_cond); }
static int32_t remove_chanhandle(S_COOL_CHANHANDLE *handle) { // Find matching channel, if it exists. if(ll_count(ll_cool_chanhandle) > 0) { LL_ITER itr = ll_iter_create(ll_cool_chanhandle); S_COOL_CHANHANDLE *handle_item; while((handle_item = ll_iter_next(&itr))) { if(handle_item == handle) { ll_iter_remove_data(&itr); return 0; } } } return -1; }
void gbox_remove_cards_without_goodsids(LLIST *card_list) { if(card_list) { LL_ITER it = ll_iter_create(card_list); struct gbox_card *card; while((card = ll_iter_next(&it))) { if(ll_count(card->goodsids) == 0) { ll_iter_remove(&it); gbox_free_card(card); } else { ll_destroy_data_NULL(card->badsids); } } } return; }
void log_list_thread() { char buf[LOG_BUF_SIZE]; while (1) { LL_ITER it = ll_iter_create(log_list); struct s_log *log; while ((log=ll_iter_next_remove(&it))) { int8_t do_flush = ll_count(log_list) == 0; //flush on writing last element cs_strncpy(buf, log->txt, LOG_BUF_SIZE); if (log->direct_log) cs_write_log(buf, do_flush); else write_to_log(buf, log, do_flush); free(log->txt); free(log); } cs_sleepms(50); } }
void cs_disable_log(int8_t disabled) { if (cfg.disablelog != disabled) { if(disabled && logStarted) { cs_log("Stopping log..."); int32_t i = 0; while(ll_count(log_list) > 0 && i < 200){ cs_sleepms(5); ++i; } } cfg.disablelog = disabled; if (disabled){ if(logStarted) { cs_sleepms(20); cs_close_log(); } } else { cs_open_logfiles(); } } }
// create and init the 'server' structure. static void init_servers(system_data_t *sysdata) { char *str; assert(sysdata); assert(sysdata->servers == NULL); sysdata->servers = ll_init(NULL); assert(sysdata->servers); assert(sysdata->settings->port > 0); assert(sysdata->settings->interfaces); if (ll_count(sysdata->settings->interfaces) == 0) { // no interfaces were specified, so we need to bind to all of them. server_listen(sysdata, sysdata->settings->port, NULL); } else { // we have some specific interfaces, so we will bind to each of them only. while ((str = ll_pop_tail(sysdata->settings->interfaces))) { server_listen(sysdata, sysdata->settings->port, str); free(str); } } }
/** * adds a job to the job queue * if ptr should be free() after use, set len to the size * else set size to 0 **/ int32_t add_job(struct s_client *cl, enum actions action, void *ptr, int32_t len) { if(!cl || cl->kill) { if(!cl) { cs_log("WARNING: add_job failed. Client killed!"); } // Ignore jobs for killed clients if(len && ptr) { NULLFREE(ptr); } return 0; } #ifdef CS_CACHEEX // Avoid full running queues: if(action == ACTION_CACHE_PUSH_OUT && ll_count(cl->joblist) > 2000) { cs_debug_mask(D_TRACE, "WARNING: job queue %s %s has more than 2000 jobs! count=%d, dropped!", cl->typ == 'c' ? "client" : "reader", username(cl), ll_count(cl->joblist)); if(len && ptr) { NULLFREE(ptr); } // Thread down??? pthread_mutex_lock(&cl->thread_lock); if(cl && !cl->kill && cl->thread && cl->thread_active) { // Just test for invalid thread id: if(pthread_detach(cl->thread) == ESRCH) { cl->thread_active = 0; cs_debug_mask(D_TRACE, "WARNING: %s %s thread died!", cl->typ == 'c' ? "client" : "reader", username(cl)); } } pthread_mutex_unlock(&cl->thread_lock); return 0; } #endif struct job_data *data; if(!cs_malloc(&data, sizeof(struct job_data))) { if(len && ptr) { NULLFREE(ptr); } return 0; } data->action = action; data->ptr = ptr; data->cl = cl; data->len = len; cs_ftime(&data->time); pthread_mutex_lock(&cl->thread_lock); if(cl && !cl->kill && cl->thread_active) { if(!cl->joblist) { cl->joblist = ll_create("joblist"); } ll_append(cl->joblist, data); if(cl->thread_active == 2) { pthread_kill(cl->thread, OSCAM_SIGNAL_WAKEUP); } pthread_mutex_unlock(&cl->thread_lock); cs_debug_mask(D_TRACE, "add %s job action %d queue length %d %s", action > ACTION_CLIENT_FIRST ? "client" : "reader", action, ll_count(cl->joblist), username(cl)); return 1; } pthread_attr_t attr; pthread_attr_init(&attr); /* pcsc doesn't like this either; segfaults on x86, x86_64 */ struct s_reader *rdr = cl->reader; if(cl->typ != 'r' || !rdr || rdr->typ != R_PCSC) { pthread_attr_setstacksize(&attr, PTHREAD_STACK_SIZE); } if(action != ACTION_READER_CHECK_HEALTH) { cs_debug_mask(D_TRACE, "start %s thread action %d", action > ACTION_CLIENT_FIRST ? "client" : "reader", action); } int32_t ret = pthread_create(&cl->thread, &attr, work_thread, (void *)data); if(ret) { cs_log("ERROR: can't create thread for %s (errno=%d %s)", action > ACTION_CLIENT_FIRST ? "client" : "reader", ret, strerror(ret)); free_job_data(data); } else { pthread_detach(cl->thread); } pthread_attr_destroy(&attr); cl->thread_active = 1; pthread_mutex_unlock(&cl->thread_lock); return 1; }
int32_t cs_auth_client(struct s_client * client, struct s_auth *account, const char *e_txt) { int32_t rc = 0; unsigned char md5tmp[MD5_DIGEST_LENGTH]; char buf[32]; char *t_crypt = "encrypted"; char *t_plain = "plain"; char *t_grant = " granted"; char *t_reject = " rejected"; char *t_msg[] = { buf, "invalid access", "invalid ip", "unknown reason", "protocol not allowed" }; struct s_module *module = get_module(client); memset(&client->grp, 0xff, sizeof(uint64_t)); //client->grp=0xffffffffffffff; if ((intptr_t)account != 0 && (intptr_t)account != -1 && account->disabled) { cs_add_violation(client, account->usr); cs_log("%s %s-client %s%s (%s%sdisabled account)", client->crypted ? t_crypt : t_plain, module->desc, IP_ISSET(client->ip) ? cs_inet_ntoa(client->ip) : "", IP_ISSET(client->ip) ? t_reject : t_reject+1, e_txt ? e_txt : "", e_txt ? " " : ""); return 1; } // check whether client comes in over allowed protocol if ((intptr_t)account != 0 && (intptr_t)account != -1 && (intptr_t)account->allowedprotocols && (((intptr_t)account->allowedprotocols & module->listenertype) != module->listenertype)) { cs_add_violation(client, account->usr); cs_log("%s %s-client %s%s (%s%sprotocol not allowed)", client->crypted ? t_crypt : t_plain, module->desc, IP_ISSET(client->ip) ? cs_inet_ntoa(client->ip) : "", IP_ISSET(client->ip) ? t_reject : t_reject+1, e_txt ? e_txt : "", e_txt ? " " : ""); return 1; } client->account = first_client->account; switch((intptr_t)account) { case 0: { // reject access rc = 1; cs_add_violation(client, NULL); cs_log("%s %s-client %s%s (%s)", client->crypted ? t_crypt : t_plain, module->desc, IP_ISSET(client->ip) ? cs_inet_ntoa(client->ip) : "", IP_ISSET(client->ip) ? t_reject : t_reject+1, e_txt ? e_txt : t_msg[rc]); break; } default: { // grant/check access if (IP_ISSET(client->ip) && account->dyndns) { if (!IP_EQUAL(client->ip, account->dynip)) cs_user_resolve(account); if (!IP_EQUAL(client->ip, account->dynip)) { cs_add_violation(client, account->usr); rc=2; } } client->monlvl = account->monlvl; client->account = account; if (!rc) { client->dup=0; if (client->typ=='c' || client->typ=='m') client->pcrc = crc32(0L, MD5((uchar *)(ESTR(account->pwd)), strlen(ESTR(account->pwd)), md5tmp), MD5_DIGEST_LENGTH); if (client->typ=='c') { client->last_caid = NO_CAID_VALUE; client->last_srvid = NO_SRVID_VALUE; client->expirationdate = account->expirationdate; client->disabled = account->disabled; client->allowedtimeframe[0] = account->allowedtimeframe[0]; client->allowedtimeframe[1] = account->allowedtimeframe[1]; if (account->firstlogin == 0) account->firstlogin = time((time_t*)0); client->failban = account->failban; client->c35_suppresscmd08 = account->c35_suppresscmd08; client->ncd_keepalive = account->ncd_keepalive; client->grp = account->grp; client->aureader_list = account->aureader_list; client->autoau = account->autoau; client->tosleep = (60*account->tosleep); client->c35_sleepsend = account->c35_sleepsend; memcpy(&client->ctab, &account->ctab, sizeof(client->ctab)); if (account->uniq) cs_fake_client(client, account->usr, account->uniq, client->ip); client->ftab = account->ftab; // IDENT filter client->cltab = account->cltab; // CLASS filter client->fchid = account->fchid; // CHID filter client->sidtabs.ok= account->sidtabs.ok; // services client->sidtabs.no= account->sidtabs.no; // services memcpy(&client->ttab, &account->ttab, sizeof(client->ttab)); ac_init_client(client, account); } } } case -1: { // anonymous grant access if (rc) { t_grant = t_reject; } else { if (client->typ == 'm') { snprintf(t_msg[0], sizeof(buf), "lvl=%d", client->monlvl); } else { int32_t rcount = ll_count(client->aureader_list); snprintf(buf, sizeof(buf), "au="); if (!rcount) snprintf(buf+3, sizeof(buf)-3, "off"); else { if (client->autoau) snprintf(buf+3, sizeof(buf)-3, "auto (%d reader)", rcount); else snprintf(buf+3, sizeof(buf)-3, "on (%d reader)", rcount); } } } cs_log("%s %s-client %s%s (%s, %s)", client->crypted ? t_crypt : t_plain, e_txt ? e_txt : module->desc, IP_ISSET(client->ip) ? cs_inet_ntoa(client->ip) : "", IP_ISSET(client->ip) ? t_grant : t_grant + 1, username(client), t_msg[rc]); break; } } return rc; }
static char *monitor_client_info(char id, struct s_client *cl, char *sbuf){ char channame[32]; sbuf[0] = '\0'; if (cl){ char ldate[16], ltime[16], *usr; int32_t lsec, isec, con, cau, lrt =- 1; time_t now; struct tm lt; now=time((time_t*)0); if ((cfg.hideclient_to <= 0) || (now-cl->lastecm < cfg.hideclient_to) || (now-cl->lastemm < cfg.hideclient_to) || (cl->typ != 'c')) { lsec = now - cl->login; isec = now - cl->last; usr = username(cl); if (cl->dup) con = 2; else if ((cl->tosleep) && (now-cl->lastswitch>cl->tosleep)) con = 1; else con = 0; // no AU reader == 0 / AU ok == 1 / Last EMM > aulow == -1 if(cl->typ == 'c' || cl->typ == 'p' || cl->typ == 'r') { if ((cl->typ == 'c' && ll_count(cl->aureader_list) == 0) || ((cl->typ == 'p' || cl->typ == 'r') && cl->reader->audisabled)) cau = 0; else if ((now-cl->lastemm) / 60 > cfg.aulow) cau = (-1); else cau = 1; } else { cau = 0; } if( cl->typ == 'r') { int32_t i; struct s_reader *rdr; for (i=0,rdr=first_active_reader; rdr ; rdr=rdr->next, i++) if (cl->reader == rdr) lrt=i; if( lrt >= 0 ) lrt = 10 + cl->reader->card_status; } else lrt = cl->cwlastresptime; localtime_r(&cl->login, <); snprintf(ldate, sizeof(ldate), "%02d.%02d.%02d", lt.tm_mday, lt.tm_mon+1, lt.tm_year % 100); int32_t cnr=get_threadnum(cl); snprintf(ltime, sizeof(ldate), "%02d:%02d:%02d", lt.tm_hour, lt.tm_min, lt.tm_sec); snprintf(sbuf, 256, "[%c--CCC]%8X|%c|%d|%s|%d|%d|%s|%d|%s|%s|%s|%d|%04X:%04X|%s|%d|%d|%d|%d|%d|%d|%d|%d|%d|%d\n", id, cl->tid, cl->typ, cnr, usr, cau, cl->crypted, cs_inet_ntoa(cl->ip), cl->port, client_get_proto(cl), ldate, ltime, lsec, cl->last_caid, cl->last_srvid, get_servicename(cl, cl->last_srvid, cl->last_caid, channame), isec, con, cl->cwfound, cl->cwnot, cl->cwcache, cl->cwignored, cl->cwtout, cl->emmok, cl->emmnok, lrt); } } return sbuf; }
//----------------------------------------------------------------------------- // A request has been received for a queue. We need take it and pass it to a // node that can handle the request. static void cmdRequest(void *base) { node_t *node = (node_t *) base; message_t *msg; queue_t *q; stats_t *stats; assert(node); assert(node->handle >= 0); assert(node->sysdata); logger(node->sysdata->logging, 3, "node:%d REQUEST (flags:%x, mask:%x)", node->handle, node->data.flags, node->data.mask); assert(node->sysdata->queues); assert(node->sysdata->bufpool); // make sure we have the required data. At least payload, and a queueid or queue. if (BIT_TEST(node->data.mask, DATA_MASK_PAYLOAD) && (BIT_TEST(node->data.mask, DATA_MASK_QUEUE) || BIT_TEST(node->data.mask, DATA_MASK_QUEUEID))) { // create the message object to hold the data. assert(node->sysdata->msg_list); msg = next_message(node); assert(msg); // The node should have received a payload command. It would have been // assigned to an appropriate buffer. We need to move that buffer to the // message, where it will be handled from there. assert(node->data.payload); assert(msg->data == NULL); msg->data = node->data.payload; node->data.payload = NULL; // if message is NOREPLY, then we dont need some bits. However, we will need to send a DELIVERED. if (BIT_TEST(node->data.flags, DATA_FLAG_NOREPLY)) { BIT_SET(msg->flags, FLAG_MSG_NOREPLY); assert(msg->source_id == 0); // the source_node would have been set when the message object was // obtained. But since we dont want it in this mode, we set it to // NULL. assert(msg->source_node != NULL); msg->source_node = NULL; assert(BIT_TEST(node->data.mask, DATA_MASK_ID)); sendDelivered(node, node->data.id); } else { assert(BIT_TEST(msg->flags, FLAG_MSG_NOREPLY) == 0); // make a note in the msg object, the source node. If a reply is // expected, a messageid should also have been supplied, use that for // the node_side. assert(msg->source_node == node); assert(BIT_TEST(node->data.mask, DATA_MASK_ID)); message_set_origid(msg, node->data.id); } if (BIT_TEST(node->data.mask, DATA_MASK_TIMEOUT)) { // set the timeout... message_set_timeout(msg, node->data.timeout); } // find the q object for this queue. if (BIT_TEST(node->data.mask, DATA_MASK_QUEUE)) { q = queue_get_name(node->sysdata->queues, expbuf_string(&node->data.queue)); } else if (BIT_TEST(node->data.mask, DATA_MASK_QUEUEID)) { q = queue_get_id(node->sysdata->queues, node->data.qid); } else { assert(0); } if (q == NULL) { // we dont have a queue, so we will need to create one. q = queue_create(node->sysdata, expbuf_string(&node->data.queue)); } assert(q); assert(ll_count(node->sysdata->queues) > 0); // add the message to the queue. logger(node->sysdata->logging, 2, "processRequest: node:%d, msg_id:%d, q:%d", node->handle, msg->id, q->qid); assert(q->sysdata); queue_addmsg(q, msg); stats = node->sysdata->stats; assert(stats); stats->requests ++; } else { // required data was not found. // need to return some sort of error assert(0); } }
void cc_cacheex_push_in(struct s_client *cl, uchar *buf) { struct cc_data *cc = cl->cc; ECM_REQUEST *er; if(!cc) { return; } if(cl->reader) { cl->reader->last_s = cl->reader->last_g = time((time_t *)0); } if(cl) { cl->last = time(NULL); } int8_t rc = buf[14]; if(rc != E_FOUND && rc != E_UNHANDLED) //Maybe later we could support other rcs { return; } uint16_t size = buf[12] | (buf[13] << 8); if(size != sizeof(er->ecmd5) + sizeof(er->csp_hash) + sizeof(er->cw)) { cs_log_dbg(D_CACHEEX, "cacheex: %s received old cash-push format! data ignored!", username(cl)); return; } if(!(er = get_ecmtask())) { return; } er->caid = b2i(2, buf + 0); er->prid = b2i(4, buf + 2); er->srvid = b2i(2, buf + 10); er->ecm[0] = buf[19]!=0x80 && buf[19]!=0x81 ? 0 : buf[19]; //odd/even byte, usefull to send it over CSP and to check cw for swapping er->rc = rc; er->ecmlen = 0; if(buf[18]) { if(buf[18] & (0x01 << 7)) { er->cwc_cycletime = (buf[18] & 0x7F); // remove bit 8 to get cycletime er->cwc_next_cw_cycle = 1; } else { er->cwc_cycletime = buf[18]; er->cwc_next_cw_cycle = 0; } } if (er->cwc_cycletime && er->cwc_next_cw_cycle < 2) { if(cl->typ == 'c' && cl->account && cl->account->cacheex.mode) { cl->account->cwc_info++; } else if((cl->typ == 'p' || cl->typ == 'r') && (cl->reader && cl->reader->cacheex.mode)) { cl->cwc_info++; } cs_log_dbg(D_CWC, "CWC (CE) received from %s cycletime: %isek - nextcwcycle: CW%i for %04X@%06X:%04X", username(cl), er->cwc_cycletime, er->cwc_next_cw_cycle, er->caid, er->prid, er->srvid); } uint8_t *ofs = buf + 20; //Read ecmd5 memcpy(er->ecmd5, ofs, sizeof(er->ecmd5)); //16 ofs += sizeof(er->ecmd5); if(!check_cacheex_filter(cl, er)) { return; } //Read csp_hash: er->csp_hash = ntohl(b2i(4, ofs)); ofs += 4; //Read cw: memcpy(er->cw, ofs, sizeof(er->cw)); //16 ofs += sizeof(er->cw); //Read lastnode count: uint8_t count = *ofs; ofs++; //check max nodes: if(count > cacheex_maxhop(cl)) { cs_log_dbg(D_CACHEEX, "cacheex: received %d nodes (max=%d), ignored! %s", (int32_t)count, cacheex_maxhop(cl), username(cl)); NULLFREE(er); return; } cs_log_dbg(D_CACHEEX, "cacheex: received %d nodes %s", (int32_t)count, username(cl)); //Read lastnodes: uint8_t *data; if (er){ er->csp_lastnodes = ll_create("csp_lastnodes"); } while(count) { if(!cs_malloc(&data, 8)) { break; } memcpy(data, ofs, 8); ofs += 8; ll_append(er->csp_lastnodes, data); count--; cs_log_dbg(D_CACHEEX, "cacheex: received node %" PRIu64 "X %s", cacheex_node_id(data), username(cl)); } //for compatibility: add peer node if no node received: if(!ll_count(er->csp_lastnodes)) { if(!cs_malloc(&data, 8)) { return; } memcpy(data, cc->peer_node_id, 8); ll_append(er->csp_lastnodes, data); cs_log_dbg(D_CACHEEX, "cacheex: added missing remote node id %" PRIu64 "X", cacheex_node_id(data)); } cacheex_add_to_cache(cl, er); }
static void stats_handler(int fd, short int flags, void *arg) { stats_t *stats; system_data_t *sysdata; int clients; int queues; int msg_pending, msg_proc; queue_t *q; assert(fd < 0); assert((flags & EV_TIMEOUT) == EV_TIMEOUT); assert(arg); stats = arg; // clear the stats event. assert(stats->stats_event); event_free(stats->stats_event); stats->stats_event = NULL; assert(stats->sysdata); sysdata = stats->sysdata; // assert(stats->sysdata->server != NULL); // server = stats->sysdata->server; assert(sysdata->nodelist); clients = ll_count(sysdata->nodelist); queues = 0; msg_pending = 0; msg_proc = 0; ll_start(sysdata->queues); while ((q = ll_next(sysdata->queues))) { queues ++; msg_pending += ll_count(&q->msg_pending); msg_proc += ll_count(&q->msg_proc); } ll_finish(sysdata->queues); assert(stats != NULL); if (stats->in_bytes || stats->out_bytes || stats->requests || stats->replies || stats->broadcasts || stats->re || stats->we) { logger(sysdata->logging, 1, "Bytes[%u/%u], Clients[%u], Requests[%u], Replies[%u], Broadcasts[%u], Queues[%u], Msgs[%d/%d], MsgPool[%u/%u], Events[%u/%u/%u]", stats->in_bytes, stats->out_bytes, clients, stats->requests, stats->replies, stats->broadcasts, queues, msg_pending, msg_proc, sysdata->msg_used, sysdata->msg_max, stats->re, stats->we, stats->te); stats->in_bytes = 0; stats->out_bytes = 0; stats->requests = 0; stats->replies = 0; stats->broadcasts = 0; stats->re = 0; stats->we = 0; stats->te = 0; } // if we are not shutting down, then schedule the stats event again. if (stats->shutdown == 0) { stats_start(stats); } }
int mst_kruksal(struct vertex *arr1[],struct vertex *arr2[],int arg_weight,int nodes) { int i,j,k=0,l=0,flag=0,first_flag1=1,count1=0,random_weight,vertex1,vertex2; struct vertex *temp1; int F[MAX-1][3]; /* set of edges in min. span. tree */ int num_edges = 0,edges=0; /* num of edges in min. span. tree */ int next_edge = 0; /* next edge not yet considered */ int weight = 0; /* minimal spanning tree weight */ int a,b,c; /* counter/placeholder variables */ for(i=0; i<nodes; i++) { temp1 = arr1[i]; vertex1 = arr1[i]->vertex_id; count1 = ll_count(arr1[i]); first_flag1 = 1; for(j=0; j<count1; j++) { if(first_flag1 == 1) { first_flag1 = 0; } else { vertex2 = arr1[i]->vertex_id; mst_edge_matrix[k][0] = vertex1; /* first vertex of edge */ mst_edge_matrix[k][1] = vertex2; /* second vertex of edge */ random_weight = (1 + rand() % arg_weight); if(random_weight == 0) { random_weight = arg_weight; } //printf("\nv1 %d",vertex1); //printf("\nv2 %d",vertex2); //printf("\nw1 %d",random_weight); for(l=0; l<k; l++) { if((mst_edge_matrix[l][0] == vertex2) && (mst_edge_matrix[l][1] == vertex1)) { //printf("\nmatch"); mst_edge_matrix[k][2] = mst_edge_matrix[l][2]; /* weight of edge */ flag = 1; break; } } if(flag != 1) { mst_edge_matrix[k][2] = random_weight; } k++; flag = 0; } if(arr1[i]->next !=NULL) { arr1[i] = arr1[i]->next; } } arr1[i] = temp1; } edges = k; /* Display edges */ printf("\n\n"); printf("Edges with Weights:\n"); printf("Edge\tEdge\tWeight\n"); for (i = 0; i < edges; i++) { for (j = 0; j < 3; j++) { printf("%d\t", mst_edge_matrix[i][j]); } printf("\n"); } for (i = edges - 1; i > 0; i--) { for (j = 0; j < i; j++) { if (mst_edge_matrix[j][2] > mst_edge_matrix[j+1][2]) { a = mst_edge_matrix[j][0]; b = mst_edge_matrix[j][1]; c = mst_edge_matrix[j][2]; mst_edge_matrix[j][0] = mst_edge_matrix[j+1][0]; mst_edge_matrix[j][1] = mst_edge_matrix[j+1][1]; mst_edge_matrix[j][2] = mst_edge_matrix[j+1][2]; mst_edge_matrix[j+1][0] = a; mst_edge_matrix[j+1][1] = b; mst_edge_matrix[j+1][2] = c; } } } /* Display edges */ /*printf("\n"); for (i = 0; i < edges; i++) { for (j = 0; j < 3; j++) { printf(" %3d", mst_edge_matrix[i][j]); } printf("\n"); }*/ /* create n disjoint subsets */ mst_initial (nodes); /* initialize set of edges in min. span. tree to empty */ for (i = 0; i < nodes - 1; i++) { for (j = 0; j < 3; j++) { F[i][j] = -1; /* '-1' denotes 'empty' */ } } //mst_test_univ(nodes); /* find minimal spanning tree */ while (num_edges < nodes - 1) { a = mst_edge_matrix[next_edge][0]; b = mst_edge_matrix[next_edge][1]; i = mst_find(a); j = mst_find(b); if (!mst_equal(i, j)) { mst_merge (i, j); F[num_edges][0] = mst_edge_matrix[next_edge][0]; F[num_edges][1] = mst_edge_matrix[next_edge][1]; F[num_edges][2] = mst_edge_matrix[next_edge][2]; num_edges++; //mst_test_univ(nodes); } next_edge++; } /* display edges comprising minimal spanning tree */ printf("\n"); printf("\nMinimal Spanning Tree Edges:\n"); printf("F = ("); for (i = 0; i < nodes - 1; i++) { printf("(V%d,V%d)", F[i][0], F[i][1]); if (i < nodes - 2) { printf(", "); } printf("W:%d ",F[i][2]); weight = weight + F[i][2]; } printf(")\n"); return weight; }
static int32_t ghttp_recv_chk(struct s_client *client, uchar *dcw, int32_t *rc, uchar *buf, int32_t n) { char *data; char *hdrstr; uchar *content; int rcode, len, clen = 0; s_ghttp *context = (s_ghttp *)client->ghttp; ECM_REQUEST *er = NULL; if(n < 5) { return -1; } data = strstr((char *)buf, "HTTP/1.1 "); if(!data || ll_count(context->ecm_q) > 6) { cs_debug_mask(D_CLIENT, "%s: non http or otherwise corrupt response: %s", client->reader->label, buf); cs_ddump_mask(D_CLIENT, buf, n, "%s: ", client->reader->label); network_tcp_connection_close(client->reader, "receive error"); NULLFREE(context->session_id); ll_clear(context->ecm_q); return -1; } LL_ITER itr = ll_iter_create(context->ecm_q); er = (ECM_REQUEST *)ll_iter_next(&itr); rcode = _get_int_header(buf, "HTTP/1.1 "); clen = _get_int_header(buf, "Content-Length: "); content = (uchar *)(strstr(data, "\r\n\r\n") + 4); hdrstr = _get_header_substr(buf, "ETag: \"", "\"\r\n"); if(hdrstr) { NULLFREE(context->host_id); context->host_id = (uchar *)hdrstr; cs_debug_mask(D_CLIENT, "%s: new name: %s", client->reader->label, context->host_id); len = b64decode(context->host_id); if(len == 0 || len >= 64) { NULLFREE(context->host_id); } else { cs_debug_mask(D_CLIENT, "%s: redirected...", client->reader->label); NULLFREE(context->session_id); ll_clear_data(ghttp_ignored_contexts); ll_clear(context->ecm_q); return -1; } } hdrstr = _get_header_substr(buf, "ETag: W/\"", "\"\r\n"); if(hdrstr) { NULLFREE(context->fallback_id); context->fallback_id = (uchar *)hdrstr; cs_debug_mask(D_CLIENT, "%s: new fallback name: %s", client->reader->label, context->fallback_id); len = b64decode(context->fallback_id); if(len == 0 || len >= 64) { NULLFREE(context->fallback_id); } } hdrstr = _get_header(buf, "Set-Cookie: GSSID="); if(hdrstr) { NULLFREE(context->session_id); context->session_id = (uchar *)hdrstr; cs_debug_mask(D_CLIENT, "%s: set session_id to: %s", client->reader->label, context->session_id); } // buf[n] = '\0'; // cs_ddump_mask(D_TRACE, content, clen, "%s: reply\n%s", client->reader->label, buf); if(rcode < 200 || rcode > 204) { cs_debug_mask(D_CLIENT, "%s: http error code %d", client->reader->label, rcode); data = strstr((char *)buf, "Content-Type: application/octet-stream"); // if not octet-stream, google error. need reconnect? if(data) // we have error info string in the post content { if(clen > 0) { content[clen] = '\0'; cs_debug_mask(D_CLIENT, "%s: http error message: %s", client->reader->label, content); } } if(rcode == 503) { if(er && _is_post_context(context->post_contexts, er, false)) { if(_swap_hosts(context)) { cs_debug_mask(D_CLIENT, "%s: switching to fallback", client->reader->label); } else { cs_debug_mask(D_CLIENT, "%s: recv_chk got 503 despite post, trying reconnect", client->reader->label); network_tcp_connection_close(client->reader, "reconnect"); ll_clear(context->ecm_q); } } else { // on 503 cache timeout, retry with POST immediately (and switch to POST for subsequent) if(er) { _set_pid_status(context->post_contexts, er->onid, er->tsid, er->srvid, 0); cs_debug_mask(D_CLIENT, "%s: recv_chk got 503, trying direct post", client->reader->label); _ghttp_post_ecmdata(client, er); } } } else if(rcode == 401) { NULLFREE(context->session_id); if(er) { cs_debug_mask(D_CLIENT, "%s: session expired, trying direct post", client->reader->label); _ghttp_post_ecmdata(client, er); } } else if(rcode == 403) { client->reader->enable = 0; network_tcp_connection_close(client->reader, "login failure"); ll_clear(context->ecm_q); cs_log("%s: invalid username/password, disabling reader.", client->reader->label); } // not sure if this is needed on failure, copied from newcamd *rc = 0; memset(dcw, 0, 16); return -1; } // successful http reply (200 ok or 204 no content) hdrstr = _get_header(buf, "Pragma: context-ignore="); if(hdrstr) { if(clen > 1) { cs_ddump_mask(D_CLIENT, content, clen, "%s: pmt ignore reply - %s (%d pids)", client->reader->label, hdrstr, clen / 2); uint32_t onid = 0, tsid = 0, sid = 0; if(sscanf(hdrstr, "%4x-%4x-%4x", &onid, &tsid, &sid) == 3) { _set_pids_status(ghttp_ignored_contexts, onid, tsid, sid, content, clen); } NULLFREE(hdrstr); return -1; } NULLFREE(hdrstr); } data = strstr((char *)buf, "Pragma: context-ignore-clear"); if(data) { cs_debug_mask(D_CLIENT, "%s: clearing local ignore list (size %d)", client->reader->label, ll_count(ghttp_ignored_contexts)); ll_clear_data(ghttp_ignored_contexts); } // switch back to cache get after rapid ecm response (arbitrary atm), only effect is a slight bw save for client if(!er || _is_post_context(context->post_contexts, er, false)) { data = strstr((char *)buf, "Pragma: cached"); if(data || (client->cwlastresptime > 0 && client->cwlastresptime < 640)) { cs_debug_mask(D_CLIENT, "%s: probably cached cw (%d ms), switching back to cache get for next req", client->reader->label, client->cwlastresptime); if(er) { _is_post_context(context->post_contexts, er, true); } } } if(clen == 16) // cw in content { memcpy(dcw, content, 16); *rc = 1; er = ll_remove_first(context->ecm_q); if(!er) { return -1; } cs_ddump_mask(D_TRACE, dcw, 16, "%s: cw recv chk for idx %d", client->reader->label, er->idx); return er->idx; } else { if(clen != 0) { cs_ddump_mask(D_CLIENT, content, clen, "%s: recv_chk fail, clen = %d", client->reader->label, clen); } } return -1; }
void do_emm(struct s_client * client, EMM_PACKET *ep) { char *typtext[]={"unknown", "unique", "shared", "global"}; char tmp[17]; int32_t emmnok=0; struct s_reader *aureader = NULL; cs_ddump_mask(D_EMM, ep->emm, ep->emmlen, "emm:"); int8_t cl_dvbapi = 0, assemble = 0; #ifdef HAVE_DVBAPI cl_dvbapi = streq(cfg.dvbapi_usr, client->account->usr); #endif if (client->account->emm_reassembly > 1 || (client->account->emm_reassembly && cl_dvbapi)) assemble = 1; LL_ITER itr = ll_iter_create(client->aureader_list); while ((aureader = ll_iter_next(&itr))) { if (!aureader->enable) continue; uint16_t caid = b2i(2, ep->caid); uint32_t provid = b2i(4, ep->provid); if (aureader->audisabled) { rdr_debug_mask(aureader, D_EMM, "AU is disabled"); /* we have to write the log for blocked EMM here because this EMM never reach the reader module where the rest of EMM log is done. */ if (aureader->logemm & 0x10) { rdr_log(aureader, "%s emmtype=%s, len=%d, idx=0, cnt=1: audisabled (0 ms)", client->account->usr, typtext[ep->type], ep->emm[2]); } continue; } if (!(aureader->grp & client->grp)) { rdr_debug_mask(aureader, D_EMM, "skip emm, group mismatch"); continue; } //TODO: provider possibly not set yet, this is done in get_emm_type() if (!emm_reader_match(aureader, caid, provid)) continue; struct s_cardsystem *cs = NULL; if (is_cascading_reader(aureader)) { // network reader (R_CAMD35 R_NEWCAMD R_CS378X R_CCCAM) if (!aureader->ph.c_send_emm) // no emm support continue; cs = get_cardsystem_by_caid(caid); if (!cs) { rdr_debug_mask(aureader, D_EMM, "unable to find cardsystem for caid %04X", caid); continue; } } else { // local reader if (aureader->csystem.active) cs=&aureader->csystem; } if (cs && cs->get_emm_type) { if (!cs->get_emm_type(ep, aureader)) { rdr_debug_mask(aureader, D_EMM, "emm skipped, get_emm_type() returns error"); emmnok++; continue; } } if (cs && cs->get_emm_filter) { if (!do_simple_emm_filter(aureader, cs, ep)) { rdr_debug_mask(aureader, D_EMM, "emm skipped, emm_filter() returns invalid"); emmnok++; continue; } } if (cs && cs->do_emm_reassembly) { if (assemble) { if (!cs->do_emm_reassembly(client, ep)) return; } else { rdr_debug_mask(aureader, D_EMM, "processing raw emm"); } } rdr_debug_mask_sensitive(aureader, D_EMM, "emmtype %s. Reader serial {%s}.", typtext[ep->type], cs_hexdump(0, aureader->hexserial, 8, tmp, sizeof(tmp))); rdr_debug_mask_sensitive(aureader, D_EMM, "emm UA/SA: {%s}.", cs_hexdump(0, ep->hexserial, 8, tmp, sizeof(tmp))); client->last = time(NULL); saveemm(aureader, ep); int32_t is_blocked = 0; switch (ep->type) { case UNKNOWN: is_blocked = (aureader->blockemm & EMM_UNKNOWN) == EMM_UNKNOWN; break; case UNIQUE : is_blocked = (aureader->blockemm & EMM_UNIQUE ) == EMM_UNIQUE; break; case SHARED : is_blocked = (aureader->blockemm & EMM_SHARED ) == EMM_SHARED; break; case GLOBAL : is_blocked = (aureader->blockemm & EMM_GLOBAL ) == EMM_GLOBAL; break; } // if not already blocked we check for block by len if (!is_blocked) is_blocked = cs_emmlen_is_blocked( aureader, ep->emm[2] ) ; if (is_blocked != 0) { #ifdef WEBIF aureader->emmblocked[ep->type]++; is_blocked = aureader->emmblocked[ep->type]; #endif /* we have to write the log for blocked EMM here because this EMM never reach the reader module where the rest of EMM log is done. */ if (aureader->logemm & 0x08) { rdr_log(aureader, "%s emmtype=%s, len=%d, idx=0, cnt=%d: blocked (0 ms)", client->account->usr, typtext[ep->type], ep->emm[2], is_blocked); } continue; } client->lastemm = time((time_t*)0); client->emmok++; if (client->account) client->account->emmok++; first_client->emmok++; //Check emmcache early: int32_t i; unsigned char md5tmp[CS_EMMSTORESIZE]; struct s_client *au_cl = aureader->client; MD5(ep->emm, ep->emm[2], md5tmp); ep->client = client; for (i=0; i<CS_EMMCACHESIZE; i++) { if (!memcmp(au_cl->emmcache[i].emmd5, md5tmp, CS_EMMSTORESIZE)) { rdr_debug_mask(aureader, D_EMM, "emm found in cache: count %d rewrite %d", au_cl->emmcache[i].count, aureader->rewritemm); if (aureader->cachemm && (au_cl->emmcache[i].count > aureader->rewritemm)) { reader_log_emm(aureader, ep, i, 2, NULL); return; } break; } } EMM_PACKET *emm_pack; if (cs_malloc(&emm_pack, sizeof(EMM_PACKET))) { rdr_debug_mask(aureader, D_EMM, "emm is being sent to reader"); memcpy(emm_pack, ep, sizeof(EMM_PACKET)); add_job(aureader->client, ACTION_READER_EMM, emm_pack, sizeof(EMM_PACKET)); } } if (emmnok > 0 && emmnok == ll_count(client->aureader_list)) { client->emmnok++; if (client->account) client->account->emmnok++; first_client->emmnok++; } }
static void cmdDelivered(void *base) { node_t *node = (node_t *) base; msg_id_t msgid; message_t *msg; queue_t *q; assert(node); assert(node->sysdata); logger(node->sysdata->logging, 3, "node:%d DELIVERED (flags:%x, mask:%x)", node->handle, node->data.flags, node->data.mask); // get the messageID assert(BIT_TEST(node->data.mask, DATA_MASK_ID)); msgid = node->data.id; assert(msgid >= 0); logger(node->sysdata->logging, 2, "processDelivered. Node:%d, msg_id:%d", node->handle, msgid); // find message in node->out_msg msg = node_findoutmsg(node, msgid); if (msg == NULL) { // didn't find the message that is being marked as delivered. assert(0); } else { if (BIT_TEST(msg->flags, FLAG_MSG_NOREPLY)) { // message is NOREPLY, logger(node->sysdata->logging, 2, "delivery(%d): Noreply.", msgid); // assert that message doesnt have source-node. assert(msg->source_node == NULL); // tell the queue that the node has finished processing a message. This // will find the node, and remove it from the node_busy list. assert(msg->queue); assert(msg->target_node); queue_msg_done(msg->queue, msg->target_node); // then remove from the queue->msg_proc list assert(msg->queue); q = msg->queue; ll_remove(&q->msg_proc, msg); msg->queue = NULL; // set action to remove the message. assert(BIT_TEST(msg->flags, FLAG_MSG_ACTIVE)); message_clear(msg); assert(node->sysdata->msg_used > 0); node->sysdata->msg_used --; assert(node->sysdata->msg_used >= 0); node->sysdata->msg_next = msg->id; // if there are more messages in the queue, then we need to deliver them. if (ll_count(&q->msg_pending) > 0) { logger(node->sysdata->logging, 2, "delivery(%d): setting delivery action.", msgid); queue_deliver(q); } else { logger(node->sysdata->logging, 2, "delivery(%d): no items to deliver.", msgid); } } else { // message is expecting a reply, so we need to tell the source that it was delivered. // mark the message as delivered. assert(BIT_TEST(msg->flags, FLAG_MSG_DELIVERED) == 0); BIT_SET(msg->flags, FLAG_MSG_DELIVERED); // send delivery message back to source. assert(msg->source_node); assert(msg->source_id >= 0); sendDelivered(msg->source_node, msg->source_id); // but we dont need to original payload anymore, so we can release that back into the bufpool. assert(msg->data); assert(node->sysdata); assert(node->sysdata->bufpool); expbuf_clear(msg->data); expbuf_pool_return(node->sysdata->bufpool, msg->data); msg->data = NULL; } } }
//----------------------------------------------------------------------------- // When a node indicates that it wants to consume a queue,the node needs to be // added to the queue list. If this is the first time this queue is being // consumed, then we need to create an action so that it can be consumed on // other servers. static void cmdConsume(void *base) { node_t *node = (node_t *) base; queue_t *q=NULL; int max; int priority; unsigned int qflags; assert(node); assert(node->sysdata); logger(node->sysdata->logging, 3, "node:%d CONSUME (flags:%x, mask:%x)", node->handle, node->data.flags, node->data.mask); // make sure that we have the minimum information that we need. if (BIT_TEST(node->data.mask, DATA_MASK_QUEUE)) { logger(node->sysdata->logging, 2, "Processing QUEUE request from node:%d", node->handle); assert(BIT_TEST(node->data.mask, DATA_MASK_QUEUE)); assert(BUF_LENGTH(&node->data.queue) > 0); // check to see if we already have a queue with this name, in our list. assert(q == NULL); if (node->sysdata->queues) q = queue_get_name(node->sysdata->queues, expbuf_string(&node->data.queue)); if (q == NULL) { // we didn't find the queue... logger(node->sysdata->logging, 2, "Didn't find queue '%s', creating new entry.", expbuf_string(&node->data.queue)); q = queue_create(node->sysdata, expbuf_string(&node->data.queue)); } // at this point we have a queue object. We dont yet know if this // consumption request can continue, because we haven't looked at the // queue options. assert(q != NULL); max = 0; priority = 0; qflags = 0; if (BIT_TEST(node->data.mask, DATA_MASK_MAX)) max = node->data.max; if (BIT_TEST(node->data.mask, DATA_MASK_PRIORITY)) priority = node->data.priority; if (BIT_TEST(node->data.flags, DATA_FLAG_EXCLUSIVE)) BIT_SET(qflags, QUEUE_FLAG_EXCLUSIVE); if (queue_add_node(q, node, max, priority, qflags) > 0) { // send reply back to the node. sendConsumeReply(node, q->name, q->qid); } // need to check the queue to see if there are messages pending. If there // are, then send some to this node. if (ll_count(&q->msg_pending) > 0) { queue_deliver(q); } } }
static void cmdReply(void *base) { node_t *node = (node_t *) base; msg_id_t id; message_t *msg; stats_t *stats; queue_t *q; assert(node); assert(node->handle >= 0); assert(node->sysdata); logger(node->sysdata->logging, 3, "node:%d REPLY (flags:%x, mask:%x)", node->handle, node->data.flags, node->data.mask); // make sure that we have the minimum information that we need. if (BIT_TEST(node->data.mask, DATA_MASK_ID) && BIT_TEST(node->data.mask, DATA_MASK_PAYLOAD)) { id = node->data.id; assert(id >= 0); // find the message that the reply belongs to. assert(node->sysdata); assert(node->sysdata->msg_list); assert(id < node->sysdata->msg_max); msg = node->sysdata->msg_list[id]; assert(msg); assert(msg->id == id); assert(BIT_TEST(msg->flags, FLAG_MSG_ACTIVE)); assert(msg->target_node == node); // apply the payload which is part of the reply, replacing the payload which was the request. assert(node->sysdata); assert(node->sysdata->bufpool); assert(node->data.payload); assert(msg->data == NULL); msg->data = node->data.payload; node->data.payload = NULL; // send the payload to the source node of the message. assert(msg->source_node); sendReply(msg->source_node, msg); // tell the queue that the node has finished processing a message. This // will find the node, and remove it from the node_busy list. assert(msg->queue); assert(msg->target_node); queue_msg_done(msg->queue, msg->target_node); // then remove from the queue->msg_proc list assert(msg->queue); q = msg->queue; ll_remove(&q->msg_proc, msg); msg->queue = NULL; assert(msg->data); assert(node->sysdata); assert(node->sysdata->bufpool); expbuf_clear(msg->data); expbuf_pool_return(node->sysdata->bufpool, msg->data); msg->data = NULL; // set action to remove the message. msg->source_node = NULL; msg->target_node = NULL; assert(BIT_TEST(msg->flags, FLAG_MSG_ACTIVE)); message_clear(msg); assert(node->sysdata->msg_used > 0); node->sysdata->msg_used --; assert(node->sysdata->msg_used >= 0); node->sysdata->msg_next = msg->id; // if there are more messages in the queue, then we need to deliver them. if (ll_count(&q->msg_pending) > 0) { logger(node->sysdata->logging, 2, "delivery: setting delivery action."); queue_deliver(q); } else { logger(node->sysdata->logging, 2, "delivery: no items to deliver."); } stats = node->sysdata->stats; assert(stats); stats->replies ++; } else { // we should handle failure a bit better, and log the information. assert(0); } }
void *work_thread(void *ptr) { struct job_data *data = (struct job_data *)ptr; struct s_client *cl = data->cl; struct s_reader *reader = cl->reader; struct timeb start, end; // start time poll, end time poll struct job_data tmp_data; struct pollfd pfd[1]; pthread_setspecific(getclient, cl); cl->thread = pthread_self(); cl->thread_active = 1; set_work_thread_name(data); struct s_module *module = get_module(cl); uint16_t bufsize = module->bufsize; //CCCam needs more than 1024bytes! if(!bufsize) { bufsize = 1024; } uint8_t *mbuf; if(!cs_malloc(&mbuf, bufsize)) { return NULL; } cl->work_mbuf = mbuf; // Track locally allocated data, because some callback may call cs_exit/cs_disconect_client/pthread_exit and then mbuf would be leaked int32_t n = 0, rc = 0, i, idx, s; uint8_t dcw[16]; int8_t restart_reader = 0; while(cl->thread_active) { cs_ftime(&start); // register start time while(cl->thread_active) { if(!cl || cl->kill || !is_valid_client(cl)) { pthread_mutex_lock(&cl->thread_lock); cl->thread_active = 0; pthread_mutex_unlock(&cl->thread_lock); cs_debug_mask(D_TRACE, "ending thread (kill)"); __free_job_data(cl, data); cl->work_mbuf = NULL; // Prevent free_client from freeing mbuf (->work_mbuf) free_client(cl); if(restart_reader) { restart_cardreader(reader, 0); } NULLFREE(mbuf); pthread_exit(NULL); return NULL; } if(data && data->action != ACTION_READER_CHECK_HEALTH) { cs_debug_mask(D_TRACE, "data from add_job action=%d client %c %s", data->action, cl->typ, username(cl)); } if(!data) { if(!cl->kill && cl->typ != 'r') { client_check_status(cl); } // do not call for physical readers as this might cause an endless job loop pthread_mutex_lock(&cl->thread_lock); if(cl->joblist && ll_count(cl->joblist) > 0) { LL_ITER itr = ll_iter_create(cl->joblist); data = ll_iter_next_remove(&itr); if(data) { set_work_thread_name(data); } //cs_debug_mask(D_TRACE, "start next job from list action=%d", data->action); } pthread_mutex_unlock(&cl->thread_lock); } if(!data) { /* for serial client cl->pfd is file descriptor for serial port not socket for example: pfd=open("/dev/ttyUSB0"); */ if(!cl->pfd || module->listenertype == LIS_SERIAL) { break; } pfd[0].fd = cl->pfd; pfd[0].events = POLLIN | POLLPRI; pthread_mutex_lock(&cl->thread_lock); cl->thread_active = 2; pthread_mutex_unlock(&cl->thread_lock); rc = poll(pfd, 1, 3000); pthread_mutex_lock(&cl->thread_lock); cl->thread_active = 1; pthread_mutex_unlock(&cl->thread_lock); if(rc > 0) { cs_ftime(&end); // register end time cs_debug_mask(D_TRACE, "[OSCAM-WORK] new event %d occurred on fd %d after %"PRId64" ms inactivity", pfd[0].revents, pfd[0].fd, comp_timeb(&end, &start)); data = &tmp_data; data->ptr = NULL; cs_ftime(&start); // register start time for new poll next run if(reader) { data->action = ACTION_READER_REMOTE; } else { if(cl->is_udp) { data->action = ACTION_CLIENT_UDP; data->ptr = mbuf; data->len = bufsize; } else { data->action = ACTION_CLIENT_TCP; } if(pfd[0].revents & (POLLHUP | POLLNVAL | POLLERR)) { cl->kill = 1; } } } } if(!data) { continue; } if(!reader && data->action < ACTION_CLIENT_FIRST) { __free_job_data(cl, data); break; } if(!data->action) { break; } struct timeb actualtime; cs_ftime(&actualtime); int32_t gone = comp_timeb(&actualtime, &data->time); if(data != &tmp_data && gone > (int) cfg.ctimeout+1000) { cs_debug_mask(D_TRACE, "dropping client data for %s time %dms", username(cl), gone); __free_job_data(cl, data); continue; } if(data != &tmp_data) { cl->work_job_data = data; } // Track the current job_data switch(data->action) { case ACTION_READER_IDLE: reader_do_idle(reader); break; case ACTION_READER_REMOTE: s = check_fd_for_data(cl->pfd); if(s == 0) // no data, another thread already read from fd? { break; } if(s < 0) { if(reader->ph.type == MOD_CONN_TCP) { network_tcp_connection_close(reader, "disconnect"); } break; } rc = reader->ph.recv(cl, mbuf, bufsize); if(rc < 0) { if(reader->ph.type == MOD_CONN_TCP) { network_tcp_connection_close(reader, "disconnect on receive"); } break; } cl->last = time(NULL); // *********************************** TO BE REPLACE BY CS_FTIME() LATER **************** idx = reader->ph.c_recv_chk(cl, dcw, &rc, mbuf, rc); if(idx < 0) { break; } // no dcw received if(!idx) { idx = cl->last_idx; } reader->last_g = time(NULL); // *********************************** TO BE REPLACE BY CS_FTIME() LATER **************** // for reconnect timeout for(i = 0, n = 0; i < cfg.max_pending && n == 0; i++) { if(cl->ecmtask[i].idx == idx) { cl->pending--; casc_check_dcw(reader, i, rc, dcw); n++; } } break; case ACTION_READER_RESET: cardreader_do_reset(reader); break; case ACTION_READER_ECM_REQUEST: reader_get_ecm(reader, data->ptr); break; case ACTION_READER_EMM: reader_do_emm(reader, data->ptr); break; case ACTION_READER_CARDINFO: reader_do_card_info(reader); break; case ACTION_READER_INIT: if(!cl->init_done) { reader_init(reader); } break; case ACTION_READER_RESTART: cl->kill = 1; restart_reader = 1; break; case ACTION_READER_RESET_FAST: reader->card_status = CARD_NEED_INIT; cardreader_do_reset(reader); break; case ACTION_READER_CHECK_HEALTH: cardreader_do_checkhealth(reader); break; case ACTION_READER_CAPMT_NOTIFY: if(reader->ph.c_capmt) { reader->ph.c_capmt(cl, data->ptr); } break; case ACTION_CLIENT_UDP: n = module->recv(cl, data->ptr, data->len); if(n < 0) { break; } module->s_handler(cl, data->ptr, n); break; case ACTION_CLIENT_TCP: s = check_fd_for_data(cl->pfd); if(s == 0) // no data, another thread already read from fd? { break; } if(s < 0) // system error or fd wants to be closed { cl->kill = 1; // kill client on next run continue; } n = module->recv(cl, mbuf, bufsize); if(n < 0) { cl->kill = 1; // kill client on next run continue; } module->s_handler(cl, mbuf, n); break; case ACTION_CACHEEX_TIMEOUT: #ifdef CS_CACHEEX cacheex_timeout(data->ptr); #endif break; case ACTION_FALLBACK_TIMEOUT: fallback_timeout(data->ptr); break; case ACTION_CLIENT_TIMEOUT: ecm_timeout(data->ptr); break; case ACTION_ECM_ANSWER_READER: chk_dcw(data->ptr); break; case ACTION_ECM_ANSWER_CACHE: write_ecm_answer_fromcache(data->ptr); break; case ACTION_CLIENT_INIT: if(module->s_init) { module->s_init(cl); } cl->is_udp = module->type == MOD_CONN_UDP; cl->init_done = 1; break; case ACTION_CLIENT_IDLE: if(module->s_idle) { module->s_idle(cl); } else { cs_log("user %s reached %d sec idle limit.", username(cl), cfg.cmaxidle); cl->kill = 1; } break; case ACTION_CACHE_PUSH_OUT: { #ifdef CS_CACHEEX ECM_REQUEST *er = data->ptr; int32_t res = 0, stats = -1; // cc-nodeid-list-check if(reader) { if(reader->ph.c_cache_push_chk && !reader->ph.c_cache_push_chk(cl, er)) { break; } res = reader->ph.c_cache_push(cl, er); stats = cacheex_add_stats(cl, er->caid, er->srvid, er->prid, 0); } else { if(module->c_cache_push_chk && !module->c_cache_push_chk(cl, er)) { break; } res = module->c_cache_push(cl, er); } debug_ecm(D_CACHEEX, "pushed ECM %s to %s res %d stats %d", buf, username(cl), res, stats); cl->cwcacheexpush++; if(cl->account) { cl->account->cwcacheexpush++; } first_client->cwcacheexpush++; #endif break; } case ACTION_CLIENT_KILL: cl->kill = 1; break; case ACTION_CLIENT_SEND_MSG: { #ifdef MODULE_CCCAM struct s_clientmsg *clientmsg = (struct s_clientmsg *)data->ptr; cc_cmd_send(cl, clientmsg->msg, clientmsg->len, clientmsg->cmd); #endif break; } } // switch __free_job_data(cl, data); } if(thread_pipe[1] && (mbuf[0] != 0x00)) { cs_ddump_mask(D_TRACE, mbuf, 1, "[OSCAM-WORK] Write to pipe:"); if(write(thread_pipe[1], mbuf, 1) == -1) // wakeup client check { cs_debug_mask(D_TRACE, "[OSCAM-WORK] Writing to pipe failed (errno=%d %s)", errno, strerror(errno)); } } // Check for some race condition where while we ended, another thread added a job pthread_mutex_lock(&cl->thread_lock); if(cl->joblist && ll_count(cl->joblist) > 0) { pthread_mutex_unlock(&cl->thread_lock); continue; } else { cl->thread_active = 0; pthread_mutex_unlock(&cl->thread_lock); break; } } cl->thread_active = 0; cl->work_mbuf = NULL; // Prevent free_client from freeing mbuf (->work_mbuf) NULLFREE(mbuf); pthread_exit(NULL); return NULL; }
static void log_cacheex_cw(ECM_REQUEST *er, char *reason) { uint8_t *data; uint8_t remotenodeid[8]; data = ll_last_element(er->csp_lastnodes); if(data) { memcpy(remotenodeid, data, 8); } else { memset(remotenodeid, 0 , 8); } char buf_ecm[109]; format_ecm(er, buf_ecm, 109); cs_log_dbg(D_CACHEEX,"got pushed ecm [%s]: %s - odd/even 0x%x - CSP cw: %s - pushed from %s, at hop %d, origin node-id %" PRIu64 "X", reason, buf_ecm, er->ecm[0], (checkECMD5(er)?"NO":"YES"), er->from_csp ? "csp" : username((er->cacheex_src?er->cacheex_src:er->client)), ll_count(er->csp_lastnodes), er->csp_lastnodes ? cacheex_node_id(remotenodeid): 0); }
static int32_t cc_cacheex_push_out(struct s_client *cl, struct ecm_request_t *er) { int8_t rc = (er->rc < E_NOTFOUND) ? E_FOUND : er->rc; if(rc != E_FOUND && rc != E_UNHANDLED) { return -1; } //Maybe later we could support other rcs if(cl->reader) { if(!cl->reader->tcp_connected) { cc_cli_connect(cl); } } struct cc_data *cc = cl->cc; if(!cc || !cl->udp_fd) { cs_log_dbg(D_CACHEEX, "cacheex: not connected %s -> no push", username(cl)); return (-1); } uint32_t size = sizeof(er->ecmd5) + sizeof(er->csp_hash) + sizeof(er->cw) + sizeof(uint8_t) + (ll_count(er->csp_lastnodes) + 1) * 8; unsigned char *buf; if(!cs_malloc(&buf, size + 20)) //camd35_send() adds +20 { return -1; } // build ecm message //buf[0] = er->caid >> 8; //buf[1] = er->caid & 0xff; //buf[2] = er->prid >> 24; //buf[3] = er->prid >> 16; //buf[4] = er->prid >> 8; //buf[5] = er->prid & 0xff; //buf[10] = er->srvid >> 8; //buf[11] = er->srvid & 0xff; buf[12] = (sizeof(er->ecmd5) + sizeof(er->csp_hash) + sizeof(er->cw)) & 0xff; buf[13] = (sizeof(er->ecmd5) + sizeof(er->csp_hash) + sizeof(er->cw)) >> 8; //buf[12] = 0; //buf[13] = 0; buf[14] = rc; i2b_buf(2, er->caid, buf + 0); i2b_buf(4, er->prid, buf + 2); i2b_buf(2, er->srvid, buf + 10); if(er->cwc_cycletime && er->cwc_next_cw_cycle < 2) { buf[18] = er->cwc_cycletime; // contains cwc stage3 cycletime if(er->cwc_next_cw_cycle == 1) { buf[18] = (buf[18] | 0x80); } // set bit 8 to high if(cl->typ == 'c' && cl->account && cl->account->cacheex.mode) { cl->account->cwc_info++; } else if((cl->typ == 'p' || cl->typ == 'r') && (cl->reader && cl->reader->cacheex.mode)) { cl->cwc_info++; } cs_log_dbg(D_CWC, "CWC (CE) push to %s cycletime: %isek - nextcwcycle: CW%i for %04X@%06X:%04X", username(cl), er->cwc_cycletime, er->cwc_next_cw_cycle, er->caid, er->prid, er->srvid); } buf[19] = er->ecm[0] != 0x80 && er->ecm[0] != 0x81 ? 0 : er->ecm[0]; uint8_t *ofs = buf + 20; //write oscam ecmd5: memcpy(ofs, er->ecmd5, sizeof(er->ecmd5)); //16 ofs += sizeof(er->ecmd5); //write csp hashcode: i2b_buf(4, htonl(er->csp_hash), ofs); ofs += 4; //write cw: memcpy(ofs, er->cw, sizeof(er->cw)); //16 ofs += sizeof(er->cw); //write node count: *ofs = ll_count(er->csp_lastnodes) + 1; ofs++; //write own node: memcpy(ofs, cc->node_id, 8); ofs += 8; //write other nodes: LL_LOCKITER *li = ll_li_create(er->csp_lastnodes, 0); uint8_t *node; while((node = ll_li_next(li))) { memcpy(ofs, node, 8); ofs += 8; } ll_li_destroy(li); int32_t res = cc_cmd_send(cl, buf, size + 20, MSG_CACHE_PUSH); if(res > 0) // cache-ex is pushing out, so no receive but last_g should be updated otherwise disconnect! { if(cl->reader) { cl->reader->last_s = cl->reader->last_g = time((time_t *)0); } // correct if(cl) { cl->last = time(NULL); } } NULLFREE(buf); return res; }
void printZlibInfo(const std::vector<unsigned char>& in, const Options& options) { if(!options.zlib_info && !options.zlib_blocks) return; std::vector<lodepng::ZlibBlockInfo> zlibinfo; lodepng::extractZlibInfo(zlibinfo, in); if(options.zlib_info) { //std::cout << "Zlib info: " << std::endl; size_t compressed = 0; size_t uncompressed = 0; std::vector<size_t> boundaries_compressed; std::vector<size_t> boundaries_uncompressed; for(size_t i = 0; i < zlibinfo.size(); i++) { compressed += zlibinfo[i].compressedbits / 8; uncompressed += zlibinfo[i].uncompressedbytes; boundaries_compressed.push_back(compressed); boundaries_uncompressed.push_back(uncompressed); } std::cout << "Compressed size: " << compressed << std::endl; std::cout << "Uncompressed size: " << uncompressed << std::endl; std::cout << "Amount of zlib blocks: " << zlibinfo.size() << std::endl; if(zlibinfo.size() > 1) { std::cout << "Block sizes (uncompressed): "; for(size_t i = 0; i < zlibinfo.size(); i++) std::cout << zlibinfo[i].uncompressedbytes << " "; std::cout << std::endl; std::cout << "Block sizes (compressed): "; for(size_t i = 0; i < zlibinfo.size(); i++) std::cout << (zlibinfo[i].compressedbits / 8) << " "; std::cout << std::endl; std::cout << "Block boundaries (uncompressed): "; for(size_t i = 0; i + 1 < boundaries_uncompressed.size(); i++) std::cout << boundaries_uncompressed[i] << " "; std::cout << std::endl; std::cout << "Block boundaries (compressed): "; for(size_t i = 0; i + 1 < boundaries_compressed.size(); i++) std::cout << boundaries_compressed[i] << " "; std::cout << std::endl; } } if(options.zlib_blocks) { for(size_t i = 0; i < zlibinfo.size(); i++) { const lodepng::ZlibBlockInfo& info = zlibinfo[i]; std::cout << "Zlib block " << i << ":" << std::endl; std::cout << " block type: " << info.btype << std::endl; size_t compressedsize = info.compressedbits / 8; size_t uncompressedsize = info.uncompressedbytes; std::cout << " block compressed: " << compressedsize << " (" << compressedsize / 1024 << "K) (" << info.compressedbits << " bits)" << std::endl; std::cout << " block uncompressed: " << uncompressedsize << " (" << uncompressedsize / 1024 << "K)" << std::endl; if(info.btype > 2) { std::cout << "Error: Invalid Block Type" << std::endl; return; } if(info.btype == 2) { std::cout << " encoded trees size: " << info.treebits / 8 << " (" << info.treebits << " bits)" << std::endl; std::cout << " HLIT: " << info.hlit << std::endl; std::cout << " HDIST: " << info.hdist << std::endl; std::cout << " HCLEN: " << info.hclen << std::endl; std::cout << std::hex; std::cout << " code length code lengths: "; for(size_t j = 0; j < 19; j++) std::cout << info.clcl[j]; std::cout << std::endl; if(!options.use_hex) std::cout << std::dec; if(options.zlib_full) { for(size_t j = 0; j < info.treecodes.size(); j++) { int code = info.treecodes[j]; if(code < 17) { std::cout << " tree: " << code << std::endl; } else { j++; std::cout << " tree: " << code << " rep: " << info.treecodes[j] << std::endl; } } } std::cout << std::hex; std::cout << " lit code lengths 0-127 : "; for(size_t j = 0; j < 128; j++) std::cout << info.litlenlengths[j]; std::cout << std::endl; std::cout << " lit code lengths 128-255: "; for(size_t j = 128; j < 256; j++) std::cout << info.litlenlengths[j]; std::cout << std::endl; std::cout << " end code length : "; std::cout << info.litlenlengths[256]; std::cout << std::endl; std::cout << " len code lengths : "; for(size_t j = 257; j < 288; j++) std::cout << info.litlenlengths[j]; std::cout << std::endl; std::cout << " dist code lengths : "; for(size_t j = 0; j < 32; j++) std::cout << info.distlengths[j]; std::cout << std::endl; if(!options.use_hex) std::cout << std::dec; } if(info.btype != 0) { std::cout << " code counts: lit: " << info.numlit << ", len/dist: " << info.numlen << ", total: " << (info.numlit + info.numlen + 1) << ", with dists: " << (info.numlit + 2 * info.numlen + 1) << std::endl; if(options.zlib_full) { for(size_t j = 0; j < info.lz77_lcode.size(); j++) { int symbol = info.lz77_lcode[j]; if(symbol == 256) { std::cout << " end" << std::endl; } else if(symbol < 256) { std::cout << " lit: " << symbol << std::endl; } else { std::cout << " len: " << info.lz77_lvalue[j] << ", dist: " << info.lz77_dvalue[j] << std::endl; } } } if(options.zlib_counts) { std::vector<size_t> ll_count(288, 0); std::vector<size_t> d_count(32, 0); for(size_t j = 0; j < info.lz77_lcode.size(); j++) { int symbol = info.lz77_lcode[j]; if(symbol <= 256) { ll_count[symbol]++; } else { ll_count[symbol]++; d_count[info.lz77_dcode[j]]++; } } std::cout << " lit code 0-63 counts : "; for(size_t j = 0; j < 64; j++) std::cout << ll_count[j] << " "; std::cout << std::endl; std::cout << " lit code 64-127 counts : "; for(size_t j = 64; j < 128; j++) std::cout << ll_count[j] << " "; std::cout << std::endl; std::cout << " lit code 128-191 counts: "; for(size_t j = 128; j < 192; j++) std::cout << ll_count[j] << " "; std::cout << std::endl; std::cout << " lit code 192-255 counts: "; for(size_t j = 192; j < 256; j++) std::cout << ll_count[j] << " "; std::cout << std::endl; std::cout << " end code count : "; std::cout << ll_count[256] << " "; std::cout << std::endl; std::cout << " len code counts : "; for(size_t j = 257; j < 288; j++) std::cout << ll_count[j] << " "; std::cout << std::endl; std::cout << " dist code counts : "; for(size_t j = 0; j < 32; j++) std::cout << d_count[j] << " "; std::cout << std::endl; } } } } }
static void refresh_lcd_file(void) { char targetfile[256]; char tmpfile[256]; char channame[32]; if(cfg.lcd_output_path == NULL){ snprintf(targetfile, sizeof(targetfile),"%s%s", get_tmp_dir(), "/oscam.lcd"); snprintf(tmpfile, sizeof(tmpfile), "%s%s.tmp", get_tmp_dir(), "/oscam.lcd"); } else { snprintf(targetfile, sizeof(targetfile),"%s%s", cfg.lcd_output_path, "/oscam.lcd"); snprintf(tmpfile, sizeof(tmpfile), "%s%s.tmp", cfg.lcd_output_path, "/oscam.lcd"); } int8_t iscccam = 0; int32_t seconds = 0, secs = 0, fullmins = 0, mins = 0, fullhours = 0, hours = 0, days = 0; time_t now = time((time_t*)0); while(running) { now = time((time_t*)0); int16_t cnt = 0, idx = 0, count_r = 0, count_p = 0, count_u = 0; FILE *fpsave; if((fpsave = fopen(tmpfile, "w"))){ idx = 0; int16_t i; char *type; char *label; char *status; // Statuslines start secs = 0; fullmins = 0; mins = 0; fullhours = 0; hours = 0; days = 0; seconds = now - first_client->login; secs = seconds % 60; if (seconds > 60) { fullmins = seconds / 60; mins = fullmins % 60; if(fullmins > 60) { fullhours = fullmins / 60; hours = fullhours % 24; days = fullhours / 24; } } fprintf(fpsave,"Version: %s\n", CS_VERSION); fprintf(fpsave,"Revision: %s\n", CS_SVN_VERSION); if(days == 0) fprintf(fpsave, "up: %02d:%02d:%02d\n", hours, mins, secs); else fprintf(fpsave, "up: %02dd %02d:%02d:%02d\n", days, hours, mins, secs); fprintf(fpsave,"totals: %d/%d/%d/%d/%d/%d\n", first_client->cwfound, first_client->cwnot, first_client->cwignored, first_client->cwtout, first_client->cwcache, first_client->cwtun); fprintf(fpsave,"uptime: %d\n", seconds); // Statuslines end // Readertable head fprintf(fpsave,"Typ| Label | Idle | w | s | b | e | St\n"); fprintf(fpsave,"---+------------+--------------+---+---+---+---+----\n"); struct s_client *cl; // Reader/Proxy table start for ( i=0, cl=first_client; cl ; cl=cl->next, i++) { if ((cl->typ=='r' || cl->typ=='p') && ((now - cl->last) < 20 || !cfg.lcd_hide_idle)){ type = ""; label = ""; status = "OFF"; secs = 0; fullmins = 0; mins = 0; fullhours = 0; hours = 0; days = 0; seconds = now - cl->last; if (cl->typ == 'r'){ type = "R"; idx = count_r; label = cl->reader->label; if (cl->reader->card_status == CARD_INSERTED) status = "OK"; count_r++; } else if (cl->typ == 'p'){ type = "P"; iscccam = 0; idx = count_p; label = cl->reader->label; if ((strncmp(monitor_get_proto(cl), "cccam", 5) == 0)) iscccam = 1; if (cl->reader->card_status == CARD_INSERTED) status = "CON"; count_p++; } secs = seconds % 60; if (seconds > 60) { fullmins = seconds / 60; mins = fullmins % 60; if(fullmins > 60) { fullhours = fullmins / 60; hours = fullhours % 24; days = fullhours / 24; } } int16_t written = 0, skipped = 0, blocked = 0, error = 0; char *emmtext; if(cs_malloc(&emmtext, 16 * sizeof(char), -1)){ if(cl->typ == 'r' || !iscccam ){ for (i=0; i<4; i++) { error += cl->reader->emmerror[i]; blocked += cl->reader->emmblocked[i]; skipped += cl->reader->emmskipped[i]; written += cl->reader->emmwritten[i]; } snprintf(emmtext, 16, "%3d|%3d|%3d|%3d", written > 999? 999 : written, skipped > 999? 999 : skipped, blocked > 999? 999 : blocked, error > 999? 999 : error); } #ifdef MODULE_CCCAM else if(cl->typ == 'p' && iscccam ){ struct cc_data *rcc = cl->cc; if(rcc){ LLIST *cards = rcc->cards; if (cards) { int32_t cnt = ll_count(cards); int32_t locals = rcc->num_hop1; snprintf(emmtext, 16, " %3d/%3d card%s", locals, cnt, (cnt > 1)? "s ": " "); } } else { snprintf(emmtext, 16, " No cards "); } } #endif else { snprintf(emmtext, 16, " "); } } if(days == 0) { fprintf(fpsave,"%s%d | %-10.10s | %02d:%02d:%02d |%s| %s\n", type, idx, label, hours, mins, secs, emmtext, status); } else { fprintf(fpsave,"%s%d | %-10.10s |% 3dd %02d:%02d:%02d |%s| %s\n", type, idx, label, days, hours, mins, secs, emmtext, status); } free(emmtext); } } fprintf(fpsave,"---+------------+--------------+---+---+---+--++----\n"); // Reader/Proxy table end // Usertable start fprintf(fpsave,"Typ| Label | Channel | Time\n"); fprintf(fpsave,"---+------------+-----------------------------+-----\n"); /* //Testclient fprintf(fpsave,"%s%d | %-10.10s | %-10.10s:%-17.17s| % 4d\n", "U", 1, "test", "Sky De", "Discovery Channel", 568); */ for ( i=0, cl=first_client; cl ; cl=cl->next, i++) { seconds = now - cl->lastecm; if (cl->typ == 'c' && seconds < 15){ type = "U"; idx = count_u; label = cl->account->usr; count_u++; get_servicename(cl, cl->last_srvid, cl->last_caid, channame); fprintf(fpsave,"%s%d | %-10.10s | %-10.10s:%-17.17s| % 4d\n", type, idx, label, cl->last_srvidptr && cl->last_srvidptr->prov ? cl->last_srvidptr->prov : "", cl->last_srvidptr && cl->last_srvidptr->name ? cl->last_srvidptr->name : "", cl->cwlastresptime); } } fprintf(fpsave,"---+------------+-----------------------------+-----\n"); // Usertable end fclose(fpsave); } idx = 0; cs_sleepms(cfg.lcd_write_intervall * 1000); cnt++; if(rename(tmpfile, targetfile) < 0) cs_log("An error occured while writing oscam.lcd file %s.", targetfile); } }
/** * adds a job to the job queue * if ptr should be free() after use, set len to the size * else set size to 0 **/ int32_t add_job(struct s_client *cl, enum actions action, void *ptr, int32_t len) { if(!cl || cl->kill) { if(!cl) { cs_log("WARNING: add_job failed. Client killed!"); } // Ignore jobs for killed clients if(len && ptr) { NULLFREE(ptr); } return 0; } if(action == ACTION_CACHE_PUSH_OUT && cacheex_check_queue_length(cl)) { if(len && ptr) { NULLFREE(ptr); } return 0; } struct job_data *data; if(!cs_malloc(&data, sizeof(struct job_data))) { if(len && ptr) { NULLFREE(ptr); } return 0; } data->action = action; data->ptr = ptr; data->cl = cl; data->len = len; cs_ftime(&data->time); SAFE_MUTEX_LOCK(&cl->thread_lock); if(cl && !cl->kill && cl->thread_active) { if(!cl->joblist) { cl->joblist = ll_create("joblist"); } ll_append(cl->joblist, data); if(cl->thread_active == 2) { pthread_kill(cl->thread, OSCAM_SIGNAL_WAKEUP); } SAFE_MUTEX_UNLOCK(&cl->thread_lock); cs_log_dbg(D_TRACE, "add %s job action %d queue length %d %s", action > ACTION_CLIENT_FIRST ? "client" : "reader", action, ll_count(cl->joblist), username(cl)); return 1; } /* pcsc doesn't like this; segfaults on x86, x86_64 */ int8_t modify_stacksize = 0; struct s_reader *rdr = cl->reader; if(cl->typ != 'r' || !rdr || rdr->typ != R_PCSC) { modify_stacksize = 1; } if(action != ACTION_READER_CHECK_HEALTH) { cs_log_dbg(D_TRACE, "start %s thread action %d", action > ACTION_CLIENT_FIRST ? "client" : "reader", action); } int32_t ret = start_thread("client work", work_thread, (void *)data, &cl->thread, 1, modify_stacksize); if(ret) { cs_log("ERROR: can't create thread for %s (errno=%d %s)", action > ACTION_CLIENT_FIRST ? "client" : "reader", ret, strerror(ret)); free_job_data(data); } cl->thread_active = 1; SAFE_MUTEX_UNLOCK(&cl->thread_lock); return 1; }
int32_t coolapi_set_filter (int32_t fd, int32_t num, int32_t pid, uchar * flt, uchar * mask, int32_t type) { dmx_t * dmx = find_demux(fd, 0); if(!dmx) { cs_debug_mask(D_DVBAPI, "dmx is NULL!"); return -1; } int32_t result, channel_found=0; void * channel = NULL; if (ll_count(ll_cool_chanhandle) > 0) { LL_ITER itr = ll_iter_create(ll_cool_chanhandle); S_COOL_CHANHANDLE *handle_item; while ((handle_item=ll_iter_next(&itr))) { if (handle_item->demux_index == dmx->demux_index && handle_item->pid == pid) { channel = handle_item->channel; channel_found=1; break; } } } if (!channel) { buffer_open_arg_t bufarg; int32_t uBufferSize = 8256; memset(&bufarg, 0, sizeof(bufarg)); bufarg.type = 3; bufarg.size = uBufferSize; bufarg.unknown3 = (uBufferSize * 7) / 8; result = cnxt_cbuf_open(&dmx->buffer1, &bufarg, NULL, NULL); coolapi_check_error("cnxt_cbuf_open", result); bufarg.type = 0; result = cnxt_cbuf_open(&dmx->buffer2, &bufarg, NULL, NULL); coolapi_check_error("cnxt_cbuf_open", result); channel_open_arg_t chanarg; memset(&chanarg, 0, sizeof(channel_open_arg_t)); chanarg.type = 4; result = cnxt_dmx_channel_open(dmx->device, &dmx->channel, &chanarg, dmx_callback, dmx); coolapi_check_error("cnxt_dmx_channel_open", result); result = cnxt_dmx_set_channel_buffer(dmx->channel, 0, dmx->buffer1); coolapi_check_error("cnxt_dmx_set_channel_buffer", result); result = cnxt_dmx_channel_attach(dmx->channel, 0xB, 0, dmx->buffer2); coolapi_check_error("cnxt_dmx_channel_attach", result); result = cnxt_cbuf_attach(dmx->buffer2, 2, dmx->channel); coolapi_check_error("cnxt_cbuf_attach", result); result = cnxt_dmx_set_channel_pid(dmx->channel, pid); coolapi_check_error("cnxt_dmx_set_channel_pid", result); result = cnxt_cbuf_flush (dmx->buffer1, 0); coolapi_check_error("cnxt_cbuf_flush", result); result = cnxt_cbuf_flush (dmx->buffer2, 0); coolapi_check_error("cnxt_cbuf_flush", result); S_COOL_CHANHANDLE *handle_item; if (cs_malloc(&handle_item,sizeof(S_COOL_CHANHANDLE))) { handle_item->pid = pid; handle_item->channel = dmx->channel; handle_item->buffer1 = dmx->buffer1; handle_item->buffer2 = dmx->buffer2; handle_item->demux_index = dmx->demux_index; ll_append(ll_cool_chanhandle, handle_item); } cs_debug_mask(D_DVBAPI, "opened new channel %x", (int32_t) dmx->channel); } else { channel_found=1; dmx->channel = channel; dmx->buffer1 = NULL; dmx->buffer2 = NULL; } cs_debug_mask(D_DVBAPI, "setting new filter fd=%08x demux=%d channel=%x num=%d pid=%04x flt=%x mask=%x", fd, dmx->demux_index, (int32_t) dmx->channel, num, pid, flt[0], mask[0]); pthread_mutex_lock(&dmx->mutex); filter_set_t filter; dmx->filter_num = num; dmx->pid = pid; dmx->type = type; memset(&filter, 0, sizeof(filter)); filter.length = 12; memcpy(filter.filter, flt, 16); memcpy(filter.mask, mask, 16); result = cnxt_dmx_open_filter(dmx->device, &dmx->filter); coolapi_check_error("cnxt_dmx_open_filter", result); result = cnxt_dmx_set_filter(dmx->filter, &filter, NULL); coolapi_check_error("cnxt_dmx_set_filter", result); result = cnxt_dmx_channel_attach_filter(dmx->channel, dmx->filter); coolapi_check_error("cnxt_dmx_channel_attach_filter", result); if (channel_found) { result = cnxt_dmx_channel_ctrl(dmx->channel, 0, 0); coolapi_check_error("cnxt_dmx_channel_ctrl", result); } result = cnxt_dmx_channel_ctrl(dmx->channel, 2, 0); coolapi_check_error("cnxt_dmx_channel_ctrl", result); pthread_mutex_unlock(&dmx->mutex); S_COOL_FILTER *filter_item; if (cs_malloc(&filter_item,sizeof(S_COOL_FILTER))) { // fill filter item filter_item->fd = fd; filter_item->pid = pid; filter_item->channel = (int32_t) dmx->channel; memcpy(filter_item->filter16, flt, 16); memcpy(filter_item->mask16, mask, 16); //add filter item ll_append(ll_cool_filter, filter_item); } return 0; }
//----------------------------------------------------------------------------- // callback function that will fire when the connection to the controller is reached. static void controller_connect_handler(int fd, short int flags, void *arg) { controller_t *ct = (controller_t *) arg; node_t *node; system_data_t *sysdata; queue_t *q; int error; socklen_t foo; struct timeval t = {.tv_sec = 1, .tv_usec = 0}; short int exclusive; assert(fd >= 0); assert(flags != 0); assert(ct); assert(ct->node == NULL); assert(ct->target); assert(ct->sysdata); sysdata = ct->sysdata; // we only need to detect EV_WRITE for a connect event. assert(flags == EV_WRITE); // remove the connect event assert(ct->connect_event); event_free(ct->connect_event); ct->connect_event = NULL; // we are no longer connected. We are either connected, or not. assert(BIT_TEST(ct->flags, FLAG_CONTROLLER_CONNECTING)); BIT_CLEAR(ct->flags, FLAG_CONTROLLER_CONNECTING); // check to see if we really are connected. foo = sizeof(error); getsockopt(fd, SOL_SOCKET, SO_ERROR, &error, &foo); if (error == ECONNREFUSED) { // we were connecting, but couldn't. BIT_SET(ct->flags, FLAG_CONTROLLER_CLOSED); // close the socket that didn't connect. close(fd); //set the action so that we can attempt to reconnect. assert(ct->connect_event == NULL); assert(sysdata->evbase); ct->connect_event = evtimer_new(sysdata->evbase, controller_wait_handler, (void *) ct); evtimer_add(ct->connect_event, &t); } else { logger(((system_data_t *)ct->sysdata)->logging, 2, "connected to remote controller: %s", ct->target); // create the node object. node = node_create(sysdata, fd); // add node to the main nodes list. ct->node = node; assert(node->controller == NULL); node->controller = ct; BIT_SET(node->flags, FLAG_NODE_CONTROLLER); // we need to check to see if we have any queues with active consumers, // and if we do, then we need to send consume requests to this node for // each one. assert(sysdata->queues); ll_start(sysdata->queues); while ((q = ll_next(sysdata->queues))) { assert(q->qid > 0); assert(q->name); if (ll_count(&q->nodes_busy) > 0 || ll_count(&q->nodes_ready) > 0) { logger(((system_data_t *)ct->sysdata)->logging, 2, "Sending queue consume ('%s') to alternate controller at %s", q->name, ct->target ); exclusive = 0; if (BIT_TEST(q->flags, QUEUE_FLAG_EXCLUSIVE)) exclusive = 1; sendConsume(node, q->name, 1, RQ_PRIORITY_LOW, exclusive); ll_push_head(&q->nodes_consuming, node); } } ll_finish(sysdata->queues); } } void controller_connect(controller_t *ct) { evutil_socket_t sock; int result; int len; assert(ct); assert(ct->target); assert(ct->node == NULL); assert(BIT_TEST(ct->flags, FLAG_CONTROLLER_CONNECTED) == 0); assert(BIT_TEST(ct->flags, FLAG_CONTROLLER_FAILED) == 0); assert(BIT_TEST(ct->flags, FLAG_CONTROLLER_CONNECTING) == 0); // if not already resolved.... resolve the target. if (BIT_TEST(ct->flags, FLAG_CONTROLLER_RESOLVED) == 0) { assert(ct->flags == 0); logger(((system_data_t *)ct->sysdata)->logging, 3, "resolving controller %s.", ct->target); len = sizeof(ct->saddr); if (evutil_parse_sockaddr_port(ct->target, &ct->saddr, &len) == 0) { BIT_SET(ct->flags, FLAG_CONTROLLER_RESOLVED); } else { BIT_SET(ct->flags, FLAG_CONTROLLER_FAILED); } } if (BIT_TEST(ct->flags, FLAG_CONTROLLER_FAILED) == 0) { assert(BIT_TEST(ct->flags, FLAG_CONTROLLER_RESOLVED)); BIT_SET(ct->flags, FLAG_CONTROLLER_CONNECTING); sock = socket(AF_INET,SOCK_STREAM,0); assert(sock >= 0); // Before we attempt to connect, set the socket to non-blocking mode. evutil_make_socket_nonblocking(sock); logger(((system_data_t *)ct->sysdata)->logging, 3, "Attempting Remote connect to %s.", ct->target); result = connect(sock, &ct->saddr, sizeof(struct sockaddr)); assert(result < 0); assert(errno == EINPROGRESS); // connect process has been started. Now we need to create an event so that we know when the connect has completed. assert(ct->connect_event == NULL); assert(ct->sysdata); assert(((system_data_t *)ct->sysdata)->evbase); ct->connect_event = event_new(((system_data_t *)ct->sysdata)->evbase, sock, EV_WRITE, controller_connect_handler, ct); event_add(ct->connect_event, NULL); } else { assert(ct->target); logger(((system_data_t *)ct->sysdata)->logging, 2, "Remote connect to %s has failed.", ct->target); } }