From 3479b3dbacceeb2fdc7591bdb150c10e31299ba4 Mon Sep 17 00:00:00 2001 From: Dimitri Sokolyuk Date: Fri, 9 Oct 2015 19:41:46 +0200 Subject: First real communication --- acse/acse.go | 21 ++++++++++++++ csta/system-status.go | 2 ++ kxtde/main.go | 79 +++++++++++++++++++++++++++++++++++++++++++++++++++ parse/packets.go | 18 ++++++++++++ parse/parse.go | 37 ++++++++++++++++-------- rose/rose.go | 34 ++++++++++++++++++---- 6 files changed, 174 insertions(+), 17 deletions(-) create mode 100644 kxtde/main.go diff --git a/acse/acse.go b/acse/acse.go index 2552710..5fb1786 100644 --- a/acse/acse.go +++ b/acse/acse.go @@ -46,6 +46,12 @@ type RLRE struct { asn1.Tag `asn1:"application,tag:3"` } +// ABRT Source +const ( + ABRTServiceUser = iota + ABRTServiceProvider +) + // A-ABORT // Application Constructed implicit 4 type ABRT struct { @@ -89,3 +95,18 @@ func Associate() ([]byte, error) { } return asn1.Marshal(aarq) } + +const ( + AssociateResultAccepted = iota + AssociateResultRejectedPermanent + AssociateResultRejectedTransient +) + +func AssociateResult(b []byte) (int, error) { + aare := AARE{} + _, err := asn1.Unmarshal(b, &aare) + if err != nil { + return 0, err + } + return aare.Result, nil +} diff --git a/csta/system-status.go b/csta/system-status.go index 1953d7b..9e0ea22 100644 --- a/csta/system-status.go +++ b/csta/system-status.go @@ -2,6 +2,8 @@ package csta import "github.com/dim13/asn1" +const SystemStatusOpcode = 211 + const ( SystemStatusInitializing asn1.Enumerated = iota SystemStatusEnabled diff --git a/kxtde/main.go b/kxtde/main.go new file mode 100644 index 0000000..98e5038 --- /dev/null +++ b/kxtde/main.go @@ -0,0 +1,79 @@ +package main + +import ( + "flag" + "log" + + "dim13.org/asn1/acse" + "dim13.org/asn1/csta" + "dim13.org/asn1/rose" + "dim13.org/asn1/spdu" + + "github.com/dim13/asn1" +) + +var pbx = flag.String("pbx", "192.168.240.20:33333", "PBX CTI Service") + +const ( + AARQ = 0x60 + AARE = 0x61 + RLRQ = 0x62 + RLRE = 0x63 + ABRT = 0x64 + Invoke = 0xa1 + Result = 0xa2 +) + +func main() { + conn, err := spdu.Dial(*pbx) + if err != nil { + log.Fatal(err) + } + defer conn.Close() + + aare, _ := acse.Associate() + conn.Write(aare) + + var connected bool + for { + buf, err := spdu.ReadAll(conn) + if err != nil { + log.Fatal(err) + } + switch buf[0] { + case AARQ: + case AARE: + result, _ := acse.AssociateResult(buf) + connected = result == acse.AssociateResultAccepted + case RLRQ: + case RLRE: + case ABRT: + case Invoke: + id, opcode, payload, err := rose.Unmarshal(buf) + if err != nil { + log.Fatal(err) + } + switch opcode { + case csta.SystemStatusOpcode: + ss := &csta.SystemStatusArg{} + _, err := asn1.Unmarshal(payload, ss) + if err != nil { + log.Fatal(err) + } + log.Println(id, "System Status", ss.SystemStatus) + null, _ := asn1.Marshal(asn1.Null{}) + res, err := rose.Marshal(id, opcode, null) + if err != nil { + log.Fatal(err) + } + conn.Write(res) + default: + log.Println("Opcode", opcode, payload) + } + case Result: + } + if !connected { + log.Fatal("EOT") + } + } +} diff --git a/parse/packets.go b/parse/packets.go index 917ae19..80e6f67 100644 --- a/parse/packets.go +++ b/parse/packets.go @@ -182,6 +182,24 @@ var session = [][]byte{ 0x08, 0x30, 0x06, 0x81, 0x04, 0x01, 0x31, 0x00, 0x01, }, + { // AARQ + 0x61, 0x2F, 0x80, 0x02, 0x07, 0x80, 0xA1, 0x07, + 0x06, 0x05, 0x2B, 0x0C, 0x00, 0x81, 0x5A, 0xA2, + 0x03, 0x02, 0x01, 0x00, 0xA3, 0x05, 0xA1, 0x03, + 0x02, 0x01, 0x01, 0xBE, 0x14, 0x28, 0x12, 0x06, + 0x07, 0x2B, 0x0C, 0x00, 0x82, 0x1D, 0x81, 0x48, + 0xA0, 0x07, 0xA0, 0x05, 0x03, 0x03, 0x00, 0x08, + 0x00, + }, + { // AARE + 0x61, 0x19, 0x80, 0x02, 0x07, 0x80, 0xA1, 0x07, + 0x06, 0x05, 0x2B, 0x0C, 0x00, 0x81, 0x5A, 0xA2, + 0x03, 0x02, 0x01, 0x01, 0xA3, 0x05, 0xA1, 0x03, + 0x02, 0x01, 0x01, + }, + { // ABRT + 0x64, 0x03, 0x80, 0x01, 0x00, + }, } var ( diff --git a/parse/parse.go b/parse/parse.go index f128440..3d74e58 100644 --- a/parse/parse.go +++ b/parse/parse.go @@ -37,30 +37,43 @@ func main() { //fmt.Println(ber.Dump(s)) switch s[0] { case 0xa1: - v := &rose.Invoke{} - unmarshal(s, v) - if v.Opcode == 211 { + id, opcode, buf, err := rose.Unmarshal(s) + if err != nil { + fmt.Println(err) + } + if opcode == csta.SystemStatusOpcode { ss := &csta.SystemStatusArg{} - unmarshal(v.RawValue.FullBytes, ss) - fmt.Println(ss.SystemStatus) + asn1.Unmarshal(buf, ss) + fmt.Println("Status", ss.SystemStatus) + null, _ := asn1.Marshal(asn1.Null{}) + res, err := rose.Marshal(id, opcode, null) + if err != nil { + fmt.Println(err) + } + fmt.Printf("%x\n", s) + fmt.Printf("%x\n", res) + } else { + unmarshal(s, &rose.Invoke{}) } case 0xa2: - v := &rose.ReturnResult{} - unmarshal(s, v) - if v.Result.Opcode == 211 { - ss := &csta.SystemStatusRes{} - unmarshal(v.Result.RawValue.FullBytes, ss) - } + unmarshal(s, &rose.ReturnResult{}) case 0x60: unmarshal(s, &acse.AARQ{}) + a, _ := acse.Associate() + fmt.Printf("%x\n", s) + fmt.Printf("%x\n", a) case 0x61: unmarshal(s, &acse.AARE{}) + reason, _ := acse.AssociateResult(s) + fmt.Println("Reason", reason) case 0x62: unmarshal(s, &acse.RLRQ{}) case 0x63: unmarshal(s, &acse.RLRE{}) case 0x64: - unmarshal(s, &acse.ABRT{}) + a := &acse.ABRT{} + unmarshal(s, a) + fmt.Println(a) } } diff --git a/rose/rose.go b/rose/rose.go index 27365cd..1e670cc 100644 --- a/rose/rose.go +++ b/rose/rose.go @@ -7,7 +7,12 @@ import "github.com/dim13/asn1" // Invoke is Context-specific Constructed 1 type Invoke struct { asn1.Tag `asn1:"tag:1"` - InvokeId int + InvokeID int + Opcode int `asn1:"optional"` + asn1.RawValue `asn1:"optional"` +} + +type Result struct { Opcode int `asn1:"optional"` asn1.RawValue `asn1:"optional"` } @@ -15,9 +20,28 @@ type Invoke struct { // ReturnResult it Context-specific Constructed 2 type ReturnResult struct { asn1.Tag `asn1:"tag:2"` - InvokeId int - Result struct { - Opcode int `asn1:"optional"` - asn1.RawValue `asn1:"optional"` + InvokeID int + Result `asn1:"optional,expicit"` +} + +func Unmarshal(b []byte) (int, int, []byte, error) { + v := &Invoke{} + _, err := asn1.Unmarshal(b, v) + if err != nil { + return 0, 0, nil, err + } + return v.InvokeID, v.Opcode, v.RawValue.FullBytes, nil +} + +func Marshal(id, opcode int, b []byte) ([]byte, error) { + v := ReturnResult{ + InvokeID: id, + Result: Result{ + Opcode: opcode, + RawValue: asn1.RawValue{ + FullBytes: b, + }, + }, } + return asn1.Marshal(v) } -- cgit v1.2.3