source: trunk/oscam-reader.c@ 109

Last change on this file since 109 was 93, checked in by smurzch2, 11 years ago

Change timeouts from seconds to milliseconds.

Thanks for this patch to okmikel.
Timeouts are now ajustable in ms instead of seconds in the oscam.conf.
Values <= 100 are still interpreted as seconds because of compatibility reasons
to old config files

File size: 12.6 KB
Line 
1#include "globals.h"
2
3int ridx=0, logfd=0;
4
5static int proxy;
6static struct s_emm *emmcache;
7static int last_idx=1;
8static ushort idx=1;
9
10void cs_ri_brk(int flag)
11{
12#ifdef CS_RDR_INIT_HIST
13 static int brk_pos=0;
14 if (flag)
15 brk_pos=reader[ridx].init_history_pos;
16 else
17 reader[ridx].init_history_pos=brk_pos;
18#endif
19}
20
21void cs_ri_log(char *fmt,...)
22{
23 int val;
24 char txt[256];
25
26 va_list params;
27 va_start(params, fmt);
28 vsprintf(txt, fmt, params);
29 va_end(params);
30 cs_log("%s", txt);
31#ifdef CS_RDR_INIT_HIST
32 val=sizeof(reader[ridx].init_history)-reader[ridx].init_history_pos-1;
33 if (val>0)
34 snprintf((char *) reader[ridx].init_history+reader[ridx].init_history_pos, val, "%s", txt);
35 reader[ridx].init_history_pos+=strlen(txt)+1;
36#endif
37}
38
39static void casc_check_dcw(int idx, int rc, uchar *cw)
40{
41 int i;
42 for (i=1; i<CS_MAXPENDING; i++)
43 {
44 if ((ecmtask[i].rc>=10) &&
45 (!memcmp(ecmtask[i].ecmd5, ecmtask[idx].ecmd5, CS_ECMSTORESIZE)))
46 {
47 if (rc)
48 {
49 ecmtask[i].rc=(i==idx) ? 1 : 2;
50 if(ecmtask[i].gbxRidx)ecmtask[i].rc=0;
51 memcpy(ecmtask[i].cw, cw, 16);
52 }
53 else
54 ecmtask[i].rc=0;
55 write_ecm_answer(fd_c2m, &ecmtask[i]);
56 ecmtask[i].idx=0;
57 }
58 }
59}
60
61static int casc_recv_timer(uchar *buf, int l, int msec)
62{
63 struct timeval tv;
64 fd_set fds;
65 int rc;
66
67 if (!pfd) return(-1);
68 tv.tv_sec = msec/1000;
69 tv.tv_usec = (msec%1000)*1000;
70 FD_ZERO(&fds);
71 FD_SET(pfd, &fds);
72 select(pfd+1, &fds, 0, 0, &tv);
73 rc=0;
74 if (FD_ISSET(pfd, &fds))
75 if (!(rc=reader[ridx].ph.recv(buf, l)))
76 rc=-1;
77
78 return(rc);
79}
80
81void network_tcp_connection_close(int fd)
82{
83 cs_debug("tcp_conn_close(): fd=%d, is_server=%d", fd, is_server);
84 close(fd);
85 client[cs_idx].udp_fd = 0;
86
87 if (!is_server)
88 {
89 int i;
90 pfd=0;
91 reader[ridx].tcp_connected = 0;
92
93 for (i=0; i<CS_MAXPENDING; i++)
94 {
95 ecmtask[i].idx=0;
96 ecmtask[i].rc=0;
97 }
98
99 if (reader[ridx].ph.c_init())
100 {
101 cs_debug("network_tcp_connection_close() exit(1);");
102 cs_exit(1);
103 }
104
105 cs_resolve();
106 reader[ridx].ncd_msgid=0;
107 reader[ridx].last_s=reader[ridx].last_g=0;
108// cs_log("last_s=%d, last_g=%d", reader[ridx].last_s, reader[ridx].last_g);
109 }
110}
111
112static void casc_do_sock_log()
113{
114 int i, idx;
115 ushort caid, srvid;
116 ulong provid;
117
118 idx=reader[ridx].ph.c_recv_log(&caid, &provid, &srvid);
119 client[cs_idx].last=time((time_t)0);
120 if (idx<0) return; // no dcw-msg received
121
122 for (i=1; i<CS_MAXPENDING; i++)
123 {
124 if ( (ecmtask[i].rc>=10)
125 && (ecmtask[i].idx==idx)
126 && (ecmtask[i].caid==caid)
127 && (ecmtask[i].prid==provid)
128 && (ecmtask[i].srvid==srvid))
129 {
130 casc_check_dcw(i, 0, ecmtask[i].cw); // send "not found"
131 break;
132 }
133 }
134}
135
136static void casc_do_sock(int w)
137{
138 int i, n, idx, rc, j;
139 uchar buf[1024];
140 uchar dcw[16];
141
142 if ((n=casc_recv_timer(buf, sizeof(buf), w))<=0)
143 {
144 if (reader[ridx].ph.type==MOD_CONN_TCP)
145 {
146 cs_debug("casc_do_sock: close connection");
147 network_tcp_connection_close(client[cs_idx].udp_fd);
148 }
149 return;
150 }
151 client[cs_idx].last=time((time_t)0);
152 idx=reader[ridx].ph.c_recv_chk(dcw, &rc, buf, n);
153 if (idx<0) return; // no dcw received
154 reader[ridx].last_g=time((time_t*)0); // for reconnect timeout
155//cs_log("casc_do_sock: last_s=%d, last_g=%d", reader[ridx].last_s, reader[ridx].last_g);
156 if (!idx) idx=last_idx;
157 j=0;
158 for (i=1; i<CS_MAXPENDING; i++)
159 {
160
161 if (ecmtask[i].idx==idx)
162 {
163 casc_check_dcw(i, rc, dcw);
164 j=1;
165 break;
166 }
167 }
168}
169
170static void casc_get_dcw(int n)
171{
172 int w;
173 struct timeb tps, tpe;
174 tpe=ecmtask[n].tps;
175 //tpe.millitm+=1500; // TODO: timeout of 1500 should be config
176 tpe.millitm+=cfg->srtimeout;
177 tpe.time+=(tpe.millitm/1000);
178 tpe.millitm%=1000;
179
180 cs_ftime(&tps);
181 while (((w=1000*(tpe.time-tps.time)+tpe.millitm-tps.millitm)>0)
182 && (ecmtask[n].rc>=10))
183 {
184 casc_do_sock(w);
185 cs_ftime(&tps);
186 }
187 if (ecmtask[n].rc>=10)
188 casc_check_dcw(n, 0, ecmtask[n].cw); // simulate "not found"
189}
190
191
192
193int casc_process_ecm(ECM_REQUEST *er)
194{
195 int rc, n, i, sflag;
196 time_t t;//, tls;
197
198 uchar buf[512];
199
200 t=time((time_t *)0);
201 for (n=0, i=sflag=1; i<CS_MAXPENDING; i++)
202 {
203 if ((t-ecmtask[i].tps.time > ((cfg->ctimeout + 500) / 1000) + 1) &&
204 (ecmtask[i].rc>=10)) // drop timeouts
205 {
206 ecmtask[i].rc=0;
207 }
208 if ((!n) && (ecmtask[i].rc<10)) // free slot found
209 n=i;
210 if ((ecmtask[i].rc>=10) && // ecm already pending
211 (!memcmp(er->ecmd5, ecmtask[i].ecmd5, CS_ECMSTORESIZE)) &&
212 (er->level<=ecmtask[i].level)) // ... this level at least
213 sflag=0;
214 }
215 if (!n)
216 {
217 cs_log("WARNING: ecm pending table overflow !!");
218 return(-2);
219 }
220 memcpy(&ecmtask[n], er, sizeof(ECM_REQUEST));
221 if( reader[ridx].typ == R_NEWCAMD )
222 ecmtask[n].idx=(reader[ridx].ncd_msgid==0)?2:reader[ridx].ncd_msgid+1;
223 else
224 ecmtask[n].idx=idx++;
225 ecmtask[n].rc=10;
226 cs_debug("---- ecm_task %d, idx %d, sflag=%d, level=%d",
227 n, ecmtask[n].idx, sflag, er->level);
228
229 if( reader[ridx].ph.type==MOD_CONN_TCP && reader[ridx].tcp_rto )
230 {
231 int rto = abs(reader[ridx].last_s - reader[ridx].last_g);
232 if (rto >= reader[ridx].tcp_rto)
233 {
234 cs_debug("rto=%d", rto);
235 network_tcp_connection_close(client[cs_idx].udp_fd);
236 }
237 }
238
239 if (cfg->show_ecm_dw && !client[cs_idx].dbglvl)
240 cs_dump(er->ecm, er->l, 0);
241 rc=0;
242 if (sflag)
243 {
244 if (!client[cs_idx].udp_sa.sin_addr.s_addr) // once resolved at least
245 cs_resolve();
246
247 if ((rc=reader[ridx].ph.c_send_ecm(&ecmtask[n], buf)))
248 casc_check_dcw(n, 0, ecmtask[n].cw); // simulate "not found"
249 else
250 last_idx = ecmtask[n].idx;
251 reader[ridx].last_s = t; // used for inactive_timeout and reconnect_timeout in TCP reader
252
253 if (!reader[ridx].ph.c_multi)
254 casc_get_dcw(n);
255 }
256
257//cs_log("casc_process_ecm 1: last_s=%d, last_g=%d", reader[ridx].last_s, reader[ridx].last_g);
258
259 if (idx>0x1ffe) idx=1;
260 return(rc);
261}
262
263static int reader_store_emm(uchar *emm, uchar type)
264{
265 static int rotate=0;
266 int rc;
267 memcpy(emmcache[rotate].emm, emm, emm[2]);
268 emmcache[rotate].type=type;
269 emmcache[rotate].count=1;
270// cs_debug("EMM stored (index %d)", rotate);
271 rc=rotate;
272 rotate=(rotate+1) % CS_EMMCACHESIZE;
273 return(rc);
274}
275
276static void reader_get_ecm(ECM_REQUEST *er)
277{
278 //cs_log("hallo idx:%d rc:%d caid:%04X",er->idx,er->rc,er->caid);
279 if ((er->rc<10) )
280 {
281 send_dcw(er);
282 return;
283 }
284 er->ocaid=er->caid;
285 if (!chk_bcaid(er, &reader[ridx].ctab))
286 {
287 cs_debug("caid %04X filtered", er->caid);
288 er->rcEx=E2_CAID;
289 er->rc=0;
290 write_ecm_answer(fd_c2m, er);
291 return;
292 }
293 if (check_ecmcache(er, client[er->cidx].grp))
294 {
295 er->rc=2;
296 write_ecm_answer(fd_c2m, er);
297 return;
298 }
299 if (proxy)
300 {
301 client[cs_idx].last_srvid=er->srvid;
302 client[cs_idx].last_caid=er->caid;
303 casc_process_ecm(er);
304 return;
305 }
306 er->rc=reader_ecm(er);
307 write_ecm_answer(fd_c2m, er);
308 //if(reader[ridx].typ=='r') reader[ridx].qlen--;
309}
310
311static void reader_send_DCW(ECM_REQUEST *er)
312{
313 if ((er->rc<10) )
314 {
315 send_dcw(er);
316 }
317}
318
319static int reader_do_emm(EMM_PACKET *ep)
320{
321 int i, no, rc, ecs;
322 char *rtxt[]={ "error", "written", "skipped" };
323 struct timeb tps, tpe;
324
325 cs_ftime(&tps);
326
327 if (memcmp(ep->hexserial, reader[ridx].hexserial, 8))
328 return(3);
329
330 no=0;
331 for (i=ecs=0; (i<CS_EMMCACHESIZE) && (!ecs); i++)
332 if (!memcmp(emmcache[i].emm, ep->emm, ep->emm[2]))
333 {
334 if (reader[ridx].cachemm)
335 ecs=(reader[ridx].rewritemm > emmcache[i].count) ? 1 : 2;
336 else
337 ecs=1;
338 no=++emmcache[i].count;
339 i--;
340 }
341
342 if ((rc=ecs)<2)
343 {
344 rc=(proxy) ? 0 : reader_emm(ep);
345 if (!ecs)
346 {
347 i=reader_store_emm(ep->emm, ep->type);
348 no=1;
349 }
350 }
351 if (rc) client[cs_idx].lastemm=time((time_t)0);
352
353 if (reader[ridx].logemm>=rc)
354 {
355 cs_ftime(&tpe);
356// cs_log("%s type=%02x, len=%d, idx=%d, cnt=%d: %s (%d ms)",
357// cs_inet_ntoa(client[ep->cidx].ip), emmcache[i].type, ep->emm[2],
358// i, no, rtxt[rc], 1000*(tpe.time-tps.time)+tpe.millitm-tps.millitm);
359 cs_log("%s type=%02x, len=%d, idx=%d, cnt=%d: %s (%d ms)",
360 username(ep->cidx), emmcache[i].type, ep->emm[2],
361 i, no, rtxt[rc], 1000*(tpe.time-tps.time)+tpe.millitm-tps.millitm);
362 }
363 return(rc);
364}
365
366static int reader_listen(int fd1, int fd2)
367{
368 int fdmax, tcp_toflag, use_tv=(!proxy);
369 int is_tcp=(reader[ridx].ph.type==MOD_CONN_TCP);
370 fd_set fds;
371 struct timeval tv;
372
373 if(reader[ridx].typ==R_GBOX){
374 struct timeb tpe;
375 int ms,x;
376 cs_ftime(&tpe);
377 for(x=0;x<CS_MAXPENDING;x++){
378 ms=1000*(tpe.time-ecmtask[x].tps.time)+tpe.millitm-ecmtask[x].tps.millitm;
379 if(ecmtask[x].rc == 10 && ms > cfg->ctimeout && ridx == ecmtask[x].gbxRidx){
380 //cs_log("hello rc=%d idx:%d x:%d ridx%d ridx:%d",ecmtask[x].rc,ecmtask[x].idx,x,ridx,ecmtask[x].gbxRidx);
381 ecmtask[x].rc=5;
382 send_dcw(&ecmtask[x]);
383
384 }
385 }
386 }
387
388 if (master_pid!=getppid()) cs_exit(0);
389 tcp_toflag=(fd2 && is_tcp && reader[ridx].tcp_ito && reader[ridx].tcp_connected);
390 tv.tv_sec = 0;
391 tv.tv_usec = 100000L;
392 if (tcp_toflag)
393 {
394 tv.tv_sec = reader[ridx].tcp_ito*60;
395 tv.tv_usec = 0;
396 use_tv = 1;
397 }
398 FD_ZERO(&fds);
399 FD_SET(fd1, &fds);
400 if (fd2) FD_SET(fd2, &fds);
401 if (logfd) FD_SET(logfd, &fds);
402 fdmax=(fd1>fd2) ? fd1 : fd2;
403 fdmax=(fdmax>logfd) ? fdmax : logfd;
404 if (select(fdmax+1, &fds, 0, 0, (use_tv) ? &tv : 0)<0) return(0);
405 if (master_pid!=getppid()) cs_exit(0);
406
407 if ((logfd) && (FD_ISSET(logfd, &fds)))
408 {
409 cs_debug("select: log-socket ist set");
410 return(3);
411 }
412
413 if ((fd2) && (FD_ISSET(fd2, &fds)))
414 {
415 cs_debug("select: socket is set");
416 return(2);
417 }
418
419 if (FD_ISSET(fd1, &fds))
420 {
421 if (tcp_toflag)
422 {
423 time_t now;
424 int time_diff;
425 time(&now);
426 time_diff = abs(now-reader[ridx].last_s);
427 if (time_diff>(reader[ridx].tcp_ito*60))
428 {
429 cs_debug("%s inactive_timeout (%d), close connection (fd=%d)",
430 reader[ridx].ph.desc, time_diff, fd2);
431 network_tcp_connection_close(fd2);
432 }
433 }
434 cs_debug("select: pipe is set");
435 return(1);
436 }
437
438 if (tcp_toflag)
439 {
440 cs_debug("%s inactive_timeout (%d), close connection (fd=%d)",
441 reader[ridx].ph.desc, tv.tv_sec, fd2);
442 network_tcp_connection_close(fd2);
443 return(0);
444 }
445
446 if (!proxy) reader_checkhealth();
447 return(0);
448}
449
450static void reader_do_pipe()
451{
452 uchar *ptr;
453 switch(read_from_pipe(fd_m2c, &ptr, 0))
454 {
455 case PIP_ID_ECM:
456 reader_get_ecm((ECM_REQUEST *)ptr);
457 break;
458 case PIP_ID_DCW:
459 reader_send_DCW((ECM_REQUEST *)ptr);
460 break;
461 case PIP_ID_EMM:
462 reader_do_emm((EMM_PACKET *)ptr);
463 break;
464 case PIP_ID_CIN:
465 reader_card_info();
466 break;
467 }
468}
469
470static void reader_main()
471{
472 while (1)
473 {
474 switch(reader_listen(fd_m2c, pfd))
475 {
476 case 1: reader_do_pipe() ; break;
477 case 2: casc_do_sock(0) ; break;
478 case 3: casc_do_sock_log(); break;
479 }
480 }
481}
482
483void start_cardreader()
484{
485 cs_ptyp=D_READER;
486
487 if ((proxy=reader[ridx].typ & R_IS_CASCADING))
488 {
489 client[cs_idx].typ='p';
490 client[cs_idx].port=reader[ridx].r_port;
491 strcpy(client[cs_idx].usr, reader[ridx].r_usr);
492 switch(reader[ridx].typ)
493 {
494 case R_CAMD33 : module_camd33(&reader[ridx].ph); break;
495 case R_CAMD35 : module_camd35(&reader[ridx].ph); break;
496 case R_NEWCAMD : module_newcamd(&reader[ridx].ph); break;
497 case R_RADEGAST: module_radegast(&reader[ridx].ph); break;
498 case R_SERIAL : module_oscam_ser(&reader[ridx].ph); break;
499 case R_CS378X : module_camd35_tcp(&reader[ridx].ph); break;
500#ifdef CS_WITH_GBOX
501 case R_GBOX : module_gbox(&reader[ridx].ph);strcpy(client[cs_idx].usr, reader[ridx].label); break;
502#endif
503 }
504 if (!(reader[ridx].ph.c_init))
505 {
506 cs_log("FATAL: %s-protocol not supporting cascading", reader[ridx].ph.desc);
507 sleep(1);
508 cs_exit(1);
509 }
510 if (reader[ridx].ph.c_init())
511 cs_exit(1);
512 if ((reader[ridx].log_port) && (reader[ridx].ph.c_init_log))
513 reader[ridx].ph.c_init_log();
514 }
515 else
516 {
517 client[cs_idx].ip=cs_inet_addr("127.0.0.1");
518 if (reader_device_init(reader[ridx].device, reader[ridx].typ))
519 cs_exit(1);
520 }
521
522 emmcache=(struct s_emm *)malloc(CS_EMMCACHESIZE*(sizeof(struct s_emm)));
523 if (!emmcache)
524 {
525 cs_log("Cannot allocate memory (errno=%d)", errno);
526 cs_exit(1);
527 }
528 memset(emmcache, 0, CS_EMMCACHESIZE*(sizeof(struct s_emm)));
529
530 ecmtask=(ECM_REQUEST *)malloc(CS_MAXPENDING*(sizeof(ECM_REQUEST)));
531 if (!ecmtask)
532 {
533 cs_log("Cannot allocate memory (errno=%d)", errno);
534 cs_exit(1);
535 }
536 memset(ecmtask, 0, CS_MAXPENDING*(sizeof(ECM_REQUEST)));
537
538 reader_main();
539 cs_exit(0);
540}
Note: See TracBrowser for help on using the repository browser.