Asterisk Wake Up call application

February 2, 2010 - 2 comments

If you want to be awaken by your Asterisk PBX, here’s a simple bit of code to add in your dial plan.

Basically, you would call 9253 followed by the time the phone should ring, for exemple if you want to be awaken at 06:30am you would call 92530630 (on your dialpad WAKE0610).

This code only allows to set ONE alarm.

If you want to delete -for exemple the 0630am- alarm, you would call 6692530610 (on dialpad NOWAKE0610).

Asterisk will create a call file and put it under /var/spool/asterisk/outgoing/
How does Asterisk know when to call you ? It will check the timestamp of the call files.

Make sure you enable func_strings.so module, it is required for STRFTIME.

[Context-This-Code-Should-Go-In]

; WAKE + hour + minute : sets a wake up call
exten => _9253XXXX,1,Answer()
exten => _9253XXXX,n,Set(wakeuptime=${EXTEN:4:4})
exten => _9253XXXX,n,Set(today=${STRFTIME(${EPOCH},,%Y%m%d)})
exten => _9253XXXX,n,Set(tomorrow=${STRFTIME($[${EPOCH} + 86400],,%Y%m%d)})
exten => _9253XXXX,n,Set(now=${STRFTIME(${EPOCH},,%Y%m%d%H%M)})
exten => _9253XXXX,n,System(echo -e "Channel: SIP/${CALLERID(num)}\\nContext: WakeUp\\nExtension: 92531" > /tmp/${UNIQUEID}.call)
exten => _9253XXXX,n,GotoIf($["${today}${wakeuptime}" < "${now}"]?tomorrow:today)
exten => _9253XXXX,n(today),NoOp(Scheduling wake up call for ${CALLERID(num)} today at ${wakeuptime} / )
exten => _9253XXXX,n,System(touch -t ${today}${wakeuptime} /tmp/${UNIQUEID}.call)
exten => _9253XXXX,n,Goto(move)
exten => _9253XXXX,n(tomorrow),NoOp(Scheduling wake up call for ${CALLERID(num)} tomorrow at ${wakeuptime} / )
exten => _9253XXXX,n,System(touch -t ${tomorrow}${wakeuptime} /tmp/${UNIQUEID}.call)
exten => _9253XXXX,n(move),System(mv /tmp/${UNIQUEID}.call /var/spool/asterisk/outgoing/${wakeuptime}.${UNIQUEID}.call)
exten => _9253XXXX,n,Wait(1)
exten => _9253XXXX,n,SayNumber(${wakeuptime})
exten => _9253XXXX,n,Hangup()

; NOWAKE + hour + minute : deletes a wake up call
exten => _669253XXXX,1,Answer()
exten => _669253XXXX,n,Set(wakeuptime=${EXTEN:6:4})
exten => _669253XXXX,n,NoOp(Deleting alarm set at ${wakeuptime})
exten => _669253XXXX,n,System(rm -f /var/spool/asterisk/outgoing/${wakeuptime}*)
exten => _669253XXXX,n,Wait(1)
exten => _669253XXXX,n,Background(auth-thankyou)
exten => _669253XXXX,n,Hangup()

[WakeUp]
;;; Context for outgoing wake up calls only, well you can always call 92531 but it's rather pointless
exten => 92531,1,Answer()
exten => 92531,n,Wait(1)
exten => 92531,n,Background(hello-world)
exten => 92531,n,Wait(1)
exten => 92531,n,Hangup()

Asterisk : XMPP notifications for missed calls

January 20, 2010 - No comment

Tester under Asterisk 1.4.21.

If someone calls and hangs up before leaving a voicemail (that means while the phone is ringing or during voicemail message), Asterisk will send a “missed call” notification by XMPP/Jabber.

/etc/asterisk/jabber.conf :

This file contains the info for Asterisk to connect to the Jabber server.
When restarting Asterisk, it will connect automatically and add contacts specified under buddy fields to its contact list.
You can specify several accounts in this file, and use different accounts for different notifications, for example.
From Asterisk CLI, there’s a command “jabber test” which would display the status of your contacts, this command only works with the account specified in the [asterisk] context.

[general]
debug=no
autoprune=no ; this is important to set this to no, if set to yes and you don't specify any "buddy=" it will delete contacts from your buddy list
autoregister=yes        

