1 #define MODULE_LOG_PREFIX "work"
4 #include "module-cacheex.h"
5 #include "oscam-client.h"
8 #include "oscam-lock.h"
10 #include "oscam-reader.h"
11 #include "oscam-string.h"
12 #include "oscam-work.h"
13 #include "reader-common.h"
14 #ifdef READER_NAGRA_MERLIN
15 #include "reader-nagracak7.h"
17 #include "module-cccam.h"
18 #include "module-cccam-data.h"
19 #include "module-cccshare.h"
20 #include "oscam-time.h"
22 extern CS_MUTEX_LOCK system_lock
;
23 extern int32_t thread_pipe
[2];
35 static void free_job_data(struct job_data
*data
)
39 if(data
->len
&& data
->ptr
)
41 // special free checks
42 if(data
->action
==ACTION_ECM_ANSWER_CACHE
)
44 NULLFREE(((struct s_write_from_cache
*)data
->ptr
)->er_cache
);
52 void free_joblist(struct s_client
*cl
)
54 int32_t lock_status
= pthread_mutex_trylock(&cl
->thread_lock
);
55 LL_ITER it
= ll_iter_create(cl
->joblist
);
57 struct job_data
*data
;
58 while((data
= ll_iter_next(&it
)))
63 ll_destroy(&cl
->joblist
);
66 if(cl
->work_job_data
) // Free job_data that was not freed by work_thread
67 { free_job_data(cl
->work_job_data
); }
69 cl
->work_job_data
= NULL
;
72 { SAFE_MUTEX_UNLOCK(&cl
->thread_lock
); }
74 pthread_mutex_destroy(&cl
->thread_lock
);
78 Work threads are named like this:
79 w[r|c]XX-[rdr->label|client->username]
81 w - work thread prefix
82 [r|c] - depending whether the the action is related to reader or client
83 XX - two digit action code from enum actions
84 label - reader label or client username (see username() function)
86 static void set_work_thread_name(struct job_data
*data
)
88 char thread_name
[16 + 1];
89 snprintf(thread_name
, sizeof(thread_name
), "w%c%02d-%s",
90 data
->action
< ACTION_CLIENT_FIRST
? 'r' : 'c',
94 set_thread_name(thread_name
);
97 #define __free_job_data(client, job_data) \
99 client->work_job_data = NULL; \
100 if(job_data && job_data != &tmp_data) { \
101 free_job_data(job_data); \
106 void *work_thread(void *ptr
)
108 struct job_data
*data
= (struct job_data
*)ptr
;
109 struct s_client
*cl
= data
->cl
;
110 struct s_reader
*reader
= cl
->reader
;
111 struct timeb start
, end
; // start time poll, end time poll
113 struct job_data tmp_data
;
114 struct pollfd pfd
[1];
116 SAFE_SETSPECIFIC(getclient
, cl
);
117 cl
->thread
= pthread_self();
118 cl
->thread_active
= 1;
120 set_work_thread_name(data
);
122 struct s_module
*module
= get_module(cl
);
123 uint16_t bufsize
= module
->bufsize
; // CCCam needs more than 1024bytes!
125 { bufsize
= DEFAULT_MODULE_BUFSIZE
; }
128 if(!cs_malloc(&mbuf
, bufsize
))
131 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
132 int32_t n
= 0, rc
= 0, i
, idx
, s
;
134 int8_t restart_reader
= 0;
136 while(cl
->thread_active
)
138 cs_ftime(&start
); // register start time
140 while(cl
->thread_active
)
142 if(!cl
|| cl
->kill
|| !is_valid_client(cl
))
144 SAFE_MUTEX_LOCK(&cl
->thread_lock
);
145 cl
->thread_active
= 0;
146 SAFE_MUTEX_UNLOCK(&cl
->thread_lock
);
147 cs_log_dbg(D_TRACE
, "ending thread (kill)");
148 __free_job_data(cl
, data
);
149 cl
->work_mbuf
= NULL
; // Prevent free_client from freeing mbuf (->work_mbuf)
152 { restart_cardreader(reader
, 0); }
158 if(data
&& data
->action
!= ACTION_READER_CHECK_HEALTH
)
159 { cs_log_dbg(D_TRACE
, "data from add_job action=%d client %c %s", data
->action
, cl
->typ
, username(cl
)); }
163 if(!cl
->kill
&& cl
->typ
!= 'r')
164 { client_check_status(cl
); } // do not call for physical readers as this might cause an endless job loop
166 SAFE_MUTEX_LOCK(&cl
->thread_lock
);
167 if(cl
->joblist
&& ll_count(cl
->joblist
) > 0)
169 LL_ITER itr
= ll_iter_create(cl
->joblist
);
170 data
= ll_iter_next_remove(&itr
);
172 { set_work_thread_name(data
); }
173 //cs_log_dbg(D_TRACE, "start next job from list action=%d", data->action);
175 SAFE_MUTEX_UNLOCK(&cl
->thread_lock
);
180 /* for serial client cl->pfd is file descriptor for serial port not socket
181 for example: pfd=open("/dev/ttyUSB0"); */
182 if(!cl
->pfd
|| module
->listenertype
== LIS_SERIAL
)
186 pfd
[0].events
= POLLIN
| POLLPRI
;
188 SAFE_MUTEX_LOCK(&cl
->thread_lock
);
189 cl
->thread_active
= 2;
190 SAFE_MUTEX_UNLOCK(&cl
->thread_lock
);
192 rc
= poll(pfd
, 1, 3000);
194 SAFE_MUTEX_LOCK(&cl
->thread_lock
);
195 cl
->thread_active
= 1;
196 SAFE_MUTEX_UNLOCK(&cl
->thread_lock
);
200 cs_ftime(&end
); // register end time
201 cs_log_dbg(D_TRACE
, "[OSCAM-WORK] new event %d occurred on fd %d after %"PRId64
" ms inactivity", pfd
[0].revents
,
202 pfd
[0].fd
, comp_timeb(&end
, &start
));
205 cs_ftime(&start
); // register start time for new poll next run
208 { data
->action
= ACTION_READER_REMOTE
; }
213 data
->action
= ACTION_CLIENT_UDP
;
218 { data
->action
= ACTION_CLIENT_TCP
; }
220 if(pfd
[0].revents
& (POLLHUP
| POLLNVAL
| POLLERR
))
229 if(!reader
&& data
->action
< ACTION_CLIENT_FIRST
)
231 __free_job_data(cl
, data
);
238 struct timeb actualtime
;
239 cs_ftime(&actualtime
);
240 int64_t gone
= comp_timeb(&actualtime
, &data
->time
);
241 if(data
!= &tmp_data
&& gone
> (int) cfg
.ctimeout
+1000)
243 cs_log_dbg(D_TRACE
, "dropping client data for %s time %"PRId64
" ms", username(cl
), gone
);
244 __free_job_data(cl
, data
);
248 if(data
!= &tmp_data
)
249 { cl
->work_job_data
= data
; } // Track the current job_data
253 case ACTION_READER_IDLE
:
254 reader_do_idle(reader
);
257 case ACTION_READER_REMOTE
:
258 s
= check_fd_for_data(cl
->pfd
);
259 if(s
== 0) // no data, another thread already read from fd?
263 if(reader
->ph
.type
== MOD_CONN_TCP
)
264 { network_tcp_connection_close(reader
, "disconnect"); }
267 rc
= reader
->ph
.recv(cl
, mbuf
, bufsize
);
270 if(reader
->ph
.type
== MOD_CONN_TCP
)
271 { network_tcp_connection_close(reader
, "disconnect on receive"); }
274 cl
->last
= time(NULL
); // *********************************** TO BE REPLACE BY CS_FTIME() LATER ****************
275 idx
= reader
->ph
.c_recv_chk(cl
, dcw
, &rc
, mbuf
, rc
);
276 if(idx
< 0) { break; } // no dcw received
277 if(!idx
) { idx
= cl
->last_idx
; }
278 reader
->last_g
= time(NULL
); // *********************************** TO BE REPLACE BY CS_FTIME() LATER **************** // for reconnect timeout
279 for(i
= 0, n
= 0; i
< cfg
.max_pending
&& n
== 0; i
++)
281 if(cl
->ecmtask
[i
].idx
== idx
)
284 casc_check_dcw(reader
, i
, rc
, dcw
);
290 case ACTION_READER_RESET
:
291 cardreader_do_reset(reader
);
294 case ACTION_READER_ECM_REQUEST
:
295 reader_get_ecm(reader
, data
->ptr
);
298 case ACTION_READER_EMM
:
299 reader_do_emm(reader
, data
->ptr
);
302 case ACTION_READER_CARDINFO
:
303 reader_do_card_info(reader
);
306 case ACTION_READER_POLL_STATUS
:
307 cardreader_poll_status(reader
);
310 #ifdef READER_NAGRA_MERLIN
311 case ACTION_READER_RENEW_SK
:
312 CAK7_getCamKey(reader
);
316 case ACTION_READER_INIT
:
318 { reader_init(reader
); }
321 case ACTION_READER_RESTART
:
326 case ACTION_READER_RESET_FAST
:
327 reader
->card_status
= CARD_NEED_INIT
;
328 cardreader_do_reset(reader
);
331 case ACTION_READER_CHECK_HEALTH
:
332 cardreader_do_checkhealth(reader
);
335 case ACTION_READER_CAPMT_NOTIFY
:
336 if(reader
->ph
.c_capmt
) { reader
->ph
.c_capmt(cl
, data
->ptr
); }
339 case ACTION_CLIENT_UDP
:
340 n
= module
->recv(cl
, data
->ptr
, data
->len
);
342 module
->s_handler(cl
, data
->ptr
, n
);
345 case ACTION_CLIENT_TCP
:
346 s
= check_fd_for_data(cl
->pfd
);
347 if(s
== 0) // no data, another thread already read from fd?
349 if(s
< 0) // system error or fd wants to be closed
351 cl
->kill
= 1; // kill client on next run
354 n
= module
->recv(cl
, mbuf
, bufsize
);
357 cl
->kill
= 1; // kill client on next run
360 module
->s_handler(cl
, mbuf
, n
);
363 case ACTION_CACHEEX1_DELAY
:
364 cacheex_mode1_delay(data
->ptr
);
367 case ACTION_CACHEEX_TIMEOUT
:
368 cacheex_timeout(data
->ptr
);
371 case ACTION_FALLBACK_TIMEOUT
:
372 fallback_timeout(data
->ptr
);
375 case ACTION_CLIENT_TIMEOUT
:
376 ecm_timeout(data
->ptr
);
379 case ACTION_ECM_ANSWER_READER
:
383 case ACTION_ECM_ANSWER_CACHE
:
384 write_ecm_answer_fromcache(data
->ptr
);
387 case ACTION_CLIENT_INIT
:
389 { module
->s_init(cl
); }
390 cl
->is_udp
= module
->type
== MOD_CONN_UDP
;
394 case ACTION_CLIENT_IDLE
:
396 { module
->s_idle(cl
); }
399 cs_log("user %s reached %d sec idle limit.", username(cl
), cfg
.cmaxidle
);
404 case ACTION_CACHE_PUSH_OUT
:
405 cacheex_push_out(cl
, data
->ptr
);
408 case ACTION_CLIENT_KILL
:
412 case ACTION_CLIENT_SEND_MSG
:
414 if (config_enabled(MODULE_CCCAM
))
416 struct s_clientmsg
*clientmsg
= (struct s_clientmsg
*)data
->ptr
;
417 cc_cmd_send(cl
, clientmsg
->msg
, clientmsg
->len
, clientmsg
->cmd
);
422 case ACTION_PEER_IDLE
:
423 if(module
->s_peer_idle
)
424 { module
->s_peer_idle(cl
); }
427 case ACTION_CLIENT_HIDECARDS
:
430 if(config_enabled(MODULE_CCCSHARE
))
432 int32_t hidetime
= (cl
->account
->acosc_penalty_duration
== -1 ? cfg
.acosc_penalty_duration
: cl
->account
->acosc_penalty_duration
);
438 LLIST
**sharelist
= get_and_lock_sharelist();
439 LLIST
*sharelist2
= ll_create("hidecards-sharelist");
441 for(ii
= 0; ii
< CAID_KEY
; ii
++)
445 ll_putall(sharelist2
, sharelist
[ii
]);
451 struct cc_card
**cardarray
= get_sorted_card_copy(sharelist2
, 0, &cardsize
);
452 ll_destroy(&sharelist2
);
454 for(ii
= 0; ii
< cardsize
; ii
++)
456 if(hidecards_card_valid_for_client(cl
, cardarray
[ii
]))
458 if (cardarray
[ii
]->id
)
460 hide_count
= hide_card_to_client(cardarray
[ii
], cl
);
463 cs_log_dbg(D_TRACE
, "Hiding card_%d caid=%04x remoteid=%08x from %s for %d %s",
464 uu
, cardarray
[ii
]->caid
, cardarray
[ii
]->remote_id
, username(cl
), hidetime
, hidetime
>1 ? "secconds" : "seccond");
471 cs_sleepms(hidetime
* 1000);
474 for(ii
= 0; ii
< cardsize
; ii
++)
476 if(hidecards_card_valid_for_client(cl
, cardarray
[ii
]))
478 if (cardarray
[ii
]->id
)
480 hide_count
= unhide_card_to_client(cardarray
[ii
], cl
);
483 cs_log_dbg(D_TRACE
, "Unhiding card_%d caid=%04x remoteid=%08x for %s",
484 uu
, cardarray
[ii
]->caid
, cardarray
[ii
]->remote_id
, username(cl
));
496 } // case ACTION_CLIENT_HIDECARDS
500 __free_job_data(cl
, data
);
503 if(thread_pipe
[1] && (mbuf
[0] != 0x00))
505 cs_log_dump_dbg(D_TRACE
, mbuf
, 1, "[OSCAM-WORK] Write to pipe:");
506 if(write(thread_pipe
[1], mbuf
, 1) == -1) // wakeup client check
508 cs_log_dbg(D_TRACE
, "[OSCAM-WORK] Writing to pipe failed (errno=%d %s)", errno
, strerror(errno
));
512 // Check for some race condition where while we ended, another thread added a job
513 SAFE_MUTEX_LOCK(&cl
->thread_lock
);
514 if(cl
->joblist
&& ll_count(cl
->joblist
) > 0)
516 SAFE_MUTEX_UNLOCK(&cl
->thread_lock
);
521 cl
->thread_active
= 0;
522 SAFE_MUTEX_UNLOCK(&cl
->thread_lock
);
526 cl
->thread_active
= 0;
527 cl
->work_mbuf
= NULL
; // Prevent free_client from freeing mbuf (->work_mbuf)
534 * adds a job to the job queue
535 * if ptr should be free() after use, set len to the size
538 int32_t add_job(struct s_client
*cl
, enum actions action
, void *ptr
, int32_t len
)
543 { cs_log("WARNING: add_job failed. Client killed!"); } // Ignore jobs for killed clients
549 if(action
== ACTION_CACHE_PUSH_OUT
&& cacheex_check_queue_length(cl
))
556 struct job_data
*data
;
557 if(!cs_malloc(&data
, sizeof(struct job_data
)))
564 data
->action
= action
;
568 cs_ftime(&data
->time
);
570 SAFE_MUTEX_LOCK(&cl
->thread_lock
);
571 if(cl
&& !cl
->kill
&& cl
->thread_active
)
574 { cl
->joblist
= ll_create("joblist"); }
575 ll_append(cl
->joblist
, data
);
576 if(cl
->thread_active
== 2)
577 { pthread_kill(cl
->thread
, OSCAM_SIGNAL_WAKEUP
); }
578 SAFE_MUTEX_UNLOCK(&cl
->thread_lock
);
579 cs_log_dbg(D_TRACE
, "add %s job action %d queue length %d %s",
580 action
> ACTION_CLIENT_FIRST
? "client" : "reader", action
,
581 ll_count(cl
->joblist
), username(cl
));
585 /* pcsc doesn't like this; segfaults on x86, x86_64 */
586 int8_t modify_stacksize
= 0;
587 struct s_reader
*rdr
= cl
->reader
;
588 if(cl
->typ
!= 'r' || !rdr
|| rdr
->typ
!= R_PCSC
)
589 { modify_stacksize
= 1; }
591 if(action
!= ACTION_READER_CHECK_HEALTH
)
593 cs_log_dbg(D_TRACE
, "start %s thread action %d",
594 action
> ACTION_CLIENT_FIRST
? "client" : "reader", action
);
597 int32_t ret
= start_thread("client work", work_thread
, (void *)data
, &cl
->thread
, 1, modify_stacksize
);
600 cs_log("ERROR: can't create thread for %s (errno=%d %s)",
601 action
> ACTION_CLIENT_FIRST
? "client" : "reader", ret
, strerror(ret
));
605 cl
->thread_active
= 1;
606 SAFE_MUTEX_UNLOCK(&cl
->thread_lock
);