Android 4.1 Netd detailed analysis (6) DnsProxyListener

Source: Internet
Author: User

Personal email: xiaokeweng@gmail.com

In the previous sections, we started with the main function and analyzed the two parts of CommandListener and Netlinkmanager, which can communicate with the Kernel layer and Framework layer and complete a set of functional systems. The following two parts are mentioned: DnsProxyListener and MDnsSdListener. Both are
DNS problems. The following section describes the two parts in the main function.

// *** Mian. cpp *** dpl = new DnsProxyListener (); if (dpl-> startListener () {ALOGE ("Unable to start DnsProxyListener (% s )", strerror (errno); exit (1);} // multicast_DNS_server_descript_listener multicast DNS daemon mdnsl = new MDnsSdListener (); if (mdnsl-> startListener ()) {ALOGE ("Unable to start MDnsSdListener (% s)", strerror (errno); exit (1 );}

First
DnsProxyListener starts analysis. This part mainly implements DNS proxy resolution, from name to address, from name to server port number. This part is highly similar to CommandListener.

// *** DnsProxyListener. cpp ***** // registration command: GetAddrInfoCmd (), GetHostByAddrCmd () DnsProxyListener: listener (): FrameworkListener ("dnsproxyd") {registerCmd (new GetAddrInfoCmd ()); registerCmd (new GetHostByAddrCmd ());}

Constructor, register the command, and set the basic properties of the socket to the connected socket of dnsproxyd. They will be used in the subsequent socket creation, next, call the dpl-> startListener () method. The class inheritance relationship is Dnsproxlistener → FrameworkListener → SocketListener. Therefore, it is equivalent to calling SocketListener.
Class startListener (). This method creates a socket according to the previous attributes and starts listening. These parts are similar to those used in CommandListener.

// *****/System/core/libsysutils/src/SocketListener ***** int SocketListener: startListener () {if (! MSocketName & mSock =-1) {SLOGE ("Failed to start unbound listener"); errno = EINVAL; return-1;} else if (mSocketName) {if (mSock = android_get_control_socket (mSocketName) <0) {SLOGE ("Obtaining file descriptor socket '% s' failed: % s", mSocketName, strerror (errno )); return-1;} SLOGV ("got mSock = % d for % s", mSock, mSocketName);} if (mListen & listen (mSock, 4) <0) {// link (tcp) SLOGE ("Un Able to listen on socket (% s) ", strerror (errno); return-1;} else if (! MListen) // No link (udp) mClients-> push_back (new SocketClient (mSock, false, musew.num); if (pipe (mCtrlPipe )) {SLOGE ("pipe failed (% s)", strerror (errno); return-1 ;}if (pthread_create (& mThread, NULL, SocketListener: threadStart, this )) {SLOGE ("pthread_create (% s)", strerror (errno); return-1 ;}return 0 ;}

Call startListener () to create a thread and call the threadStart function.