[asterisk] ; must be called "asterisk" if we want the command "jabber test" to work
type=client
serverhost=jabber.example.org
username=pbx@example.org/pbx
secret=PASSWORD
port=5222
usetls=yes
usesasl=yes
buddy=youraccountreceivingnotifications@gmail.com
buddy=anotheraccountthatmayreceivenotifications@gmail.com
statusmessage=Asterisk XMPP bot. Don't talk to me, your messages would be lost forever.
timeout=100

[account2]
type=client
serverhost=jabber.example.org
username=anotheraccount@example.org/pbx
secret=PASSWORD
port=5222
usetls=yes
usesasl=yes
buddy=someoneelse@gmail.com
statusmessage=Asterisk XMPP bot. Don't talk to me, your messages would be lost forever.
timeout=100

/etc/asterisk/extensions.conf :

When you pass the option “g” to the Dial() command, when the user hangs up, Asterisk exits the Dial() command and continue by jumping to the special “h” extension in the current context. From the console you should expect something like “Spawn extension (macro-DialVM, h, 5) exited” when the whole thing has been processed.

If you don’t specify the option, Asterisk will exit at the Dial() command. You would then see “Spawn extension (macro-DialVM, s, 1) exited” right after the user hangs up.

In this bit of dialplan, we enable XMPP notifications for calls made on extension 555 in the context named Local.
Dialing is made through a macro called macro-DialVM.
XMPP notifications are sent through macro-XMPPSend.

[macro-XMPPSend]
;;; Description : sends XMPP messages only if user is online and not away
;;; ARG1 = Jabber ID to be notified
;;; ARG2 = Message
;;; Jabberstatus and Jabbersend take the account name to user to send notifications as first argument ([asterisk] or [account2] under jabber.conf)

; getting user's status
; Status can be in order : 1)Online, 2)Chatty, 3)Away, 4)XAway, 5)DND, 6)Offline, 7)Not in roster
exten => s,1,Jabberstatus(asterisk,${ARG1},STATUS)
; If the value of STATUS is anything under 3 (or Away), in other words if user is Online or in Chatty mode
exten => s,n,GotoIf($["${STATUS}" < "3"]?available:unavailable)
; then we send a message
exten => s,n(available),NoOp(${ARG1} is available)
exten => s,n,Jabbersend(asterisk,${ARG1},${ARG2})
exten => s,n,MacroExit()
; if the user is not available, we don't send anything
exten => s,n(unavailable),NoOp(${ARG1} is not available in at least one location.. Do not send notification)
exten => s,n,MacroExit()

[macro-DialVM]
;;; Description : dials (option g enabled, jumps to h extension) and goes to voicemail if reaching timeout.
;;; ARG1 = extension to be dialed
;;; ARG2 = timeout
;;; XMPP notification if call missed

exten => s,1,Dial(SIP/${ARG1},${ARG2},wg)
exten => s,n,Voicemail(${ARG1})

; option g must be passed to Dial() to jump to h extension or it would spawn at "macro-DialVM,s,1"
; if user doesn't leave a voicemail, VMSTATUS = FAILED
; if user hangs up before reaching the voicemail app, DIALSTATUS = CANCEL
exten => h,1,NoOp(Did user hang up before leaving a voicemail ?)
exten => h,n,GotoIf($["${VMSTATUS}" = "FAILED"]?missed:nextcheck)
exten => h,n(nextcheck),GotoIf($["${DIALSTATUS}" = "CANCEL"]?missed:notmissed)
exten => h,n(missed),Macro(XMPPSend,youraccountreceivingnotifications@gmail.com,${CALLERID(all)} just tried to call ${ARG1})
exten => h,n(notmissed),Hangup()

[Local]
;;; Description : Local calls context

; My extension is 555, with a timeout of 30 seconds
exten => 555,1,Macro(DialVM,${EXTEN},30)

Asterisk dependencies on Debian Lenny or Squeeze ??

January 16, 2010 - 2 comments

Can someone explain why build-essential is a dependency of Asterisk under Lenny or Squeeze ?

142 MB.. seriously ? Meanwhile Askozia fits on 30 MB, and that includes the OS.

