Skip to content
Permalink

Comparing changes

Choose two branches to see what’s changed or to start a new pull request. If you need to, you can also or learn more about diff comparisons.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also . Learn more about diff comparisons here.
base repository: catalinii/minisatip
Failed to load repositories. Confirm that selected base ref is valid, then try again.
Loading
base: v1.3.28
Choose a base ref
...
head repository: catalinii/minisatip
Failed to load repositories. Confirm that selected head ref is valid, then try again.
Loading
compare: master
Choose a head ref
  • 13 commits
  • 7 files changed
  • 4 contributors

Commits on Sep 5, 2024

  1. Update links in README.md

    Link to the local copy of the PDF document specification.
    lars18th authored and Jalle19 committed Sep 5, 2024
    Copy the full SHA
    d1a668b View commit details
  2. LOG the running mode

    Print in the log the running mode: background/foreground
    lars18th authored and Jalle19 committed Sep 5, 2024
    Copy the full SHA
    67cab8b View commit details

Commits on Sep 9, 2024

  1. Fix incorrect device_id initialization

    lars18th authored and Jalle19 committed Sep 9, 2024
    Copy the full SHA
    209f02c View commit details
  2. Improve logging of satipc

    Improve a bit the LOG of the RTSP messages send/received of the satipc module. More easy to see without enlarging the log.
    lars18th authored and Jalle19 committed Sep 9, 2024
    Copy the full SHA
    e64ffa6 View commit details

Commits on Sep 10, 2024

  1. Fix target device_id when other device is detected

    When the enforced/stored device_id is already used, use another one free.
    lars18th authored and Jalle19 committed Sep 10, 2024
    Copy the full SHA
    226b311 View commit details

