Support context extract. (#1)

diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml
index a198b6c..2cfeb06 100644
--- a/.github/workflows/ci.yaml
+++ b/.github/workflows/ci.yaml
@@ -1,4 +1,4 @@
-name: CI AND IT
+name: CI
 
 on:
   pull_request:
diff --git a/Cargo.lock b/Cargo.lock
index afa77c2..dee751b 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -1,6 +1,12 @@
 # This file is automatically @generated by Cargo.
 # It is not intended for manual editing.
 [[package]]
+name = "base64"
+version = "0.11.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b41b7ea54a0c9d92199de89e20e58d49f02f8e699814ef3fdf266f6f748d15c7"
+
+[[package]]
 name = "c2-chacha"
 version = "0.2.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -83,6 +89,7 @@
 name = "skywalking-core"
 version = "0.1.0"
 dependencies = [
+ "base64",
  "rand",
 ]
 
diff --git a/tracing-core/Cargo.toml b/tracing-core/Cargo.toml
index 6751303..821e4ef 100644
--- a/tracing-core/Cargo.toml
+++ b/tracing-core/Cargo.toml
@@ -7,4 +7,5 @@
 license = "Apache 2.0"
 
 [dependencies]
-rand = "0.7.3"
\ No newline at end of file
+rand = "0.7.3"
+base64 = "0.11.0"
\ No newline at end of file
diff --git a/tracing-core/src/context.rs b/tracing-core/src/context.rs
index 5817110..6525c04 100644
--- a/tracing-core/src/context.rs
+++ b/tracing-core/src/context.rs
@@ -13,17 +13,21 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
+use base64::{decode, encode};
+
 use crate::{ContextListener, ID, Span};
+use crate::context_carrier::{Extractable, Injectable};
 use crate::id::IDGenerator;
+use crate::segment_ref::SegmentRef;
 use crate::span::TracingSpan;
 
 /// Context represents the context of a tracing process.
 /// All new span belonging to this tracing context should be created through this context.
 pub trait Context {
     /// Create an entry span belonging this context
-    fn create_entry_span(&mut self, operation_name: String, parent: Option<&Box<dyn Span>>) -> Box<dyn Span>;
+    fn create_entry_span(&mut self, operation_name: String, parent: Option<&Box<dyn Span>>, extractor: &dyn Extractable) -> Box<dyn Span>;
     /// Create an exit span belonging this context
-    fn create_exit_span(&mut self, operation_name: String, parent: Option<&Box<dyn Span>>) -> Box<dyn Span>;
+    fn create_exit_span(&mut self, operation_name: String, parent: Option<&Box<dyn Span>>, peer: String, injector: &dyn Injectable) -> Box<dyn Span>;
     /// Create an local span belonging this context
     fn create_local_span(&mut self, operation_name: String, parent: Option<&Box<dyn Span>>) -> Box<dyn Span>;
     /// Finish the given span. The span is only being accept if it belongs to this context.
@@ -67,25 +71,39 @@
 
 /// Default implementation of Context
 impl Context for TracingContext {
-    fn create_entry_span(&mut self, operation_name: String, parent: Option<&Box<dyn Span>>) -> Box<dyn Span> {
-        TracingSpan::new_entry_span(operation_name, self.next_span_id(), match parent {
+    fn create_entry_span(&mut self, operation_name: String, parent: Option<&Box<dyn Span>>, extractor: &dyn Extractable) -> Box<dyn Span> {
+        let mut entry_span = TracingSpan::new_entry_span(operation_name, self.next_span_id(), match parent {
             None => { -1 }
             Some(s) => { s.span_id() }
-        })
+        });
+        match SegmentRef::from_text(extractor.extract("sw6".to_string())) {
+            Some(reference) => {
+                if self.self_generated_id {
+                    self.self_generated_id = false;
+                    self.primary_trace_id = reference.get_trace_id();
+                }
+                entry_span._add_ref(reference);
+            }
+            _ => {}
+        }
+        Box::new(entry_span)
     }
 
-    fn create_exit_span(&mut self, operation_name: String, parent: Option<&Box<dyn Span>>) -> Box<dyn Span> {
-        TracingSpan::new_exit_span(operation_name, self.next_span_id(), match parent {
+    fn create_exit_span(&mut self, operation_name: String, parent: Option<&Box<dyn Span>>, peer: String, injector: &dyn Injectable) -> Box<dyn Span> {
+        let exit_span = TracingSpan::new_exit_span(operation_name, self.next_span_id(), match parent {
             None => { -1 }
             Some(s) => { s.span_id() }
-        })
+        }, peer);
+
+
+        Box::new(exit_span)
     }
 
     fn create_local_span(&mut self, operation_name: String, parent: Option<&Box<dyn Span>>) -> Box<dyn Span> {
-        TracingSpan::new_local_span(operation_name, self.next_span_id(), match parent {
+        Box::new(TracingSpan::new_local_span(operation_name, self.next_span_id(), match parent {
             None => { -1 }
             Some(s) => { s.span_id() }
-        })
+        }))
     }
 
     fn finish_span(&mut self, mut span: Box<dyn Span>) {
@@ -101,20 +119,20 @@
     use std::sync::mpsc;
     use std::sync::mpsc::{Receiver, Sender};
 
-    use crate::{Context, ContextListener, Tag, TracingContext};
+    use crate::{Context, ContextListener, Extractable, ID, Tag, TracingContext};
 
     #[test]
     fn test_context_stack() {
         let reporter = MockReporter::new();
         let mut context = TracingContext::new(&reporter).unwrap();
-        let span1 = context.create_entry_span(String::from("op1"), None);
+        let span1 = context.create_entry_span(String::from("op1"), None, &MockerHeader {});
         {
             assert_eq!(span1.span_id(), 0);
-            let mut span2 = context.create_entry_span(String::from("op2"), Some(&span1));
+            let mut span2 = context.create_local_span(String::from("op2"), Some(&span1));
             span2.tag(Tag::new(String::from("tag1"), String::from("value1")));
             {
                 assert_eq!(span2.span_id(), 1);
-                let mut span3 = context.create_entry_span(String::from("op3"), Some(&span2));
+                let mut span3 = context.create_local_span(String::from("op3"), Some(&span2));
                 assert_eq!(span3.span_id(), 2);
 
                 context.finish_span(span3);
@@ -127,6 +145,7 @@
         // context has moved into reporter. Can't be used again.
 
         let received_context = reporter.recv.recv().unwrap();
+        assert_eq!(received_context.primary_trace_id == ID::new(3, 4, 5), true);
         assert_eq!(received_context.finished_spans.len(), 3);
     }
 
@@ -161,6 +180,14 @@
         }
     }
 
+    struct MockerHeader {}
+
+    impl Extractable for MockerHeader {
+        fn extract(&self, key: String) -> &str {
+            "1-My40LjU=-MS4yLjM=-4-1-1-IzEyNy4wLjAuMTo4MDgw-Iy9wb3J0YWw=-MTIz"
+        }
+    }
+
     struct MockRegisterPending {}
 
     impl ContextListener for MockRegisterPending {
diff --git a/tracing-core/src/context_carrier.rs b/tracing-core/src/context_carrier.rs
index b56a2c3..3ab607d 100644
--- a/tracing-core/src/context_carrier.rs
+++ b/tracing-core/src/context_carrier.rs
@@ -14,10 +14,16 @@
 // limitations under the License.
 
 /// The Injectable implementation supports inject the give key/value for further propagation,
-/// especially in across process propagation.
 /// Such as putting a key/value into the HTTP header.
 pub trait Injectable {
     /// Inject the given key/value into the implementation.
     /// The way of injection is determined by the implementation, no panic! should happens even injection fails.
-    fn inject(key: String, value: String);
+    fn inject(&self, key: String, value: String);
+}
+
+/// The Extractable implementations extract propagated context out the implementation.
+/// Such as fetching the key/value from the HTTP header.
+pub trait Extractable {
+    /// Fetch the value by the given key.
+    fn extract(&self, key: String) -> &str;
 }
\ No newline at end of file
diff --git a/tracing-core/src/id.rs b/tracing-core/src/id.rs
index 7f31724..b276986 100644
--- a/tracing-core/src/id.rs
+++ b/tracing-core/src/id.rs
@@ -15,6 +15,7 @@
 
 use std::hash::Hash;
 use std::time::SystemTime;
+
 use rand::RngCore;
 
 pub struct IDGenerator {}
@@ -53,18 +54,18 @@
 
     /// Convert the literal string text back to ID object.
     /// Return Option::None if the text is not combined by 3 dot split i64 parts
-    pub fn from(id_text: String) -> Option<Self> {
+    pub fn from(id_text: String) -> Result<Self, String> {
         let strings: Vec<&str> = id_text.split(".").collect();
         if strings.len() == 3 {
             let part1 = strings[0].parse::<i64>();
-            if part1.is_err() { return None; }
+            if part1.is_err() { return Err("part 1 is not a i64".to_string()); }
             let part2 = strings[1].parse::<i64>();
-            if part2.is_err() { return None; }
+            if part2.is_err() { return Err("part 2 is not a i64".to_string()); }
             let part3 = strings[2].parse::<i64>();
-            if part3.is_err() { return None; }
-            Some(ID::new(part1.unwrap(), part2.unwrap(), part3.unwrap()))
+            if part3.is_err() { return Err("part 3 is not a i64".to_string()); }
+            Ok(ID::new(part1.unwrap(), part2.unwrap(), part3.unwrap()))
         } else {
-            None
+            Err("The ID is not combined by 3 parts.".to_string())
         }
     }
 }
@@ -107,9 +108,9 @@
         assert_eq!(id4.eq(&id1), true);
 
         let id5_none = ID::from(String::from("1.2"));
-        assert_eq!(id5_none == None, true);
+        assert_ne!(id5_none.err().unwrap().len(), 0);
 
         let id6_illegal = ID::from(String::from("1.2.a"));
-        assert_eq!(id6_illegal == None, true);
+        assert_ne!(id6_illegal.err().unwrap().len(), 0);
     }
 }
\ No newline at end of file
diff --git a/tracing-core/src/lib.rs b/tracing-core/src/lib.rs
index 457c326..7d9a2d1 100644
--- a/tracing-core/src/lib.rs
+++ b/tracing-core/src/lib.rs
@@ -15,6 +15,8 @@
 
 pub use context::Context;
 pub use context::TracingContext;
+pub use context_carrier::Extractable;
+pub use context_carrier::Injectable;
 pub use context_listener::ContextListener;
 pub use id::ID;
 pub use log::EventField;
@@ -29,4 +31,5 @@
 pub mod context_listener;
 pub mod log;
 pub mod context_carrier;
+pub mod segment_ref;
 
diff --git a/tracing-core/src/segment_ref.rs b/tracing-core/src/segment_ref.rs
new file mode 100644
index 0000000..104060c
--- /dev/null
+++ b/tracing-core/src/segment_ref.rs
@@ -0,0 +1,150 @@
+// Licensed to the Apache Software Foundation (ASF) under one or more
+// contributor license agreements.  See the NOTICE file distributed with
+// this work for additional information regarding copyright ownership.
+// The ASF licenses this file to You under the Apache License, Version 2.0
+// (the "License"); you may not use this file except in compliance with
+// the License.  You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+use crate::ID;
+
+pub struct SegmentRef {
+    trace_id: ID,
+    segment_id: ID,
+    span_id: i32,
+    parent_service_instance_id: i32,
+    entry_service_instance_id: i32,
+    network_address: Option<String>,
+    network_address_id: i32,
+    entry_endpoint: Option<String>,
+    entry_endpoint_id: i32,
+    parent_endpoint: Option<String>,
+    parent_endpoint_id: i32,
+}
+
+impl SegmentRef {
+    pub fn from_text(value: &str) -> Option<Self> {
+        let strings: Vec<&str> = value.split("-").collect();
+        if strings.len() == 9 {
+            // Ignore string[0].
+            let trace_id = match SegmentRef::string_to_id(strings[1]) {
+                Some(id) => { id }
+                _ => { return None; }
+            };
+            let segment_id = match SegmentRef::string_to_id(strings[2]) {
+                Some(id) => { id }
+                _ => { return None; }
+            };
+            let span_id = match strings[3].parse::<i32>() {
+                Ok(id) => { id }
+                _ => { return None; }
+            };
+            let parent_service_instance_id = match strings[4].parse::<i32>() {
+                Ok(id) => { id }
+                _ => { return None; }
+            };
+            let entry_service_instance_id = match strings[5].parse::<i32>() {
+                Ok(id) => { id }
+                _ => { return None; }
+            };
+
+            let (network_address, network_address_id) = match SegmentRef::decode_base64_to_string_or_id(strings[6]) {
+                Some(decoded) => { decoded }
+                _ => { return None; }
+            };
+            let (entry_endpoint, entry_endpoint_id) = match SegmentRef::decode_base64_to_string_or_id(strings[7]) {
+                Some(decoded) => { decoded }
+                _ => { return None; }
+            };
+            let (parent_endpoint, parent_endpoint_id) = match SegmentRef::decode_base64_to_string_or_id(strings[8]) {
+                Some(decoded) => { decoded }
+                _ => { return None; }
+            };
+
+            Some(SegmentRef {
+                trace_id,
+                segment_id,
+                span_id,
+                parent_service_instance_id,
+                entry_service_instance_id,
+                network_address,
+                network_address_id,
+                entry_endpoint,
+                entry_endpoint_id,
+                parent_endpoint,
+                parent_endpoint_id,
+            })
+        } else {
+            None
+        }
+    }
+
+    pub fn get_trace_id(&self) -> ID {
+        self.trace_id.clone()
+    }
+
+    fn string_to_id(text: &str) -> Option<ID> {
+        match base64::decode(text) {
+            Ok(value) => {
+                match String::from_utf8(value) {
+                    Ok(str) => {
+                        match ID::from(str) {
+                            Ok(id) => { Some(id) }
+                            _ => None
+                        }
+                    }
+                    _ => { None }
+                }
+            }
+            _ => { None }
+        }
+    }
+
+    fn decode_base64_to_string_or_id(text: &str) -> Option<(Option<String>, i32)> {
+        match base64::decode(text) {
+            Ok(value) => {
+                match String::from_utf8(value) {
+                    Ok(str) => {
+                        if str.starts_with("#") {
+                            let network: Vec<&str> = str.split("#").collect();
+                            (Some((Some(network[1].to_string()), 0)))
+                        } else {
+                            match str.parse::<i32>() {
+                                Ok(id) => { Some((None, id)) }
+                                _ => { None }
+                            }
+                        }
+                    }
+                    _ => { None }
+                }
+            }
+            _ => { None }
+        }
+    }
+}
+
+#[cfg(test)]
+mod segment_ref_tests {
+    use crate::ID;
+    use crate::segment_ref::SegmentRef;
+
+    #[test]
+    fn test_deserialize_context_carrier() {
+        let carrier = SegmentRef::from_text("1-My40LjU=-MS4yLjM=-4-1-1-IzEyNy4wLjAuMTo4MDgw-Iy9wb3J0YWw=-MTIz").unwrap();
+        assert_eq!(carrier.trace_id == ID::new(3, 4, 5), true);
+        assert_eq!(carrier.segment_id == ID::new(1, 2, 3), true);
+        assert_eq!(carrier.span_id, 4);
+        assert_eq!(carrier.entry_service_instance_id, 1);
+        assert_eq!(carrier.parent_service_instance_id, 1);
+        assert_eq!(carrier.network_address, Some("127.0.0.1:8080".to_string()));
+        assert_eq!(carrier.entry_endpoint, Some("/portal".to_string()));
+        assert_eq!(carrier.parent_endpoint_id, 123);
+    }
+}
diff --git a/tracing-core/src/span.rs b/tracing-core/src/span.rs
index 9829d7d..623cdc6 100644
--- a/tracing-core/src/span.rs
+++ b/tracing-core/src/span.rs
@@ -16,6 +16,7 @@
 use std::time::SystemTime;
 
 use crate::log::LogEvent;
+use crate::segment_ref::SegmentRef;
 use crate::Tag;
 
 /// Span is one of the tracing concept, representing a time duration.
@@ -79,31 +80,33 @@
     component_id: Option<i32>,
     tags: Vec<Tag>,
     logs: Vec<LogEvent>,
+    refs: Vec<SegmentRef>,
 }
 
 /// Tracing Span is only created inside TracingContext.
 impl TracingSpan {
     /// Create a new entry span
-    pub fn new_entry_span(operation_name: String, span_id: i32, parent_span_id: i32) -> Box<dyn Span> {
+    pub fn new_entry_span(operation_name: String, span_id: i32, parent_span_id: i32) -> TracingSpan {
         let mut span = TracingSpan::_new(operation_name, span_id, parent_span_id);
         span.is_entry = true;
-        Box::new(span)
+        span
     }
 
     /// Create a new exit span
-    pub fn new_exit_span(operation_name: String, span_id: i32, parent_span_id: i32) -> Box<dyn Span> {
+    pub fn new_exit_span(operation_name: String, span_id: i32, parent_span_id: i32, peer: String) -> TracingSpan {
         let mut span = TracingSpan::_new(operation_name, span_id, parent_span_id);
         span.is_exit = true;
-        Box::new(span)
+        span.peer = Some(peer);
+        span
     }
 
     /// Create a new local span
-    pub fn new_local_span(operation_name: String, span_id: i32, parent_span_id: i32) -> Box<dyn Span> {
+    pub fn new_local_span(operation_name: String, span_id: i32, parent_span_id: i32) -> TracingSpan {
         let span = TracingSpan::_new(operation_name, span_id, parent_span_id);
-        Box::new(span)
+        span
     }
 
-    /// Create a span and set the limited internal values
+    /// Create a span
     fn _new(operation_name: String, span_id: i32, parent_span_id: i32) -> Self {
         TracingSpan {
             operation_name,
@@ -118,8 +121,13 @@
             component_id: None,
             tags: Vec::new(),
             logs: Vec::new(),
+            refs: Vec::new(),
         }
     }
+
+    pub fn _add_ref(&mut self, reference: SegmentRef) {
+        self.refs.push(reference);
+    }
 }
 
 impl Span for TracingSpan {