2015年12月20日 星期日

漢字之色 Hue in Chinese Literal Characters


    紅   FF0000                                                                             


    綠   008000                                                                             


    藍   0000FF                                                                             


    黑   000000                                                                             


    白   FFFFFF                                                                             


    黃  FFD400                                                                             


    紫  A757A8                                                                             


    橙  F15A22                                                                             


    銀  C0C0C0                                                                             


    灰 808080                                                                               


    金 FFD700                                                                               


    絳  8E2835                                                                             
     《 段玉裁 說文解字注 》  大赤也。大赤者、今俗所謂大紅也。上文純赤者、今俗所謂朱紅也。朱紅淡、大紅濃。大紅如日出之色。朱紅如日中之色。
     《左思·吳都賦 》《註》  絳,絳草也


    黔  303030                                                                              
   《說文解字》 秦謂民爲黔首,謂黑色也。
   《易·說卦》艮爲黔喙之屬


    土  C39143                                                                              



    赭  CC7722                                                                              
   《說文解字》赤土也。

        亦為  6E060D                                                                             


    皂 353535                                                                                
《廣韻·上聲·晧》皁:皁隸又槽屬亦黒繒俗作皂


    柿 ED6D3D                                                                               
《說文解字》赤實果。


    玄 1C0C0F                                                                               
《說文解字》幽遠也。黑而有赤色者爲玄。


    朱 EF454A                                                                               
《說文解字》赤心木,松柏屬


    涅 544839                                                                               
《說文解字》黑土在水中也。


    銅  B87333                                                                             
《說文解字》赤金也


    緇 4C2F34                                                                               
《說文解字》帛黑色
《釋名》緇,滓也。泥緇黑色者曰滓,此色然也。


    炭 404040                                                                               
《說文解字》燒木餘也



    霽 90B4D8                                                                               
 《說文解字》雨止也
 《埤雅》 雨晴曰霽


    彤 A53301                                                                               
     《玉篇》赤色 (丹石煉後之染料)
     

    赤 ED1A3D                                                                               
 《說文解字》南方色也。从大从火。


    翠 3F9877                                                                               
 《說文解字》青羽雀也。


    肌 F1BB93                                                                               
 《說文解字》肉也。


    丹 DC4726                                                                               
 《說文解字》巴越之赤石也


    墨 555555                                                                               


    靛 1A5798                                                                               
      《本草綱目》藍質浮水面者爲靛花。

        亦為  343399                                                                             
           與英文indigo對應


    碧 1CD1A6                                                                               
        《說文解字》石之靑美者


    蒼 7B8D42                                                                               
       《說文解字》 草色也              

     亦為  B0DCD5                                                                              
       《詩·王風》悠悠蒼天


    緋 E54848                                                                               
    《說文解字》帛赤色也


    黛 3C3135                                                                              
    《說文解字》畫眉也
    《楚辭·大招》粉白黛黑

        亦為  494168                                                                             
          《漢典》《通俗文》 染青石謂之點黛



    茜 B13546                                                                               
      《說文解字》茅蒐也
      《本草》一名地血 一名風車草 一名過山龍 今染絳茜草也


    縞 F1EBDD                                                                               
        《傳》縞 白繒



    鼠 949495                                                                               



    柳 A8C87F                                                                               



    榛 BFA46F                                                                               
 《說文解字》木也。



    烏 303030                                                                               



    鉛 E0E0E0                                                                               



    赩 EA1818                                                                               
      《說文解字》大赤也
        《楚辭·大招》註》赩,赤色無草木貌也


    桃 F58F98                                                                               


    青 0067C0                                                                               

        亦為  008000                                                                             


    紺 233B6C                                                                               
                        : 日文

        亦為  28134c                                                                             
                     《說文解字》帛深青而揚赤色也


    縹 267CA7                                                                               
       《說文解字》帛靑白色也


    鳶 85403A                                                                               
《說文解字》鷙鳥也


    褐 994C00                                                                               
       《說文解字》編枲韤。一曰粗衣
         潘岳·藉田賦》《註》褐,麤布也


    栗 800000                                                                              
       《周禮·天官·籩人》饋食之籩 其實栗 又堅木也


    黯 41555C                                                                              
       《蔡邕·述行賦》玄雲黯以凝結兮,集零雨之溱溱
       《說文解字》深黑也  (註 : 其也昭 許慎非色盲 曛昧光異不察)
                                
        亦為  4D4D4D                                                                             
                 (註 : 色盲可辨黯 炭之尤)
  

    赮 D82979                                                                              
        《說文解字》赤色也
          《玉篇》東方赤色


    秘 60B49F                                                                              


    鶸 CBC547                                                                              
       《說文解字》昆鳥  (金雀也)


    猩 C9301B                                                                              
          《玉篇》猩猩,如狗,面似人
          《漢典》鲜红


    瑠璃 2A5CAA                                                                               




