Fawkes API  Fawkes Development Version
 All Classes Namespaces Functions Variables Typedefs Enumerations Enumerator Friends Groups Pages
service_model.cpp
1 
2 /***************************************************************************
3  * service_model.cpp - Manages list of discovered services of given type
4  *
5  * Created: Mon Sep 29 16:37:14 2008
6  * Copyright 2008 Daniel Beck
7  *
8  ****************************************************************************/
9 
10 /* This program is free software; you can redistribute it and/or modify
11  * it under the terms of the GNU General Public License as published by
12  * the Free Software Foundation; either version 2 of the License, or
13  * (at your option) any later version. A runtime exception applies to
14  * this software (see LICENSE.GPL_WRE file mentioned below for details).
15  *
16  * This program is distributed in the hope that it will be useful,
17  * but WITHOUT ANY WARRANTY; without even the implied warranty of
18  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19  * GNU Library General Public License for more details.
20  *
21  * Read the full text in the LICENSE.GPL_WRE file in the doc directory.
22  */
23 
24 #include <gui_utils/service_model.h>
25 #include <netcomm/dns-sd/avahi_thread.h>
26 
27 #include <sys/types.h>
28 #include <sys/socket.h>
29 #include <arpa/inet.h>
30 
31 using namespace std;
32 using namespace fawkes;
33 
34 /** @class fawkes::ServiceModel::ServiceRecord gui_utils/service_model.h
35  * Detects services and manages information about detected services.
36  *
37  * @author Daniel Beck
38  */
39 
40 /** @class fawkes::ServiceModel gui_utils/service_model.h
41  * Abstract base class for widgets that allow to view the detected
42  * services of a certain type.
43  *
44  * @author Daniel Beck
45  */
46 
47 /** @var fawkes::ServiceModel::m_service_list
48  * Storage object.
49  */
50 
51 /** @var fawkes::ServiceModel::m_service_record
52  * Column record class
53  */
54 
55 /** @var fawkes::ServiceModel::m_avahi
56  * Avahi thread.
57  */
58 
59 /** @var fawkes::ServiceModel::m_signal_service_added
60  * This signal is emitted whenever a new service has been added.
61  */
62 
63 /** @var fawkes::ServiceModel::m_signal_service_removed
64  * This signal is emitted whenever a service is removed
65  */
66 
67 /** @struct fawkes::ServiceModel::ServiceAddedRecord
68  * Data structure to hold information about a newly added services.
69  */
70 
71 /** @struct fawkes::ServiceModel::ServiceRemovedRecord
72  * Data structure to hold information about a recently removed services.
73  */
74 
75 /** @var fawkes::ServiceModel::m_added_services
76  * Queue that holds the newly added services.
77  */
78 
79 /** @var fawkes::ServiceModel::m_removed_services
80  * Queue that holds the recently removed services.
81  */
82 
83 /** Constructor.
84  * @param service the service identifier
85  */
86 ServiceModel::ServiceModel(const char* service)
87 {
88  m_service_list = Gtk::ListStore::create(m_service_record);
89 
90  m_avahi = new AvahiThread();
91  m_avahi->watch_service(service, this);
92  m_avahi->start();
93 
94  m_own_avahi_thread = true;
95 
96  m_signal_service_added.connect( sigc::mem_fun(*this, &ServiceModel::on_service_added) );
97  m_signal_service_removed.connect( sigc::mem_fun(*this, &ServiceModel::on_service_removed) );
98 }
99 
100 /** Constructor.
101  * @param avahi_thread an AvahiThread that already watches for the
102  * desired type of services
103  */
104 ServiceModel::ServiceModel(fawkes::AvahiThread* avahi_thread)
105 {
106  m_service_list = Gtk::ListStore::create(m_service_record);
107 
108  m_avahi = avahi_thread;
109  m_own_avahi_thread = false;
110 }
111 
112 /** Destructor. */
113 ServiceModel::~ServiceModel()
114 {
115  if (m_own_avahi_thread)
116  {
117  m_avahi->cancel();
118  m_avahi->join();
119  delete m_avahi;
120  }
121 }
122 
123 /** Get a reference to the model.
124  * @return a reference to the model
125  */
126 Glib::RefPtr<Gtk::ListStore>&
127 ServiceModel::get_list_store()
128 {
129  return m_service_list;
130 }
131 
132 /** Access the column record.
133  * @return the column record
134  */
136 ServiceModel::get_column_record()
137 {
138  return m_service_record;
139 }
140 
141 void
142 ServiceModel::all_for_now()
143 {
144 }
145 
146 void
147 ServiceModel::cache_exhausted()
148 {
149 }
150 
151 void
152 ServiceModel::browse_failed( const char* name,
153  const char* type,
154  const char* domain )
155 {
156 }
157 
158 void
159 ServiceModel::service_added( const char* name,
160  const char* type,
161  const char* domain,
162  const char* host_name,
163  const struct sockaddr* addr,
164  const socklen_t addr_size,
165  uint16_t port,
166  std::list<std::string>& txt,
167  int flags )
168 {
170  char ipaddr[INET_ADDRSTRLEN];
171  struct sockaddr_in *saddr = (struct sockaddr_in *)addr;
172  s.name = string(name);
173  s.type = string(type);
174  s.domain = string(domain);
175  s.hostname = string(host_name);
176  s.ipaddr = inet_ntop(AF_INET, &(saddr->sin_addr), ipaddr, sizeof(ipaddr));
177  s.port = port;
178 
179  m_added_services.push_locked(s);
180 
181  m_signal_service_added();
182 }
183 
184 void
185 ServiceModel::service_removed( const char* name,
186  const char* type,
187  const char* domain )
188 {
190  s.name = string(name);
191  s.type = string(type);
192  s.domain = string(domain);
193 
194  m_removed_services.push_locked(s);
195 
196  m_signal_service_removed();
197 }
198 
199 /** Signal handler for the service-added signal. */
200 void
201 ServiceModel::on_service_added()
202 {
203  m_added_services.lock();
204 
205  while ( !m_added_services.empty() )
206  {
207  ServiceAddedRecord& s = m_added_services.front();
208 
209  Gtk::TreeModel::Row row = *m_service_list->append();
210 
211  row[m_service_record.name] = s.name;
212  row[m_service_record.type] = s.type;
213  row[m_service_record.domain] = s.domain;
214  row[m_service_record.hostname] = s.hostname;
215  row[m_service_record.ipaddr] = s.ipaddr;
216  row[m_service_record.port] = s.port;
217 
218  m_added_services.pop();
219  }
220 
221  m_added_services.unlock();
222 }
223 
224 /** Signal handler for the service-removed signal. */
225 void
226 ServiceModel::on_service_removed()
227 {
228  m_removed_services.lock();
229 
230  while ( !m_removed_services.empty() )
231  {
232  ServiceRemovedRecord& s = m_removed_services.front();
233 
234  Gtk::TreeIter iter;
235  iter = m_service_list->children().begin();
236 
237  while ( iter != m_service_list->children().end() )
238  {
239  Gtk::TreeModel::Row row = *iter;
240  if ( (row[m_service_record.name] == s.name) &&
241  (row[m_service_record.type] == s.type) &&
242  (row[m_service_record.domain] == s.domain) )
243  {
244  iter = m_service_list->erase(iter);
245  m_service_list->row_deleted( m_service_list->get_path(iter) );
246  }
247  else
248  { ++iter; }
249  }
250 
251  m_removed_services.pop();
252  }
253 
254  m_removed_services.unlock();
255 }
std::string ipaddr
the IP address of the new service
Definition: service_model.h:92
std::string hostname
the hostname of the new service
Definition: service_model.h:91
Detects services and manages information about detected services.
Definition: service_model.h:43
std::string type
the type of the service
Definition: service_model.h:99
unsigned short port
the port the new service is running on
Definition: service_model.h:93
Data structure to hold information about a recently removed services.
Definition: service_model.h:96
std::string type
the type of the new service
Definition: service_model.h:89
std::string name
the name of the new service
Definition: service_model.h:88
Avahi main thread.
Definition: avahi_thread.h:55
void cancel()
Cancel a thread.
Definition: thread.cpp:640
std::string domain
the domain of the service
Data structure to hold information about a newly added services.
Definition: service_model.h:86
std::string domain
the domain of the new service
Definition: service_model.h:90
std::string name
the name of the service
Definition: service_model.h:98