github.com/cloudfoundry-attic/garden-linux@v0.333.2-candidate/container_daemon/unix_socket/connector.go (about)

     1  package unix_socket
     2  
     3  import (
     4  	"encoding/json"
     5  	"errors"
     6  	"fmt"
     7  	"net"
     8  	"os"
     9  	"syscall"
    10  
    11  	"github.com/cloudfoundry-incubator/garden-linux/container_daemon"
    12  )
    13  
    14  type Connector struct {
    15  	SocketPath string
    16  }
    17  
    18  func (c *Connector) Connect(msg *container_daemon.RequestMessage) (*container_daemon.ResponseMessage, error) {
    19  	conn, err := net.Dial("unix", c.SocketPath)
    20  	if err != nil {
    21  		return nil, fmt.Errorf("unix_socket: connect to server socket: %s", err)
    22  	}
    23  	defer conn.Close() // Ignore error
    24  
    25  	msgJson, err := json.Marshal(msg)
    26  	if err != nil {
    27  		return nil, fmt.Errorf("unix_socket: failed to marshal json message: %s", err)
    28  	}
    29  
    30  	_, err = conn.Write(msgJson)
    31  	if err != nil {
    32  		return nil, fmt.Errorf("unix_socket: failed to write to connection: %s", err)
    33  	}
    34  
    35  	return readData(conn)
    36  }
    37  
    38  func readData(conn net.Conn) (*container_daemon.ResponseMessage, error) {
    39  	var b [2048]byte
    40  	var oob [2048]byte
    41  	var response container_daemon.ResponseMessage
    42  
    43  	n, oobn, _, _, err := conn.(*net.UnixConn).ReadMsgUnix(b[:], oob[:])
    44  	if err != nil {
    45  		return nil, fmt.Errorf("unix_socket: failed to read unix msg: %s (read: %d, %d)", err, n, oobn)
    46  	}
    47  
    48  	if n > 0 {
    49  		err := json.Unmarshal(b[:n], &response)
    50  		if err != nil {
    51  			return nil, fmt.Errorf("unix_socket: Unmarshal failed: %s", err)
    52  		}
    53  		if response.ErrMessage != "" {
    54  			return nil, errors.New(response.ErrMessage)
    55  		}
    56  	} else {
    57  		return nil, errors.New("unix_socket: No response received")
    58  	}
    59  
    60  	scms, err := syscall.ParseSocketControlMessage(oob[:oobn])
    61  	if err != nil {
    62  		return nil, fmt.Errorf("unix_socket: failed to parse socket control message: %s", err)
    63  	}
    64  
    65  	if len(scms) > 0 {
    66  		scm := scms[0]
    67  		fds, err := syscall.ParseUnixRights(&scm)
    68  		if err != nil {
    69  			return nil, fmt.Errorf("unix_socket: failed to parse unix rights: %s", err)
    70  		}
    71  
    72  		response.Files = make([]container_daemon.StreamingFile, len(fds))
    73  		for i, fd := range fds {
    74  			response.Files[i] = os.NewFile(uintptr(fd), fmt.Sprintf("/dev/fake-fd-%d", i))
    75  		}
    76  	}
    77  
    78  	return &response, nil
    79  }