source: trunk/oscam-reader.c@ 3181

Last change on this file since 3181 was 3181, checked in by dingo35, 10 years ago

Adding threadsafety FIXMEs, feel free to join checking..

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