# apt-get install asterisk
Reading package lists... Done
Building dependency tree
Reading state information... Done
The following extra packages will be installed:
  asterisk-config asterisk-sounds-main binutils build-essential bzip2 ca-certificates cpp cpp-4.3 debhelper dpkg-dev file g++ g++-4.3 gcc gcc-4.3 gettext gettext-base
  html2text intltool-debian libasound2 libc-client2007b libc6-dev libcap2 libcompress-raw-zlib-perl libcompress-zlib-perl libcurl3 libdigest-hmac-perl libdigest-sha1-perl
  libfile-remove-perl libgmp3c2 libgomp1 libgsm1 libidn11 libiksemel3 libio-compress-base-perl libio-compress-zlib-perl libio-stringy-perl libldap-2.4-2 libltdl3
  libmagic1 libmail-box-perl libmail-sendmail-perl libmailtools-perl libmime-types-perl libmpfr1ldbl libobject-realize-later-perl libogg0 libpci3 libperl5.10 libpq5
  libpri1.0 libradiusclient-ng2 libsensors3 libsnmp-base libsnmp15 libspeex1 libspeexdsp1 libsqlite0 libssh2-1 libstdc++6-4.3-dev libsys-hostname-long-perl libsysfs2
  libtimedate-perl libtonezone1 liburi-perl libuser-identity-perl libvorbis0a libvorbisenc2 libvpb0 linux-libc-dev make mlock module-assistant odbcinst1debian1 openssl
  patch perl perl-modules po-debconf ucf unixodbc vpb-driver-source
Suggested packages:
  ekiga ohphone twinkle kphone asterisk-doc asterisk-dev asterisk-h323 binutils-doc bzip2-doc cpp-doc gcc-4.3-locales dh-make debian-keyring g++-multilib g++-4.3-multilib
  gcc-4.3-doc libstdc++6-4.3-dbg gcc-multilib manpages-dev autoconf automake1.9 libtool flex bison gdb gcc-doc gcc-4.3-multilib libmudflap0-4.3-dev libgcc1-dbg
  libgomp1-dbg libmudflap0-dbg cvs gettext-doc libasound2-plugins uw-mailutils glibc-doc libmime-tools-perl libhtml-tree-perl libhtml-format-perl spamassassin
  libmail-imapclient-perl lm-sensors speex libstdc++6-4.3-doc libwww-perl vpb-utils make-doc diff-doc perl-doc libterm-readline-gnu-perl libterm-readline-perl-perl
  libmyodbc odbc-postgresql libct1
The following NEW packages will be installed:
  asterisk asterisk-config asterisk-sounds-main binutils build-essential bzip2 ca-certificates cpp cpp-4.3 debhelper dpkg-dev file g++ g++-4.3 gcc gcc-4.3 gettext
  gettext-base html2text intltool-debian libasound2 libc-client2007b libc6-dev libcap2 libcompress-raw-zlib-perl libcompress-zlib-perl libcurl3 libdigest-hmac-perl
  libdigest-sha1-perl libfile-remove-perl libgmp3c2 libgomp1 libgsm1 libidn11 libiksemel3 libio-compress-base-perl libio-compress-zlib-perl libio-stringy-perl
  libldap-2.4-2 libltdl3 libmagic1 libmail-box-perl libmail-sendmail-perl libmailtools-perl libmime-types-perl libmpfr1ldbl libobject-realize-later-perl libogg0 libpci3
  libperl5.10 libpq5 libpri1.0 libradiusclient-ng2 libsensors3 libsnmp-base libsnmp15 libspeex1 libspeexdsp1 libsqlite0 libssh2-1 libstdc++6-4.3-dev
  libsys-hostname-long-perl libsysfs2 libtimedate-perl libtonezone1 liburi-perl libuser-identity-perl libvorbis0a libvorbisenc2 libvpb0 linux-libc-dev make mlock
  module-assistant odbcinst1debian1 openssl patch perl perl-modules po-debconf ucf unixodbc vpb-driver-source
0 upgraded, 83 newly installed, 0 to remove and 0 not upgraded.
Need to get 47.3MB of archives.
After this operation, 142MB of additional disk space will be used.
Do you want to continue [Y/n]? 

EDIT Janv. 30 :

Thanks to Kurt for the tip in the comments.
It completely went unnoticed to me, but Debian Lenny indeed installs “recommends” packages :

To avoid the bloat caused by this new policy, edit /etc/apt/apt.conf and add :
APT::Install-Recommends "0";

