Changeset 11130 in ntrip


Ignore:
Timestamp:
Oct 28, 2026, 9:32:30 AM (17 hours ago)
Author:
stuerze
Message:

Some fixes from security point of view

Location:
trunk/BNC
Files:
20 edited

Legend:

Unmodified
Added
Removed
  • trunk/BNC/scripts/cmbPlot.pl

    r10491 r11130  
    7474# for pdf generation
    7575my ( $png, $page, $headline, $headline_text );
     76my @pngFiles;    # images to be deleted after inclusion in the PDF
    7677my $y0 = 180 / mm;
    7778my ( $x, $y, $width, $height ) = ( 40 / mm, $y0, 130 / mm, 80 / mm );
    … …  
    179180    my @datasets;    # init datasets
    180181    my $pngName = sprintf ( "%s_CLK_CORR_%s.png", $inputFilename, $key_sys );
     182    push @pngFiles, $pngName;
    181183    my $chart = Chart::Gnuplot->new(
    182184                                     output   => $pngName,
    … …  
    232234    my @datasets;    # init datasets
    233235    my $pngName = sprintf ( "%s_CLK_FULL_%s.png", $inputFilename, $key_sys );
     236    push @pngFiles, $pngName;
    234237    my $chart = Chart::Gnuplot->new(
    235238        output   => $pngName,
    … …  
    287290            my @datasets;                             # init datasets
    288291            my $pngName = sprintf ( "%s_OFFSETSAT_%s_%s.png", $inputFilename, $key_ac, $key_sys );
     292            push @pngFiles, $pngName;
    289293            my $chartOFFSETSAT = Chart::Gnuplot->new(
    290294                output   => $pngName,
    … …  
    340344    my @datasets;    # init datasets
    341345    my $pngName = sprintf ( "%s_OFFSETAC_%s.png", $inputFilename, $key_sys );
     346    push @pngFiles, $pngName;
    342347    my $chart = Chart::Gnuplot->new(
    343348        output   => $pngName,
    … …  
    393398        my @datasets;                      # init datasets
    394399        my $pngName = sprintf ( "%s_RES_%s_%s.png", $inputFilename, $key_ac, $key_sys );
     400        push @pngFiles, $pngName;
    395401        my $chart = Chart::Gnuplot->new(
    396402                                         output   => $pngName,
    … …  
    432438$pdf->save();
    433439$pdf->end();
    434 system ("rm $inputDir/*png");
    435 system("evince $inputDir/$pdf_name&");
     440unlink @pngFiles;    # only the images written here
     441if ( !fork() ) { exec( "evince", "$inputDir$pdf_name" ) or exit 1; }
    436442
    437443#foreach my $t(@array) {print"$t \n ";}
  • trunk/BNC/scripts/compareSP3Plot.pl

    r11083 r11130  
    6666# for pdf generation
    6767my ($png, $page, $headline, $headline_text);
     68my @pngFiles;    # images to be deleted after inclusion in the PDF
    6869my $y0 = 190/mm;
    6970my ($x, $y, $width, $height) = (40/mm, $y0, 130/mm, 70/mm);
    … …  
    134135            my (@datasets_r, @datasets_a, @datasets_o); # init datasets
    135136            my $pngName_r   = sprintf ("%s_RADIAL_%s.png", $inputFilename, $key_sys);
     137            push @pngFiles, $pngName_r;
    136138            my $pngName_a   = sprintf ("%s_ALONG_%s.png", $inputFilename, $key_sys);
     139            push @pngFiles, $pngName_a;
    137140            my $pngName_o   = sprintf ("%s_OUT_%s.png", $inputFilename, $key_sys);
     141            push @pngFiles, $pngName_o;
    138142            my $chart_r = Chart::Gnuplot->new(
    139143                          output => $pngName_r, terminal => 'png', title => "Radial component",
    … …  
    231235            my (@datasets_c, @datasets_r); # init datasets
    232236            my $pngName_c  = sprintf ("%s_CLK_%s.png", $inputFilename, $key_sys);
     237            push @pngFiles, $pngName_c;
    233238            my $pngName_r  = sprintf ("%s_CLKRED_%s.png", $inputFilename, $key_sys);
     239            push @pngFiles, $pngName_r;
    234240            my $chart_c = Chart::Gnuplot->new(
    235241                          output => $pngName_c, terminal => 'png',title => "Clock only",
    … …  
    305311            my @datasets_s; # init datasets
    306312            my $pngName_s  = sprintf ("%s_SIS_%s.png", $inputFilename, $key_sys);
     313            push @pngFiles, $pngName_s;
    307314            # SIS contains the satellite offsets: y range from the data
    308315            my $maxAbs = 0.1;
    … …  
    342349    $pdf->save();
    343350    $pdf->end();
    344     system("rm *png");
     351    unlink @pngFiles;    # only the images written here
     352    @pngFiles = ();
    345353    #system("evince $inputDir/$pdf_name&");
    346354}
  • trunk/BNC/scripts/pppPlot.pl

    r10879 r11130  
    8787# for pdf gerneration
    8888my ( $png, $page, $headline, $headline_text );
     89my @pngFiles;    # images to be deleted after inclusion in the PDF
    8990my $y0 = 180 / mm;
    9091my ( $x, $y, $width, $height ) = ( 40 / mm, $y0, 130 / mm, 80 / mm );
    … …  
    170171                DEBUG "Plot NEU ";
    171172                my $pngNameNEU = sprintf( "%s_NEU.png", $station );
     173                push @pngFiles, $pngNameNEU;
    172174                my $chartNEU   = newChart("$station ($dateStr)");
    173175                $chartNEU->set(
    … …  
    207209                DEBUG "Plot FIX";
    208210                my $pngNameFIX = sprintf( "%s_FIX.png", $station );
     211                push @pngFiles, $pngNameFIX;
    209212                my $chartFIX   = newChart("$station ($dateStr)");
    210213                $chartFIX->set(
    … …  
    236239                DEBUG "Plot TRP";
    237240                my $pngNameTRP = sprintf( "%s_TRP.png", $station );
     241                push @pngFiles, $pngNameTRP;
    238242                my $chartTRP   = newChart("$station ($dateStr)");
    239243                $chartTRP->set( output => $pngNameTRP );
    … …  
    278282                my @datasets      = ();                                  # init datasets
    279283                my $pngNameRECCLK = sprintf( "%s_RECCLK.png", $station );
     284                push @pngFiles, $pngNameRECCLK;
    280285                $chartRECCLK->set( output => $pngNameRECCLK );
    281286                $chartRECCLK->set( ylabel => "Receiver Clocks [m]" );
    … …  
    323328                        my @datasets = ();    # init datasets
    324329                        my $pngNameELE = sprintf( "%s_ELE_%s.png", $station, $key_sys );
     330                        push @pngFiles, $pngNameELE;
    325331                        $chartELE->set( output => $pngNameELE );
    326332                        $chartELE->set(
    … …  
    370376                                my ( @datasets_amb, @datasets_epo );    # init datasets
    371377                                my $pngNameAMB = sprintf( "%s_AMB_%s_%s.png",   $station, $key_ambType, $key_sys );
     378                                push @pngFiles, $pngNameAMB;
    372379                                my $pngNameEPO = sprintf( "%s_EPO_%s_%s.png",   $station, $key_ambType, $key_sys );
     380                                push @pngFiles, $pngNameEPO;
    373381                                my $chartAMB = Chart::Gnuplot->new(
    374382                                        output   => $pngNameAMB,
    … …  
    458466                        my @datasets;    # init datasets
    459467                        my $pngNameION = sprintf( "%s_ION_%s.png", $station, $ksys );
     468                        push @pngFiles, $pngNameION;
    460469                        $chartION->set( output => $pngNameION );
    461470                        # SATELLITE
    … …  
    504513                                my $pngNameBIA = sprintf( "%s_BIAS_%s_%s.png",
    505514                                        $station, $key_biasType, $key_sys );
     515                                push @pngFiles, $pngNameBIA;
    506516                                $chartBIAS->set( output => $pngNameBIA );
    507517                                $chartBIAS->set( ylabel => "Receiver Bias $key_biasType [m]" );
    … …  
    548558                                my @datasets;
    549559                                my $pngNameRES = sprintf( "%s_RES_%s_%s.png", $station, $key_resType, $key_sys );
     560                                push @pngFiles, $pngNameRES;
    550561                                $chartRES->set( output => $pngNameRES );
    551562                                $chartRES->set(ylabel => "Residuals $key_resType [m]" );
    … …  
    603614                        my @datasets;
    604615                        my $pngNameCLKCORR = sprintf( "%s_CLKCORR_%s.png", $station, $ksys );
     616                        push @pngFiles, $pngNameCLKCORR;
    605617                        $chartCLKCORR->set( output => $pngNameCLKCORR );
    606618                        # SATELLITE
    … …  
    647659                        $chartYAW->set( legend => { position => "outside right" } );
    648660                        my $pngNameYAW = sprintf( "%s_YAW_%s.png", $station, $sat );
     661                        push @pngFiles, $pngNameYAW;
    649662                        $chartYAW->set( output => $pngNameYAW );
    650663                        # YAW from SSR data
    … …  
    696709                                my @datasets;
    697710                                my $pngNameCB =  sprintf( "%s_CB_%s_%s.png", $station, $key_type, $key_sys );
     711                                push @pngFiles, $pngNameCB;
    698712                                $chartCB->set( output => $pngNameCB );
    699713                                $chartCB->set( ylabel => "Code Biases $key_type [m]" );
    … …  
    740754                                my (@datasetsJC, $datasetJC);
    741755                                my $pngNamePB =  sprintf( "%s_PB_%s_%s.png", $station, $key_type, $key_sys );
     756                                push @pngFiles, $pngNamePB;
    742757                                my $pngNameJC =  sprintf( "%s_JC_%s_%s.png", $station, $key_type, $key_sys );
     758                                push @pngFiles, $pngNameJC;
    743759                                my $chartPB = newChart("$ssrData ($dateStr)");
    744760                        $chartPB->set( legend => { position => "outside right" } );
    … …  
    799815$pdf->end();
    800816
    801 system("rm *.png");
     817unlink @pngFiles;    # only the images written here
     818@pngFiles = ();
    802819if (Common::amInteractiv) {
    803         system("evince $inputDir/$pdf_name");
     820        system( "evince", "$inputDir$pdf_name" );
    804821}
    805822
  • trunk/BNC/src/RTCM/RTCM2.cpp

    r7629 r11130  
    667667  };
    668668
    669   if ( 24*DW.size() < start+n-1 ) {
     669  if ( 24*DW.size() < start+n ) { // last bit read: start+n-1
    670670#if (DEBUG>0)
    671671    cerr << "Debug output RTCM2packet::getUnsignedBits" << endl
    … …  
    727727  };
    728728
    729   if ( 24*DW.size() < start+n-1 ) {
     729  if ( 24*DW.size() < start+n ) { // last bit read: start+n-1
    730730#if (DEBUG>0)
    731731    cerr << "Debug output RTCM2packet::getUnsignedBits" << endl
  • trunk/BNC/src/RTCM3/RTCM3Decoder.cpp

    r11124 r11130  
    3939 * -----------------------------------------------------------------------*/
    4040
     41#include <atomic>
    4142#include <iostream>
    4243#include <iomanip>
    … …  
    241242/**
    242243 * Frequency numbers of GLONASS with an offset of 100 to detect unset values.
    243  * Gets filled by ephemeris and data blocks and shared between different streams.
     244 * Gets filled by ephemeris and data blocks and shared between different streams
     245 * (MSM4/6 streams without channel numbers use those of an ephemeris stream).
     246 * Atomic, as the streams are decoded in different threads.
    244247 */
    245 static int GLOFreq[RTCM3_MSM_NUMSAT];
     248static std::atomic<int> GLOFreq[RTCM3_MSM_NUMSAT];
    246249
    247250/*
    … …  
    19982001  GETSTRING(antnum, antenna)
    19992002  if ((antnum > -1 && antnum < 265) &&
    2000       (_antType.empty() || strncmp(_antType.back()._descriptor, antenna, recnum) != 0)) {
     2003      (_antType.empty() || int(strlen(_antType.back()._descriptor)) != antnum ||
     2004       strncmp(_antType.back()._descriptor, antenna, antnum) != 0)) {
    20012005    _antType.push_back(t_antInfo());
    20022006    memcpy(_antType.back()._descriptor, antenna, antnum);
    … …  
    20172021    GETSTRING(recsernum, recserialnum)
    20182022    if ((recnum > -1 && recnum < 265) &&
    2019         (_recType.empty() || strncmp(_recType.back()._descriptor, receiver, recnum) != 0)) {
     2023        (_recType.empty() || int(strlen(_recType.back()._descriptor)) != recnum ||
     2024         strncmp(_recType.back()._descriptor, receiver, recnum) != 0)) {
    20202025      _recType.push_back(t_recInfo());
    20212026      memcpy(_recType.back()._descriptor, receiver, recnum);
  • trunk/BNC/src/RTCM3/bits.h

    r11023 r11130  
    104104   b = variable to store size, s = variable to store string pointer */
    105105#define GETSTRING(b, s) { \
     106  if(size < 1) return false; \
    106107  b = *(data++); \
     108  --size; \
     109  if((b) > size) return false; \
    107110  s = (char *) data; \
    108111  data += b; \
    109   size -= b+1; \
     112  size -= b; \
    110113}
    111114
    … …  
    126129  }
    127130
     131/* up to 56 bits: less than 8 bits are pending in the 64-bit bitbuffer */
    128132#define ADDBITS(a, b) { \
    129     bitbuffer = (bitbuffer<<(a))|((b)&((1<<a)-1)); \
     133    bitbuffer = (bitbuffer<<(a))|((uint64_t)(b)&((1ULL<<(a))-1)); \
    130134    numbits += (a); \
    131135    STOREBITS \
  • trunk/BNC/src/RTCM3/clock_and_orbit/clock_orbit.h

    r11124 r11130  
    605605#define E_NADIR_ANGLE_DEPENDENT_CORR_RANGE_EXTENSION(a) ADDBITS(4,  a)                      /* DF+015 (new RTCM) to extend DF+021*/
    606606#define E_SATELLITE_SET_INDICATOR(a)                    ADDBITS(1,  a)                      /* DF+016 (new RTCM) */
    607 /* ADDBITS' mask "(1<<a)-1" uses a 32-bit int literal, so a plain
    608    ADDBITS(64, a) is broken the same way GETSSRBITS(a, 64) was on decode
    609    (see D_SATELLITE_MASK) - here even ADDBITS(32, ...) is unsafe, since
    610    shifting a 32-bit int by exactly its own width is undefined behavior
    611    too. Stay well clear of that edge by writing four 16-bit chunks. */
     607/* ADDBITS handles up to 56 bits, so the 64-bit mask is written as two
     608   32-bit halves (as GETSSRBITS(a, 64) does not work either, see
     609   D_SATELLITE_MASK). */
    612610#define E_SATELLITE_MASK(a)                             { \
    613611  uint64_t mask64_ = (a); \
    614   ADDBITS(16, (mask64_ >> 48) & 0xFFFFU) \
    615   ADDBITS(16, (mask64_ >> 32) & 0xFFFFU) \
    616   ADDBITS(16, (mask64_ >> 16) & 0xFFFFU) \
    617   ADDBITS(16,  mask64_        & 0xFFFFU) \
     612  ADDBITS(32, mask64_ >> 32) \
     613  ADDBITS(32, mask64_ & 0xFFFFFFFFU) \
    618614}                                                                                           /* DF394 */
    619615#define E_FREQUENCY_SET_INDICATOR(a)                    ADDBITS(1,  a)                      /* DF+017 (new RTCM) */
  • trunk/BNC/src/RTCM3/clock_and_orbit/clock_orbit_rtcm_new.cpp

    r11126 r11130  
    489489        if (md->Entries[i].nonDefaultIndicator &&
    490490            md->Entries[i].additionalParameterIndicator) {
    491           /* up to 255 bits, only 32 stored (leading bits zero); in pieces of
    492              16 bits, as ADDBITS cannot handle more than 30 bits */
     491          /* up to 255 bits, only 32 stored: leading zero bits (ADDBITS
     492             handles at most 56 bits at a time), then the value */
    493493          unsigned int k = md->Entries[i].additionalParameterNumBits;
    494           while (k) {
    495             unsigned int n = (k > 16) ? 16 : k;
     494          while (k > 32) {
     495            unsigned int n = (k - 32 > 56) ? 56 : k - 32;
     496            ADDBITS(n, 0)
    496497            k -= n;
    497             E_ADDITIONAL_MODEL_PARAMETER_DATA((k < 32) ? (md->Entries[i].additionalParameterData >> k) : 0, n)
    498           }
     498          }
     499          if (k)
     500            E_ADDITIONAL_MODEL_PARAMETER_DATA(md->Entries[i].additionalParameterData, k)
    499501      }
    500502    }
  • trunk/BNC/src/bnchelp.html

    r11128 r11130  
    147147    &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 2.8.2 <a href="#corrint">Interval</a><br>
    148148    &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 2.8.3 <a href="#corrport">Port</a><br>
    149     &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 2.8.4 <a href="#ssrqc">QC Directory, QC Streams, QC Reference, QC Interval, QC Bias File</a><br>
     149    &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 2.8.4 <a href="#ssrqc">QC Directory, QC Streams, QC Reference, QC Interval, QC Bias File, QC ANTEX File</a><br>
    150150    &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 2.8.4 <a href="#corrwait">Wait for Full Corr Epoch</a><br>
    151151    &nbsp; &nbsp; &nbsp; 2.9 <a href="#syncout"><b>Feed Engine</b></a><br>
    … …  
    50975097
    50985098  <p>
    5099   <h4 id="ssrqc">2.8.4 QC Directory, QC Streams, QC Reference, QC Interval, QC Bias File - optional</h4>
     5099  <h4 id="ssrqc">2.8.4 QC Directory, QC Streams, QC Reference, QC Interval, QC Bias File, QC ANTEX File - optional</h4>
    51005100  </p>
    51015101  <p>
    … …  
    51065106    e.g. 'ALL,!SIRGAS200001' for a stream referring to another reference frame than the ITRF. 'QC Reference' selects the reference of the stream comparison (see below). Select
    51075107    the 'QC Interval' for the reports (default: 1 hour). A 'QC Bias File' (Bias SINEX, OSB or DSB, e.g. a CAS DCB or
    5108     a GFZ OSB product) is an optional reference for the code bias check (see below). One daily file
     5108    a GFZ OSB product) is an optional reference for the code bias check (see below). A 'QC ANTEX File' (e.g. the
     5109    current igs20.atx) enables the attitude check (see below). One daily file
    51095110    '&lt;stream&gt;_S_&lt;YYYYDDD&gt;0000_01D_QC.txt' is written per stream; at the end of each interval and at the
    51105111    end of the program, a report per system is appended. Broadcast ephemerides must be received as well, e.g. via
    … …  
    52415242    clock 0.689 (STD 0.008), radial 0.020, along 0.036, cross 0.022, SIS (radial - clock) 0.687 (STD 0.008)
    52425243  G satellites deviating from the reference, RMS SIS [m]: G02(0.38) G16(0.33) G20(0.91) G26(3.36)
     5244</pre>
     5245  <p>
     5246    <b>Attitude check:</b> With a 'QC ANTEX File', BNC checks for every stream sending the satellite yaw angle whether
     5247    its clocks are consistent with its yaw angles during noon and midnight turns. In every stream comparison (30
     5248    seconds), the difference of the yaw angle of BNC's attitude model ('Computed', see section 'Combination') minus the
     5249    yaw angle of the stream is followed continuously over time; the phase wind-up predicts a clock difference of the
     5250    stream to an AC following the model of lambda_IF * dpsi / 2pi (lambda_IF: ionosphere-free wavelength of the
     5251    reference signals, about 10.7 cm for GPS). A turn starts when the yaw difference changes by more than 20 degrees
     5252    against the samples 5 to 15 minutes before, and ends when it is stable again within 2 degrees for 10 minutes. For
     5253    each turn, the observed clock change of the stream relative to the consensus is compared with the predicted one:
     5254    the changes at the end of the turn, the regression slope of the observed on the predicted changes, and the clock
     5255    RMS during the turn without and with the predicted change. A slope between 0.7 and 1.3 with the RMS reduced by
     5256    at least half means that the yaw angles in the stream describe the attitude the AC used for its clocks - the
     5257    condition for selecting the attitude 'SSR' for this AC in the combination. Turns with a predicted change below 3
     5258    cm are not assessed; a clock change of at least 3 cm is then reported as not explained by the yaw difference,
     5259    which shows that the other ACs model this turn differently from BNC's model (the check assumes that the consensus
     5260    follows it), e.g.
     5261  </p>
     5262  <pre>
     5263  G attitude check G14 09:42:30-10:25:30: yaw difference to the model 362 deg, clock change vs. consensus 8.2 cm, predicted 10.7 cm (max 10.7 cm), slope 0.77, clock RMS 6.1 -> 2.0 cm: SSR yaw consistent with the clocks
     5264  G attitude check G25 07:53:00-08:51:30: yaw difference to the model 39 deg, clock change vs. consensus -9.8 cm, predicted -0.0 cm (max 1.2 cm), slope 1.84, clock RMS 5.9 -> 5.8 cm: clock change not explained by the yaw difference (the other ACs model this turn differently?)
    52435265</pre>
    52445266  <p>
  • trunk/BNC/src/bncmain.cpp

    r11087 r11130  
    215215        "   ssrQcIntr    {SSR QC report interval [character string: 5 min|15 min|30 min|1 hour|1 day]}\n"
    216216        "   ssrQcBiasFile {Bias SINEX file (OSB or DSB) as reference for the SSR QC code bias check, full path [character string]}\n"
     217        "   ssrQcAntexFile {ANTEX file for the SSR QC attitude check (SSR yaw vs. clocks during turns), full path [character string]}\n"
    217218        "\n"
    218219        "Feed Engine Panel keys:\n"
  • trunk/BNC/src/bncnetqueryrtp.cpp

    r11128 r11130  
    110110
    111111  const int timeOut = 5000;
     112  const int maxHeaderLines = 100; // of an RTSP answer
    112113
    113114  _status = running;
    … …  
    177178        QByteArray serverPort;
    178179        QString line = in.readLine();
    179         while (!line.isEmpty()) {
     180        int nLines = 0;
     181        while (!line.isEmpty() && ++nLines <= maxHeaderLines) {
    180182          if (line.indexOf("Session:") == 0) {
    181183            _session = line.mid(9).toLatin1();
    … …  
    226228              QTextStream in(_socket);
    227229              line = in.readLine();
    228               while (!line.isEmpty()) {
     230              nLines = 0;
     231              while (!line.isEmpty() && ++nLines <= maxHeaderLines) {
    229232                if (line.indexOf("200 OK") != -1) {
    230233                  emit newMessage(_url.toEncoded(QUrl::RemoveUserInfo).replace(0,1,"")
  • trunk/BNC/src/bncnetqueryv1.cpp

    r11124 r11130  
    253253    bool proxyResponse = false;
    254254    QStringList response;
     255    const int maxResponseSize = 16384;
     256    int responseSize = 0;
    255257    while (true) {
    256258      if (_socket->canReadLine()) {
    257259        QString line = _socket->readLine();
     260
     261        // a caster response header is short; do not collect an endless one
     262        responseSize += line.size();
     263        if (responseSize > maxResponseSize) {
     264          delete _socket;
     265          _socket = 0;
     266          _status = error;
     267          emit newMessage(_url.path().toLatin1().replace(0,1,"")
     268                          + ": Caster response header too long", true);
     269          return;
     270        }
    258271   
    259272        if (line.indexOf("ICY 200 OK") == -1 &&
    … …  
    289302        break;
    290303        }
     304      }
     305      else if (_socket->bytesAvailable() > maxResponseSize) { // no line end
     306        delete _socket;
     307        _socket = 0;
     308        _status = error;
     309        emit newMessage(_url.path().toLatin1().replace(0,1,"")
     310                        + ": Caster response header too long", true);
     311        return;
    291312      }
    292313      else if (!_socket->waitForReadyRead(_timeOut)) {
  • trunk/BNC/src/src.pri

    r11087 r11130  
    1919
    2020win32:QMAKE_CXXFLAGS += /std:c++17
     21
     22# Hardening, independent of the distribution's compiler defaults: stack
     23# protector, bounds checks of the std containers (abort instead of memory
     24# corruption), read-only relocations. _FORTIFY_SOURCE is not set, it requires
     25# optimization, which is switched off above.
     26linux:QMAKE_CXXFLAGS += -fstack-protector-strong -D_GLIBCXX_ASSERTIONS
     27linux:QMAKE_LFLAGS   += -Wl,-z,relro,-z,now
    2128
    2229debug:OBJECTS_DIR=.obj/debug
  • trunk/BNC/tests/README.md

    r11127 r11130  
    3131| `tools/ssr_harness.sh` | builds `tools/ssr_harness.cpp` with the SSR decoders under ASan/UBSan and runs it |
    3232| `tools/ssl_check.py` | TLS checks of the Ntrip 2s client and upload (not part of `run_tests.py`) |
     33| `tools/net_check.py` | UDP/RTP sender filter and upload status checks on loopback (not part of `run_tests.py`) |
    3334| `work/` | scratch output, not versioned |
    3435
    … …  
    100101  coefficients are C(d,o) = (100*d+o)/200 TECU and S = -C, both `.ssr` files
    101102  are identical apart from the station ID. These frames overflowed the
    102   coefficient and name arrays; the 4-layer VTEC crashed BNC.
     103  coefficient and name arrays; the 4-layer VTEC crashed BNC. Also two RTCM
     104  1033: a complete one and one whose receiver descriptor length runs beyond
     105  the message (rejected; before, stale buffer content was logged).
     106
     107* `rawfile_hostile`: raw file with hostile chunk headers from
     108  `tools/mkcrafted.py --rawfile`: the station ID `../ESCAPE0` must give
     109  `Output/.._ESCAPE0_*.ssr` (no file outside the output directory), a chunk
     110  header announcing 2000000000 bytes is rejected with a log message.
    103111
    104112## Sanitizer check of the SSR decoders
    … …  
    115123also covers the new RTCM-SSR metadata (message 60 in
    116124`crafted_limits.raw`: 7 entries with additional parameters of 40 and 0 bits,
    117 and 31 entries, which must be rejected), which `RTCM3Decoder.cpp` does not
    118 dispatch at present. Every decoded VTEC and metadata message is encoded
    119 again with the `Make*` function of the same class and decoded once more; the
    120 result must be identical. Exit code 0 only without sanitizer errors and
     125and 31 entries, which must be rejected) and satellite antenna messages
     126(BDS with mask bits in all four 16-bit quarters, GPS with shared blocks),
     127which `RTCM3Decoder.cpp` does not dispatch at present. Every decoded VTEC, metadata and antenna message is
     128encoded again with the `Make*` function of the same class and decoded once
     129more; the result must be identical, for the antenna messages also the bytes. Exit code 0 only without sanitizer errors and
    121130differences.
    122131
    … …  
    135144certificate for another host name (rejected) and a client certificate
    136145required by the caster, with and without `sslIgnoreErrors`. Takes about 3 min.
     146
     147## Network check
     148
     149```
     150tests/tools/net_check.py [--bnc PATH]
     151```
     152
     153Runs BNC live against fake servers on loopback addresses (no root needed).
     154A second sender on another address sends spoofed datagrams to BNC's port: in
     155the modes 'U' (Ntrip 2 UDP) and 'R' (RTSP/RTP) and in 'UN' with a sender
     156address in the URL, BNC's raw output must contain only the server's data;
     157'UN' with 127.0.0.1 accepts any sender, as before. An Ntrip 1 caster sending an endless
     158response header is cut off, a normal Ntrip 1 stream still works. An upload
     159answered with `HTTP/1.1 401` and a header containing `200` must be reported
     160as broken. Takes about 2 min.
    137161
    138162## Adding a replay case
  • trunk/BNC/tests/tools/bncraw.py

    r11127 r11130  
    197197
    198198
     199def frame(payload):
     200    """RTCM3 frame (preamble, length, payload, CRC24Q) of a payload."""
     201    head = bytes([0xD3, (len(payload) >> 8) & 0x03, len(payload) & 0xFF])
     202    return head + payload + crc24q(head + payload).to_bytes(3, "big")
     203
     204
    199205def cmd_slice(args):
    200206    stations = set(args.stations.split(",")) if args.stations else None
     207    types = args.types.split(",") if args.types else None
     208    parsers = {}
    201209
    202210    def selected():
    … …  
    208216            if args.end and t >= args.end:
    209217                continue
     218            if types:
     219                # keep only the RTCM3 messages of the given types (or type prefixes)
     220                frames = parsers.setdefault(sta, Rtcm3Framer()).feed(data)
     221                kept = b"".join(frame(pl) for pl in frames
     222                                if any(msg_type(pl).startswith(tt) for tt in types))
     223                if not kept:
     224                    continue
     225                data = kept
    210226            yield t, sta, fmt, data
    211227
    … …  
    245261    p.add_argument("--end", help="ISO time, exclusive")
    246262    p.add_argument("--stations", help="comma separated staIDs to keep")
     263    p.add_argument("--types", help="comma separated RTCM3 message types or prefixes to keep, "
     264                                   "e.g. 1019,4076_02 (GPS ephemerides and IGS-SSR GPS messages)")
    247265    p.set_defaults(func=cmd_slice)
    248266
  • trunk/BNC/tests/tools/fakecaster.py

    r11127 r11130  
    1515additionally requires a client certificate signed by that CA. With --serve
    1616a GET request (BNC as Ntrip client) is answered with the RTCM bytes of the
    17 given raw file. Failed TLS handshakes are reported on stdout.
     17given raw file. With --reply an upload is answered with this text instead
     18of the 200 status (e.g. a rejection), and the connection is closed. Failed
     19TLS handshakes are reported on stdout.
    1820"""
    1921
    … …  
    5557        self.total = 0
    5658        self.handshakes = 0
     59        self.rejected = 0
    5760        self.served = 0
    5861
    … …  
    6770
    6871
    69 def serve(conn, store, timeout, tls=None, served=None):
     72def serve(conn, store, timeout, tls=None, served=None, reply=None):
    7073    conn.settimeout(timeout)
    7174    buf = b""
    … …  
    8992                         b"Content-Type: gnss/data\r\nConnection: close\r\n\r\n" + served)
    9093            store.served += len(served)
     94            return
     95        if reply is not None:
     96            conn.sendall(reply)
     97            store.rejected += 1
    9198            return
    9299        if header.startswith(b"SOURCE"):
    … …  
    127134    ap.add_argument("--tls-client-ca", help="require a client certificate of this CA")
    128135    ap.add_argument("--serve", help="raw file whose RTCM bytes are sent on GET")
     136    ap.add_argument("--reply", help="answer to uploads instead of 200 ('\\r\\n' escapes allowed)")
    129137    args = ap.parse_args()
    130138
    … …  
    136144            tls.verify_mode = ssl.CERT_REQUIRED
    137145            tls.load_verify_locations(args.tls_client_ca)
     146    reply = None
     147    if args.reply is not None:
     148        reply = args.reply.encode("latin-1").decode("unicode_escape").encode("latin-1")
    138149    served = None
    139150    if args.serve:
    … …  
    155166        except socket.timeout:
    156167            break
    157         t = threading.Thread(target=serve, args=(conn, store, args.timeout, tls, served),
     168        t = threading.Thread(target=serve, args=(conn, store, args.timeout, tls, served, reply),
    158169                             daemon=True)
    159170        t.start()
    … …  
    166177    if served is not None:
    167178        print("served %d bytes" % store.served, flush=True)
     179    if reply is not None:
     180        print("%d upload(s) answered with --reply" % store.rejected, flush=True)
    168181    return 0
    169182
  • trunk/BNC/tests/tools/mkcrafted.py

    r11125 r11130  
    66  CRAFT0IGS0  IGS-SSR VTEC (4076/201), decoded by SsrCorrIgs, followed by
    77              RTCM 1300/1301/1302 with 31-character names (BNC's RTCM scan
    8               lists them only for streams that also decode successfully)
     8              lists them only for streams that also decode successfully);
     9              in the first epoch also two RTCM 1033 (antenna and receiver
     10              descriptors): a complete one and one whose receiver descriptor
     11              length (200) runs beyond the end of the message
    912  CRAFT0RTC0  RTCM-SSR VTEC (1264), decoded by SsrCorrRtcm
    1013  CRAFT0NEW0  new RTCM-SSR metadata (60), not dispatched by BNC at present;
    … …  
    1215                - 7 entries (maximum), additional parameter of 40 and 0 bits
    1316                - 31 entries (5-bit count, more than META_MAXNUMENTRIES=7)
     17              and satellite antenna messages (DF+010-DF+021):
     18                - BDS (83): C01, C17, C33, C49, C64 (mask bits in all four
     19                  16-bit quarters of DF394), individual blocks
     20                - GPS (80): G01, G02, G32 sharing one block and one frequency
     21                  block; nadir angle corrections incl. the invalid value
    1422
    1523VTEC epochs (every 5 s):
    … …  
    2230by eye; the heights are 100 km * layer number.
    2331
     32With --rawfile, a raw file with hostile chunk headers is written instead
     33(test of the raw file reader, data/crafted_rawfile.raw):
     34  ../ESCAPE0  station ID with a path: RTCM-SSR VTEC whose .ssr file must be
     35              written inside the output directory
     36  CRAFT0RTC0  RTCM-SSR VTEC, 5 s later
     37  then a chunk header announcing 2000000000 bytes, which must be rejected
     38
    2439Usage: mkcrafted.py <out.raw>
     40       mkcrafted.py --rawfile <out.raw>
    2541"""
    2642
    … …  
    140156
    141157
     158def descriptors(strings, truncate=False):
     159    """RTCM 1033: antenna, setup ID, serial, receiver, firmware, serial."""
     160    w = BitWriter()
     161    w.u(1033, 12)
     162    w.u(0, 12)               # reference station ID
     163    ant, antser, rec, firm, recser = strings
     164    w.text(ant, 8)
     165    w.u(0, 8)                # antenna setup ID
     166    w.text(antser, 8)
     167    if truncate:
     168        w.u(200, 8)          # receiver descriptor length beyond the message
     169        for c in rec.encode("ascii"):
     170            w.u(c, 8)
     171    else:
     172        w.text(rec, 8)
     173        w.text(firm, 8)
     174        w.text(recser, 8)
     175    return frame(w.payload())
     176
     177
    142178def metadata(entries):
    143179    """entries: list of None (default model) or number of additional bits."""
    … …  
    163199
    164200
     201def antenna(msg, sats, shared, nadir):
     202    """Satellite antenna message; sats: PRNs (1..64) of the mask."""
     203    w = BitWriter()
     204    w.u(msg, 12)
     205    w.u(4711, 16)            # provider ID
     206    w.u(5, 6)                # satellite antenna IOD
     207    w.u(1, 1)                # phase center information
     208    w.u(0, 1)                # group delay information
     209    w.u(1, 1)                # nadir angle dependent corrections follow
     210    w.u(3, 5)                # maximum off-nadir angle: corrections 0..3 deg
     211    w.u(1, 4)                # range extension: 3 + 1 = 4 bits
     212    w.u(shared, 1)           # satellite set indicator
     213    mask = 0
     214    for prn in sats:
     215        mask |= 1 << (64 - prn)
     216    w.u(mask, 64)
     217    for n in range(1 if shared else len(sats)):
     218        w.u(shared, 1)       # frequency set indicator
     219        w.u(0b101000, 6)     # frequencies 0 and 2
     220        for f in range(1 if shared else 2):
     221            w.u(1, 1)        # nadir correction follows
     222            w.s(100 * n + 10 * f + 1, 12)    # mm
     223            for deg in range(4):
     224                w.s(nadir[(n + f + deg) % len(nadir)], 4)   # mm, -8: invalid
     225    return frame(w.payload())
     226
     227
     228def rawfile(path):
     229    chunks = []
     230    for i, sta in enumerate(["../ESCAPE0", "CRAFT0RTC0"]):
     231        t = T0 + datetime.timedelta(seconds=5 * i)
     232        chunks.append((t.isoformat(), sta, "RTCM_3", vtec_rtcm(t, [(2, 2)])))
     233    write_chunks(path, chunks)
     234    t = T0 + datetime.timedelta(seconds=10)
     235    with open(path, "ab") as o:
     236        o.write(("%s CRAFT0RTC0 RTCM_3 2000000000\n" % t.isoformat()).encode())
     237        o.write(vtec_rtcm(t, [(2, 2)]) + b"\n")
     238
     239
    165240def main():
     241    if len(sys.argv) == 3 and sys.argv[1] == "--rawfile":
     242        rawfile(sys.argv[2])
     243        return
    166244    if len(sys.argv) != 2:
    167245        sys.exit(__doc__)
    … …  
    175253        t = T0 + datetime.timedelta(seconds=5 * i)
    176254        stamp = t.isoformat()
    177         chunks.append((stamp, "CRAFT0IGS0", "RTCM_3", vtec_igs(t, layers)
    178                        + service_crs() + helmert() + rtcm_crs()))
     255        data = vtec_igs(t, layers) + service_crs() + helmert() + rtcm_crs()
     256        if i == 0:
     257            data += descriptors(["LEIAR25.R4      LEIT", "12345", "SEPT POLARX5",
     258                                 "5.5.0", "3001234"])
     259            data += descriptors(["TRUNCATED ANTENNA", "9", "RECEIVER", "", ""],
     260                                truncate=True)
     261        chunks.append((stamp, "CRAFT0IGS0", "RTCM_3", data))
    179262        chunks.append((stamp, "CRAFT0RTC0", "RTCM_3", vtec_rtcm(t, layers)))
    180263    stamp = (T0 + datetime.timedelta(seconds=15)).isoformat()
    181264    chunks.append((stamp, "CRAFT0NEW0", "RTCM_3",
    182                    metadata([40, 0] + [None] * 5) + metadata([None] * 31)))
     265                   metadata([40, 0] + [None] * 5) + metadata([None] * 31)
     266                   + antenna(83, [1, 17, 33, 49, 64], 0, [-7, 0, 7, 3])
     267                   + antenna(80, [1, 2, 32], 1, [5, -8, -1, 2])))
    183268    write_chunks(sys.argv[1], chunks)
    184269
  • trunk/BNC/tests/tools/ssr_harness.cpp

    r11127 r11130  
    77// reported by AddressSanitizer instead of silently corrupting the next member.
    88//
    9 // Every decoded VTEC (all formats) and metadata message (new RTCM-SSR) is
    10 // encoded again with the Make* function of the same class and decoded once
    11 // more; the result must be identical (exit code 1 otherwise).
     9// Every decoded VTEC (all formats), metadata and satellite antenna message
     10// (new RTCM-SSR) is encoded again with the Make* function of the same class
     11// and decoded once more; the result must be identical, for the antenna
     12// messages also the bytes of the frame (exit code 1 otherwise).
    1213//
    1314// Usage: ssr_harness <file>   (BNC raw file or plain RTCM3 byte stream)
    … …  
    9697  int irc = t1.decode(ssr, frame, size);
    9798  printf("  %-8s irc %3d", name, irc);
     99  SsrCorrRtcmNew* rtcmNew = dynamic_cast<SsrCorrRtcmNew*>(ssr);
    98100  if (irc >= 0 && t1.v->NumLayers) {
    99101    double sum = 0.0;
    … …  
    125127      }
    126128    }
    127     SsrCorrRtcmNew* rtcmNew = dynamic_cast<SsrCorrRtcmNew*>(ssr);
    128129    if (rtcmNew) {
    129130      char buffer[CLOCKORBIT_BUFFERSIZE];
    … …  
    134135      nFailed += !ok;
    135136    }
     137  }
     138  for (unsigned s = 0; rtcmNew && irc >= 0 && s < CLOCKORBIT_SATNUM; s++) {
     139    if (!t1.a->SatelliteMask[s]) {
     140      continue;
     141    }
     142    printf("  ANT type %u mask %016llx", t1.a->messageType[s],
     143           (unsigned long long)t1.a->SatelliteMask[s]);
     144    char buffer[CLOCKORBIT_BUFFERSIZE];
     145    size_t len = rtcmNew->MakeAntenna(t1.a, t1.a->messageType[s], buffer, sizeof(buffer));
     146    t_target t2;
     147    bool sameBytes = len == size && memcmp(buffer, frame, size) == 0;
     148    bool ok = len > 0 && t2.decode(ssr, (const unsigned char*)buffer, len) >= 0 &&
     149              memcmp(t1.a, t2.a, sizeof(*t1.a)) == 0;
     150    printf("  re-encoded: %s, %s", ok ? "identical" : "DIFFERENT",
     151           sameBytes ? "same bytes" : "OTHER BYTES");
     152    nFailed += !ok || !sameBytes;
    136153  }
    137154  printf("\n");
Note: See TracChangeset for help on using the changeset viewer.