00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024 #include <core/exception.h>
00025 #include <core/exceptions/software.h>
00026 #include <netcomm/fawkes/client.h>
00027 #include <netcomm/utils/resolver.h>
00028 #include <gui_utils/service_chooser_dialog.h>
00029 #include <gui_utils/service_model.h>
00030
00031 #include <algorithm>
00032 #include <cstring>
00033 #include <sys/types.h>
00034 #include <sys/socket.h>
00035 #include <arpa/inet.h>
00036 #include <netinet/in.h>
00037
00038 namespace fawkes {
00039 #if 0
00040 }
00041 #endif
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056 ServiceChooserDialog::ServiceChooserDialog(Gtk::Window &parent,
00057 Glib::ustring title,
00058 const char *service)
00059 : Gtk::Dialog(title, parent, true, true),
00060 __parent(parent), __expander("Manual entry")
00061 {
00062 __service_model = new ServiceModel(service);
00063 ctor();
00064 __client = NULL;
00065 }
00066
00067
00068
00069
00070
00071
00072
00073
00074 ServiceChooserDialog::ServiceChooserDialog(Gtk::Window &parent,
00075 FawkesNetworkClient *client,
00076 Glib::ustring title,
00077 const char *service)
00078 : Gtk::Dialog(title, parent, true, true),
00079 __parent(parent), __expander("Manual entry")
00080 {
00081 __service_model = new ServiceModel(service);
00082 ctor();
00083 __client = client;
00084 }
00085
00086
00087
00088 ServiceChooserDialog::~ServiceChooserDialog()
00089 {
00090 delete __service_model;
00091 }
00092
00093
00094 void
00095 ServiceChooserDialog::ctor()
00096 {
00097 set_default_size(360, 240);
00098
00099 __treeview.set_model(__service_model->get_list_store());
00100 __treeview.append_column("Service", __service_model->get_column_record().name);
00101 __treeview.append_column("IP Address", __service_model->get_column_record().ipaddr);
00102 __scrollwin.add(__treeview);
00103 __scrollwin.set_policy(Gtk::POLICY_AUTOMATIC, Gtk::POLICY_AUTOMATIC);
00104 __treeview.show();
00105 __expander.add(__entry);
00106 __entry.show();
00107 __entry.set_activates_default(true);
00108
00109 char * fawkes_ip = getenv("FAWKES_IP");
00110 if (fawkes_ip) __entry.set_text(fawkes_ip);
00111 else __entry.set_text("localhost");
00112
00113 Gtk::VBox *vbox = get_vbox();
00114 vbox->pack_start(__scrollwin);
00115 vbox->pack_end(__expander, Gtk::PACK_SHRINK);
00116 __scrollwin.show();
00117 __expander.show();
00118
00119 add_button(Gtk::Stock::CANCEL, 0);
00120 add_button(Gtk::Stock::OK, 1);
00121
00122 set_default_response(1);
00123
00124 __treeview.signal_row_activated().connect(sigc::bind(sigc::hide<0>(sigc::hide<0>(sigc::mem_fun(*this, &ServiceChooserDialog::response))), 1));
00125
00126 #ifdef GLIBMM_PROPERTIES_ENABLED
00127 __expander.property_expanded().signal_changed().connect(sigc::mem_fun(*this, &ServiceChooserDialog::on_expander_changed));
00128 #endif
00129 }
00130
00131
00132
00133
00134
00135
00136
00137
00138
00139
00140
00141 void
00142 ServiceChooserDialog::get_selected_service(Glib::ustring &name,
00143 Glib::ustring &hostname,
00144 Glib::ustring &ipaddr,
00145 unsigned short int &port)
00146 {
00147 Glib::RefPtr<Gtk::TreeSelection> treesel = __treeview.get_selection();
00148 if (__expander.get_expanded() && !__treeview.has_focus()) {
00149 if ( __entry.get_text_length() > 0 ) {
00150 char *tmpvalue = strdup(__entry.get_text().c_str());
00151
00152 if ( strchr(tmpvalue, ':') != NULL ) {
00153 char *save_ptr;
00154 hostname = strtok_r(tmpvalue, ":", &save_ptr);
00155 char *tmpport = strtok_r(NULL, "", &save_ptr);
00156
00157 int port_num = atoi(tmpport);
00158 if ( (port_num < 0) || (port_num > 0xFFFF) ) {
00159 throw OutOfBoundsException("Invalid port", port_num, 0, 0xFFFF);
00160 }
00161 port = port_num;
00162 } else {
00163 hostname = tmpvalue;
00164 port = 0;
00165 }
00166
00167
00168 ipaddr = hostname;
00169
00170 name = hostname;
00171
00172 free(tmpvalue);
00173 return;
00174 }
00175 }
00176
00177 Gtk::TreeModel::iterator iter = treesel->get_selected();
00178 if (iter) {
00179 Gtk::TreeModel::Row row = *iter;
00180 name = row[__service_model->get_column_record().name];
00181 hostname = row[__service_model->get_column_record().hostname];
00182 ipaddr = row[__service_model->get_column_record().ipaddr];
00183 port = row[__service_model->get_column_record().port];
00184
00185 } else {
00186 throw Exception("No host selected");
00187 }
00188 }
00189
00190
00191
00192
00193
00194
00195
00196 void
00197 ServiceChooserDialog::get_raw_address(struct sockaddr *addr, socklen_t addr_size)
00198 {
00199 if ( addr_size < sizeof(struct sockaddr_in) ) {
00200 throw Exception("Size of addrlen too small, only %u bytes, but required %zu\n",
00201 addr_size, sizeof(struct sockaddr_in));
00202 }
00203 Glib::ustring name, hostname, ipaddr;
00204 unsigned short int port;
00205 get_selected_service (name, hostname, ipaddr, port);
00206
00207 if (inet_pton(AF_INET, ipaddr.c_str(), &(((struct sockaddr_in *)addr)->sin_addr)) <= 0) {
00208 NetworkNameResolver resolver;
00209 struct sockaddr_in *saddr;
00210 socklen_t saddr_len;
00211 if (resolver.resolve_name_blocking(ipaddr.c_str(), (struct sockaddr **)&saddr, &saddr_len)) {
00212 memcpy(addr, saddr, std::min(saddr_len, addr_size));
00213 } else {
00214 throw Exception("Could not lookup hostname '%s' and it is not a valid IP address",
00215 ipaddr.c_str());
00216 }
00217 }
00218
00219 }
00220
00221
00222
00223
00224
00225
00226 void
00227 ServiceChooserDialog::on_expander_changed()
00228 {
00229 if (__expander.get_expanded()) {
00230 __entry.grab_focus();
00231 } else {
00232 __treeview.grab_focus();
00233 }
00234 }
00235
00236
00237
00238
00239
00240
00241
00242
00243
00244 void
00245 ServiceChooserDialog::run_and_connect()
00246 {
00247 if (! __client) throw NullPointerException("FawkesNetworkClient not set");
00248 if (__client->connected()) throw Exception("Client is already connected");
00249
00250 if ( run() ) {
00251 try {
00252 Glib::ustring name;
00253 Glib::ustring hostname;
00254 Glib::ustring ipaddr;
00255 unsigned short int port;
00256 get_selected_service(name, hostname, ipaddr, port);
00257 if ( port == 0 ) port = 1910;
00258
00259 __client->connect(hostname.c_str(), ipaddr.c_str(), port);
00260 } catch (Exception &e) {
00261 Glib::ustring message = *(e.begin());
00262 Gtk::MessageDialog md(__parent, message, false,
00263 Gtk::MESSAGE_ERROR, Gtk::BUTTONS_OK,
00264 true);
00265 md.set_title("Connection failed");
00266 md.run();
00267 }
00268 }
00269 }
00270
00271 }