待補








參考

日文wiki 色名一覽

你不知道的中国古代色彩称谓大全

顏字色



青、、皁、、碳、、黧、黝、、黟、黕
素、鉛白、雪白、珍珠白、乳白、
青(草)、、翠、、銅(綠)、(綠)
琥珀、(黃)
、騂、、蒨、火、、玫瑰、胭脂、(紅)
(天)、(青)、




2015年12月13日 星期日

Utilize Avahi Libraries in Android for mDNS Discovering



零.

Continue my previous avahi article, here, i would port the same example code to Android platform.

Download and unravel Android NDK

for me, the untarred NDK root locates in ~/Android/AndroidNDK/android-ndk-r10e
  
And install the android tools in the linux system. (yum for fedora, apt-get for ubunu/debian)

sudo apt-get install gcc-arm-linux-androideabi


sudo apt-get install android-tools-adb


I strongly suggest you DO NOT install the others android-tool, headers and libraries via apt-get/yum.

If you need those, just download from Android website and decompress them.


一.

      Download and untar the avahi libraries, in here I use version 0.6.31.

      Download 2 patches and place them in the untarred avahi folder:

0001-Add-Android-support.patch
0002-Add-uninstalled.pc.in-files.patch

apply the patches.

patch -p1  0001-Add-Android-support.patch

      You would encounter a warning here, just ignore it. it is for there is no .git folder inside the avahi folder.


patch -p1 0002-Add-uninstalled.pc.in-files.patch


     For the old configuration tools does not support androideabi, you need to upgrade the config.guess and config.sub from here. it is, to overwrite these 2 files inside the avahi root folder.


二.
    The struct in6_pktinfo has been added in Android 4.0(2011/10). When the avahi 0.6.31 was released (2012/2), the BioniC (the position of glibC for Android) libraries on most populace's Android phone was not implemented the whole IVP6. Therefore, the structure ha been declare inside avahi. In present(2015/12), I thought there is no one set build-target version before 4.0.   It is requisite to modify code to remove the obsolete lines in avahi-core/socket.c , about line 67:


#endif

#if(0)
#ifdef __BIONIC__
struct in6_pktinfo {
        struct in6_addr ipi6_addr;
        int ipi6_ifindex;
};
#endif
#endif

