diff --git a/.gitignore b/.gitignore index 66fd13c..299d96d 100644 --- a/.gitignore +++ b/.gitignore @@ -1,15 +1,14 @@ # Binaries for programs and plugins -*.exe -*.exe~ -*.dll -*.so -*.dylib +node +led +colonel +sentinel # Test binary, built with `go test -c` -*.test # Output of the go coverage tool, specifically when used with LiteIDE -*.out # Dependency directories (remove the comment below to include it) # vendor/ + +.gitignore diff --git a/convo/Makefile b/convo/Makefile new file mode 100644 index 0000000..e22f58d --- /dev/null +++ b/convo/Makefile @@ -0,0 +1,8 @@ +all: clean build + +clean: + rm speak reply + +build: + go build speak.go + go build reply.go diff --git a/convo/convo.txt b/convo/convo.txt new file mode 100644 index 0000000..d128095 --- /dev/null +++ b/convo/convo.txt @@ -0,0 +1,23 @@ +# ============================================================================== +# Auth: Alex Celani +# File: convo.txt +# Revn: 05-10-2022 0.1 +# Func: elaborate on how the convo Golang networks programs should run +# +# TODO: create +# ============================================================================== +# CHANGE LOG +# ------------------------------------------------------------------------------ +# 05-10-2022: init +# +# ============================================================================== + + +uh + +just send a bunch of information back and forth + +A sends data to B, B receives, processes, and responds +A receives, processes, and responds + +Repeat until some cutoff condition diff --git a/convo/reply b/convo/reply new file mode 100755 index 0000000..f44c736 Binary files /dev/null and b/convo/reply differ diff --git a/convo/reply.go b/convo/reply.go new file mode 100644 index 0000000..75aa1d6 --- /dev/null +++ b/convo/reply.go @@ -0,0 +1,84 @@ +// ============================================================================= +// Auth: Alex Celani +// File: reply.go +// Revn: 05-13-2022 0.1 +// Func: host connection, reply to speak.go +// +// TODO: create +// ============================================================================= +// CHANGE LOG +// ----------------------------------------------------------------------------- +// 05-13-2022: init +// +// ============================================================================= + +package main + +import ( + "net" + "os" + "fmt" + "time" +) + + +func check( err error ) { + if err != nil { + fmt.Println( "Fatal: ", err.Error() ) + os.Exit( 1 ) + } +} + + +func handle( conn net.Conn ) { + + table := map[string]string{ "hello":"hello", + "how are you":"fine and yourself", + "well enough for the weather":"aye it scalds", + "i lost my begonias":"exit" } + var buffer [512]byte + for { + n, err := conn.Read( buffer[:] ) + check( err ) + + fmt.Println( "\t\t\t", string( buffer[:n] ) ) + + time.Sleep( 2 * time.Second ) + + response, present := table[string( buffer[:n] )] + if present { + _, err = conn.Write( []byte( response ) ) + check( err ) + + + if response == "exit" { + break + } else { + fmt.Println( response ) + } + } else { + fmt.Println( "excuse me good sir" ) + os.Exit( 2 ) + } + } +} + + +func main() { + + service := ":1200" + + addr, err := net.ResolveTCPAddr( "tcp", service ) + check( err ) + + listener, err := net.ListenTCP( "tcp", addr ) + + conn, err := listener.Accept() + check( err ) + + handle( conn ) + + os.Exit( 0 ) + +} + diff --git a/convo/speak b/convo/speak new file mode 100755 index 0000000..cced46c Binary files /dev/null and b/convo/speak differ diff --git a/convo/speak.go b/convo/speak.go new file mode 100644 index 0000000..f1170a8 --- /dev/null +++ b/convo/speak.go @@ -0,0 +1,85 @@ +// ============================================================================= +// Auth: Alex Celani +// File: speak.go +// Revn: 05-11-2022 0.1 +// Func: initiate conversation +// +// TODO: create +// ============================================================================= +// CHANGE LOG +// ----------------------------------------------------------------------------- +// 05-11-2022: init +// 05-17-2022: changed an entry in the response table +// +// ============================================================================= + +package main + +import ( + "net" + "os" + "fmt" + "time" +) + + +func check( err error ) { + if err != nil { + fmt.Println( "fatal: ", err.Error() ) + os.Exit( 1 ) + } +} + + +func handle( conn net.Conn ) { + + table := map[string]string{ "hello":"how are you", + "fine and yourself":"well enough for the weather", + "aye it scalds":"i lost my begonias" } + var buffer [512]byte + for { + n, err := conn.Read( buffer[:] ) + check( err ) + + if string( buffer[:n] ) == "exit" { + break + } + + fmt.Println( "\t\t\t", string( buffer[:n] ) ) + + time.Sleep( 2 * time.Second ) + + response, present := table[string( buffer[:n] )] + if present { + _, err = conn.Write( []byte( response ) ) + check( err ) + + fmt.Println( response ) + } else { + fmt.Println( "excuse me good sir" ) + os.Exit( 2 ) + } + } +} + + +func main() { + + service := ":1200" + + addr, err := net.ResolveTCPAddr( "tcp", service ) + check( err ) + + conn, err := net.DialTCP( "tcp", nil, addr ) + check( err ) + + _, err = conn.Write( []byte( "hello" ) ) + check( err ) + fmt.Println( "hello" ) + + handle( conn ) + + os.Exit( 0 ) + +} + diff --git a/draft1_route/Makefile b/draft1_route/Makefile new file mode 100644 index 0000000..a477c89 --- /dev/null +++ b/draft1_route/Makefile @@ -0,0 +1,9 @@ +all: clean build + +clean: + rm colonel sentinel node + +build: + go build colonel.go + go build sentinel.go + go build node.go diff --git a/draft1_route/colonel.go b/draft1_route/colonel.go new file mode 100644 index 0000000..59a79af --- /dev/null +++ b/draft1_route/colonel.go @@ -0,0 +1,96 @@ +// ============================================================================= +// Auth: Alex Celani +// File: colonel.go +// Revn: 06-20-2022 1.0 +// Func: Send message to another machine and then receive a single +// response. Extremely tight bounds, not robust at all +// +// TODO: comment +// ============================================================================= +// CHANGE LOG +// ----------------------------------------------------------------------------- +// 05-04-2022: init +//*06-20-2022: changed name to reflect first draft of colonel.go +// +// ============================================================================= + +package main + +import ( + "net" // ResolveTCPAddr, DialTCP, conn.Write,Read + "os" // Exit, Stdin, Stderr, Args + "fmt" // Println, Print, Fprintf + "bufio" // NewScanner, NewScanner.Scan,Text + "strings" // ToLower + "time" // Now, Sub +) + + +// quick function to take user input +func input( ps1 string ) string { + fmt.Print( ps1 ) // print prompt + scanner := bufio.NewScanner( os.Stdin ) // link to stdin + scanner.Scan() // pull data + return strings.ToLower( scanner.Text() ) // return lower text +} + + +// quick error checking +func check( err error ) { + // if user checks an error, it better be nil + if err != nil { + // put error in string, print in stderr + fmt.Fprintf( os.Stderr, "Fatal error: %s", err.Error() ) + os.Exit( 2 ) // quit + } +} + + +func main() { + + // if len is not 2 ( ./name host:port ), print usage and quit + if len( os.Args ) != 2 { + fmt.Fprintf( os.Stderr, "Usage: %s host:port", os.Args[0] ) + os.Exit( 1 ) + } + + service := os.Args[1] // capture ip address and host + + // "resolve" ip & host according to TCP rules + tcpAddr, err := net.ResolveTCPAddr( "tcp", service ) + check( err ) // check error + + // "dial" ( establish connection ) to destination ip & port + // according to TCP rules + // laddr = nil -> local address is localhost + conn, err := net.DialTCP( "tcp", nil, tcpAddr ) + check( err ) // check error + + var in string = input( ">> " ) // get user input + + start := time.Now() // start round trip timer + + // convert user input to bytes and send over connection + _, err = conn.Write( []byte( in ) ) + check( err ) // check error + + var buf [512]byte // init byte array + // read from connection into byte array + // amount of bytes read stored in n + //n, err := conn.Read( buf[0:] ) + n, err := conn.Read( buf[:] ) + check( err ) // check error + + t := time.Now() // stop round trip timer + + // convert read bytes into string and print + fmt.Println( string( buf[:n] ) ) + + fmt.Println() // newline to clean up a little + fmt.Println( "rtt: ", t.Sub( start ) ) // print elapsed time + + + os.Exit( 0 ) // exeunt + +} + diff --git a/draft1_route/node.go b/draft1_route/node.go new file mode 100644 index 0000000..a4ed0bf --- /dev/null +++ b/draft1_route/node.go @@ -0,0 +1,130 @@ +// ============================================================================= +// Auth: Alex Celani +// File: node.go +// Revn: 06-22-2022 1.0 +// Func: receive data as an endpoint, send response back to middleman +// +// TODO: +// ============================================================================= +// CHANGE LOG +// ----------------------------------------------------------------------------- +// 05-04-2022: init +// 05-09-2022: began commenting +// 05-10-2022: finished commenting +// added alter() and forward() +// made passed value to alter()/forward() a slice +// changed refs to recv byte array to slice of n bytes +// 06-20-2022: changed name to reflect first draft of node.go +//*06-22-2022: bug squashing and commenting +// +// ============================================================================= + +package main + +import ( + "net" // ResolveTCPAddr, conn.Write,Read,Close + // ListenTCP, listener.Accept + "os" // Args, Stderr, Exit + "fmt" // Fprintf, Println + "strings" // ToLower +) + + +// quick error checking +func check( err error ) { + // if user checks an error, it better be nil + if err != nil { + // put error in string, print in stderr + fmt.Fprintf( os.Stderr, "Fatal error: %s", err.Error() ) + os.Exit( 2 ) // quit + } +} + + +// parse incoming message, keep only second word +func parse( recv string ) string { + // split message over spaces + keywords := strings.Split( recv, " " ) + return keywords[1] // return the second word +} + + +// function to handle incoming connections +func handleClient( conn net.Conn ) { + defer conn.Close() // barring any error, still close connection + + // init map of fields to their values + reply := map[string]string{ "soc" : "30", + "batt" : "30", + "temp" : "65", + "humid" : "35", + "sun" : "10", + "list" : "soc batt temp humid sun list" } + + var buf [512]byte // declare large byte array, store messages + + // iterate forever to always read over connection + for { + // read n bytes from connection into buffer + n, err := conn.Read( buf[0:] ) + if err != nil { // erroring on read will simply leave the + return // function so it can start again later + } + + // print recv'd message + // string() only works on byte SLICES so [:] is required + fmt.Println( "recv: ", string( buf[:n] ) ) + + // send input to parse + recv := parse( string( buf[:n] ) ) + fmt.Println( "parse: ", recv ) // print + + // declare variables to grab values from field map + var resp string + var prs bool + // get values from map, prs is false if key (recv) DNE in map + resp, prs = reply[recv] + if !prs { // if key was not present + resp = "field does not exist" // response is DNE + } + fmt.Println( "answer: ", resp ) // print response + + // write that response back to original client + _, err = conn.Write( []byte( resp ) ) + if err != nil { // erroring on write will simply leave the + return // function so it can start again later + } + + fmt.Println( "sent: ", resp ) // print response + } +} + + +func main() { + + // ip:port + // ip doesn't exist, implies localhost + service := ":1202" // capture ip address and host + + // "resolve" ip & host according to TCP rules + tcpAddr, err := net.ResolveTCPAddr( "tcp", service ) + check( err ) // check error + + // bind and "listen" to ip and port, according to tcp rules + listener, err := net.ListenTCP( "tcp", tcpAddr ) + check( err ) // check error + + // iterate forever + // TODO i mean i can totally make this more user friendly + for { + // accept a connection that makes its way to bound port + conn, err := listener.Accept() + if err != nil { // if connection fails... + continue // don't quit program, not fatal error + } + + // asynchronous function to handle connection to client + go handleClient( conn ) + } +} + diff --git a/draft1_route/sent b/draft1_route/sent new file mode 100755 index 0000000..2dd95a6 Binary files /dev/null and b/draft1_route/sent differ diff --git a/draft1_route/sent.go b/draft1_route/sent.go new file mode 100644 index 0000000..d2b5c3a --- /dev/null +++ b/draft1_route/sent.go @@ -0,0 +1,157 @@ +// ============================================================================= +// Auth: Alex Celani +// File: sent.go +// Revn: 06-22-2022 1.0 +// Func: Receive message, play with it, send to a third place, receive +// response, send off to first place +// +// TODO: comment +// ============================================================================= +// CHANGE LOG +// ----------------------------------------------------------------------------- +// 05-04-2022: init +// 05-05-2022: commented +// 05-10-2022: added argument 'n' to alter() for halving purposes +// changed passed value to alter()/forward() a slice +// 06-20-2022: changed name to reflect first draft of sentinel.go +//*06-22-2022: bug fixing and commenting +// +// ============================================================================= + +package main + +import ( + "net" // ResolveTCPAddr, DialTCP, conn.Write,Read,Close + // ListenTCP, listener.Accept + "os" // Exit, Stderr, Stdin, Args + "fmt" // Println, Fprintf + "strings" // ToLower, ToUpper +) + + +// quick error checking +func check( err error ){ + // if user checks an error, it better be nil + if err != nil { + // put error in string, print to stderr + fmt.Fprintf( os.Stderr, "Fatal error: %s", err.Error() ) + os.Exit( 1 ) // quit + } +} + + +// function to send message to third party and get response +func send( toSend string ) string { + // ip:port + // ip doesn't exist, implies localhost + service := "192.168.1.3:1202" // capture ip address and host + + // "resolve" ip & host according to TCP rules + tcpAddr, err := net.ResolveTCPAddr( "tcp", service ) + check( err ) // check error + + // "dial" ( establish connection ) to destination ip & port + // according to TCP rules + // laddr = nil -> local address is localhost + conn, err := net.DialTCP( "tcp", nil, tcpAddr ) + check( err ) // check error + + defer conn.Close() // barring any error, still close connection + + // convert user input to bytes and send over connection + _, err = conn.Write( []byte( toSend ) ) + check( err ) // check error + + var buf [512]byte // init byte array + // read from connection into byte array + // amount of bytes read stored in n + //n, err := conn.Read( buf[0:] ) + n, err := conn.Read( buf[0:] ) + check( err ) // check error + + return string( buf[:n] ) // return only written bytes +} + + +// remove the first word from the string +// actually mad inefficient tbh, but it works +func parse( recv string ) string { + // split string over spaces + keywords := strings.Split( recv, " " ) + var command string // declare return variable + // iterate over all but the first word + for _, keyword := range keywords[1:] { + command = command + keyword // add word to returnable + command = command + " " // separate by spaces + } + // remove the trailing space + command = command[:len( command ) - 1] + return command // return +} + + +// function to handle incoming connections +func handleClient( conn net.Conn ) { + defer conn.Close() // barring any error, still close connection + + var buf [512]byte // declare large byte array, store messages + + // iterate forever to always read over connection + for { + // read n bytes from connection into buffer + n, err := conn.Read( buf[0:] ) + if err != nil { // erroring on read will simply leave the + return // function so it can start again later + } + + // instantiate receipt variable + var recv string = string( buf[:n] ) + + // print recv'd message + // string() only works on byte SLICES so [:] is required + fmt.Println( "recv: ", recv ) + + // parse the input in some way + recv = parse( recv ) + fmt.Println( "parse: ", recv ) // print parse + + resp := send( recv ) // send message off + fmt.Println( "node: ", resp ) // print response + + // write that response back to original client + _, err = conn.Write( []byte( resp ) ) + if err != nil { // erroring on write will simply leave the + return // function so it can start again later + } + } +} + + +func main() { + + // ip:port + // ip doesn't exist, implies localhost + service := ":1201" // capture ip address and host + + // "resolve" ip & host according to TCP rules + tcpAddr, err := net.ResolveTCPAddr( "tcp", service ) + check( err ) // check error + + // bind and "listen" to ip and port, according to tcp rules + listener, err := net.ListenTCP( "tcp", tcpAddr ) + check( err ) // check error + + // iterate forever + // TODO i mean i can totally make this more user friendly + for { + // accept a connection that makes its way to bound port + conn, err := listener.Accept() + if err != nil { // if connection fails... + continue // don't quit program, not fatal error + } + + // asynchronous function to handle connection to client + go handleClient( conn ) + } +} + diff --git a/draft1_route/sentinel.go b/draft1_route/sentinel.go new file mode 100644 index 0000000..b0f55e3 --- /dev/null +++ b/draft1_route/sentinel.go @@ -0,0 +1,157 @@ +// ============================================================================= +// Auth: Alex Celani +// File: sentinel.go +// Revn: 06-22-2022 1.0 +// Func: Receive message, play with it, send to a third place, receive +// response, send off to first place +// +// TODO: comment +// ============================================================================= +// CHANGE LOG +// ----------------------------------------------------------------------------- +// 05-04-2022: init +// 05-05-2022: commented +// 05-10-2022: added argument 'n' to alter() for halving purposes +// changed passed value to alter()/forward() a slice +// 06-20-2022: changed name to reflect first draft of sentinel.go +//*06-22-2022: bug fixing and commenting +// +// ============================================================================= + +package main + +import ( + "net" // ResolveTCPAddr, DialTCP, conn.Write,Read,Close + // ListenTCP, listener.Accept + "os" // Exit, Stderr, Stdin, Args + "fmt" // Println, Fprintf + "strings" // ToLower, ToUpper +) + + +// quick error checking +func check( err error ){ + // if user checks an error, it better be nil + if err != nil { + // put error in string, print to stderr + fmt.Fprintf( os.Stderr, "Fatal error: %s", err.Error() ) + os.Exit( 1 ) // quit + } +} + + +// function to send message to third party and get response +func send( toSend string ) string { + // ip:port + // ip doesn't exist, implies localhost + service := ":1202" // capture ip address and host + + // "resolve" ip & host according to TCP rules + tcpAddr, err := net.ResolveTCPAddr( "tcp", service ) + check( err ) // check error + + // "dial" ( establish connection ) to destination ip & port + // according to TCP rules + // laddr = nil -> local address is localhost + conn, err := net.DialTCP( "tcp", nil, tcpAddr ) + check( err ) // check error + + defer conn.Close() // barring any error, still close connection + + // convert user input to bytes and send over connection + _, err = conn.Write( []byte( toSend ) ) + check( err ) // check error + + var buf [512]byte // init byte array + // read from connection into byte array + // amount of bytes read stored in n + //n, err := conn.Read( buf[0:] ) + n, err := conn.Read( buf[0:] ) + check( err ) // check error + + return string( buf[:n] ) // return only written bytes +} + + +// remove the first word from the string +// actually mad inefficient tbh, but it works +func parse( recv string ) string { + // split string over spaces + keywords := strings.Split( recv, " " ) + var command string // declare return variable + // iterate over all but the first word + for _, keyword := range keywords[1:] { + command = command + keyword // add word to returnable + command = command + " " // separate by spaces + } + // remove the trailing space + command = command[:len( command ) - 1] + return command // return +} + + +// function to handle incoming connections +func handleClient( conn net.Conn ) { + defer conn.Close() // barring any error, still close connection + + var buf [512]byte // declare large byte array, store messages + + // iterate forever to always read over connection + for { + // read n bytes from connection into buffer + n, err := conn.Read( buf[0:] ) + if err != nil { // erroring on read will simply leave the + return // function so it can start again later + } + + // instantiate receipt variable + var recv string = string( buf[:n] ) + + // print recv'd message + // string() only works on byte SLICES so [:] is required + fmt.Println( "recv: ", recv ) + + // parse the input in some way + recv = parse( recv ) + fmt.Println( "parse: ", recv ) // print parse + + resp := send( recv ) // send message off + fmt.Println( "node: ", resp ) // print response + + // write that response back to original client + _, err = conn.Write( []byte( resp ) ) + if err != nil { // erroring on write will simply leave the + return // function so it can start again later + } + } +} + + +func main() { + + // ip:port + // ip doesn't exist, implies localhost + service := ":1201" // capture ip address and host + + // "resolve" ip & host according to TCP rules + tcpAddr, err := net.ResolveTCPAddr( "tcp", service ) + check( err ) // check error + + // bind and "listen" to ip and port, according to tcp rules + listener, err := net.ListenTCP( "tcp", tcpAddr ) + check( err ) // check error + + // iterate forever + // TODO i mean i can totally make this more user friendly + for { + // accept a connection that makes its way to bound port + conn, err := listener.Accept() + if err != nil { // if connection fails... + continue // don't quit program, not fatal error + } + + // asynchronous function to handle connection to client + go handleClient( conn ) + } +} + diff --git a/draft2_pin/Makefile b/draft2_pin/Makefile new file mode 100644 index 0000000..da2ed77 --- /dev/null +++ b/draft2_pin/Makefile @@ -0,0 +1,9 @@ +all: clean build + +clean: + rm colonel sentinel + +build: + go build colonel.go + go build sentinel.go + diff --git a/draft2_pin/colonel.go b/draft2_pin/colonel.go new file mode 100644 index 0000000..980621d --- /dev/null +++ b/draft2_pin/colonel.go @@ -0,0 +1,78 @@ +// ============================================================================= +// Auth: Alex Celani +// File: colonel.go +// Revn: 06-22-2022 1.0 +// Func: Send message to another machine and then receive a single +// response +// +// TODO: comment +// ============================================================================= +// CHANGE LOG +// ----------------------------------------------------------------------------- +// 05-04-2022: init +// 06-20-2022: changed name to reflect first draft of colonel.go +//*06-22-2022: bug fixing and commenting +// +// ============================================================================= + +package main + +import ( + "net" // ResolveTCPAddr, DialTCP, conn.Write,Read + "os" // Exit, Stdin, Stderr, Args + "fmt" // Println, Print, Fprintf + "bufio" // NewScanner, NewScanner.Scan,Text + "strings" // ToLower +) + + +// quick function to take user input +func input( ps1 string ) string { + fmt.Print( ps1 ) // print prompt + scanner := bufio.NewScanner( os.Stdin ) // link to stdin + scanner.Scan() // pull data + return strings.ToLower( scanner.Text() ) // return lower text +} + + +// quick error checking +func check( err error ) { + // if user checks an error, it better be nil + if err != nil { + // put error in string, print in stderr + fmt.Fprintf( os.Stderr, "Fatal error: %s", err.Error() ) + os.Exit( 2 ) // quit + } +} + + +func main() { + + // if len is not 2 ( ./name host:port ), print usage and quit + if len( os.Args ) != 2 { + fmt.Fprintf( os.Stderr, "Usage: %s host:port", os.Args[0] ) + os.Exit( 1 ) + } + + service := os.Args[1] // capture ip address and host + + // "resolve" ip & host according to TCP rules + tcpAddr, err := net.ResolveTCPAddr( "tcp", service ) + check( err ) // check error + + // "dial" ( establish connection ) to destination ip & port + // according to TCP rules + // laddr = nil -> local address is localhost + conn, err := net.DialTCP( "tcp", nil, tcpAddr ) + check( err ) // check error + + var in string = input( ">> " ) // get user input + + // convert user input to bytes and send over connection + _, err = conn.Write( []byte( in ) ) + check( err ) // check error + + os.Exit( 0 ) // exeunt + +} + diff --git a/draft2_pin/sentinel.go b/draft2_pin/sentinel.go new file mode 100644 index 0000000..c13246f --- /dev/null +++ b/draft2_pin/sentinel.go @@ -0,0 +1,119 @@ +// ============================================================================= +// Auth: Alex Celani +// File: sentinel.go +// Revn: 06-22-2022 1.0 +// Func: Receive message, play with it, send to a third place, receive +// response, send off to first place +// +// TODO: comment +// ============================================================================= +// CHANGE LOG +// ----------------------------------------------------------------------------- +// 05-04-2022: init +// 05-05-2022: commented +// 05-10-2022: added argument 'n' to alter() for halving purposes +// changed passed value to alter()/forward() a slice +// 06-20-2022: changed name to reflect first draft of sentinel.go +//*06-22-2022: bug fixing and comments +// +// ============================================================================= + +package main + +import ( + "net" // ResolveTCPAddr, DialTCP, conn.Write,Read,Close + // ListenTCP, listener.Accept + "os" // Exit, Stderr, Stdin, Args + "fmt" // Println, Fprintf + "github.com/stianeikeland/go-rpio" // talk to RasPi pins +) + + +// quick error checking +func check( err error ){ + // if user checks an error, it better be nil + if err != nil { + // put error in string, print to stderr + fmt.Fprintf( os.Stderr, "Fatal error: %s", err.Error() ) + os.Exit( 1 ) // quit + } +} + + +// function to handle incoming connections +func handleClient( conn net.Conn ) { + defer conn.Close() // barring any error, still close connection + + var buf [512]byte // declare large byte array, store messages + + // iterate forever to always read over connection + for { + // read n bytes from connection into buffer + n, err := conn.Read( buf[0:] ) + if err != nil { // erroring on read will simply leave the + return // function so it can start again later + } + + // instantiate receipt variable + var recv string = string( buf[:n] ) + + // print recv'd message + // string() only works on byte SLICES so [:] is required + fmt.Println( "recv: ", recv ) + + // toggle pin on successful receipt + pin.Toggle() + + } +} + + +// declare pin +var ( + // Use mcu pin 10, corresponds to physical pin 19 on the pi + pin = rpio.Pin(10) +) + + +func main() { + + // Open and map memory to access gpio, check for errors + // inline open gpio pin and check the error var + if err := rpio.Open(); err != nil { + // on error, print error and exit + fmt.Println(err) + os.Exit(1) + } + + // Unmap gpio memory when done + defer rpio.Close() + + // Set pin to output mode + pin.Output() + + // ip:port + // ip doesn't exist, implies localhost + service := ":1201" // capture ip address and host + + // "resolve" ip & host according to TCP rules + tcpAddr, err := net.ResolveTCPAddr( "tcp", service ) + check( err ) // check error + + // bind and "listen" to ip and port, according to tcp rules + listener, err := net.ListenTCP( "tcp", tcpAddr ) + check( err ) // check error + + // iterate forever + // TODO i mean i can totally make this more user friendly + for { + // accept a connection that makes its way to bound port + conn, err := listener.Accept() + if err != nil { // if connection fails... + continue // don't quit program, not fatal error + } + + // asynchronous function to handle connection to client + go handleClient( conn ) + } +} + diff --git a/draft3_pinroute/Makefile b/draft3_pinroute/Makefile new file mode 100644 index 0000000..af75c52 --- /dev/null +++ b/draft3_pinroute/Makefile @@ -0,0 +1,9 @@ +all: clean build + +clean: + rm colonel sentinel led + +build: + go build colonel.go + go build sentinel.go + go build led.go diff --git a/draft3_pinroute/boot.go b/draft3_pinroute/boot.go new file mode 100644 index 0000000..33f3e1d --- /dev/null +++ b/draft3_pinroute/boot.go @@ -0,0 +1,55 @@ +// ============================================================================= +// Auth: Alex Celani +// File: boot.go +// Revn: 06-23-2022 0.1 +// Func: Blink a light when the pi boots (or on login, but who cares) +// +// TODO: create +// ============================================================================= +// CHANGE LOG +// ----------------------------------------------------------------------------- +// 06-23-2022: init +// +// ============================================================================= + +package main + + +import ( + "github.com/stianeikeland/go-rpio" + "os" + "time" +) + + +/* +Toggles a LED on physical pin 19 (mcu pin 10) +Connect a LED with resistor from pin 19 to ground. +*/ + + +// Use mcu pin 10, corresponds to physical pin 19 on the pi +var pin rpio.Pin + + +func main() { + + pin = rpio.Pin( 10 ) + // Open and map memory to access gpio, check for errors + if err := rpio.Open(); err != nil { + os.Exit(1) + } + + // Unmap gpio memory when done + defer rpio.Close() + + // Set pin to output mode + pin.Output() + + // Toggle pin 20 times + for i := 0; i < 4; i++ { + pin.Toggle() + time.Sleep(time.Second / 10) + } +} + diff --git a/draft3_pinroute/colonel.go b/draft3_pinroute/colonel.go new file mode 100644 index 0000000..f36a429 --- /dev/null +++ b/draft3_pinroute/colonel.go @@ -0,0 +1,100 @@ +// ============================================================================= +// Auth: Alex Celani +// File: colonel.go +// Revn: 06-23-2022 1.1 +// Func: Send message to another machine and then receive a single +// response. Extremely tight bounds, not robust at all +// +// TODO: comment +// ============================================================================= +// CHANGE LOG +// ----------------------------------------------------------------------------- +// 05-04-2022: init +//*06-20-2022: changed name to reflect first draft of colonel.go +// 06-23-2022: made input an infinite loop +// +// ============================================================================= + +package main + +import ( + "net" // ResolveTCPAddr, DialTCP, conn.Write,Read + "os" // Exit, Stdin, Stderr, Args + "fmt" // Println, Print, Fprintf + "bufio" // NewScanner, NewScanner.Scan,Text + "strings" // ToLower + "time" // Now, Sub +) + + +// quick function to take user input +func input( ps1 string ) string { + fmt.Print( ps1 ) // print prompt + scanner := bufio.NewScanner( os.Stdin ) // link to stdin + scanner.Scan() // pull data + return strings.ToLower( scanner.Text() ) // return lower text +} + + +// quick error checking +func check( err error ) { + // if user checks an error, it better be nil + if err != nil { + // put error in string, print in stderr + fmt.Fprintf( os.Stderr, "Fatal error: %s", err.Error() ) + os.Exit( 2 ) // quit + } +} + + +func main() { + + // if len is not 2 ( ./name host:port ), print usage and quit + if len( os.Args ) != 2 { + fmt.Fprintf( os.Stderr, "Usage: %s host:port", os.Args[0] ) + os.Exit( 1 ) + } + + service := os.Args[1] // capture ip address and host + + // "resolve" ip & host according to TCP rules + tcpAddr, err := net.ResolveTCPAddr( "tcp", service ) + check( err ) // check error + + // "dial" ( establish connection ) to destination ip & port + // according to TCP rules + // laddr = nil -> local address is localhost + conn, err := net.DialTCP( "tcp", nil, tcpAddr ) + check( err ) // check error + + for { // loop forever + + var in string = input( ">> " ) // get user input + + start := time.Now() // start round trip timer + + // convert user input to bytes and send over connection + _, err = conn.Write( []byte( in ) ) + check( err ) // check error + + var buf [512]byte // init byte array + // read from connection into byte array + // amount of bytes read stored in n + //n, err := conn.Read( buf[0:] ) + n, err := conn.Read( buf[:] ) + check( err ) // check error + + t := time.Now() // stop round trip timer + + // convert read bytes into string and print + fmt.Println( "<<", string( buf[:n] ) ) + + fmt.Println() // newline to clean up a little + fmt.Println( "rtt: ", t.Sub( start ) ) // print time + + } + + os.Exit( 0 ) // exeunt + +} + diff --git a/draft3_pinroute/config b/draft3_pinroute/config new file mode 100644 index 0000000..e5629ce --- /dev/null +++ b/draft3_pinroute/config @@ -0,0 +1,5 @@ +color;blue green red purple teal yellow white +status;on off +&& +color;blue +status;off diff --git a/draft3_pinroute/draft3_pinroute.txt b/draft3_pinroute/draft3_pinroute.txt new file mode 100644 index 0000000..189af5d --- /dev/null +++ b/draft3_pinroute/draft3_pinroute.txt @@ -0,0 +1,33 @@ +# ============================================================================== +# Auth: Alex Celani +# File: XXX.xx +# Revn: MM-DD-YYYY 0.0 +# Func: +# +# TODO: create +# ============================================================================== +# CHANGE LOG +# ------------------------------------------------------------------------------ +# MM-DD-YYYY: init +# +# ============================================================================== + + +literally +combine draft1 with draft2 + +sentinel:: your whole job, tbh, is to forward to the correct node + and there's really only one node + change stuff like "plant humid" into "plant.humid" or + "lamp color" into "lamp.color" + +node:: move real parsing here + control RBG common anode led + node name -> led + fields ->^v led.color + ^ on + ^ off + v status + ^v bright + v list + diff --git a/draft3_pinroute/led.go b/draft3_pinroute/led.go new file mode 100644 index 0000000..c6c9c36 --- /dev/null +++ b/draft3_pinroute/led.go @@ -0,0 +1,217 @@ +// ============================================================================= +// Auth: Alex Celani +// File: led.go +// Revn: 06-26-2022 1.2 +// Func: receive data as an endpoint, send response back to middleman +// +// TODO: +// ============================================================================= +// CHANGE LOG +// ----------------------------------------------------------------------------- +// 05-04-2022: init +// 05-09-2022: began commenting +// 05-10-2022: finished commenting +// added alter() and forward() +// made passed value to alter()/forward() a slice +// changed refs to recv byte array to slice of n bytes +// 06-20-2022: changed name to reflect first draft of node.go +//*06-22-2022: bug squashing and commenting +// 06-23-2022: updated to produce three different colors +// 06-26-2022: commented +// +// ============================================================================= + +package main + +import ( + "net" // ResolveTCPAddr, conn.Write,Read,Close + // ListenTCP, listener.Accept + "os" // Args, Stderr, Exit + "fmt" // Fprintf, Println + "strings" // ToLower + "github.com/stianeikeland/go-rpio" // talk to RasPi pins +) + + +// quick error checking +func check( err error ) { + // if user checks an error, it better be nil + if err != nil { + // put error in string, print in stderr + fmt.Fprintf( os.Stderr, "Fatal error: %s", err.Error() ) + os.Exit( 2 ) // quit + } +} + + +// parse incoming message, keep only second word +func parse( recv string ) string { + // split message over spaces + keywords := strings.Split( recv, " " ) + return keywords[1] // return the second word +} + + +// function to handle incoming connections +func handleClient( conn net.Conn ) { + defer conn.Close() // barring any error, still close connection + + var buf [512]byte // declare large byte array, store messages + + // iterate forever to always read over connection + for { + // read n bytes from connection into buffer + n, err := conn.Read( buf[0:] ) + if err != nil { // erroring on read will simply leave the + return // function so it can start again later + } + + // print recv'd message + // string() only works on byte SLICES so [:] is required + fmt.Println( "recv: ", string( buf[:n] ) ) + + // split command into words for ease of parsing + command := strings.Split( string( buf[:n] ), " " ) + + if command[1] != "led" { // confirm message belongs here + os.Exit( 2 ) // if not, exit + } + + var resp string // declare response variable + + + // TODO convert to switches? + // len is 3 for "asK" commands + if len( command ) == 3 { + if command[2] == "color" { + // if user wants color, return color + resp = color + } else if command[2] == "status" { + // if user wants status, return status + resp = status + } else { + // there are only those two fields + resp = "usage unknown" + } + // len is 4 for tell commands + } else if len( command ) == 4 { + // if user wants to set color + if command[2] == "color" { + color = command[3] // set current color + resp = color // return current color + switch color { + case "blue": // does user want blue? + // turn blue on, turn rest off + pinB.High() + pinR.Low() + pinG.Low() + case "red": // does user want red? + // turn red on, turn rest off + pinB.Low() + pinR.High() + pinG.Low() + case "green": // does user want green? + // turn green on, turn rest off + pinB.Low() + pinR.Low() + pinG.High() + default: // color unknown + // turn off + pinB.Low() + pinR.Low() + pinG.Low() + } + // if user wants to set status + } else if command[2] == "status" { + status = command[3] // set current status + resp = status // return current status + switch status { + case "on": // does user want on? + // default to red + pinB.Low() + pinR.High() + pinG.Low() + default: // anything else, like off + // default to off + pinB.Low() + pinR.Low() + pinG.Low() + } + // user entered something else entirely + } else { + resp = "usage unknown" + } + // no other lengths are valid + } else { + os.Exit( 2 ) // exit in this case + } + + fmt.Println( "answer: ", resp ) // print response + + // write that response back to original client + _, err = conn.Write( []byte( resp ) ) + if err != nil { // erroring on write will simply leave the + return // function so it can start again later + } + + fmt.Println( "sent: ", resp ) // print response + } +} + + +//var params = make( map[string]string ) +//var states = make( map[string]string ) +var pinR rpio.Pin // declare red led pin +var pinG rpio.Pin // declare green led pin +var pinB rpio.Pin // declare blue led pin +var color string // declare color variable +var status string // declare status variable + + +func main() { + + // initialize pins to GPIO 11, 9, and 25 + pinR = rpio.Pin( 11 ) + pinG = rpio.Pin( 9 ) + pinB = rpio.Pin( 25 ) + + if err := rpio.Open(); err != nil { + // on error, print error and exit + fmt.Println(err) + os.Exit(1) + } + + // Unmap gpio memory when done + defer rpio.Close() + + // Set pins to output mode + pinR.Output() + pinG.Output() + pinB.Output() + + // ip:port + // ip doesn't exist, implies localhost + service := ":1202" // capture ip address and host + + // "resolve" ip & host according to TCP rules + tcpAddr, err := net.ResolveTCPAddr( "tcp", service ) + check( err ) // check error + + // bind and "listen" to ip and port, according to tcp rules + listener, err := net.ListenTCP( "tcp", tcpAddr ) + check( err ) // check error + + // iterate forever + // TODO i mean i can totally make this more user friendly + for { + // accept a connection that makes its way to bound port + conn, err := listener.Accept() + if err != nil { // if connection fails... + continue // don't quit program, not fatal error + } + + // asynchronous function to handle connection to client + go handleClient( conn ) + } +} + diff --git a/draft3_pinroute/sentinel.go b/draft3_pinroute/sentinel.go new file mode 100644 index 0000000..bcbe932 --- /dev/null +++ b/draft3_pinroute/sentinel.go @@ -0,0 +1,156 @@ +// ============================================================================= +// Auth: Alex Celani +// File: sentinel.go +// Revn: 06-26-2022 1.2 +// Func: Receive message, determine recipient, forward, get response, +// forward back +// +// TODO: +// ============================================================================= +// CHANGE LOG +// ----------------------------------------------------------------------------- +// 05-04-2022: init +// 05-05-2022: commented +// 05-10-2022: added argument 'n' to alter() for halving purposes +// changed passed value to alter()/forward() a slice +// 06-20-2022: changed name to reflect first draft of sentinel.go +//*06-22-2022: bug fixing and commenting +// 06-23-2022: removed call to parse +// 06-26-2022: refined a new route() function to check for destination +// validity +// +// ============================================================================= + +package main + +import ( + "net" // ResolveTCPAddr, DialTCP, conn.Write,Read,Close + // ListenTCP, listener.Accept + "os" // Exit, Stderr, Stdin, Args + "fmt" // Println, Fprintf + "strings" // ToLower, ToUpper +) + + +// quick error checking +func check( err error ){ + // if user checks an error, it better be nil + if err != nil { + // put error in string, print to stderr + fmt.Fprintf( os.Stderr, "Fatal error: %s", err.Error() ) + os.Exit( 1 ) // quit + } +} + + +// read the given message and route to the right endpoint +func route( recv []string ) bool { + return recv[1] == "led" // only option right now is led +} + + +// function to send message to third party and get response +func send( toSend string ) string { + // ip:port + // ip doesn't exist, implies localhost + service := ":1202" // capture ip address and host + + // "resolve" ip & host according to TCP rules + tcpAddr, err := net.ResolveTCPAddr( "tcp", service ) + check( err ) // check error + + // "dial" ( establish connection ) to destination ip & port + // according to TCP rules + // laddr = nil -> local address is localhost + conn, err := net.DialTCP( "tcp", nil, tcpAddr ) + check( err ) // check error + + defer conn.Close() // barring any error, still close connection + + // convert user input to bytes and send over connection + _, err = conn.Write( []byte( toSend ) ) + check( err ) // check error + + var buf [512]byte // init byte array + // read from connection into byte array + // amount of bytes read stored in n + //n, err := conn.Read( buf[0:] ) + n, err := conn.Read( buf[0:] ) + check( err ) // check error + + return string( buf[:n] ) // return only written bytes +} + + +// function to handle incoming connections +func handleClient( conn net.Conn ) { + defer conn.Close() // barring any error, still close connection + + var buf [512]byte // declare large byte array, store messages + + // iterate forever to always read over connection + for { + // read n bytes from connection into buffer + n, err := conn.Read( buf[0:] ) + if err != nil { // erroring on read will simply leave the + return // function so it can start again later + } + + // instantiate receipt variable + var recv string = string( buf[:n] ) + + // print recv'd message + // string() only works on byte SLICES so [:] is required + fmt.Println( "recv: ", recv ) + + keywords := strings.Split( recv, " " ) + + // parse the input in some way + var resp string // declare response variable + if route( keywords ) { // is destination valid? + resp = send( recv ) // send message and get response + // if user wants a list of endpoints + } else if keywords[1] == "list" { + resp = "led" // return list of endpoints + } + + + fmt.Println( "node: ", resp ) // print response + + // write that response back to original client + _, err = conn.Write( []byte( resp ) ) + if err != nil { // erroring on write will simply leave the + return // function so it can start again later + } + } +} + + +func main() { + + // ip:port + // ip doesn't exist, implies localhost + service := ":1201" // capture ip address and host + + // "resolve" ip & host according to TCP rules + tcpAddr, err := net.ResolveTCPAddr( "tcp", service ) + check( err ) // check error + + // bind and "listen" to ip and port, according to tcp rules + listener, err := net.ListenTCP( "tcp", tcpAddr ) + check( err ) // check error + + // iterate forever + // TODO i mean i can totally make this more user friendly + for { + // accept a connection that makes its way to bound port + conn, err := listener.Accept() + if err != nil { // if connection fails... + continue // don't quit program, not fatal error + } + + // asynchronous function to handle connection to client + go handleClient( conn ) + } +} + diff --git a/sentinel.txt b/sentinel.txt new file mode 100644 index 0000000..3f371da --- /dev/null +++ b/sentinel.txt @@ -0,0 +1,136 @@ +# ==================================================================== +# Auth: dodd +# File: sentinel.txt +# Revn: 05-10-2022 0.2 +# Func: jot down some ideas about what the hub is and how it works +# +# TODO: +# ==================================================================== +# CHANGE LOG +# -------------------------------------------------------------------- +# 04-27-2022: init +# 05-10-2022: changed name from hub to sentinel +# +# ==================================================================== + + +elevator pitch:: execute a command in terminal + terminal sends request to external hub device + hub pings one or more homemade smarthome devices + smarthome devices repond to hub + hub sends information back to terminal + terminal displays requested data + +idea:: filter network model +" + /----\ /----\ + / v / v + |A| |B| |C| ( but with more C nodes ) + ^ / ^ / + \----/ \----/ +" + + terminal program is node A + hub is node B + other devices are nodes C + cat feeder + ball lamp + door monitor + etc + +design:: + how -> networking language + _python_ --> easy to write, will work + moves challenge to the project + _c/c++_ --> segmentation fault (core dumped). pass + _golang_ --> will need to learn networks pretty well + I'm already getting pretty good experience + with golang tho + _rust_ --> can't even get the fucking syntax to highlight + + everything important is going to need to be hardcoded? ports, + ip addresses + + probably would want to be connection-oriented protocol + TCP/IP + + +usage:: terminal commands + ask:: -> ask deviceC property + ==> send message to deviceC asking for status report + on property + ==> fail gracefully if property doesnt exist for given + device + --> ask cat-feeder fill example command + --> cat-feeder.fill 50% example response + + --> ask ball-lamp soc example command + --> ball-lamp.soc 20% example response + + tell:: -> tell deviceC command argument + ==> send message to deviceC instructing it to commit + an action + ==> fail gracefully if command doesn't exist for + device or if argument is invalid + + --> tell door arm on example command + --> door.arm on example response + + --> tell ball-lamp color blue example command + --> ball-lamp.color blue example response + + list:: -> list [deviceC] -v + ==> return a list of devices (deviceC not specified) + ==> ping deviceC to see what properties it has and + their direction + ==> including verbose -v flag shows devices and their + properties + ==> including -v and a device is treated like only + specifying the device + + --> list example command + --> door example response + ball-lamp + cat-feeder + office-light + + --> list ball-lamp example command + --> ball-lamp example response + \--^ on + \--^ off + \--^ color + \-- white + \-- red + \-- green + \-- blue + \-- rainbow + \--^ bright[ness] + \-- [1 - 100] + \--v soc + \--v batt[ery] + + --> list -v example command + --> door example response + \--^ arm + \--v status + \--v soc + \--v batt[ery] + ball-lamp + \--^ on + \--^ off + \--^ color + \-- white + \-- red + \-- green + \-- blue + \-- rainbow + \--^ bright[ness] + \-- [1 - 100] + \--v soc + \--v batt[ery] + (etc) + + stats:: -> stats + ==> request statistics from all online devices + ===> uptime, battery, current status on all + properties, en masse diff --git a/three/Makefile b/three/Makefile new file mode 100644 index 0000000..49384a1 --- /dev/null +++ b/three/Makefile @@ -0,0 +1,9 @@ +all: clean build + +clean: + rm messagerA messagerB messagerC + +build: + go build messagerA.go + go build messagerB.go + go build messagerC.go diff --git a/three/messagerA b/three/messagerA new file mode 100755 index 0000000..157e317 Binary files /dev/null and b/three/messagerA differ diff --git a/three/messagerA.go b/three/messagerA.go new file mode 100644 index 0000000..270f74b --- /dev/null +++ b/three/messagerA.go @@ -0,0 +1,95 @@ +// ============================================================================= +// Auth: Alex Celani +// File: messagerA.go +// Revn: 05-04-2022 0.1 +// Func: Send message to another machine and then receive a single +// response +// +// TODO: comment +// ============================================================================= +// CHANGE LOG +// ----------------------------------------------------------------------------- +// 05-04-2022: init +// +// ============================================================================= + +package main + +import ( + "net" // ResolveTCPAddr, DialTCP, conn.Write,Read + "os" // Exit, Stdin, Stderr, Args + "fmt" // Println, Print, Fprintf + "bufio" // NewScanner, NewScanner.Scan,Text + "strings" // ToLower + "time" // Now, Sub +) + + +// quick function to take user input +func input( ps1 string ) string { + fmt.Print( ps1 ) // print prompt + scanner := bufio.NewScanner( os.Stdin ) // link to stdin + scanner.Scan() // pull data + return strings.ToLower( scanner.Text() ) // return lower text +} + + +// quick error checking +func check( err error ) { + // if user checks an error, it better be nil + if err != nil { + // put error in string, print in stderr + fmt.Fprintf( os.Stderr, "Fatal error: %s", err.Error() ) + os.Exit( 2 ) // quit + } +} + + +func main() { + + // if len is not 2 ( ./name host:port ), print usage and quit + if len( os.Args ) != 2 { + fmt.Fprintf( os.Stderr, "Usage: %s host:port", os.Args[0] ) + os.Exit( 1 ) + } + + service := os.Args[1] // capture ip address and host + + // "resolve" ip & host according to TCP rules + tcpAddr, err := net.ResolveTCPAddr( "tcp", service ) + check( err ) // check error + + // "dial" ( establish connection ) to destination ip & port + // according to TCP rules + // laddr = nil -> local address is localhost + conn, err := net.DialTCP( "tcp", nil, tcpAddr ) + check( err ) // check error + + var in string = input( ">> " ) // get user input + + start := time.Now() // start round trip timer + + // convert user input to bytes and send over connection + _, err = conn.Write( []byte( in ) ) + check( err ) // check error + + var buf [512]byte // init byte array + // read from connection into byte array + // amount of bytes read stored in n + //n, err := conn.Read( buf[0:] ) + n, err := conn.Read( buf[:] ) + check( err ) // check error + + t := time.Now() // stop round trip timer + + // convert read bytes into string and print + fmt.Println( string( buf[:n] ) ) + + fmt.Println() // newline to clean up a little + fmt.Println( "rtt: ", t.Sub( start ) ) // print elapsed time + + + os.Exit( 0 ) // exeunt + +} + diff --git a/three/messagerB b/three/messagerB new file mode 100755 index 0000000..edca1e0 Binary files /dev/null and b/three/messagerB differ diff --git a/three/messagerB.go b/three/messagerB.go new file mode 100644 index 0000000..3e02a2f --- /dev/null +++ b/three/messagerB.go @@ -0,0 +1,151 @@ +// ============================================================================= +// Auth: Alex Celani +// File: messagerB.go +// Revn: 05-10-2022 0.3 +// Func: Receive message, play with it, send to a third place, receive +// response, send off to first place +// +// TODO: comment +// ============================================================================= +// CHANGE LOG +// ----------------------------------------------------------------------------- +// 05-04-2022: init +// 05-05-2022: commented +// 05-10-2022: added argument 'n' to alter() for halving purposes +// changed passed value to alter()/forward() a slice +// +// ============================================================================= + +package main + +import ( + "net" // ResolveTCPAddr, DialTCP, conn.Write,Read,Close + // ListenTCP, listener.Accept + "os" // Exit, Stderr, Stdin, Args + "fmt" // Println, Fprintf + "strings" // ToLower, ToUpper +) + + +// quick error checking +func check( err error ){ + // if user checks an error, it better be nil + if err != nil { + // put error in string, print to stderr + fmt.Fprintf( os.Stderr, "Fatal error: %s", err.Error() ) + os.Exit( 1 ) // quit + } +} + + +// function to send message to third party and get response +func quickSend( send string ) string { + // ip:port + // ip doesn't exist, implies localhost + service := ":1202" // capture ip address and host + + // "resolve" ip & host according to TCP rules + tcpAddr, err := net.ResolveTCPAddr( "tcp", service ) + check( err ) // check error + + // "dial" ( establish connection ) to destination ip & port + // according to TCP rules + // laddr = nil -> local address is localhost + conn, err := net.DialTCP( "tcp", nil, tcpAddr ) + check( err ) // check error + + defer conn.Close() // barring any error, still close connection + + // convert user input to bytes and send over connection + _, err = conn.Write( []byte( send ) ) + check( err ) // check error + + var buf [512]byte // init byte array + // read from connection into byte array + // amount of bytes read stored in n + //n, err := conn.Read( buf[0:] ) + n, err := conn.Read( buf[0:] ) + check( err ) // check error + + return string( buf[:n] ) // return only written bytes +} + + +// function to change received message before passing it along +func alter( recv []byte, n int ) string { + var send string = string( recv[:n/2] ) + send = strings.ToUpper( send ) + fmt.Println( "to c: ", send ) + return send +} + + +// function to convert message to string before forwarding +func forward( recv []byte ) string { + return string( recv[:] ) +} + + +// function to handle incoming connections +func handleClient( conn net.Conn ) { + defer conn.Close() // barring any error, still close connection + + var buf [512]byte // declare large byte array, store messages + + // iterate forever to always read over connection + for { + // read n bytes from connection into buffer + n, err := conn.Read( buf[0:] ) + if err != nil { // erroring on read will simply leave the + return // function so it can start again later + } + + // print recv'd message + // string() only works on byte SLICES so [:] is required + fmt.Println( "recv: ", string( buf[:] ) ) + +// var send string = string( buf[:n/2] ) +// send = strings.ToUpper( send ) + + send := alter( buf[:], n ) // send message to get changed +// send := forward( buf[:] ) + recv := quickSend( send ) // send message off + fmt.Println( "из c: ", recv ) // print response + + // write that response back to original client + _, err = conn.Write( []byte( recv ) ) + if err != nil { // erroring on write will simply leave the + return // function so it can start again later + } + } +} + + +func main() { + + // ip:port + // ip doesn't exist, implies localhost + service := ":1201" // capture ip address and host + + // "resolve" ip & host according to TCP rules + tcpAddr, err := net.ResolveTCPAddr( "tcp", service ) + check( err ) // check error + + // bind and "listen" to ip and port, according to tcp rules + listener, err := net.ListenTCP( "tcp", tcpAddr ) + check( err ) // check error + + // iterate forever + // TODO i mean i can totally make this more user friendly + for { + // accept a connection that makes its way to bound port + conn, err := listener.Accept() + if err != nil { // if connection fails... + continue // don't quit program, not fatal error + } + + // asynchronous function to handle connection to client + go handleClient( conn ) + } +} + diff --git a/three/messagerC b/three/messagerC new file mode 100755 index 0000000..92e9c46 Binary files /dev/null and b/three/messagerC differ diff --git a/three/messagerC.go b/three/messagerC.go new file mode 100644 index 0000000..383b0e1 --- /dev/null +++ b/three/messagerC.go @@ -0,0 +1,118 @@ +// ============================================================================= +// Auth: Alex Celani +// File: messagerC.go +// Revn: 05-10-2022 0.3 +// Func: +// +// TODO: create +// ============================================================================= +// CHANGE LOG +// ----------------------------------------------------------------------------- +// 05-04-2022: init +// 05-09-2022: began commenting +// 05-10-2022: finished commenting +// added alter() and forward() +// made passed value to alter()/forward() a slice +// changed refs to recv byte array to slice of n bytes +// +// ============================================================================= + +package main + +import ( + "net" // ResolveTCPAddr, conn.Write,Read,Close + // ListenTCP, listener.Accept + "os" // Args, Stderr, Exit + "fmt" // Fprintf, Println + "strings" // ToLower +) + + +// quick error checking +func check( err error ) { + // if user checks an error, it better be nil + if err != nil { + // put error in string, print in stderr + fmt.Fprintf( os.Stderr, "Fatal error: %s", err.Error() ) + os.Exit( 2 ) // quit + } +} + + +// function to change received message before passing it along +func alter( recv []byte ) string { + var send string = string( recv[:] ) + send = send + " " + send + send = strings.ToLower( send ) + return send +} + + +// function to convert message to string before forwarding +func forward( recv []byte ) string { + return string( recv[:] ) +} + + +// function to handle incoming connections +func handleClient( conn net.Conn ) { + defer conn.Close() // barring any error, still close connection + + var buf [512]byte // declare large byte array, store messages + + // iterate forever to always read over connection + for { + // read n bytes from connection into buffer + n, err := conn.Read( buf[0:] ) + if err != nil { // erroring on read will simply leave the + return // function so it can start again later + } + + // print recv'd message + // string() only works on byte SLICES so [:] is required + fmt.Println( "recv: ", string( buf[:n] ) ) + + send := alter( buf[:n] ) // send message ot get changed +// send := forward( buf[:] ) + + // write that response back to original client + _, err = conn.Write( []byte( send ) ) + if err != nil { // erroring on write will simply leave the + return // function so it can start again later + } + + fmt.Println( "sent: ", send ) // print response + } +} + + +func main() { + + // ip:port + // ip doesn't exist, implies localhost + service := ":1202" // capture ip address and host + + // "resolve" ip & host according to TCP rules + tcpAddr, err := net.ResolveTCPAddr( "tcp", service ) + check( err ) // check error + + // bind and "listen" to ip and port, according to tcp rules + listener, err := net.ListenTCP( "tcp", tcpAddr ) + check( err ) // check error + + // iterate forever + // TODO i mean i can totally make this more user friendly + for { + // accept a connection that makes its way to bound port + conn, err := listener.Accept() + if err != nil { // if connection fails... + continue // don't quit program, not fatal error + } + + // asynchronous function to handle connection to client + go handleClient( conn ) + } +} + + +