Example #1
0
func (t *testAttachServer) Start() error {
	log.Info("opening ttyS0 pipe pair for backchannel (server)")
	c, err := os.OpenFile(pathPrefix+"/ttyS0c", os.O_WRONLY|syscall.O_NOCTTY, 0777)
	if err != nil {
		detail := fmt.Sprintf("failed to open cpipe for backchannel: %s", err)
		log.Error(detail)
		return errors.New(detail)
	}

	s, err := os.OpenFile(pathPrefix+"/ttyS0s", os.O_RDONLY|syscall.O_NOCTTY, 0777)
	if err != nil {
		detail := fmt.Sprintf("failed to open spipe for backchannel: %s", err)
		log.Error(detail)
		return errors.New(detail)
	}

	log.Infof("creating raw connection from ttyS0 pipe pair (c=%d, s=%d)\n", c.Fd(), s.Fd())
	var conn net.Conn
	conn, err = serial.NewHalfDuplexFileConn(s, c, pathPrefix+"/ttyS0", "file")
	if err != nil {
		detail := fmt.Sprintf("failed to create raw connection from ttyS0 pipe pair: %s", err)
		log.Error(detail)
		return errors.New(detail)
	}

	t.conn.Lock()
	defer t.conn.Unlock()

	t.conn.conn = conn
	return nil
}
Example #2
0
// create client on the mock pipe
func mockBackChannel(ctx context.Context) (net.Conn, error) {
	log.Info("opening ttyS0 pipe pair for backchannel (client)")
	c, err := os.OpenFile(pathPrefix+"/ttyS0c", os.O_RDONLY|syscall.O_NOCTTY, 0777)
	if err != nil {
		detail := fmt.Sprintf("failed to open cpipe for backchannel: %s", err)
		log.Error(detail)
		return nil, errors.New(detail)
	}

	s, err := os.OpenFile(pathPrefix+"/ttyS0s", os.O_WRONLY|syscall.O_NOCTTY, 0777)
	if err != nil {
		detail := fmt.Sprintf("failed to open spipe for backchannel: %s", err)
		log.Error(detail)
		return nil, errors.New(detail)
	}

	log.Infof("creating raw connection from ttyS0 pipe pair (c=%d, s=%d)\n", c.Fd(), s.Fd())
	conn, err := serial.NewHalfDuplexFileConn(c, s, pathPrefix+"/ttyS0", "file")

	if err != nil {
		detail := fmt.Sprintf("failed to create raw connection from ttyS0 pipe pair: %s", err)
		log.Error(detail)
		return nil, errors.New(detail)
	}

	// HACK: currently RawConn dosn't implement timeout so throttle the spinning
	ticker := time.NewTicker(1000 * time.Millisecond)
	for {
		select {
		case <-ticker.C:
			// FIXME: need to implement timeout of purging hangs with no content
			// on the pipe
			// serial.PurgeIncoming(ctx, conn)
			err := serial.HandshakeClient(conn, true)
			if err != nil {
				if err == io.EOF {
					// with unix pipes the open will block until both ends are open, therefore
					// EOF means the other end has been intentionally closed
					return nil, err
				}
				log.Error(err)
			} else {
				return conn, nil
			}
		case <-ctx.Done():
			conn.Close()
			ticker.Stop()
			return nil, ctx.Err()
		}
	}
}
Example #3
0
// create client on the mock pipe and dial the given host:port
func mockNetworkToSerialConnection(host string) (*sync.WaitGroup, error) {
	log.Info("opening ttyS0 pipe pair for backchannel")
	c, err := os.OpenFile(pathPrefix+"/ttyS0c", os.O_RDONLY|syscall.O_NOCTTY, 0777)
	if err != nil {
		return nil, fmt.Errorf("failed to open cpipe for backchannel: %s", err)
	}

	s, err := os.OpenFile(pathPrefix+"/ttyS0s", os.O_WRONLY|syscall.O_NOCTTY, 0777)
	if err != nil {
		return nil, fmt.Errorf("failed to open spipe for backchannel: %s", err)
	}

	log.Infof("creating raw connection from ttyS0 pipe pair (c=%d, s=%d)\n", c.Fd(), s.Fd())
	fconn, err := serial.NewHalfDuplexFileConn(c, s, pathPrefix+"/ttyS0", "file")
	if err != nil {
		return nil, fmt.Errorf("failed to create raw connection from ttyS0 pipe pair: %s", err)
	}

	// Dial the attach server.  This is a TCP client
	networkClientCon, err := net.Dial("tcp", host)
	if err != nil {
		return nil, err
	}
	log.Debugf("dialed %s", host)

	wg := sync.WaitGroup{}
	wg.Add(2)

	go func() {
		io.Copy(networkClientCon, fconn)
		wg.Done()
	}()

	go func() {
		io.Copy(fconn, networkClientCon)
		wg.Done()
	}()

	return &wg, nil
}