| OLD | NEW | 
| (Empty) |  | 
 |    1 // Copyright (c) 2015, the Fletch project authors. Please see the AUTHORS file | 
 |    2 // for details. All rights reserved. Use of this source code is governed by a | 
 |    3 // BSD-style license that can be found in the LICENSE.md file. | 
 |    4  | 
 |    5 #if defined(FLETCH_TARGET_OS_MACOS) | 
 |    6  | 
 |    7 #include <errno.h> | 
 |    8 #include <stdio.h> | 
 |    9 #include <stdlib.h> | 
 |   10 #include <string.h> | 
 |   11 #include <arpa/inet.h> | 
 |   12 #include <pthread.h> | 
 |   13  | 
 |   14 #include <dns_sd.h> | 
 |   15  | 
 |   16 #include "include/dart_api.h" | 
 |   17 #include "include/dart_native_api.h" | 
 |   18  | 
 |   19 #include "mdns_extension.h" | 
 |   20  | 
 |   21 // Context passed to the callback receiving the mDNS information. | 
 |   22 struct Context { | 
 |   23   // The Dart port where the result should be delivered. | 
 |   24   Dart_Port port; | 
 |   25 }; | 
 |   26  | 
 |   27 // Print fatal error and exit. | 
 |   28 static void Fatal(const char *message) { | 
 |   29   fprintf(stderr, "%s (errno %d)\n", message, errno); | 
 |   30   exit(-1); | 
 |   31 } | 
 |   32  | 
 |   33 // Code running in the threads started for pumping the results. | 
 |   34 static void* ThreadFunction(void* data) { | 
 |   35   DNSServiceRef ref = reinterpret_cast<DNSServiceRef>(data); | 
 |   36  | 
 |   37   // Preocess results until an error occurs. | 
 |   38   DNSServiceErrorType result = kDNSServiceErr_NoError; | 
 |   39   while (result == kDNSServiceErr_NoError) { | 
 |   40     result = DNSServiceProcessResult(ref); | 
 |   41   } | 
 |   42   // The expected error from deallocation the ref. | 
 |   43   if (result != kDNSServiceErr_BadReference) { | 
 |   44     fprintf(stderr, "Error from DNSServiceProcessResult: %d\n", result); | 
 |   45   } | 
 |   46  | 
 |   47   return NULL; | 
 |   48 } | 
 |   49  | 
 |   50 // Start a thread for receiving results from a specific DNSServiceRef. | 
 |   51 static int StartThread(DNSServiceRef ref) { | 
 |   52   pthread_attr_t attr; | 
 |   53   int result = pthread_attr_init(&attr); | 
 |   54   if (result != 0) Fatal("Error from pthread_attr_init"); | 
 |   55  | 
 |   56   result = pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); | 
 |   57   if (result != 0) Fatal("Error from pthread_attr_setdetachstate"); | 
 |   58  | 
 |   59   pthread_t tid; | 
 |   60   result = pthread_create(&tid, &attr, ThreadFunction, ref); | 
 |   61   if (result != 0) Fatal("Error from pthread_create"); | 
 |   62  | 
 |   63   result = pthread_attr_destroy(&attr); | 
 |   64   if (result != 0) Fatal("Error from pthread_attr_destroy"); | 
 |   65  | 
 |   66   return 0; | 
 |   67 } | 
 |   68  | 
 |   69 // Callback for results initiated by calling DNSServiceGetAddrInfo. | 
 |   70 static void GetAddrInfoCallback(DNSServiceRef ref, | 
 |   71                                 DNSServiceFlags flags, | 
 |   72                                 uint32_t interfaceIndex, | 
 |   73                                 DNSServiceErrorType errorCode, | 
 |   74                                 const char *hostname, | 
 |   75                                 const struct sockaddr *address, | 
 |   76                                 uint32_t ttl, | 
 |   77                                 void *context) { | 
 |   78   if (address->sa_family == AF_INET) { | 
 |   79     const struct sockaddr_in* address_in = (const struct sockaddr_in*)address; | 
 |   80     const uint8_t* addr = | 
 |   81         reinterpret_cast<const uint8_t*>(&address_in->sin_addr.s_addr); | 
 |   82  | 
 |   83     struct Context* ctx = reinterpret_cast<struct Context*>(context); | 
 |   84  | 
 |   85     // Build the response message. | 
 |   86     Dart_CObject cobject_hostname; | 
 |   87     cobject_hostname.type = Dart_CObject_kString; | 
 |   88     cobject_hostname.value.as_string = const_cast<char*>(hostname); | 
 |   89     Dart_CObject cobject_address; | 
 |   90     cobject_address.type = Dart_CObject_kTypedData; | 
 |   91     cobject_address.value.as_typed_data.length = 4; | 
 |   92     cobject_address.value.as_typed_data.type = Dart_TypedData_kUint8; | 
 |   93     cobject_address.value.as_typed_data.values = const_cast<uint8_t*>(addr); | 
 |   94     Dart_CObject cobject_result; | 
 |   95     cobject_result.type = Dart_CObject_kArray; | 
 |   96     Dart_CObject* result_array[] = {&cobject_hostname, &cobject_address}; | 
 |   97     cobject_result.value.as_array.length = 2; | 
 |   98     cobject_result.value.as_array.values = result_array; | 
 |   99     Dart_PostCObject(ctx->port, &cobject_result); | 
 |  100  | 
 |  101     // Result received, free allocated data and stop lookup. | 
 |  102     free(ctx); | 
 |  103     DNSServiceRefDeallocate(ref); | 
 |  104   } | 
 |  105 } | 
 |  106  | 
 |  107 // Lookup request from Dart. | 
 |  108 void HandleLookup(Dart_Port port_id, char* hostname) { | 
 |  109   DNSServiceRef ref; | 
 |  110   DNSServiceErrorType result; | 
 |  111   struct Context* context = | 
 |  112       reinterpret_cast<struct Context*>(malloc(sizeof(struct Context))); | 
 |  113   context->port = port_id; | 
 |  114   result = DNSServiceGetAddrInfo(&ref, | 
 |  115                                  0, | 
 |  116                                  0, | 
 |  117                                  kDNSServiceProtocol_IPv4, | 
 |  118                                  hostname, | 
 |  119                                  &GetAddrInfoCallback, | 
 |  120                                  context); | 
 |  121   if (result != kDNSServiceErr_NoError) { | 
 |  122     fprintf(stderr, "Error from DNSServiceProcessResult: %d\n", result); | 
 |  123   } else { | 
 |  124     // Start a thread for retreiving the results. | 
 |  125     // TODO(sgjesse): Add a timeout for killing the thread if there | 
 |  126     // are no responses. | 
 |  127     StartThread(ref); | 
 |  128   } | 
 |  129 } | 
 |  130  | 
 |  131 #endif | 
| OLD | NEW |