energy/ipc/cef-ipc.go

211 lines
5.9 KiB
Go
Raw Normal View History

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 (
. "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 (
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启动 IPCRender进程创建 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)},
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() {
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
}