Commits on Sep 11, 2024

  1. Fix satipc module when TEARDOWN is not correctly handled (#1187)

    This fixes the edge case when a new tuning call is received in the tuner when the TEARDOWN message is sended to the remote SAT>IP server but the confirmation (OK 200) is not already received. Futhermore improves a bit the logging.
    lars18th authored Sep 11, 2024
    Copy the full SHA
    3906d95 View commit details

Commits on Sep 13, 2024

  1. Remove unrecognized option --disable-dvbaes (#1189)

    Fixes "configure: WARNING: unrecognized options: --disable-dvbaes"
    
    Addition as already fixed in b6d0e50
    heitbaum authored Sep 13, 2024
    Copy the full SHA
    6d32c4c View commit details

Commits on Nov 2, 2024

  1. Copy the full SHA
    3d73db0 View commit details

Commits on Dec 10, 2024

  1. tables_destroy: call ca_close_ca without argument

    This matches function call and fixes build with gcc-15
    
        tables.c: In function 'tables_destroy':
        tables.c:390:13: error: too many arguments to function 'ca[i].op->ca_close_ca'
          390 |             ca[i].op->ca_close_ca(&ca[i]);
              |             ^~
    heitbaum authored and Jalle19 committed Dec 10, 2024
    Copy the full SHA
    69d85b8 View commit details

Commits on Feb 2, 2025

  1. Set custom thread name (#1204)

    Forward the internally used thread name to OS for easier debugging.
    basicmaster authored Feb 2, 2025
    Copy the full SHA
    4ad9a8d View commit details

Commits on Feb 9, 2025

  1. readBootID: log initial values

    Improve the debug of the readBootID() function including the initial values and the file where data is stored.
    lars18th authored and Jalle19 committed Feb 9, 2025
    Copy the full SHA
    4df14b7 View commit details
  2. aesthetic changes

    lars18th authored and Jalle19 committed Feb 9, 2025
    Copy the full SHA
    d455669 View commit details

Commits on Mar 5, 2025

  1. Keep original thread name for main thread (#1208) (#1209)

    Fixes e.g. `killall` not matching the general process by (binary) name.
    basicmaster authored Mar 5, 2025
    Copy the full SHA
    2334430 View commit details
Showing with 56 additions and 33 deletions.
  1. +1 −1 .github/workflows/build.yml
  2. +7 −6 README.md
  3. +25 −9 src/minisatip.c
  4. +1 −1 src/pmt.c
  5. +19 −14 src/satipc.c
  6. +2 −1 src/socketworks.c
  7. +1 −1 src/tables.c
2 changes: 1 addition & 1 deletion .github/workflows/build.yml
Original file line number Diff line number Diff line change
@@ -50,5 +50,5 @@ jobs:
run: |
apt-get -y remove --purge libssl-dev
make clean
./configure --enable-axe --enable-dvbapi --enable-dvbcsa --disable-dvbca --disable-dvbaes --disable-netcv
./configure --enable-axe --enable-dvbapi --enable-dvbcsa --disable-dvbca --disable-netcv
make
13 changes: 7 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
@@ -5,22 +5,23 @@

# Welcome to Minisatip

Minisatip is a multi-threaded satip server version 1.2 that runs under Linux and it was tested with DVB-S, DVB-S2, DVB-T, DVB-T2, DVB-C, DVB-C2, ATSC and ISDB-T cards. More details about supported hardware: https://github.com/catalinii/minisatip/blob/master/Supported_Hardware.md
Minisatip is a multi-threaded satip server version 1.2 that runs under Linux and it was tested with DVB-S, DVB-S2, DVB-T, DVB-T2, DVB-C, DVB-C2, ATSC and ISDB-T cards. More details about supported hardware: [Supported_Hardware.md](https://github.com/catalinii/minisatip/blob/master/Supported_Hardware.md)

The protocol specification can be found at: [docs/satip_specification_version_1_2_2.pdf](https://github.com/catalinii/minisatip/blob/master/docs/satip_specification_version_1_2_2.pdf)\
(original file downloaded from http://satip.info/sites/satip/files/resource/satip_specification_version_1_2_2.pdf and now offline).

The protocol specification can be found at:
http://satip.info/sites/satip/files/resource/satip_specification_version_1_2_2.pdf
It is very lightweight (designed for embedded systems with memory and processing constrains), does not need any additional libraries for basic functionality and can be used by existing satip clients like: Tvheadend, DVBViewer, vdr, VideoLAN or Android/iOS applications. Minisatip can act as a satip client as well in order to connect to satip servers from different networks.

The application is designed to stream the requested data to multiple clients (even with one dvb card) in the same time while opening different pids.

It is tested on x86_64, x86, ARM and MIPS platforms and it requires DVBAPI 5. Supported protocols are RTSP (both tcp and udp), HTTP (port 8080) and SSDP (as specified in the SAT>IP documentation). On top of that, it supports dvbapi protocol implemented by oscam (requires dvbcsa library) to decrypt channels using an official subscription and support dvbca protocol (requires libssl-dev library) for dvb cards with CA hardware. In order to enable/disable features, please edit the Makefile.

The application shows also a status page by default at the address: http://IP:8080
The latest binaries for embedded platforms: https://minisatip.org/forum/viewtopic.php?f=5&t=371
The application shows also a status page by default at the address: http://IP:8080 \
The latest binaries for embedded platforms: [https://minisatip.org/forum/binaries](https://minisatip.org/forum/viewtopic.php?f=5&t=371)

## Contact

Please use https://minisatip.org/forum/ for any question or join slack: https://join.slack.com/t/minisatip/shared_invite/zt-rms717g0-SQR25SFs8RH9JlVZV4II7A
Please use https://minisatip.org/forum/ for any question or join [Slack](https://join.slack.com/t/minisatip/shared_invite/zt-rms717g0-SQR25SFs8RH9JlVZV4II7A)

In order to speed up the investigation of an issue, please provide the full log and a link to the application that is not working.

34 changes: 25 additions & 9 deletions src/minisatip.c
Original file line number Diff line number Diff line change
@@ -134,6 +134,7 @@ int rtsp, http, si, si1, ssdp1;
#define CA_CHANNELS_OPT 'c'
#define CACHE_DIR_OPT 'z'
#define DISABLE_CAT_OPT '5'
#define DISABLE_PMT_SCAN '9'
// Options that don't have a short option available
#define LONG_OPT_ONLY_START 1024
#define VERSION_OPT (LONG_OPT_ONLY_START + 1)
@@ -189,6 +190,7 @@ static const struct option long_options[] = {
{"help", no_argument, NULL, HELP_OPT},
{"virtual-diseqc", required_argument, NULL, ABSOLUTE_SRC},
{"version", no_argument, NULL, VERSION_OPT},
{"disable-pmt-scan", no_argument, NULL, DISABLE_PMT_SCAN},
#ifndef DISABLE_DDCI
{"disable-cat", required_argument, NULL, DISABLE_CAT_OPT},
#endif
@@ -560,6 +562,9 @@ Help\n\
* eg: 13E,19.2E on adapter 0 and 23.5E,28.2E on adapter 2&3 (source 0,1):\n\
-A 0-1:0:0,2-3:1:0\n\
\t* Note: Option -A is not compatible with clients requesting fe= (tvheadend)\n\
\n\
* -9 --disable-pmt-scan: Disables scanning PMTs and only reads the PMTs that are requested by the client\n\
\t* Provides more reliable decrypting for channels included in multiple providers\n\
\n"
#ifdef AXE
"\
@@ -654,7 +659,7 @@ void set_options(int argc, char *argv[]) {
opts.timeout_sec = 30000;
opts.adapter_timeout = 30000;
opts.daemon = 1;
opts.device_id = 1;
opts.device_id = 0;
opts.dvr_buffer = DVR_BUFFER;
opts.adapter_buffer = ADAPTER_BUFFER;
opts.udp_threshold = 25;
@@ -1063,7 +1068,6 @@ void set_options(int argc, char *argv[]) {
}

case PRIORITY_OPT:

opts.th_priority = map_int(optarg, NULL);
break;

@@ -1104,6 +1108,11 @@ void set_options(int argc, char *argv[]) {
case ABSOLUTE_SRC:
set_absolute_src(optarg);
break;

case DISABLE_PMT_SCAN:
opts.pmt_scan = 1 - opts.pmt_scan;
break;

#ifdef AXE
case QUATTRO_OPT:
opts.quattro = 1;
@@ -1244,7 +1253,7 @@ int read_rtsp(sockets *s) {
LOG("Read RTSP (sock %d, handle %d) [%s:%d] sid %d, len: %d", s->id,
s->sock, get_sockaddr_host(s->sa, ra, sizeof(ra)),
get_sockaddr_port(s->sa), s->sid, rlen);
LOGM("MSG client >> process :\n%s", s->buf);
LOGM("MSG client >> process :\n%s", s->buf); //LOGM->LOG

if ((s->type != TYPE_HTTP) &&
(strncasecmp((const char *)s->buf, "GET", 3) == 0)) {
@@ -1889,6 +1898,7 @@ int main(int argc, char *argv[]) {
}
if (opts.daemon)
becomeDaemon();
LOG("Running mode: %s", opts.daemon ? "background" : "foreground");
if (opts.slog)
openlog(app_name,
LOG_NDELAY | LOG_NOWAIT | LOG_PID |
@@ -2009,35 +2019,41 @@ int main(int argc, char *argv[]) {

int readBootID() {
opts.bootid = 0;
opts.device_id = 0;
int local_device_id = 0;
char bootid_path[256];

// Read existing values
snprintf(bootid_path, sizeof(bootid_path) - 1, "%s/bootid", opts.cache_dir);
LOG("Initial values bootid %d, device_id %d, UUID %s (reading new from %s)",
opts.bootid, opts.device_id, opts.uuid, bootid_path);
FILE *f = fopen(bootid_path, "rt");
__attribute__((unused)) int rv;
if (f) {
rv = fscanf(f, "%d %d %s", &opts.bootid, &opts.device_id, opts.uuid);
rv = fscanf(f, "%d %d %s", &opts.bootid, &local_device_id, opts.uuid);
fclose(f);
}

// Increment bootid and set defaults if values are missing
opts.bootid++;
if (opts.device_id < 1) {
opts.device_id = 1;
if (local_device_id < 1) {
local_device_id = 1;
}
if (!strcmp(opts.uuid, "")) {
uuid4_generate(opts.uuid);
}

if (opts.device_id < local_device_id) {
opts.device_id = local_device_id;
}

// Store new values
f = fopen(bootid_path, "wt");
if (f) {
fprintf(f, "%d %d %s", opts.bootid, opts.device_id, opts.uuid);
fclose(f);
}
LOG("Running with bootid %d, device_id %d, UUID %s", opts.bootid,
opts.device_id, opts.uuid);
LOG("Running with bootid %d, device_id %d, UUID %s",
opts.bootid, opts.device_id, opts.uuid);
return opts.bootid;
}

2 changes: 1 addition & 1 deletion src/pmt.c
Original file line number Diff line number Diff line change
@@ -1637,7 +1637,7 @@ int process_pat(int filter, unsigned char *b, int len, void *opaque) {
new_mask[2] = 0xFF;
add_filter_mask(
ad->id, pid, (void *)process_pmt, pmt,
(existing_pmt == NULL) ? FILTER_ADD_REMOVE | FILTER_CRC : 0,
opts.pmt_scan && (existing_pmt == NULL) ? FILTER_ADD_REMOVE | FILTER_CRC : 0,
new_filter, new_mask);
}
if (pmt_id >= 0)
33 changes: 19 additions & 14 deletions src/satipc.c
Original file line number Diff line number Diff line change
@@ -249,11 +249,10 @@ int satipc_reply(sockets *s) {
if (sep)
rc = map_intd(sep + 9, NULL, 0);

LOGM("MSG process << server :\n%s", s->buf);
LOG("satipc_reply (adapter %d, state %d): receiving from handle %d, sock "
"%d, "
"code %d",
s->sid, sip->state, s->sock, s->id, rc);
LOGM("MSG process << server :\n%s", s->buf); //LOGM->LOG
LOG("satipc_reply (adapter %d): sock %d (receiving from handle %d, state %d): "
"[[ code %d ]]",
s->sid, s->sock, s->id, sip->state, rc);

is_transport = strstr((char *)s->buf, "Transport:") != NULL;
handle_client_capabilities(sip, (char *)s->buf);
@@ -296,8 +295,8 @@ int satipc_reply(sockets *s) {
"%d",
sip->id, rc);
}
LOG("satipc %d, expect_reply %d, want_tune %d want commit %d", sip->id,
sip->expect_reply, sip->want_tune, sip->want_commit);
LOG("satipc %d, expect_reply %d, want_tune %d want commit %d, state %d", sip->id,
sip->expect_reply, sip->want_tune, sip->want_commit, sip->state);

if (rc == 200) {
if (is_transport)
@@ -647,7 +646,7 @@ int satip_standby_device(adapter *ad) {
if (!sip)
return 0;

LOG("satip device %s:%d going to standby", sip->sip, sip->sport);
LOG("satip device %s:%d going to standby (expect_reply %d)", sip->sip, sip->sport, sip->expect_reply);
if (sip->state == SATIP_STATE_PLAY) {
sip->state = SATIP_STATE_TEARDOWN;
satipc_request(ad);
@@ -1269,9 +1268,9 @@ int http_request(adapter *ad, char *url, char *method, int force) {
lb = snprintf(buf, sizeof(buf), format, method, sip->sip, sip->sport, sid,
qm, url, sip->cseq++, session);

LOG("satipc_http_request (adapter %d): sock %d: %s %s", ad->id,
LOG("satipc_http_request (adapter %d): sock %d: [[ %s %s ]]", ad->id,
remote_socket, method, url);
LOGM("MSG process >> server :\n%s", buf);
LOGM("MSG process >> server :\n%s", buf); //LOGM->LOG

if (remote_socket >= 0) {
sockets_write(remote_socket, buf, lb);
@@ -1435,15 +1434,16 @@ int satipc_request(adapter *ad) {

LOG("satipc: request for adapter %d, state %d, freq %d, pids to add %d, "
"pids to delete %d, expect_reply %d, want_tune %d, "
"last_cmd %d, "
"sent_transport %d, closed_rtsp %d",
ad->id, sip->state, ad->tp.freq, sip->lap, sip->ldp, sip->expect_reply,
sip->want_tune, sip->sent_transport, sip->rtsp_socket_closed);
sip->want_tune, sip->last_cmd, sip->sent_transport, sip->rtsp_socket_closed);

if (sip->rtsp_socket_closed)
return 0;

if ((ad->tp.freq == 0) &&
((sip->state == SATIP_STATE_OPTIONS) ||
((sip->state == SATIP_STATE_OPTIONS) || (sip->state == SATIP_STATE_INACTIVE) ||
(sip->state == SATIP_STATE_SETUP) || (sip->state == SATIP_STATE_PLAY)))
return 0;

@@ -1457,6 +1457,10 @@ int satipc_request(adapter *ad) {
return 0;
}

// if TEARDOWN has been recently received then re-start the session
if (sip->state == SATIP_STATE_INACTIVE && sip->last_cmd == RTSP_TEARDOWN)
sip->state = SATIP_STATE_SETUP;

// set the init parameters
if (sip->state == SATIP_STATE_OPTIONS) {
sip->sent_transport = 0;
@@ -1474,6 +1478,7 @@ int satipc_request(adapter *ad) {
sip->state = SATIP_STATE_PLAY;
}

LOGM("satipc: for adapter %d, executing state %d", ad->id, sip->state);
switch (sip->state) {
case SATIP_STATE_OPTIONS:
err = satipc_send_options(ad);
@@ -1521,8 +1526,8 @@ int satipc_tune(int aid, transponder *tp) {
adapter *ad;
satipc *sip;
get_ad_and_sipr(aid, 1);
LOG("satipc: tuning to freq %d, sys %d for adapter %d", ad->tp.freq / 1000,
ad->tp.sys, aid);
LOG("satipc: tuning to freq %d, sys %d for adapter %d (state %d, expect_reply %d)", ad->tp.freq / 1000,
ad->tp.sys, aid, sip->state, sip->expect_reply);
ad->err = 0;
sip->want_commit = 0;
sip->want_tune = 1;
3 changes: 2 additions & 1 deletion src/socketworks.c
Original file line number Diff line number Diff line change
@@ -702,15 +702,16 @@ void *select_and_execute(void *arg) {
return NULL;
}

tid = get_tid();
memset(thread_info[thread_index].thread_name, 0,
sizeof(thread_info[thread_index].thread_name));
if (arg) {
safe_strncpy(thread_info[thread_index].thread_name, (char *)arg);
pthread_setname_np(tid, thread_info[thread_index].thread_name);
} else
strcpy(thread_info[thread_index].thread_name, "main");

select_timeout = SELECT_TIMEOUT;
tid = get_tid();
thread_info[thread_index].tid = tid;
les = 1;
es = 0;
2 changes: 1 addition & 1 deletion src/tables.c
Original file line number Diff line number Diff line change
@@ -387,7 +387,7 @@ int tables_destroy() {
int i;
for (i = 0; i < nca; i++) {
if (ca[i].enabled && ca[i].op->ca_close_ca)
ca[i].op->ca_close_ca(&ca[i]);
ca[i].op->ca_close_ca();
}
return 0;
}