1
  
2
  
3
  
4
  
5
  
6
  
7
  
8
  
9
  
10
  
11
  
12
  
13
  
14
  
15
  
16
  
17
  
18
  
19
  
20
  
21
  
22
  
23
  
24
  
25
  
26
  
27
  
28
  
29
  
30
  
31
  
32
  
33
  
34
  
35
  
36
  
37
  
38
  
39
  
40
  
41
  
42
  
43
  
44
  
45
  
46
  
47
  
48
  
49
  
50
  
51
  
52
  
53
  
54
  
55
  
56
  
57
  
58
  
59
  
60
  
61
  
62
  
63
  
64
  
65
  
66
  
67
  
68
  
69
  
70
  
71
  
72
  
73
  
74
  
75
  
76
  
77
  
78
  
79
  
80
  
81
  
82
  
83
  
84
  
85
  
86
  
87
  
88
  
89
  
90
  
91
  
92
  
93
  
94
  
95
  
96
  
97
  
98
  
99
  
100
  
101
  
102
  
103
  
104
  
105
  
106
  
107
  
108
  
109
  
110
  
111
  
112
  
113
  
114
  
115
  
116
  
117
  
118
  
119
  
//  Interface to DNS Service Discovery. Written by Jonas Walldén. 
 
#pike __REAL_VERSION__ 
 
#if constant(_Protocols_DNS_SD.Service) 
 
 
//!  This class provides an interface to DNS Service Discovery. The 
//!  functionality of DNS-SD is described at <http://www.dns-sd.org/>. 
//! 
//!  Using the Proctocols.DNS_SD.Service class a Pike program can 
//!  announce services, for example a web site or a database server, to 
//!  computers on the local network. 
//! 
//!  When registering a service you need to provide the service name. 
//!  service type, domain and port number. You can also optionally 
//!  specify a TXT record. The contents of the TXT record varies between 
//!  different services; for example, a web server can announce a path 
//!  to a web page, and a printer spooler is able to list printer 
//!  features such as color support or two-sided printing. 
//! 
//!  The service is registered on the network for as long as the instance 
//!  of the Service class is valid. 
class Service { 
  inherit _Protocols_DNS_SD.Service; 
 
  private protected string clip_utf8_str(string s, int maxlen) 
  { 
    //  Clip before UTF-8 encoding to limit loop to a few iterations at most 
    s = s[..maxlen - 1]; 
    string s_utf8 = string_to_utf8(s); 
    while (strlen(s_utf8) > maxlen) { 
      //  Shorten one (possibly wide) character 
      s = s[..strlen(s) - 2]; 
      s_utf8 = string_to_utf8(s); 
    } 
    return s_utf8; 
  } 
 
 
  private protected string get_flat_txt_record(void|string|array(string) txt) 
  { 
    string txt_flat; 
 
    if (txt && stringp(txt)) 
      txt = ({ txt }); 
    if (arrayp(txt) && sizeof(txt)) { 
      txt_flat = ""; 
      foreach(txt, string entry) { 
        entry = clip_utf8_str(entry, 255); 
        txt_flat += sprintf("%1H", entry); 
      } 
    } 
    return txt_flat; 
  } 
 
  //!  Updates the TXT record for the service. 
  //! 
  //!  @param txt 
  //!    A TXT record with service-specific information. It can be given as a 
  //!    plain string or an array of property assignment strings. To remove 
  //!    an existing TXT record you give an empty string as the argument. 
  void update_txt(string|array(string) txt) 
  { 
    //  Get flattened string representation of text record 
    string txt_flat = get_flat_txt_record(txt); 
 
    //  Invoke C interface 
    ::update_txt(txt_flat || ""); 
  } 
 
 
  //!  Registers a service on the local network. 
  //! 
  //!  @param name 
  //!    User-presentable name of the service. 
  //!  @param service 
  //!    Type of service on the form @tt{_type._protocol@}. Type is an 
  //!    identifier related to the service type. A list of registered 
  //!    service types can be found at 
  //!    @url{http://http://www.dns-sd.org/ServiceTypes.html/@}. Protocol 
  //!    is normally @tt{tcp@} but @tt{udp@} is also a valid choice. For 
  //!    example, a web server would get a @[service] of @tt{_http._tcp@}. 
  //!  @param domain 
  //!    Domain name. Normally an empty string which the DNS-SD library 
  //!    will translate into @tt{local.@}. 
  //!  @param port 
  //!    Port number for the service (e.g. 80 for a web site). 
  //!  @param txt 
  //!    An optional TXT record with service-specific information. It can 
  //!    be given as a plain string or an array of property assignment 
  //!    strings. The TXT record can be changed later by calling @[update_txt] 
  //!    in the object returned when you register the service. 
  //! 
  //!  @example 
  //!  object svc = Protocols.DNS_SD.Service( 
  //!                 "Company Intranet Forum",  //  name 
  //!                 "_http._tcp",              //  service type 
  //!                 "",                        //  domain (default) 
  //!                 80,                        //  port 
  //!                 ({ "path=/forum/" })       //  TXT record 
  //!               ); 
  void create(string name, string service, string domain, int port, 
              void|string|array(string) txt) 
  { 
    if (name) 
      name = clip_utf8_str(name, 63); 
 
    //  Pack array of text message records 
    string txt_flat = get_flat_txt_record(txt); 
 
    //  Invoke C code 
    ::create(name || "", service, domain || "", port, txt_flat || ""); 
  } 
 
}; 
#endif