github.com/Cloud-Foundations/Dominator@v0.3.4/hypervisor/rpcd/lib.go (about) 1 package rpcd 2 3 import ( 4 "io" 5 6 "github.com/Cloud-Foundations/Dominator/lib/srpc" 7 ) 8 9 func connectChannelsToConnection(conn *srpc.Conn, input chan<- byte, 10 output <-chan byte) error { 11 closeNotifier := make(chan error, 1) 12 go func() { // Read from connection and write to input until EOF. 13 buffer := make([]byte, 256) 14 for { 15 if nRead, err := conn.Read(buffer); err != nil { 16 if err != io.EOF { 17 closeNotifier <- err 18 } else { 19 closeNotifier <- srpc.ErrorCloseClient 20 } 21 return 22 } else { 23 for _, char := range buffer[:nRead] { 24 input <- char 25 } 26 } 27 } 28 }() 29 // Read from output until closure or transmission error. 30 for { 31 select { 32 case data, ok := <-output: 33 var buffer []byte 34 if !ok { 35 buffer = []byte("VM serial port closed\n") 36 } else { 37 buffer = readData(data, output) 38 } 39 if _, err := conn.Write(buffer); err != nil { 40 return err 41 } 42 if err := conn.Flush(); err != nil { 43 return err 44 } 45 if !ok { 46 return srpc.ErrorCloseClient 47 } 48 case err := <-closeNotifier: 49 return err 50 } 51 } 52 } 53 54 func readData(firstByte byte, moreBytes <-chan byte) []byte { 55 buffer := make([]byte, 1, len(moreBytes)+1) 56 buffer[0] = firstByte 57 for { 58 select { 59 case char, ok := <-moreBytes: 60 if !ok { 61 return buffer 62 } 63 buffer = append(buffer, char) 64 default: 65 return buffer 66 } 67 } 68 }