Void * SocketListener: threadStart (void * obj) {SocketListener * me = reinterpret_cast <SocketListener *> (obj); // get upper layer // irrelevant type conversion, get the exact same bit me-> runListener (); pthread_exit (NULL); return NULL ;}

Then the Enable thread calls runlistener () to check the socket status. The fd_set and selelct functions are used to receive data and the onDataAvailable function is triggered.(Similar to the previous chapter, do not paste all the code)

Void SocketListener: runListener () {SocketClientCollection * pendingList = new SocketClientCollection (); while (1) {SocketClientCollection: iterator it; fd_set read_fds; // fd_set int rc = 0; int max =-1; FD_ZERO (& read_fds); // mListener is used to determine whether there is a link (TCP) or no link (UDP) if (mListen) {max = mSock; FD_SET (mSock, & read_fds );}............

Then, the dispathCommand function in Frameworklistener is triggered to parse data directly in string format, because the NetworkManagerService at the framework layer calls the doCommand function in nativedaemonconneto issue a string command.(Similar to the previous chapter, do not paste all the code)

void FrameworkListener::dispatchCommand(SocketClient *cli, char *data) {    FrameworkCommandCollection::iterator i;    int argc = 0;    char *argv[FrameworkListener::CMD_ARGS_MAX];    char tmp[255];    char *p = data;    char *q = tmp;    char *qlimit = tmp + sizeof(tmp) - 1;    bool esc = false;    bool quote = false;    int k;    bool haveCmdNum = !mWithSeq;    memset(argv, 0, sizeof(argv));    memset(tmp, 0, sizeof(tmp));    while(*p) {        if (*p == '\\') {//if (*p == '\')            if (esc) {                if (q >= qlimit)                    goto overflow;                *q++ = '\\';//*q = *p++…………

After resolution matching and selection, call the runCommand function for processing. This function is a pure virtual function defined in FrameworkCommand and provides interfaces for sub-classes, the specific implementation here is in the two member classes GetAddrInfoCmd and GetAddrInfoHandler of DnsProxyListener.

// Where is the command? A: The runcommand of // In onDataAvailable in frameworkCommand is equivalent to the onEvent in netlinkListener. It is a response to the call command that receives the code from the framework layer // (generally a function registered by this class. /// Arg []: 1 2 3 4 5 6 // name service flags family socktype protocol // int DnsProxyListener: GetAddrInfoCmd: runCommand (SocketClient * cli, int argc, char ** argv) {if (DBG) {for (int I = 0; I <argc; I ++) {ALOGD ("argv [% I] = % s ", i, argv [I]) ;}} if (argc! = 7) {char * msg = NULL; asprintf (& msg, "Invalid number of arguments to getaddrinfo: % I", argc); ALOGW ("% s", msg ); cli-> sendMsg (ResponseCode: CommandParameterError, msg, false); free (msg); return-1;} char * name = argv [1]; if (strcmp ("^", name) = 0) {// arg [1]! = "^" Name = NULL;} else {// name = arg [1] name = strdup (name);} char * service = argv [2]; // argv [2]! = "^" If (strcmp ("^", service) = 0) {service = NULL;} else {service = strdup (service ); // service = arg [2]} struct addrinfo * hints = NULL; int ai_flags = atoi (argv [3]); // ai_flags = argv [3] int ai_family = atoi (argv [4]); // ai_family = argv [4] int ai_socktype = atoi (argv [5]); // ai_socktype = argv [5] int ai_protocol = atoi (argv [6]); // ai_protocol = argv [6] if (ai_flags! =-1 | ai_family! =-1 | ai_socktype! =-1 | ai_protocol! =-1) {hints = (struct addrinfo *) calloc (1, sizeof (struct addrinfo); hints-> ai_flags = ai_flags; hints-> ai_family = ai_family; hints-> ai_socktype = ai_socktype; hints-> ai_protocol = ai_protocol;} if (DBG) {ALOGD ("GetAddrInfoHandler for % s/% s", name? Name: "[nullhost]", service? Service: "[nullservice]");} cli-> incRef (); DnsProxyListener: GetAddrInfoHandler * handler = new DnsProxyListener: GetAddrInfoHandler (cli, name, service, hints ); // call GetAddrInfoHandler-> run handler-> start (); //////////////////////////////////////// /// // return 0 ;}

Then, the data obtained from the Framework command will be parsed and assigned to the GetAddrInfoHandler constructor in the form of an addrinfo struct as the parameter. Then, the start () method will be used.

// Start () and threadStart () functions void DnsProxyListener: GetAddrInfoHandler: start () {pthread_create (& mThread, NULL, DnsProxyListener: GetAddrInfoHandler: threadStart, this );} void * DnsProxyListener: GetAddrInfoHandler: threadStart (void * obj) {GetAddrInfoHandler * handler = reinterpret_cast <GetAddrInfoHandler *> (obj); handler-> run (); delete handler; pthread_exit (NULL); return NULL ;}

Finally, start a new thread call, run () function, call the gethonstbyaddr () function for parsing, and send the parsing result to the framework layer. It involves the addrinfo struct and the getaddrinfo library functions.

//************************************** ********************************** // Run () function // use the getaddrinfo function to parse the address, the parsed content is the command from the framework layer // and the returned value is submitted back to the framework layer //******************* **************************************** * ************ // struct addrinfo {// int ai_flags; // int ai_family; // int ai_socktype; // int ai_protocol; // socklen_t ai_addrlen; // char * ai_canonname; // struct sockaddr * ai_addr;/s Truct addrinfo * ai_next; //}; // void DnsProxyListener: GetAddrInfoHandler: run () {if (DBG) {ALOGD ("GetAddrInfoHandler, now for % s/% s ", mHost, mService);} struct addrinfo * result = NULL; uint32_t rv = getaddrinfo (mHost, mService, mHints, & result ); // important function, using mHost: host name or address string // mService: server name or 10 forbidden port number // mhints: indicates the type of information to be returned ~ /// Parameters of this function are all from, framework layer issued command format such as the following text // reference: http://blog.csdn.net/xjtuse_mal/article/details/1967471 if (rv) {// getaddrinfo failed mClient-> sendBinaryMsg (ResponseCode:: DnsProxyOperationFailed, & rv, sizeof (rv);} else {bool success =! MClient-> sendCode (ResponseCode: DnsProxyQueryResult); struct addrinfo * ai = result; while (ai & success) {// return the parsing result to the framework layer success = sendLenAndData (mClient, sizeof (struct addrinfo), ai) & sendLenAndData (mClient, ai-> ai_addrlen, ai-> ai_addr) & sendLenAndData (mClient, ai-> ai_canonname? Strlen (ai-> ai_canonname) + 1: 0, ai-> ai_canonname); ai = ai-> ai_next; // a struct chain ~ The ai_next element has the following two scenarios: // (1) the mHost may be associated with multiple addresses, then, a corresponding structure is returned for each address of all the clusters. /// (2) if the service parameter specified by the service supports multiple socket types // a corresponding structure is returned for each socket type} success = success & sendLenAndData (mClient, 0 ,""); // Add the end '\ 0' if (! Success) {ALOGW ("Error writing DNS result to client") ;}} if (result) {freeaddrinfo (result) ;}mclient-> decRef ();}

So far, the framework layer has issued commands. netd accepts and parses the commands, and then returns the parsing results after calling the processing function to the Message Communication loop of the framework layer, socket is used for communication.

// Internal class GetAddrInfoCmd (public NetdCommand) // GetAddrInfoHandler // GetHostByAddrCmd (public NetdCommand) // GetHostByAddrHandler

The basic framework of GetHostByAddrHandler of the other classes is similar to that described above. The two internal classes work together to implement the two commands registered to the Framework layer. DNS resolution is implemented. The name can be changed to the address and the name to the server port.

 

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.