- fix Building without Nagra not possible at Nagra_Merlin https://trac.streamboard...
[oscam.git] / oscam-work.c
blobbee981dc1776513f49ddf9ba70011ebaea1aa372
1 #define MODULE_LOG_PREFIX "work"
3 #include "globals.h"
4 #include "module-cacheex.h"
5 #include "oscam-client.h"
6 #include "oscam-ecm.h"
7 #include "oscam-emm.h"
8 #include "oscam-lock.h"
9 #include "oscam-net.h"
10 #include "oscam-reader.h"
11 #include "oscam-string.h"
12 #include "oscam-work.h"
13 #include "reader-common.h"
14 #include "module-cccam.h"
15 #include "module-cccam-data.h"
16 #include "module-cccshare.h"
17 #include "oscam-time.h"
19 extern CS_MUTEX_LOCK system_lock;
20 extern int32_t thread_pipe[2];
22 struct job_data
24 enum actions action;
25 struct s_reader *rdr;
26 struct s_client *cl;
27 void *ptr;
28 struct timeb time;
29 uint16_t len;
32 static void free_job_data(struct job_data *data)
34 if(!data)
35 { return; }
36 if(data->len && data->ptr)
38 // special free checks
39 if(data->action==ACTION_ECM_ANSWER_CACHE)
41 NULLFREE(((struct s_write_from_cache *)data->ptr)->er_cache);
44 NULLFREE(data->ptr);
46 NULLFREE(data);
49 void free_joblist(struct s_client *cl)
51 int32_t lock_status = pthread_mutex_trylock(&cl->thread_lock);
52 LL_ITER it = ll_iter_create(cl->joblist);
54 struct job_data *data;
55 while((data = ll_iter_next(&it)))
57 free_job_data(data);
60 ll_destroy(&cl->joblist);
61 cl->account = NULL;
63 if(cl->work_job_data) // Free job_data that was not freed by work_thread
64 { free_job_data(cl->work_job_data); }
66 cl->work_job_data = NULL;
68 if(lock_status == 0)
69 { SAFE_MUTEX_UNLOCK(&cl->thread_lock); }
71 pthread_mutex_destroy(&cl->thread_lock);
75 Work threads are named like this:
76 w[r|c]XX-[rdr->label|client->username]
78 w - work thread prefix
79 [r|c] - depending whether the the action is related to reader or client
80 XX - two digit action code from enum actions
81 label - reader label or client username (see username() function)
83 static void set_work_thread_name(struct job_data *data)
85 char thread_name[16 + 1];
86 snprintf(thread_name, sizeof(thread_name), "w%c%02d-%s",
87 data->action < ACTION_CLIENT_FIRST ? 'r' : 'c',
88 data->action,
89 username(data->cl)
91 set_thread_name(thread_name);
94 #define __free_job_data(client, job_data) \
95 do { \
96 client->work_job_data = NULL; \
97 if(job_data && job_data != &tmp_data) { \
98 free_job_data(job_data); \
99 } \
100 job_data = NULL; \
101 } while(0)
103 void *work_thread(void *ptr)
105 struct job_data *data = (struct job_data *)ptr;
106 struct s_client *cl = data->cl;
107 struct s_reader *reader = cl->reader;
108 struct timeb start, end; // start time poll, end time poll
110 struct job_data tmp_data;
111 struct pollfd pfd[1];
113 SAFE_SETSPECIFIC(getclient, cl);
114 cl->thread = pthread_self();
115 cl->thread_active = 1;
117 set_work_thread_name(data);
119 struct s_module *module = get_module(cl);
120 uint16_t bufsize = module->bufsize; // CCCam needs more than 1024bytes!
121 if(!bufsize)
122 { bufsize = DEFAULT_MODULE_BUFSIZE; }
124 uint8_t *mbuf;
125 if(!cs_malloc(&mbuf, bufsize))
126 { return NULL; }
128 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
129 int32_t n = 0, rc = 0, i, idx, s, dblvl;
130 (void)dblvl;
131 uint8_t dcw[16];
132 int8_t restart_reader = 0;
134 while(cl->thread_active)
136 cs_ftime(&start); // register start time
138 while(cl->thread_active)
140 if(!cl || cl->kill || !is_valid_client(cl))
142 SAFE_MUTEX_LOCK(&cl->thread_lock);
143 cl->thread_active = 0;
144 SAFE_MUTEX_UNLOCK(&cl->thread_lock);
145 cs_log_dbg(D_TRACE, "ending thread (kill)");
146 __free_job_data(cl, data);
147 cl->work_mbuf = NULL; // Prevent free_client from freeing mbuf (->work_mbuf)
148 free_client(cl);
149 if(restart_reader)
150 { restart_cardreader(reader, 0); }
151 NULLFREE(mbuf);
152 pthread_exit(NULL);
153 return NULL;
156 if(data && data->action != ACTION_READER_CHECK_HEALTH)
157 { cs_log_dbg(D_TRACE, "data from add_job action=%d client %c %s", data->action, cl->typ, username(cl)); }
159 if(!data)
161 if(!cl->kill && cl->typ != 'r')
162 { client_check_status(cl); } // do not call for physical readers as this might cause an endless job loop
164 SAFE_MUTEX_LOCK(&cl->thread_lock);
165 if(cl->joblist && ll_count(cl->joblist) > 0)
167 LL_ITER itr = ll_iter_create(cl->joblist);
168 data = ll_iter_next_remove(&itr);
169 if(data)
170 { set_work_thread_name(data); }
171 //cs_log_dbg(D_TRACE, "start next job from list action=%d", data->action);
173 SAFE_MUTEX_UNLOCK(&cl->thread_lock);
176 if(!data)
178 /* for serial client cl->pfd is file descriptor for serial port not socket
179 for example: pfd=open("/dev/ttyUSB0"); */
180 if(!cl->pfd || module->listenertype == LIS_SERIAL)
181 { break; }
183 pfd[0].fd = cl->pfd;
184 pfd[0].events = POLLIN | POLLPRI;
186 SAFE_MUTEX_LOCK(&cl->thread_lock);
187 cl->thread_active = 2;
188 SAFE_MUTEX_UNLOCK(&cl->thread_lock);
190 rc = poll(pfd, 1, 3000);
192 SAFE_MUTEX_LOCK(&cl->thread_lock);
193 cl->thread_active = 1;
194 SAFE_MUTEX_UNLOCK(&cl->thread_lock);
196 if(rc > 0)
198 cs_ftime(&end); // register end time
199 cs_log_dbg(D_TRACE, "[OSCAM-WORK] new event %d occurred on fd %d after %"PRId64" ms inactivity", pfd[0].revents,
200 pfd[0].fd, comp_timeb(&end, &start));
201 data = &tmp_data;
202 data->ptr = NULL;
203 cs_ftime(&start); // register start time for new poll next run
205 if(reader)
206 { data->action = ACTION_READER_REMOTE; }
207 else
209 if(cl->is_udp)
211 data->action = ACTION_CLIENT_UDP;
212 data->ptr = mbuf;
213 data->len = bufsize;
215 else
216 { data->action = ACTION_CLIENT_TCP; }
218 if(pfd[0].revents & (POLLHUP | POLLNVAL | POLLERR))
219 { cl->kill = 1; }
224 if(!data)
225 { continue; }
227 if(!reader && data->action < ACTION_CLIENT_FIRST)
229 __free_job_data(cl, data);
230 break;
233 if(!data->action)
234 { break; }
236 struct timeb actualtime;
237 cs_ftime(&actualtime);
238 int64_t gone = comp_timeb(&actualtime, &data->time);
239 if(data != &tmp_data && gone > (int) cfg.ctimeout+1000)
241 cs_log_dbg(D_TRACE, "dropping client data for %s time %"PRId64" ms", username(cl), gone);
242 __free_job_data(cl, data);
243 continue;
246 if(data != &tmp_data)
247 { cl->work_job_data = data; } // Track the current job_data
249 switch(data->action)
251 case ACTION_READER_IDLE:
252 reader_do_idle(reader);
253 break;
255 case ACTION_READER_REMOTE:
256 s = check_fd_for_data(cl->pfd);
257 if(s == 0) // no data, another thread already read from fd?
258 { break; }
259 if(s < 0)
261 if(cl->reader->ph.type == MOD_CONN_TCP)
262 { network_tcp_connection_close(reader, "disconnect"); }
263 break;
265 rc = cl->reader->ph.recv(cl, mbuf, bufsize);
266 if(rc < 0)
268 if(cl->reader->ph.type == MOD_CONN_TCP)
270 network_tcp_connection_close(reader, "disconnect on receive");
271 #ifdef CS_CACHEEX_AIO
272 cl->cacheex_aio_checked = 0;
273 #endif
275 break;
277 cl->last = time(NULL); // *********************************** TO BE REPLACE BY CS_FTIME() LATER ****************
278 idx = cl->reader->ph.c_recv_chk(cl, dcw, &rc, mbuf, rc);
279 if(idx < 0) { break; } // no dcw received
280 if(!idx) { idx = cl->last_idx; }
281 cl->reader->last_g = time(NULL); // *********************************** TO BE REPLACE BY CS_FTIME() LATER **************** // for reconnect timeout
282 for(i = 0, n = 0; i < cfg.max_pending && n == 0; i++)
284 if(cl->ecmtask[i].idx == idx)
286 cl->pending--;
287 casc_check_dcw(reader, i, rc, dcw);
288 n++;
291 break;
293 case ACTION_READER_RESET:
294 cardreader_do_reset(reader);
295 break;
297 case ACTION_READER_ECM_REQUEST:
298 reader_get_ecm(reader, data->ptr);
299 break;
301 case ACTION_READER_EMM:
302 reader_do_emm(reader, data->ptr);
303 break;
305 case ACTION_READER_SENDCMD:
306 #ifdef WITH_CARDREADER
307 dblvl = cs_dblevel;
308 cs_dblevel = dblvl | D_READER;
309 rc = cardreader_do_rawcmd(reader, data->ptr);
310 cs_log_dbg(D_TRACE, "sendcmd rc: %i, csystem: %s", rc, reader->csystem->desc);
311 if(rc == -9)
313 CMD_PACKET *cp = data->ptr;
314 uint8_t response[MAX_CMD_SIZE];
315 memset(response, 0, sizeof(response));
316 uint16_t response_length[1] = { 0 };
317 rc = reader_cmd2icc(reader, cp->cmd, cp->cmdlen, response, response_length);
318 cs_log_dbg(D_TRACE, "sendcmd rc: %i, len: %i", rc, *response_length);
319 if (*response_length)
321 cs_log_dump_dbg(D_TRACE, response, *response_length, "sendcmd response:");
324 cs_dblevel = dblvl;
325 #endif
326 break;
328 case ACTION_READER_CARDINFO:
329 reader_do_card_info(reader);
330 break;
332 case ACTION_READER_POLL_STATUS:
333 #ifdef READER_VIDEOGUARD
334 cardreader_poll_status(reader);
335 #endif
336 break;
338 case ACTION_READER_INIT:
339 if(!cl->init_done)
340 { reader_init(reader); }
341 break;
343 case ACTION_READER_RESTART:
344 cl->kill = 1;
345 restart_reader = 1;
346 break;
348 case ACTION_READER_RESET_FAST:
349 cl->reader->card_status = CARD_NEED_INIT;
350 cardreader_do_reset(reader);
351 break;
353 case ACTION_READER_CHECK_HEALTH:
354 cardreader_do_checkhealth(reader);
355 break;
357 case ACTION_READER_CAPMT_NOTIFY:
358 if(cl->reader->ph.c_capmt) { cl->reader->ph.c_capmt(cl, data->ptr); }
359 break;
361 case ACTION_CLIENT_UDP:
362 n = module->recv(cl, data->ptr, data->len);
363 if(n < 0) { break; }
364 module->s_handler(cl, data->ptr, n);
365 break;
367 case ACTION_CLIENT_TCP:
368 s = check_fd_for_data(cl->pfd);
369 if(s == 0) // no data, another thread already read from fd?
370 { break; }
371 if(s < 0) // system error or fd wants to be closed
373 cl->kill = 1; // kill client on next run
374 continue;
376 n = module->recv(cl, mbuf, bufsize);
377 if(n < 0)
379 cl->kill = 1; // kill client on next run
380 continue;
382 module->s_handler(cl, mbuf, n);
383 break;
385 case ACTION_CACHEEX1_DELAY:
386 cacheex_mode1_delay(data->ptr);
387 break;
389 case ACTION_CACHEEX_TIMEOUT:
390 cacheex_timeout(data->ptr);
391 break;
393 case ACTION_FALLBACK_TIMEOUT:
394 fallback_timeout(data->ptr);
395 break;
397 case ACTION_CLIENT_TIMEOUT:
398 ecm_timeout(data->ptr);
399 break;
401 case ACTION_ECM_ANSWER_READER:
402 chk_dcw(data->ptr);
403 break;
405 case ACTION_ECM_ANSWER_CACHE:
406 write_ecm_answer_fromcache(data->ptr);
407 break;
409 case ACTION_CLIENT_INIT:
410 if(module->s_init)
411 { module->s_init(cl); }
412 cl->is_udp = module->type == MOD_CONN_UDP;
413 cl->init_done = 1;
414 break;
416 case ACTION_CLIENT_IDLE:
417 if(module->s_idle)
418 { module->s_idle(cl); }
419 else
421 cs_log("user %s reached %d sec idle limit.", username(cl), cfg.cmaxidle);
422 cl->kill = 1;
424 break;
426 case ACTION_CACHE_PUSH_OUT:
427 cacheex_push_out(cl, data->ptr);
428 break;
430 case ACTION_CLIENT_KILL:
431 cl->kill = 1;
432 break;
434 case ACTION_CLIENT_SEND_MSG:
436 if (config_enabled(MODULE_CCCAM))
438 struct s_clientmsg *clientmsg = (struct s_clientmsg *)data->ptr;
439 cc_cmd_send(cl, clientmsg->msg, clientmsg->len, clientmsg->cmd);
441 break;
444 case ACTION_PEER_IDLE:
445 if(module->s_peer_idle)
446 { module->s_peer_idle(cl); }
447 break;
449 case ACTION_CLIENT_HIDECARDS:
451 #ifdef CS_ANTICASC
452 if(config_enabled(MODULE_CCCSHARE))
454 int32_t hidetime = (cl->account->acosc_penalty_duration == -1 ? cfg.acosc_penalty_duration : cl->account->acosc_penalty_duration);
455 if(hidetime)
457 int32_t hide_count;
458 int32_t cardsize;
459 int32_t ii, uu=0;
460 LLIST **sharelist = get_and_lock_sharelist();
461 LLIST *sharelist2 = ll_create("hidecards-sharelist");
463 for(ii = 0; ii < CAID_KEY; ii++)
465 if(sharelist[ii])
467 ll_putall(sharelist2, sharelist[ii]);
471 unlock_sharelist();
473 struct cc_card **cardarray = get_sorted_card_copy(sharelist2, 0, &cardsize);
474 ll_destroy(&sharelist2);
476 for(ii = 0; ii < cardsize; ii++)
478 if(hidecards_card_valid_for_client(cl, cardarray[ii]))
480 if (cardarray[ii]->id)
482 hide_count = hide_card_to_client(cardarray[ii], cl);
483 if(hide_count)
485 cs_log_dbg(D_TRACE, "Hiding card_%d caid=%04x remoteid=%08x from %s for %d %s",
486 uu, cardarray[ii]->caid, cardarray[ii]->remote_id, username(cl), hidetime, hidetime>1 ? "secconds" : "seccond");
487 uu += 1;
493 cs_sleepms(hidetime * 1000);
494 uu = 0;
496 for(ii = 0; ii < cardsize; ii++)
498 if(hidecards_card_valid_for_client(cl, cardarray[ii]))
500 if (cardarray[ii]->id)
502 hide_count = unhide_card_to_client(cardarray[ii], cl);
503 if(hide_count)
505 cs_log_dbg(D_TRACE, "Unhiding card_%d caid=%04x remoteid=%08x for %s",
506 uu, cardarray[ii]->caid, cardarray[ii]->remote_id, username(cl));
507 uu += 1;
513 NULLFREE(cardarray);
516 #endif
517 break;
518 } // case ACTION_CLIENT_HIDECARDS
520 } // switch
522 __free_job_data(cl, data);
525 if(thread_pipe[1] && (mbuf[0] != 0x00))
527 cs_log_dump_dbg(D_TRACE, mbuf, 1, "[OSCAM-WORK] Write to pipe:");
528 if(write(thread_pipe[1], mbuf, 1) == -1) // wakeup client check
530 cs_log_dbg(D_TRACE, "[OSCAM-WORK] Writing to pipe failed (errno=%d %s)", errno, strerror(errno));
534 // Check for some race condition where while we ended, another thread added a job
535 SAFE_MUTEX_LOCK(&cl->thread_lock);
536 if(cl->joblist && ll_count(cl->joblist) > 0)
538 SAFE_MUTEX_UNLOCK(&cl->thread_lock);
539 continue;
541 else
543 cl->thread_active = 0;
544 SAFE_MUTEX_UNLOCK(&cl->thread_lock);
545 break;
548 cl->thread_active = 0;
549 cl->work_mbuf = NULL; // Prevent free_client from freeing mbuf (->work_mbuf)
550 NULLFREE(mbuf);
551 pthread_exit(NULL);
552 return NULL;
556 * adds a job to the job queue
557 * if ptr should be free() after use, set len to the size
558 * else set size to 0
560 int32_t add_job(struct s_client *cl, enum actions action, void *ptr, int32_t len)
562 if(!cl || cl->kill)
564 if(!cl)
565 { cs_log("WARNING: add_job failed. Client killed!"); } // Ignore jobs for killed clients
566 if(len && ptr)
567 { NULLFREE(ptr); }
568 return 0;
571 if(action == ACTION_CACHE_PUSH_OUT && cacheex_check_queue_length(cl))
573 if(len && ptr)
574 { NULLFREE(ptr); }
575 return 0;
578 struct job_data *data;
579 if(!cs_malloc(&data, sizeof(struct job_data)))
581 if(len && ptr)
582 { NULLFREE(ptr); }
583 return 0;
586 data->action = action;
587 data->ptr = ptr;
588 data->cl = cl;
589 data->len = len;
590 cs_ftime(&data->time);
592 SAFE_MUTEX_LOCK(&cl->thread_lock);
593 if(cl && !cl->kill && cl->thread_active)
595 if(!cl->joblist)
596 { cl->joblist = ll_create("joblist"); }
597 ll_append(cl->joblist, data);
598 if(cl->thread_active == 2)
599 { pthread_kill(cl->thread, OSCAM_SIGNAL_WAKEUP); }
600 SAFE_MUTEX_UNLOCK(&cl->thread_lock);
601 cs_log_dbg(D_TRACE, "add %s job action %d queue length %d %s",
602 action > ACTION_CLIENT_FIRST ? "client" : "reader", action,
603 ll_count(cl->joblist), username(cl));
604 return 1;
607 /* pcsc doesn't like this; segfaults on x86, x86_64 */
608 int8_t modify_stacksize = 0;
609 struct s_reader *rdr = cl->reader;
610 if(cl->typ != 'r' || !rdr || rdr->typ != R_PCSC)
611 { modify_stacksize = 1; }
613 if(action != ACTION_READER_CHECK_HEALTH)
615 cs_log_dbg(D_TRACE, "start %s thread action %d",
616 action > ACTION_CLIENT_FIRST ? "client" : "reader", action);
619 int32_t ret = start_thread("client work", work_thread, (void *)data, &cl->thread, 1, modify_stacksize);
620 if(ret)
622 cs_log("ERROR: can't create thread for %s (errno=%d %s)",
623 action > ACTION_CLIENT_FIRST ? "client" : "reader", ret, strerror(ret));
624 free_job_data(data);
627 cl->thread_active = 1;
628 SAFE_MUTEX_UNLOCK(&cl->thread_lock);
629 return 1;