Commit 64f34bc

bryfry <bryon.fryer@gmail.com>
2016-04-22 16:35:00
migrate go-code
1 parent 7875bef
go-code/hello/hello.go
@@ -0,0 +1,9 @@
+package main
+
+import (
+  "fmt"
+  "github.com/bryfry/string" 
+)
+func main() {
+  fmt.Println(string.Reverse("Hello, World!"))
+}
go-code/ltcodes/.ltcodes.go.swp
Binary file
go-code/ltcodes/ltcodes.go
@@ -0,0 +1,186 @@
+package ltcodes
+
+import "math/rand"
+import "fmt"
+import "math"
+import "bytes"
+
+type Packet struct {
+	n      int
+	degree int
+	seed   int64
+	data   []byte
+}
+
+type indexedPacket struct {
+	index  []int
+	degree int
+	data   []byte
+}
+
+func xorBytes(b ...[]byte) []byte {
+	b_len := len(b[0])
+	for _, m := range b {
+		if len(m) != b_len {
+			panic("length mismatch!")
+		}
+	}
+	br := make([]byte, b_len)
+	for i := range b[0] {
+		br[i] = 0
+		for _, m := range b {
+			br[i] = br[i] ^ m[i]
+		}
+	}
+	return br
+}
+
+func degreeGen(msg_len int, block_len int) int {
+	// returns 1 <= d <= msg_len - block_len
+	// TODO: implement "robust soliton distribution" here
+	return rand.Intn(msg_len-block_len-1) + 1
+}
+
+// create or reconstruct the list of source blocks that were used
+// to generate an encoded block
+func indexGen(degree int, seed int64, n_blocks int) []int {
+	psudo_seed := rand.NewSource(seed)
+	psudo_rng := rand.New(psudo_seed)
+	indices := make([]int, degree)
+	for i := 0; i < degree; i++ {
+		indices[i] = psudo_rng.Intn(n_blocks)
+	}
+	return indices
+}
+
+// Emit one encoded Packet from message msg and of length block_len
+// Packet return includes: generated degree (degree), index seed (seed),
+// number of blocks msg has been divided into (n), and the encoded data (data)
+func Encode(packets chan<- Packet, msg []byte, block_len int) Packet {
+	for {
+		// TODO: add check for erroneous block_len (relative to len(m))
+		n_blocks := len(msg) / block_len
+		degree := degreeGen(len(msg), block_len)
+		blocks := make([][]byte, degree)
+		seed := rand.Int63n(math.MaxInt64)
+		indices := indexGen(degree, seed, n_blocks)
+		for i, m := range indices {
+			blocks[i] = make([]byte, block_len)
+			blocks[i] = msg[m*block_len : (m*block_len + block_len)]
+		}
+		packets <- Packet{n: n_blocks, degree: degree, seed: seed, data: xorBytes(blocks...)}
+	}
+}
+
+// check if decoding complete
+func messageDecoded(message [][]byte) bool {
+	for _, v := range message {
+		if v == nil {
+			return false
+		}
+	}
+	return true
+}
+
+// translation from packet to indexedPacket type
+func indexPacket(p Packet) indexedPacket {
+	i := indexGen(p.degree, p.seed, p.n)
+	return indexedPacket{index: i, degree: p.degree, data: p.data}
+}
+
+// decrease the index of "packet" at index "i" by xoring in "clean_data"
+// return updated packet
+func reducePacket(i int, packet indexedPacket, clean_data []byte) indexedPacket {
+	packet.data = xorBytes(packet.data, clean_data)
+	packet.index = append(packet.index[:i], packet.index[i+1:]...)
+	packet.degree = packet.degree - 1
+	return packet
+}
+
+// check packet for index values that match up with clean ones (stored in message)
+// reduce packet if match found and return it
+func process(packet indexedPacket, message [][]byte) indexedPacket {
+	for i := 0; i < len(packet.index); i++ { //, m_i := range packet.index {
+		if message[packet.index[i]] != nil {
+			packet = reducePacket(i, packet, message[packet.index[i]])
+		}
+	}
+	return packet
+}
+
+// check clean data against buffer of unprocessed data
+func processClean(clean indexedPacket, buffer_area []indexedPacket, message [][]byte) ([][]byte, []indexedPacket) {
+	if len(clean.index) != 1 {
+		panic("received 'clean' of degree != 1")
+	}
+	clean_index := clean.index[0]
+	message[clean_index] = clean.data
+	if messageDecoded(message) {
+		return message, buffer_area
+	}
+
+	// loop over all buffered packets
+	for b_i := 0; b_i < len(buffer_area); b_i++ {
+		packet := buffer_area[b_i]
+
+		// loop over packet index
+		for i := 0; i < len(packet.index); i++ {
+
+			// if match, reduce packet
+			if clean_index == packet.index[i] {
+
+				// important to update packet (for loop needs it)
+				packet = reducePacket(i, packet, clean.data)
+				buffer_area[b_i] = packet
+
+				// check for and handle a new clean packet
+				if packet.degree == 1 {
+					buffer_area = append(buffer_area[:b_i], buffer_area[b_i+1:]...)
+					if message[packet.index[0]] == nil {
+						message, buffer_area = processClean(packet, buffer_area, message)
+					}
+				}
+			}
+		}
+	}
+	return message, buffer_area
+}
+
+// receive packets and combine them until message discovered
+func Decode(packets <-chan Packet, decodeDone chan<- bool) {
+
+	// get first packet and setup
+	p := <-packets
+	message := make([][]byte, p.n)
+	buffer_area := make([]indexedPacket, 1)
+	buffer_area[0] = indexPacket(p)
+	counter := 0
+
+	// packet receive loop
+	for {
+		p := indexPacket(<-packets)
+		counter++
+
+		if p.degree > 1 {
+			p = process(p, message)
+
+			if p.degree > 1 {
+				buffer_area = append(buffer_area, p)
+
+			} else if p.degree == 1 {
+				message, buffer_area = processClean(p, buffer_area, message)
+			}
+
+		} else if p.degree == 1 {
+			message, buffer_area = processClean(p, buffer_area, message)
+		}
+
+		if messageDecoded(message) {
+			fmt.Println("Packets:", counter)
+			outMsg := bytes.Join(message, []byte{})
+			fmt.Println("Packets / byte:", float64(counter)/float64(len(outMsg)))
+			decodeDone <- true
+			return
+		}
+	}
+}
go-code/ltdemo/.ltdemo.go.swp
Binary file
go-code/ltdemo/ltdemo
Binary file
go-code/ltdemo/ltdemo.go
@@ -0,0 +1,50 @@
+package main
+
+//import "encoding/hex"
+//import "math"
+import "github.com/bryfry/ltcodes"
+import "math/rand"
+import "fmt"
+import "time"
+
+func main() {
+	rand.Seed(time.Now().UTC().UnixNano())
+	block_len := 15
+	test_msg := []byte("this is a test, this is only a test. Drop the beat!")
+	//fmt.Println(test_msg)
+	packets := make(chan ltcodes.Packet, 100)
+	decodeDone := make(chan bool)
+
+	// emit packets
+	go ltcodes.Encode(packets, test_msg, block_len)
+	go ltcodes.Decode(packets, decodeDone)
+	for {
+		select {
+		case <-decodeDone:
+			fmt.Println("Decode complete!")
+			return
+		}
+	}
+	close(packets)
+
+	// move to test
+	/*debug_xor := false
+	if debug_xor {
+		b1 := []byte("WhatAmIDoingHere?")
+		b2 := []byte("thisisjustatest !")
+		b3 := []byte("omg, there's more")
+		fmt.Println(hex.EncodeToString(xorBytes(b1, b2, b1, b2)))
+		fmt.Println(hex.EncodeToString([]byte(b1)))
+		fmt.Println(hex.EncodeToString(xorBytes(b1, b2, b3)))
+		fmt.Println(hex.EncodeToString(xorBytes(b1, b1)))   // expect all 00's
+		fmt.Println(string(xorBytes(b1, b2, b1))[:len(b1)]) // expect b2
+		b123 := [][]byte{b1, b2, b3}
+		b11 := [][]byte{b1, b1}
+		b121 := [][]byte{b1, b2, b1}
+		b1only := [][]byte{b1}
+		fmt.Println(hex.EncodeToString(xorBytes(b123...))) // expect same an non 2d slice array
+		fmt.Println(hex.EncodeToString(xorBytes(b11...)))  // expect all 00's
+		fmt.Println(string(xorBytes(b121...))[:len(b1)])   // expect b2
+		fmt.Println(string(xorBytes(b1only...))[:len(b1)]) // expect b1
+	}*/
+}
go-code/string/string.go
@@ -0,0 +1,10 @@
+package string
+
+func Reverse(s string) string {
+  b := []rune(s)
+  for i:=0; i<len(b)/2; i++ {
+    j := len(b)-i-1
+    b[i], b[j] = b[j], b[i]
+  }
+  return string(b)
+}
go-code/string/string_test.go
@@ -0,0 +1,19 @@
+package string
+
+import "testing"
+
+func Test(t *testing.T) {
+  var tests = []struct {
+    s, want string
+  }{
+    {"Backward", "drawkcaB"},
+    {"I am dissapoint ಠ_ಠ","ಠ_ಠ tniopassid ma I"},
+    {"",""},
+  }
+  for _, c := range tests {
+    got := Reverse(c.s)
+    if got != c.want {
+      t.Errorf("Reverse(%q) == %q, want %q", c.s, got, c.want)
+    }
+  }
+}
go-code/.gitignore
@@ -0,0 +1,1 @@
+.DS_Store
go-code/README.md
@@ -0,0 +1,4 @@
+go-code
+=======
+
+playground for go code