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 #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];
32 static void free_job_data(struct job_data
*data
)
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
);
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
)))
60 ll_destroy(&cl
->joblist
);
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
;
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',
91 set_thread_name(thread_name
);
94 #define __free_job_data(client, job_data) \
96 client->work_job_data = NULL; \
97 if(job_data && job_data != &tmp_data) { \
98 free_job_data(job_data); \
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!
122 { bufsize
= DEFAULT_MODULE_BUFSIZE
; }
125 if(!cs_malloc(&mbuf
, bufsize
))
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
;
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)
150 { restart_cardreader(reader
, 0); }
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
)); }
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
);
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
);
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
)
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
);
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
));
203 cs_ftime(&start
); // register start time for new poll next run
206 { data
->action
= ACTION_READER_REMOTE
; }
211 data
->action
= ACTION_CLIENT_UDP
;
216 { data
->action
= ACTION_CLIENT_TCP
; }
218 if(pfd
[0].revents
& (POLLHUP
| POLLNVAL
| POLLERR
))
227 if(!reader
&& data
->action
< ACTION_CLIENT_FIRST
)
229 __free_job_data(cl
, data
);
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
);
246 if(data
!= &tmp_data
)
247 { cl
->work_job_data
= data
; } // Track the current job_data
251 case ACTION_READER_IDLE
:
252 reader_do_idle(reader
);
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?
261 if(cl
->reader
->ph
.type
== MOD_CONN_TCP
)
262 { network_tcp_connection_close(reader
, "disconnect"); }
265 rc
= cl
->reader
->ph
.recv(cl
, mbuf
, bufsize
);
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;
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
)
287 casc_check_dcw(reader
, i
, rc
, dcw
);
293 case ACTION_READER_RESET
:
294 cardreader_do_reset(reader
);
297 case ACTION_READER_ECM_REQUEST
:
298 reader_get_ecm(reader
, data
->ptr
);
301 case ACTION_READER_EMM
:
302 reader_do_emm(reader
, data
->ptr
);
305 case ACTION_READER_SENDCMD
:
306 #ifdef WITH_CARDREADER
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
);
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:");
328 case ACTION_READER_CARDINFO
:
329 reader_do_card_info(reader
);
332 case ACTION_READER_POLL_STATUS
:
333 #ifdef READER_VIDEOGUARD
334 cardreader_poll_status(reader
);
338 case ACTION_READER_INIT
:
340 { reader_init(reader
); }
343 case ACTION_READER_RESTART
:
348 case ACTION_READER_RESET_FAST
:
349 cl
->reader
->card_status
= CARD_NEED_INIT
;
350 cardreader_do_reset(reader
);
353 case ACTION_READER_CHECK_HEALTH
:
354 cardreader_do_checkhealth(reader
);
357 case ACTION_READER_CAPMT_NOTIFY
:
358 if(cl
->reader
->ph
.c_capmt
) { cl
->reader
->ph
.c_capmt(cl
, data
->ptr
); }
361 case ACTION_CLIENT_UDP
:
362 n
= module
->recv(cl
, data
->ptr
, data
->len
);
364 module
->s_handler(cl
, data
->ptr
, n
);
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?
371 if(s
< 0) // system error or fd wants to be closed
373 cl
->kill
= 1; // kill client on next run
376 n
= module
->recv(cl
, mbuf
, bufsize
);
379 cl
->kill
= 1; // kill client on next run
382 module
->s_handler(cl
, mbuf
, n
);
385 case ACTION_CACHEEX1_DELAY
:
386 cacheex_mode1_delay(data
->ptr
);
389 case ACTION_CACHEEX_TIMEOUT
:
390 cacheex_timeout(data
->ptr
);
393 case ACTION_FALLBACK_TIMEOUT
:
394 fallback_timeout(data
->ptr
);
397 case ACTION_CLIENT_TIMEOUT
:
398 ecm_timeout(data
->ptr
);
401 case ACTION_ECM_ANSWER_READER
:
405 case ACTION_ECM_ANSWER_CACHE
:
406 write_ecm_answer_fromcache(data
->ptr
);
409 case ACTION_CLIENT_INIT
:
411 { module
->s_init(cl
); }
412 cl
->is_udp
= module
->type
== MOD_CONN_UDP
;
416 case ACTION_CLIENT_IDLE
:
418 { module
->s_idle(cl
); }
421 cs_log("user %s reached %d sec idle limit.", username(cl
), cfg
.cmaxidle
);
426 case ACTION_CACHE_PUSH_OUT
:
427 cacheex_push_out(cl
, data
->ptr
);
430 case ACTION_CLIENT_KILL
:
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
);
444 case ACTION_PEER_IDLE
:
445 if(module
->s_peer_idle
)
446 { module
->s_peer_idle(cl
); }
449 case ACTION_CLIENT_HIDECARDS
:
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
);
460 LLIST
**sharelist
= get_and_lock_sharelist();
461 LLIST
*sharelist2
= ll_create("hidecards-sharelist");
463 for(ii
= 0; ii
< CAID_KEY
; ii
++)
467 ll_putall(sharelist2
, sharelist
[ii
]);
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
);
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");
493 cs_sleepms(hidetime
* 1000);
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
);
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
));
518 } // case ACTION_CLIENT_HIDECARDS
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
);
543 cl
->thread_active
= 0;
544 SAFE_MUTEX_UNLOCK(&cl
->thread_lock
);
548 cl
->thread_active
= 0;
549 cl
->work_mbuf
= NULL
; // Prevent free_client from freeing mbuf (->work_mbuf)
556 * adds a job to the job queue
557 * if ptr should be free() after use, set len to the size
560 int32_t add_job(struct s_client
*cl
, enum actions action
, void *ptr
, int32_t len
)
565 { cs_log("WARNING: add_job failed. Client killed!"); } // Ignore jobs for killed clients
571 if(action
== ACTION_CACHE_PUSH_OUT
&& cacheex_check_queue_length(cl
))
578 struct job_data
*data
;
579 if(!cs_malloc(&data
, sizeof(struct job_data
)))
586 data
->action
= action
;
590 cs_ftime(&data
->time
);
592 SAFE_MUTEX_LOCK(&cl
->thread_lock
);
593 if(cl
&& !cl
->kill
&& cl
->thread_active
)
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
));
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
);
622 cs_log("ERROR: can't create thread for %s (errno=%d %s)",
623 action
> ACTION_CLIENT_FIRST
? "client" : "reader", ret
, strerror(ret
));
627 cl
->thread_active
= 1;
628 SAFE_MUTEX_UNLOCK(&cl
->thread_lock
);