newspaint

Documenting Problems That Were Difficult To Find The Answer To

Category Archives: Technology

Rust/Cargo Outputting Dollar Angle Bracket Symbols

So you’re compiling source using Cargo/Rust and you see output similar to the following:

error[E0046]$<2>: not all trait items implemented, missing: `decode`, `encode`$<2>
  $<2>--> $<2>src/main.rs:7:1$<2>
   $<2>|$<2>
7$<2>  $<2>| $<2>impl tokio_core::io::Codec for LineCodec {$<2>
   $<2>| $<2>^$<2> missing `decode`, `encode` in implementation$<2>

error$: aborting due to previous error$

This is full of dollar, angle bracket, number, angle bracket characters.

The fix is to change your terminal, e.g.:

TERM=xterm

On doing this I had the output in full colour without the mysterious symbols.

Conditionally adding a directory to PATH if not already in PATH

In BASH it is possible to check that a directory is not already in the PATH environment variable before adding it.

The basic string-in-string search function was adopted from this forum post.

stringContains() { [ -z "${1##*$2*}" ]; }
stringBegins()   { [ -z "${1##$2*}"  ]; }
stringEnds()     { [ -z "${1##*$2}"  ]; }

# call as inPath "$PATH" "/my/new/path"
inPath() {
  if stringBegins   "$1" "$2:";  then return 0; fi
  if stringEnds     "$1" ":$2";  then return 0; fi
  if stringContains "$1" ":$2:"; then return 0; fi
  if [ "$1" == "$2" ];           then return 0; fi
  return 1;
}

If you wanted to, say, add “/home/myuser/bin” if it didn’t already exist, you could add the above functions and the following:

if inPath "$PATH" "/home/myuser/bin"; then
  : # do nothing
else
  PATH="$PATH:/home/myuser/bin"
fi

Windows 10 TCP/Internet Slow With Chrome and OpenWRT Router

So I was having issues getting a Windows 10 laptop running Google Chrome connected via wifi to a router running OpenWRT Chaos Calmer 15.05.1.

The Windows 10 laptop would take a long time to establish a connection and then a long time for any data to transfer at an incredibly slow rate.

At first I thought it was Google Chrome but downloaded Firefox and was still having the same issues.

There are many proposed solutions but the commands that appeared to make a magical difference and instantly speed things up were:

netsh interface tcp show global
netsh interface tcp set global autotuning=disabled

At this stage things did not magically get better.

Then I tried:

netsh interface tcp show heuristics
netsh interface tcp set heuristics enabled

Now the Internet suddenly got quicker.

To undo these changes (if they don’t work for you):

netsh interface tcp set global autotuning=normal
netsh interface tcp set heuristics disabled

Also, because I messed around with the MTU on the WiFi interface I had to run the following to restore things to a relatively normal default:

netsh interface ipv4 set subinterface “WiFi” mtu=1458 store=persistent

Adding Huawei E160E To OpenWRT

I wanted to add a Huawei E160E USB 3G modem to OpenWRT but had some trouble getting it to work.

I used documentation from three places:

In this case I used a latest snapshot from the LEDE project. It turns out the router would simply lose networking, I’d be unable to SSH or access it via the web, after several minutes. Perhaps this was because I was forcing kmod’s with a slightly incompatible kernel. In the end I went back to Chaos Calmer 15.05.1 from OpenWRT which seemed to be more stable for me.

It turned out that I needed to add some more packages, specifically:

  • usbutils – to run “lsusb” to see when my USB devices had been detected
  • kmod-usb-uhci – ultimately I needed a kmod to see the USB controller in order to detect attached devices
  • kmod-usb2 – just in case the UHCI controller module above didn’t work

Note that when adding kmods then opkg might reject it with a LEDE build if package slightly out of sync with the kernel build, in which case use –force-depends (don’t do this, it might result in an unstable router):

opkg install --force-depends kmod-usb-uhci

Now, also ensure that the /etc/modules.d/usb-serial has the following line:

usbserial vendor=0x12d1 product=0x140c maxSize=4096

The vendor and product values are taken from the output of lsusb:

# lsusb
Bus 001 Device 002: ID 12d1:140c Huawei Technologies Co., Ltd. E180v

Once connected the signal strength can be obtained on the command line by running:

# comgt -d /dev/ttyUSB3
SIM ready
Waiting for Registration..(120 sec max)
Registered on Home network: "50502",2
Signal Quality: 13,99

The result can be looked up in the table at this link:

Value RSSI dBm Condition
2 -109 Marginal
3 -107 Marginal
4 -105 Marginal
5 -103 Marginal
6 -101 Marginal
7 -99 Marginal
8 -97 Marginal
9 -95 Marginal
10-93OK
11-91OK
12-89OK
13-87OK
14-85OK
15 -83 Good
16 -81 Good
17 -79 Good
18 -77 Good
19 -75 Good
20 -73 Excellent
21 -71 Excellent
22 -69 Excellent
23 -67 Excellent
24 -65 Excellent
25 -63 Excellent
26 -61 Excellent
27 -59 Excellent
28 -57 Excellent
29 -55 Excellent
30 -53 Excellent

Turning Off DHCP Server on Netgear Wireless Cable Gateway CGD24N

The Netgear Wireless Cable Gateway model CGD24N supplied by Bigpond in Australia can spend a second life as a simple Ethernet switch. However it assigns DHCP addresses out of the box which can really upset a home network if you’re not expecting it.

Your wireless router might be assigning addresses from one range but you keep finding guest devices assigned something from the 192.168.100.0/24 range.

It’s not that straightforward to find the DHCP on/off switch. The steps to find it are thus:

1. Log in to gateway admin interface, select NAT from menu

Select NAT from menu on left-hand side

Select NAT from menu on left-hand side

2. Turn NAT on, click apply

Select NAT on checkbox, click apply

Select NAT on checkbox, click apply

3. Select LAN IP from left hand menu

Select LAN IP from left hand menu

Select LAN IP from left hand menu

4. Select DHCP no radio button, click apply

Select DHCP no radio button, click apply

Select DHCP no radio button, click apply

How To Change TLS Bind Port In Asterisk

Asterisk doesn’t make it necessarily easy to change the port that TLS is bound to.

In sip.conf I’d set a different port (6000):

tlsbindaddr=0.0.0.0:6000

But when I set sip set debug on I would see a message like the following on answer:

<--- Reliably Transmitting (no NAT) to 5.6.7.8:42849 --->
  P/2.0 200 OK
Via: SIP/2.0/TLS 192.168.1.3:42849;branch=z9hG4bKPjBFu7pgHTfOHCaNamaqTKTq3wenp-G.oY;alias;received=5.6.7.8;rport=42849
From: "myext" ;tag=mQqEvydONdU7yOGgCi2.OiDu8lSfXZuK
To: <sip:test@myhost.com>;tag=as378489ee
Call-ID: tAYfXG5BEF9w8lY.ghupqOtwNyV3J18G
CSeq: 12562 INVITE
Server: Asterisk PBX 13.1.0~dfsg-1.1ubuntu4
Allow: INVITE, ACK, CANCEL, OPTIONS, BYE, REFER, SUBSCRIBE, NOTIFY, INFO, PUBLISH, MESSAGE
Supported: replaces, timer
Session-Expires: 1800;refresher=uas
Contact: <sip:test@1.2.3.4:5061;transport=TLS>
Content-Type: application/sdp
Require: timer
Content-Length: 387

The problem was that the Contact: header was advertising the wrong TLS port to the extension which would then attempt to contact the wrong port in response to the answered call (so no audio would start getting received by the extension).

The solution was to add to sip.conf:

externtlsport=6000

As mentioned in another article if the advertised IP address is wrong in this Contact: header then you may also want to specify:

externip=1.2.3.4

Converting XPS to PDF using MuPDF on Ubuntu Linux

I had a recently generated “.xps” file sent to me and needed it in PDF form for convenient viewing. The following took place on Xubuntu Trusty Tahr 14.04 LTS.

The “xpstopdf” tool failed me with a poorly converted document (just a single rectangle, no text).

Then I installed “mupdf”:

~$ sudo apt-get install mupdf
~$ mupdf mydocument.xps

This it rendered to my satisfaction to the screen. Next I wanted a PDF file!

But when I tried using “mudraw“, the associated tool installed with the “mupdf-tools” Ubuntu package, I got the following error:

~$ sudo apt-get install mupdf-tools
~$ mudraw -o /tmp/mydocument.pdf /tmp/mydocument.xps
error: empty page tree, cannot insert page
error: cannot draw '/tmp/mydocument.xps'

In the end I decided to try compiling the latest version available from MuPDF‘s download page (I downloaded “mupdf-1.9a-source.tar.gz” published 2016-04-21).

~$ wget 'http://mupdf.com/downloads/mupdf-1.9a-source.tar.gz'
~$ tar -xvzf mupdf-1.9a-source.tar.gz
~$ cd mupdf-1.9a-source
~$ sudo apt-get install mesa-common-dev libxcursor-dev libxshmfence-dev libxext-dev libxrandr-dev libxinerama-dev
~$ nice make -j 3
~$ ./build/release/mutool draw -o /tmp/mydocument.pdf /tmp/mydocument.xps

This time my PDF was rendered without any errors!

Want to Slow Linux ZFS Flushing/Syncing to Disk Every 5 Seconds?

So you’ve got ZFS on Linux and you notice your hard drive LED light up every 5 seconds. How can you slow that down?

The zfs_txg_timeout parameter is described as:

~# modinfo zfs |grep zfs_txg_timeout
parm:           zfs_txg_timeout:Max seconds worth of delta per txg (int)

You can check the current value of this parameter:

~# cat /sys/module/zfs/parameters/zfs_txg_timeout
5

To verify this is the parameter you want to change, set this to 10 and count the number of seconds between the hard drive light coming on:

~# echo 10 >/sys/module/zfs/parameters/zfs_txg_timeout

Once you know this is the parameter causing the hard drive activity you can tell the ZFS module the default you want it to start with on next boot by editing /etc/modprobe.d/zfs.conf and adding a line similar to the following:

options zfs zfs_txg_timeout=30

Take care when changing this number as it may result in a higher probability of lost data in the event of a power outage.

Past Duration 0.999992 Too Large

While encoding a video in ffmpeg I encountered the message:

Past duration 0.999992 too large
Last message repeated 11 times

The problem magically disappeared when I changed audio codec and bitrate for the output stream.

My input stream reported itself as:

Stream #0:2: Audio: ac3, 48000 Hz, 5.1(side), 448 kb/s

But the settings I used to encode the stream to give me the error were:

-c:a:1 aac -b:a:1 160k -metadata:s:a:1 title="5.1 channel"

Note that the input stream was ac3 but I was converting it to aac on the output. Not necessarily a bad thing for stereo output, but for 5.1 maybe not the best target codec. The ffmpeg wiki high quality audio guide states the ac3 codec is for Dolby Digital.

When I changed to the following settings the error message disappeared:

-c:a:1 ac3 -b:a:1 320k -metadata:s:a:1 title="5.1 channel"

Ripping A Video From DVD Using FFMPEG

I have a collection of DVDs I need to put in storage to clear up some space. This page lists what I have learned about how to take DVD video and create a video file as a result.

There are many other articles on the subject, such as this one.

A DVD usually has two directories on it, AUDIO_TS and VIDEO_TS. For DVD videos we only care about the VIDEO_TS directory.

Inside the VIDEO_TS directory there are a collection of files, e.g.:

     16384 Aug 23  2005 VIDEO_TS.BUP
     16384 Aug 23  2005 VIDEO_TS.IFO
    157696 Aug 23  2005 VIDEO_TS.VOB
     30720 Aug 23  2005 VTS_01_0.BUP
     30720 Aug 23  2005 VTS_01_0.IFO
 176521216 Aug 23  2005 VTS_01_0.VOB
  22235136 Aug 23  2005 VTS_01_1.VOB
     43008 Aug 23  2005 VTS_02_0.BUP
     43008 Aug 23  2005 VTS_02_0.IFO
    157696 Aug 23  2005 VTS_02_0.VOB
1073565696 Aug 23  2005 VTS_02_1.VOB
1073565696 Aug 23  2005 VTS_02_2.VOB
 839757824 Aug 23  2005 VTS_02_3.VOB

We’re only interested in *.VOB files, and generally anything after VTS_02_* as VTS_01_* is usually the contents page for the DVD.

So, we want to make a video out of the VTS_02_*.VOB files. Before we can proceed any further it is necessary for us to make a single, continuous .mpeg file. Be warned, however, this file will be large (3 gigabytes for 45 minutes).

Thus we want to have an input file that is a concatenation of the VOB files, in order. We use the input file type of concat:file_1:file_2:

Again, before we proceed further, we need to find out what streams are in the source video:

~$ ffmpeg -i "concat:VTS_02_0.VOB|VTS_02_1.VOB|VTS_02_2.VOB|VTS_02_3.VOB" -c copy /dev/null
Input #0, mpeg, from 'concat:VTS_02_0.VOB|VTS_02_1.VOB|VTS_02_2.VOB|VTS_02_3.VOB':
  Duration: 00:45:08.97, start: 0.280000, bitrate: 8821 kb/s
    Stream #0:0[0x1bf]: Data: dvd_nav_packet
    Stream #0:1[0x1e0]: Video: mpeg2video (Main), yuv420p(tv), 720x576 [SAR 16:15 DAR 4:3], 8000 kb/s, 25 fps, 25 tbr, 90k tbn, 50 tbc
    Stream #0:2[0x20]: Subtitle: dvd_subtitle
    Stream #0:3[0x81]: Audio: ac3, 48000 Hz, 5.1(side), fltp, 448 kb/s
    Stream #0:4[0x80]: Audio: ac3, 48000 Hz, stereo, fltp, 224 kb/s

Now, when we create our intermediate (temporary) .mpeg file, we need to specify which streams we want to extract. By default ffmpeg only extracts the best video and best audio stream it can find. If we want to keep all our audio streams then we have to explicitly tell ffmpeg this using the -map directive, one per stream we want to keep, in order.

In this case I want to keep streams 0:1 (video), 0:3 (5.1 audio), and 0:4 (audio stereo). But actually I want the stereo track to come before the 5.1 audio, so I’ll use the following command to make my intermediate file:

~$ ffmpeg -i "concat:VTS_02_0.VOB|VTS_02_1.VOB|VTS_02_2.VOB|VTS_02_3.VOB" -map 0:1 -map 0:4 -map 0:3 -f mpeg -c copy /tmp/intermediate.mpeg
Input #0, mpeg, from 'concat:VTS_02_0.VOB|VTS_02_1.VOB|VTS_02_2.VOB|VTS_02_3.VOB':
  Duration: 00:45:08.97, start: 0.280000, bitrate: 8821 kb/s
    Stream #0:0[0x1bf]: Data: dvd_nav_packet
    Stream #0:1[0x1e0]: Video: mpeg2video (Main), yuv420p(tv), 720x576 [SAR 16:15 DAR 4:3], 8000 kb/s, 25 fps, 25 tbr, 90k tbn, 50 tbc
    Stream #0:2[0x20]: Subtitle: dvd_subtitle
    Stream #0:3[0x81]: Audio: ac3, 48000 Hz, 5.1(side), fltp, 448 kb/s
    Stream #0:4[0x80]: Audio: ac3, 48000 Hz, stereo, fltp, 224 kb/s
Output #0, mpeg, to '/tmp/intermediate.mpeg':
  Metadata:
    encoder         : Lavf57.15.100
    Stream #0:0: Video: mpeg2video, yuv420p, 720x576 [SAR 16:15 DAR 4:3], q=2-31, 8000 kb/s, 25 fps, 25 tbr, 90k tbn, 25 tbc
    Stream #0:1: Audio: ac3, 48000 Hz, stereo, 224 kb/s
    Stream #0:2: Audio: ac3, 48000 Hz, 5.1(side), 448 kb/s
Stream mapping:
  Stream #0:1 -> #0:0 (copy)
  Stream #0:4 -> #0:1 (copy)
  Stream #0:3 -> #0:2 (copy)
video:2645654kB audio:222221kB subtitle:0kB other streams:0kB global headers:0kB muxing overhead: 0.389088%

So now we have an intermediate file. It is from this we can create the desired output.

You might have an encrypted region-specific DVD. In this case the ffmpeg tool will not work by itself. A tool that will read encrypted DVDs is a port of ffmpeg called vgtmpeg. There are Windows and Linux builds available. This uses the same command line except for the input you specify an input of something like:

~$ vgtmpeg -i dvd:///media/user/DVD_VIDEO/?title=3
C:\> vgtmpeg.exe -i dvd://F:\title=3

Note that region-coded DVDs will not work in a DVD drive that has no region code set (some new drives have no code initially configured). In Linux you can set a drive’s region code (a maximum of 5 times) using the command-line tool regionset. Once the drive’s region has been set, however, the vgtmpeg tool should work with a drive from any region even if it is different from the drive’s specified region.

Now you can compress the intermediate file.

You will probably want to tinker with the settings to suit your preferences.

First you have to specify which streams you want to encode, again. You may be forced to specify the display aspect ratio. And you may wish to add metadata (descriptions) to the audio channels (and subtitles if you use them).

Here are some settings for an example:

~$ ffmpeg -i /tmp/intermediate.mpeg \
  -map 0:0 -map 0:1 -map 0:2 \
  -c:v libx264 -preset medium -b:v 600k -aspect 16:9 -strict -2 -g 50 -vf yadif \
  -c:a:0 aac -b:a:0 160k -metadata:s:a:0 title=\"2 channel\" \
  -c:a:1 ac3 -b:a:1 320k -metadata:s:a:1 title=\"5.1 channel\" \
  /tmp/final.mkv

The -map directives select what streams we want from our input file.

The -c:v libx264 directive selects the video codec. The -preset option chooses an H.264 encoding speed to compression ratio. The -b:v option specifies a constant output bitrate (you can use two-pass encoding if you wish to utilise a different strategy). The -aspect 16:9 may not be necessary but forces the default display by the client reading the file later. The -strict -2 options are required for H.264 encoding. The -g 50 option makes the encoder store a whole image frame every 50 frames (useful for being able to forward or reverse into the video). The -vf yadif video filter de-interlaces the source video.

The -c:a:0 option sets the audio codec on the first audio stream (which is different from the stream number assigned). The -b:a:0 option sets the bit rate for the first audio stream. And the -metadata:s:a:0 option sets a title for the stream, which can make it easier for those watching your video to choose an appropriate named audio track rather than guessing what the difference is.

Finally the output file name is specified.

Audio

A guide to high quality audio with ffmpeg is documented on the ffmpeg wiki.

A 5.1 stream is perhaps better encoded using the “ac3” (Dolby Digital) codec.

If you want to convert a 5.1 stream to stereo you can use the following to select a particular audio stream and apply a filter to it:

-af:a:0 'pan=stereo|FL=FC+0.30*FL+0.30*BL|FR=FC+0.30*FR+0.30*BR'

Subtitles

DVD subtitles may not appear in the first VOB file in a set; it may be necessary to tell ffmpeg to scan ahead deep into the file so that it can find the subtitles in the second VOB file. The directives to do this are -probesize and -analyzeduration – the first being the number of bytes to read ahead into the file, and the second being the number of microseconds (of which there are 1,000,000 per second). These directives must come before the input file directive.

So, to scan ahead 4GB and 1 hour, the an example command may be:

~$ ffmpeg -i -probesize 4G -analyzeduration 3600M "concat:VTS_02_0.VOB|VTS_02_1.VOB|VTS_02_2.VOB|VTS_02_3.VOB" -c copy /dev/null

You can specify a title to go along with a subtitle track, such as:

-metadata:s:s:0 title="English"