static void mdns_mcast_group_ipv4(struct sockaddr_in *ret_sa) {

The in6_pktinfo has been declared in NDKfolder/platforms/android-version/arch/usr/include/linux/ipv6.h, to comment out it to avoid compilation error.

Optional:
if your application would be integrated  web-browser and avahi disovering functions, you should modify the code avahi-core/netlink.c, about line 160:


    memset(&addr, 0, sizeof(addr));
    addr.nl_family = AF_NETLINK;
    addr.nl_groups = groups;
#if(1)
    addr.nl_pid = 0;
#else 
    addr.nl_pid = getpid();
#endif

    if (bind(fd, (struct sockaddr *) &addr, sizeof(addr)) < 0) {

It is, the add.nl_pid value would not be conflicted with browser's. More detail of this change is in here.

三.
 The Avahi configure arguments for me be:browser

./configure --prefix=$PWD/built --disable-dbus --disable-mono --disable-monodoc --disable-qt4 --disable-qt3 --disable-glib --disable-gobject --disable-gtk --disable-gtk3 --disable-gdbm --disable-dbm --disable-python --disable-pygtk -disable-libdaemon --disable-nls --disable-xmltoman --with-xml=none --disable-core-docs --disable-doxygen-doc CPPFLAGS="-I/home/gaiger/Android/AndroidNDK/android-ndk-r10e/platforms/android-14/arch-arm/usr/include -mcpu=arm926ej-s  -mfloat-abi=soft" LDFLAGS=-L/home/gaiger/Android/AndroidNDK/android-ndk-r10e/platforms/android-14/arch-arm/usr/lib --host=arm-linux-androideabi --disable-stack-protector  --with-distro=debian

 NOTE :
     Zero:
      I disable most functions of Avahi. Because those are useless for the goal of discovering mDNS service and dependent on dbus, gtk, qt and so forth libraries.  To building those depended libraries are difficult for Android.

     One:
     The path, /home/gaiger/Android/AndroidNDK/android-ndk-r10e/platforms/android-14/arch-arm/usr, is where the Android system libraries locates, those are being part of Android NDK.

         /home/gaiger/Android/AndroidNDK/android-ndk-r10e :  where AndroidNDK root locates.
        platforms/android-14/arch-arm  : I chose to  android 4.0 with arm-architecture as my target system.

    it is very natural to add include path (-Iusr_path/include) and linking path(-Iusr_path/lib) as arguments in cross-compilation.

    TWO:
     -mcpu=arm926ej-s  -mfloat-abi=softfp :  To avoid crash in some (mostly those are not existed ) cheap Android device CPU without hardware floating computing. Besides,  Avahi do not involve in heavy floating point computing, So adapt pure soft-float computing would not lead mDNS discovering sluggish.
      arm926ej-s means, assuming the CPU does not support hardware floating but supports Jazelle ( for java VM). 
      More detail of CPU architecture, you could refer to this article.

   THREE :
    --with-distro=debian : for me , I use ubuntu.  If you use fedora/CentOS, you use set it as fedora.

   FOUR:
  --disable-stack-protector : there is no libssp (stack smash protector) in current BioniC defaultly. To advert configuring error, one should disable this function. The detail about libssp is in here.

四.
  After configuring done, it is very instinctive to press make and make install.
  To this step, the avahi libraries for Android has been built, in the avahi_root/built


五.
   Create a folder and  a sub-folder in avahi root: sandyboxcode/jni

   Copy the code sandbox-discover-standalone.c of my last article in folder sandyboxcode/jni.
   And Create two files, Application.mk and Android.mk in the same folder ( sandyboxcode/jni).

The content of file Application.mk be:


#APP_ABI := armeabi-v7a
APP_ABI := armeabi

     
The Android.mk file be:


LOCAL_PATH := $(my-dir)

ifneq ($(DYNAMIC_LINK),true)
DYNAMIC_LINK = false

include $(CLEAR_VARS)
LOCAL_MODULE    := libavahi-core
LOCAL_SRC_FILES := ../../built/lib/libavahi-core.a
include $(PREBUILT_STATIC_LIBRARY)

include $(CLEAR_VARS)
LOCAL_MODULE    := libavahi-common
LOCAL_SRC_FILES := ../../built/lib/libavahi-common.a
include $(PREBUILT_STATIC_LIBRARY)

else

include $(CLEAR_VARS)
LOCAL_MODULE    := libavahi-core
LOCAL_SRC_FILES := ../../built/lib/libavahi-core.so
include $(PREBUILT_SHARED_LIBRARY)


include $(CLEAR_VARS)
LOCAL_MODULE    := libavahi-common
LOCAL_SRC_FILES := ../../built/lib/libavahi-common.so
include $(PREBUILT_SHARED_LIBRARY)

endif #if $DYNAMIC_LINK .neq. true


include $(CLEAR_VARS)
LOCAL_MODULE := sandbox-discover-standalone
LOCAL_SRC_FILES := sandbox-discover-standalone.c
 
LOCAL_CFLAGS := -O2 -mcpu=arm926ej-s -mfloat-abi=softfp
LOCAL_C_INCLUDES := $(LOCAL_PATH)/../../built/include 


ifeq ($(DYNAMIC_LINK),false)
LOCAL_STATIC_LIBRARIES := libavahi-core libavahi-common
else
LOCAL_SHARED_LIBRARIES += libavahi-common libavahi-core
endif #if $(DYNAMIC_LINK) eq false

LOCAL_LDLIBS +=  -llog
include $(BUILD_EXECUTABLE)


Then to the sandbox folder, type :


$your_ndk_path/ndk-build -B V=1


Now you have gotten binary of sandbox-discover-standalone for Android, under the folder libs/armeabi .


六.

  Push the built binary to a android device, which might need to be rooted to execute a binary in shell.

  For me, I use the development board tiny210 on Android 4.0, which was rooted natively.





check if the device connected to working computer indeed:

$ adb devices
List of devices attached 
0123456789ABCDEF device


push the binary to the android :

$ adb push libs/armeabi/sandbox-discover-standalone sandbox-discover-standalone
2291 KB/s (202300 bytes in 0.086s)


execute it in the shell:

$ adb shell 
/ # chmod 777 sandbox-discover-standalone
/ # ./sandbox-discover-standalone 
1 services have been found

Service Type: _http._tcp
Service Name: GAIGER NETEYE CS2230
Domain Name: local
Interface: eth0 IPv4
Address: 192.168.13.107/NETEYECS2230-001A97018882.local:80
TEXT Data: NULL

discover cast 1002 msec


It is successful totally.

Known insufficiency :

if you encounter  Segmentation fault when you execute the binary in Android,
you should correct the code in sandbox-discover-standalone.c, of function ServiceResolverCallback:


 pServiceInfo->pServiceName = strndup(pServiceName, MAX_STR_LEN);
 pServiceInfo->pDomainName = strndup(pDomain, MAX_STR_LEN);
#ifndef __ANDROID__ 
 pServiceInfo->pInterface = strndup(if_indextoname(interface, (char*)pServiceName), MAX_STR_LEN);
#endif 
 pServiceInfo->pProtocolNumber = strndup(avahi_proto_to_string(protocol), MAX_STR_LEN);

It could avoid the crashing: the function if_indextoname of bionic libraries is not as stable as libc.


Extra:

It is passible to write a stand Makefile for Android ndk build :

i assure the Makefile be in sandyboxcode/Makefile (NOT inside the jni folder), for the sandbox-discover-sandalone.c be :


CC := arm-linux-androideabi-gcc
CXX := arm-linux-androideabi-g++

INC := -I~/Android/AndroidNDK/android-ndk-r10e/platforms/android-14/arch-arm/usr/include 

INC += -I../built/include -Ijni

AVAHI_LIB_PATH := ../built/lib

LIB := ~/Android/AndroidNDK/android-ndk-r10e/platforms/android-14/arch-arm/usr/lib/liblog.so

LIB += $(AVAHI_LIB_PATH)/libavahi-core.a
LIB += $(AVAHI_LIB_PATH)/libavahi-common.a

CFLAGS := -g 

all :
 $(CC) $(CFLAGS) $(INC)  jni/sandbox-discover-standalone.c $(LIB) -o sandbox-discover-standalone
clean :
 rm sandbox-discover-standalone -rf

Note : the shared libraries liblog.so be linking directly!.

2015年12月5日 星期六

Use Avahi as a library for Discovering mDNS Service


     Avahi(http://www.avahi.org/) is an implement of multicast Domain Name System (mDNS) in Linux/Android. mDNS is a (local) network service broadcasting/discovering mechanism: for example,  the IP printers or IP cameras,  could be found via mDNS functions.

    Avahi libraries is easy to be use relatively.  There are  adequate examples to illuminate how to use those API. In here I would like to make them be ample. I would explain about discovering (the serivces) part in this article.


Note : avahi brower would depend on avahi-daemon, this post's goal is to remove the dependency.



  零. 
      Download the avahi, for me, I use version 0.6.31. Then uncompress the tar ball.

 一.      Go into the avahi folder, configure the avahi with gtk2 , qt4 and dbus

./configure --prefix=$PWD/built --disable-qt3 --disable-gtk3 --disable-mono --enable-tests --enable-core-docs --disable-python --disable-pygtk

     After the configuration has be done,type make and make install.


二. 
    Go to the built//bin folder, execute the avahi-browse:

You would get the similar result with mine:


./avahi-browse -a
+  wlan0 IPv6 i5-3210m [60:67:20:a5:44:ae]                  _workstation._tcp    local
+  wlan0 IPv4 i5-3210m [60:67:20:a5:44:ae]                  _workstation._tcp    local
+  wlan0 IPv6 i5-3210m                                      _udisks-ssh._tcp     local
+  wlan0 IPv4 i5-3210m                                      _udisks-ssh._tcp     local
+  wlan0 IPv4 GAIGER NETEYE CS2230                          _http._tcp           local




But if you stop the avahi-daemon and re-execute the avahi-browe:

sudo service avahi-daemon stop
avahi-daemon stop/waiting

./avahi-browse -a
Failed to create client object: 幕後程式沒有在執行中 

the Chinese words read "the daemon programming is not on running"

That is, the avahi-browe depends on avahi-daemon, which be the provider of service of discover.

But, If you run the avahi-discover-standalone, there is a window for reporting discovered service:



The GAIGER NETEYE CS2230 be a IP camera in the same lan domain.

     The other services discovered by avahi-browe are local services provided by avahi-daemon, those would vanish when avahi-daemon stopped.

    You could study what is the different between avahi-browe and avahi-discover-standalone,   the source codes be in folder examples/client-browse-services.c and  avahi-discover-standalone/main.c respectively.

   For most useful and portable for libraries usage, the avahi-discover-standalone/main.c should be removed from UI, and be independent of the others libraries (dbus and so forth).


三.
   Re-configure or uncompress the same tar ball again , use the configure arguments:


./configure --prefix=$PWD/built --disable-dbus --disable-mono --disable-monodoc --disable-qt4 --disable-qt3 --disable-glib --disable-gobject --disable-gtk --disable-gtk3 --disable-gdbm --disable-dbm --disable-python --disable-pygtk

And make -j2 && make install.

That is for minimization the dependence.


四.
   Create a folder be under avahi source root , the folder name be sandyboxcode for me.
   my standalone code be inside the folder:

sandbox-discover-standalone.c:


#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#include <time.h>

#include <net/if.h>

#include "avahi-core/lookup.h"

#include <avahi-common/simple-watch.h>
#include <avahi-common/malloc.h>
#include <avahi-common/error.h>


#ifndef FALSE
 #define FALSE       (0)
#endif

#ifndef TRUE
 #define TRUE       (1)
#endif

#define MAX_STR_LEN        (256)

typedef struct ServiceInfo 
{ 
 char *pServiceType;
 char *pServiceName;
 char *pDomainName;
 char *pInterface;
 char *pProtocolNumber;
 char *pAddr;
 unsigned short port;
 char *pHostName;
 char *pText;
 
 struct ServiceInfo *pNext;
}ServiceInfo, ServiceInfoList;


const char unUsedServiceInfoMemHead[] = 
{
 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff ,
 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff 
};//the impossible memory location value


static AvahiServer *pServer;
static AvahiSimplePoll *pSimplePoll;


ServiceInfoList *CreateServiceInfoList(void)
{
 ServiceInfo *pServiceInfo;
    
 pServiceInfo = (ServiceInfo*)malloc(sizeof(ServiceInfo));
 memset(pServiceInfo, (unsigned char)0xff, sizeof(ServiceInfo));   
 
 return pServiceInfo;
}/*CreateServiceInfoList*/

#define SAFE_FREE(PTR)     if(NULL != (PTR))\
         free(PTR);\
        PTR = NULL


void DestroyServiceInfo(ServiceInfo *pServiceInfo)
{
 if(NULL == pServiceInfo)
  return;

 SAFE_FREE(pServiceInfo->pServiceType); SAFE_FREE(pServiceInfo->pServiceName);
 SAFE_FREE(pServiceInfo->pDomainName);
 SAFE_FREE(pServiceInfo->pInterface);SAFE_FREE(pServiceInfo->pProtocolNumber);
 SAFE_FREE(pServiceInfo->pAddr);SAFE_FREE(pServiceInfo->pHostName);

 if(NULL != pServiceInfo->pText)
  avahi_free(pServiceInfo->pText);  
 pServiceInfo->pText = NULL;

 SAFE_FREE(pServiceInfo);
}/*DestoryServiceInfo*/


void DestroyServiceInfoList(ServiceInfoList *pServiceInfoList)
{
 ServiceInfo *pCurrent;

 pCurrent = pServiceInfoList;

 if( 0 == memcmp(pServiceInfoList, &unUsedServiceInfoMemHead[0], sizeof(unUsedServiceInfoMemHead)) )
 {
  SAFE_FREE(pCurrent); 
  return;
 }/*if unused*/

 while(NULL != pCurrent)
 {
  ServiceInfo *pNext;

  pNext = pCurrent->pNext;
  DestroyServiceInfo(pCurrent);
  pCurrent = pNext;
 }/*while*/
    
}/*CleanServiceInfoList*/


void ServiceResolverCallback(
 AvahiSServiceResolver *pResolver,
 AvahiIfIndex interface,
 AvahiProtocol protocol,
 AvahiResolverEvent event,
 const char *pServiceName,
 const char *pType,
 const char *pDomain,
 const char *pHostName,
 const AvahiAddress *pAvahiAddress,
 uint16_t port,
 AvahiStringList *pText,
 AvahiLookupResultFlags flags,
 void* pUserdata)
{
 char addrStr[AVAHI_ADDRESS_STR_MAX];
 ServiceInfo *pServiceInfo;

 //printf("__FUNCTION__ = %s\n", __FUNCTION__);
 if (AVAHI_RESOLVER_FOUND != event)
 {
  printf("NOT AVAHI_RESOLVER_FOUND\n");
  return;
 }/* AVAHI_RESOLVER_FOUND != event */

 
 pServiceInfo = (ServiceInfo*)pUserdata;
 
 if( 0 == memcmp(pServiceInfo, &unUsedServiceInfoMemHead[0], sizeof(unUsedServiceInfoMemHead)) )
 {
  memset(pServiceInfo, 0, sizeof(ServiceInfo)); 
 }
 else
 {
  while(NULL != pServiceInfo->pNext)  
   pServiceInfo = pServiceInfo->pNext;
  
  pServiceInfo->pNext = (ServiceInfo*)malloc(sizeof(ServiceInfo));
  memset(pServiceInfo->pNext, 0, sizeof(ServiceInfo));
  
  pServiceInfo = pServiceInfo->pNext;
 }/*if zero*/  

 avahi_address_snprint(&addrStr[0], AVAHI_ADDRESS_STR_MAX, pAvahiAddress);
 
 pServiceInfo->pServiceType = strndup(pType, MAX_STR_LEN);
 pServiceInfo->pServiceName = strndup(pServiceName, MAX_STR_LEN);
 pServiceInfo->pDomainName = strndup(pDomain, MAX_STR_LEN);
 pServiceInfo->pInterface = strndup(if_indextoname(interface, (char*)pServiceName), MAX_STR_LEN);
 pServiceInfo->pProtocolNumber = strndup(avahi_proto_to_string(protocol), MAX_STR_LEN);

 pServiceInfo->pAddr = strndup(&addrStr[0], MAX_STR_LEN);
 pServiceInfo->pHostName = strndup(pHostName, MAX_STR_LEN);

 pServiceInfo->port = port;

 if(NULL != pText)
 {
  char *pAvahiText = avahi_string_list_to_string(pText) ;
  pServiceInfo->pText = strndup(pAvahiText, MAX_STR_LEN);
  avahi_free(pAvahiText); 
 }/*if NULL != pText*/ 

#if(0)
 printf( 
   "Service Type: %s\n"
   "Service Name: %s\n"
   "Domain Name: %s\n"
   "Interface: %s %s\n"
   "Address: %s/%s:%u\n"
   "TEXT Data: %s\n"
   ,
   pServiceInfo->pServiceType,
   pServiceInfo->pServiceName, 
   pServiceInfo->pDomainName, 
   pServiceInfo->pInterface, pServiceInfo->pProtocolNumber,
   pServiceInfo->pAddr, pServiceInfo->pHostName, pServiceInfo->port,
   NULL == pServiceInfo->pText ? "\x1B[1;36m" "NULL" "\x1B[0m": pServiceInfo->pText       
   );   
#endif   
 
 if (NULL != pResolver)
  avahi_s_service_resolver_free(pResolver); 

}/*ServiceResolverCallback*/
 
 
void ServiceBrowserCallback(
 AvahiSServiceBrowser *pBrower,
 AvahiIfIndex interface,
 AvahiProtocol protocol,
 AvahiBrowserEvent event,
 const char *pServiceName,
 const char *pServiceType,
 const char *pDomainName,
 AvahiLookupResultFlags flags,
 void *pUserdata) 
{
 AvahiSServiceResolver *pResolver;

 //printf("__FUNCTION__ = %s\n", __FUNCTION__);
 if(NULL == pServiceName || NULL == pServiceType
  || NULL == pDomainName) 
 {
  return;
 }/*if NULL*/

 /*
  TODO:
   a service filter should be put in here. 
 */
 
 pResolver = avahi_s_service_resolver_new(pServer, interface, protocol, pServiceName, 
 pServiceType, pDomainName, AVAHI_PROTO_UNSPEC, 0, ServiceResolverCallback, 
 (void*)pUserdata);

}/*ServiceBrowserCallback*/


void ServiceTypeBrowserCallback( 
 AvahiSServiceTypeBrowser *pTypeBrower,
 AvahiIfIndex interface,
 AvahiProtocol protocol,
 AvahiBrowserEvent event,
 const char *pType,
 const char *pDomain,
 AvahiLookupResultFlags flags,
  void *pUserdata) 
{
 
 assert(pTypeBrower);

 switch (event) 
 {
 case AVAHI_BROWSER_FAILURE:
 printf("AVAHI_BROWSER_FAILURE\n");
 avahi_simple_poll_quit(pSimplePoll);
 break;

 case AVAHI_BROWSER_NEW:
 //printf("AVAHI_BROWSER_NEW\n");
 {  
  /* We ignore the returned resolver object. In the callback
     function we free it. If the server is terminated before
     the callback function is called the server will free
     the resolver for us. */
             
  if( NULL == avahi_s_service_browser_new(pServer, AVAHI_IF_UNSPEC, AVAHI_PROTO_UNSPEC, 
   pType, pDomain, 0, ServiceBrowserCallback, pUserdata))
  {
   fprintf(stderr, "error in avahi_s_service_browser_new\n");
  }/*if NULL*/

 }/*local Variables*/
 break;

 case AVAHI_BROWSER_REMOVE:
 //printf("AVAHI_BROWSER_REMOVE\n");
 break;

 case AVAHI_BROWSER_ALL_FOR_NOW:
 //printf("AVAHI_BROWSER_ALL_FOR_NOW\n");
 avahi_simple_poll_quit(pSimplePoll);
 break;
   
 case AVAHI_BROWSER_CACHE_EXHAUSTED:
 //printf("AVAHI_BROWSER_CACHE_EXHAUSTED\n"); 
 break;
 }/*switch event*/

}/*service_type_browser_callback*/


void TimeoutCallback(AvahiTimeout *pTimeout, void *pUserdata) 
{
 printf("__FUNCTION__ = %s\n", __FUNCTION__); 
 avahi_simple_poll_quit(pSimplePoll);
}/*TimeoutCallback*/


int MulticastDomainNameSystemServiceDiscover(int *pNumber, ServiceInfoList *pServiceInfoList, 
 int maxTimeoutInMilliSec)
{
 AvahiServerConfig config;
 AvahiSServiceTypeBrowser *pServiceTypeBrowser;
 ServiceInfo *pServiceInfoHead;

 int error;
 int i;
 int ret;
 struct timeval tv;
  
 pSimplePoll = NULL;
 pServiceTypeBrowser = NULL;

 *pNumber = 0;
 pServiceInfoHead = pServiceInfoList;
 if(NULL == pServiceInfoHead)
 {
  fprintf(stderr, "ServiceInfo should be initialized \n");
  ret = -1;
  goto flag_Fail;
 }/*if */

 avahi_set_allocator(NULL);
 pSimplePoll = avahi_simple_poll_new();

 if (NULL == pSimplePoll) 
 {
  fprintf(stderr, "Failed to create simple poll object.\n");
  ret = -2;
  goto flag_Fail;
 }/*if*/

 avahi_server_config_init(&config);
 config.publish_hinfo = config.publish_addresses = FALSE;
 config.publish_domain = config.publish_workstation = FALSE;
 
 pServer = avahi_server_new(avahi_simple_poll_get (pSimplePoll), &config, NULL, NULL, &error);
 avahi_server_config_free(&config);
  
 if (NULL == pServer) 
 {
  fprintf(stderr, "Failed to create server : %s\n", avahi_strerror(error));
  ret = -3;
  goto flag_Fail;
 }/*if NULL == pServer*/

 pServiceTypeBrowser = avahi_s_service_type_browser_new(pServer, 
  AVAHI_IF_UNSPEC, AVAHI_PROTO_UNSPEC, NULL, 0, 
  ServiceTypeBrowserCallback, pServiceInfoHead);

 if(NULL == pServiceTypeBrowser)
 {
  fprintf(stderr, "Failed to create brower \n");
  ret = -4;
  goto flag_Fail;
 }/*if NULL == pServiceTypeBrowser*/

 avahi_simple_poll_get(pSimplePoll)->timeout_new(
  avahi_simple_poll_get(pSimplePoll),
  avahi_elapse_time(&tv, maxTimeoutInMilliSec, 0),
  TimeoutCallback,
  NULL);    
       
 /* Run the main loop */
 avahi_simple_poll_loop(pSimplePoll);
 

 if( 0 == memcmp(pServiceInfoHead, &unUsedServiceInfoMemHead[0], 
  sizeof(unUsedServiceInfoMemHead)) )
 {
  goto flag_Fail ; 
 }/*if no service found*/


 {/*count  the list length*/  
  ServiceInfo *pServiceInfo;
  pServiceInfo = pServiceInfoHead;
  *pNumber = 0;  
  while(NULL != pServiceInfo)
  {
   pServiceInfo = pServiceInfo->pNext;
   (*pNumber)++;
  }/*NULL != pServiceInfo*/
 }/*local variable */    

 ret = *pNumber; 

flag_Fail:

 if(NULL != pServer)
  avahi_server_free(pServer);
 pServer = NULL;

 if(NULL != pSimplePoll) 
   avahi_simple_poll_free(pSimplePoll);
 pSimplePoll = NULL;

 return ret;
}/*MulticastDomainNameSystemServiceDiscover*/



#define TIMEOUT_VALUE      (5000)

int main(int argc, char *argv[])
{ 
 int n, i;
 ServiceInfoList *pServiceInfoList;
 struct timespec timeStart, timeEnd;
 
 pServiceInfoList = CreateServiceInfoList();

 clock_gettime(CLOCK_REALTIME, &timeStart);

 MulticastDomainNameSystemServiceDiscover(&n, pServiceInfoList, TIMEOUT_VALUE);
 
 clock_gettime(CLOCK_REALTIME, &timeEnd);

 printf("%d services have been found\n", n);
 if(0 != n )
 {
  ServiceInfo *pServiceInfo;
  pServiceInfo = pServiceInfoList;
  
  while(NULL != pServiceInfo)
  {  
   printf("\n");
   printf( 
     "Service Type: %s\n"
     "Service Name: %s\n"
     "Domain Name: %s\n"
     "Interface: %s %s\n"
     "Address: %s/%s:%u\n"
     "TEXT Data: %s\n"
     ,
     pServiceInfo->pServiceType,
     pServiceInfo->pServiceName, 
     pServiceInfo->pDomainName, 
     pServiceInfo->pInterface, pServiceInfo->pProtocolNumber,
     pServiceInfo->pAddr, pServiceInfo->pHostName, pServiceInfo->port,
     NULL == pServiceInfo->pText ? "\x1B[1;36m" "NULL" "\x1B[0m": pServiceInfo->pText       
     );   
     
   pServiceInfo = pServiceInfo->pNext;  
  }/*while*/
  printf("\n");
 }/*if 0 != n*/

 {
  int  elaspeTimeMicroSec; 
  elaspeTimeMicroSec = (timeEnd.tv_sec - timeStart.tv_sec) *1e6 + 
     (timeEnd.tv_nsec - timeStart.tv_nsec) /1e3;

  printf("discover cast %u msec\n", elaspeTimeMicroSec/1000);  
 }     
 DestroyServiceInfoList(pServiceInfoList);
 
 return 0;
}/*main*/

 


The corresponding Makefile be :


CC := gcc
CXX := g++


INC := -I../built/include 

LIB_PATH := ../built/lib

LIB += $(LIB_PATH)/libavahi-core.a
LIB += $(LIB_PATH)/libavahi-common.a


CFLAGS := -g

all :
 $(CC) $(CFLAGS) $(INC)  sandbox-discover-standalone.c  $(LIB)  -o sandbox-discover-standalone 

clean :
 rm sandbox-discover-standalone -rf


 
The code is very easy to be  modified as library form.

五. 
   Discover result:


./sandbox-discover-standalone
Joining mDNS multicast group on interface wlan0.IPv6 with address fe80::6267:20ff:fea5:44ae.
New relevant interface wlan0.IPv6 for mDNS.
Joining mDNS multicast group on interface wlan0.IPv4 with address 192.168.13.7.
New relevant interface wlan0.IPv4 for mDNS.
Network interface enumeration completed.
Leaving mDNS multicast group on interface wlan0.IPv6 with address fe80::6267:20ff:fea5:44ae.
Leaving mDNS multicast group on interface wlan0.IPv4 with address 192.168.13.7.
n = 1

Service Type: _http._tcp
Service Name: GAIGER NETEYE CS2230
Domain Name: local
Interface: wlan0 IPv4
Address: 192.168.13.107/NETEYECS2230-001A97018882.local:80
TEXT Data: NULL


Of course, the avahi-daemon be in stop status.