2012年7月26日 星期四

[iOS] JB program writting


iOS下面的APP限制蠻多的 (ex: 進入背景之後, 最多只有10min可以作網路相關的事情), 如果想要突破限制就得要JB, 紀錄一下如何寫JB之後的程式.

在iOS底下, 所有的APP可以放在兩個地方/Applications/<your app>.app and /var/mobile/Applications/<id>/<your app>.app (一般經由iTune or XCode 安裝的APP都會在此), 所有在/var/mobile/Applications的app 都會跑在自己的sandbox, 而且也沒有讀取整個系統的權限, 為了能夠突破iOS的限制, 以下是如何產生可以直接安裝到/Applications 取得root 權限 APP作法 (注意必須手機要經過JB):

一般都是使用 Theos 來產生你想要得APP project.

安裝步驟:
安裝iOS SDK
安裝theos
利用theos建立新的project (可以看到自動幫你產生出的檔案)

$ export THEOS=/opt/theos
$ svn co http://svn/howett.net/svn/theos/trunk $THEOS
$ curl -s http://dl.dropbox.com/u/3157793/ldid > ~/Desktop/ldid
$ chmod +x ~/Desktop/ldid
$ mv ~/Desktop/ldid $THEOS/bin/ldid
$ sudo port install dpkg
$ ./$THEOS/bin/nic.pl
IC 1.0 - New Instance Creator
------------------------------
  [1.] iphone/application
  [2.] iphone/library
  [3.] iphone/preference_bundle
  [4.] iphone/tool
  [5.] iphone/tweak
Choose a Template (required): 1
Project Name (required): zzz
Package Name [com.yourcompany.zzz]: 
Author/Maintainer Name [ytshen]: zzz
Instantiating iphone/application in zzz/...
Done.
$ls zzz
Makefile              RootViewController.h  control               theos
Resources             RootViewController.mm main.m                zzzApplication.mm
$


從Makefile上面你可以更改你的application name, 所有你需要compile object-c file (ex: .m .mm), 還有你需要include的framework:

include theos/makefiles/common.mk                                                                               
                                                                                                                
APPLICATION_NAME = xxx                                                                                 
xxx_FILES = main.m XXXApplication.mm RootViewController.mm 
xxx_FRAMEWORKS = UIKit CoreGraphics 
                                                                                                                
include $(THEOS_MAKE_PATH)/application.mk


接下來就是要如何build project, 並且deploy到手機上面:

$ export SDKVERSION=5.1
$ export THEOS_DEVICE_IP=192.168.1.11

# build project
$ make
Making all for application xxx...
 Compiling main.m...
 Compiling XXXApplication.mm...
 Compiling RootViewController.mm...
 Linking application XXX...
 Stripping XXX...
 Signing XXX...

# build deb
$ make package
Making all for application CameraUpload...
make[2]: Nothing to be done for `internal-application-compile'.
Making stage for application XXX...
 Copying resource directories into the application wrapper...
dpkg-deb: building package `com.ttt.xxx' in `./com.ttt.xxx_0.0.1-50_iphoneos-arm.deb'.

# install deb in device 
$ make package install


其他像是你想要更改APP icon或是跟一些resource相關, 你可以修改 Resource/Info.plist 達到你的要求.

Debugging:
使用這種方式的APP在debug上面沒辦法使用xcode的debug console, 所以只能透過syslog. 所以你可以透過Cydia安裝 "Erica Utilities" (for 'tail' utility), "Mobile Terminal", "OpenSSH", "SBSettings", "syslogd", "Syslog Toggle" 來達到debug的目的 安裝完之後, 你就可以透過ssh連上device在上面直接觀看syslog log.

root# tail -f /var/log/syslog 
Jul 27 13:19:16 hayokushin-mato-iPhone com.apple.launchd[1] (com.ikey.bbot): (com.ikey.bbot) Throttling respawn: Will start in 10 seconds
Jul 27 13:19:16 hayokushin-mato-iPhone syncdefaultsd[1374]: com.apple.stocks has no valid com.apple.developer.ubiquity-kvstore-identifier entitlement
Jul 27 13:19:16 hayokushin-mato-iPhone syncdefaultsd[1374]: Can't get application info for com.apple.stocks
Jul 27 13:19:31 hayokushin-mato-iPhone syncdefaultsd[1374]: com.apple.stocks has no valid com.apple.developer.ubiquity-kvstore-identifier entitlement

Reference:

2012年6月17日 星期日

[TCP] TIME_WAIT state


