OLD | NEW |
---|---|
(Empty) | |
1 // Copyright 2013 The Chromium Authors. All rights reserved. | |
2 // Use of this source code is governed by a BSD-style license that can be | |
3 // found in the LICENSE file. | |
4 | |
5 #include "cloud_print/gcp20/prototype/printer.h" | |
6 | |
7 #include <ifaddrs.h> | |
8 #include <netdb.h> | |
9 | |
10 #include "base/command_line.h" | |
11 #include "base/strings/string_number_conversions.h" | |
12 #include "cloud_print/gcp20/prototype/dns_txt_builder.h" | |
13 #include "cloud_print/gcp20/prototype/service_parameters.h" | |
14 | |
15 namespace { | |
16 | |
17 const char* kServiceType = "_privet._tcp.local"; | |
18 const char* kServiceNamePrefix = "first_gcp20_device"; | |
19 const char* kServiceDomainName = "my-privet-device.local"; | |
20 | |
21 const uint16 kDefaultTTL = 60*60; | |
22 const uint16 kDefaultHttpPort = 10101; | |
23 | |
24 uint16 ReadHttpPortFromCommandLine() { | |
25 uint32 http_port_tmp = kDefaultHttpPort; | |
26 | |
27 std::string http_port_string_tmp = | |
28 CommandLine::ForCurrentProcess()->GetSwitchValueASCII("http-port"); | |
29 base::StringToUint(http_port_string_tmp, &http_port_tmp); | |
30 | |
31 if (http_port_tmp > kuint32max) { | |
gene
2013/06/19 05:40:51
I think max port number in TCP and UDP is 64k
maksymb
2013/06/19 21:47:21
Yes, this is right. Fixed.
| |
32 LOG(ERROR) << "Port " << http_port_tmp << " is too large (maximum is " << | |
33 kDefaultHttpPort << "). Using default port."; | |
34 | |
35 http_port_tmp = kDefaultHttpPort; | |
36 } | |
37 | |
38 VLOG(1) << "HTTP port for responses: " << http_port_tmp; | |
39 return static_cast<uint16>(http_port_tmp); | |
40 } | |
41 | |
42 uint16 ReadTtlFromCommandLine() { | |
43 uint32 ttl = kDefaultTTL; | |
44 | |
45 base::StringToUint( | |
46 CommandLine::ForCurrentProcess()->GetSwitchValueASCII("ttl"), &ttl); | |
47 | |
48 VLOG(1) << "TTL for announcements: " << ttl; | |
49 return ttl; | |
50 } | |
51 | |
52 // Returns pointer to local IP address number. Examples for interface name | |
53 // are: "wlan0", "eth0", NULL (find first acceptable except "lo"). | |
54 net::IPAddressNumber GetLocalIp(const char* interface_name) { | |
55 net::IPAddressNumber result; // |result| is empty if no interface found. | |
56 | |
57 ifaddrs* first_interface = NULL; | |
58 if (getifaddrs(&first_interface) == -1) { | |
59 LOG(ERROR) << "getifaddrs() failed"; | |
60 return result; | |
61 } | |
62 | |
63 // Browse all interfaces. | |
64 char host[NI_MAXHOST] = {0}; | |
65 for (ifaddrs* interface = first_interface; interface; | |
66 interface = interface->ifa_next) { | |
67 if (!interface->ifa_addr) | |
68 continue; | |
69 | |
70 // Get additional info about current interface. | |
71 int rv = getnameinfo(interface->ifa_addr, sizeof(*interface->ifa_addr), | |
72 host, NI_MAXHOST, NULL, 0, NI_NUMERICHOST); | |
73 | |
74 if (interface->ifa_addr->sa_family == AF_INET) { | |
75 // Find interface we need. | |
76 if (interface_name ? (strcmp(interface->ifa_name, interface_name) == 0) | |
77 : (strcmp(interface->ifa_name, "lo") != 0)) { | |
78 if (rv != 0) { | |
79 LOG(ERROR) << "getnameinfo() failed: " << gai_strerror(rv); | |
80 break; | |
81 } | |
82 | |
83 net::ParseIPLiteralToNumber(host, &result); | |
84 } | |
85 } | |
86 } | |
87 | |
88 // Erase memory under list of interfaces. | |
89 freeifaddrs(first_interface); | |
90 return result; | |
91 } | |
92 | |
93 } // namespace | |
94 | |
95 Printer::Printer() : initialized_(false) { | |
96 } | |
97 | |
98 Printer::~Printer() { | |
99 Stop(); | |
100 } | |
101 | |
102 bool Printer::Start() { | |
103 if (initialized_) | |
104 return true; | |
105 | |
106 // TODO(maksymb): Add possibility to control interface via command line args. | |
107 net::IPAddressNumber ip = GetLocalIp(NULL); | |
108 if (ip.empty()) { | |
109 LOG(ERROR) << "No local IP found. Cannot start printer."; | |
110 return false; | |
111 } | |
112 VLOG(1) << "Local address: " << net::IPAddressToString(ip); | |
113 | |
114 // Starting DNS-SD server. | |
115 initialized_ = dns_server_.Start( | |
116 ServiceParameters(kServiceType, | |
117 kServiceNamePrefix, | |
118 kServiceDomainName, | |
119 ip, | |
120 ReadHttpPortFromCommandLine()), | |
121 ReadTtlFromCommandLine(), | |
122 CreateTxt()); | |
123 | |
124 return initialized_; | |
125 } | |
126 | |
127 void Printer::Stop() { | |
128 if (!initialized_) | |
129 return; | |
130 | |
131 dns_server_.Shutdown(); | |
132 } | |
133 | |
134 std::string Printer::CreateTxt() const { | |
135 DnsTxtBuilder txt_builder; | |
136 | |
137 txt_builder.AddRecord("txtvers=1"); | |
138 txt_builder.AddRecord("ty=Google Cloud Ready Printer GCP2.0 Prototype"); | |
139 txt_builder.AddRecord("note=Virtual printer"); | |
140 txt_builder.AddRecord("url=https://www.google.com/cloudprint"); | |
141 txt_builder.AddRecord("type=printer"); | |
142 txt_builder.AddRecord("id="); | |
143 txt_builder.AddRecord("cs=offline"); | |
144 | |
145 return txt_builder.Build(); | |
146 } | |
147 | |
OLD | NEW |