2022-10-04 13:21:05 +08:00
|
|
|
|
//----------------------------------------
|
|
|
|
|
//
|
|
|
|
|
// Copyright © yanghy. All Rights Reserved.
|
|
|
|
|
//
|
2022-10-04 16:38:43 +08:00
|
|
|
|
// Licensed under GNU General Public License v3.0
|
2022-10-04 13:21:05 +08:00
|
|
|
|
//
|
|
|
|
|
//----------------------------------------
|
|
|
|
|
|
2022-10-04 22:34:57 +08:00
|
|
|
|
package ipc
|
2022-10-04 13:21:05 +08:00
|
|
|
|
|
|
|
|
|
import (
|
2022-11-02 12:47:47 +08:00
|
|
|
|
. "github.com/energye/energy/common"
|
2022-10-04 22:34:57 +08:00
|
|
|
|
"github.com/energye/energy/logger"
|
2022-10-04 13:21:05 +08:00
|
|
|
|
"github.com/energye/golcl/lcl/rtl/version"
|
|
|
|
|
"net"
|
2023-01-29 13:26:02 +08:00
|
|
|
|
"os"
|
|
|
|
|
"path/filepath"
|
2022-10-04 13:21:05 +08:00
|
|
|
|
"sync"
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
var (
|
2022-10-27 21:03:15 +08:00
|
|
|
|
MemoryAddress = "energy.sock"
|
2022-10-04 13:21:05 +08:00
|
|
|
|
//GO IPC 通道选择条件
|
|
|
|
|
//
|
|
|
|
|
//默认值=IsDarwin() true:使用net socket, false:使用unix socket
|
|
|
|
|
UseNetIPCChannel = true
|
|
|
|
|
ipcSock string
|
|
|
|
|
//主进程Browser启动 IPC,Render进程创建 IPC
|
|
|
|
|
IPC = &ipcChannel{
|
|
|
|
|
browser: &browserChannel{
|
2022-10-04 22:34:57 +08:00
|
|
|
|
msgID: &MsgID{},
|
|
|
|
|
cliID: &CliID{},
|
2022-10-04 13:21:05 +08:00
|
|
|
|
events: &event{event: make(map[string]EventCallback)},
|
2022-10-27 21:03:15 +08:00
|
|
|
|
channel: sync.Map{},
|
2022-10-04 22:34:57 +08:00
|
|
|
|
emitSync: make(map[string]*EmitSyncCollection),
|
2022-10-04 13:21:05 +08:00
|
|
|
|
mutex: sync.Mutex{},
|
2022-10-04 22:34:57 +08:00
|
|
|
|
emitCallback: &EmitCallbackCollection{EmitCollection: sync.Map{}},
|
2022-10-04 13:21:05 +08:00
|
|
|
|
browseOnEvents: make([]func(browseProcess IEventOn), 0),
|
|
|
|
|
browseEmitCallback: make([]func(renderProcess IEventEmit), 0)},
|
|
|
|
|
render: &renderChannel{
|
2022-10-04 22:34:57 +08:00
|
|
|
|
msgID: &MsgID{},
|
2022-10-04 13:21:05 +08:00
|
|
|
|
mutex: sync.Mutex{},
|
2022-10-04 22:34:57 +08:00
|
|
|
|
emitCallback: &EmitCallbackCollection{EmitCollection: sync.Map{}},
|
|
|
|
|
emitSync: make(map[string]*EmitSyncCollection),
|
2022-10-04 13:21:05 +08:00
|
|
|
|
events: &event{event: make(map[string]EventCallback)},
|
|
|
|
|
renderOnEvents: make([]func(browseProcess IEventOn), 0),
|
|
|
|
|
renderEmitCallback: make([]func(renderProcess IEventEmit), 0),
|
|
|
|
|
},
|
|
|
|
|
}
|
|
|
|
|
)
|
|
|
|
|
|
2022-10-04 22:34:57 +08:00
|
|
|
|
func init() {
|
2023-01-29 13:26:02 +08:00
|
|
|
|
//ipcSock = fmt.Sprintf("%s%sgolcl%s%s", consts.HomeDir, consts.Separator, consts.Separator, MemoryAddress)
|
|
|
|
|
ipcSock = filepath.Join(os.TempDir(), MemoryAddress)
|
2022-10-04 22:34:57 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func IPCChannelChooseInit() {
|
2022-10-04 13:21:05 +08:00
|
|
|
|
UseNetIPCChannel = isUseNetIPC()
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func isUseNetIPC() bool {
|
2022-10-18 10:12:56 +08:00
|
|
|
|
if IsDarwin() || IsLinux() {
|
2022-10-04 13:21:05 +08:00
|
|
|
|
return false
|
|
|
|
|
}
|
|
|
|
|
ov := version.OSVersion
|
|
|
|
|
if (ov.Major > 10) || (ov.Major == 10 && ov.Build >= 17063) {
|
|
|
|
|
//不支持UnixSocket
|
|
|
|
|
return false
|
|
|
|
|
}
|
2022-10-18 10:12:56 +08:00
|
|
|
|
//使用net socket
|
2022-10-04 13:21:05 +08:00
|
|
|
|
return true
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 主Browser进程和Render进程事件on
|
|
|
|
|
type IEventOn interface {
|
|
|
|
|
On(name string, eventCallback EventCallback) //IPC 事件监听
|
2022-10-04 22:34:57 +08:00
|
|
|
|
Close()
|
2022-10-04 13:21:05 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 主Browser进程和Render进程事件emit
|
|
|
|
|
type IEventEmit interface {
|
|
|
|
|
IEventOn
|
2022-10-04 22:34:57 +08:00
|
|
|
|
Events() *event
|
2022-10-05 17:20:20 +08:00
|
|
|
|
SetOnEvent(callback func(event IEventOn)) //IPC 事件监听
|
2022-10-04 13:21:05 +08:00
|
|
|
|
Emit(eventName string, arguments IArgumentList) //IPC 异步事件触发
|
2022-10-04 22:34:57 +08:00
|
|
|
|
EmitAndCallback(eventName string, arguments IArgumentList, callback IPCCallback) //IPC 回调事件触发
|
2022-10-04 13:21:05 +08:00
|
|
|
|
EmitAndReturn(eventName string, arguments IArgumentList) IIPCContext //IPC 返回值事件触发(处理时间复杂操作尽量不使用,容易造成UI进程锁死)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 主进程事件emit
|
|
|
|
|
type IBrowseEventEmit interface {
|
|
|
|
|
IEventOn
|
|
|
|
|
IEventEmit
|
2022-12-14 09:49:14 +08:00
|
|
|
|
Channel(channelId int64) *channel //IPC 获取指定的通道
|
|
|
|
|
ChannelIds() (result []int64) //IPC 获取所有通道
|
2022-10-04 13:21:05 +08:00
|
|
|
|
EmitChannelId(eventName string, channelId int64, arguments IArgumentList) //IPC 异步事件触发-指定通道ID
|
2022-10-04 22:34:57 +08:00
|
|
|
|
EmitChannelIdAndCallback(eventName string, channelId int64, arguments IArgumentList, callback IPCCallback) //IPC 回调事件触发-指定通道ID
|
2022-10-04 13:21:05 +08:00
|
|
|
|
EmitChannelIdAndReturn(eventName string, channelId int64, arguments IArgumentList) IIPCContext //IPC 返回值事件触发(处理时间复杂操作尽量不使用,容易造成UI进程锁死)-指定通道ID
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func getFreePort() int {
|
|
|
|
|
//主进程获取端口号
|
|
|
|
|
if Args.IsMain() {
|
|
|
|
|
addr, err := net.ResolveTCPAddr("tcp", "localhost:0")
|
|
|
|
|
if err != nil {
|
2022-10-04 22:34:57 +08:00
|
|
|
|
panic("Failed to Get unused Port number Error: " + err.Error())
|
2022-10-04 13:21:05 +08:00
|
|
|
|
}
|
|
|
|
|
listen, err := net.ListenTCP("tcp", addr)
|
|
|
|
|
if err != nil {
|
2022-10-04 22:34:57 +08:00
|
|
|
|
panic("Failed to Get unused Port number Error: " + err.Error())
|
2022-10-04 13:21:05 +08:00
|
|
|
|
}
|
|
|
|
|
defer listen.Close()
|
|
|
|
|
return listen.Addr().(*net.TCPAddr).Port
|
|
|
|
|
}
|
|
|
|
|
return 0
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
type ipcChannel struct {
|
|
|
|
|
serverIsStart chan int
|
|
|
|
|
port int
|
|
|
|
|
browser *browserChannel
|
|
|
|
|
render *renderChannel
|
|
|
|
|
}
|
|
|
|
|
|
2022-10-04 22:34:57 +08:00
|
|
|
|
func (m *ipcChannel) Port() int {
|
|
|
|
|
return m.port
|
|
|
|
|
}
|
|
|
|
|
func (m *ipcChannel) SetPort(port ...int) {
|
|
|
|
|
if len(port) > 0 {
|
|
|
|
|
m.port = port[0]
|
|
|
|
|
} else {
|
|
|
|
|
if m.port == 0 {
|
|
|
|
|
m.port = getFreePort()
|
|
|
|
|
}
|
2022-10-04 13:21:05 +08:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func (m *ipcChannel) Browser() IBrowseEventEmit {
|
|
|
|
|
return m.browser
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func (m *ipcChannel) Render() IEventEmit {
|
|
|
|
|
return m.render
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 启动IPC服务
|
|
|
|
|
func (m *ipcChannel) StartBrowserIPC() {
|
2023-01-29 13:26:02 +08:00
|
|
|
|
logger.Debug("Create IPC browser")
|
2022-10-04 13:21:05 +08:00
|
|
|
|
group := sync.WaitGroup{}
|
|
|
|
|
group.Add(1)
|
|
|
|
|
go func() {
|
2022-10-28 16:49:35 +08:00
|
|
|
|
defer func() {
|
|
|
|
|
if err := recover(); err != nil {
|
|
|
|
|
logger.Error("Create IPC Browser Recover:", err)
|
|
|
|
|
}
|
|
|
|
|
}()
|
2022-10-04 22:34:57 +08:00
|
|
|
|
m.SetPort()
|
2022-10-04 13:21:05 +08:00
|
|
|
|
m.newBrowseChannel()
|
2022-10-04 22:34:57 +08:00
|
|
|
|
defer m.browser.Close()
|
2022-10-04 13:21:05 +08:00
|
|
|
|
if m.browser.browseOnEvents != nil {
|
|
|
|
|
for _, cb := range m.browser.browseOnEvents {
|
|
|
|
|
if cb != nil {
|
|
|
|
|
cb(m.browser)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if m.browser.browseEmitCallback != nil {
|
|
|
|
|
for _, cb := range m.browser.browseEmitCallback {
|
|
|
|
|
if cb != nil {
|
|
|
|
|
cb(m.browser)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
group.Done()
|
|
|
|
|
m.browser.accept()
|
|
|
|
|
}()
|
|
|
|
|
group.Wait()
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 创建IPC客户端服务 基于unix socket, windows <= 10.17063 基于net socket
|
|
|
|
|
//
|
|
|
|
|
//单进程,只创建一个连接
|
|
|
|
|
//
|
|
|
|
|
//多进程,每个渲染进程创建一个连接
|
|
|
|
|
func (m *ipcChannel) CreateRenderIPC(browserId int32, channelId int64) *renderChannel {
|
2023-01-29 13:26:02 +08:00
|
|
|
|
logger.Debug("Create IPC render isConnect:", m.render.isConnect, "channelId:", channelId)
|
2022-10-04 13:21:05 +08:00
|
|
|
|
if m.render.isConnect {
|
|
|
|
|
return m.render
|
|
|
|
|
}
|
|
|
|
|
//m.closeClient()
|
|
|
|
|
m.newRenderChannel()
|
|
|
|
|
if m.render.renderOnEvents != nil {
|
|
|
|
|
for _, cb := range m.render.renderOnEvents {
|
|
|
|
|
if cb != nil {
|
|
|
|
|
cb(m.render)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if m.render.renderEmitCallback != nil {
|
|
|
|
|
for _, cb := range m.render.renderEmitCallback {
|
|
|
|
|
if cb != nil {
|
|
|
|
|
cb(m.render)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
m.render.browserId = browserId
|
|
|
|
|
m.render.channelId = channelId
|
|
|
|
|
m.render.emitConnect()
|
|
|
|
|
return m.render
|
|
|
|
|
}
|