The result is clear :

# apt-get install asterisk
Reading package lists... Done
Building dependency tree
Reading state information... Done
The following extra packages will be installed:
  asterisk-config asterisk-sounds-main ca-certificates libasound2
  libc-client2007b libcap2 libcurl3 libgsm1 libidn11 libiksemel3 libldap-2.4-2
  libltdl3 libogg0 libpci3 libperl5.10 libpq5 libpri1.0 libradiusclient-ng2
  libsensors3 libsnmp-base libsnmp15 libspeex1 libspeexdsp1 libsqlite0
  libssh2-1 libsysfs2 libtonezone1 libvorbis0a libvorbisenc2 libvpb0 mlock
  odbcinst1debian1 openssl ucf unixodbc
Suggested packages:
  ekiga ohphone twinkle kphone asterisk-doc asterisk-dev asterisk-h323
  libasound2-plugins uw-mailutils lm-sensors speex vpb-utils libmyodbc
  odbc-postgresql libct1
Recommended packages:
  vpb-driver-source
The following NEW packages will be installed:
  asterisk asterisk-config asterisk-sounds-main ca-certificates libasound2
  libc-client2007b libcap2 libcurl3 libgsm1 libidn11 libiksemel3 libldap-2.4-2
  libltdl3 libogg0 libpci3 libperl5.10 libpq5 libpri1.0 libradiusclient-ng2
  libsensors3 libsnmp-base libsnmp15 libspeex1 libspeexdsp1 libsqlite0
  libssh2-1 libsysfs2 libtonezone1 libvorbis0a libvorbisenc2 libvpb0 mlock
  odbcinst1debian1 openssl ucf unixodbc
0 upgraded, 36 newly installed, 0 to remove and 13 not upgraded.
Need to get 14.0MB of archives.
After this operation, 33.2MB of additional disk space will be used.
Do you want to continue [Y/n]?

ztdummy for Debian Lenny

December 3, 2008 - 2 comments

I just compiled zaptel-modules for Debian Lenny (Kernel 2.6.26 i386)
That package contains the ztdummy module.

Here’s a link to the package :
http://www.wains.be/pub/zaptel-modules-2.6.26-1-686_1.4.11~dfsg-2+2.6.26-10_i386.deb

Slimming Asterisk for the NSLU2 under Debian

April 15, 2008 - 8 comments

A FULLY WORKING ASTERISK SIP PBX RUNNING WITH ONLY 6 MODULES LOADED ! READ ON…

This howto is based on Asterisk 1.2 under Debian Etch. Please let me know through the comments if it works for you under other versions (and if it doesn’t, please provide the steps to get a working system). Thanks.

My needs :

I had to slim Asterisk down to the most minimalistic configuration possible to run on my Linksys NSLU2 (ARM cpu @ 266 Mhz, RAM 32 MB).

- SIP calls between my IP phones and softphone
- Incoming/Outgoing calls through a SIP ITSP (ipness.com)
- Echo test to make sure audio is going through in some situation
- I only use the alaw codec, compatible with my IP phones and ITSP, you should avoid transcoding. My DSL connection offers dynamic IP only and gives around 3400 Kbps down/386 Kbps up. I could use the GSM codec, but the ITSP doesn’t support it
- No voicemail or other apps

My setup :

- The NSLU2 is behind a NAT router
- Home phone on the same subnet as the NSLU2
- Work phone behind NAT
- Softphone used from several places

Router configuration :

- Forward port UDP/5060 to UDP/5070 to the NSLU2
- UDP/5060 is used for SIP traffic (signalling)
- UDP/5061 to UDP/5070 is used for RTP traffic (audio)

Asterisk configuration files :

Before diving into the configuration..
IMPORTANT !!!
If you want to comment something out in the configuration you’ll start the line with a semi-colon (“;”)
# is used for file inclusions. # IS NOT USED FOR COMMENTS !!!

I moved unnecessary files under backup/

