Skip to content

Commit adf4be7

Browse files
committed
Implement auto restart of server, Print Apdu
1 parent 942bccd commit adf4be7

7 files changed

+147
-32
lines changed

apdu.go

+17
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ package vv104
33
import (
44
"bytes"
55
"errors"
6+
"fmt"
67
)
78

89
type Apdu struct {
@@ -26,6 +27,21 @@ func (apdu Apdu) CheckApdu() (bool, error) {
2627
return true, nil
2728
}
2829

30+
func (apdu Apdu) String() string {
31+
switch apdu.Apci.FrameFormat {
32+
33+
case IFormatFrame:
34+
fmt.Println("this is an i frame!")
35+
return apdu.Asdu.String()
36+
case SFormatFrame:
37+
return fmt.Sprintf("S-Format (%d/%d)\n", apdu.Apci.Rsn, apdu.Apci.Ssn)
38+
case UFormatFrame:
39+
return apdu.Apci.UFormat.String()
40+
41+
}
42+
return ""
43+
}
44+
2945
func (apdu *Apdu) Serialize(state State) []byte {
3046
asduBuf := new(bytes.Buffer)
3147
apciBuf := new(bytes.Buffer)
@@ -101,6 +117,7 @@ func ParseApdu(buf *bytes.Buffer) (Apdu, error) {
101117

102118
// ctrl field 1
103119
b, _ = buf.ReadByte()
120+
fmt.Println("byte ctrl field 1:", b)
104121
if (b & 0b0000_0001) == 0b0000_0000 {
105122
// i frame
106123
apdu.Apci.FrameFormat = IFormatFrame

cmd/main.go

-2
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,6 @@ func main() {
1111
state := vv104.NewState()
1212
state.Start()
1313

14-
fmt.Println(state)
15-
1614
fmt.Println("vv140 finished.")
1715
}
1816

connection.go

+54-19
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package vv104
22

33
import (
4+
"bytes"
45
"fmt"
56
"net"
67
"time"
@@ -19,24 +20,52 @@ func (state *State) startConnection() {
1920
}
2021

2122
func (state *State) startServer() {
23+
fmt.Println("startServer started")
24+
defer fmt.Println("startServer returned")
25+
2226
var err error
23-
var l net.Listener
24-
ipAndPort := state.Config.Ipv4Addr + ":" + fmt.Sprint(state.Config.Port)
25-
l, err = net.Listen("tcp", ipAndPort)
27+
28+
ipAndPortStr := state.Config.Ipv4Addr + ":" + fmt.Sprint(state.Config.Port)
29+
ipAndPort, err := net.ResolveTCPAddr("tcp", ipAndPortStr)
30+
if err != nil {
31+
panic(err)
32+
}
33+
34+
var l *net.TCPListener
35+
l, err = net.ListenTCP("tcp", ipAndPort)
36+
l.SetDeadline(time.Now().Add(2 * time.Second))
37+
defer l.Close()
38+
2639
if err != nil {
2740
panic(err)
2841
}
2942

30-
// state.wg.Add(1)
43+
state.wg.Add(1)
44+
defer state.wg.Done()
45+
3146
for {
32-
conn, err := l.Accept()
33-
if err != nil {
34-
fmt.Println(err)
35-
time.Sleep(time.Second * 2)
36-
continue
47+
select {
48+
default:
49+
50+
conn, err := l.Accept()
51+
if err != nil {
52+
if err, ok := err.(*net.OpError); ok && err.Timeout() {
53+
// it was a timeout
54+
}
55+
// other problem
56+
fmt.Println(err)
57+
continue
58+
}
59+
fmt.Println("Connected from: ", conn.RemoteAddr())
60+
go state.handleConnection(conn)
61+
62+
<-state.ctx.Done() // todo? other criteria?
63+
return
64+
65+
case <-state.ctx.Done():
66+
fmt.Println("startServer received Done(), returns")
67+
return
3768
}
38-
fmt.Println("Connected from: ", conn.RemoteAddr())
39-
go state.handleConnection(conn)
4069
}
4170

4271
}
@@ -46,16 +75,14 @@ func (state *State) startClient() {
4675
}
4776

4877
func (state *State) handleConnection(conn net.Conn) {
78+
fmt.Println("handleConnection started")
79+
defer fmt.Println("handleConnection returned")
4980
defer conn.Close()
50-
81+
var bytesbuf bytes.Buffer
5182
buf := make([]byte, 256) // todo: read whole tcp frame
5283
state.wg.Add(1)
5384
defer state.wg.Done()
5485

55-
// err := conn.SetReadDeadline(time.Now().Add(3 * time.Second))
56-
// if err != nil {
57-
// panic(err)
58-
// }
5986
for {
6087
select {
6188

@@ -71,14 +98,22 @@ func (state *State) handleConnection(conn net.Conn) {
7198
continue
7299
}
73100
fmt.Println("Error reading:", err.Error())
74-
fmt.Println("Restart because of error reading")
101+
fmt.Println("Restart because of error reading, handleConnection returns")
75102
state.cancel()
76103
return
77104
}
78-
fmt.Println(buf[:recvLen])
105+
106+
bytesbuf.Write(buf[:recvLen]) // Read from conn directly into bytesbuf?
107+
fmt.Println(bytesbuf)
108+
apdu, err := ParseApdu(&bytesbuf)
109+
if err != nil {
110+
fmt.Println("error parsing:", err)
111+
} else {
112+
fmt.Println("<<RX:", apdu)
113+
}
79114

80115
case <-state.ctx.Done():
81-
fmt.Println("handleConnection received Done(), quitting")
116+
fmt.Println("handleConnection received Done(), returns")
82117
return
83118
}
84119
}

iec104Constants.go

+2
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,8 @@ const (
2424
type UFormat byte
2525

2626
// U-Format types
27+
//
28+
//go:generate stringer -type=UFormat
2729
const (
2830
StartDTAct UFormat = 0x07
2931
StartDTCon UFormat = 0x0b

interactive_control.go

+2-2
Original file line numberDiff line numberDiff line change
@@ -5,10 +5,10 @@ import (
55
"os"
66
)
77

8-
func (state *State) readCommandsFromStdIn() {
8+
func readCommandsFromStdIn(fromStdInchan chan string) {
99
sc := bufio.NewScanner(os.Stdin)
1010

1111
for sc.Scan() {
12-
state.chans.commandsFromStdin <- sc.Text()
12+
fromStdInchan <- sc.Text()
1313
}
1414
}

state.go

+27-9
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import (
44
"context"
55
"fmt"
66
"sync"
7+
"time"
78
)
89

910
type State struct {
@@ -24,7 +25,6 @@ type AllChans struct {
2425
commandsFromStdin chan string
2526
received chan Apdu
2627
toSend chan Apdu
27-
quit chan bool
2828
}
2929

3030
const (
@@ -63,16 +63,34 @@ func NewState() State {
6363
func (state *State) Start() {
6464
state.Config.ParseFlags()
6565
state.chans.commandsFromStdin = make(chan string, 30)
66-
state.chans.received = make(chan Apdu, state.Config.W)
67-
state.chans.toSend = make(chan Apdu, state.Config.K)
68-
state.ctx, state.cancel = context.WithCancel(context.Background())
66+
go readCommandsFromStdIn(state.chans.commandsFromStdin) // never exits
6967

70-
go state.readCommandsFromStdIn()
71-
go state.startConnection()
68+
for {
69+
state.chans.received = make(chan Apdu, state.Config.W)
70+
state.chans.toSend = make(chan Apdu, state.Config.K)
71+
state.ctx, state.cancel = context.WithCancel(context.Background())
72+
go state.startConnection()
73+
74+
select {
75+
case input := <-state.chans.commandsFromStdin:
76+
77+
if input == "exit" {
78+
fmt.Println("called exit")
79+
state.cancel()
80+
state.wg.Wait()
81+
fmt.Println("Start() exited")
82+
return
83+
}
84+
85+
case <-state.ctx.Done():
86+
state.wg.Wait()
87+
fmt.Println("Restart!")
88+
time.Sleep(1500 * time.Millisecond)
89+
continue
90+
91+
}
92+
}
7293

73-
// state.wg.Wait()
74-
<-state.chans.quit
75-
fmt.Println("Start() exited")
7694
}
7795

7896
func incrementSeqNumber(seqNumber SeqNumber) SeqNumber {

uformat_string.go

+45
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)