blob: 1d70e03fd94e1faad448e16b11a80cedc61f1193 [file] [log] [blame]
giolekva313ee2b2021-12-15 15:17:29 +04001package main
2
3import (
giolekvaf58a7692021-12-15 18:05:39 +04004 "bytes"
5 "encoding/json"
giolekva313ee2b2021-12-15 15:17:29 +04006 "flag"
7 "fmt"
giolekvaf58a7692021-12-15 18:05:39 +04008 "image"
9 "image/png"
giolekva313ee2b2021-12-15 15:17:29 +040010
11 "gioui.org/app"
12 "gioui.org/io/system"
13 "gioui.org/layout"
14 "gioui.org/op"
15 "gioui.org/unit"
giolekvaf58a7692021-12-15 18:05:39 +040016 "github.com/skip2/go-qrcode"
giolekva313ee2b2021-12-15 15:17:29 +040017)
18
giolekvaf58a7692021-12-15 18:05:39 +040019var vpnApiAddr = flag.String("vpn-api-addr", "", "VPN API server address")
giolekva313ee2b2021-12-15 15:17:29 +040020
giolekvaf58a7692021-12-15 18:05:39 +040021var p *processor
22
23type processor struct {
24 vc VPNClient
25 app App
26 ui *UI
27
28 inviteQrCh chan image.Image
29 inviteQrScannedCh chan []byte
giolekva313ee2b2021-12-15 15:17:29 +040030}
31
giolekvaf58a7692021-12-15 18:05:39 +040032func newProcessor() *processor {
33 return &processor{
34 vc: NewDirectVPNClient(*vpnApiAddr),
35 app: createApp(),
36 ui: NewUI(),
37 inviteQrCh: make(chan image.Image, 1),
38 inviteQrScannedCh: make(chan []byte, 1),
39 }
40}
41
42func (p *processor) InviteQRCodeScanned(code []byte) {
43 p.inviteQrScannedCh <- code
44}
45
46func (p *processor) run() error {
giolekva313ee2b2021-12-15 15:17:29 +040047 w := app.NewWindow(
48 app.Size(unit.Px(1500), unit.Px(1500)),
49 app.Title("PCloud"),
50 )
51 var ops op.Ops
52 for {
53 select {
54 case e := <-w.Events():
55 switch e := e.(type) {
56 case app.ViewEvent:
giolekvaf58a7692021-12-15 18:05:39 +040057 if err := p.app.OnView(e); err != nil {
giolekva313ee2b2021-12-15 15:17:29 +040058 return err
59 } else {
60 w.Invalidate()
61 }
62 case *system.CommandEvent:
63 if e.Type == system.CommandBack {
giolekvaf58a7692021-12-15 18:05:39 +040064 if p.ui.OnBack() {
giolekva313ee2b2021-12-15 15:17:29 +040065 e.Cancel = true
66 w.Invalidate()
67 }
68 }
69 case system.FrameEvent:
70 gtx := layout.NewContext(&ops, e)
giolekvaf58a7692021-12-15 18:05:39 +040071 events := p.ui.Layout(gtx)
giolekva313ee2b2021-12-15 15:17:29 +040072 e.Frame(&ops)
giolekvaf58a7692021-12-15 18:05:39 +040073 if err := p.processUIEvents(events); err != nil {
giolekva313ee2b2021-12-15 15:17:29 +040074 return err
75 }
76 }
giolekvaf58a7692021-12-15 18:05:39 +040077 case img := <-p.inviteQrCh:
78 p.ui.InviteQRGenerated(img)
79 w.Invalidate()
80 case code := <-p.inviteQrScannedCh:
81 go func() {
82 p.JoinNetworkAndConnect(code)
83 }()
giolekva313ee2b2021-12-15 15:17:29 +040084 }
85 }
86 return nil
87}
88
giolekvaf58a7692021-12-15 18:05:39 +040089func (p *processor) processUIEvents(events []UIEvent) error {
90 for _, e := range events {
91 switch e.(type) {
92 case EventGetInviteQRCode:
93 go func() {
94 if img, err := p.generateInviteQRCode(); err == nil {
95 p.inviteQrCh <- img
96 } else {
97 // TODO(giolekva): do not panic
98 panic(err)
99 }
100 }()
101 case EventScanBarcode:
102 return p.app.LaunchBarcodeScanner()
103 default:
104 return fmt.Errorf("Unhandled event: %#v", e)
105 }
106 }
107 return nil
108}
109
110type qrCodeData struct {
111 VPNApiAddr string `json:"vpn_api_addr"`
112 Message []byte `json:"message"`
113 Signature []byte `json:"signature"`
114}
115
116func (p *processor) generateInviteQRCode() (image.Image, error) {
117 message := []byte("Hello PCloud")
118 signature, err := p.vc.Sign(message)
119 if err != nil {
120 return nil, err
121 }
122 c := qrCodeData{
123 p.vc.Address(),
124 message,
125 signature,
126 }
127 var data bytes.Buffer
128 if err := json.NewEncoder(&data).Encode(c); err != nil {
129 return nil, err
130 }
131 qr, err := qrcode.Encode(data.String(), qrcode.Medium, 1024)
132 if err != nil {
133 return nil, err
134 }
135 img, err := png.Decode(bytes.NewReader(qr))
136 if err != nil {
137 return nil, err
138 }
139 return img, nil
140}
141
142func (p *processor) JoinNetworkAndConnect(code []byte) {
143 var invite qrCodeData
144 if err := json.NewDecoder(bytes.NewReader(code)).Decode(&invite); err != nil {
145 panic(err)
146 }
147 config, err := p.vc.Join(invite.VPNApiAddr, invite.Message, invite.Signature)
148 if err != nil {
149 panic(err)
150 }
giolekvacc3ebcb2021-12-17 10:52:17 +0400151 fmt.Printf("-- VPN CONFIG %s\n", string(config))
giolekvaf58a7692021-12-15 18:05:39 +0400152
153}
154
giolekva313ee2b2021-12-15 15:17:29 +0400155func main() {
156 flag.Parse()
giolekvaf58a7692021-12-15 18:05:39 +0400157 p = newProcessor()
giolekva313ee2b2021-12-15 15:17:29 +0400158 go func() {
giolekvaf58a7692021-12-15 18:05:39 +0400159 if err := p.run(); err != nil {
giolekva313ee2b2021-12-15 15:17:29 +0400160 panic(err)
161 }
162 }()
163 app.Main()
164}
giolekvacc3ebcb2021-12-17 10:52:17 +0400165
166// fmt.Println(m["pki"])
167// c := nc.NewC(logrus.StandardLogger())
168// if err := c.LoadString(string(tmpl)); err != nil {
169// return nil, err
170// }
171// fmt.Println(c.Settings["pki"])
172// return c, nil