root@nslu2:/etc/asterisk# ls -l
total 40
-rw-r--r-- 1 root root 247 2008-04-13 22:03 asterisk.conf
drwxr-xr-x 2 root root 4096 2008-04-13 22:03 backup
-rw-r--r-- 1 root root 141 2008-04-13 22:10 extensions.conf
-rw-r--r-- 1 root root 1660 2008-04-13 23:34 features.conf
-rw-r--r-- 1 root root 2158 2008-04-13 22:03 logger.conf
-rw-r--r-- 1 root root 438 2008-04-13 23:37 modules.conf
-rw-r--r-- 1 root root 395 2008-04-13 22:03 rtp.conf
-rw-r--r-- 1 root root 299 2008-04-13 22:04 sip.conf
-rw-r--r-- 1 root root 904 2008-04-13 23:40 custom_extensions.conf
-rw-r--r-- 1 root root 1349 2008-04-14 09:31 custom_sip.conf

/etc/asterisk/extensions.conf :

[general]

static=yes
writeprotect=no
autofallthrough=yes
clearglobalvars=no
priorityjumping=no

; let's include custom_extensions.conf into extensions.conf
#include "/etc/asterisk/custom_extensions.conf"

/etc/asterisk/features.conf : default configuration

/etc/asterisk/logger.conf : default configuration

/etc/asterisk/modules.conf :

Order in which modules are loaded can be important. E.g. : res_features.so must be loaded before chan_sip.so

[modules]
autoload=no             ; only load explicitely declared modules

load => app_echo.so     ; echo application
load => codec_alaw.so   ; alaw codec for voice
load => pbx_config.so   ; reading and loading configuration
load => res_features.so ; chan_sip.so dependency
load => chan_sip.so     ; SIP protocol
load => app_dial.so     ; Dial application

[global]

/etc/asterisk/rtp.conf :

The audio is going through these UDP ports, they must be forwarded to the server in the router.

In this example, the number of ports used by Asterisk is relatively low (I never have more than one call going through the PBX). Set as much as you need, a channel may need up to 2 ports. Also only even ports are actually used.

[general]
rtpstart=5061
rtpend=5070

/etc/asterisk/sip.conf :

Having a dynamic IP, I must use externhost with a fresh rate of 60 seconds for resolving the domain.
If you have a static IP, define it in externip=

Localnet must be defined with your network subnet(s), localnet subnets are never passed in the “Via” parameter (can be seen in sip traces).

realm must be a unique ID

The “register =>” line is necessary in order to receive incoming calls from the ITSP.

[general]

context=incoming
bindport=5060
bindaddr=0.0.0.0

srvlookup=yes

externhost=mydynamichostname.dyndns.org
externrefresh=60

localnet=192.168.1.0/255.255.255.0

realm=mydynamichostname.dyndns.org

register => 3221234567:password:login@ipness.net:6060/3221234567

#include "/etc/asterisk/custom_sip.conf"

/etc/asterisk/custom_extensions.conf :

custom_extensions.conf is my customized dialplan

- Home phone and softphone can call local phones (1XXX range)
- Home phone and softphone can call national (e.g. : 02 123 45 67) and international numbers (00 1 910 123 4567) through the ITSP
- Work phone can only call local phones
- Every phone can call the echo application
- Incoming calls make 1001 ring first, then 1002 and finally 1000 (each with a timeout of 30 seconds)

[globals]

;;; apps context

[apps]
exten => 444,1,Answer()
exten => 444,n,Wait(1)
exten => 444,n,Echo

;;; incoming calls context

[incoming]
exten => 3221234567,1,Dial(SIP/1001,30)
exten => 3221234567,n,Dial(SIP/1002,30)
exten => 3221234567,n,Dial(SIP/1000,30)

;;; outgoing calls context

; local calls only
[local]
include => apps

exten => _1XXX,1,Dial(SIP/${EXTEN})
exten => _1XXX,n,NoOp(===== DIAL STATUS --> ${DIALSTATUS} =====)
exten => _1XXX,n,Hangup()

; national (Belgium, code 32) calls only
[national]
include => local
include => apps

exten => _0N.,1,Dial(SIP/0032${EXTEN:1}@itsp_ipness)
exten => _0N.,n,NoOp(===== DIAL STATUS --> ${DIALSTATUS} =====)
exten => _0N.,n,Hangup()

; international calls
[international]
include => national
include => local
include => apps

exten => _00.,1,Dial(SIP/${EXTEN}@itsp_ipness)
exten => _00.,n,NoOp(===== DIAL STATUS --> ${DIALSTATUS} =====)
exten => _00.,n,Hangup()

/etc/asterisk/custom_sip.conf :

