649 lines
19 KiB
Go
649 lines
19 KiB
Go
|
package main
|
||
|
|
||
|
import (
|
||
|
"crypto/tls"
|
||
|
"crypto/x509"
|
||
|
"encoding/binary"
|
||
|
"errors"
|
||
|
"fmt"
|
||
|
"log"
|
||
|
"net"
|
||
|
"os"
|
||
|
"time"
|
||
|
|
||
|
"fyne.io/fyne/v2"
|
||
|
"fyne.io/fyne/v2/app"
|
||
|
"fyne.io/fyne/v2/container"
|
||
|
"fyne.io/fyne/v2/driver/desktop"
|
||
|
"fyne.io/fyne/v2/layout"
|
||
|
"fyne.io/fyne/v2/theme"
|
||
|
"fyne.io/fyne/v2/widget"
|
||
|
|
||
|
com "git.qowevisa.me/Qowevisa/gotell/communication"
|
||
|
"git.qowevisa.me/Qowevisa/gotell/env"
|
||
|
"git.qowevisa.me/Qowevisa/gotell/extfyne/widgets"
|
||
|
)
|
||
|
|
||
|
func updateTime(clock *widget.Label) {
|
||
|
formatted := time.Now().Format("Time: 03:04:05")
|
||
|
clock.SetText(formatted)
|
||
|
}
|
||
|
|
||
|
var globalApp *MutableApplication
|
||
|
var globalCfg *FyneConfig
|
||
|
|
||
|
var (
|
||
|
ecdhKeyReceived = false
|
||
|
ecdhKeySent = false
|
||
|
)
|
||
|
|
||
|
var (
|
||
|
globalClipboardChannel = make(chan string)
|
||
|
)
|
||
|
|
||
|
func main() {
|
||
|
tlepCenter.Init()
|
||
|
userCenter.Init()
|
||
|
loadingFileName := env.ServerFullchainFileName
|
||
|
cert, err := os.ReadFile(loadingFileName)
|
||
|
if err != nil {
|
||
|
log.Fatalf("client: load root cert: %s", err)
|
||
|
}
|
||
|
log.Printf("Certificate %s loaded successfully!\n", loadingFileName)
|
||
|
//
|
||
|
roots := x509.NewCertPool()
|
||
|
if ok := roots.AppendCertsFromPEM(cert); !ok {
|
||
|
log.Fatalf("client: failed to parse root certificate")
|
||
|
}
|
||
|
|
||
|
config := &tls.Config{
|
||
|
RootCAs: roots,
|
||
|
}
|
||
|
host := "chat.qowevisa.click"
|
||
|
port := 3232
|
||
|
service := fmt.Sprintf("%s:%d", host, port)
|
||
|
log.Printf("client: connecting to %s", service)
|
||
|
conn, err := tls.Dial("tcp", service, config)
|
||
|
if err != nil {
|
||
|
log.Fatalf("client: dial: %s", err)
|
||
|
}
|
||
|
defer conn.Close()
|
||
|
log.Printf("client: connected to %s", service)
|
||
|
//
|
||
|
|
||
|
a := app.New()
|
||
|
w := a.NewWindow("gotell-fyne")
|
||
|
// w.Resize(fyne.NewSize(640, 400))
|
||
|
|
||
|
// dispatch clipboardChannel
|
||
|
go func(w fyne.Window) {
|
||
|
for val := range globalClipboardChannel {
|
||
|
w.Clipboard().SetContent(val)
|
||
|
}
|
||
|
}(w)
|
||
|
|
||
|
clock := widget.NewLabel("")
|
||
|
go func() {
|
||
|
for range time.Tick(time.Second) {
|
||
|
updateTime(clock)
|
||
|
}
|
||
|
}()
|
||
|
|
||
|
btn := widget.NewButtonWithIcon("testBtn", theme.AccountIcon(), func() {
|
||
|
fmt.Println("I'm pressed!")
|
||
|
})
|
||
|
|
||
|
mainContainer := container.New(layout.NewVBoxLayout(), clock, btn)
|
||
|
|
||
|
w.SetContent(mainContainer)
|
||
|
// w.SetContent(widget.NewLabel("Hello World!"))
|
||
|
// w2 := a.NewWindow("Larger")
|
||
|
// w2.SetContent(widget.NewLabel("More content"))
|
||
|
// w2.Resize(fyne.NewSize(100, 100))
|
||
|
// w2.Show()
|
||
|
intercomFromServer := make(chan *com.Message, 16)
|
||
|
intercomToServer := make(chan *com.Message, 16)
|
||
|
actionsChannel := make(chan int)
|
||
|
cfg := FyneConfig{
|
||
|
App: a,
|
||
|
Window: w,
|
||
|
}
|
||
|
globalCfg = &cfg
|
||
|
|
||
|
go readFromServer(conn, intercomFromServer)
|
||
|
go analyzeMessages(intercomFromServer, actionsChannel)
|
||
|
go actOnActions(cfg, actionsChannel, intercomToServer)
|
||
|
go readFromIntercom(intercomToServer, conn)
|
||
|
w.ShowAndRun()
|
||
|
}
|
||
|
|
||
|
var r com.RegisteredUser
|
||
|
var tmpLink *com.Link
|
||
|
var tmpNick string
|
||
|
|
||
|
func readFromServer(conn net.Conn, intercom chan *com.Message) {
|
||
|
buf := make([]byte, 70000)
|
||
|
for {
|
||
|
err := conn.SetDeadline(time.Now().Add(1 * time.Minute))
|
||
|
if err != nil {
|
||
|
log.Printf("ERROR: conn.SetDeadline: %v", err)
|
||
|
continue
|
||
|
}
|
||
|
n, err := conn.Read(buf)
|
||
|
if err != nil {
|
||
|
log.Printf("ERROR: client: read: %s", err)
|
||
|
if errors.Is(err, net.ErrClosed) {
|
||
|
log.Printf("caught ErrClosed!")
|
||
|
}
|
||
|
if netErr, ok := err.(net.Error); ok && netErr.Timeout() {
|
||
|
log.Println("caught! Read timeout occurred")
|
||
|
continue
|
||
|
}
|
||
|
return
|
||
|
}
|
||
|
msg, err := com.Decode(buf[:n])
|
||
|
if err != nil {
|
||
|
log.Printf("ERROR: %#v\n", err)
|
||
|
continue
|
||
|
}
|
||
|
if msg == nil {
|
||
|
continue
|
||
|
}
|
||
|
log.Printf("client: readServer: received message from server: %v", *msg)
|
||
|
switch msg.ID {
|
||
|
case com.ID_SERVER_APPROVE_CLIENT_NICKNAME:
|
||
|
newID := binary.BigEndian.Uint16(msg.Data)
|
||
|
msg.FromID = newID
|
||
|
msg.Data = []byte{}
|
||
|
r.ID = newID
|
||
|
if tmpNick != "" {
|
||
|
r.Name = tmpNick
|
||
|
}
|
||
|
r.IsRegistered = true
|
||
|
case com.ID_SERVER_APPROVE_CLIENT_LINK:
|
||
|
if tmpLink == nil {
|
||
|
continue
|
||
|
}
|
||
|
msg.ToID = tmpLink.UseCount
|
||
|
msg.Data = tmpLink.Data
|
||
|
// Crypto stuff
|
||
|
case com.ID_CLIENT_SEND_CLIENT_ECDH_PUBKEY:
|
||
|
t, err := tlepCenter.GetTLEP(msg.FromID)
|
||
|
if err != nil {
|
||
|
log.Printf("ERROR: tlep: GetTLEP: %v\n", err)
|
||
|
continue
|
||
|
}
|
||
|
err = t.ECDHApplyOtherKeyBytes(msg.Data)
|
||
|
if err != nil {
|
||
|
log.Printf("ERROR: tlep: ECDHApplyOtherKeyBytes: %v\n", err)
|
||
|
continue
|
||
|
}
|
||
|
fromName, err := userCenter.GetName(msg.FromID)
|
||
|
if err != nil {
|
||
|
log.Printf("ERROR: userCenter: GetName: %v\n", err)
|
||
|
} else {
|
||
|
msg.Data = []byte(fromName)
|
||
|
}
|
||
|
case com.ID_CLIENT_SEND_CLIENT_CBES_SPECS:
|
||
|
t, err := tlepCenter.GetTLEP(msg.FromID)
|
||
|
if err != nil {
|
||
|
log.Printf("ERROR: tlep: GetTLEP: %v\n", err)
|
||
|
continue
|
||
|
}
|
||
|
cbes, err := t.DecryptMessageEA(msg.Data)
|
||
|
if err != nil {
|
||
|
log.Printf("ERROR: tlep: DecryptMessageEA: %v\n", err)
|
||
|
continue
|
||
|
}
|
||
|
err = t.CBESSetFromBytes(cbes)
|
||
|
if err != nil {
|
||
|
log.Printf("ERROR: tlep: CBESSetFromBytes: %v\n", err)
|
||
|
continue
|
||
|
}
|
||
|
fromName, err := userCenter.GetName(msg.FromID)
|
||
|
if err != nil {
|
||
|
log.Printf("ERROR: userCenter: GetName: %v\n", err)
|
||
|
} else {
|
||
|
msg.Data = []byte(fromName)
|
||
|
}
|
||
|
// message
|
||
|
case com.ID_CLIENT_SEND_CLIENT_MESSAGE:
|
||
|
t, err := tlepCenter.GetTLEP(msg.FromID)
|
||
|
if err != nil {
|
||
|
log.Printf("ERROR: tlep: GetTLEP: %v\n", err)
|
||
|
continue
|
||
|
}
|
||
|
decrypedMsg, err := t.DecryptMessageAtMax(msg.Data)
|
||
|
if err != nil {
|
||
|
log.Printf("ERROR: tlep: DecryptMessageAtMax: %v\n", err)
|
||
|
continue
|
||
|
}
|
||
|
msg.Data = decrypedMsg
|
||
|
// switch
|
||
|
}
|
||
|
// user stuff
|
||
|
switch msg.ID {
|
||
|
case com.ID_CLIENT_ASK_CLIENT_HANDSHAKE,
|
||
|
com.ID_CLIENT_APPROVE_CLIENT_HANDSHAKE:
|
||
|
userCenter.AddUser(string(msg.Data), msg.FromID)
|
||
|
}
|
||
|
log.Printf("client: readServer: sending message to websocket: %v", *msg)
|
||
|
intercom <- msg
|
||
|
}
|
||
|
}
|
||
|
|
||
|
func analyzeMessages(intercomFromServer chan *com.Message, actionsChannel chan int) {
|
||
|
for msg := range intercomFromServer {
|
||
|
if msg == nil {
|
||
|
log.Printf("ERROR: msg is nil")
|
||
|
continue
|
||
|
}
|
||
|
log.Printf("Handling %v from server", *msg)
|
||
|
switch msg.ID {
|
||
|
case com.ID_SERVER_ASK_CLIENT_NICKNAME:
|
||
|
actionsChannel <- ACTION_SET_SCENE_NICKNAME
|
||
|
case com.ID_SERVER_APPROVE_CLIENT_NICKNAME:
|
||
|
actionsChannel <- ACTION_SET_SCENE_MAIN
|
||
|
case com.ID_SERVER_DECLINE_CLIENT_NICKNAME:
|
||
|
// TODO
|
||
|
// Link stuff
|
||
|
case com.ID_SERVER_APPROVE_CLIENT_LINK:
|
||
|
globalApp.ArrayBundle.LinksMuAr.Add(*tmpLink)
|
||
|
globalApp.Tabs.LinkTab.Content.Refresh()
|
||
|
case com.ID_SERVER_SEND_CLIENT_ANOTHER_ID:
|
||
|
selTab := globalApp.Tabs.AppTabs.Selected()
|
||
|
id := msg.ToID
|
||
|
userStr := getStdUserName(id, string(msg.Data))
|
||
|
globalApp.Widgets.UsersSelect.Options = append(globalApp.Widgets.UsersSelect.Options, userStr)
|
||
|
globalApp.Tabs.ConnsNoty++
|
||
|
globalApp.ArrayBundle.UsersOpts[userStr] = &UserOptions{
|
||
|
Status: USER_STATUS_VISIBLE,
|
||
|
ToID: id,
|
||
|
}
|
||
|
_, exists := globalApp.ArrayBundle.UserShortcuts[id]
|
||
|
if !exists {
|
||
|
globalApp.ArrayBundle.UserShortcuts[id] = userStr
|
||
|
globalApp.ArrayBundle.UserShortcutsRev[userStr] = id
|
||
|
}
|
||
|
if selTab != globalApp.Tabs.ConnectionTab {
|
||
|
updateTabsBasedOnNotyVals(&globalApp.Tabs)
|
||
|
}
|
||
|
actionsChannel <- ACTION_UPDATE_USER_OPTS_CONTS
|
||
|
case com.ID_CLIENT_ASK_CLIENT_HANDSHAKE:
|
||
|
selTab := globalApp.Tabs.AppTabs.Selected()
|
||
|
id := msg.FromID
|
||
|
userStr := getStdUserName(id, string(msg.Data))
|
||
|
globalApp.Widgets.UsersSelect.Options = append(globalApp.Widgets.UsersSelect.Options, userStr)
|
||
|
globalApp.Tabs.ConnsNoty++
|
||
|
globalApp.ArrayBundle.UsersOpts[userStr] = &UserOptions{
|
||
|
Status: USER_STATUS_HANDSHAKE_INIT,
|
||
|
ToID: id,
|
||
|
}
|
||
|
_, exists := globalApp.ArrayBundle.UserShortcuts[id]
|
||
|
if !exists {
|
||
|
globalApp.ArrayBundle.UserShortcuts[id] = userStr
|
||
|
globalApp.ArrayBundle.UserShortcutsRev[userStr] = id
|
||
|
}
|
||
|
if selTab != globalApp.Tabs.ConnectionTab {
|
||
|
updateTabsBasedOnNotyVals(&globalApp.Tabs)
|
||
|
}
|
||
|
actionsChannel <- ACTION_UPDATE_USER_OPTS_CONTS
|
||
|
case com.ID_CLIENT_APPROVE_CLIENT_HANDSHAKE:
|
||
|
id := msg.FromID
|
||
|
userStr := getStdUserName(id, string(msg.Data))
|
||
|
var shortcut string
|
||
|
val, exists := globalApp.ArrayBundle.UserShortcuts[id]
|
||
|
if !exists {
|
||
|
globalApp.ArrayBundle.UserShortcuts[id] = userStr
|
||
|
globalApp.ArrayBundle.UserShortcutsRev[userStr] = id
|
||
|
shortcut = userStr
|
||
|
} else {
|
||
|
shortcut = val
|
||
|
}
|
||
|
u, exists := globalApp.ArrayBundle.UsersOpts[shortcut]
|
||
|
if !exists {
|
||
|
log.Printf("WARNING!!: UserOpts[%s] NOT exists!", shortcut)
|
||
|
continue
|
||
|
}
|
||
|
u.Status = USER_STATUS_HANDSHAKE_ACCEPTED
|
||
|
actionsChannel <- ACTION_UPDATE_USER_OPTS_CONTS
|
||
|
case com.ID_CLIENT_SEND_CLIENT_ECDH_PUBKEY:
|
||
|
id := msg.FromID
|
||
|
if ecdhKeySent {
|
||
|
val, exists := globalApp.ArrayBundle.UserShortcuts[id]
|
||
|
if !exists {
|
||
|
log.Printf("WARNING!!: UserShortcuts[%d] NOT exists!", id)
|
||
|
continue
|
||
|
}
|
||
|
u, exists := globalApp.ArrayBundle.UsersOpts[val]
|
||
|
if !exists {
|
||
|
log.Printf("WARNING!!: UserOpts[%s] NOT exists!", val)
|
||
|
continue
|
||
|
}
|
||
|
u.Status = USER_STATUS_ECDH_ESTABLISHED
|
||
|
actionsChannel <- ACTION_UPDATE_USER_OPTS_CONTS
|
||
|
}
|
||
|
ecdhKeyReceived = true
|
||
|
case com.ID_CLIENT_SEND_CLIENT_CBES_SPECS:
|
||
|
id := msg.FromID
|
||
|
val, exists := globalApp.ArrayBundle.UserShortcuts[id]
|
||
|
if !exists {
|
||
|
log.Printf("WARNING!!: UserShortcuts[%d] NOT exists!", id)
|
||
|
continue
|
||
|
}
|
||
|
u, exists := globalApp.ArrayBundle.UsersOpts[val]
|
||
|
if !exists {
|
||
|
log.Printf("WARNING!!: UserOpts[%s] NOT exists!", val)
|
||
|
continue
|
||
|
}
|
||
|
u.Status = USER_STATUS_ECDH_CBES_ESTABLISHED
|
||
|
actionsChannel <- ACTION_UPDATE_USER_OPTS_CONTS
|
||
|
//
|
||
|
log.Printf("Checkin Messages tab")
|
||
|
userStr := getStdUserName(id, string(msg.Data))
|
||
|
var shortcut string
|
||
|
if !exists {
|
||
|
globalApp.ArrayBundle.UserShortcuts[id] = userStr
|
||
|
shortcut = userStr
|
||
|
} else {
|
||
|
shortcut = val
|
||
|
}
|
||
|
//
|
||
|
haveUser := false
|
||
|
for _, v := range globalApp.Widgets.MessagesSelect.Options {
|
||
|
if v == shortcut {
|
||
|
haveUser = true
|
||
|
break
|
||
|
}
|
||
|
}
|
||
|
log.Printf("MessagesSelect.Options1 are %v\n", globalApp.Widgets.MessagesSelect.Options)
|
||
|
log.Printf("have user is : %t\n", haveUser)
|
||
|
if !haveUser {
|
||
|
log.Printf("MessagesSelect.Options1.5 shortcut is '%s'\n", shortcut)
|
||
|
// LOL wtf
|
||
|
// globalApp.Widgets.MessagesSelect.Options = append(globalApp.Widgets.UsersSelect.Options, shortcut)
|
||
|
globalApp.Widgets.MessagesSelect.Options = append(globalApp.Widgets.MessagesSelect.Options, shortcut)
|
||
|
log.Printf("MessagesSelect.Options2 are %v\n", globalApp.Widgets.MessagesSelect.Options)
|
||
|
globalApp.Tabs.UsersNoty++
|
||
|
globalApp.Widgets.MessagesSelect.Refresh()
|
||
|
updateTabsBasedOnNotyVals(&globalApp.Tabs)
|
||
|
}
|
||
|
case com.ID_CLIENT_SEND_CLIENT_MESSAGE:
|
||
|
id := msg.FromID
|
||
|
shortcut, exists := globalApp.ArrayBundle.UserShortcuts[id]
|
||
|
if !exists {
|
||
|
log.Printf("WARNING: UserShortcuts[%d] NOT exists!", id)
|
||
|
continue
|
||
|
}
|
||
|
msgs, exists := globalApp.ArrayBundle.Messages[shortcut]
|
||
|
mBoardMsg := widgets.MBoardMessage{
|
||
|
LeftAlign: true,
|
||
|
Data: widget.NewLabel(string(msg.Data)),
|
||
|
}
|
||
|
if !exists {
|
||
|
tmp := CreateMutexArray[widgets.MBoardMessage]()
|
||
|
tmp.Add(mBoardMsg)
|
||
|
globalApp.ArrayBundle.Messages[shortcut] = &tmp
|
||
|
globalApp.Widgets.MBoardCaretacker.Refresh()
|
||
|
globalApp.Tabs.UsersTab.Content.Refresh()
|
||
|
} else {
|
||
|
msgs.Add(mBoardMsg)
|
||
|
globalApp.Widgets.MBoardCaretacker.Refresh()
|
||
|
globalApp.Tabs.UsersTab.Content.Refresh()
|
||
|
}
|
||
|
haveUser := false
|
||
|
for _, v := range globalApp.Widgets.MessagesSelect.Options {
|
||
|
if v == shortcut {
|
||
|
haveUser = true
|
||
|
break
|
||
|
}
|
||
|
}
|
||
|
if !haveUser {
|
||
|
globalApp.Widgets.MessagesSelect.Options = append(globalApp.Widgets.MessagesSelect.Options, shortcut)
|
||
|
globalApp.Tabs.UsersNoty++
|
||
|
updateTabsBasedOnNotyVals(&globalApp.Tabs)
|
||
|
globalApp.Widgets.MessagesSelect.Refresh()
|
||
|
}
|
||
|
//
|
||
|
mBoard, exists := globalApp.Widgets.MBoardMap[shortcut]
|
||
|
if exists {
|
||
|
mBoard.Add(mBoardMsg)
|
||
|
}
|
||
|
// TODO
|
||
|
default:
|
||
|
log.Printf("Can not handle msg with id %d", msg.ID)
|
||
|
log.Printf("Msg is different : %v", *msg)
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
func actOnActions(cfg FyneConfig, actionsChannel chan int, intercomToServer chan *com.Message) {
|
||
|
for action := range actionsChannel {
|
||
|
log.Printf("Receive action %d", action)
|
||
|
switch action {
|
||
|
case ACTION_SET_SCENE_NICKNAME:
|
||
|
// cfg.Window.Content()
|
||
|
scene := GetNicknameScene(intercomToServer)
|
||
|
cfg.Window.Resize(fyne.NewSize(640, 400))
|
||
|
cfg.Window.SetContent(scene)
|
||
|
case ACTION_SET_SCENE_MAIN:
|
||
|
scene, app := GetMainScene(intercomToServer, MainSceneConfig{
|
||
|
UserNickcname: tmpNick,
|
||
|
UserNameSet: true,
|
||
|
UserId: r.ID,
|
||
|
UserIdSet: true,
|
||
|
})
|
||
|
globalApp = app
|
||
|
globalApp.App.App = cfg.App
|
||
|
globalApp.App.Window = cfg.Window
|
||
|
// shortcuts
|
||
|
ctrl1 := &desktop.CustomShortcut{KeyName: fyne.Key1, Modifier: fyne.KeyModifierControl}
|
||
|
ctrl2 := &desktop.CustomShortcut{KeyName: fyne.Key2, Modifier: fyne.KeyModifierControl}
|
||
|
ctrl3 := &desktop.CustomShortcut{KeyName: fyne.Key3, Modifier: fyne.KeyModifierControl}
|
||
|
cfg.Window.Canvas().AddShortcut(ctrl1, func(shortcut fyne.Shortcut) {
|
||
|
app.Tabs.AppTabs.Select(app.Tabs.LinkTab)
|
||
|
})
|
||
|
cfg.Window.Canvas().AddShortcut(ctrl2, func(shortcut fyne.Shortcut) {
|
||
|
app.Tabs.AppTabs.Select(app.Tabs.ConnectionTab)
|
||
|
})
|
||
|
cfg.Window.Canvas().AddShortcut(ctrl3, func(shortcut fyne.Shortcut) {
|
||
|
app.Tabs.AppTabs.Select(app.Tabs.UsersTab)
|
||
|
})
|
||
|
// cfg.Window.Resize(fyne.NewSize(640, 400))
|
||
|
cfg.Window.SetContent(scene)
|
||
|
// ACTION_UPDATE_USER_OPTS_CONTS
|
||
|
case ACTION_UPDATE_USER_OPTS_CONTS:
|
||
|
for _, u := range globalApp.ArrayBundle.UsersOpts {
|
||
|
switch u.Status {
|
||
|
case USER_STATUS_VISIBLE:
|
||
|
btn := widget.NewButton("Init Handhake", func() {})
|
||
|
btn.OnTapped = func() {
|
||
|
intercomToServer <- &com.Message{
|
||
|
ID: com.ID_CLIENT_ASK_CLIENT_HANDSHAKE,
|
||
|
ToID: u.ToID,
|
||
|
}
|
||
|
btn.Hide()
|
||
|
}
|
||
|
u.OptsContainer = container.NewGridWithRows(1, btn)
|
||
|
cTaker := globalApp.Widgets.UserOptsCaretaker
|
||
|
cTaker.RemoveAll()
|
||
|
cTaker.Add(u.OptsContainer)
|
||
|
case USER_STATUS_HANDSHAKE_INIT:
|
||
|
btn := widget.NewButton("Accept Handhake", func() {})
|
||
|
btn.OnTapped = func() {
|
||
|
intercomToServer <- &com.Message{
|
||
|
ID: com.ID_CLIENT_APPROVE_CLIENT_HANDSHAKE,
|
||
|
ToID: u.ToID,
|
||
|
}
|
||
|
btn.Hide()
|
||
|
u.Status = USER_STATUS_HANDSHAKE_ACCEPTED
|
||
|
actionsChannel <- ACTION_UPDATE_USER_OPTS_CONTS
|
||
|
}
|
||
|
u.OptsContainer = container.NewGridWithRows(1, btn)
|
||
|
cTaker := globalApp.Widgets.UserOptsCaretaker
|
||
|
cTaker.RemoveAll()
|
||
|
cTaker.Add(u.OptsContainer)
|
||
|
case USER_STATUS_HANDSHAKE_ACCEPTED:
|
||
|
btn := widget.NewButton("Send ECDH PubKey", func() {})
|
||
|
btn.OnTapped = func() {
|
||
|
intercomToServer <- &com.Message{
|
||
|
ID: com.ID_CLIENT_SEND_CLIENT_ECDH_PUBKEY,
|
||
|
ToID: u.ToID,
|
||
|
}
|
||
|
btn.Hide()
|
||
|
if ecdhKeyReceived {
|
||
|
u.Status = USER_STATUS_ECDH_ESTABLISHED
|
||
|
actionsChannel <- ACTION_UPDATE_USER_OPTS_CONTS
|
||
|
}
|
||
|
ecdhKeySent = true
|
||
|
}
|
||
|
u.OptsContainer = container.NewGridWithRows(1, btn)
|
||
|
cTaker := globalApp.Widgets.UserOptsCaretaker
|
||
|
cTaker.RemoveAll()
|
||
|
cTaker.Add(u.OptsContainer)
|
||
|
case USER_STATUS_ECDH_ESTABLISHED:
|
||
|
btn := widget.NewButton("Send CBES Specs", func() {})
|
||
|
btn.OnTapped = func() {
|
||
|
intercomToServer <- &com.Message{
|
||
|
ID: com.ID_CLIENT_SEND_CLIENT_CBES_SPECS,
|
||
|
ToID: u.ToID,
|
||
|
}
|
||
|
btn.Hide()
|
||
|
}
|
||
|
u.OptsContainer = container.NewGridWithRows(1, btn)
|
||
|
cTaker := globalApp.Widgets.UserOptsCaretaker
|
||
|
cTaker.RemoveAll()
|
||
|
cTaker.Add(u.OptsContainer)
|
||
|
case USER_STATUS_ECDH_CBES_ESTABLISHED:
|
||
|
btn := widget.NewButton("TBC", func() {})
|
||
|
btn.OnTapped = func() {
|
||
|
log.Println("TODO:: 1001")
|
||
|
}
|
||
|
u.OptsContainer = container.NewGridWithRows(1, btn)
|
||
|
cTaker := globalApp.Widgets.UserOptsCaretaker
|
||
|
cTaker.RemoveAll()
|
||
|
cTaker.Add(u.OptsContainer)
|
||
|
default:
|
||
|
}
|
||
|
}
|
||
|
// globalApp.Tabs.ConnectionTab.Content.Refresh()
|
||
|
// ACTION_UPDATE_USER_OPTS_CONTS
|
||
|
default:
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
func readFromIntercom(intercom chan *com.Message, conn net.Conn) {
|
||
|
for msg := range intercom {
|
||
|
log.Printf("client: received message from Intercom: %v", msg)
|
||
|
msg.Version = com.V1
|
||
|
switch msg.ID {
|
||
|
case com.ID_CLIENT_SEND_SERVER_NICKNAME:
|
||
|
tmpNick = string(msg.Data)
|
||
|
case com.ID_CLIENT_SEND_SERVER_LINK:
|
||
|
if !r.IsRegistered {
|
||
|
continue
|
||
|
}
|
||
|
l, err := r.GenerateLink(msg.ToID)
|
||
|
if err != nil {
|
||
|
log.Printf("Error: link: %v", err)
|
||
|
continue
|
||
|
}
|
||
|
tmpLink = &l
|
||
|
answ, err := com.ClientSendServerLink(r.ID, l)
|
||
|
if err != nil {
|
||
|
log.Printf("Error: com: %v", err)
|
||
|
continue
|
||
|
}
|
||
|
log.Printf("client: readWS: sending data to server: %v", answ)
|
||
|
conn.Write(answ)
|
||
|
continue
|
||
|
case com.ID_CLIENT_ASK_CLIENT_HANDSHAKE,
|
||
|
com.ID_CLIENT_APPROVE_CLIENT_HANDSHAKE,
|
||
|
com.ID_CLIENT_DECLINE_CLIENT_HANDSHAKE,
|
||
|
com.ID_CLIENT_SEND_CLIENT_ECDH_PUBKEY,
|
||
|
com.ID_CLIENT_SEND_CLIENT_CBES_SPECS,
|
||
|
com.ID_CLIENT_SEND_CLIENT_MKLG_FINGERPRINT,
|
||
|
com.ID_CLIENT_DECLINE_CLIENT_MKLG_FINGERPRINT,
|
||
|
com.ID_CLIENT_SEND_CLIENT_MESSAGE:
|
||
|
if !r.IsRegistered {
|
||
|
continue
|
||
|
}
|
||
|
msg.FromID = r.ID
|
||
|
// switch
|
||
|
}
|
||
|
// user stuff
|
||
|
switch msg.ID {
|
||
|
case com.ID_CLIENT_ASK_CLIENT_HANDSHAKE,
|
||
|
com.ID_CLIENT_APPROVE_CLIENT_HANDSHAKE:
|
||
|
if r.IsRegistered {
|
||
|
msg.Data = []byte(r.Name)
|
||
|
}
|
||
|
}
|
||
|
// Crypto stuff
|
||
|
switch msg.ID {
|
||
|
case com.ID_CLIENT_ASK_CLIENT_HANDSHAKE,
|
||
|
com.ID_CLIENT_APPROVE_CLIENT_HANDSHAKE:
|
||
|
err := tlepCenter.AddTLEP(msg.ToID, fmt.Sprintf("%s-%d", r.Name, msg.ToID))
|
||
|
if err != nil {
|
||
|
log.Printf("ERROR: tlepCenter.AddUser: %v\n", err)
|
||
|
}
|
||
|
case com.ID_CLIENT_SEND_CLIENT_ECDH_PUBKEY:
|
||
|
t, err := tlepCenter.GetTLEP(msg.ToID)
|
||
|
if err != nil {
|
||
|
log.Printf("ERROR: tlep: GetTLEP: %v\n", err)
|
||
|
continue
|
||
|
}
|
||
|
key, err := t.ECDHGetPublicKey()
|
||
|
if err != nil {
|
||
|
log.Printf("ERROR: tlep: ECDHGetPublicKey: %v\n", err)
|
||
|
continue
|
||
|
}
|
||
|
msg.Data = key
|
||
|
case com.ID_CLIENT_SEND_CLIENT_CBES_SPECS:
|
||
|
t, err := tlepCenter.GetTLEP(msg.ToID)
|
||
|
if err != nil {
|
||
|
log.Printf("ERROR: tlep: GetTLEP: %v\n", err)
|
||
|
continue
|
||
|
}
|
||
|
err = t.CBESInitRandom()
|
||
|
if err != nil {
|
||
|
log.Printf("ERROR: tlep: CBESInitRandom: %v\n", err)
|
||
|
continue
|
||
|
}
|
||
|
cbes, err := t.CBESGetBytes()
|
||
|
if err != nil {
|
||
|
log.Printf("ERROR: tlep: ECDHGetPublicKey: %v\n", err)
|
||
|
continue
|
||
|
}
|
||
|
cbesEAEncr, err := t.EncryptMessageEA(cbes)
|
||
|
if err != nil {
|
||
|
log.Printf("ERROR: tlep: EncryptMessageEA: %v\n", err)
|
||
|
continue
|
||
|
}
|
||
|
msg.Data = cbesEAEncr
|
||
|
// message
|
||
|
case com.ID_CLIENT_SEND_CLIENT_MESSAGE:
|
||
|
t, err := tlepCenter.GetTLEP(msg.ToID)
|
||
|
if err != nil {
|
||
|
log.Printf("ERROR: tlep: GetTLEP: %v\n", err)
|
||
|
continue
|
||
|
}
|
||
|
encrypedMsg, err := t.EncryptMessageAtMax(msg.Data)
|
||
|
if err != nil {
|
||
|
log.Printf("ERROR: tlep: EncryptMessageAtMax: %v\n", err)
|
||
|
continue
|
||
|
}
|
||
|
msg.Data = encrypedMsg
|
||
|
// switch
|
||
|
}
|
||
|
encodedMsg, err := msg.Bytes()
|
||
|
if err != nil {
|
||
|
log.Printf("Encoding error: %s", err)
|
||
|
continue
|
||
|
}
|
||
|
log.Printf("client: readWS: sending data to server: %v", encodedMsg)
|
||
|
conn.Write(encodedMsg)
|
||
|
}
|
||
|
}
|