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  }