<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Weird rocketry &#187; dev</title>
	<atom:link href="http://webapp.org.ua/category/dev/feed/" rel="self" type="application/rss+xml" />
	<link>https://webapp.org.ua</link>
	<description>Flights to outer code</description>
	<lastBuildDate>Sat, 16 Jul 2016 11:12:13 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.1</generator>
		<item>
		<title>OpenWRT Chaos Calmer 15.05 on Dlink DIR-320 with CDMA modem</title>
		<link>https://webapp.org.ua/dev/openwrt-chaos-calmer-15-05-on-dlink-dir-320-with-cdma-modem/</link>
		<comments>https://webapp.org.ua/dev/openwrt-chaos-calmer-15-05-on-dlink-dir-320-with-cdma-modem/#comments</comments>
		<pubDate>Thu, 07 Apr 2016 11:53:19 +0000</pubDate>
		<dc:creator>bananos</dc:creator>
				<category><![CDATA[dev]]></category>
		<category><![CDATA[hardware]]></category>
		<category><![CDATA[sysadmin]]></category>
		<category><![CDATA[3.18]]></category>
		<category><![CDATA[AirCard 250U]]></category>
		<category><![CDATA[brcm47xx]]></category>
		<category><![CDATA[cdma]]></category>
		<category><![CDATA[dir-320]]></category>
		<category><![CDATA[dlink]]></category>
		<category><![CDATA[extroot]]></category>
		<category><![CDATA[image builder]]></category>
		<category><![CDATA[linux kernel]]></category>
		<category><![CDATA[openwrt]]></category>
		<category><![CDATA[opkg]]></category>
		<category><![CDATA[PL2303TA]]></category>
		<category><![CDATA[serial]]></category>
		<category><![CDATA[sierra]]></category>
		<category><![CDATA[usb-ttl]]></category>

		<guid isPermaLink="false">http://webapp.org.ua/?p=492</guid>
		<description><![CDATA[The goal of this article is to install latest OpenWRT firmware on a very popular DIR-320 Wi-Fi router (BRCM47XX based). The reason why you might do this is to be able to connect modern hardware(modems) to this pretty old legacy device. Official firmware 3G modem support list is pretty limited and uses old kernel. On [...]]]></description>
			<content:encoded><![CDATA[<div class="markdown-content">
<p><a href="http://webapp.org.ua/wp-content/uploads/2016/04/openwrt_logo_dir-320.jpg"><img src="http://webapp.org.ua/wp-content/uploads/2016/04/openwrt_logo_dir-320.jpg" alt="" title="openwrt_logo_dir-320" width="474" height="353" class="alignleft size-full wp-image-505"/></a></p>
<p>The goal of this article is to install latest OpenWRT firmware on a very popular DIR-320 Wi-Fi router (BRCM47XX based). The reason why you might do this is to be able to connect modern hardware(modems) to this pretty old legacy device.</p>
<p><a href="http://ftp.dlink.ru/pub/Router/DIR-320/Data_sh/RevA/Supported%203G%20modems.pdf">Official firmware 3G modem support list</a> is pretty limited and uses old kernel. On the other hand, there is an alternative <a href="http://www.dd-wrt.com/site/index">DD-WRT</a> firwmare with linux kernel 2.6.x which is pretty old also. Therefore, the only viable option is installing OpenWRT which ships the latest linux kernels 3.18.xx.</p>
<p>As a bonus sub-topic we&#8217;ll consider setting up an external CDMA(EVDO) modem and using it to access internet.</p>
</div>
<p><span id="more-492"></span></p>
<div class="markdown-content">
<p><br style="clear:left;"/><br />
In order to proceed and experiment by yourself the following is necessary:</p>
<ul>
<li><a href="https://wikidevi.com/wiki/D-Link_DIR-320_rev_A1">Dlink DIR-320 router</a> (<em>rev. A1/A2 only!</em>, be careful as there are B1/B2/NRU versions which are completely different hardware!)</li>
<li>RJ45 CAT5 Patch cable</li>
<li>USB to Serial adapter (I&#8217;ve been able to successfully use cheap <a href="http://www.ebay.com/sch/i.html?_nkw=Module+Converter+Serial+Adapter+Cable+For+Win+8+PL2303TA+USB+TTL+to+RS232">PL2303TA based USB TTL to RS232</a>)</li>
<li>USB flash card or hard drive</li>
<li>USB 3G modem (in my case it&#8217;s <a href="http://www.pcmag.com/article2/0,2817,2367921,00.asp">Sierra AirCard 250U</a>)</li>
<li>USB Hub (external power source is highly recommended)</li>
<li>x86_64 Linux host system (i&#8217;m using Ubuntu 15.10 x86_64)</li>
<li>a lot of patience :)</li>
</ul>
<h2>Install OpenWRT using Image builder for brcm47xx/legacy</h2>
<p>On your host linux system, download and unpack <a href="https://wiki.openwrt.org/doc/howto/obtain.firmware.generate">OpenWRT image builder</a> packages:</p>
<pre><code class="bash" title="">bananos@ubby:$ wget "https://downloads.openwrt.org/chaos_calmer/15.05.1/brcm47xx/legacy/OpenWrt-ImageBuilder-15.05.1-brcm47xx-legacy.Linux-x86_64.tar.bz2"
bananos@ubby:$ tar -xvvf "OpenWrt-ImageBuilder-15.05.1-brcm47xx-legacy.Linux-x86_64.tar.bz2"
</code></pre>
<p>After that, we&#8217;re going to assemble our custom firmware out of pre-built packages. Image builder was created specifically to overcome the slowness and complexity of compiling OpenWRT from sources.</p>
<pre><code class="bash" title="">bananos@ubby:$ sudo apt-get install -y subversion build-essential libncurses5-dev zlib1g-dev gawk git ccache gettext libssl-dev xsltproc
bananos@ubby:$ cd "OpenWrt-ImageBuilder-15.05.1-brcm47xx-legacy.Linux-x86_64"
bananos@ubby:$ make image PROFILE="Broadcom-b43" PACKAGES="base-files libc libgcc busybox kmod-usb2 kmod-usb-ohci kmod-usb-uhci kmod-usb-storage kmod-fs-ext4 block-mount kmod-scsi-core -dropbear mtd uci -opkg netifd fstools swconfig wpad-mini nvram -otrx kmod-leds-gpio kmod-gpio-button-hotplug kmod-ledtrig-default-on kmod-ledtrig-timer kmod-ledtrig-netdev dnsmasq iptables -ip6tables ppp ppp-mod-pppoe kmod-nf-nathelper firewall odhcpd odhcp6c"

make[1]: Entering directory '/home/bananos/Projects/openwrt_dir320/image_builder/OpenWrt-ImageBuilder-15.05.1-brcm47xx-legacy.Linux-x86_64'
echo 'Building images for brcm47xx - Broadcom SoC, all Ethernet, BCM43xx WiFi (b43, default)'
Building images for brcm47xx - Broadcom SoC, all Ethernet, BCM43xx WiFi (b43, default)
echo 'Packages: base-files block-mount busybox dnsmasq firewall fstools iptables kernel kmod-b43 kmod-b43legacy kmod-fs-ext4 kmod-gpio-button-hotplug kmod-leds-gpio kmod-ledtrig-default-on kmod-ledtrig-netdev kmod-ledtrig-timer kmod-nf-nathelper kmod-scsi-core kmod-usb-ohci kmod-usb-storage kmod-usb-uhci kmod-usb2 libc libgcc mtd netifd nvram odhcp6c odhcpd ppp ppp-mod-pppoe swconfig uci wpad-mini'
Packages: base-files block-mount busybox dnsmasq firewall fstools iptables kernel kmod-b43 kmod-b43legacy kmod-fs-ext4 kmod-gpio-button-hotplug kmod-leds-gpio kmod-ledtrig-default-on kmod-ledtrig-netdev kmod-ledtrig-timer kmod-nf-nathelper kmod-scsi-core kmod-usb-ohci kmod-usb-storage kmod-usb-uhci kmod-usb2 libc libgcc mtd netifd nvram odhcp6c odhcpd ppp ppp-mod-pppoe swconfig uci wpad-mini
echo

rm -rf /home/bananos/Projects/openwrt_dir320/image_builder/OpenWrt-ImageBuilder-15.05.1-brcm47xx-legacy.Linux-x86_64/build_dir/target-mipsel_mips32_uClibc-0.9.33.2/root-brcm47xx
.....

</code></pre>
<p>Note the <code>-</code> symbol before some of the packages, this means that those must be excluded from resulting build. As a result our target image will have almost nothing except external usb support and bare linux kernel. This is due to really tiny capacity of the internal router storage(4Mb). In order to increase it we&#8217;ll be using external USB storage(extroot) which is covered in detail in the next sections of this article.</p>
<p>Make sure you have active connection to internet as Image Builder will download some packages from the online repository. At the end of the build, you should be able to find a bunch of prepackaged firmwares in <code>bin/</code> directory:</p>
<pre><code class="bash" title="">bananos@ubby:$ ls bin/brcm47xx/ | grep "asus"

openwrt-15.05.1-brcm47xx-legacy-asus-wl-300g-squashfs.trx
openwrt-15.05.1-brcm47xx-legacy-asus-wl-320gp-squashfs.trx
openwrt-15.05.1-brcm47xx-legacy-asus-wl-330ge-squashfs.trx
openwrt-15.05.1-brcm47xx-legacy-asus-wl-500gp-v1-squashfs.trx
openwrt-15.05.1-brcm47xx-legacy-asus-wl-500gp-v2-squashfs.trx
openwrt-15.05.1-brcm47xx-legacy-asus-wl-500w-squashfs.trx
openwrt-15.05.1-brcm47xx-legacy-asus-wl-520gu-squashfs.trx
openwrt-15.05.1-brcm47xx-legacy-asus-wl-550ge-squashfs.trx
openwrt-15.05.1-brcm47xx-legacy-asus-wl-hdd25-squashfs.trx
</code></pre>
<p>Our file of interest is <code>openwrt-15.05.1-brcm47xx-legacy-asus-wl-500gp-v2-squashfs.trx</code> since Asus WL500gp-V2 uses the same hardware as Dlink DIR-320 Rev A.</p>
<h2>Firmware Flashing</h2>
<p>There are a lot of firmware flashing instructions on the net, but we&#8217;ll be using the <a href="https://wiki.openwrt.org/doc/howto/generic.flashing.tftp">most generic and reliable via TFTP</a>. Create the following bash file named <code>flash.sh</code>:</p>
<pre><code class="bash" title="">#!/bin/bash
echo "=================================================================="
echo "This script will upload dd-wrt firmware (firmware.bin)"
echo "in the current directory to 192.168.0.1 "
echo "during the router's bootup. "
echo ""
echo "* Set your ethernet card's settings to: "
echo "     IP:      192.168.0.10 "
echo "     Mask:    255.255.255.0 "
echo "     Gateway: 192.168.0.1 "
echo "* Unplug the router's power cable. "
echo ""
echo "Press Ctrl+C to abort or any other key to continue... "

read

echo ""
echo "* Re-plug the router's power cable. "
echo ""
echo "=================================================================="
echo "Waiting for the router... Press Ctrl+C to abort. "
echo ""

try(){
ping -c 1 -w 1 192.168.0.1
}
try

while [ "$?" != "0" ] ;
do
try
done
echo "*** Start Flashing **** "
atftp --no-source-port-checking -p -l firmware.bin 192.168.0.1
echo "Firmware successfully loaded!"
</code></pre>
<p>The script&#8217;s usage instructions are pretty self-explanatory, but before using it we must do a few more things:</p>
<pre><code class="bash" title="">bananos@ubby:$ chmod +x flash.sh
bananos@ubby:$ cp bin/brcm47xx/openwrt-15.05.1-brcm47xx-legacy-asus-wl-500gp-v2-squashfs.trx firmware.bin
bananos@ubby:$ sudo apt-get install -y atftp atftpd
</code></pre>
<p>Assuming that your USB-to-Serial adapter was detected as <code>/dev/ttyUSB0</code>, let&#8217;s open serial terminal to be able to observe what is happening on the router in real time:</p>
<pre><code class="bash" title="">bananos@ubby:$ sudo bash -c "screen /dev/ttyUSB0 115200"
</code></pre>
<p>Now, prepare your ethernet network card settings and</p>
<ul>
<li>plug port #1 of your router to linux machine</li>
<li>run <code>./flash.sh</code> and press any key to see a lot of <code>connect: Network is unreachable</code> messages</li>
<li>plug router power cable and wait for the flashing process to finish</li>
</ul>
<p>In the serial console you&#8217;ll notice something similar to this:</p>
<pre><code class="" title="">Decompressing...........done

CFE version 1.0.37 for BCM947XX (32bit,SP,LE)
Build Date: Thu Jul 19 10:53:24 CST 2007 (root@redhat9)
Copyright (C) 2000,2001,2002,2003 Broadcom Corporation.

Initializing Arena
Initializing Devices.
Boot partition size = 262144(0x40000)
et0: Broadcom BCM47xx 10/100 Mbps Ethernet Controller 4.150.3.0
CPU type 0x29029: 240MHz
Total memory: 32768 KBytes

Total memory used by CFE:  0x80300000 - 0x803C0720 (788256)
Initialized Data:          0x80337730 - 0x8033AE50 (14112)
BSS Area:                  0x8033AE50 - 0x8033C720 (6352)
Local Heap:                0x8033C720 - 0x803A0720 (409600)
Stack Area:                0x803A0720 - 0x803C0720 (131072)
Text (code) segment:       0x80300000 - 0x80337730 (227120)
Boot area (physical):      0x003C1000 - 0x00401000
Relocation Factor:         I:00000000 - D:00000000

alpha bootcode ver 0.1.2
cmd = ifconfig eth0 -addr=192.168.0.1 -mask=255.255.255.0
We disable the arp for self.
We disable the arp for self.
Device eth0:  hwaddr 00-90-4C-C0-00-01, ipaddr 192.168.0.1, mask 255.255.255.0
        gateway not set, nameserver not set
cmd = go;
cmd = load -raw -addr=0x803c0720 -max=0x3a0000 :
Loader:raw Filesys:tftp Dev:eth0 File:: Options:(null)
Loading: entry point=803C0720
........... 3674112 bytes read
Entry at 0x803c0720
cmd = flash -noheader -mem -size=0x381000 0x803c0720 flash1.trx
Reading from 0x803c0720: Programming...done. 3674112 bytes written
Dest=80001000, source =803c0720, filename=flash1.trx
cmd = boot -raw -z -addr=0x80001000 -max=0x3a0000 flash0.os:
Loader:raw Filesys:raw Dev:flash0.os File: Options:(null)
Loading: entry point=80001000
.. 3712 bytes read
Entry at 0x80001000
Closing network.
Starting program at 0x80001000
[    0.000000] Linux version 3.18.23 (buildbot@builder1) (gcc version 4.8.3 (OpenWrt/Linaro GCC 4.8-2014.04 r48532) ) #1 Tue Mar 1 09:18:44 CET 2016
[    0.000000] CPU0 revision is: 00029029 (Broadcom BMIPS3300)
[    0.000000] bcm47xx: Using ssb bus
[    0.000000] ssb: Found chip with id 0x5354, rev 0x03 and package 0x00
[    0.000000] can not parse nvram name (null)boardnum(null) with value  got -22
[    0.000000] can not parse nvram name (null)rxpo2g(null) with value 0xfff8 got -34
[    0.000000] ssb: Sonics Silicon Backplane found at address 0x18000000
[    0.000000] Determined physical RAM map:
[    0.000000]  memory: 02000000 @ 00000000 (usable)
[    0.000000] Initrd not found or empty - disabling initrd
[    0.000000] Zone ranges:
[    0.000000]   Normal   [mem 0x00000000-0x01ffffff]
[    0.000000] Movable zone start for each node
[    0.000000] Early memory node ranges
[    0.000000]   node   0: [mem 0x00000000-0x01ffffff]
[    0.000000] Initmem setup node 0 [mem 0x00000000-0x01ffffff]
[    0.000000] Primary instruction cache 16kB, VIPT, 4-way, linesize 16 bytes.
[    0.000000] Primary data cache 16kB, 2-way, VIPT, cache aliases, linesize 16 bytes
[    0.000000] Built 1 zonelists in Zone order, mobility grouping on.  Total pages: 8128
[    0.000000] Kernel command line:  noinitrd console=ttyS0,115200
[    0.000000] PID hash table entries: 128 (order: -3, 512 bytes)
[    0.000000] Dentry cache hash table entries: 4096 (order: 2, 16384 bytes)
[    0.000000] Inode-cache hash table entries: 2048 (order: 1, 8192 bytes)
[    0.000000] Memory: 28956K/32768K available (2605K kernel code, 103K rwdata, 316K rodata, 164K init, 267K bss, 3812K reserved)
[    0.000000] NR_IRQS:128
[    0.000000] MIPS: machine is Unknown Board
[    0.060000] Calibrating delay loop... 239.61 BogoMIPS (lpj=1198080)
[    0.070000] pid_max: default: 32768 minimum: 301
[    0.070000] Mount-cache hash table entries: 1024 (order: 0, 4096 bytes)
[    0.070000] Mountpoint-cache hash table entries: 1024 (order: 0, 4096 bytes)
[    0.080000] NET: Registered protocol family 16
[    0.100000] Switched to clocksource MIPS
[    0.110000] NET: Registered protocol family 2
[    0.110000] TCP established hash table entries: 1024 (order: 0, 4096 bytes)
[    0.110000] TCP bind hash table entries: 1024 (order: 0, 4096 bytes)
[    0.110000] TCP: Hash tables configured (established 1024 bind 1024)
[    0.110000] TCP: reno registered
[    0.110000] UDP hash table entries: 256 (order: 0, 4096 bytes)
[    0.110000] UDP-Lite hash table entries: 256 (order: 0, 4096 bytes)
[    0.110000] NET: Registered protocol family 1
[    0.110000] futex hash table entries: 256 (order: -1, 3072 bytes)
[    0.120000] squashfs: version 4.0 (2009/01/31) Phillip Lougher
[    0.120000] jffs2: version 2.2 (NAND) (SUMMARY) (LZMA) (RTIME) (CMODE_PRIORITY) (c) 2001-2006 Red Hat, Inc.
[    0.120000] msgmni has been set to 56
[    0.120000] io scheduler noop registered
[    0.120000] io scheduler deadline registered (default)
[    0.120000] Serial: 8250/16550 driver, 16 ports, IRQ sharing enabled
[    0.130000] console [ttyS0] disabled
[    0.150000] serial8250.0: ttyS0 at MMIO 0xb8000300 (irq = 3, base_baud = 1562500) is a U6_16550A
[    0.450000] console [ttyS0] enabled
[    0.470000] serial8250.0: ttyS1 at MMIO 0xb8000400 (irq = 3, base_baud = 1562500) is a U6_16550A
[    0.490000] physmap platform flash device: 02000001 at 1c000000
[    0.490000] physmap-flash.0: Found 1 x16 devices at 0x0 in 8-bit bank. Manufacturer ID 0x000001 Chip ID 0x0000f6
[    0.500000] Amd/Fujitsu Extended Query Table at 0x0040
[    0.510000]   Amd/Fujitsu Extended Query version 1.1.
[    0.510000] physmap-flash.0: Swapping erase regions for top-boot CFI table.
[    0.520000] number of CFI chips: 1
[    0.530000] 6 bcm47xxpart partitions found on MTD device physmap-flash.0
[    0.540000] Creating 6 MTD partitions on "physmap-flash.0":
[    0.540000] 0x000000000000-0x000000040000 : "boot"
[    0.550000] 0x000000040000-0x0000003f0000 : "firmware"
[    0.560000] 0x00000004001c-0x00000004090c : "loader"
[    0.570000] 0x00000004090c-0x000000146000 : "linux"
[    0.580000] 0x000000146000-0x0000003f0000 : "rootfs"
[    0.580000] mtd: device 4 (rootfs) set to be root filesystem
[    0.590000] 1 squashfs-split partitions found on MTD device rootfs
[    0.600000] 0x000000380000-0x0000003f0000 : "rootfs_data"
[    0.600000] 0x0000003f0000-0x000000400000 : "nvram"
[    0.710000] libphy: Fixed MDIO Bus: probed
[    0.710000] b44: Broadcom 44xx/47xx 10/100 PCI ethernet driver version 2.0
[    0.730000] libphy: b44_eth_mii: probed
[    0.850000] b53_common: found switch: BCM5325, rev 0
[    0.860000] b44 ssb0:0: attached PHY driver [Broadcom B53 (1)] (mii_bus:phy_addr=1:1e)
[    0.870000] b44 ssb0:0 eth0: Broadcom 44xx/47xx 10/100 PCI ethernet driver 00:90:4c:c0:00:01
[    0.880000] bcm47xx-wdt bcm47xx-wdt.0: BCM47xx Watchdog Timer enabled (30 seconds, Software Timer)
[    0.890000] GPIO_WDT: failed to register misc device
[    0.890000] TCP: cubic registered
[    0.890000] NET: Registered protocol family 17
[    0.900000] bridge: automatic filtering via arp/ip/ip6tables has been deprecated. Update your scripts to load br_netfilter if you need this.
[    0.910000] Bridge firewalling registered
[    0.920000] 8021q: 802.1Q VLAN Support v1.8
[    0.940000] VFS: Mounted root (squashfs filesystem) readonly on device 31:4.
[    0.950000] Freeing unused kernel memory: 164K (802f7000 - 80320000)
[    2.620000] init: Console is alive
[    2.630000] init: - watchdog -
[    5.430000] usbcore: registered new interface driver usbfs
[    5.430000] usbcore: registered new interface driver hub
[    5.440000] usbcore: registered new device driver usb
[    5.640000] SCSI subsystem initialized
[    5.670000] ehci_hcd: USB 2.0 'Enhanced' Host Controller (EHCI) Driver
[    5.680000] ehci-platform: EHCI generic platform driver
[    5.680000] ehci-platform ehci-platform.0: EHCI Host Controller
[    5.690000] ehci-platform ehci-platform.0: new USB bus registered, assigned bus number 1
[    5.700000] ehci-platform ehci-platform.0: irq 6, io mem 0x18003800
[    5.730000] ehci-platform ehci-platform.0: USB 2.0 started, EHCI 1.00
[    5.730000] hub 1-0:1.0: USB hub found
[    5.740000] hub 1-0:1.0: 2 ports detected
[    5.750000] ohci_hcd: USB 1.1 'Open' Host Controller (OHCI) Driver
[    5.760000] ohci-platform: OHCI generic platform driver
[    5.770000] ohci-platform ohci-platform.0: Generic Platform OHCI controller
[    5.780000] ohci-platform ohci-platform.0: new USB bus registered, assigned bus number 2
[    5.790000] ohci-platform ohci-platform.0: irq 6, io mem 0x18003000
[    5.850000] hub 2-0:1.0: USB hub found
[    5.860000] hub 2-0:1.0: 2 ports detected
[    5.870000] uhci_hcd: USB Universal Host Controller Interface driver
[    5.890000] usbcore: registered new interface driver usb-storage
[    6.680000] init: - preinit -
[    7.170000] b44 ssb0:0 eth0: Link is up at 100 Mbps, half duplex
[    7.180000] b44 ssb0:0 eth0: Flow control is off for TX and off for RX
[    7.460000] random: mktemp urandom read with 11 bits of entropy available
Press the [f] key and hit [enter] to enter failsafe mode
Press the [1], [2], [3] or [4] key and hit [enter] to select the debug level
[    8.980000] b44 ssb0:0 eth0: Link is Up - 100Mbps/Full - flow control off
[   11.010000] mount_root: loading kmods from internal overlay
[   11.380000] block: attempting to load /etc/config/fstab
[   11.390000] block: unable to load configuration (fstab: Entry not found)
[   11.400000] block: no usable configuration
[   11.400000] mount_root: jffs2 not ready yet, using temporary tmpfs overlay
[   11.460000] b44 ssb0:0 eth0: powering down PHY
[   11.490000] procd: - early -
[   11.500000] procd: - watchdog -
[   12.000000] b44 ssb0:0 eth0: Link is Down
[   12.410000] procd: - ubus -
[   13.430000] procd: - init -
Please press Enter to activate this console.
[   17.510000] NET: Registered protocol family 10
[   17.530000] Loading modules backported from Linux version master-2015-03-09-0-g141f155
[   17.540000] Backport generated by backports.git backports-20150129-0-gdd4a670
[   17.560000] nf_conntrack version 0.5.0 (455 buckets, 1820 max)
[   17.670000] xt_time: kernel timezone is -0000
[   17.730000] cfg80211: Calling CRDA to update world regulatory domain
[   17.740000] ip_tables: (C) 2000-2006 Netfilter Core Team
[   17.770000] cfg80211: World regulatory domain updated:
[   17.770000] cfg80211:  DFS Master region: unset
[   17.780000] cfg80211:   (start_freq - end_freq @ bandwidth), (max_antenna_gain, max_eirp), (dfs_cac_time)
[   17.790000] cfg80211:   (2402000 KHz - 2472000 KHz @ 40000 KHz), (N/A, 2000 mBm), (N/A)
[   17.800000] cfg80211:   (2457000 KHz - 2482000 KHz @ 20000 KHz, 92000 KHz AUTO), (N/A, 2000 mBm), (N/A)
[   17.810000] cfg80211:   (2474000 KHz - 2494000 KHz @ 20000 KHz), (N/A, 2000 mBm), (N/A)
[   17.820000] cfg80211:   (5170000 KHz - 5250000 KHz @ 80000 KHz, 160000 KHz AUTO), (N/A, 2000 mBm), (N/A)
[   17.830000] cfg80211:   (5250000 KHz - 5330000 KHz @ 80000 KHz, 160000 KHz AUTO), (N/A, 2000 mBm), (0 s)
[   17.840000] cfg80211:   (5490000 KHz - 5730000 KHz @ 160000 KHz), (N/A, 2000 mBm), (0 s)
[   17.840000] cfg80211:   (5735000 KHz - 5835000 KHz @ 80000 KHz), (N/A, 2000 mBm), (N/A)
[   17.850000] cfg80211:   (57240000 KHz - 63720000 KHz @ 2160000 KHz), (N/A, 0 mBm), (N/A)
[   18.230000] PPP generic driver version 2.4.2
[   18.240000] NET: Registered protocol family 24
[   18.410000] b43-phy0: Broadcom 5354 WLAN found (core revision 13)
[   18.440000] b43-phy0: Found PHY: Analog 6, Type 5 (LP), Revision 0
[   18.450000] b43-phy0: Found Radio: Manuf 0x17F, ID 0x2062, Revision 1, Version 0
[   18.470000] Broadcom 43xx driver loaded [ Features: PNL ]
[   18.550000] Broadcom 43xx-legacy driver loaded [ Features: PLD ]
[   26.610000] b44 ssb0:0 eth0: Link is up at 100 Mbps, full duplex
[   26.610000] b44 ssb0:0 eth0: Flow control is off for TX and off for RX
[   28.030000] b44 ssb0:0 eth0: Link is Up - 100Mbps/Full - flow control off
[   31.430000] jffs2_scan_eraseblock(): End of filesystem marker found at 0x0
[   31.450000] jffs2_build_filesystem(): unlocking the mtd device... done.
[   31.450000] jffs2_build_filesystem(): erasing all blocks after the end marker... ^[[A^[[A
[   34.450000] b44 ssb0:0 eth0: powering down PHY
[   34.530000] b44 ssb0:0 eth0: Link is up at 100 Mbps, full duplex
[   34.540000] b44 ssb0:0 eth0: Flow control is off for TX and off for RX
[   34.580000] device eth0.1 entered promiscuous mode
[   34.580000] device eth0 entered promiscuous mode
[   34.600000] br-lan: port 1(eth0.1) entered forwarding state
[   34.610000] br-lan: port 1(eth0.1) entered forwarding state
[   35.830000] done.
[   35.830000] jffs2: notice: (845) jffs2_build_xattr_subsystem: complete building xattr subsystem, 0 of xdatum (0 unchecked, 0 orphan) and 0 of xref (0 dead, 0 orphan) found.
[   36.610000] br-lan: port 1(eth0.1) entered forwarding state
[   80.480000] random: nonblocking pool is initialized

BusyBox v1.23.2 (2016-03-01 08:53:11 CET) built-in shell (ash)

  _______                     ________        __
 |       |.-----.-----.-----.|  |  |  |.----.|  |_
 |   -   ||  _  |  -__|     ||  |  |  ||   _||   _|
 |_______||   __|_____|__|__||________||__|  |____|
          |__| W I R E L E S S   F R E E D O M
 -----------------------------------------------------
 CHAOS CALMER (15.05.1, r48532)
 -----------------------------------------------------
  * 1 1/2 oz Gin            Shake with a glassful
  * 1/4 oz Triple Sec       of broken ice and pour
  * 3/4 oz Lime Juice       unstrained into a goblet.
  * 1 1/2 oz Orange Juice
  * 1 tsp. Grenadine Syrup
 -----------------------------------------------------
root@OpenWrt:/#

</code></pre>
<p>After successful flash procedure, reboot your router by powering it off and setting your ethernet network card back to DHCP (that&#8217;s necessary because the default router DHCP server assigns addresses in <code>192.168.1.XXX</code> subnet, which is different from <code>192.168.0.XXX</code> which we used for flashing purposes)</p>
<p>Turn on the device once again and wait until wired connection with your host system establishes. After that, you may happily telnet into the router:</p>
<pre><code class="bash" title="">bananos@ubby:$ telnet 192.168.1.1
Trying 192.168.1.1...
Connected to 192.168.1.1.
Escape character is '^]'.
 === IMPORTANT ============================
  Use 'passwd' to set your login password
  this will disable telnet and enable SSH
 ------------------------------------------

BusyBox v1.23.2 (2016-03-01 08:53:11 CET) built-in shell (ash)

.....
</code></pre>
<p>Congrats! The first, most important step is completed. In the next section we&#8217;ll configure <a href="https://wiki.openwrt.org/doc/howto/extroot">extroot</a> to be able to install additional OpenWrt packages such as LuCI and various kernel modules.</p>
<h2>Setting up extroot</h2>
<p>Connect your USB drive to linux host system. The first thing we&#8217;re going to do is partitioning. Assuming that your newly inserted disk is <code>/dev/sdb</code> I would suggest somewhat similar to this:</p>
<pre><code class="bash" title="">bananos@ubby:$ sudo fdisk -l /dev/sdb
Disk /dev/sdb: 28 GiB, 30005821440 bytes, 58605120 sectors
Units: sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disklabel type: dos
Disk identifier: 0xa58948b4

Device     Boot   Start      End  Sectors   Size Id Type
/dev/sdb1            63  2008124  2008062 980.5M 82 Linux swap / Solaris
/dev/sdb2       2008125  6024374  4016250   1.9G 83 Linux
/dev/sdb3       6024375 58605119 52580745  25.1G 83 Linux
</code></pre>
<p>In my case, I&#8217;m using 1.8 inch TOSHIBA MK3008GAL hard drive. To make partitioning table similar to above mentioned you may use GUI tool called <code>GParted</code> or use plain <code>fdisk</code>. Primary partition usage is as follows:</p>
<ul>
<li><code>/dev/sdb1</code> is for swapping purposes due to a low (32Mb) amount of RAM</li>
<li><code>/dev/sdb2</code> is for root filesystem (rootfs <code>/</code>)</li>
<li><code>/dev/sdb3</code> is for home directory (<code>/home</code>)</li>
</ul>
<p>After partitioning, format <code>rootfs</code> and <code>/home</code> into ext4 filesystems:</p>
<pre><code class="" title="">bananos@ubby:$ sudo umount /dev/sdb2
bananos@ubby:$ sudo mkfs.ext4 /dev/sdb2
mke2fs 1.42.12 (29-Aug-2014)
Creating filesystem with 502031 4k blocks and 125696 inodes
Filesystem UUID: 69b17872-9486-4113-8d9f-59a5e4221027
Superblock backups stored on blocks:
    32768, 98304, 163840, 229376, 294912

Allocating group tables: done
Writing inode tables: done
Creating journal (8192 blocks): done
Writing superblocks and filesystem accounting information: done

bananos@ubby:$ sudo umount /dev/sdb3
bananos@ubby:$ sudo mkfs.ext4 /dev/sdb3

....

bananos@ubby:$ sudo mkswap /dev/sdb1
Setting up swapspace version 1, size = 980.5 MiB (1028120576 bytes)
no label, UUID=457a57b6-aae0-410a-8832-4e182e15e04b

</code></pre>
<p>Now, connect USB drive to your router, turn it on, and telnet once again:</p>
<pre><code class="bash" title="">root@OpenWrt:/# logread | grep "sda"
Tue Mar  1 08:15:13 2016 kern.notice kernel: [    7.290000] sd 0:0:0:0: [sda] 58605120 512-byte logical blocks: (30.0 GB/27.9 GiB)
Tue Mar  1 08:15:13 2016 kern.notice kernel: [    7.320000] sd 0:0:0:0: [sda] Write Protect is off
Tue Mar  1 08:15:13 2016 kern.debug kernel: [    7.320000] sd 0:0:0:0: [sda] Mode Sense: 03 00 00 00
Tue Mar  1 08:15:13 2016 kern.err kernel: [    7.330000] sd 0:0:0:0: [sda] No Caching mode page found
Tue Mar  1 08:15:13 2016 kern.err kernel: [    7.330000] sd 0:0:0:0: [sda] Assuming drive cache: write through
Tue Mar  1 08:15:13 2016 kern.info kernel: [    7.400000]  sda: sda1 sda2 sda3
Tue Mar  1 08:15:13 2016 kern.notice kernel: [    7.440000] sd 0:0:0:0: [sda] Attached SCSI disk
</code></pre>
<p>We&#8217;ve just used <code>logread</code> to make sure that hard drive was successfully detected by kernel. Now, let&#8217;s proceed to creating external rootfs:</p>
<pre><code class="bash" title="">root@OpenWrt:/# ls -l /dev/sda
brw-r--r--    1 root     root        8,   0 Jan  1  1970 /dev/sda
root@OpenWrt:/# block detect
config 'global'
        option  anon_swap       '0'
        option  anon_mount      '0'
        option  auto_swap       '1'
        option  auto_mount      '1'
        option  delay_root      '5'
        option  check_fs        '0'

config 'swap'
        option  uuid    '457a57b6-aae0-410a-8832-4e182e15e04b'
        option  enabled '0'

config 'mount'
        option  target  '/mnt/sda2'
        option  uuid    '69b17872-9486-4113-8d9f-59a5e4221027'
        option  enabled '0'

config 'mount'
        option  target  '/mnt/sda3'
        option  uuid    '37582519-c560-45d3-9a4e-9a95d255b33a'
        option  enabled '0'
</code></pre>
<p>We&#8217;ve just seen that usb hard drive is present at <code>/dev/sda</code> and has 3 partitions. Next, we&#8217;ll create a so-called <a href="https://wiki.openwrt.org/doc/howto/extroot/extroot.theory">pivot-overlay</a>:</p>
<pre><code class="bash" title="">root@OpenWrt:/# mount /dev/sda2 /mnt ; tar -C /overlay -cvf - . | tar -C /mnt -xf - ; umount /mnt
./
./.fs_state
./work/
./work/work/
./upper/
./upper/etc/
./upper/etc/uci-defaults/
./upper/etc/uci-defaults/11_migrate-sysctl
./upper/etc/uci-defaults/03_network_migration
./upper/etc/uci-defaults/odhcpd.defaults
./upper/etc/uci-defaults/10_migrate-shadow
./upper/etc/uci-defaults/10-fstab
./upper/etc/uci-defaults/12_network-generate-ula
./upper/etc/uci-defaults/09_fix_crc
./upper/etc/config/
./upper/etc/config/dhcp
./upper/etc/config/fstab
./upper/etc/config/firewall
./upper/etc/config/network
./upper/etc/config/system
./upper/etc/config/wireless
./upper/etc/ethers
./upper/etc/dnsmasq.time
</code></pre>
<p>The above mentioned command will mount <code>/dev/sda2</code> as <code>/mnt</code>, then will copy everything from <code>/overlay</code> to <code>/mnt</code> and unmount partition. Now, create <code>fstab</code> template:</p>
<pre><code class="bash" title="">root@OpenWrt:/# block detect &gt; /etc/config/fstab ; vi /etc/config/fstab
</code></pre>
<p>After editing your <code>fstab</code> file it should look like following:</p>
<pre><code class="" title="">config 'global'
        option  anon_swap       '0'
        option  anon_mount      '0'
        option  auto_swap       '1'
        option  auto_mount      '1'
        option  delay_root      '5'
        option  check_fs        '1'

config 'swap'
        option  enabled '1'
        option  device '/dev/sda1'

config 'mount'
        option  target  '/overlay'
        option  enabled '1'
        option  device  '/dev/sda2'
        option  fstype  'ext4'
        option  options 'rw,relatime,data=ordered,async,errors=remount-ro'
        option  enabled_fsck '1'

config 'mount'
        option  target  '/home'
        option  enabled '1'
        option  device '/dev/sda3'
        option  fstype  'ext4'
        option  options 'rw,relatime,data=ordered,async,errors=remount-ro'
        option  enabled_fsck '1'
</code></pre>
<p>Don&#8217;t forget to create <code>/home</code> directory by entering <code>mkdir -p /home</code>! Now, reboot your router and check that everything was mounted correctly:</p>
<pre><code class="bash" title="">root@OpenWrt:/# df -h
Filesystem                Size      Used Available Use% Mounted on
rootfs                    1.9G      2.9M      1.7G   0% /
/dev/root                 2.3M      2.3M         0 100% /rom
tmpfs                    14.2M     44.0K     14.2M   0% /tmp
/dev/sda2                 1.9G      2.9M      1.7G   0% /overlay
overlayfs:/overlay        1.9G      2.9M      1.7G   0% /
tmpfs                   512.0K         0    512.0K   0% /dev
/dev/sda3                24.6G     43.9M     23.2G   0% /home

root@OpenWrt:/# swapon -s
Filename                                Type            Size    Used    Priority
/dev/sda1                               partition       1004024 0       -1
</code></pre>
<p>We can see here, that rootfs(<code>/</code>) partition now has 1.7G of free space, and there&#8217;s almost 998M of swap. That&#8217;s it! External root filesystem is ready to use. In the next step, we&#8217;ll install <code>opkg</code> package manager, to be able to do something useful with our fresh linux system.</p>
<h2>Installation of package manager (opkg)</h2>
<p>A bare linux system is of no use if we&#8217;re not able to install additional software. That&#8217;s what we&#8217;ll accomplish in this section. Since we don&#8217;t have access to internet(yet) from the router itself, we&#8217;ll download <code>opkg</code> binary package manually and install it on the working system.</p>
<p>As an additional option you may consider downloading all of the OpenWRT binary packages to newly prepared usb drive if you have plenty of free space. That&#8217;s very useful if there will be no access to internet from the router itself during spontaneous connection failures or maintenance periods.</p>
<p>Re-attach hard drive to linux host system and assuming that<br />
<code>/media/bananos/69b17872-9486-4113-8d9f-59a5e4221027</code> is your <code>/home</code> directory mentioned above, download all packages:</p>
<pre><code class="bash" title="">root@ubby:$ cd `/media/bananos/69b17872-9486-4113-8d9f-59a5e4221027` &amp;&amp; mkdir repo &amp;&amp; cd repo
root@ubby:$ wget -r --no-parent --reject "index.html*" "https://downloads.openwrt.org/chaos_calmer/15.05.1/brcm47xx/legacy/packages/"
......

FINISHED --2016-03-31 16:48:54--
Total wall clock time: 7m 23s
Downloaded: 4508 files, 307M in 2m 9s (2.39 MB/s)
</code></pre>
<p>This will download all packages from <code>https://downloads.openwrt.org/chaos_calmer/15.05.1/brcm47xx/legacy/packages/</code> preserving directory structure. Let&#8217;s make it more clean:</p>
<pre><code class="bash" title="">root@ubby:$ mv downloads.openwrt.org/chaos_calmer/15.05.1/brcm47xx/legacy/packages/* .
root@ubby:$ rm -rf downloads.openwrt.org/
root@ubby:# ls
base luci  management  packages  routing  telephony
</code></pre>
<p>Now, let&#8217;s install <a href="https://wiki.openwrt.org/doc/techref/opkg">opkg</a> manager by copying corresponding package to rootfs:</p>
<pre><code class="bash" title="">root@ubby:$ cp base/opkg_9c97d5ecd795709c8584e972bfdf3aee3a5b846d-9_brcm47xx.ipk /media/bananos/37582519-c560-45d3-9a4e-9a95d255b33a/opkg.ipk
root@ubby:$ cd /media/bananos/37582519-c560-45d3-9a4e-9a95d255b33a/

root@ubby:$ 7z x opkg.ipk

7-Zip [64] 9.20  Copyright (c) 1999-2010 Igor Pavlov  2010-11-18
p7zip Version 9.20 (locale=en_US.UTF-8,Utf16=on,HugeFiles=on,2 CPUs)

Processing archive: opkg.ipk
Extracting  opkg
Everything is Ok
Size:       71680
Compressed: 64546

root@ubby:$ tar -xvf opkg
./debian-binary
./data.tar.gz
./control.tar.gz

root@ubby:$ rm control.tar.gz opkg.ipg debian-binary rm opkg
</code></pre>
<p>Unplug USB-hdd from host system and replug it back to router, run <code>telnet</code> and check that <code>data.tar.gz</code> is at <code>/overlay</code>:</p>
<pre><code class="bash" title="">root@OpenWrt:/# ls /overlay/
data.tar.gz  etc          lost+found   upper        work
root@OpenWrt:/# mv /overlay/data.tar.gz /
root@OpenWrt:/# tar -xzvf data.tar.gz
./
./lib/
./lib/upgrade/
./lib/upgrade/keep.d/
./lib/upgrade/keep.d/opkg
./bin/
./bin/opkg
./usr/
./usr/lib/
./usr/lib/opkg/
./usr/sbin/
./usr/sbin/opkg-key
./etc/
./etc/uci-defaults/
./etc/uci-defaults/20_migrate-feeds
./etc/opkg/
./etc/opkg/customfeeds.conf
./etc/opkg/distfeeds.conf
./etc/opkg.conf
</code></pre>
<p>If everything was correct and you extracted tar package directly to <code>/</code> then it is possible to run <code>opkg</code> itself:</p>
<pre><code class="bash" title="">root@OpenWrt:/# opkg --version
opkg version 0.1.8
</code></pre>
<p>Now, if you have working internet connection it is possible to install additional OpenWRT packages like LuCI, but we&#8217;re going to leverage our offline repo we&#8217;ve created above. Open <code>/etc/opkg/distfeeds.conf</code> and create following file contents:</p>
<pre><code class="" title="">#src/gz chaos_calmer_base http://downloads.openwrt.org/chaos_calmer/15.05.1/brcm47xx/legacy/packages/base
#src/gz chaos_calmer_luci http://downloads.openwrt.org/chaos_calmer/15.05.1/brcm47xx/legacy/packages/luci
#src/gz chaos_calmer_packages http://downloads.openwrt.org/chaos_calmer/15.05.1/brcm47xx/legacy/packages/packages
#src/gz chaos_calmer_routing http://downloads.openwrt.org/chaos_calmer/15.05.1/brcm47xx/legacy/packages/routing
#src/gz chaos_calmer_telephony http://downloads.openwrt.org/chaos_calmer/15.05.1/brcm47xx/legacy/packages/telephony
#src/gz chaos_calmer_management http://downloads.openwrt.org/chaos_calmer/15.05.1/brcm47xx/legacy/packages/management

src/gz chaos_calmer_base file:///home/repo/base
src/gz chaos_calmer_luci file:///home/repo/luci
src/gz chaos_calmer_packages file:///home/repo/packages
src/gz chaos_calmer_routing file:///home/repo/routing
src/gz chaos_calmer_telephony file:///home/repo/telephony
src/gz chaos_calmer_management file:///home/repo/management
</code></pre>
<p>run update procedure:</p>
<pre><code class="bash" title="">root@OpenWrt:/# opkg update
Downloading file:///home/repo/base/Packages.gz.
Updated list of available packages in /var/opkg-lists/chaos_calmer_base.
Downloading file:///home/repo/base/Packages.sig.
Signature check passed.
Downloading file:///home/repo/luci/Packages.gz.
Updated list of available packages in /var/opkg-lists/chaos_calmer_luci.
Downloading file:///home/repo/luci/Packages.sig.
Signature check passed.
Downloading file:///home/repo/packages/Packages.gz.
Updated list of available packages in /var/opkg-lists/chaos_calmer_packages.
Downloading file:///home/repo/packages/Packages.sig.
Signature check passed.
Downloading file:///home/repo/routing/Packages.gz.
Updated list of available packages in /var/opkg-lists/chaos_calmer_routing.
Downloading file:///home/repo/routing/Packages.sig.
Signature check passed.
Downloading file:///home/repo/telephony/Packages.gz.
Updated list of available packages in /var/opkg-lists/chaos_calmer_telephony.
Downloading file:///home/repo/telephony/Packages.sig.
Signature check passed.
Downloading file:///home/repo/management/Packages.gz.
Updated list of available packages in /var/opkg-lists/chaos_calmer_management.
Downloading file:///home/repo/management/Packages.sig.
Signature check passed.
</code></pre>
<p>Now, it is possible to install any additional software we like. For example, let&#8217;s install <code>nano</code> text editor:</p>
<pre><code class="bash" title="">root@OpenWrt:/# opkg install nano
Installing nano (2.4.1-1) to root...
Downloading file:///home/repo/packages/nano_2.4.1-1_brcm47xx.ipk.
Installing libncurses (5.9-2) to root...
Downloading file:///home/repo/base/libncurses_5.9-2_brcm47xx.ipk.
Installing terminfo (5.9-2) to root...
Downloading file:///home/repo/base/terminfo_5.9-2_brcm47xx.ipk.
Configuring terminfo.
Configuring libncurses.
Configuring nano.
</code></pre>
<h2>Make sure internet works</h2>
<p>If you have access to an internet via LAN cable (i.e. you do have another router running DHCP in your network with internet access), plug your DIR-320 WAN port into your network. Make sure, it gets dynamic IP:</p>
<pre><code class="bash" title="">root@OpenWrt:/# ifconfig

br-lan    Link encap:Ethernet  HWaddr 00:90:4C:C0:00:01
          inet addr:192.168.1.1  Bcast:192.168.1.255  Mask:255.255.255.0
          inet6 addr: fd47:5a3c:26b2::1/60 Scope:Global
          inet6 addr: fe80::290:4cff:fec0:1/64 Scope:Link
          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
          RX packets:0 errors:0 dropped:0 overruns:0 frame:0
          TX packets:37 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:0
          RX bytes:0 (0.0 B)  TX bytes:3926 (3.8 KiB)

eth0.2    Link encap:Ethernet  HWaddr 00:90:4C:C0:00:01
          inet addr:192.168.0.194  Bcast:192.168.0.255  Mask:255.255.255.0
          inet6 addr: fe80::290:4cff:fec0:1/64 Scope:Link
          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
          RX packets:223 errors:0 dropped:0 overruns:0 frame:0
          TX packets:104 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:0
          RX bytes:50169 (48.9 KiB)  TX bytes:9778 (9.5 KiB)
</code></pre>
<p>Make sure that your existing network uses different subnet. By default, OpenWRT is configured to use <code>192.168.1.X</code> subnet, so you should use something like <code>192.168.0.X</code> or <code>192.168.2.X</code>. Verify that you&#8217;re able to download content from the internet:</p>
<pre><code class="bash" title="">root@OpenWrt:/# wget http://httpbin.org/ip -O /dev/null
Connecting to httpbin.org (54.175.219.8:80)
null                 100% |*******************************|    32   0:00:00 ETA
</code></pre>
<p>If you&#8217;re not able to get any content outside your network, it is most likely a problem with firewall. One of the symptoms of this problem is that when you issue <code>ping</code> command, there will be following output <code>ping: sendmsg: Operation not permitted</code>.</p>
<p>To allow all traffic in any direction(don&#8217;t do this in production environment!), do the following:</p>
<pre><code class="bash" title="">root@OpenWrt:/# echo "iptables -P INPUT ACCEPT" &gt;&gt; /etc/firewall.user
root@OpenWrt:/# echo "iptables -P OUTPUT ACCEPT" &gt;&gt; /etc/firewall.user
root@OpenWrt:/# echo "iptables -P FORWARD ACCEPT" &gt;&gt; /etc/firewall.user
root@OpenWrt:/# /etc/init.d/firewall restart
</code></pre>
<h2>LuCI installation</h2>
<p><a href="https://wiki.openwrt.org/doc/techref/luci">LuCI</a> is a web-based GUI for managing OpenWRT. A lot of essential configuration which is pretty cumbersome to do via command-line could be easily made through LuCI.</p>
<p>Before installing LuCI packages I would strongly suggest setting up <code>kmod-zram</code> and <code>zram-swap</code> packages if you&#8217;re not using external HDD swap, but instead rely on slow, error-prone flash memory. <a href="https://en.wikipedia.org/wiki/Zram">Zram</a> is a special linux kernel module which makes part of your RAM compressed and behave like swap.</p>
<p>Now, let&#8217;s proceed:</p>
<pre><code class="bash" title="">root@OpenWrt:/# opkg update &amp;&amp; opkg install --force-overwrite wget ca-certificates coreutils dropbear
root@OpenWrt:/# opkg install ip fdisk usbutils screen htop
root@OpenWrt:/# opkg install luci luci-proto-3g luci-proto-ipv6 luci-proto-openconnect luci-proto-ppp luci-proto-relay
</code></pre>
<p>After successfull installation of the above mentioned packages, reboot and plug your linux host into one of the 4 LAN ports of the router. Since LuCI is not yet configured, it is not possible to access it via WAN, therefore we&#8217;re going to setup it from the internal router network. Open up your favorite browser and go to <code>http://192.168.1.1/cgi-bin/luci</code></p>
<p><a href="http://webapp.org.ua/wp-content/uploads/2016/04/openwrt_luci_login_page.png"><img src="http://webapp.org.ua/wp-content/uploads/2016/04/openwrt_luci_login_page.png" alt="" title="openwrt_luci_login_page" width="703" height="547" class="aligncenter size-full wp-image-510" /></a></p>
<p>From now on, you may fully configure your router by setting up root password, enabling Wi-Fi, etc.</p>
<h2>3g/CDMA modem configuration</h2>
<p>Now, the most interesting part &#8212; how do we connect external CDMA modem to the router and make sure it will function as a WAN interface for LAN clients? At the time of this writing, I had in my hands a used <a href="http://www.amazon.com/Sierra-Wireless-Aircard-250U4G-Silver/dp/B009ZY10GK">Sierra AirCard 250U</a>:</p>
<p><a href="http://webapp.org.ua/wp-content/uploads/2016/04/openwrt_sierra_wireless_250u.jpg"><img src="http://webapp.org.ua/wp-content/uploads/2016/04/openwrt_sierra_wireless_250u.jpg" alt="" title="openwrt_sierra_wireless_250u" width="457" height="329" class="aligncenter size-full wp-image-512" /></a></p>
<p>In this part of the article, we&#8217;re going to setup it to act as an external WAN interface. First off, disconnect ethernet cable from router&#8217;s WAN port and connect modem. Make sure you&#8217;re using USB-hub with external power supply, since 3G modems may drain a lot of current from single USB port and you might experience a lot of weird issues.</p>
<p>Open up terminal console using <code>ssh</code> (telnet should be already disabled if you&#8217;ve configured router&#8217;s root password):</p>
<pre><code class="bash" title="">bananos@ubby:$ ssh  root@192.168.1.1
Warning: Permanently added '192.168.1.1' (RSA) to the list of known hosts.
root@192.168.1.1's password:
</code></pre>
<p>When CDMA modem is powered on, it is possible to see it in the list of connected usb devices:</p>
<pre><code class="bash" title="">root@OpenWrt:~# lsusb
Bus 001 Device 007: ID 1199:0301 Sierra Wireless, Inc.
Bus 001 Device 008: ID 198f:0220 Beceem Communications Inc. BCSM250 WiMAX Adapter
Bus 001 Device 004: ID 0424:2512 Standard Microsystems Corp. USB 2.0 Hub
Bus 001 Device 003: ID 05ac:0221 Apple, Inc. Aluminum Keyboard (ISO)
Bus 001 Device 005: ID 067b:2506 Prolific Technology, Inc. Kaser 8gB micro hard drive
Bus 002 Device 001: ID 1d6b:0001 Linux Foundation 1.1 root hub
Bus 001 Device 002: ID 05ac:1006 Apple, Inc. Hub in Aluminum Keyboard
Bus 001 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub
</code></pre>
<p>In this example I&#8217;m using Apple Keyboard as USB hub :)  Aricard 250U may actually work in CDMA/WiMax mode, and is detected as two separate devices <code>Sierra Wireless, Inc.</code> and <code>Beceem Communications Inc. BCSM250 WiMAX Adapter</code>. Now, let&#8217;s search for Sierra support in software packages:</p>
<pre><code class="bash" title="">root@OpenWrt:~# opkg update
root@OpenWrt:~# opkg list | grep sierra
kmod-usb-net-sierrawireless - 3.18.23-1 - Kernel support for Sierra Wireless devices
kmod-usb-serial-sierrawireless - 3.18.23-1 - Kernel support for Sierra Wireless devices
</code></pre>
<p>Luckily, there is kernel support for Sierra devices and we&#8217;re going to leverage that! This is exactly the case where modern linux kernel shines in all its beauty. On top of this kernel modules we need to install some other generic stuff:</p>
<pre><code class="bash" title="">root@OpenWrt:~# opkg install kmod-usb-serial kmod-usb-serial-option kmod-usb-serial-wwan kmod-usb-serial-ipw
root@OpenWrt:~# opkg install comgt usb-modeswitch coreutils-stty
root@OpenWrt:~# opkg install kmod-usb-net-sierrawireless kmod-usb-serial-sierrawireless
root@OpenWrt:~# reboot
</code></pre>
<p>Make sure that sierra kernel support is functioning:</p>
<pre><code class="bash" title="">root@OpenWrt:~# lsmod | grep sierra
sierra                  6048  0
sierra_net              5600  0
usbnet                 15872  1 sierra_net
</code></pre>
<p>As this point, we have a serial interface to CDMA modem at <code>/dev/ttyUSB0</code>. Verify that modem responds to AT commands:</p>
<pre><code class="" title="">root@OpenWrt:~# gcom info -d /dev/ttyUSB0
##### Wireless WAN Modem Configuration #####
Product text:
====

Manufacturer: Sierra Wireless, Inc.
Model: AC250U Rev 2.0 (3)
Revision: p3012901,8815 [May 28 2010 14:42:39]
QCOM: SWI6085_FP.01.28
BOOT: SWI6085_PP.01.29.01 2010/05/28 18:13:46
APPL: SWI6085_PP.01.29.01 2010/05/28 18:13:46
USB VID: 0x1199 PID: 0x0301
ESN: 09612160827
0x60B98F3B
+GCAP: +CIS707-A, CIS-856, CIS-856-A, +MS, +ES, +DS, +FCLASS
SKU: 0x132BD1
OK
====
Manufacturer:           ERROR
IMEI and Serial Number: 09612160827
Manufacturer's Revision:
p3012901,8815 [May 28 2010 14:42:3
Hardware Revision:

Network Locked:

Customisation:

Band settings:          (
)
APN:

##### END #####
</code></pre>
<p>Now, switch to LuCI and go to <code>Network-&gt;Interfaces</code>. Stop <code>WAN6</code> unless you're going to use IPv6 and edit <code>WAN</code> interface.</p>
<p><a href="http://webapp.org.ua/wp-content/uploads/2016/04/openwrt_add_new_3g_wan.png"><img src="http://webapp.org.ua/wp-content/uploads/2016/04/openwrt_add_new_3g_wan.png" alt="" title="openwrt_add_new_3g_wan"  width="900" class="aligncenter size-full wp-image-514" /></a></p>
<p>When editing existing <code>WAN</code> interface, change <code>Protocol</code> to <code>UMTS/GPRS/EV-DO</code>, click <code>Switch protocol</code> button and wait for additional parameters to appear:</p>
<p><a href="http://webapp.org.ua/wp-content/uploads/2016/04/openwrt_cdma_connection_params.png"><img src="http://webapp.org.ua/wp-content/uploads/2016/04/openwrt_cdma_connection_params.png" alt="" title="openwrt_cdma_connection_params" width="649" height="711" class="aligncenter size-full wp-image-513" /></a></p>
<p>On this screen you should enter provider specific info (take a look at your contract/prepaid plan details). Since my modem is connected to <a href="http://intertelecom.ua">Ukraine's CDMA Intertelecom</a> my connection parameters are:</p>
<ul>
<li><code>Protocol</code>: UMTS/GPRS/EV-DO</li>
<li><code>Modem device</code>: /dev/ttyUSB0 (we've tested above that it actually responds to AT commands)</li>
<li><code>Service type</code>: CDMA/EV-DO</li>
<li><code>APN</code>: empty</li>
<li><code>PIN</code>: empty</li>
<li><code>PAP/CHAP username</code>: IT</li>
<li><code>PAP/CHAP password</code>: IT</li>
<li><code>Dial number</code>: #777</li>
</ul>
<p>Note, that your interface will now be named <code>3g-wan</code> and since there is a flag called <code>Bring up on boot</code> in the <code>Advanced tab</code> your CDMA connection will be established automatically on power up. To make sure that everything works, open up terminal once again:</p>
<pre><code class="bash" title="">root@OpenWrt:~# logread | grep -E "chat|ppp"
Tue Apr  5 19:38:31 2016 daemon.notice pppd[6810]: pppd 2.4.7 started by root, uid 0
Tue Apr  5 19:38:32 2016 local2.info chat[6821]: abort on (BUSY)
Tue Apr  5 19:38:32 2016 local2.info chat[6821]: abort on (NO CARRIER)
Tue Apr  5 19:38:32 2016 local2.info chat[6821]: abort on (ERROR)
Tue Apr  5 19:38:32 2016 local2.info chat[6821]: abort on (NO DIAL TONE)
Tue Apr  5 19:38:32 2016 local2.info chat[6821]: abort on (NO ANSWER)
Tue Apr  5 19:38:32 2016 local2.info chat[6821]: abort on (DELAYED)
Tue Apr  5 19:38:32 2016 local2.info chat[6821]: report (CONNECT)
Tue Apr  5 19:38:32 2016 local2.info chat[6821]: timeout set to 10 seconds
Tue Apr  5 19:38:32 2016 local2.info chat[6821]: send (AT^M)
Tue Apr  5 19:38:32 2016 local2.info chat[6821]: expect (OK)
Tue Apr  5 19:38:32 2016 local2.info chat[6821]: AT^M^M
Tue Apr  5 19:38:32 2016 local2.info chat[6821]: OK
Tue Apr  5 19:38:32 2016 local2.info chat[6821]:  -- got it
Tue Apr  5 19:38:32 2016 local2.info chat[6821]: send (ATZ^M)
Tue Apr  5 19:38:33 2016 local2.info chat[6821]: timeout set to 30 seconds
Tue Apr  5 19:38:33 2016 local2.info chat[6821]: expect (OK)
Tue Apr  5 19:38:33 2016 local2.info chat[6821]: ^M
Tue Apr  5 19:38:33 2016 local2.info chat[6821]: ATZ^M^M
Tue Apr  5 19:38:33 2016 local2.info chat[6821]: OK
Tue Apr  5 19:38:33 2016 local2.info chat[6821]:  -- got it
Tue Apr  5 19:38:33 2016 local2.info chat[6821]: send (ATDT#777^M)
Tue Apr  5 19:38:33 2016 local2.info chat[6821]: expect (CONNECT)
Tue Apr  5 19:38:33 2016 local2.info chat[6821]: ^M
Tue Apr  5 19:38:33 2016 local2.info chat[6821]: ATDT#777^M^M
Tue Apr  5 19:38:33 2016 local2.info chat[6821]: CONNECT
Tue Apr  5 19:38:33 2016 local2.info chat[6821]:  -- got it
Tue Apr  5 19:38:33 2016 local2.info chat[6821]: send (^M)
Tue Apr  5 19:38:33 2016 daemon.info pppd[6810]: Serial connection established.
Tue Apr  5 19:38:33 2016 daemon.info pppd[6810]: Using interface 3g-wan
Tue Apr  5 19:38:33 2016 kern.info kernel: [ 8554.840000] 3g-wan: renamed from ppp0
Tue Apr  5 19:38:33 2016 daemon.notice pppd[6810]: Connect: 3g-wan &lt; --&gt; /dev/ttyUSB0
Tue Apr  5 19:38:33 2016 daemon.notice pppd[6810]: PAP authentication succeeded
Tue Apr  5 19:38:33 2016 daemon.notice pppd[6810]: local  IP address 10.227.181.163
Tue Apr  5 19:38:33 2016 daemon.notice pppd[6810]: remote IP address 172.17.4.100
Tue Apr  5 19:38:33 2016 daemon.notice pppd[6810]: primary   DNS address 192.168.4.3
Tue Apr  5 19:38:33 2016 daemon.notice pppd[6810]: secondary DNS address 192.168.4.7
Tue Apr  5 20:08:32 2016 daemon.info pppd[6810]: LCP terminated by peer
Tue Apr  5 20:08:32 2016 daemon.info pppd[6810]: Connect time 30.0 minutes.
Tue Apr  5 20:08:32 2016 daemon.info pppd[6810]: Sent 826328 bytes, received 547992 bytes.
Tue Apr  5 20:08:33 2016 daemon.info pppd[6810]: Terminating on signal 15
Tue Apr  5 20:08:35 2016 daemon.notice pppd[6810]: Connection terminated.
Tue Apr  5 20:08:36 2016 daemon.notice pppd[6810]: Modem hangup
Tue Apr  5 20:08:36 2016 daemon.info pppd[6810]: Exit.
Tue Apr  5 20:08:37 2016 daemon.notice pppd[7884]: pppd 2.4.7 started by root, uid 0
Tue Apr  5 20:08:38 2016 local2.info chat[7896]: abort on (BUSY)
Tue Apr  5 20:08:38 2016 local2.info chat[7896]: abort on (NO CARRIER)
Tue Apr  5 20:08:38 2016 local2.info chat[7896]: abort on (ERROR)
Tue Apr  5 20:08:38 2016 local2.info chat[7896]: abort on (NO DIAL TONE)
Tue Apr  5 20:08:38 2016 local2.info chat[7896]: abort on (NO ANSWER)
Tue Apr  5 20:08:38 2016 local2.info chat[7896]: abort on (DELAYED)
Tue Apr  5 20:08:38 2016 local2.info chat[7896]: report (CONNECT)
Tue Apr  5 20:08:38 2016 local2.info chat[7896]: timeout set to 10 seconds
Tue Apr  5 20:08:38 2016 local2.info chat[7896]: send (AT^M)
Tue Apr  5 20:08:38 2016 local2.info chat[7896]: expect (OK)
Tue Apr  5 20:08:38 2016 local2.info chat[7896]: AT^M^M
Tue Apr  5 20:08:38 2016 local2.info chat[7896]: OK
Tue Apr  5 20:08:38 2016 local2.info chat[7896]:  -- got it
Tue Apr  5 20:08:38 2016 local2.info chat[7896]: send (ATZ^M)
Tue Apr  5 20:08:38 2016 local2.info chat[7896]: timeout set to 30 seconds
Tue Apr  5 20:08:38 2016 local2.info chat[7896]: expect (OK)
Tue Apr  5 20:08:38 2016 local2.info chat[7896]: ^M
Tue Apr  5 20:08:38 2016 local2.info chat[7896]: ATZ^M^M
Tue Apr  5 20:08:38 2016 local2.info chat[7896]: OK
Tue Apr  5 20:08:38 2016 local2.info chat[7896]:  -- got it
Tue Apr  5 20:08:38 2016 local2.info chat[7896]: send (ATDT#777^M)
Tue Apr  5 20:08:38 2016 local2.info chat[7896]: expect (CONNECT)
Tue Apr  5 20:08:38 2016 local2.info chat[7896]: ^M
Tue Apr  5 20:08:39 2016 local2.info chat[7896]: ATDT#777^M^M
Tue Apr  5 20:08:39 2016 local2.info chat[7896]: CONNECT
Tue Apr  5 20:08:39 2016 local2.info chat[7896]:  -- got it
Tue Apr  5 20:08:39 2016 local2.info chat[7896]: send (^M)
Tue Apr  5 20:08:39 2016 daemon.info pppd[7884]: Serial connection established.
</code></pre>
<p>These are the logs from <code>pppd</code> daemon and CHAT script, responsible for sending AT commands to modem. As you can see there may be random hangups, but the connection is automatically re-established which is very nice.</p>
<p>And when you enter <code>ifconfig</code> command you should see <code>3g-wan</code> interface too:</p>
<pre><code class="" title="">root@OpenWrt:~# ifconfig
3g-wan    Link encap:Point-to-Point Protocol
          inet addr:10.227.196.50  P-t-P:172.17.4.100  Mask:255.255.255.255
          UP POINTOPOINT RUNNING NOARP MULTICAST  MTU:1500  Metric:1
          RX packets:977 errors:0 dropped:0 overruns:0 frame:0
          TX packets:2117 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:3
          RX bytes:529666 (517.2 KiB)  TX bytes:324250 (316.6 KiB)
</code></pre>
<p>In case you&#8217;re interested in diving deeper into how things work, I&#8217;d recommend looking at these files:</p>
<ul>
<li><code>/etc/config/network</code> contains network configuration</li>
<li><code>/lib/netifd/proto/3g.sh</code> shell logic responsible for running <code>pppd</code> daemon</li>
</ul>
<h2>Measuring signal strength</h2>
<p>The last problem you&#8217;ll probably stumble upon &#8212; is how to measure signal strength, especially if you&#8217;re setting up standalone solution at a remote location with a modem connected to an external antenna. This is usually accomplished by sending special <code>AT</code> command to modem. Note, however, that most software and examples over internet are targeted towards more popular GRPS/UMTS modems, and they will probably won&#8217;t work.</p>
<p>Before using serial protocol to communicate with modem, we must shutdown existing <code>3g-wan</code> connection, because otherwise we&#8217;ll get <code>cat: read error: Resource temporarily unavailable</code>:</p>
<pre><code class="bash" title="">root@OpenWrt:~# ifdown wan
</code></pre>
<p>Note, that <code>ifdown</code> won&#8217;t accept <code>3g-wan</code> as interface, but oddly enough the above command works. For now, let&#8217;s focus on how to send <code>AT</code> commands to modem:</p>
<ul>
<li>run <code>screen</code></li>
<li>open 2 consoles</li>
</ul>
<p>In the first console run <code>cat /dev/ttyUSB0</code> (this is a place to look for modem replies) and in the second run <code>echo -ne "at!status?\r\n" &gt; /dev/ttyUSB0</code>. Switch back consoles and you should see something like this:</p>
<pre><code class="bash" title="">root@OpenWrt:~# cat /dev/ttyUSB0
at!rssi?
-83

OK
</code></pre>
<p>A range from -60 dbm to -90 dBm is considered adequate. Using this special AT command you may now run it in a loop with small delay, observe signal strength in the second console and properly adjust external antenna. Also, there seems to be an unofficial OpenWRT package specifically for signal monitoring called <a href="http://dl.eko.one.pl/chaos_calmer/ar71xx/packages/3ginfo_20160223_all.ipk">3ginfo</a>, but I&#8217;ve not tried it and not sure if it works for CDMA/EVDO modems.</p>
<h2>TL;DR;</h2>
<p>Seriously, If you want to avoid all the hassle of setting up CDMA modem and OpenWRT, just buy yourself a device which combines WiFi router and 3g modem &#8212; <a href="https://en.wikipedia.org/wiki/MiFi">MiFi</a> will do just fine :)</p>
<p>Download <a href="/wp-content/uploads/2016/04/openwrt-15.05.1-brcm47xx-legacy-asus-wl-500gp-v2-squashfs.trx">openwrt-15.05.1-brcm47xx-legacy-asus-wl-500gp-v2-squashfs.trx</a>  (MD5: <strong>420e24e9a042c01585d818c14afa11d3</strong>)</p>
<h2>Links</h2>
<ul>
<li><a href="https://wiki.openwrt.org/doc/recipes/3gdongle">OpenWRT 3g dongle howto</a></li>
<li><a href="http://ubuntuguide.org/wiki/Ubuntu:Gutsy#Using_USB_EVDO_Internet_modem">Using USB EVDO Internet_modem</a></li>
<li><a href="http://wiki.villagetelco.org/Using_a_3G_USB_Modem">Using a 3G USB Modem</a></li>
<li><a href="http://www.daveconroy.com/verified-raspberry-pi-and-3g-sierra-wireless-250u-aircard-from-sprint/">Raspberry pi and 3g sierra wireless 250u</a></li>
<li><a href="http://kb.netgear.com/app/answers/detail/a_id/22827/~/can-i-use-my-netgear-aircard-modem-on-a-linux-operating-system-(v.1.7.40)%3F#CDMA_AT_Commands">CDMA AT Commands</a></li>
<li><a href="http://www.panticz.de/node/670">OpenWrt connect to UMTS with Huawei E620 3G USB Modem</a></li>
<li><a href="https://wiki.ubuntu.com/SierraMC8775">Sierra Wireless model MC8775 PCI Express</a></li>
<li><a href="http://askubuntu.com/questions/323352/how-do-i-log-usb-modem-at-command-output">How do i log usb modem AT command output</a></li>
<li><a href="http://manpages.ubuntu.com/manpages/gutsy/man1/gcom.1.html">gcom datacard control tool</a></li>
<li><a href="http://eko.one.pl/?p=openwrt-3ginfo">OpenWRT 3ginfo</a></li>
<li><a href="http://unix.stackexchange.com/questions/220657/sending-serial-commands-with-echo-vs-screen-session">Sending serial commands with echo vs screen session</a></li>
</ul>
</div>
]]></content:encoded>
			<wfw:commentRss>https://webapp.org.ua/dev/openwrt-chaos-calmer-15-05-on-dlink-dir-320-with-cdma-modem/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Running php 5.2 fpm on ARM processor</title>
		<link>https://webapp.org.ua/dev/running-php-5-2-fpm-on-arm-processor/</link>
		<comments>https://webapp.org.ua/dev/running-php-5-2-fpm-on-arm-processor/#comments</comments>
		<pubDate>Sun, 20 Mar 2016 20:06:57 +0000</pubDate>
		<dc:creator>bananos</dc:creator>
				<category><![CDATA[dev]]></category>
		<category><![CDATA[arm]]></category>
		<category><![CDATA[armhf]]></category>
		<category><![CDATA[fpm]]></category>
		<category><![CDATA[legacy]]></category>
		<category><![CDATA[php]]></category>
		<category><![CDATA[scaleway]]></category>

		<guid isPermaLink="false">http://webapp.org.ua/?p=439</guid>
		<description><![CDATA[Sometimes you need to run legacy php code on ARM processors. Since php 5.2 was released 2 November 2006 at the time there were not a lot of powerful ARM solutions capable of running full-fledged websites. However, right now there is a possibility to run pretty heavy code on modern ARM platforms and a lot [...]]]></description>
			<content:encoded><![CDATA[<div class="markdown-content">
<p>Sometimes you need to run legacy php code on ARM processors. Since php 5.2 was released 2 November 2006 at the time there were not a lot of powerful ARM solutions capable of running full-fledged websites. However, right now there is a possibility to run pretty heavy code on modern ARM platforms and a lot of linux distros support ARM architecture. There is even <a href="https://www.scaleway.com/">dedicated ARM cloud hosting</a>.</p>
<p>In this post we&#8217;re going to fix the inability to run PHP in the FPM(Fast Process Manager) mode which is an absolute requirement if you want to run production websites.</p>
</div>
<p><span id="more-439"></span></p>
<div class="markdown-content">
<h2>Compiling from sources</h2>
<p>Since there is no old php releases in modern linux distros we&#8217;re obviously going to compile everything from scratch. For our purposes we&#8217;ll use <code>ubuntu 15.04</code>, let&#8217;s download php sources from PHP museum:</p>
<pre><code class="bash" title="">$ mkdir -p /mnt/build/ &amp;&amp; cd /mnt/build/
$ wget http://museum.php.net/php5/php-5.2.17.tar.gz &amp;&amp; tar -xf php-5.2.17.tar.gz
$ apt-get install -y build-essential nano wget curl libbz2-dev libncurses5-dev autoconf libxml2-dev

</code></pre>
<h2>PHP-FPM patch</h2>
<p>For historical reasons, Fast Process Manager(FPM) for 5.2.X branch exists only in the <a href="http://php-fpm.org/downloads/php-5.2.17-fpm-0.5.14.diff.gz">form of patch</a>. Let&#8217;s download this patch and apply it the most recent 5.2 version:</p>
<pre><code class="bash" title="">$ cd php-5.2.17/
$ wget http://php-fpm.org/downloads/php-5.2.17-fpm-0.5.14.diff.gz &amp;&amp; gzip -d php-5.2.17-fpm-0.5.14.diff.gz
$ patch -p1 &lt; php-5.2.17-fpm-0.5.14.diff
 patching file configure
Hunk #7 succeeded at 110645 (offset 1324 lines).
Hunk #8 succeeded at 118930 (offset 1324 lines).
Hunk #9 succeeded at 119634 (offset 1324 lines).
Hunk #10 succeeded at 119689 (offset 1324 lines).
patching file configure.in
patching file libevent/ChangeLog
patching file libevent/Makefile.am
patching file libevent/Makefile.in
patching file libevent/README
patching file libevent/aclocal.m4

</code></pre>
<p>After this operation <code>--enable-fpm</code> option becomes available in <code>./configure</code> script:</p>
<pre><code class="bash" title="">$ ./configure --help | grep "fpm"
  --enable-fpm              FastCGI: If this is enabled, the fastcgi support
  --with-fpm-conf=PATH        Set the path for php-fpm configuration file [PREFIX/etc/php-fpm.conf]
  --with-fpm-log=PATH         Set the path for php-fpm log file [PREFIX/logs/php-fpm.log]
  --with-fpm-pid=PATH         Set the path for php-fpm pid file [PREFIX/logs/php-fpm.pid]

</code></pre>
<p>Let&#8217;s try to compile php with FPM support:</p>
<pre><code class="bash" title="">$ ./configure --prefix=/opt/php52 --enable-fastcgi --enable-fpm

loading cache ./config.cache
checking for Cygwin environment... no
checking for mingw32 environment... no
checking for egrep... grep -E
checking for a sed that does not truncate output... /bin/sed
checking host system type... armv7l-unknown-linux-gnueabi
checking target system type... armv7l-unknown-linux-gnueabi
checking for gcc... gcc
checking whether the C compiler (gcc  ) works... yes
checking whether the C compiler (gcc  ) is a cross-compiler... no
checking whether we are using GNU C... yes
....

Thank you for using PHP.

</code></pre>
<p>So far, everything is looking fine. Let&#8217;s try to build it by running <code>make</code> using 4 ARM cores to speedup process:</p>
<pre><code class="bash" title="">$ make -j4

/bin/sh /mnt/build/php-5.2.17/libtool --silent --preserve-dup-deps --mode=compile gcc -Iext/date/lib -Iext/date/ -I/mnt/build/php-5.2.17/ext/date/ -DPHP_ATOM_
INC -I/mnt/build/php-5.2.17/include -I/mnt/build/php-5.2.17/main -I/mnt/build/php-5.2.17 -I/mnt/build/php-5.2.17/ext/date/lib -I/usr/include/libxml2 -I/mnt/bu
ild/php-5.2.17/TSRM -I/mnt/build/php-5.2.17/Zend    -I/usr/include -g -O2  -c /mnt/build/php-5.2.17/ext/date/php_date.c -o ext/date/php_date.lo
/bin/sh /mnt/build/php-5.2.17/libtool --silent --preserve-dup-deps --mode=compile gcc -Iext/date/lib -Iext/date/ -I/mnt/build/php-5.2.17/ext/date/ -DPHP_ATOM_
INC -I/mnt/build/php-5.2.17/include -I/mnt/build/php-5.2.17/main -I/mnt/build/php-5.2.17 -I/mnt/build/php-5.2.17/ext/date/lib -I/usr/include/libxml2 -I/mnt/bu
ild/php-5.2.17/TSRM -I/mnt/build/php-5.2.17/Zend    -I/usr/include -g -O2  -c /mnt/build/php-5.2.17/ext/date/lib/astro.c -o ext/date/lib/astro.lo

..........

/mnt/build/php-5.2.17/ext/dom/node.c: In function ‘dom_canonicalization’:
/mnt/build/php-5.2.17/ext/dom/node.c:1953:21: error: dereferencing pointer to incomplete type ‘xmlBuf {aka struct _xmlBuf}’
    ret = buf-&gt;buffer-&gt;use;
                     ^
Makefile:553: recipe for target 'ext/dom/node.lo' failed
make: *** [ext/dom/node.lo] Error 1

</code></pre>
<h2>libxml2 patching</h2>
<p>And boom! We&#8217;re stuck with the first error: <code>dereferencing pointer to incomplete type xmlBuf {aka struct _xmlBuf}</code>. After googling around, the problem seems to be related to <code>libxml2</code> incompatibility and is <a href="https://code.google.com/archive/p/php52-backports/issues/16">well documented</a>. Let&#8217;s fix that error by applying yet another patch:</p>
<pre><code class="bash" title="">$ wget https://github.com/bananos/dockerized/raw/master/armbuild-php52/patches/libxml29_compat.patch
$ patch -p1 &lt; libxml29_compat.patch
patching file ext/dom/node.c
Hunk #1 succeeded at 1950 (offset 55 lines).
patching file ext/dom/documenttype.c
Hunk #1 succeeded at 215 (offset 10 lines).
patching file ext/simplexml/simplexml.c
Hunk #1 succeeded at 1343 (offset -74 lines).

</code></pre>
<p>And run <code>make</code> once again:</p>
<pre><code class="bash" title="">$ make -j4

......

In file included from /mnt/build/php-5.2.17/sapi/cgi/fpm/fpm_shm_slots.h:8:0,
                 from /mnt/build/php-5.2.17/sapi/cgi/fpm/fpm_children.c:28:
/mnt/build/php-5.2.17/sapi/cgi/fpm/fpm_atomic.h:62:2: error: #error unsupported processor. please write a patch and send it to me
 #error unsupported processor. please write a patch and send it to me
  ^
/mnt/build/php-5.2.17/sapi/cgi/fpm/fpm_atomic.h:66:32: error: unknown type name ‘atomic_t’
 static inline int fpm_spinlock(atomic_t *lock, int try_once)
                                ^
In file included from /mnt/build/php-5.2.17/sapi/cgi/fpm/fpm_children.c:28:0:
/mnt/build/php-5.2.17/sapi/cgi/fpm/fpm_shm_slots.h:16:3: error: unknown type name ‘atomic_t’
   atomic_t lock;
   ^
In file included from /mnt/build/php-5.2.17/sapi/cgi/fpm/fpm_shm_slots.h:8:0,
                 from /mnt/build/php-5.2.17/sapi/cgi/fpm/fpm_worker_pool.c:15:
/mnt/build/php-5.2.17/sapi/cgi/fpm/fpm_atomic.h:62:2: error: #error unsupported processor. please write a patch and send it to me
 #error unsupported processor. please write a patch and send it to me
  ^
/mnt/build/php-5.2.17/sapi/cgi/fpm/fpm_atomic.h:66:32: error: unknown type name ‘atomic_t’
 static inline int fpm_spinlock(atomic_t *lock, int try_once)
                                ^
In file included from /mnt/build/php-5.2.17/sapi/cgi/fpm/fpm_worker_pool.c:15:0:
/mnt/build/php-5.2.17/sapi/cgi/fpm/fpm_shm_slots.h:16:3: error: unknown type name ‘atomic_t’
   atomic_t lock;
   ^
Makefile:433: recipe for target 'sapi/cgi/fpm/fpm_worker_pool.lo' failed
make: *** [sapi/cgi/fpm/fpm_worker_pool.lo] Error 1
make: *** Waiting for unfinished jobs....
Makefile:431: recipe for target 'sapi/cgi/fpm/fpm_children.lo' failed
make: *** [sapi/cgi/fpm/fpm_children.lo] Error 1

</code></pre>
<p>Well, this is embarrassing. As we can see from compiler logs, the FPM author suggests us to write a patch and send it to him because current CPU type is not supported. Obviously, the first thing I did was to try google yet another patch to solve this problem, but unfortunately, there is no one &#8212; people moved on to newer PHP versions and no one cared enough to write a fix.</p>
<p>Therefore, we&#8217;re going to write our own patch. Let&#8217;s take a look at <code>/mnt/build/php-5.2.17/sapi/cgi/fpm/fpm_atomic.h:62:2</code></p>
<pre><code class="cpp" title="">

  /* $Id: fpm_atomic.h,v 1.3 2008/09/18 23:34:11 anight Exp $ */
  /* (c) 2007,2008 Andrei Nigmatulin */

#ifndef FPM_ATOMIC_H
#define FPM_ATOMIC_H 1

#include &lt;stdint.h&gt;
#include &lt;sched .h&gt;

#if ( __i386__ || __i386 )

typedef int32_t                     atomic_int_t;
typedef uint32_t                    atomic_uint_t;
typedef volatile atomic_uint_t      atomic_t;

static inline atomic_int_t atomic_fetch_add(atomic_t *value, atomic_int_t add)
{
        __asm__ volatile ( "lock;" "xaddl %0, %1;" :
                "+r" (add) : "m" (*value) : "memory");

        return add;
}

static inline atomic_uint_t atomic_cmp_set(atomic_t *lock, atomic_uint_t old, atomic_uint_t set)
{
        unsigned char res;

        __asm__ volatile ( "lock;" "cmpxchgl %3, %1;" "sete %0;" :
                "=a" (res) : "m" (*lock), "a" (old), "r" (set) : "memory");

    return res;
}

#elif ( __amd64__ || __amd64 )

// definitions of the same functions for AMD64

#else

#error unsupported processor. please write a patch and send it to me

#endif

</code></pre>
<h2>Atomic types</h2>
<p>Looks like we need to define those 2 functions for ARM platform. But how do we do it without proper knowledge of <code>C</code> and specifics of <code>armhf</code> architecture? Luckily, we may steal some code from newer PHP versions, which do work in FPM mode on ARM platform. Go to <code>https://github.com/php/php-src/blob/PHP-5.3/sapi/fpm/fpm/fpm_atomic.h</code> and take a look at source code:</p>
<pre><code class="cpp" title="">

    /* $Id: fpm_atomic.h,v 1.3 2008/09/18 23:34:11 anight Exp $ */
    /* (c) 2007,2008 Andrei Nigmatulin */

#ifndef FPM_ATOMIC_H
#define FPM_ATOMIC_H 1

#if HAVE_INTTYPES_H
# include &lt;inttypes .h&gt;
#else
# include &lt;stdint .h&gt;
#endif
#include &lt;sched .h&gt;

#ifdef HAVE_BUILTIN_ATOMIC

/**
 * all the cases below (as provided by upstream) define:
 * word as atomic_int_t, and
 * unsigned word as atomic_uint_t
 * and only use volatile atomic_uint_t as atomic_t
 */

typedef volatile unsigned long atomic_t;
#define atomic_cmp_set(a,b,c) __sync_bool_compare_and_swap(a,b,c)

#elif ( __i386__ || __i386 )

///  a lot of platform-speicific definitions of above mentioned functions

#if (__GNUC__) &amp;&amp; (__GNUC__ &lt; 4 || (__GNUC__ == 4 &amp;&amp; __GNUC_MINOR__ &lt; 2))

#elif ( __arm__ || __arm ) /* W-Mark Kubacki */

///  other code we're not interested in

</code></pre>
<p>Although, it does contain the mention of ARM, the code defined for this case won&#8217;t be executed, since this is not our case:</p>
<pre><code class=" bash" title="">$ gcc -v
Using built-in specs.
COLLECT_GCC=gcc
COLLECT_LTO_WRAPPER=/usr/lib/gcc/arm-linux-gnueabihf/5/lto-wrapper
Target: arm-linux-gnueabihf
Configured with: ../src/configure -v --with-pkgversion='Ubuntu 5.2.1-22ubuntu2' --with-bugurl=file:///usr/share/doc/gcc-5/README.Bugs --enable-languages=c,ada,c++,java,go,d,fortran,objc,obj-c++ --prefix=/usr --program-suffix=-5 --enable-shared --enable-linker-build-id --libexecdir=/usr/lib --without-included-gettext --enable-threads=posix --libdir=/usr/lib --enable-nls --with-sysroot=/ --enable-clocale=gnu --enable-libstdcxx-debug --enable-libstdcxx-time=yes --with-default-libstdcxx-abi=new --enable-gnu-unique-object --disable-libitm --disable-libquadmath --enable-plugin --with-system-zlib --disable-browser-plugin --enable-java-awt=gtk --enable-gtk-cairo --with-java-home=/usr/lib/jvm/java-1.5.0-gcj-5-armhf/jre --enable-java-home --with-jvm-root-dir=/usr/lib/jvm/java-1.5.0-gcj-5-armhf --with-jvm-jar-dir=/usr/lib/jvm-exports/java-1.5.0-gcj-5-armhf --with-arch-directory=arm --with-ecj-jar=/usr/share/java/eclipse-ecj.jar --enable-objc-gc --enable-multiarch --enable-multilib --disable-sjlj-exceptions --with-arch=armv7-a --with-fpu=vfpv3-d16 --with-float=hard --with-mode=thumb --disable-werror --enable-multilib --enable-checking=release --build=arm-linux-gnueabihf --host=arm-linux-gnueabihf --target=arm-linux-gnueabihf
Thread model: posix
gcc version 5.2.1 20151010 (Ubuntu 5.2.1-22ubuntu2)

</code></pre>
<p>What we&#8217;re going to do is leveraging built-in atomic types, which are controlled by <code>HAVE_BUILTIN_ATOMIC</code> flag. But first, let&#8217;s do a drop-in replacement of <code>fpm_atomic.h</code> from 5.3 branch:</p>
<pre><code class="" title="">$ cd /mnt/build/php-5.2.17/sapi/cgi/fpm
$ rm fpm_atomic.h &amp;&amp; wget "https://github.com/php/php-src/raw/PHP-5.3/sapi/fpm/fpm/fpm_atomic.h"

</code></pre>
<p>Another <code>magic</code> step is in fact, fix configure system to be able to enable above mentioned flag. Open <code>/mnt/build/php-5.2.17/sapi/cgi/fpm/acinclude.m4</code>  and add at the top:</p>
<pre><code class="" title="">AC_DEFUN([AC_FPM_BUILTIN_ATOMIC],
[
  AC_MSG_CHECKING([if gcc supports __sync_bool_compare_and_swap])
  AC_TRY_LINK(,
  [
    int variable = 1;
    return (__sync_bool_compare_and_swap(&amp;variable, 1, 2)
           &amp;&amp; __sync_add_and_fetch(&amp;variable, 1)) ? 1 : 0;
  ],
  [
    AC_MSG_RESULT([yes])
    AC_DEFINE(HAVE_BUILTIN_ATOMIC, 1, [Define to 1 if gcc supports __sync_bool_compare_and_swap() a.o.])
  ],
  [
    AC_MSG_RESULT([no])
  ])
])

</code></pre>
<p>After this is done, everything should compile just fine.</p>
<h2>TL;DR</h2>
<p>For those lazy folks who don&#8217;t want all the investigation details here&#8217;s an updated patch which I prepared:<br />
<code>https://github.com/bananos/dockerized/blob/master/armbuild-php52/patches/php-5.2.17-fpm-arm-0.5.14.diff</code></p>
<p>In order to use it, just download vanilla php-5.2.17 sources and apply the patch:</p>
<pre><code class="bash" title="">mkdir -p /tmp/build
cd /tmp/build &amp;&amp; wget http://museum.php.net/php5/php-5.2.17.tar.gz &amp;&amp; tar -xf php-5.2.17.tar.gz
cd /tmp/build &amp;&amp; wget https://github.com/bananos/dockerized/raw/master/armbuild-php52/patches/php-5.2.17-fpm-arm-0.5.14.diff
cd /tmp/build &amp;&amp; patch -p1 -d php-5.2.17/ &lt; /tmp/build/php-5.2.17-fpm-arm-0.5.14.diff

</code></pre>
<p>If you&#8217;re familiar with <a href="https://www.docker.com/">Docker</a> you may might also check precompiled and flattened <a href="https://github.com/bananos/dockerized/tree/master/armbuild-php52">PHP-5.2.17 ARMHF image</a><br />
with some most popular <code>PECL</code> packages pre-built.</p>
<p>Happy running your old legacy PHP code!</p>
<h2>Sources</h2>
<p>http://php-fpm.org/</p>
<p>https://github.com/bananos/dockerized/tree/master/armbuild-php52/</p>
<p>https://github.com/php/php-src/</p>
<p>https://code.google.com/archive/p/php52-backports/issues/16</p>
<p>http://saravananlinux.blogspot.com/2014/01/libxml-error-while-compiling-dual-php.html</p>
</div>
<p></sched></sched></stdint></inttypes></sched></p>
]]></content:encoded>
			<wfw:commentRss>https://webapp.org.ua/dev/running-php-5-2-fpm-on-arm-processor/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>CloudWatch custom metrics</title>
		<link>https://webapp.org.ua/dev/cloudwatch-custom-metrics/</link>
		<comments>https://webapp.org.ua/dev/cloudwatch-custom-metrics/#comments</comments>
		<pubDate>Wed, 16 Dec 2015 15:40:08 +0000</pubDate>
		<dc:creator>bananos</dc:creator>
				<category><![CDATA[dev]]></category>
		<category><![CDATA[sysadmin]]></category>
		<category><![CDATA[aws]]></category>
		<category><![CDATA[cloudwatch]]></category>
		<category><![CDATA[monitoring]]></category>
		<category><![CDATA[time series]]></category>

		<guid isPermaLink="false">http://webapp.org.ua/?p=397</guid>
		<description><![CDATA[In this post we&#8217;re going to investigate how to create custom metrics for the AWS CloudWatch service. In some cases it&#8217;s not enough to have default set of AWS metrics which are already defined for you in dashboard. Let&#8217;s say you want to monitor the number of active customers on your website, or you would [...]]]></description>
			<content:encoded><![CDATA[<div class="markdown-content">
<p><img class="size-full wp-image-417 alignleft" title="cloudwatch_logo" src="http://webapp.org.ua/wp-content/uploads/2015/12/cloudwatch_logo.png" alt="" width="225" height="225" /></p>
<p>In this post we&#8217;re going to investigate how to create custom metrics for the AWS CloudWatch service. In some cases it&#8217;s not enough to have default set of AWS metrics which are already defined for you in dashboard. Let&#8217;s say you want to monitor the number of active customers on your website, or you would like to know the number of failed requests to your API backend.</p>
<p>Whatever it is, CloudWatch will allow you to record any time-based data using AWS APIs.</p>
<p><br style="clear: both;" /></p>
</div>
<p><span id="more-397"></span></p>
<div class="markdown-content">
<h2>Install AWS CLI</h2>
<p>First off, in order to post data to CloudWatch you need to install and setup <a href="https://pypi.python.org/pypi/awscli/">command-line tools to work with AWS APIs</a>:</p>
<pre><code class="bash" title="">$ pip install awscli
</code></pre>
<p>If you don&#8217;t know what <code>pip</code> is, head over <a href="https://pip.pypa.io/en/latest/installing.html">pip installation manual</a>.<br />
Once AWS CLI is installed the <code>aws</code> command should be available via your command shell:</p>
<pre><code class="bash" title="">$ aws
usage: aws [options]   [ ...] [parameters]
To see help text, you can run:

aws help
aws: error: too few arguments
</code></pre>
<p>Before issuing real commands to AWS service you need to configure cli tools:</p>
<pre><code class="bash" title="">$ aws configure
AWS Access Key ID [****************KCEQ]:
AWS Secret Access Key [****************x++s]:
Default region name [us-west-2]:
Default output format [json]:
</code></pre>
<p>After successfull configuration you should be able to use command-line interface for AWS, for example, let&#8217;s list all available EC2 instances:</p>
<pre><code class="" title="">$ aws ec2 describe-instances | grep "PublicDnsName" | awk '{$1=$1};1' | uniq
"PublicDnsName": "ec2-44-148-96-212.us-west-2.compute.amazonaws.com",
"PublicDnsName": "ec2-42-25-174-143.us-west-2.compute.amazonaws.com",
"PublicDnsName": "ec2-44-68-194-93.us-west-2.compute.amazonaws.com",
"PublicDnsName": "ec2-44-69-229-202.us-west-2.compute.amazonaws.com",
</code></pre>
<h2>Choose a metric</h2>
<p>Let&#8217;s say that we want to monitor application API status by periodically requesting specific endpoint and checking HTTP response code. In our example we&#8217;ll use <code>http://httpbin.org/status/200</code> URL to demo.</p>
<p>We will consider HTTP 200 response code as a <code>service alive</code> event and treat it as <code>1</code>, and any other response code(including timeout) as a <code>service failure</code> event or <code>0</code>.</p>
<p>The following bash code(<code>service_mon.sh</code>) will output HTTP response code:</p>
<pre><code class="bash" title="">#!/bin/bash
CODE=`curl -k -s -o /dev/null -w "%{http_code}" http://httpbin.org/status/200`
echo $CODE
</code></pre>
<p>Run it and verify that script outputs <code>200</code>:</p>
<pre><code class="" title="">$ ./service_mon.sh
200
</code></pre>
<h2>Choose metric name</h2>
<p>We&#8217;re going to name our metric <code>ServiceStatus</code> and will report it to CloudWatch using <code>cloudwatch</code> subcommand. Modify above mentioned <code>service_mon.sh</code> script to be the following:</p>
<pre><code class="bash" title="">#!/bin/bash

# get response code
CODE=`curl -k -s -o /dev/null -w "%{http_code}" http://httpbin.org/status/200`
if [ "$CODE" -eq 200 ] ; then
aws cloudwatch put-metric-data --metric-name ServiceStatus --namespace CL_AGENTS --value 1 --unit "Count"
else
aws cloudwatch put-metric-data --metric-name ServiceStatus --namespace CL_AGENTS --value 0 --unit "Count"
fi
</code></pre>
<p>Note <code>CL_AGENTS</code> in cmd parameters, this is a convenient group name for all your metrics, typically you&#8217;d want to put your application name in there. In this example we&#8217;re specifying a type for our data called <code>Count</code>, this is not the only possible option. Here&#8217;s a list of other units:</p>
<pre><code class="" title="">[ Seconds, Microseconds, Milliseconds, Bytes, Kilobytes, Megabytes, Gigabytes, Terabytes, Bits, Kilobits,
Megabits, Gigabits, Terabits, Percent, Count, Bytes/Second, Kilobytes/Second, Megabytes/Second, Gigabytes/Second,
Terabytes/Second, Bits/Second, Kilobits/Second, Megabits/Second, Gigabits/Second, Terabits/Second, Count/Second, None ]
</code></pre>
<p><a href="http://webapp.org.ua/wp-content/uploads/2015/12/aws_metric_namespace.png"><img class="aligncenter size-full wp-image-415" title="aws_metric_namespace" src="http://webapp.org.ua/wp-content/uploads/2015/12/aws_metric_namespace.png" alt="" width="688" height="578" /></a></p>
<p>&nbsp;</p>
<h2>Periodic script execution</h2>
<p>Put the script we&#8217;ve written into crontab:</p>
<pre><code class="" title=""># m h  dom mon dow   command
*/5 * * * * /mnt/service_mon.sh

</code></pre>
<p><span style="text-align: center;">This will post service status to CloudWatch every 5 minutes.  Here&#8217;s how it might look like in web based AWS console:</span></p>
<p style="text-align: center;"><a href="http://webapp.org.ua/wp-content/uploads/2015/12/cloudwatch_metric.png"><img class="aligncenter size-full wp-image-418" title="cloudwatch_metric" src="http://webapp.org.ua/wp-content/uploads/2015/12/cloudwatch_metric.png" alt="" width="824" height="439" /></a></p>
<p>You may also report multiple values at the same time using JSON file:</p>
<pre><code class="json" title="">[
{
"MetricName": "ServiceStatus",
"Timestamp": "Wednesday, June 12, 2013 8:28:20 PM",
"Value": 1,
"Unit": "Count"
},
{
"MetricName": "ServiceStatus",
"Timestamp": "Wednesday, June 12, 2013 8:30:20 PM",
"Value": 0,
"Unit": "Count"
}
]

</code></pre>
<p>To do bulk reporting use this format:</p>
<pre><code class="" title="">$ aws cloudwatch put-metric-data --namespace "CL_AGENTS" --metric-data file://metric.json
</code></pre>
<h2>Setup alarms</h2>
<p>Up until now our metric is almost useless, except that we may see nice graphs in the CloudWatch. To do it more usable, let&#8217;s add alarm if our API is down:</p>
<ul>
<li>Select <code>ServiceName</code> metric in the <code>CL_AGENTS</code> namespace we&#8217;ve just created</li>
<li>Click <code>Create Alarm</code> button on the right side of the graph</li>
<li>In the subsequent popup, select alarm details:</li>
</ul>
<p style="text-align: center;"><a href="http://webapp.org.ua/wp-content/uploads/2015/12/cloudwatch_create_alarm.png"><img class="aligncenter size-full wp-image-416" title="cloudwatch_create_alarm" src="http://webapp.org.ua/wp-content/uploads/2015/12/cloudwatch_create_alarm.png" alt="" width="836" height="587" /></a></p>
<h2>Gotchas</h2>
<ul>
<li>Keep in mind that CloudWatch will store your time-series data only for <strong>2 weeks (14 days)</strong>, therefore if you want more history and insights for your data you&#8217;re probably will be better off using custom database like <a href="https://github.com/influxdb/influxdb">InfluxDB</a> for example</li>
<li>Make sure to setup aws cli under the same user which your crontab is using, otherwise AWS configuration won&#8217;t be accessible for cron and your monitoring script will not work</li>
</ul>
<h2>Links</h2>
<ul>
<li><a href="https://aws.amazon.com/cloudwatch/">Amazon Cloudwatch service</a></li>
<li><a href="http://docs.aws.amazon.com/cli/latest/reference/cloudwatch/put-metric-data.html">Detailed documentation for put-metric-data command</a></li>
<li><a href="https://en.wikipedia.org/wiki/Time_series_database">Time series database</a></li>
</ul>
</div>
]]></content:encoded>
			<wfw:commentRss>https://webapp.org.ua/dev/cloudwatch-custom-metrics/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Intellij IDEA and Go plugin</title>
		<link>https://webapp.org.ua/dev/intellij-idea-and-go-plugin/</link>
		<comments>https://webapp.org.ua/dev/intellij-idea-and-go-plugin/#comments</comments>
		<pubDate>Wed, 21 Aug 2013 13:39:59 +0000</pubDate>
		<dc:creator>bananos</dc:creator>
				<category><![CDATA[dev]]></category>
		<category><![CDATA[golang]]></category>
		<category><![CDATA[golang-idea-plugin]]></category>
		<category><![CDATA[IDEA]]></category>

		<guid isPermaLink="false">http://webapp.org.ua/?p=327</guid>
		<description><![CDATA[Ever wondered where to find IDE for programming Google Go language? Well, there are not a lot of choices out there and some of them lack pretty significant functionality, especially if you&#8217;re a newbie in Go like me. Some popular choices include: 1. LiteIDE the only IDE targeted specifically towards Go 2. GoSublime a Sublime [...]]]></description>
			<content:encoded><![CDATA[<div class="markdown-content">
<p><a href="http://webapp.org.ua/wp-content/uploads/2013/08/logo.png"><img class="alignleft size-full wp-image-336" title="logo" src="http://webapp.org.ua/wp-content/uploads/2013/08/logo.png" alt="" width="400" height="300" /></a>Ever wondered where to find IDE for programming Google <a href="http://golang.org">Go language</a>?<br />
Well, there are not a lot of choices out there and some of them lack pretty significant functionality, especially if you&#8217;re a newbie in Go like me.</p>
<p>Some popular choices include:</p>
<p>
1. <a href="https://github.com/visualfc/liteide">LiteIDE</a> the only IDE targeted specifically towards Go<br />
2. <a href="https://github.com/DisposaBoy/GoSublime">GoSublime</a> a Sublime Text plugin
</p>
<p>I&#8217;ve tried both of them and found out that both of them lack <code>Go to declaration</code> feature, which is crucual in the process of digging around new code. On top of that LiteIDE requires installation of <a href="https://github.com/nsf/gocode">gocode</a> daemon for autocompletion to work fine.</p>
<p>As you can see usage of these IDEs requires a lot of bells and whistles to get basic functioning.</p>
<p><br style="clear:both"/></p>
<p>However there&#8217;s a third option which I&#8217;m going to talk about in this post: <a href="https://github.com/mtoader/google-go-lang-idea-plugin">Google Go language plugin for IntelliJ Idea</a></p>
<p>It covers two of my initial requirements for Go IDE:</p>
<ol>
<li><code>Go to declaration</code> feature, i.e. you may click on any declaration and go check how it&#8217;s implemented under the hood</li>
<li><code>Autocompletion</code>, that&#8217;s a huge time saver and a great helper in exploring available options</li>
</ol>
<p>If you&#8217;re familiar with any Intellij IDEs you&#8217;ll get additional time-saving benefits too.  Let&#8217;s proceed!</p>
<p>As of time of this writing, there&#8217;s no up-to-date binary distribution of the plugin (hence, the post:),<br />
so we&#8217;re going to build everything from the sources.</p>
</div>
<p><span id="more-327"></span></p>
<div class="markdown-content">
<h2>Install IDEA community edition</h2>
<p>Go to <a href="http://www.jetbrains.com/idea/download/">Jetbrain download page</a> and install latest free community edition.<br />
As of time of this writing the latest IDEA version was 12.</p>
<h2>Grab IDEA sources!</h2>
<h3 id="post-327-md-2">Get Intellij IDEA community sources</h3>
<pre><code class="bash" title=""># repo is ~ 1gb, this may take a while
git clone git://git.jetbrains.org/idea/community.git idea
cd idea

# figure out what IDEA build you've just installed
cat /Applications/IntelliJ\ IDEA\ 12.app/build.txt; echo -e "\r\n";
IC-129.713

# checkout specified tag in the source repo
git checkout idea/129.713

# run ant to build everything
ant
</code></pre>
<p>Depending on the machine this may take 10-20min to compile.</p>
<h2>Grab Go plugin sources</h2>
<pre><code class="bash" title="">git clone https://github.com/mtoader/google-go-lang-idea-plugin.git
cd google-go-land-idea-plugin/

# compile plugin
ANT_OPTS=-Xmx1g ant -Didea.community.build=/Users/bananos/Projects/idea/ -f build-package.xml

Buildfile: /Users/bananos/Projects/google-go-lang-idea-plugin/build-package.xml

clean:

init:
[mkdir] Created dir: /Users/bananos/Projects/google-go-lang-idea-plugin/build
[mkdir] Created dir: /Users/bananos/Projects/google-go-lang-idea-plugin/dist
[echo] Using IDEA build from: /Users/bananos/Projects/idea/

compile:
[javac2] Compiling 561 source files to /Users/bananos/Projects/google-go-lang-idea-plugin/build

........................
........................
package:
[jar] Building jar: /Users/bananos/Projects/google-go-lang-idea-plugin/dist/ro.redeul.google.go.jar

BUILD SUCCESSFUL
Total time: 23 seconds

</code></pre>
<p>Make sure you specify correct <code>idea.community.build</code>  variable which should point to recently checked out IDEA community repo.</p>
<p>Unless you struggled with some critical errors, expect to find <code>*.jar</code> files:</p>
<pre><code class="bash" title="">ls -l dist/

total 1904
-rw-r--r--  1 bananos  staff  974789 Aug 21 15:55 ro.redeul.google.go.jar

</code></pre>
<p>This is a binary distribution we were looking for!</p>
<h2>Install plugin</h2>
<p>Run IDEA, and go to <code>Preferences-&gt;Plugins</code> and click <code>Install plugin from disk</code> button, then select <code>ro.redeul.google.go.jar</code> file from the previous step.</p>
<p><img class="aligncenter size-full wp-image-334" title="IDEA: Install plugin from disk" src="http://webapp.org.ua/wp-content/uploads/2013/08/idea-go-step1.png" alt="" width="901" height="468" /></p>
<h2>Install Go SDK</h2>
<p>Assuming that you&#8217;ve installed Go via <a href="http://mxcl.github.com/homebrew/">brew</a>, your Go SDK will be in <code>/usr/local/Cellar/go/1.1.1/</code></p>
<p>Go to the <code>File -&gt; Project Structure</code> and configure Go SDK by clicking <code>+</code> button and<br />
selecting <code>/usr/local/Cellar/go/1.1.1/</code> folder.</p>
<p style="text-align: center;"><img class="aligncenter size-full wp-image-334" title="IDEA: Configure Go sdk" src="http://webapp.org.ua/wp-content/uploads/2013/08/idea-go-step2.png" alt="" width="857" height="472" /></p>
<p>Make sure to add your project <code>pkg</code> folder under <code>Classpath</code> and your project sources under <code>Sourcepath</code> tabs.</p>
<h2>TL;DR</h2>
<p>For lazy ones, here is a link to <a href="/wp-content/uploads/2013/08/ro.redeul.google.go.jar">compiled binary</a>!</p>
</div>
]]></content:encoded>
			<wfw:commentRss>https://webapp.org.ua/dev/intellij-idea-and-go-plugin/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Phonegap vs. Titanium</title>
		<link>https://webapp.org.ua/dev/phonegap-vs-titanium/</link>
		<comments>https://webapp.org.ua/dev/phonegap-vs-titanium/#comments</comments>
		<pubDate>Mon, 02 Jul 2012 13:59:46 +0000</pubDate>
		<dc:creator>bananos</dc:creator>
				<category><![CDATA[dev]]></category>
		<category><![CDATA[comparison]]></category>
		<category><![CDATA[cross-platform]]></category>
		<category><![CDATA[framework]]></category>
		<category><![CDATA[html5]]></category>
		<category><![CDATA[mobile]]></category>
		<category><![CDATA[phonegap]]></category>
		<category><![CDATA[titanium]]></category>

		<guid isPermaLink="false">http://webapp.org.ua/?p=214</guid>
		<description><![CDATA[For a while we&#8217;ve been spiking on different solutions to implement mobile app for our platform, and here are some of my initial thoughts on the problem.  Given that I&#8217;m too lazy and not so enthusiastic about Objective-C for iOS or Java for Android I was searching for some solution which could deliver value from both worlds [...]]]></description>
			<content:encoded><![CDATA[<p>For a while we&#8217;ve been spiking on different solutions to implement mobile app for our platform, and here are some of my initial thoughts on the problem.  Given that I&#8217;m too lazy and not so enthusiastic about Objective-C for iOS or Java for Android I was searching for some solution which could deliver value from both worlds with minimum initial effort.</p>
<h2>Phonegap (hybrid approach)</h2>
<p><a href="http://phonegap.com/"><img class="aligncenter size-full wp-image-267" title="Phonegap logo" src="http://webapp.org.ua/wp-content/uploads/2012/05/Logo.png" alt="" width="512" height="512" /></a></p>
<p>&nbsp;</p>
<h3>Pros</h3>
<ul>
<li> Ability to develop apps in HTML5 ( means more web devices are captured)</li>
<li>Overall speed of iterative development is high (it&#8217;s almost like refreshing the page)</li>
<li>Easy to debug (remote WebKit console in Emulator)</li>
<li>It&#8217;s JavaScript!</li>
<li>Huge amount of JS-frameworks for touch devices (Sencha, iUI, jQuery mobile, iWebkit, etc) ready for use</li>
<li>Ability to make bindings to native hardware by writing Objective-C plugins</li>
<li>Good  documentation &amp; large community</li>
</ul>
<p><span id="more-214"></span></p>
<h3>Cons</h3>
<ul>
<li>Overall performance of demos is poor</li>
<li>Contact list demos with huge amount of data just crash Safari (tested on hardware)</li>
<li>Building custom GUI is limited by HTML/CSS, there is a huge risk of ending up with unresponsive UI</li>
<li>A particular weakness of Phonegap is that it&#8217;s being migrated into Apache incubator &amp; development/docs seem a bit messy</li>
<li>Adobe recently bought Phonegap &amp; most probably their focus will shift towards Adobe&#8217;s AIR platform</li>
</ul>
<h2>Titanium (native approach)</h2>
<p><a href="http://www.appcelerator.com/"><br />
<img class="aligncenter size-full wp-image-270" title="titanium_logo" src="http://webapp.org.ua/wp-content/uploads/2012/07/titanium_logo.png" alt="" width="512" height="512" /></a></p>
<h3>Pros</h3>
<ul>
<li>Javascript, no need for Objective-C</li>
<li>Resulting app is Native!</li>
<li>Possibility to fully customize GUI</li>
<li>Produce HTML5 version of your application (works in browser!)</li>
<li>Ability to write cross-platform code for Android as well (also native!)</li>
<li>Titanium IDE (a free integrated development environment based on Eclipse, <a href="http://techcrunch.com/2011/01/18/appcelerator-acquires-web-app-development-suite-aptana/">ex-Aptana</a>)</li>
<li>Ability to make bindings to native hardware by writing Objective-C plugins</li>
<li>A shift towards iPhone development first (Android comes second) — which is adequate for current market shares of both</li>
<li>Community &amp; company behind Titanium seems to be pretty responsive</li>
<li><a href="http://venturebeat.com/2011/11/01/appcelerator-raises-15m/">Appcelerator recently raised 15 million series C funding</a>, which means they are serious about the platformm &amp; will<br />
continue to improve it</li>
<li>Appcelerator is known to be largest third-party app publisher on both iOS and Android and is used by companies like NBC, Zipcar, eBay</li>
</ul>
<h3>Cons</h3>
<ul>
<li>Even though it&#8217;s Javascript, you&#8217;ll have to learn Titanium mobile API</li>
<li>Some developers had <a href="http://usingimho.wordpress.com/2011/06/14/why-you-should-stay-away-from-appcelerators-titanium/">hard time debugging their apps</a> &amp; catching memory leaks</li>
<li>Documentation is somewhat messy &amp; not as perfect if compared to Phonegap, however there is a positive improvement trend since the beginning of this year</li>
<li>A sort of platform lock-in, which means that in the long run it will be way too hard to switch to other mobile technology</li>
</ul>
<blockquote><p>Just to make it clear, Titanium does not produce fully native code from your javascript. It does not compile your code to ARM  opcodes, what it does, in fact,<br />
is binary javascript interpreter (Webkit&#8217;s JavascriptCore on iPhone, V8 on Android)</p></blockquote>
<h2>A note on hybrid approach</h2>
<p>By hybrid approach I mean usage of HTML5/javascript with hooks into native iOS/Android API calls.</p>
<p>Of course, both Titanium and Phonegap fall into the category of &#8220;hybrid&#8221; but the key difference is implementation:<br />
while Phonegap application runs inside browser, Titanium&#8217;s app runs inside javascript interpreter</p>
<p>Hybrid approach seemed like a real option, but in fact for custom/responsive GUI app you&#8217;ll inevitably need a lot of<br />
code to support native UI.  Hybrid works for small features like accessing accelerometer, camera, phone&#8217;s contacts, etc.</p>
<p>It seems that creating complex &amp; responsive UI in HTML5 is not really possible, thus UX will be pretty<br />
limited. Hybrid approach for the UI part is not a good fit from the development point of view:</p>
<ul>
<li>Large amount of platform specific UI code (Obj-C) + javascript leads to technology fragmentation which is generally bad</li>
<li>a lot of quirks to connect native platform &amp; javascript app leads to poor app design which will hurt you in long run</li>
</ul>
<h2>Conclusion</h2>
<p>As you might guess, in the end it all comes to what type of application you&#8217;re going to build. If it&#8217;s mostly data-access, satellite mobile<br />
application to your mainline app, than Titanium might be an option to consider. If you&#8217;re building something more similar to Path,<br />
you&#8217;d better start right from hiring Objective-C folks.</p>
<p>And yet another warning, if you&#8217;re looking for cross-platform mobile application development, Titanium might not be a good choice.<br />
Bad news, there&#8217;s no silver bullet here. Though, it does provide some mechanisms to do it well, but the dream of writing one single codebase<br />
and ability to produce native apps for multiple platforms is very hard to achieve.</p>
<ul>
<li>Native app for iPhone &amp; Android (rich UX, more happy users)</li>
<li>Huge company behind Titanium,  paid support which means you&#8217;ll not be left with your problems alone</li>
<li>Hundreds of successful apps already made with Titanium which fit Nimble API model (i.e. they are not standalone)</li>
</ul>
<table>
<tbody>
<tr>
<th></th>
<th>Phonegap</th>
<th>Titanium</th>
</tr>
<tr>
<th>Language</th>
<td>Javascript</td>
<td>Javascript</td>
</tr>
<tr>
<th>Dev toolkit</th>
<td>poor</td>
<td>IDE, almost full integration</td>
</tr>
<tr>
<th>Custom GUI</th>
<td>Bound by browser&#8217;s CSS engine</td>
<td>Native capabilities</td>
</tr>
<tr>
<th>3-rd party native plugins</th>
<td>Yes</td>
<td>Yes, there is even marketplace</td>
</tr>
<tr>
<th>Community</th>
<td>Large</td>
<td>Large</td>
</tr>
<tr>
<th>Documentation</th>
<td>Good</td>
<td>Good</td>
</tr>
<tr>
<th>JS skills required</th>
<td>Web-dev is enough</td>
<td>Need to learn custom APIs</td>
</tr>
<tr>
<th>App performance</th>
<td>Mediocre</td>
<td>Good</td>
</tr>
<tr>
<th>Debugging</th>
<td>Easy</td>
<td>Hard</td>
</tr>
<tr>
<th>iPhone support</th>
<td>Yes</td>
<td>Yes, first-class</td>
</tr>
<tr>
<th>Android support</th>
<td>Yes</td>
<td>Yes, second-class</td>
</tr>
</tbody>
</table>
<h2>References</h2>
<ul>
<li><a href="http://www.quora.com/Path-company-product/Is-Path-built-with-PhoneGap">Phonegap giveaways on CSS animations and location services</a></li>
<li><a href="http://www.mobileapptesting.com/native-app-or-html5-pandora-says-yes/2011/10/">Native app or html5?</a></li>
<li><a href="http://stackoverflow.com/questions/4217551/what-happens-to-javascript-code-after-app-is-compiled-using-titanium-mobile/4798547">How Titanium really works? </a></li>
</ul>
]]></content:encoded>
			<wfw:commentRss>https://webapp.org.ua/dev/phonegap-vs-titanium/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Preparing AdHoc distribution in Titanium Mobile</title>
		<link>https://webapp.org.ua/dev/preparing-adhoc-distribution-in-titanium-mobile/</link>
		<comments>https://webapp.org.ua/dev/preparing-adhoc-distribution-in-titanium-mobile/#comments</comments>
		<pubDate>Tue, 14 Feb 2012 16:39:26 +0000</pubDate>
		<dc:creator>bananos</dc:creator>
				<category><![CDATA[dev]]></category>
		<category><![CDATA[adhoc]]></category>
		<category><![CDATA[distribution]]></category>
		<category><![CDATA[ios]]></category>
		<category><![CDATA[ios code signing]]></category>
		<category><![CDATA[ios provisioning]]></category>
		<category><![CDATA[ipa]]></category>
		<category><![CDATA[mobile]]></category>
		<category><![CDATA[titanium]]></category>
		<category><![CDATA[xcode]]></category>

		<guid isPermaLink="false">http://webapp.org.ua/?p=218</guid>
		<description><![CDATA[Appcelerator Titanium is a very promising technology which allows you to write native mobile applications in Javascript for both iPhone &#38; Android. After playing around a bit with Titanium Mobile, I decided to showcase technology strengths to our stakeholders, particularly by letting them use KitchenSink demo for iOS. In order to distribute iOS application into [...]]]></description>
			<content:encoded><![CDATA[<p><img class="size-full wp-image-224 alignright" title="TITANIUM_logo1" src="http://webapp.org.ua/wp-content/uploads/2012/02/TITANIUM_logo1.png" alt="" width="325" height="325" /></p>
<p><a title="Appcelerator" href="http://www.appcelerator.com/">Appcelerator Titanium</a> is a very promising technology which allows you to write native mobile applications in Javascript for both iPhone &amp; Android.</p>
<p>After playing around a bit with Titanium Mobile, I decided to showcase technology strengths to our stakeholders, particularly by letting them use KitchenSink demo for iOS.</p>
<p>In order to distribute iOS application into real hardware you&#8217;ll have to pass through a bunch of  Apple&#8217;s obstacles including:</p>
<ul>
<li>Registering as an apple developer &amp; getting valid certificate</li>
<li>Registering your app ID</li>
<li>Creating provisioning profile for specific iPhone UDIDs</li>
<li>Mess around with certificates/private keys to properly sign your application</li>
</ul>
<p>It turns out that it&#8217;s not that easy to produce valid AdHoc distribution of your iOS app in Titanium, in this post I&#8217;m going to show you how to do it.</p>
<p>&nbsp;</p>
<p><span id="more-218"></span></p>
<p>Before we start, make sure you have latest Xcode &amp; Titanium SDK/Studio installed, as of the time of this writing Xcode version was 4.2.1, and Titanium mobile SDK was 1.8.1</p>
<p>For demo purposes we&#8217;ll use <a href="https://github.com/appcelerator/KitchenSink">KitchenSink</a> application provided as a showcase of Titanium mobile:</p>
<h2>Clone &amp; run KitchenSink in emulator</h2>
<pre><code>git clone https://github.com/appcelerator/KitchenSink.git</code></pre>
<p>Open <a href="http://www.appcelerator.com/products/titanium-studio/">Titanium Studio</a> and select <code>File-&gt;Import-&gt;Import Existing Titanium Project</code></p>
<p><a href="http://webapp.org.ua/wp-content/uploads/2012/02/tisdtudio_import_existing.png"><img class="aligncenter size-full wp-image-227" title="tisdtudio_import_existing" src="http://webapp.org.ua/wp-content/uploads/2012/02/tisdtudio_import_existing.png" alt="" width="616" height="550" /></a></p>
<p>&nbsp;</p>
<h3>Configure project for iphone only</h3>
<p><a href="http://webapp.org.ua/wp-content/uploads/2012/02/ti_configure-1.png"><img class="aligncenter size-full wp-image-238" title="ti_configure" src="http://webapp.org.ua/wp-content/uploads/2012/02/ti_configure-1.png" alt="KitchenSink configuration" width="803" height="729" /></a></p>
<h3>Run project on iOS simulator</h3>
<p><a href="http://webapp.org.ua/wp-content/uploads/2012/02/Run_on_simulator.png"><img class="aligncenter size-full wp-image-239" title="Run_on_simulator" src="http://webapp.org.ua/wp-content/uploads/2012/02/Run_on_simulator.png" alt="KitchenSink on iOS simulator" width="923" height="724" /></a></p>
<p>At this point,  Titanium will create an Xcode project for KitchenSink application. Wait for it to compile and run, then exit Simulator.</p>
<h2>Open generated Xcode project</h2>
<p><a href="http://webapp.org.ua/wp-content/uploads/2012/02/Screen-Shot-2012-02-14-at-4.58.17-PM.png"><img class="aligncenter size-full wp-image-241" title="Titanium mobile xcode project" src="http://webapp.org.ua/wp-content/uploads/2012/02/Screen-Shot-2012-02-14-at-4.58.17-PM.png" alt="Titanium mobile xcode project" width="414" height="335" /></a></p>
<p>Run Xcode, and open <code>KitchenSink.xcodeproj</code> , Objective-C code could be found at <code>kitchensink/build/iphone</code></p>
<h3>Manage project schemas</h3>
<p>In Xcode, open <code>Product-&gt;Edit scheme:</code></p>
<p><a href="http://webapp.org.ua/wp-content/uploads/2012/02/xcode_project_schema.png"></a><a href="http://webapp.org.ua/wp-content/uploads/2012/02/xcode_project_schema-1.png"><img class="aligncenter size-full wp-image-244" title="xcode project schema" src="http://webapp.org.ua/wp-content/uploads/2012/02/xcode_project_schema-1.png" alt="Xcode project schema" width="900" height="699" /></a><br />
For each schema (<code>KitchenSink, KitchenSink-iPad, KitchenSink-universal</code>)  select <code>Archive</code> and make sure that<br />
<code>Build Configuration</code> is set to <code>debug</code></p>
<p>&nbsp;</p>
<h2>Configure code signing for build targets</h2>
<p>For each target, select <code> Build Settings -&gt; Code Signing -&gt; Code Signing  Identity </code></p>
<p><a href="http://webapp.org.ua/wp-content/uploads/2012/02/code_signing.png"><img class="aligncenter size-full wp-image-245" title="code_signing" src="http://webapp.org.ua/wp-content/uploads/2012/02/code_signing.png" alt="code signing configuration for Titanium" width="909" height="699" /></a></p>
<p>Make sure to select valid provisioning identity that you previously created on Apple&#8217;s provisioning portal for a particular iOS device/application. In my case, it was called <code>com.nimble.KitchenSink</code> and provisioning profile was called <code>KitchenSink_AdHoc</code>.  For identities to be recognized by Xcode you should have been installed Apple Developer&#8217;s certificate as well as your organization certificate into MacOS keychain.</p>
<h2>Archive (produce final IPA file)</h2>
<p>Select <code>KitchenSink</code> target, then from the main menu choose <code>Product-&gt;Archive</code></p>
<p><a href="http://webapp.org.ua/wp-content/uploads/2012/02/Screen-Shot-2012-02-14-at-5.49.33-PM.png"><img class="aligncenter size-full wp-image-250" title="Xcode archive" src="http://webapp.org.ua/wp-content/uploads/2012/02/Screen-Shot-2012-02-14-at-5.49.33-PM.png" alt="Produce IPA file" width="677" height="546" /></a></p>
<p>Wait for Xcode to compile &amp; archive. You may find resulting Archive in Xcode Organizer:</p>
<p><a href="http://webapp.org.ua/wp-content/uploads/2012/02/kitchensink_archive-1.png"><img class="aligncenter size-full wp-image-254" title="kitchensink archive" src="http://webapp.org.ua/wp-content/uploads/2012/02/kitchensink_archive-1.png" alt="Kitchensink archive" width="848" height="338" /></a></p>
<p>Click &#8220;Share&#8221; and provide the same identity which was used for <code>Code Signing</code> section above:</p>
<p><a href="http://webapp.org.ua/wp-content/uploads/2012/02/ipa_provisioning.png"><img class="aligncenter size-full wp-image-257" title="ipa_provisioning" src="http://webapp.org.ua/wp-content/uploads/2012/02/ipa_provisioning.png" alt="IPA provisioning" width="728" height="491" /></a></p>
<p>Save resulting IPA file along with corresponding <code>KitchenSink_Adhoc.mobileprovision</code>   profile.</p>
<p>&nbsp;</p>
<h2>Install it on device</h2>
<p>That&#8217;s the easiest part if you&#8217;ve done everything right.  Just drag&amp;drop  mobileprovision &amp; ipa  files into iTunes and run sync with an actual iOS device.</p>
<p>If you missed something for code signing, during iTunes sync, you might encounter errors like this:</p>
<blockquote><p>The executable was signed with invalid entitlements.<br />
The entitlements specified in your application’s Code Signing Entitlements file do not match those specified in your provisioning profile.</p></blockquote>
]]></content:encoded>
			<wfw:commentRss>https://webapp.org.ua/dev/preparing-adhoc-distribution-in-titanium-mobile/feed/</wfw:commentRss>
		<slash:comments>8</slash:comments>
		</item>
		<item>
		<title>Why GWT?</title>
		<link>https://webapp.org.ua/dev/why-gwt/</link>
		<comments>https://webapp.org.ua/dev/why-gwt/#comments</comments>
		<pubDate>Mon, 10 Oct 2011 11:35:48 +0000</pubDate>
		<dc:creator>bananos</dc:creator>
				<category><![CDATA[dev]]></category>
		<category><![CDATA[GWT]]></category>
		<category><![CDATA[javascript flaws]]></category>
		<category><![CDATA[largescale javascript development]]></category>

		<guid isPermaLink="false">http://webapp.org.ua/?p=138</guid>
		<description><![CDATA[GWT is a set of tools which allows you to write javascript code in java language. That is, to avoid confusion, GWT does not have a lot in common with tons of existing Java technology stacks out there. It is designed in a such way that backing your javascript application by server build on top [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://webapp.org.ua/wp-content/uploads/2011/10/gwtlogo.jpg"><img class="alignleft size-full wp-image-233" title="gwt logo" src="http://webapp.org.ua/wp-content/uploads/2011/10/gwtlogo.jpg" alt="" width="360" height="180" /></a><br />
<a href="http://code.google.com/webtoolkit/">GWT</a> is a set of tools which allows you to write javascript code in java language. That is, to avoid confusion, GWT does not have a lot in common with tons of existing Java technology stacks out there.</p>
<p>It is designed in a such way that backing your javascript application by server build on top of Java stack becomes a huge advantage. However, it does not mean that you can&#8217;t build GWT apps backed by PHP/Python/Ruby servers which might be more lightweight solution (both from technology &amp; business points of view).</p>
<p><span id="more-138"></span></p>
<p>You can easily implement your data exchange using <a href="http://code.google.com/webtoolkit/doc/latest/tutorial/JSON.html">JSON</a> or use ports for your <a href="http://code.google.com/p/gwtphprpc/">favorite language of native GWTs RPC serialization mechanism.</a></p>
<p>One might be curious about GWT language choice, but If you&#8217;ll google a little bit about available Java projects &amp; tools, the solution google folks made, becomes very obvious. Java as a language &amp; technology <em>proven to be successful over long period of time</em>. By using Java in GWT you&#8217;re able to <em>leverage good stuff from both worlds.</em></p>
<p>The bottom-line is as following: if you want to use GWT in your project there only few prerequisites:</p>
<ul>
<li>Your devs are familiar with basic OOP principles &amp; are strong in JavaScript for modern browsers</li>
<li>You are ready to pay an upfront cost of GWT/java lurning curve &amp; overall initial slowness of development cycle</li>
</ul>
<h2 id="p2">What are the main problems GWT was designed to solve</h2>
<h3>The problem of large-scale javascript development</h3>
<p>Javascript as tool was not designed for writing huge applications, therefore it has some serious problems. Lack of tools, huge cost of maintenance, debugging issues, differences between Javascript engines, etc. (for more details see <a href="#p5">p.5</a>)</p>
<h3>The problem of building desktop-alike applications in browser (<a href="http://en.wikipedia.org/wiki/Rich_Internet_application">RIA</a>)</h3>
<p>From the very beginning you should clearly understand the difference between <em>web site</em> &amp; <em>web application</em>, because some people confuse between these two.</p>
<p><a href="http://en.wikipedia.org/wiki/Website">A web site</a> is a collection of related documents or information resources containing images, videos or other digital assets.</p>
<p><a href="http://en.wikipedia.org/wiki/Web_application">A web application</a> is an application that is accessed over a network such as the Internet or an intranet.</p>
<p>What this means, is that you have to use completely different approach for developing complex web-apps. As a consequence, your web-app will be a more like a desktop GUI application from the architectural point of view.</p>
<p>If it&#8217;s more about GUI, than you&#8217;d better use somewhat <a href="http://martinfowler.com/eaaDev/uiArchs.html">time-tested, bulletproof architectures</a> like <a href="http://en.wikipedia.org/wiki/Model%E2%80%93view%E2%80%93controller">MVC</a>/<a href="http://en.wikipedia.org/wiki/Model%E2%80%93view%E2%80%93presenter">MVP</a> and look for their implementations in your technology stack. Otherwise, without having that kind of backbone, within a couple of months, blindly coding, you&#8217;ll end up with a <a href="http://i1.irc.lv/images/qna/636686_444516.jpeg">pile of unmanageable crap.</a></p>
<p>The conclusion is as following:</p>
<blockquote><p>It&#8217;s too risky to develop large javascript apps without special tools to manage complexity</p></blockquote>
<p>What kind of tools we&#8217;re talking about? Simply put, those could be categorized as:</p>
<ul>
<li>Debugging tools (<a href="http://getfirebug.com/">Firebug</a>, <a href="http://www.microsoft.com/download/en/details.aspx?id=18359">IE Dev tools</a>, <a href="http://code.google.com/chrome/devtools/docs/overview.html">Webkit developer tools</a>, etc.)</li>
<li>Packaging/optimization/obfuscation tools (<a href="http://developer.yahoo.com/yui/compressor/">YUI Compressor</a>, <a href="http://code.google.com/closure/compiler/docs/gettingstarted_ui.html">Closure Compiler</a>, <a href="http://www.crockford.com/javascript/jsmin.html">JSMin</a>, etc. )</li>
<li>Abstraction layers implemented as frameworks/libraries (<a href="http://jquery.com/">jQuery</a>, <a href="http://jqueryui.com/">jQuery UI</a>, <a href="http://developer.yahoo.com/yui/">YUI Library</a>, <a href="http://www.sproutcore.com/">SproutCore</a>, <a href="http://javascriptmvc.com/">Javascript MVC</a>, <a href="http://cappuccino.org/">Cappuccino</a>, <a href="http://persistencejs.org/">PersistenceJS</a>, etc.)</li>
</ul>
<p>Each of these tools focuses on a number of particular problems: crossbrowser issues(jQuery), building consistent GUI(jQueryUI), abstracting data layer(PersistenceJS), offering a full implementation stack of well-known architecture pattern (Sproutcore, Javascript MVC).</p>
<p>It&#8217;s up to you wether to use them or not, but in 2009, when we made evaluation(see spikes section <a href="#p7">p.7</a>) none of mentioned solutions proven to meet our needs. Some of them were pretty buggy, others were not mature enough and some of them didn&#8217;t have a strong community.</p>
<p>As you probably see, there are tons of different ways on how to write your webapp in javascript, but</p>
<blockquote><p><a href="http://www.reddit.com/r/javascript/comments/c9yzq/how_do_you_guys_architect_large_projects_with_js/">there&#8217;s no stable and consistent technology</a> <a href="http://stackoverflow.com/questions/5095525/approach-to-handle-javascript-on-bigger-projects">which is <em>widely adopted</em></a> <a href="http://www.slideshare.net/fjakobs/masterin-large-scale-java-script-applications">for developing large-scale <em>webapps</em></a></p></blockquote>
<h2 id="p4">Should I use GWT or just stick with modern Javascript/HTML5 stack?</h2>
<p>That is not the right question to ask. It&#8217;s not wether you should use GWT or not, but <em>what kind of user experience do you want to deliver?</em></p>
<p>As I already mentioned, GWT will allow you to build feature-rich user interfaces and deliver desktop-alike experience to your end users: almost instant action response, rich interactions with <em>complex business logic</em>. GWT is not for creating web-sites, however your application will be run in browser. From this point of view, browser is just a way to deliver application to your customers.</p>
<p>Check this out, if you&#8217;re still in doubt by making your decision in favor of GWT:</p>
<ul>
<li><a href="http://stackoverflow.com/questions/4463252/when-to-use-gwt-and-when-to-not">When to use GWT and when to not</a></li>
<li><a href="http://stackoverflow.com/questions/4385117/gwt-for-big-projects">GWT for big projects</a></li>
<li><a href="http://stackoverflow.com/questions/3949044/projects-that-were-build-with-gwt/">Projects that were build with GWT</a></li>
</ul>
<p>Of course, no-one can prohibit you from building your RIA by means of modern HTML5 technologies, using plain JavaScript. But you must be aware that this will probably work only for tiny projects. Why?</p>
<h2 id="p5">Javascript flaws</h2>
<p>As you might heard, Javascript was invented as a tool for scripting purposes by <a href="http://en.wikipedia.org/wiki/Brendan_Eich">Netscape developers</a>. The main goal of javascript was to write small programs which would enhance behavior of web pages.</p>
<p>Later on, it was adopted in other areas as a general tool for automation by system administrators, graphic artists, 3D modeling industry, etc.</p>
<p>An important thought here, is that javascript was not designed for writing real-world complex apps from the beginning:</p>
<ul>
<li>No package mechanism</li>
<li>By default everything is in the global namespace</li>
<li>Only basic building blocks for OOP</li>
<li><a href="http://taggedzi.com/blog/display/debugging-javascript-in-ie">Debugging</a> <a href="http://developer.appcelerator.com/question/27731/javascript-debugging">might</a> be a <a href="	http://www.devarticles.com/c/a/JavaScript/Debugging-in-Javascript/">real</a> <a href="http://www.codestore.net/store.nsf/unid/DOMT-5UBUVW">nightmare</a></li>
<li>Lack of development tools</li>
<li><a href="http://c2.com/cgi/wiki?JavaScriptFlaws">Javascript has its own flaws as a language</a></li>
<li>Scales pretty bad on a large number of developers</li>
</ul>
<p>That said, you&#8217;ll <em>inevitably need a special tooling to develop large apps in javascript</em></p>
<h2>Pros &amp; cons of GWT</h2>
<h3>Pros:</h3>
<ul>
<li>Mature technology stack backed by Java(OOP &amp; strong typing is a huge win on large projects)</li>
<li>Debugging tools</li>
<li>By using Java, code maintenance &amp; refactoring becomes really fun to do</li>
<li>Comprehensive, easily restyled widget library + <a href="http://code.google.com/webtoolkit/tools/gwtdesigner/index.html">GWT designer</a> to build complex GUI interfaces</li>
<li>Security against JavaScript attacks</li>
<li>Logging</li>
<li>Accessibility</li>
<li>Internationalization</li>
<li>Data transport / management mechanisms</li>
<li>Crossbrowser</li>
<li>MVP framework</li>
<li>Unit testing framework</li>
<li>HTML5 support</li>
<li>Open-source</li>
<li>Tons of great libraries &amp; frameworks (<a href="http://code.google.com/p/mvp4g/">Mvp4g</a>, <a href="http://code.google.com/p/gwtquery/">GwtQuery</a>)</li>
<li>Strong and active community, supported by Google</li>
<li><a href="http://code.google.com/eclipse/">Deployment</a> &amp; <a href="http://code.google.com/webtoolkit/speedtracer/">optimization</a> tools</li>
<li>Scales well by increasing number of developers</li>
</ul>
<p>And one of the major advantages of GWT is:</p>
<blockquote><p>At the end, it&#8217;s still javascript, which means that you can <em>leverage all existing javascript/HTML5 technologies</em> either by using plugins or by writing native javascript through <a href="http://code.google.com/webtoolkit/doc/latest/DevGuideCodingBasicsJSNI.html">JSNI</a></p></blockquote>
<h3>Cons:</h3>
<ul>
<li>Initial java-related overhead for setup/configuration (<a href="http://code.google.com/webtoolkit/doc/latest/DevGuideCompilingAndDebugging.html">dev-mode</a>, special plugins for modern browsers, etc.)</li>
<li>Speed of development is highly affected, you need top-notch hardware to comfortably write code</li>
<li>A lot of data abstraction layers are highly coupled with Java backends</li>
<li>Relatively high entrance threshold for new developers</li>
</ul>
<p>You might want to check out <a href="http://en.wikipedia.org/wiki/Comparison_of_JavaScript_frameworks ">feature comparisons matrix for different javascript frameworks</a> as well.</p>
<h2>Spike scenarios to examine different technology stacks</h2>
<ul>
<li><strong>Data abstraction, packaging, event-binding spike.</strong> There should be a simple form with one textfield. As you type, 2 different widgets on the test page should update themselves with a data from textfield. Those 2 widgets should be controlled by independent business logic in separated packages(modules) of application.</li>
<li><strong>Form validation spike.</strong> This will examine how easy it is to validate user data, including validation made on server-side.</li>
</ul>
<p>By implementing first spike &amp; evaluating your solution, ask yourself about units of functionality that will make up your future application:</p>
<ul>
<li>How will those pieces be organized into units of code?</li>
<li>How will those pieces communicate with each other?</li>
<li>How will dependencies between components be expressed and managed while adhering to the principle of loose coupling?</li>
<li>How will components manifest themselves in the DOM? Do they need to?</li>
<li>How will we persist data across URL and page loads?</li>
<li>How will we manage communication with the server?</li>
<li>How will we make sure users only see the data they’re allowed to see?</li>
</ul>
<p>There is no spike whatsoever which can show you strengths of GWT in managing large-scale apps right away. This is obvious — until you&#8217;re going to play with some trivial samples, it might look as an unnecessary technology overhead. But it greatly pays off in the long run. Our 2+ years of frontend development proved GWT to be the right choice.</p>
<p>You might be interested to investigate <a href="http://stackoverflow.com/questions/3949044/projects-that-were-build-with-gwt/">why others are using GWT</a> &amp; <a href="http://gwtgallery.appspot.com/">what are the type of projects being built</a>.</p>
<h2>Hidden cost of transition from GWT to javascript</h2>
<p>What if, after huge investment in GWT you decided to switch back to Javascript?</p>
<p>That is a pretty serious question from the business perspective. Remember, that we&#8217;re talking about apps here, not web-pages. This means, that your existing GWT application already carries a lot of <em>complex business logic</em>, it&#8217;s <em>not a simple presentation layer</em> as one might think.</p>
<p>Keeping this in mind, you&#8217;ll probably end up with:</p>
<ul>
<li>Complete rewrite of application (you&#8217;d better want to spent this time for new valued features to compete in your market, don&#8217;t you?)</li>
<li>Hiring pretty expensive javascript-gurus (you don&#8217;t want those numerous folks writing random jQuery snippets to develop your complex business-logic app, do you?)</li>
</ul>
<p>From these points of view, transition doesn&#8217;t seem to be a good idea, even though you might find out that GWT resources are pretty expensive. The trick why those folks are so expensive is that they specialize a lot on GWT backend stacks, which is an enterprise class java technologies. Instead, if your back-end stack is non-java, you could happily hire senior javascript guys &amp; easily convert them into GWT devs. Our 2+ years experience showed that it works pretty well — monthly learning curve and your dev-team is able to use all of GWT strengths.</p>
<h2>How to leverage existing Javascript solutions?</h2>
<p>Javascript is so widespread today and there are tons of cool stuff already built. How is it possible to grab some piece from that tasteful cake?</p>
<p>You&#8217;re probably looking at these:</p>
<ul>
<li>Cost of javascript resources is pretty attractive</li>
<li>Re-use of existing open-source javascript code</li>
</ul>
<p>But wait, is GWT <em>really</em> java? Nope. At the end it&#8217;s the same old javascript which is used everywhere. What this means for you as business, is that you could still leverage <em>any javascript solutions</em> out there.</p>
<p>In the case of existing GWT application, the solution seems to be pretty obvious. Core GUI front-end may be maintained using GWT &amp; third-party extensions can be easily built using plain javascript. However, this does bring a few of technical problems:</p>
<ul>
<li>There is a need to invent a well designed interface for integration of GWT Core app and third-party javascript</li>
<li>There is a problem of css-styling of core app by means of third-party extensions</li>
</ul>
<p>Those are a real <em>technical</em> problems, which you just need to spent some time to resolve. This way, you&#8217;ll continue to happily use GWT for the &#8220;core&#8221; stuff &amp; leverage javascript extensions which might add a huge value to your application.</p>
]]></content:encoded>
			<wfw:commentRss>https://webapp.org.ua/dev/why-gwt/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Python vs. PHP duck typing</title>
		<link>https://webapp.org.ua/dev/python-vs-php-duck-typing/</link>
		<comments>https://webapp.org.ua/dev/python-vs-php-duck-typing/#comments</comments>
		<pubDate>Fri, 12 Aug 2011 12:44:38 +0000</pubDate>
		<dc:creator>bananos</dc:creator>
				<category><![CDATA[dev]]></category>
		<category><![CDATA[duck typing]]></category>
		<category><![CDATA[php]]></category>
		<category><![CDATA[python]]></category>
		<category><![CDATA[typecast]]></category>

		<guid isPermaLink="false">http://webapp.org.ua/?p=128</guid>
		<description><![CDATA[Having previous experience in writing PHP code could potentially lead you to hours of debugging in Python. Consider the following simple example in PHP: PHP $s = "0"; $my = (bool) $s; var_dump($s); var_dump($my) And the output would be: string(1) "0" bool(false) Which is pretty expectable behavior in PHP, since it first casts string to [...]]]></description>
			<content:encoded><![CDATA[<p>Having previous experience in writing PHP code could potentially lead you to hours of debugging in Python.<br />
Consider the following simple example in PHP:</p>
<h2>PHP</h2>
<pre><code class="php">
$s = "0";
$my = (bool) $s;

var_dump($s);
var_dump($my)
</code>
</pre>
<p><span id="more-128"></span></p>
<p>And the output would be:</p>
<pre><code class="bash">
string(1) "0"
bool(<strong>false</strong>)
</code></pre>
<p>Which is pretty expectable behavior in PHP, since it first casts string to int, and than to boolean.</p>
<p>Consider the same example in Python:</p>
<h2>Python</h2>
<pre><code class="python">
s = "0"
my = bool(s)
print type(s), s
print type(my), my
</code>
</pre>
<p>And the output would be:</p>
<pre><code class="bash">

&lt;type 'str'&gt; 0
&lt;type 'bool'&gt; <strong>True</strong>

</code></pre>
<p>We&#8217;re not going to debate here wether this is good or bad, but you should be aware such things before they&#8217;ll steal hours of your time</p>
<p>To achieve the same behavior as in PHP, you&#8217;ll need to add explicit integer typecast:</p>
<pre><code class="python">
s = "0"
my = bool(int(s))
print type(s), s
print type(my), my
</code>
</pre>
<p>And the output would be:</p>
<pre><code class="bash">

&lt;type 'str'&gt; 0
&lt;type 'bool'&gt; <strong>False</strong>

</code></pre>
]]></content:encoded>
			<wfw:commentRss>https://webapp.org.ua/dev/python-vs-php-duck-typing/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Syntax highlighting for Nano on Mac OS X</title>
		<link>https://webapp.org.ua/dev/syntax-highlighting-for-nano-on-mac-os-x/</link>
		<comments>https://webapp.org.ua/dev/syntax-highlighting-for-nano-on-mac-os-x/#comments</comments>
		<pubDate>Fri, 22 Jul 2011 14:12:07 +0000</pubDate>
		<dc:creator>bananos</dc:creator>
				<category><![CDATA[dev]]></category>
		<category><![CDATA[nano]]></category>
		<category><![CDATA[osx]]></category>
		<category><![CDATA[syntax highlighting]]></category>

		<guid isPermaLink="false">http://webapp.org.ua/?p=109</guid>
		<description><![CDATA[Nano is one of my favorite text editors, for a couple of reasons It&#8217;s very simple (as campared to Vim, which I was not able to quickly grasp on) It&#8217;s available by default on almost any *nix distro out there It has syntax highlighting (always turned off by default for some reason) It this post [...]]]></description>
			<content:encoded><![CDATA[<p><img src="http://webapp.org.ua/wp-content/uploads/2011/07/colorsyntax.png" alt="" /><br />
<a href="http://www.nano-editor.org/">Nano</a> is one of my favorite text editors, for a couple of reasons</p>
<ul>
<li>It&#8217;s very simple (as campared to Vim, which I was not able to quickly grasp on)</li>
<li>It&#8217;s available by default on almost any *nix distro out there</li>
<li>It has syntax highlighting (always turned off by default for some reason)</li>
</ul>
<p>It this post I&#8217;ll show you how to install latest Nano to your Mac OS X environment with syntax highlighting turned on for most of programming&amp;markup languages.</p>
<p><span id="more-109"></span><br />
For managing my OSX packages I&#8217;m using <a href="https://github.com/mxcl/homebrew">brew</a>, but unfortunately it does not have nano formula yet. Built-in version of nano is pretty outdated (2.0.6), and there is no binaries available exclusively for mac. So we&#8217;re going to do  a classic configure-make-install dance.</p>
<h2>Step1. Download nano sources</h2>
<p><code>wget http://www.nano-editor.org/dist/v2.2/nano-2.2.6.tar.gz<br />
</code></p>
<p>&nbsp;</p>
<h2>Step2. Download syntax highlighting configs for nano</h2>
<pre><code class="bash">wget http://webapp.org.ua/wp-content/uploads/2011/07/nanorc.tar</code></pre>
<p>These are compiled from different sources over the internet with some small mods made by myself.</p>
<h2>Step3. Compile &amp; install</h2>
<pre><code class="bash">
tar -xvvf nano-2.2.6.tar.gz
cd nano-2.2.6
sudo ./configure --prefix=/usr/
sudo make install
cd /
sudo tar -xvvf nanorc.tar
</code></pre>
<p>At this point you&#8217;re done. Latest nano with syntax highlighting will be installed at your system paths.</p>
]]></content:encoded>
			<wfw:commentRss>https://webapp.org.ua/dev/syntax-highlighting-for-nano-on-mac-os-x/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>Compiling uWSGI from sources</title>
		<link>https://webapp.org.ua/dev/compiling-uwsgi-from-sources/</link>
		<comments>https://webapp.org.ua/dev/compiling-uwsgi-from-sources/#comments</comments>
		<pubDate>Fri, 03 Jun 2011 08:33:47 +0000</pubDate>
		<dc:creator>bananos</dc:creator>
				<category><![CDATA[dev]]></category>
		<category><![CDATA[compile]]></category>
		<category><![CDATA[libxml2]]></category>
		<category><![CDATA[patching]]></category>
		<category><![CDATA[uwsgi]]></category>

		<guid isPermaLink="false">http://webapp.org.ua/?p=86</guid>
		<description><![CDATA[&#160; As you probably know, uWSGI is a fast application container for serving your webapps. It is often used with Django against nginx webserver. Written in pure C &#38; having a lot of other cool features. It seems that installation of uWSGI is pretty simple according to official docs but it isn&#8217;t. If you want [...]]]></description>
			<content:encoded><![CDATA[<p><img class="alignleft size-full wp-image-88" src="http://webapp.org.ua/wp-content/uploads/2011/06/logo_uWSGI.png" title="logo_uWSGI"  alt="uWSGI" width="236" height="73" /></p>
<p>&nbsp;</p>
<p>As you probably know,  uWSGI is a fast application container for serving your webapps. It is often used with <a href="www.djangoproject.com/">Django</a> against <a href="nginx.org">nginx</a> webserver. Written in pure C &amp; having a lot of other <a href="http://projects.unbit.it/uwsgi/wiki">cool features</a>.</p>
<p>It seems that installation of uWSGI is pretty simple according to <a href="http://projects.unbit.it/uwsgi/wiki/Install">official docs</a> but it isn&#8217;t.<br />
<span id="more-86"></span></p>
<p>If you want to deploy your Django app on a brand new linux box (VPS/Amazon EC2), using buildout without a lot of dependencies things become more complicated.</p>
<p>Here is how you can tune up your uWSGI:</p>
<pre><code class="no-highlight">wget http://projects.unbit.it/downloads/uwsgi-0.9.7.2.tar.gz
tar -xvvf  uwsgi-0.9.7.2.tar.gz
cd uwsgi-0.9.7.2</code></pre>
<p>If  you&#8217;ll simply run <code>make</code> as this point, you&#8217;ll experience  something like this:</p>
<pre><code> *** libxml2 headers unavailable. uWSGI build is interrupted. You have to install libxml2 development package or use libexpat or disable XML </code></pre>
<p>Since uWSGI needs libxml2 for reading XML configs, which is only one of the available configuration options (<a href="http://projects.unbit.it/uwsgi/wiki/Doc">command line</a>, <a href="http://projects.unbit.it/uwsgi/wiki/UseEnv">environment variables</a>, <a href="http://projects.unbit.it/uwsgi/wiki/Example">XML</a>, <a href="http://projects.unbit.it/uwsgi/wiki/INIFiles">.ini</a>, yaml files and via <a href="http://projects.unbit.it/uwsgi/wiki/useLDAP">LDAP</a>.), we&#8217;re going to drop this dependency (I&#8217;m more comfortable with command-line style)</p>
<p>It&#8217;s not obvious how to drop libxml2 dependency, because there&#8217;s no configure &amp; usual C-style make. Instead, build is fully controlled by <code>uwsgiconfig.py</code> script, which you can grok for a while to get a grasp on how the whole process works.</p>
<p>Build options are stored in <code>buildconf/ folder</code>:</p>
<pre><code class="no-highlight">root@devbox:~/server/thirdparty/uwsgi-0.9.7.2# ls -l buildconf/
total 64
-rw-r--r-- 1 root root  50 Apr  6 10:50 core.ini
-rw-r--r-- 1 root root 497 Apr  6 10:50 default.ini
-rw-r--r-- 1 root root  54 Apr  6 10:50 erlang.ini
-rw-r--r-- 1 root root  49 Apr  6 10:50 lua.ini
-rw-r--r-- 1 root root  40 Apr  6 10:50 luap.ini
-rw-r--r-- 1 root root 485 Apr  6 10:50 modular.ini
-rw-r--r-- 1 root root  78 Apr  6 10:50 package.ini
-rw-r--r-- 1 root root  50 Apr  6 10:50 psgi.ini
-rw-r--r-- 1 root root  60 Apr  6 10:50 pyerl.ini
-rw-r--r-- 1 root root  86 Apr  6 10:50 pylua.ini
-rw-r--r-- 1 root root 462 Apr  6 10:50 pyrb.ini
-rw-r--r-- 1 root root  69 Apr  6 10:50 rack.ini
-rw-r--r-- 1 root root 449 Apr  6 10:50 rackp.ini
-rw-r--r-- 1 root root 377 Apr  6 10:50 unbit.ini
-rw-r--r-- 1 root root 108 Apr  6 10:50 unbitstaff.ini</code></pre>
<p>For our customized build we&#8217;ll create a new build config, called <code>myproject.ini</code>:</p>
<pre><code class="no-highlight">root@devbox:~/server/thirdparty/uwsgi-0.9.7.2/buildconf# cp default.ini myproject.ini </code></pre>
<p>He&#8217;re how internals should look like if you want to turn off libxml2 support:</p>
<pre><code class="ini">
[uwsgi]
xml = false
ini = true
yaml = true
snmp = true
sctp = false
spooler = true
embedded = true
udp = true
multicast = true
threading = true
sendfile = true
minterpreters = true
async = true
evdis = false
ldap = auto
pcre = auto
debug = false
unbit = false
; xml_implementation = libxml2
plugins =
bin_name = uwsgi
plugin_dir = .
embedded_plugins = python, ping, nagios, rpc, fastrouter, http, ugreen

locking = auto
event = auto
timer = auto
filemonitor = auto

[python]
paste = true
web3 = true
</code></pre>
<p>At this point you&#8217;re ready to type</p>
<pre><code class="no-highlight"> python uwsgiconfig.py --build myproject </code></pre>
<p>In theory this should build you a brand-new uWSGI, but only in theory. Probably, what you&#8217;ll get by doing above command will be:</p>
<pre><code class="no-highlight">using profile: buildconf/myproject.ini
*** uWSGI compiling server core ***
gcc -pthread -c utils.c -o utils.o -O2 -Wall -Werror -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64  -fno-strict-aliasing -Wextra -Wno-unused-parameter -Wno-missing-field-initializers -DUWSGI_BUILD_DATE="\"03 June 2011 09:10:42\"" -DUWSGI_LOCK_USE_MUTEX -DUWSGI_EVENT_USE_EPOLL -DUWSGI_EVENT_TIMER_USE_TIMERFD -DUWSGI_EVENT_FILEMONITOR_USE_INOTIFY
gcc -pthread -c protocol.c -o protocol.o -O2 -Wall -Werror -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64  -fno-strict-aliasing -Wextra -Wno-unused-parameter -Wno-missing-field-initializers -DUWSGI_BUILD_DATE="\"03 June 2011 09:10:42\"" -DUWSGI_LOCK_USE_MUTEX -DUWSGI_EVENT_USE_EPOLL -DUWSGI_EVENT_TIMER_USE_TIMERFD -DUWSGI_EVENT_FILEMONITOR_USE_INOTIFY
gcc -pthread -c socket.c -o socket.o -O2 -Wall -Werror -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64  -fno-strict-aliasing -Wextra -Wno-unused-parameter -Wno-missing-field-initializers -DUWSGI_BUILD_DATE="\"03 June 2011 09:10:42\"" -DUWSGI_LOCK_USE_MUTEX -DUWSGI_EVENT_USE_EPOLL -DUWSGI_EVENT_TIMER_USE_TIMERFD -DUWSGI_EVENT_FILEMONITOR_USE_INOTIFY
gcc -pthread -c logging.c -o logging.o -O2 -Wall -Werror -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64  -fno-strict-aliasing -Wextra -Wno-unused-parameter -Wno-missing-field-initializers -DUWSGI_BUILD_DATE="\"03 June 2011 09:10:42\"" -DUWSGI_LOCK_USE_MUTEX -DUWSGI_EVENT_USE_EPOLL -DUWSGI_EVENT_TIMER_USE_TIMERFD -DUWSGI_EVENT_FILEMONITOR_USE_INOTIFY
gcc -pthread -c master.c -o master.o -O2 -Wall -Werror -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64  -fno-strict-aliasing -Wextra -Wno-unused-parameter -Wno-missing-field-initializers -DUWSGI_BUILD_DATE="\"03 June 2011 09:10:42\"" -DUWSGI_LOCK_USE_MUTEX -DUWSGI_EVENT_USE_EPOLL -DUWSGI_EVENT_TIMER_USE_TIMERFD -DUWSGI_EVENT_FILEMONITOR_USE_INOTIFY
cc1: warnings being treated as errors
master.c: In function ‘uwsgi_subscribe’:
master.c:74: error: implicit declaration of function ‘send_udp_message’</code></pre>
<p>and your build will miserably fail</p>
<p>To fix that, you need to edit  <code>uwsgiconfig.py</code>, find following line:</p>
<pre><code class="python">self.cflags = ['-O2', '-Wall', '-Werror', '-D_LARGEFILE_SOURCE', '-D_FILE_OFFSET_BITS=64'] + os.environ.get("CFLAGS", "").split()</code></pre>
<p>and remove <code> -Werror </code></p>
<p>In case you want to do it automatically by your deployment scripts, here is a small sed snippet:</p>
<pre><code class="no-highlight">sed  -ie "s#'-Werror',##g" uwsgiconfig.py</code></pre>
<p>After patching <code>uwsgiconfig.py </code> you&#8217;re ready to rock&amp;roll:</p>
<pre> <code class="no-highlight"> python uwsgiconfig.py --build myproject</code></pre>
]]></content:encoded>
			<wfw:commentRss>https://webapp.org.ua/dev/compiling-uwsgi-from-sources/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>
