func SendRequest(c *net.UnixConn, req *server.Request) error { payload, err := json.Marshal(req) if err != nil { return err } err = binary.Write(c, binary.BigEndian, uint32(len(payload))) if err != nil { return err } n, err := c.Write(payload) if err != nil { return err } else if n != len(payload) { return fmt.Errorf("Failed to write full payload, expected %v, wrote %v", len(payload), n) } if !req.HasFds { return nil } // Send filedescriptors with a 1 byte message. var oob []byte oob = syscall.UnixRights(req.Fds...) payload = make([]byte, 1) n, oobn, err := c.WriteMsgUnix(payload, oob, nil) if err != nil { return err } else if n != len(payload) || oobn != len(oob) { return fmt.Errorf("Error writing to socket, expected n=%v got %v, oob=%v got %v", len(payload), n, len(oob), oobn) } return nil }
func writeData(conn *net.UnixConn, files []*os.File, pid int, responseErr error) { var errMsg string = "" if responseErr != nil { errMsg = responseErr.Error() } response := &Response{ Pid: pid, ErrMessage: errMsg, } responseJson, _ := json.Marshal(response) // Ignore error args := make([]int, len(files)) for i, f := range files { args[i] = int(f.Fd()) } resp := syscall.UnixRights(args...) conn.WriteMsgUnix(responseJson, resp, nil) // Ignore error // Close the files whose descriptors have been sent to the host to ensure that // a close on the host takes effect in a timely fashion. for _, file := range files { file.Close() // Ignore error } }
func WriteFile(c *net.UnixConn, file *os.File, timeout time.Duration) error { if timeout > 0 { deadline := time.Now().Add(timeout) if err := c.SetWriteDeadline(deadline); err != nil { return err } } oob := syscall.UnixRights(int(file.Fd())) _, _, err := c.WriteMsgUnix(nil, oob, nil) return err }
func RemoteSendCredentials(conn *net.UnixConn) error { ucred := &syscall.Ucred{ Pid: int32(os.Getpid()), Uid: uint32(os.Getuid()), Gid: uint32(os.Getgid()), } oob := syscall.UnixCredentials(ucred) _, _, err := conn.WriteMsgUnix(nil, oob, nil) return err }
func (fd Fd) writeTo(c *net.UnixConn) error { var b []byte oob := syscall.UnixRights(int(fd)) _, oobn, err := c.WriteMsgUnix(b, oob, nil) if err != nil { return err } if oobn != len(oob) { return fmt.Errorf("expected to write %d oob bytes, wrote %d", len(oob), oobn) } return nil }
func SendFd(conn *net.UnixConn, file *os.File) error { rights := syscall.UnixRights(int(file.Fd())) dummy := []byte("x") n, oobn, err := conn.WriteMsgUnix(dummy, rights, nil) if err != nil { return fmt.Errorf("sendfd: err %v", err) } if n != len(dummy) { return fmt.Errorf("sendfd: short write %v", conn) } if oobn != len(rights) { return fmt.Errorf("sendfd: short oob write %v", conn) } return nil }
func SendWaylandMessage(conn *net.UnixConn, m *Message) error { header := &bytes.Buffer{} // calculate message total size m.size = uint32(m.data.Len() + 8) binary.Write(header, binary.LittleEndian, m.Id) binary.Write(header, binary.LittleEndian, m.size<<16|m.Opcode&0x0000ffff) d, c, err := conn.WriteMsgUnix(append(header.Bytes(), m.data.Bytes()...), m.control.Bytes(), nil) if err != nil { panic(err.Error()) } if c != m.control.Len() || d != (header.Len()+m.data.Len()) { panic("WriteMsgUnix failed.") } return err }
func writeData(conn *net.UnixConn, response *container_daemon.ResponseMessage) { data, _ := json.Marshal(response) // Ignore error args := make([]int, len(response.Files)) for i, f := range response.Files { args[i] = int(f.Fd()) } oobData := syscall.UnixRights(args...) conn.WriteMsgUnix(data, oobData, nil) // Ignore error // Close the files whose descriptors have been sent to the host to ensure that // a close on the host takes effect in a timely fashion. for _, file := range response.Files { file.Close() // Ignore error } }
// passFDChild is the child process used by TestPassFD. func passFDChild() { defer os.Exit(0) // Look for our fd. It should be fd 3, but we work around an fd leak // bug here (http://golang.org/issue/2603) to let it be elsewhere. var uc *net.UnixConn for fd := uintptr(3); fd <= 10; fd++ { f := os.NewFile(fd, "unix-conn") var ok bool netc, _ := net.FileConn(f) uc, ok = netc.(*net.UnixConn) if ok { break } } if uc == nil { fmt.Println("failed to find unix fd") return } // Make a file f to send to our parent process on uc. // We make it in tempDir, which our parent will clean up. flag.Parse() tempDir := flag.Arg(0) f, err := ioutil.TempFile(tempDir, "") if err != nil { fmt.Printf("TempFile: %v", err) return } f.Write([]byte("Hello from child process!\n")) f.Seek(0, 0) rights := syscall.UnixRights(int(f.Fd())) dummyByte := []byte("x") n, oobn, err := uc.WriteMsgUnix(dummyByte, rights, nil) if err != nil { fmt.Printf("WriteMsgUnix: %v", err) return } if n != 1 || oobn != len(rights) { fmt.Printf("WriteMsgUnix = %d, %d; want 1, %d", n, oobn, len(rights)) return } }
// Send File over UnixConn func SendFD(conn *net.UnixConn, file *os.File) (err error) { cmsgb := make([]byte, CmsgSpace(unsafe.Sizeof(int(0)))) cms := (*syscall.Cmsghdr)(unsafe.Pointer(&cmsgb[0])) cms.Len = CmsgLen(unsafe.Sizeof(int(0))) cms.Level = 1 cms.Type = 1 fdnum := file.Fd() fdArea := cmsgb[unsafe.Sizeof(syscall.Cmsghdr{}):] fdArea[0] = byte(fdnum) fdArea[1] = byte(fdnum >> 8) fdArea[2] = byte(fdnum >> 16) fdArea[3] = byte(fdnum >> 24) _, _, err = conn.WriteMsgUnix([]byte{}, cmsgb, nil) return }
func sendUnix(conn *net.UnixConn, data []byte, fds ...int) error { _, _, err := conn.WriteMsgUnix(data, syscall.UnixRights(fds...), nil) return err }