tsdecrypt reads and decrypts CSA encrypted incoming mpeg transport stream over UDP/RTP using code words obtained from OSCAM or similar CAM server. tsdecrypt communicates with CAM server using cs378x (camd35 over tcp) protocol or newcamd protocol. https://georgi.unixsol.org/programs/tsdecrypt/
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

tables.c 4.4KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151
  1. #include "data.h"
  2. #include "tables.h"
  3. #include "camd.h"
  4. #include "libts/tsfuncs.h"
  5. #include "libfuncs/libfuncs.h"
  6. extern void show_ts_pack(struct ts *ts, uint16_t pid, char *wtf, char *extra, uint8_t *ts_packet);
  7. #define handle_table_changes(TABLE) \
  8. do { \
  9. show_ts_pack(ts, pid, #TABLE, NULL, ts_packet); \
  10. ts->cur##TABLE = ts_##TABLE##_push_packet(ts->cur##TABLE, ts_packet); \
  11. if (!ts->cur##TABLE->initialized) \
  12. return; \
  13. if (ts_##TABLE##_is_same(ts->TABLE, ts->cur##TABLE)) { \
  14. ts_##TABLE##_clear(ts->cur##TABLE); \
  15. return; \
  16. } \
  17. ts_##TABLE##_free(&ts->TABLE); \
  18. ts->TABLE = ts_##TABLE##_copy(ts->cur##TABLE); \
  19. ts_##TABLE##_clear(ts->cur##TABLE); \
  20. if (ts->debug_level >= 1) \
  21. ts_##TABLE##_dump(ts->TABLE); \
  22. } while(0)
  23. void process_pat(struct ts *ts, uint16_t pid, uint8_t *ts_packet) {
  24. int i;
  25. if (pid != 0x00)
  26. return;
  27. handle_table_changes(pat);
  28. for (i=0;i<ts->pat->programs_num;i++) {
  29. struct ts_pat_program *prg = ts->pat->programs[i];
  30. if (prg->pid) {
  31. if (prg->program != 0) {
  32. ts->pmt_pid = prg->pid;
  33. ts->service_id = prg->program;
  34. }
  35. }
  36. }
  37. }
  38. void process_cat(struct ts *ts, uint16_t pid, uint8_t *ts_packet) {
  39. if (pid != 0x01)
  40. return;
  41. handle_table_changes(cat);
  42. ts_get_emm_info(ts->cat, ts->req_CA_sys, &ts->emm_caid, &ts->emm_pid);
  43. }
  44. void process_pmt(struct ts *ts, uint16_t pid, uint8_t *ts_packet) {
  45. int i;
  46. if (!pid || pid != ts->pmt_pid)
  47. return;
  48. handle_table_changes(pmt);
  49. pidmap_clear(&ts->pidmap);
  50. pidmap_set(&ts->pidmap, 0x0000); // PAT
  51. pidmap_set(&ts->pidmap, 0x0011); // SDT
  52. pidmap_set(&ts->pidmap, ts->pmt->ts_header.pid); // PMT PID
  53. pidmap_set(&ts->pidmap, ts->pmt->PCR_pid); // PCR
  54. for (i=0;i<ts->pmt->streams_num;i++) {
  55. struct ts_pmt_stream *stream = ts->pmt->streams[i];
  56. pidmap_set(&ts->pidmap, stream->pid); // Data
  57. }
  58. if (!ts->ecm_caid) {
  59. ts_get_ecm_info(ts->pmt, ts->req_CA_sys, &ts->ecm_caid, &ts->ecm_pid);
  60. char *CA_sys = ts_get_CA_sys_txt(ts_get_CA_sys(ts->ecm_caid));
  61. ts_LOGf("%s Service : 0x%04x\n", CA_sys, ts->service_id);
  62. ts_LOGf("%s CA_id : 0x%04x\n", CA_sys, ts->emm_caid);
  63. ts_LOGf("%s EMM pid : 0x%04x\n", CA_sys, ts->emm_pid);
  64. ts_LOGf("%s ECM pid : 0x%04x\n", CA_sys, ts->ecm_pid);
  65. }
  66. }
  67. #define dump_sz (16)
  68. #define dump_buf_sz (dump_sz * 6)
  69. void process_emm(struct ts *ts, uint16_t pid, uint8_t *ts_packet) {
  70. char dump[dump_buf_sz];
  71. if (!ts->emm_pid || ts->emm_pid != pid)
  72. return;
  73. show_ts_pack(ts, pid, "emm", NULL, ts_packet);
  74. if (!ts->emm_send)
  75. return;
  76. ts->emm = ts_privsec_push_packet(ts->emm, ts_packet);
  77. if (!ts->emm->initialized)
  78. return;
  79. struct ts_header *th = &ts->emm->ts_header;
  80. struct ts_section_header *sec = ts->emm->section_header;
  81. if (ts->debug_level >= 2) {
  82. ts_hex_dump_buf(dump, dump_buf_sz, sec->section_data, min(dump_sz, sec->section_data_len), 0);
  83. ts_LOGf("EMM | CAID: 0x%04x PID 0x%04x Table: 0x%02x Length: %3d ----------- Data: %s..\n",
  84. ts->emm_caid,
  85. th->pid,
  86. sec->table_id,
  87. sec->section_data_len,
  88. dump);
  89. }
  90. camd_msg_process(ts, camd_msg_alloc_emm(ts->emm_caid, sec->section_data, sec->section_data_len));
  91. ts_privsec_copy(ts->emm, ts->last_emm);
  92. ts_privsec_clear(ts->emm);
  93. }
  94. void process_ecm(struct ts *ts, uint16_t pid, uint8_t *ts_packet) {
  95. char dump[dump_buf_sz];
  96. if (!ts->ecm_pid || ts->ecm_pid != pid)
  97. return;
  98. ts->ecm = ts_privsec_push_packet(ts->ecm, ts_packet);
  99. if (!ts->ecm->initialized)
  100. return;
  101. struct ts_header *th = &ts->ecm->ts_header;
  102. struct ts_section_header *sec = ts->ecm->section_header;
  103. int duplicate = ts_privsec_is_same(ts->ecm, ts->last_ecm);
  104. if (!duplicate || ts->is_cw_error) {
  105. ts_hex_dump_buf(dump, dump_buf_sz, sec->section_data, min(dump_sz, sec->section_data_len), 0);
  106. ts_LOGf("ECM | CAID: 0x%04x PID 0x%04x Table: 0x%02x Length: %3d IDX: 0x%04x Data: %s..\n",
  107. ts->ecm_caid,
  108. th->pid,
  109. sec->table_id,
  110. sec->section_data_len,
  111. ts->ecm_counter,
  112. dump);
  113. if (ts->is_cw_error)
  114. ts->ecm_counter--;
  115. ts->is_cw_error = 0;
  116. camd_msg_process(ts, camd_msg_alloc_ecm(ts->ecm_caid, ts->service_id, ts->ecm_counter++, sec->section_data, sec->section_data_len));
  117. } else if (ts->debug_level >= 3) {
  118. ts_LOGf("ECM | CAID: 0x%04x PID 0x%04x Table: 0x%02x Length: %3d IDX: 0x%04x Data: -dup-\n",
  119. ts->ecm_caid,
  120. th->pid,
  121. sec->table_id,
  122. sec->section_data_len,
  123. ts->ecm_counter - 1);
  124. }
  125. ts_privsec_copy(ts->ecm, ts->last_ecm);
  126. ts_privsec_clear(ts->ecm);
  127. show_ts_pack(ts, pid, !duplicate ? "ecm" : "ec+", NULL, ts_packet);
  128. }