custom_sip.conf is my customized accounts file.

canreinvite must be set to no for all sip accounts (unless you have several phones on the server subnet, than you can set to yes).
NAT must be set to yes for any device behind NAT routers.

; SIP accounts

[1000]
type=friend
context=international
callerid="Softphone" <1000>
qualify=yes
secret=1111
nat=yes
canreinvite=no
dtmfmode=rfc2833
host=dynamic
call-limit=2
disallow=all
allow=alaw

[1001]
type=friend
context=international
callerid="Home" <1001>
qualify=yes
secret=1111
nat=no ; IP phone is on the same subnet as the server
canreinvite=no
dtmfmode=rfc2833
host=dynamic
call-limit=2
disallow=all
allow=alaw

[1002]
type=friend
context=local
callerid="Work" <1002>
qualify=yes
secret=1111
nat=yes
canreinvite=no
dtmfmode=rfc2833
host=dynamic
call-limit=2
disallow=all
allow=alaw

[1003]
type=friend
context=local
callerid="Friend" <1003>
qualify=no
secret=1111
nat=yes
canreinvite=no
dtmfmode=rfc2833
host=dynamic
call-limit=1
disallow=all
allow=alaw

; ITSP

[itsp_ipness]
type=peer
username=login
secret=password
fromuser=3221234567
fromdomain=ipness.net
host=ipness.net
port=6060
nat=yes
canreinvite=no
context=incoming
insecure=very
qualify=yes
disallow=all
allow=alaw

Result :

nslu2*CLI> show modules
Module                         Description                              Use Count
app_echo.so                    Simple Echo Application                  0
codec_alaw.so                  A-law Coder/Decoder                      0
pbx_config.so                  Text Extension Configuration             0
res_features.so                Call Features Resource                   1
chan_sip.so                    Session Initiation Protocol (SIP)        0
app_dial.so                    Dialing Application                      0       

nslu2*CLI> show applications
    -= Registered Asterisk Applications =-
       AbsoluteTimeout: Set absolute maximum time of call
                Answer: Answer a channel if ringing
            BackGround: Play a file while awaiting extension
                  Busy: Indicate the Busy condition
            Congestion: Indicate the Congestion condition
                  Dial: Place a call and connect to the current channel
          DigitTimeout: Set maximum timeout between digits
                  Echo: Echo audio read back to the user
            ExecIfTime: Conditional application execution based on the current time
                  Goto: Jump to a particular priority, extension, or context
                GotoIf: Conditional goto
            GotoIfTime: Conditional Goto based on the current time
                Hangup: Hang up the calling channel
             ImportVar: Import a variable from a channel into a new variable
                  NoOp: Do Nothing
                  Park: Park yourself
            ParkedCall: Answer a parked call
              Progress: Indicate progress
              ResetCDR: Resets the Call Data Record
       ResponseTimeout: Set maximum timeout awaiting response
             RetryDial: Place a call, retrying on failure allowing optional exit extension.
               Ringing: Indicate ringing tone
              SayAlpha: Say Alpha
             SayDigits: Say Digits
             SayNumber: Say Number
           SayPhonetic: Say Phonetic
                   Set: Set channel variable(s) or function value(s)
           SetAccount: Set the CDR Account Code
           SetAMAFlags: Set the AMA Flags
          SetGlobalVar: Set a global variable to a given value
           SetLanguage: Set the channel's preferred language
                SetVar: Set channel variable(s)
          SIPAddHeader: Add a SIP header to the outbound call
           SIPDtmfMode: Change the dtmfmode for a SIP call
          SIPGetHeader: Get a SIP header from an incoming call
                  Wait: Waits for some time
             WaitExten: Waits for an extension to be entered
    -= 37 Applications Registered =-

nslu2*CLI> show functions
Installed Custom Functions:
--------------------------------------------------------------------------------
CHECKSIPDOMAIN        CHECKSIPDOMAIN(<domain|IP>)          Checks if domain is a local domain
SIPCHANINFO           SIPCHANINFO(item)                    Gets the specified SIP parameter from the current channel
SIPPEER               SIPPEER(<peername>[:item])           Gets SIP peer information
SIP_HEADER            SIP_HEADER(<name>)                   Gets the specified SIP header
4 custom functions installed.

Asterisk is using around 12 MB of memory when idle.