Usually when I terminate the server and want to bind the port again, it will show some error that I can not bind the port because the port is in TIME_WAIT state. As a result, I will need to set socket option (SO_REUSEADDR) to re-bind the port. In the past, I only know that there is some work left inside the kernel to handle the connection (from http://stackoverflow.com/questions/577885/uses-of-so-reuseaddr). But according to the link in the bottom, there could be two issues which we need TIME_WAIT state!


  1. there is no way to be sure that the last ack was communicated successfully, TIME_WAIT to make sure it can wait and retransmission last ack if the other end sned FIN again.
  2. there may be "wandering duplicates" left on the net that must be dealt with if they are delivered.


More detail in TIME_WAIT explainthis and protocol design implication

2012年4月22日 星期日

[C++] class member pointer usage

Use C++ member pointer for container.
#include <iostream>
#include <vector>
#include <map>
#include <functional>
                
class Foo       
{               
public:         
    Foo() {}    
    ~Foo() {}   
    int A(int a)
    {           
        return a+1;
    }             
    int B(int a)
    {           
        return a+2;
    }           
};              
                
int main()      
{               
    // use mem_fun_ref which can be used for for_each ... etc
    std::vector<std::mem_fun1_ref_t<int, Foo, int> > vec;   
    std::map<std::string, std::mem_fun1_ref_t<int, Foo, int> > map1;
    Foo a;      
    std::string s("aa");
                
    vec.push_back(std::mem_fun_ref(&Foo::A));
    map1.insert(std::pair<std::string, std::mem_fun1_ref_t<int, Foo, int> >(s, std::mem_fun_ref(&Foo::A)));
    std::cout << vec[0](a, 1) << std::endl;
    std::cout << map1.begin()->second(a, 2) << std::endl;   
                
    // use function pointer directly
    typedef int (Foo::*FuncPtr)(int);
    std::vector<FuncPtr> vec2;
    vec2.push_back(&Foo::A);
    vec2.push_back(&Foo::B);
    std::cout << (a.*(vec2[1]))(3) << std::endl; // it should be 5
                
    std::map<std::string, FuncPtr> map2;
    map2[s] = &Foo::B;
    std::cout < (a.*(map2[s]))(3) < std::endl; // it should be 5
    return 0;   
}               

2012年1月28日 星期六

[PThread] condition variable usage pattern

producer/consumer model. The return value for each pthread function call need to be checked too.

Producer:


while(/* condition for producer to contintue */)
{
pthread_mutex_lock(&mutex);

// do something for producer

// the order of the two following call is not important
// unlock before signal may more efficient than signal before unlock
pthread_mutex_unlock(&mutex);
pthread_cond_signal(&cond);
}

Consumer:


while(/* condition for consumer to continue */)
{
// must contain lock before calling condition wait
pthread_mutex_lock(&mutex);

// the condition wait need to be recheck for
// 1. spurious wakeup
// 2. other thread can be waken early
while(/* condition to check for state not valid */)
{
s = pthread_cond_wait(&cond, &mutex);
}
// do consumer work, now under mutex protection
pthread_mutex_unlock(&mutex);
// some other work which don't need mutex
}

Spurious wakeup:
Some condition wait implementation can cause the thread to be waken up when no signal to the condition variable.
man pthreadconidsignal for further detail.

2012年1月15日 星期日

[TCP] some tuning options

The IPTOS_LOWDELAY keyword is most appropriate for low-delay networks such as LANs, while IPTOS_THROUGHPUT is for higher-latency WAN links. Your network may be configured differently, so it's possible that using the options might have the opposite effect.

The TCP_NODELAY option disables the Nagle algorithm.

If you have firewalls or other devices that keep state in your network, you may be interested in the SO_KEEPALIVE option, which turns on TCP keepalives.

$ netstat -d -i 2

Every 2 seconds, the status of the available interfaces is shown. In the example above, the RX-OK and TX-OKcolumns show that packets are flowing in and out. The errors, drops, and overruns are all 0 in both directions, showing that there has been no packet loss.


2012年1月9日 星期一

[C++] Exception-safe code



Some guide

Exception-safe definition:
- Basic
    invariants and no resource are leaked
- Strong
    operations has either completed successfully or throw exception leaving program
    state exactlyly as it was before the operation started
- No-throw
    operation will not emit an exception

Exception guide line:
- Throw by value
- Catch by reference
- no exception specification
                                                                                                                                                                                                           
* function can not template partial specialization

Some code example:

#include <iostream>     
void foo() throw ()
{                  
    // it will cause abort 
    // because it throw when the exception specification said NO
    throw(1);      
}                  
                   
void goo()         
{                  
    try {          
        int a = 1; 
        throw(1);  
    } catch(...) { 
        // this will cause abort too 
        // because you can not rethrow in catch statement
        throw;     
    }              
}                  
                   
/*                 
 * The following is the C API for C++ library pattern to handle exception
 */                
                   
int getReturnCodeFromException()
{                  
    try {          
        // rethrow 
        throw;     
    } catch(int a) 
    {              
        return -1; 
    } catch(double b)
    {              
        return -2; 
    }              
    // for each type of exception, you can create different return code
    // ...         
}                  
void cppAPI1()
{           
    throw (1);
}           
            
            
void cppAPI2()
{           
    throw (1.12);
}           
            
int cAPI1() 
{           
    try {   
        cppAPI1();
    } catch(...) {                           
        int rc = getReturnCodeFromException();
        return rc;
    }       
}           
            
int cAPI2() 
{           
    try {   
        cppAPI2();
    } catch(...) {                           
        int rc = getReturnCodeFromException();
        return rc;
    }       
}           
            
int main()  
{           
//    foo();
//    goo();
    std::cout << "cAPI1 rc = " << cAPI1() << std::endl;
    std::cout << "cAPI2 rc = " << cAPI2() << std::endl;
    return 0;
}                                
Reference http://exceptionsafecode.com/

2012年1月6日 星期五

[C++] dynamic_cast

You can use dynamic_cast to identify the type. Then you can do something different according to Derived class with the same Base class pointer.
Just a reminder, when you call destructor of derived class. The vtable pointer and RTTI is no longer exist.
As a result, you will get NULL at second dynamic_cast.
#include <iostream>
#include <cstdio>
#include <cstdlib>

class Base
{
public:
    Base():a(1){};
    ~Base(){};
    virtual void foo() {};
    int a;
};

class Derived : public Base
{
public:
    Derived(){};
    ~Derived(){};
    virtual void foo() {};
};

int main()
{
    void *p = malloc(sizeof(Derived));

    Base *base = new (p) Derived();
    Derived *d = dynamic_cast(base);
    if(d)
        std::cout << "cast ok!\n";     d->~Derived();
    Derived *dd = dynamic_cast(base);
    if(dd)
        std::cout << "cast ok!\n";
    else std::cout << "cast fail!\n";
    return 0;
}