source: trunk/oscam-reader.c@ 4149

Last change on this file since 4149 was 4149, checked in by dingo35, 12 years ago

checked some routines on threadsafety

File size: 23.7 KB
Line 
1#include "globals.h"
2
3int logfd=0;
4
5void reader_do_idle(struct s_reader * reader);
6
7void cs_ri_brk(struct s_reader * reader, int flag)
8{
9 if (flag)
10 reader->brk_pos=reader->init_history_pos;
11 else
12 reader->init_history_pos=reader->brk_pos;
13}
14
15void cs_ri_log(struct s_reader * reader, char *fmt,...)
16{
17 char txt[256];
18
19 va_list params;
20 va_start(params, fmt);
21 vsprintf(txt, fmt, params);
22 va_end(params);
23 cs_log("%s", txt);
24
25 if (cfg->saveinithistory) {
26 FILE *fp;
27 char filename[256];
28 char *buffer;
29 sprintf(filename, "%s/reader%d", get_tmp_dir(), get_ridx(reader));
30 int size = reader->init_history_pos+strlen(txt)+1;
31 buffer = malloc(size+1);
32
33 if (buffer == NULL)
34 return;
35
36 memset(buffer, 32, size);
37
38 fp = fopen(filename, "r");
39
40 if (fp) {
41 fread(buffer, 1, reader->init_history_pos, fp);
42 fclose(fp);
43 }
44
45 sprintf(buffer+reader->init_history_pos, "%s\n", txt);
46
47 fp = fopen(filename, "w");
48 if (fp) {
49 fwrite(buffer, 1, reader->init_history_pos+strlen(txt)+1, fp);
50 fclose(fp);
51 }
52
53 free(buffer);
54 }
55 reader->init_history_pos+=strlen(txt)+1;
56}
57
58static void casc_check_dcw(struct s_reader * reader, int idx, int rc, uchar *cw)
59{
60 int i;
61 struct s_client *cl = reader->client;
62 for (i=0; i<CS_MAXPENDING; i++)
63 {
64 if ((cl->ecmtask[i].rc>=10) &&
65 (!memcmp(cl->ecmtask[i].ecmd5, cl->ecmtask[idx].ecmd5, CS_ECMSTORESIZE)))
66 {
67 if (rc)
68 {
69 cl->ecmtask[i].rc=(i==idx) ? 1 : 2;
70#ifdef CS_WITH_GBOX
71 if(cl->ecmtask[i].gbxRidx)cl->ecmtask[i].rc=0;
72#endif
73 memcpy(cl->ecmtask[i].cw, cw, 16);
74 }
75 else
76 cl->ecmtask[i].rc=0;
77 write_ecm_answer(reader, &cl->ecmtask[i]);
78 cl->ecmtask[i].idx=0;
79 }
80 }
81}
82
83int casc_recv_timer(struct s_reader * reader, uchar *buf, int l, int msec)
84{
85 struct timeval tv;
86 fd_set fds;
87 int rc;
88 struct s_client *cl = reader->client;
89
90 if (!cl->pfd) return(-1);
91 tv.tv_sec = msec/1000;
92 tv.tv_usec = (msec%1000)*1000;
93 FD_ZERO(&fds);
94 FD_SET(cl->pfd, &fds);
95 select(cl->pfd+1, &fds, 0, 0, &tv);
96 rc=0;
97 if (FD_ISSET(cl->pfd, &fds))
98 if (!(rc=reader->ph.recv(cl, buf, l)))
99 rc=-1;
100
101 return(rc);
102}
103
104#define MSTIMEOUT 0x800000
105#define DEFAULT_CONNECT_TIMEOUT 500
106
107int network_select(int forRead, int timeout)
108{
109 int sd = cur_client()->udp_fd;
110 if(sd>=0) {
111 fd_set fds;
112 FD_ZERO(&fds); FD_SET(sd,&fds);
113 struct timeval tv;
114 if(timeout&MSTIMEOUT) { tv.tv_sec=0; tv.tv_usec=(timeout&~MSTIMEOUT)*1000; }
115 else { tv.tv_sec=0; tv.tv_usec=timeout*1000; }
116 int r=select(sd+1,forRead ? &fds:0,forRead ? 0:&fds,0,&tv);
117 if(r>0) return 1;
118 else if(r<0) {
119 cs_debug_mask(D_READER, "socket: select failed: %s",strerror(errno));
120 return -1;
121 }
122 else {
123 if(timeout>0) {
124 cs_debug_mask(D_READER, "socket: select timed out (%d %s)",timeout&~MSTIMEOUT,(timeout&MSTIMEOUT)?"ms":"secs");
125 }
126 errno=ETIMEDOUT;
127 return 0;
128 }
129 }
130 return -1;
131}
132
133// according to documentation getaddrinfo() is thread safe
134int hostResolve(struct s_reader *rdr)
135{
136 int result = 0;
137 struct s_client *cl = rdr->client;
138
139 pthread_mutex_lock(&gethostbyname_lock);
140
141 in_addr_t last_ip = cl->ip;
142
143 if (cfg->resolve_gethostbyname) { //Resolve with gethostbyname:
144 struct hostent *rht = gethostbyname(rdr->device);
145 if (!rht) {
146 cs_log("can't resolve %s", rdr->device);
147 result = 0;
148 } else {
149 memcpy(&cl->udp_sa.sin_addr, rht->h_addr, sizeof(cl->udp_sa.sin_addr));
150 cl->ip=cs_inet_order(cl->udp_sa.sin_addr.s_addr);
151 result = 1;
152 }
153 }
154 else { //Resolve with getaddrinfo:
155 struct addrinfo hints, *res = NULL;
156 memset(&hints, 0, sizeof(hints));
157 hints.ai_socktype = SOCK_STREAM;
158 hints.ai_family = cl->udp_sa.sin_family;
159 hints.ai_protocol = IPPROTO_TCP;
160
161 int err = getaddrinfo(rdr->device, NULL, &hints, &res);
162 if (err != 0 || !res || !res->ai_addr) {
163 cs_log("can't resolve %s, error: %s", rdr->device, err ? gai_strerror(err) : "unknown");
164 result = 0;
165 } else {
166 cl->udp_sa.sin_addr.s_addr = ((struct sockaddr_in *)(res->ai_addr))->sin_addr.s_addr;
167 cl->ip = cs_inet_order(cl->udp_sa.sin_addr.s_addr);
168 result = 1;
169 }
170 if (res) freeaddrinfo(res);
171 }
172
173 if (!result) {
174 cl->udp_sa.sin_addr.s_addr = 0;
175 cl->ip = 0;
176 } else if (cl->ip != last_ip) {
177 uchar *ip = (uchar*) &cl->ip;
178 cs_log("%s: resolved ip=%d.%d.%d.%d", rdr->device, ip[3], ip[2], ip[1], ip[0]);
179 }
180
181 pthread_mutex_unlock(&gethostbyname_lock);
182
183 return result;
184}
185
186void clear_block_delay(struct s_reader *rdr) {
187 rdr->tcp_block_delay = 100;
188 cs_ftime(&rdr->tcp_block_connect_till);
189}
190
191void block_connect(struct s_reader *rdr) {
192 if (!rdr->tcp_block_delay)
193 rdr->tcp_block_delay = 100; //starting blocking time, 100ms
194 rdr->tcp_block_connect_till.time += rdr->tcp_block_delay / 1000;
195 rdr->tcp_block_connect_till.millitm += rdr->tcp_block_delay % 1000;
196 rdr->tcp_block_delay *= 2; //increment timeouts
197 if (rdr->tcp_block_delay >= 60*1000)
198 rdr->tcp_block_delay = 60*1000; //max 1min, todo config
199 cs_debug_mask(D_TRACE, "tcp connect blocking delay for %s set to %d", rdr->label, rdr->tcp_block_delay);
200}
201
202int is_connect_blocked(struct s_reader *rdr) {
203 struct timeb cur_time;
204 cs_ftime(&cur_time);
205 return (comp_timeb(&cur_time, &rdr->tcp_block_connect_till) < 0);
206}
207
208int network_tcp_connection_open()
209{
210 struct s_client *cl = cur_client();
211 struct s_reader *rdr = cl->reader;
212 cs_log("connecting to %s", rdr->device);
213
214 in_addr_t last_ip = cl->ip;
215 if (!hostResolve(rdr))
216 return -1;
217
218 if (last_ip != cl->ip) //clean blocking delay on ip change:
219 clear_block_delay(rdr);
220 if (is_connect_blocked(rdr)) { //inside of blocking delay, do not connect!
221 cs_log("tcp connect blocking delay asserted for %s", rdr->label);
222 return -1;
223 }
224
225 int flag = 1;
226 setsockopt(cl->udp_fd, IPPROTO_TCP, TCP_NODELAY, (char *) &flag, sizeof(int));
227
228 int sd = cl->udp_fd;
229 int fl = fcntl(sd, F_GETFL);
230 fcntl(sd, F_SETFL, O_NONBLOCK); //set to nonblocking mode to avoid "endless" connecting loops and pipe-overflows:
231 int res =connect(sd, (struct sockaddr *)&cl->udp_sa, sizeof(cl->udp_sa));
232 if (res == 0) {
233 fcntl(sd, F_SETFL, fl); //connect sucessfull, restore blocking mode
234 clear_block_delay(rdr);
235 return sd;
236 }
237
238 if (errno == EINPROGRESS || errno == EALREADY) {
239 if (network_select(0, DEFAULT_CONNECT_TIMEOUT) > 0) { //if connect is in progress, wait apr. 500ms
240 int r = -1;
241 uint l = sizeof(r);
242 if (getsockopt(sd, SOL_SOCKET, SO_ERROR, &r, (socklen_t*)&l) == 0) {
243 if (r == 0) {
244 fcntl(sd, F_SETFL, fl);
245 clear_block_delay(rdr);
246 return sd; //now we are connected
247 }
248 }
249 }
250 }
251 //else we are not connected - or already connected:
252 else if (errno == EISCONN) {
253 cs_log("already connected!");
254 fcntl(sd, F_SETFL, fl);
255 clear_block_delay(rdr);
256 return sd;
257 }
258
259 if (errno == EBADF || errno == ENOTSOCK) {
260 cs_log("connect failed: bad socket/descriptor %d", sd);
261 }
262 else if (errno == ETIMEDOUT) {
263 cs_log("connect failed: timeout");
264 }
265 else if (errno == ECONNREFUSED) {
266 cs_log("connection refused");
267 }
268 else if (errno == ENETUNREACH) {
269 cs_log("connect failed: network unreachable!");
270 }
271 else if (errno == EADDRINUSE) {
272 cs_log("connect failed: address in use!");
273 }
274 else
275 cs_log("connect(fd=%d) failed: (errno=%d: %s)", sd, errno, strerror(errno));
276
277 fcntl(sd, F_SETFL, fl); //restore blocking mode
278
279 //connect has failed. Block connect for a while:
280 block_connect(rdr);
281
282 return -1;
283}
284
285void network_tcp_connection_close(struct s_client *cl, int fd)
286{
287 if(!cl) return;
288 struct s_reader *reader = cl->reader;
289 cs_debug_mask(D_READER, "tcp_conn_close(): fd=%d, cl->typ == 'c'=%d", fd, cl->typ == 'c');
290
291 if (fd) {
292 close(fd);
293 if (fd == cl->udp_fd)
294 cl->udp_fd = 0;
295 if (fd == cl->pfd)
296 cl->pfd = 0;
297
298 if(reader)
299 clear_block_delay(reader);
300 }
301
302
303 if (cl->typ != 'c')
304 {
305 int i;
306 //cl->pfd = 0;
307 if(reader)
308 reader->tcp_connected = 0;
309
310 if (cl->ecmtask) {
311 for (i = 0; i < CS_MAXPENDING; i++) {
312 cl->ecmtask[i].idx = 0;
313 cl->ecmtask[i].rc = 0;
314 }
315 }
316
317 if(reader) {
318 reader->ncd_msgid=0;
319 reader->last_s=reader->last_g=0;
320
321 if (reader->ph.c_init(cl)) {
322 cs_debug_mask(D_READER, "network_tcp_connection_close() exit(1);");
323 cs_exit(1);
324 }
325 }
326 }
327}
328
329static void casc_do_sock_log(struct s_reader * reader)
330{
331 int i, idx;
332 ushort caid, srvid;
333 ulong provid;
334 struct s_client *cl = reader->client;
335
336 idx=reader->ph.c_recv_log(&caid, &provid, &srvid);
337 cl->last=time((time_t)0);
338 if (idx<0) return; // no dcw-msg received
339
340 for (i=0; i<CS_MAXPENDING; i++)
341 {
342 if ( (cl->ecmtask[i].rc>=10)
343 && (cl->ecmtask[i].idx==idx)
344 && (cl->ecmtask[i].caid==caid)
345 && (cl->ecmtask[i].prid==provid)
346 && (cl->ecmtask[i].srvid==srvid))
347 {
348 casc_check_dcw(reader, i, 0, cl->ecmtask[i].cw); // send "not found"
349 break;
350 }
351 }
352}
353
354static void casc_do_sock(struct s_reader * reader, int w)
355{
356 int i, n, idx, rc, j;
357 uchar buf[1024];
358 uchar dcw[16];
359 struct s_client *cl = reader->client;
360
361 if ((n=casc_recv_timer(reader, buf, sizeof(buf), w))<=0)
362 {
363 if (reader->ph.type==MOD_CONN_TCP && reader->typ != R_RADEGAST)
364 {
365 if (reader->ph.c_idle)
366 reader_do_idle(reader);
367 else {
368 cs_debug_mask(D_READER, "casc_do_sock: close connection");
369 network_tcp_connection_close(reader->client, cl->udp_fd);
370 }
371 return;
372 }
373 }
374 cl->last=time((time_t)0);
375 idx=reader->ph.c_recv_chk(cl, dcw, &rc, buf, n);
376
377 if (idx<0) return; // no dcw received
378 reader->last_g=time((time_t*)0); // for reconnect timeout
379//cs_log("casc_do_sock: last_s=%d, last_g=%d", reader->last_s, reader->last_g);
380 if (!idx) idx=cl->last_idx;
381 j=0;
382 for (i=0; i<CS_MAXPENDING; i++)
383 {
384
385 if (cl->ecmtask[i].idx==idx)
386 {
387 casc_check_dcw(reader, i, rc, dcw);
388 j=1;
389 break;
390 }
391 }
392}
393
394static void casc_get_dcw(struct s_reader * reader, int n)
395{
396 int w;
397 struct timeb tps, tpe;
398 struct s_client *cl = reader->client;
399 tpe=cl->ecmtask[n].tps;
400 //tpe.millitm+=1500; // TODO: timeout of 1500 should be config
401
402 tpe.time += cfg->srtimeout/1000;
403 tpe.millitm += cfg->srtimeout%1000;
404
405 cs_ftime(&tps);
406 while (((w=1000*(tpe.time-tps.time)+tpe.millitm-tps.millitm)>0)
407 && (cl->ecmtask[n].rc>=10))
408 {
409 casc_do_sock(reader, w);
410 cs_ftime(&tps);
411 }
412 if (cl->ecmtask[n].rc>=10)
413 casc_check_dcw(reader, n, 0, cl->ecmtask[n].cw); // simulate "not found"
414}
415
416
417
418int casc_process_ecm(struct s_reader * reader, ECM_REQUEST *er)
419{
420 int rc, n, i, sflag;
421 time_t t;//, tls;
422 struct s_client *cl = reader->client;
423
424 uchar buf[512];
425
426 t=time((time_t *)0);
427 for (n=-1, i=0, sflag=1; i<CS_MAXPENDING; i++)
428 {
429 if ((t-(ulong)cl->ecmtask[i].tps.time > ((cfg->ctimeout + 500) / 1000) + 1) &&
430 (cl->ecmtask[i].rc>=10)) // drop timeouts
431 {
432 cl->ecmtask[i].rc=0;
433 }
434 if (n<0 && (cl->ecmtask[i].rc<10)) // free slot found
435 n=i;
436 if ((cl->ecmtask[i].rc>=10) && // ecm already pending
437 (!memcmp(er->ecmd5, cl->ecmtask[i].ecmd5, CS_ECMSTORESIZE)) &&
438 (er->level<=cl->ecmtask[i].level)) // ... this level at least
439 sflag=0;
440 }
441 if (n<0)
442 {
443 cs_log("WARNING: ecm pending table overflow !!");
444 return(-2);
445 }
446 memcpy(&cl->ecmtask[n], er, sizeof(ECM_REQUEST));
447 if( reader->typ == R_NEWCAMD )
448 cl->ecmtask[n].idx=(reader->ncd_msgid==0)?2:reader->ncd_msgid+1;
449 else
450 cl->ecmtask[n].idx=cl->idx++;
451 cl->ecmtask[n].rc=10;
452 cs_debug_mask(D_READER, "---- ecm_task %d, idx %d, sflag=%d, level=%d",
453 n, cl->ecmtask[n].idx, sflag, er->level);
454
455 if( reader->ph.type==MOD_CONN_TCP && reader->tcp_rto )
456 {
457 int rto = abs(reader->last_s - reader->last_g);
458 if (rto >= (reader->tcp_rto*60))
459 {
460 if (reader->ph.c_idle)
461 reader_do_idle(reader);
462 else {
463 cs_debug_mask(D_READER, "rto=%d", rto);
464 network_tcp_connection_close(reader->client, cl->udp_fd);
465 }
466 }
467 }
468
469 cs_ddump_mask(D_ATR, er->ecm, er->l, "casc ecm:");
470 rc=0;
471 if (sflag)
472 {
473 if ((rc=reader->ph.c_send_ecm(cl, &cl->ecmtask[n], buf)))
474 casc_check_dcw(reader, n, 0, cl->ecmtask[n].cw); // simulate "not found"
475 else
476 cl->last_idx = cl->ecmtask[n].idx;
477 reader->last_s = t; // used for inactive_timeout and reconnect_timeout in TCP reader
478
479 if (!reader->ph.c_multi)
480 casc_get_dcw(reader, n);
481 }
482
483//cs_log("casc_process_ecm 1: last_s=%d, last_g=%d", reader->last_s, reader->last_g);
484
485 if (cl->idx>0x1ffe) cl->idx=1;
486 return(rc);
487}
488
489static int reader_store_emm(uchar *emm, uchar type)
490{
491 int rc;
492 struct s_client *cl = cur_client();
493 memcpy(cl->emmcache[cl->rotate].emmd5, MD5(emm, emm[2], cl->dump), CS_EMMSTORESIZE);
494 cl->emmcache[cl->rotate].type=type;
495 cl->emmcache[cl->rotate].count=1;
496// cs_debug_mask(D_READER, "EMM stored (index %d)", rotate);
497 rc=cl->rotate;
498 cl->rotate=(++cl->rotate < CS_EMMCACHESIZE)?cl->rotate:0;
499 return(rc);
500}
501
502static void reader_get_ecm(struct s_reader * reader, ECM_REQUEST *er)
503{
504 //cs_log("hallo idx:%d rc:%d caid:%04X",er->idx,er->rc,er->caid);
505 if ((er->rc<10) )
506 {
507 send_dcw(reader->client, er);
508 return;
509 }
510
511 er->ocaid=er->caid;
512 if (!chk_bcaid(er, &reader->ctab))
513 {
514 cs_debug_mask(D_READER, "caid %04X filtered", er->caid);
515 er->rcEx=E2_CAID;
516 er->rc=0;
517 write_ecm_answer(reader, er);
518 return;
519 }
520 // cache2
521 if (check_cwcache2(er, er->client->grp))
522 {
523 er->rc=2;
524 write_ecm_answer(reader, er);
525 return;
526 }
527 if (reader->typ & R_IS_CASCADING)
528 {
529 struct s_client *cl = reader->client;
530 cl->last_srvid=er->srvid;
531 cl->last_caid=er->caid;
532 casc_process_ecm(reader, er);
533 return;
534 }
535#ifdef WITH_CARDREADER
536 if (reader->ratelimitecm) {
537 cs_debug_mask(D_READER, "ratelimit idx:%d rc:%d caid:%04X srvid:%04X",er->idx,er->rc,er->caid,er->srvid);
538 int foundspace=-1;
539 int h;
540 for (h=0;h<reader->ratelimitecm;h++) {
541 if (reader->rlecmh[h].srvid == er->srvid) {
542 foundspace=h;
543 cs_debug_mask(D_READER, "ratelimit found srvid in use at pos: %d",h);
544 break;
545 }
546 }
547 if (foundspace<0) {
548 for (h=0;h<reader->ratelimitecm;h++) {
549 if ((reader->rlecmh[h].last ==- 1) || ((time(NULL)-reader->rlecmh[h].last) > reader->ratelimitseconds)) {
550 foundspace=h;
551 cs_debug_mask(D_READER, "ratelimit found space at pos: %d old seconds %d",h,reader->rlecmh[h].last);
552 break;
553 }
554 }
555 }
556 if (foundspace<0) {
557 //drop
558 cs_debug_mask(D_READER, "ratelimit could not find space for srvid %04X. Dropping.",er->srvid);
559 er->rcEx=32;
560 er->rc=0;
561 int clcw;
562 for (clcw=0;clcw<16;clcw++) er->cw[clcw]=(uchar)0;
563 snprintf( er->msglog, MSGLOGSIZE, "ECMratelimit no space for srvid" );
564 write_ecm_answer(reader, er);
565 return;
566 } else {
567 reader->rlecmh[foundspace].last=time(NULL);
568 reader->rlecmh[foundspace].srvid=er->srvid;
569 }
570
571 }
572 cs_ddump_mask(D_ATR, er->ecm, er->l, "ecm:");
573 er->msglog[0] = 0;
574 struct timeb tps, tpe;
575 cs_ftime(&tps);
576 er->rc=reader_ecm(reader, er);
577 cs_ftime(&tpe);
578 if (cs_dblevel) {
579 ushort lc, *lp;
580 for (lp=(ushort *)er->ecm+(er->l>>2), lc=0; lp>=(ushort *)er->ecm; lp--)
581 lc^=*lp;
582 cs_debug_mask(D_TRACE, "reader: %s ecm: %04X real time: %d ms", reader->label, lc, 1000*(tpe.time-tps.time)+tpe.millitm-tps.millitm);
583 }
584 write_ecm_answer(reader, er);
585 reader_post_process(reader);
586#endif
587 //fixme re-activated code for testing
588 if(reader->typ=='r') reader->qlen--;
589 //printf("queue: %d\n",reader->qlen);
590}
591
592static int reader_do_emm(struct s_reader * reader, EMM_PACKET *ep)
593{
594 int i, no, rc, ecs;
595 char *rtxt[] = { "error", (reader->typ & R_IS_CASCADING) ? "sent" : "written", "skipped", "blocked" };
596 char *typedesc[]= { "unknown", "unique", "shared", "global" };
597 struct timeb tps, tpe;
598 struct s_client *cl = reader->client;
599
600 cs_ftime(&tps);
601
602 MD5(ep->emm, ep->emm[2], cl->dump);
603
604 no=0;
605 for (i=ecs=0; (i<CS_EMMCACHESIZE) && (!ecs); i++) {
606 if (!memcmp(cl->emmcache[i].emmd5, cl->dump, CS_EMMSTORESIZE)) {
607 if (reader->cachemm)
608 ecs=(reader->rewritemm > cl->emmcache[i].count) ? 1 : 2;
609 else
610 ecs=1;
611 no=++cl->emmcache[i].count;
612 i--;
613 }
614 }
615
616 if ((rc=ecs)<2)
617 {
618 if (reader->typ & R_IS_CASCADING) {
619 cs_debug_mask(D_READER, "network emm reader: %s" ,reader->label);
620
621 if (reader->ph.c_send_emm) {
622 rc=reader->ph.c_send_emm(ep);
623 } else {
624 cs_debug_mask(D_READER, "send_emm() support missing");
625 rc=0;
626 }
627 } else {
628 cs_debug_mask(D_READER, "local emm reader: %s" ,reader->label);
629#ifdef WITH_CARDREADER
630 rc=reader_emm(reader, ep);
631#else
632 rc=0;
633#endif
634 }
635
636 if (!ecs)
637 {
638 i=reader_store_emm(ep->emm, ep->type);
639 no=1;
640 }
641 }
642
643 if (rc) cl->lastemm=time((time_t)0);
644
645#ifdef CS_LED
646 if (rc) cs_switch_led(LED3, LED_BLINK_ON);
647#endif
648
649 if (reader->logemm & (1 << rc))
650 {
651 cs_ftime(&tpe);
652
653 cs_log("%s emmtype=%s, len=%d, idx=%d, cnt=%d: %s (%d ms) by %s",
654 username(ep->client), typedesc[cl->emmcache[i].type], ep->emm[2],
655 i, no, rtxt[rc], 1000*(tpe.time-tps.time)+tpe.millitm-tps.millitm, reader->label); //FIXME not sure why emmtyp must come from ep->client and typedesc can be of cur_client
656 }
657
658#ifdef WEBIF
659 //counting results
660 switch(rc){
661 case 0:
662 reader->emmerror[ep->type]++;
663 break;
664 case 1:
665 reader->emmwritten[ep->type]++;
666 break;
667 case 2:
668 reader->emmskipped[ep->type]++;
669 break;
670 case 3:
671 reader->emmblocked[ep->type]++;
672 break;
673 }
674#endif
675
676#ifdef QBOXHD_LED
677 if (rc) qboxhd_led_blink(QBOXHD_LED_COLOR_BLUE,QBOXHD_LED_BLINK_MEDIUM);
678#endif
679
680
681 return(rc);
682}
683
684static int reader_listen(struct s_reader * reader, int fd1, int fd2)
685{
686 int fdmax, tcp_toflag, use_tv=(!(reader->typ & R_IS_CASCADING));
687 int is_tcp=(reader->ph.type==MOD_CONN_TCP);
688 fd_set fds;
689 struct timeval tv;
690
691#ifdef CS_WITH_GBOX
692 if(reader->typ==R_GBOX) {
693 struct timeb tpe;
694 int x;
695 ulong ms;
696 cs_ftime(&tpe);
697 for(x=0;x<CS_MAXPENDING;x++){
698 ms=1000*(tpe.time-cl->ecmtask[x].tps.time)+tpe.millitm-cl->ecmtask[x].tps.millitm;
699 if(cl->ecmtask[x].rc == 10 && ms > cfg->ctimeout && cl->ridx == cl->ecmtask[x].gbxRidx) {
700 //cs_log("hello rc=%d idx:%d x:%d ridx%d ridx:%d",cl->ecmtask[x].rc,cl->ecmtask[x].idx,x,ridx,cl->ecmtask[x].gbxRidx);
701 cl->ecmtask[x].rc=5;
702 send_dcw(cl, &cl->ecmtask[x]);
703 }
704 }
705 }
706#endif
707
708 tcp_toflag=(fd2 && is_tcp && reader->tcp_ito && reader->tcp_connected);
709 tv.tv_sec = 0;
710 tv.tv_usec = 100000L;
711 if (tcp_toflag)
712 {
713 tv.tv_sec = reader->tcp_ito*60;
714 tv.tv_usec = 0;
715 use_tv = 1;
716 }
717 FD_ZERO(&fds);
718 FD_SET(fd1, &fds);
719 if (fd2) FD_SET(fd2, &fds);
720 if (logfd) FD_SET(logfd, &fds);
721 fdmax=(fd1>fd2) ? fd1 : fd2;
722 fdmax=(fdmax>logfd) ? fdmax : logfd;
723 if (select(fdmax+1, &fds, 0, 0, (use_tv) ? &tv : 0)<0) return(0);
724
725 if ((logfd) && (FD_ISSET(logfd, &fds)))
726 {
727 cs_debug_mask(D_READER, "select: log-socket ist set");
728 return(3);
729 }
730
731 if ((fd2) && (FD_ISSET(fd2, &fds)))
732 {
733 cs_debug_mask(D_READER, "select: socket is set");
734 return(2);
735 }
736
737 if (FD_ISSET(fd1, &fds))
738 {
739 if (tcp_toflag)
740 {
741 time_t now;
742 int time_diff;
743 time(&now);
744 time_diff = abs(now-reader->last_s);
745 if (time_diff>(reader->tcp_ito*60))
746 {
747 if (reader->ph.c_idle)
748 reader_do_idle(reader);
749 else {
750 cs_debug_mask(D_READER, "%s inactive_timeout (%d), close connection (fd=%d)",
751 reader->ph.desc, time_diff, fd2);
752 network_tcp_connection_close(reader->client, fd2);
753 }
754 }
755 }
756 cs_debug_mask(D_READER, "select: pipe is set");
757 return(1);
758 }
759
760 if (tcp_toflag)
761 {
762 if (reader->ph.c_idle)
763 reader_do_idle(reader);
764 else {
765 cs_debug_mask(D_READER, "%s inactive_timeout (%d), close connection (fd=%d)",
766 reader->ph.desc, tv.tv_sec, fd2);
767 network_tcp_connection_close(reader->client, fd2);
768 }
769 return(0);
770 }
771
772#ifdef WITH_CARDREADER
773 if (!(reader->typ & R_IS_CASCADING)) reader_checkhealth(reader);
774#endif
775 return(0);
776}
777
778void reader_do_card_info(struct s_reader * reader)
779{
780#ifdef WITH_CARDREADER
781 reader_card_info(reader);
782#endif
783 if (reader->ph.c_card_info)
784 reader->ph.c_card_info();
785}
786
787void clear_reader_pipe(struct s_reader * reader)
788{
789 uchar *ptr;
790 int pipeCmd;
791 while (reader && reader->client && reader->client->fd_m2c_c)
792 {
793 pipeCmd = read_from_pipe(reader->client->fd_m2c_c, &ptr, 0);
794 if (ptr) free(ptr);
795 if (pipeCmd==PIP_ID_ERR || pipeCmd==PIP_ID_NUL)
796 break;
797 }
798}
799
800static void reader_do_pipe(struct s_reader * reader)
801{
802 uchar *ptr;
803 int pipeCmd = read_from_pipe(reader->client->fd_m2c_c, &ptr, 0);
804
805 switch(pipeCmd)
806 {
807 case PIP_ID_ECM:
808 reader_get_ecm(reader, (ECM_REQUEST *)ptr);
809 break;
810 case PIP_ID_EMM:
811 reader_do_emm(reader, (EMM_PACKET *)ptr);
812 break;
813 case PIP_ID_CIN:
814 reader_do_card_info(reader);
815 break;
816 case PIP_ID_ERR:
817 cs_exit(1);
818 break;
819 default:
820 cs_log("unhandled pipe message %d (reader %s)", pipeCmd, reader->label);
821 break;
822 }
823 if (ptr) free(ptr);
824}
825
826void reader_do_idle(struct s_reader * reader)
827{
828 if (reader->ph.c_idle)
829 reader->ph.c_idle();
830}
831
832static void reader_main(struct s_reader * reader)
833{
834 while (1)
835 {
836 switch(reader_listen(reader, reader->client->fd_m2c_c, reader->client->pfd))
837 {
838 case 0: reader_do_idle(reader); break;
839 case 1: reader_do_pipe(reader) ; break;
840 case 2: casc_do_sock(reader, 0) ; break;
841 case 3: casc_do_sock_log(reader); break;
842 }
843 }
844}
845
846void * start_cardreader(void * rdr)
847{
848 struct s_reader * reader = (struct s_reader *) rdr;
849
850 reader->client->thread=pthread_self();
851 pthread_setspecific(getclient, reader->client);
852 strcpy(reader->client->usr, first_client->usr);
853
854 if (reader->typ & R_IS_CASCADING)
855 {
856 reader->client->typ='p';
857 reader->client->port=reader->r_port;
858 strcpy(reader->client->usr, reader->r_usr);
859 cs_log("proxy thread started (thread=%8X, label=%s, server=%s)",pthread_self(), reader->label, reader->device);
860
861 if (!(reader->ph.c_init)) {
862 cs_log("FATAL: %s-protocol not supporting cascading", reader->ph.desc);
863 cs_sleepms(1000);
864 cs_exit(1);
865 }
866
867 if (reader->ph.c_init(reader->client)) {
868 //proxy reader start failed
869 cs_exit(1);
870 }
871
872 if ((reader->log_port) && (reader->ph.c_init_log))
873 reader->ph.c_init_log();
874 }
875#ifdef WITH_CARDREADER
876 else
877 {
878 reader->client->ip=cs_inet_addr("127.0.0.1");
879 cs_log("reader thread started (thread=%8X, label=%s, device=%s, detect=%s%s, mhz=%d, cardmhz=%d)", pthread_self(), reader->label,
880 reader->device, reader->detect&0x80 ? "!" : "",RDR_CD_TXT[reader->detect&0x7f], reader->mhz,reader->cardmhz);
881 while (reader_device_init(reader)==2)
882 cs_sleepms(60000); // wait 60 secs and try again
883 }
884
885#endif
886 reader->client->emmcache=(struct s_emm *)malloc(CS_EMMCACHESIZE*(sizeof(struct s_emm)));
887 if (!reader->client->emmcache)
888 {
889 cs_log("Cannot allocate memory (errno=%d)", errno);
890 cs_exit(1);
891 }
892 memset(reader->client->emmcache, 0, CS_EMMCACHESIZE*(sizeof(struct s_emm)));
893
894 reader->client->ecmtask=(ECM_REQUEST *)malloc(CS_MAXPENDING*(sizeof(ECM_REQUEST)));
895 if (!reader->client->ecmtask)
896 {
897 cs_log("Cannot allocate memory (errno=%d)", errno);
898 cs_exit(1);
899 }
900 memset(reader->client->ecmtask, 0, CS_MAXPENDING*(sizeof(ECM_REQUEST)));
901 reader_main(reader);
902 cs_exit(0);
903 return NULL; //dummy to prevent compiler error
904}
905
Note: See TracBrowser for help on using the repository browser.