github.com/gogf/gf@v1.16.9/os/gproc/gproc_comm.go (about) 1 // Copyright GoFrame Author(https://goframe.org). All Rights Reserved. 2 // 3 // This Source Code Form is subject to the terms of the MIT License. 4 // If a copy of the MIT was not distributed with this file, 5 // You can obtain one at https://github.com/gogf/gf. 6 7 package gproc 8 9 import ( 10 "context" 11 "fmt" 12 "github.com/gogf/gf/container/gmap" 13 "github.com/gogf/gf/errors/gcode" 14 "github.com/gogf/gf/errors/gerror" 15 "github.com/gogf/gf/internal/intlog" 16 "github.com/gogf/gf/net/gtcp" 17 "github.com/gogf/gf/os/gfile" 18 "github.com/gogf/gf/util/gconv" 19 ) 20 21 // MsgRequest is the request structure for process communication. 22 type MsgRequest struct { 23 SendPid int // Sender PID. 24 RecvPid int // Receiver PID. 25 Group string // Message group name. 26 Data []byte // Request data. 27 } 28 29 // MsgResponse is the response structure for process communication. 30 type MsgResponse struct { 31 Code int // 1: OK; Other: Error. 32 Message string // Response message. 33 Data []byte // Response data. 34 } 35 36 const ( 37 defaultFolderNameForProcComm = "gf_pid_port_mapping" // Default folder name for storing pid to port mapping files. 38 defaultGroupNameForProcComm = "" // Default group name. 39 defaultTcpPortForProcComm = 10000 // Starting port number for receiver listening. 40 maxLengthForProcMsgQueue = 10000 // Max size for each message queue of the group. 41 ) 42 43 var ( 44 // commReceiveQueues is the group name to queue map for storing received data. 45 // The value of the map is type of *gqueue.Queue. 46 commReceiveQueues = gmap.NewStrAnyMap(true) 47 48 // commPidFolderPath specifies the folder path storing pid to port mapping files. 49 commPidFolderPath string 50 ) 51 52 func init() { 53 availablePaths := []string{ 54 "/var/tmp", 55 "/var/run", 56 } 57 if homePath, _ := gfile.Home(); homePath != "" { 58 availablePaths = append(availablePaths, gfile.Join(homePath, ".config")) 59 } 60 availablePaths = append(availablePaths, gfile.TempDir()) 61 for _, availablePath := range availablePaths { 62 checkPath := gfile.Join(availablePath, defaultFolderNameForProcComm) 63 if !gfile.Exists(checkPath) && gfile.Mkdir(checkPath) != nil { 64 continue 65 } 66 if gfile.IsWritable(checkPath) { 67 commPidFolderPath = checkPath 68 break 69 } 70 } 71 if commPidFolderPath == "" { 72 intlog.Errorf( 73 context.TODO(), 74 `cannot find available folder for storing pid to port mapping files in paths: %+v, process communication feature will fail`, 75 availablePaths, 76 ) 77 } 78 79 } 80 81 // getConnByPid creates and returns a TCP connection for specified pid. 82 func getConnByPid(pid int) (*gtcp.PoolConn, error) { 83 port := getPortByPid(pid) 84 if port > 0 { 85 if conn, err := gtcp.NewPoolConn(fmt.Sprintf("127.0.0.1:%d", port)); err == nil { 86 return conn, nil 87 } else { 88 return nil, err 89 } 90 } 91 return nil, gerror.NewCodef(gcode.CodeOperationFailed, "could not find port for pid: %d", pid) 92 } 93 94 // getPortByPid returns the listening port for specified pid. 95 // It returns 0 if no port found for the specified pid. 96 func getPortByPid(pid int) int { 97 return gconv.Int(gfile.GetContentsWithCache(getCommFilePath(pid))) 98 } 99 100 // getCommFilePath returns the pid to port mapping file path for given pid. 101 func getCommFilePath(pid int) string { 102 return gfile.Join(commPidFolderPath, gconv.String(pid)) 103 }