diff --git a/dev/seq/pieces/client b/dev/seq/pieces/client new file mode 100755 index 0000000..c53e43f Binary files /dev/null and b/dev/seq/pieces/client differ diff --git a/dev/seq/pieces/client.go b/dev/seq/pieces/client.go new file mode 100644 index 0000000..29b45be --- /dev/null +++ b/dev/seq/pieces/client.go @@ -0,0 +1,190 @@ +// ============================================================================= +// Auth: alex +// File: client.go +// Revn: 05-19-2024 0.2 +// Func: ask server for a message of the day quote +// +// TODO: gut +// write +// ============================================================================= +// CHANGE LOG +// ----------------------------------------------------------------------------- +// 05-18-2024: gutted +// 05-19-2024: fixed +// commented +// +// ============================================================================= + +package main + +import ( + //"io" // io.EOF + "flag" // BoolVar, StringVar, Parse + "fmt" // Println + "net" // ResolveTCPAddr, DialTCP, conn.Write,Read + "os" // Exit + //"strconv" // Atoi, Itoa + //"strings" // Split +) + + +/* +// print errors if they occur, quit +func check( err error ) { + + var errep string // declare error report string + switch err { // switch case over error input + case nil: // if there was no error + // then there was no error + errep = "err is nil" + case io.EOF: // if there was an End Of File error + errep = "Error: " + err.Error() // document error + conn.Close() // close connection + default: // anything besides those are a big deal + errep = "Fatal: " + err.Error() + } + + var critical bool // declare critical error flag + // must be neither nil nor EOF + critical = err != nil && err != io.EOF + if critical { // XXX critical print + // TODO at some point, critical should be logging instead of + // printing, only verbose should print + fmt.Println( "check() -> ", errep ) + } + + if critical { // if there was a critical error + os.Exit( 1 ) // cut and run + } +} + + +// get server response and print +func handle( conn net.Conn ) { + + var buffer [tsize]byte // create buffer to hold response + // read n bytes from server into buffer ( byte slice ) + n, err := conn.Read( buffer[:] ) + check( err ) // check for errors + + // split recv'd message over @, separate header from message + msg := strings.Split( string( buffer[:n] ), "@" ) + + var resp string // declare response variable + switch msg[0] { // switch/case over the header + case "la": // /la/, list answer + if len( msg ) > 2 { + resp = "lr@" + + } else { + // split recv'd message over newline to create quote list + quotes := strings.Split( msg[1], "\n" ) + for p, v := range quotes { // iterate over quotes + // print num of quote, followed by that quote + fmt.Println( p + 1, "\t", v ) + } + resp = "te@success" + } + default: // something undefined entirely + // TODO write out to file + //fmt.Println( "Message header not recognized" ) + //fmt.Println( msg ) + conn.Close() // TODO how important is this line + return // dead return, essentially lets program quit + } + + // send formulated response back to server + _, err = conn.Write( []byte( resp ) ) + check( err ) // make sure write worked + + handle( conn ) // call handle again +} +*/ + + +// quick check for errors +func check( err error ) { + if err != nil { // err should be nil, !nil is bad + // print error and ditch + fmt.Println( "fatal::", err ) + os.Exit( 1 ) + } +} + + +// level 4 handle +func handle( conn net.Conn ) { + // create byte array of pre-ordained size + buf := make( []byte, tsize ) + + // read from connection into byte array + _, err := conn.Read( buf ) + check( err ) // routine check for errors + + msg := string( buf ) // convert to string + +/* + // iterate over message string + for p, c := range msg { + // cast char ( rune ) to string and see if it's the end char + if string( c ) == "|" { + // if end char, print everything BUT char and exit + fmt.Println( msg[:p] ) + return + } + } +*/ + + // iterate over message string + for _, c := range msg { + // cast char ( rune ) to string and see if it's the end char + if string( c ) == "X" { + // if end char, print everything BUT char and exit + fmt.Println( msg ) + return + } + } + + fmt.Println( msg ) // if char is not found, print entire + handle( conn ) // message and recursively call level4 +} + + + +// globals +var tsize int +var dest string // provide a new destination ip and port + + +func main() { + + // define flags + flag.IntVar( &tsize, "s", 10, "tx size" ) + flag.StringVar( &dest, "ip", ":1300", "ip:port of server" ) + flag.Parse() // process flags + + service := dest // declare server ip:port + + // create address object + addr, err := net.ResolveTCPAddr( "tcp", service ) + check( err ) // check for errors + + // make connection with object + conn, err := net.DialTCP( "tcp", nil, addr ) + check( err ) // check for errors + + //command := "lr@pls" + + // write command to server, beginning transaction + //_, err = conn.Write( []byte( command ) ) + //check( err ) // make sure write worked + + handle( conn ) // handle response + // TODO stack trace when handle returns, should probably be + // updated + conn.Close() // close connection when finished + + os.Exit( 0 ) // exit + +} + diff --git a/dev/seq/pieces/test b/dev/seq/pieces/test index fa423f5..d933964 100755 Binary files a/dev/seq/pieces/test and b/dev/seq/pieces/test differ diff --git a/dev/seq/pieces/test.go b/dev/seq/pieces/test.go index 6d9dcaf..3b15a4d 100644 --- a/dev/seq/pieces/test.go +++ b/dev/seq/pieces/test.go @@ -1,11 +1,10 @@ // ============================================================================= // Auth: Alex Celani // File: test.go -// Revn: 05-13-2024 0.2 +// Revn: 05-19-2024 0.4 // Func: explore bounding on piecewise file transmission ( PWFT ) // -// TODO: rewrite makedata() to write to a file -// write level4() +// TODO: implement // ============================================================================= // CHANGE LOG // ----------------------------------------------------------------------------- @@ -15,22 +14,59 @@ // level 2 PWFT // 05-13-2024: comment level 1 and level 2 PWFT // level 3 PWFT +// 05-18-2024: began level 4 changes +// 05-19-2024: got level 4 working +// commented +// wrote level 5 +// commented +// wrote level 6! +// commented // // ============================================================================= package main import ( + "flag" "fmt" "math/rand" + "net" // ResovleTCPAddr, ListenTCP, listener.Accept + // conn.Read,Write + "os" // Exit "strconv" ) + +/* func makedata() { for c := 0; c < dsize; c++ { datum[c] = rand.Intn( dsize ) } } +*/ + +// special make function for strings +func makedatatx() { + // classic iteration of length dsize, toss in same-sized array + for c := 0; c < dsize; c++ { + // toss in same size array + // rand int picks letter, 0x61 -> lowercase ascii, cast byte + datumtx[c] = byte( rand.Intn( 26 ) + 0x61 ) + } + // cast to string and print ( as slice ) + fmt.Println( string( datumtx[:] ) ) +} + + +// handle errors catastrophically +func check( err error ) { + if err != nil { // error is not nil on error + // print error + fmt.Println( "Fatal: ", err.Error() ) + os.Exit( 1 ) // bail + } +} + // Levels of PWFT // 0. print everything indescriminately @@ -41,6 +77,7 @@ func makedata() { // 5. file tx piecewise with header // 6. file tx piecewise with variable header + // level 0 PWFT func level0( data []int) { fmt.Println( data ) // level 0 sux @@ -108,19 +145,124 @@ func level3() { } +// level 4 PWFT +func level4( conn net.Conn ) { + txn := dsize / tsize // amount of transmissions + + // iterate for number of transmissions + for c := 0; c < txn; c++ { + // write that amount of times, very specific slice + _, err := conn.Write( datumtx[c*tsize:(c+1)*tsize] ) + check( err ) // routine error check + } + + // write final of last chunk of data + _, err := conn.Write( datumtx[txn * tsize:] ) + check( err ) // routine error check + _, err = conn.Write( []byte( "|" ) ) // write end char + check( err ) // routine error check +} + + +// level 5 PWFT +func level5( conn net.Conn ) { + header := "la@x@" // static header + psize := tsize - len( header ) // calculate payload size + + txn := dsize / psize // amount of transmissions + + // iterate for number of transmissions + for c := 0; c < txn; c++ { + // concat header with payload, easier as string, cast to byte + packet := header + string( datumtx[c*psize:(c+1)*psize] ) + // write that amount of times, very specific slice + _, err := conn.Write( []byte( packet ) ) + check( err ) // routine error check + } + + // concat last payload + packet := header + string( datumtx[txn*psize:] ) + // write final of last chunk of data + _, err := conn.Write( []byte( packet ) ) + check( err ) // routine error check + _, err = conn.Write( []byte( "|" ) ) // write end char + check( err ) // routine error check +} + + +// level 6 PWFT +func level6( conn net.Conn ) { + var header string // declare header + var hhead, htail string = "la@", "@" // static pieces of header + txn := 1 // init transmission number + pos := 0 // init position tracker + + for { // easier to do an infinite loop and break later + // combine both static parts of the header with the tx number + header = hhead + strconv.Itoa( txn ) + htail + hlen := len( header ) // keep track of total header length + + // craft packet + packet := header + string( datumtx[pos:( pos + tsize - hlen )] ) + + // cast packet to byte array and send + _, err := conn.Write( []byte( packet ) ) + check( err ) // routine error check + + // update position as last position printed + pos = pos + tsize - hlen + txn++ // update transmission number + + // check to see if *updated* position goes out of bounds + if pos + tsize - hlen > dsize { + break // break if'n + } + } + // print nth header ( X denotes final transmission ) + header = hhead + "X" + htail + packet := header + string( datumtx[pos:] ) + // cast data to string, concat, cast to byte array, send + _, err := conn.Write( []byte( packet ) ) + check( err ) // routine error check + +} + // size variables var dsize int = 104 // data global var datum = make( []int, dsize ) +var datumtx = make( []byte, dsize ) +var tsize int func main() { - makedata() // fill global with data + flag.IntVar( &tsize, "s", 10, "tx size" ) + flag.Parse() + + makedatatx() // fill global with data + + service := ":1300" // create service on ip and port + + // resolve ip address and port + addr, err := net.ResolveTCPAddr( "tcp", service ) + check( err ) // make sure ip resolves + + // create listener object from ip:port + listener, err := net.ListenTCP( "tcp", addr ) + // print global data to show that PWFT works as intended - level0( datum ) + //level0( datum ) - level3() // do the thing + //level3() // do the thing + + for { + // wait, create connection when found + conn, err := listener.Accept() + check( err ) // make sure connection works + + go level6( conn ) // handle connection + } }