[rygel/wip/basic-management: 81/95] core: Add BasicManagement Traceroute implementation
- From: Jussi Kukkonen <jussik src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [rygel/wip/basic-management: 81/95] core: Add BasicManagement Traceroute implementation
- Date: Fri, 11 Oct 2013 13:01:07 +0000 (UTC)
commit 021da7a11bd0aad19a2174db7ffde266019bf2f9
Author: Jussi Kukkonen <jussi kukkonen intel com>
Date: Sat Jun 15 22:01:24 2013 +0300
core: Add BasicManagement Traceroute implementation
.../rygel-basic-management-test-traceroute.vala | 158 +++++++++++++++++++-
src/librygel-core/rygel-basic-management.vala | 2 +-
2 files changed, 154 insertions(+), 6 deletions(-)
---
diff --git a/src/librygel-core/rygel-basic-management-test-traceroute.vala
b/src/librygel-core/rygel-basic-management-test-traceroute.vala
index f575025..78187be 100644
--- a/src/librygel-core/rygel-basic-management-test-traceroute.vala
+++ b/src/librygel-core/rygel-basic-management-test-traceroute.vala
@@ -38,6 +38,36 @@ internal class Rygel.BasicManagementTestTraceroute : BasicManagementTest {
private static const uint MAX_HOSTS = 2048;
private static const uint MAX_RESULT_SIZE = 4;
+ private enum ProcessState {
+ INIT,
+ HOPS,
+ }
+
+ private enum Status {
+ SUCCESS,
+ ERROR_CANNOT_RESOLVE_HOSTNAME,
+ ERROR_MAX_HOP_COUNT_EXCEEDED,
+ ERROR_INTERNAL,
+ ERROR_OTHER;
+
+ public string to_string() {
+ switch (this) {
+ case SUCCESS:
+ return "Success";
+ case ERROR_CANNOT_RESOLVE_HOSTNAME:
+ return "Error_CannotResolveHostName";
+ case ERROR_MAX_HOP_COUNT_EXCEEDED:
+ return "Error_MaxHopCountExceeded";
+ case ERROR_INTERNAL:
+ return "Error_Internal";
+ case ERROR_OTHER:
+ return "Error_Other";
+ default:
+ assert_not_reached();
+ }
+ }
+ }
+
public string host { construct; get; default = ""; }
private uint32 _wait_time_out;
@@ -84,7 +114,12 @@ internal class Rygel.BasicManagementTestTraceroute : BasicManagementTest {
default = DEFAULT_DSCP;
}
- private string status;
+ private Regex regex;
+ private Regex rtt_regex;
+ private Status status;
+ private bool error_set;
+ private ProcessState state;
+ private string host_ip;
private string additional_info;
private uint32 response_time;
private string hop_hosts;
@@ -107,7 +142,24 @@ internal class Rygel.BasicManagementTestTraceroute : BasicManagementTest {
public override void constructed () {
base.constructed ();
- stdout.printf("*Traceroute* constructed()\n");
+ try {
+ this.regex = new Regex ("^\\s*(\\d+)\\s+(\\S+)\\s+(\\S+)\\s*(.*)$", 0, 0);
+ this.rtt_regex = new Regex ("(\\S+)\\s+ms\\b", 0, 0);
+ } catch (Error e) {
+ warning ("Failed to create Regexes '%s'", e.message);
+ }
+
+ this.state = ProcessState.INIT;
+ this.status = Status.ERROR_INTERNAL;
+ this.error_set = false;
+ this.hop_hosts = "";
+
+ this.command = { "traceroute",
+ "-m", this.max_hop_count.to_string (),
+ "-w", (this.wait_time_out / 1000).to_string (),
+ "-t", (this.dscp >> 2).to_string (),
+ this.host,
+ this.data_block_size.to_string () };
/* Fail early if internal parameter limits are violated */
if (this.wait_time_out < MIN_TIMEOUT ||
@@ -140,11 +192,107 @@ internal class Rygel.BasicManagementTestTraceroute : BasicManagementTest {
}
}
+ private void set_error (Status status, string info) {
+ this.error_set = true;
+ this.additional_info = info;
+ this.status = status;
+ }
+
+ protected override void handle_error (string line) {
+ if (line.contains ("Cannot handle \"host\" cmdline arg")) {
+ this.set_error (Status.ERROR_CANNOT_RESOLVE_HOSTNAME, "");
+ } else if (line.contains ("Network is unreachable")) {
+ this.set_error (Status.ERROR_OTHER, "Network is unreachable.");
+ } else {
+ this.set_error (Status.ERROR_INTERNAL, line);
+ }
+ }
+
+ protected override void handle_output (string line) {
+ string error = null;
+
+ line.strip ();
+ switch (this.state) {
+ case ProcessState.INIT:
+ if (line.contains ("traceroute to ")) {
+ this.state = ProcessState.HOPS;
+ var start = line.index_of_char ('(');
+ var end = line.index_of_char (')', start);
+ if (end > start)
+ this.host_ip = line.slice (start + 1, end);
+ } else {
+ warning ("traceroute parser: Unexpected line '%s'", line);
+ }
+ break;
+ case ProcessState.HOPS:
+ if (line.contains (" !H "))
+ error = "Host is unreachable.";
+ else if (line.contains (" !N "))
+ error = "Network is unreachable.";
+ else if (line.contains (" !P "))
+ error = "Protocol is unreachable.";
+ else if (line.contains (" !S "))
+ error = "Source route failed.";
+ else if (line.contains (" !F "))
+ error = "Fragmentation needed.";
+ else if (line.contains (" !X "))
+ error = "Network blocks traceroute.";
+
+ if (error != null) {
+ /* should ERROR_CANNOT_RESOLVE_HOSTNAME be used for some errors ? */
+ this.set_error (Status.ERROR_OTHER, error);
+ return;
+ }
+ MatchInfo info;
+ if (!regex.match (line, 0, out info)) {
+ warning ("traceroute parser: Unexpected line '%s'", line);
+ return;
+ }
+
+ if (!this.error_set) {
+ if (info.fetch (3).contains (this.host_ip)) {
+ this.status = Status.SUCCESS;
+ } else {
+ /* set this error as placeholder: normally a later
+ * handle_output() call will set status to SUCCESS */
+ this.status = Status.ERROR_MAX_HOP_COUNT_EXCEEDED;
+ }
+ }
+
+ var host_name = info.fetch (2);
+ if (host_name == "*")
+ host_name = "";
+
+ var rtt_string = info.fetch (4);
+ rtt_regex.match (rtt_string, 0, out info);
+ var rtt_count = 0;
+ var rtt_average = 0.0;
+ try {
+ while (info.matches ()) {
+ rtt_count++;
+ rtt_average += double.parse (info.fetch (1));
+ info.next ();
+ }
+ } catch (RegexError e) {
+ warning ("Regex error while parsing rtt values: %s", e.message);
+ }
+
+ if (rtt_count > 0)
+ rtt_average = rtt_average / rtt_count;
+
+ this.response_time = (uint) Math.round (rtt_average);
+ if (this.hop_hosts.length != 0)
+ this.hop_hosts += ",";
+ this.hop_hosts += host_name;
+
+ break;
+ default:
+ assert_not_reached ();
+ }
+ }
public void get_results(out string status, out string additional_info,
out uint32 response_time, out string hop_hosts) {
- stdout.printf("*Traceroute* get_results()\n");
-
- status = this.status;
+ status = this.status.to_string ();
additional_info = this.additional_info;
response_time = this.response_time;
hop_hosts = this.hop_hosts;
diff --git a/src/librygel-core/rygel-basic-management.vala b/src/librygel-core/rygel-basic-management.vala
index ba31b85..03eadd1 100644
--- a/src/librygel-core/rygel-basic-management.vala
+++ b/src/librygel-core/rygel-basic-management.vala
@@ -407,7 +407,7 @@ public class Rygel.BasicManagement : Service {
typeof (uint32),
out wait_time_out,
"DataBlockSize",
- typeof (string),
+ typeof (uint),
out data_block_size,
"MaxHopCount",
typeof (uint),
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]