Skip to content

Commit

Permalink
Merge pull request #55 from UlfBj/master
Browse files Browse the repository at this point in the history
Protobuf encoding cleanup
  • Loading branch information
UlfBj authored Nov 21, 2024
2 parents 69ee97e + 3629dfd commit b3a0315
Show file tree
Hide file tree
Showing 19 changed files with 155 additions and 1,083 deletions.
22 changes: 11 additions & 11 deletions client/client-1.0/Javascript/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
# Project: WAII: client/client-1.0

Client implementations for communication with the server found at the server/server-1.0 directory.<br>
The functionality in the W3C VISS v2 specs shall be supported, with features such as:<br>
The functionality in the VISS specs shall be supported, with features such as:<br>
HTTP and WebSockets transport protocols<br>
-- Queries<br>
-- Access control <br><br>
Expand All @@ -23,13 +23,13 @@ Current limitations: <br>
- Set requests do not lead to an update with the provided value.<br>

The available clients are:<br>
- httpclient.html // uses the HTTP protocol to communicate with the W3C VISS v2 server. Payload encoding not invoked.<br>
- wsclient_uncompressed.html // uses the Websocket protocol to communicate with the W3C VISS v2 server. Payload encoding not invoked.<br>
- wsclient_compressed.html // uses the Websocket protocol to communicate with the W3C VISS v2 server. Payload encoding invoked.<br>
- httpclient.html // uses the HTTP protocol to communicate with the VISS server. Payload encoding not invoked.<br>
- wsclient.html // uses the Websocket protocol to communicate with the VISS server. Payload encoding not invoked.<br>
- wsclient_protoencode.html // uses the Websocket protocol to communicate with the VISS server. Protobuf payload encoding invoked.<br>
- agtclient.html // uses the Websocket protocol to communicate with the Access Grant server.<br>
- atclient.html // uses the Websocket protocol to communicate with the Access token server.<br>

The appclient_commands.txt file contains some example payloads that a client may use. Depending on the VSS tree used by the W3C VISS v2 server,
The appclient_commands.txt file contains some example payloads that a client may use. Depending on the VSS tree used by the VISS server,
the paths used in the examples may not address existing nodes in the tree.

## Build instructions:
Expand All @@ -45,11 +45,11 @@ After the server URL is set, then requests can be issued to the server. <br>
For request examples, see the file appclient_commands.txt that contains request examples for both Websockets and HTTP transport protocols. <br>
The VSS paths shown in the examples can be replaced by any path that the VSS tree at the VSS Github project supports (https://github.com/GENIVI/vehicle_signal_specification). <br><br>

The W3C VISS v2 access control model describes two authorization servers, the Access Grant Token (AGT) server, and the Access Token (AT) server. <br>
To obtain an Access Grant token the agtclient.html can be used. The IP address is the same as for the W3C VISS v2 server, the path is "agtserver",<br>
The VISS access control model describes two authorization servers, the Access Grant Token (AGT) server, and the Access Token (AT) server. <br>
To obtain an Access Grant token the agtclient.html can be used. The IP address is the same as for the VISS server, the path is "agtserver",<br>
and the request to the agtserver must be a JSON formatted message with the following format<br>
{"vin":"XXX", "context":"Independent+OEM+Cloud", "proof":"ABC", "key":"DEF"}<br>
where the "vin" value can be replaced by any (fictious) VIN number, the "context" value with any role triplet that the W3C VISS v2 spec supports,
where the "vin" value can be replaced by any (fictious) VIN number, the "context" value with any role triplet that the VISS spec supports,
the "proof" value with anything as authentication is not implemented.<br>
If a "key" parameter is included, to initiate a Long Term Flow, it may have any value as it is currently not used.<br>
The response contains the Access Grant Token, that is used as input in the following request to the AT server.<br>
Expand All @@ -58,10 +58,10 @@ To issue this request, the atclient.html can be opened in a browser, input the s
where the "token" value is the token received from the AGT server,
the "purpose" value must be a short name on the Purpose list (where only "fuel-status" is available as an example).<br>
The "pop" parameter shall only be included if a "key" parameter was included in the AGT request, the value can be anything as it is currently not used.<br>
If the AGT token is verified as valid, which it should be if it comes from the AGT server, the response contains the AT token that can then be used in requests to the W3C VISS v2 server.<br><br>
The access control model implements the Access control selection model described in the W3C VISS v2 specification,so to enable testing of access control, the VSS tree must be updated with access control metadata. This is done by adding the key-value pair "validate:X" to a node in a vspec file,
If the AGT token is verified as valid, which it should be if it comes from the AGT server, the response contains the AT token that can then be used in requests to the VISS server.<br><br>
The access control model implements the Access control selection model described in the VISS specification,so to enable testing of access control, the VSS tree must be updated with access control metadata. This is done by adding the key-value pair "validate:X" to a node in a vspec file,
where X must be either "write-only" or "read-write".
This can be inserted into any node, also branch nodes, in which case the access control is inherited by all nodes being descendants of that node.<br>
E.g if in the branch node "Body" the metadata "validate:read-write" is inserted, then all signals in the subtree having "Vehicle.Body" as the root will require a token with ReadWrite scope for any read or write requests.<br>
Please see the <a href="https://github.com/w3c/automotive/blob/gh-pages/spec/Gen2_Core.html">W3C W3C VISS v2 CORE spec, Access Control chapter</a> for more info.
Please see the <a href="https://github.com/COVESA/vehicle-information-service-specification">COVESA VISS CORE spec, Access Control chapter</a> for more info.

File renamed without changes.
99 changes: 0 additions & 99 deletions client/client-1.0/Javascript/wsclient_compressed.html

This file was deleted.

3 changes: 1 addition & 2 deletions client/client-1.0/compress_client/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,7 @@ Arguments:
-h --help Print help information
-v --vissv2Url IP/url to VISSv2 server
-p --protocol Protocol must be either http or websocket. Default: ws
-c --compression Compression must be either proprietary or protobuf level 1
or 2. Default: pbl1
-c --compression Compression must be either none or protobuf. Default: proto
--logfile outputs to logfile in ./logs folder
--loglevel changes log output level. Default: info
</pre>
Expand Down
60 changes: 12 additions & 48 deletions client/client-1.0/compress_client/compress_client.go
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,9 @@ func createListFromFile(fname string) int {
}

func initVissV2WebSocket(compression string) *websocket.Conn {
if compression == "proto" {
compression = "protoenc"
}
scheme := "ws"
portNum := "8080"
if secConfig.TransportSec == "yes" {
Expand All @@ -104,7 +107,7 @@ func initVissV2WebSocket(compression string) *websocket.Conn {
var addr = flag.String("addr", vissv2Url+":"+portNum, "http service address")
dataSessionUrl := url.URL{Scheme: scheme, Host: *addr, Path: ""}
subProtocol := make([]string, 1)
subProtocol[0] = "VISSv2" + compression
subProtocol[0] = "VISS-" + compression
dialer := websocket.Dialer{
HandshakeTimeout: time.Second,
ReadBufferSize: 1024,
Expand Down Expand Up @@ -135,40 +138,10 @@ func getResponse(conn *websocket.Conn, request []byte) []byte {

func performCommand(commandNumber int, conn *websocket.Conn, optionChannel chan string) {
fmt.Printf("Request: %s\n", requestList.Request[commandNumber])
if compression != "prop" {
if compression == "proto" {
performPbCommand(commandNumber, conn, optionChannel)
} else {
compressedRequest := utils.CompressMessage([]byte(requestList.Request[commandNumber]))
fmt.Printf("JSON request size= %d, Compressed request size=%d\n", len(requestList.Request[commandNumber]), len(compressedRequest))
fmt.Printf("Compression= %d%\n", (100*len(requestList.Request[commandNumber]))/len(compressedRequest))
compressedResponse := getResponse(conn, compressedRequest)
jsonResponse := string(utils.DecompressMessage([]byte(compressedResponse)))
fmt.Printf("Response: %s\n", jsonResponse)
fmt.Printf("JSON response size= %d, Compressed response size=%d\n", len(jsonResponse), len(compressedResponse))
fmt.Printf("Compression= %d%\n", (100*len(jsonResponse))/len(compressedResponse))
if strings.Contains(requestList.Request[commandNumber], "subscribe") == true {
for {
_, msg, err := conn.ReadMessage()
if err != nil {
fmt.Printf("Notification error: %s\n", err)
return
}
jsonNotification := string(utils.DecompressMessage(msg))
fmt.Printf("Notification: %s\n", jsonNotification)
fmt.Printf("JSON notification size= %d, Compressed notification size=%d\n", len(jsonNotification), len(msg))
fmt.Printf("Compression= %d%\n", (100*len(jsonNotification))/len(msg))
select {
case <-optionChannel:
// issue unsubscribe request
subscriptionId := utils.ExtractSubscriptionId(jsonResponse)
unsubReq := `{"action":"unsubscribe", "subscriptionId":"` + subscriptionId + `"}`
compressedUnsubReq := utils.CompressMessage([]byte(unsubReq))
getResponse(conn, compressedUnsubReq)
return
default:
}
}
}
fmt.Printf("This client does currently not support No encoding\n")
}
}

Expand Down Expand Up @@ -206,14 +179,10 @@ func performPbCommand(commandNumber int, conn *websocket.Conn, optionChannel cha
}
}

func convertToCompression(compression string) utils.Compression {
switch compression {
case "prop":
return utils.PROPRIETARY
case "pbl1":
return utils.PB_LEVEL1
case "pbl2":
return utils.PB_LEVEL2
func convertToCompression(encoding string) utils.Encoding {
switch encoding {
case "proto":
return utils.PROTOBUF
}
return utils.NONE
}
Expand Down Expand Up @@ -243,8 +212,8 @@ func main() {
url_vissv2 := parser.String("v", "vissv2Url", &argparse.Options{Required: true, Help: "IP/url to VISSv2 server"})
prot := parser.Selector("p", "protocol", []string{"http", "ws"}, &argparse.Options{Required: false,
Help: "Protocol must be either http or websocket", Default: "ws"})
comp := parser.Selector("c", "compression", []string{"prop", "pbl1", "pbl2"}, &argparse.Options{Required: false,
Help: "Compression must be either proprietary or protobuf level 1 or 2", Default: "pbl1"})
comp := parser.Selector("c", "compression", []string{"none", "proto"}, &argparse.Options{Required: false,
Help: "Compression must be either none or protobuf", Default: "proto"})
logFile := parser.Flag("", "logfile", &argparse.Options{Required: false, Help: "outputs to logfile in ./logs folder"})
logLevel := parser.Selector("", "loglevel", []string{"trace", "debug", "info", "warn", "error", "fatal", "panic"}, &argparse.Options{
Required: false,
Expand Down Expand Up @@ -277,11 +246,6 @@ func main() {
os.Exit(1)
}

if utils.InitCompression("vsspathlist.json") != true {
fmt.Printf("Failed in creating list from vsspathlist.json")
os.Exit(1)
}

conn := initVissV2WebSocket(compression)

optionChannel := make(chan string)
Expand Down
4 changes: 2 additions & 2 deletions client/client-1.0/compress_client/requests.json
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
{"request":[{"action":"get","path":"Vehicle/Cabin/Door/Row1/Right/IsOpen","requestId":"232"},{"action":"get","path":"Vehicle.Acceleration.Longitudinal","requestId":"233"},
{"request":[{"action":"get","path":"Vehicle/Cabin/Door/Row1/DriverSide/IsOpen","requestId":"232"},{"action":"get","path":"Vehicle.Acceleration.Longitudinal","requestId":"233"},
{"action":"get","path":"Vehicle/ADAS","filter":{"type":"paths","parameter":["ABS/*","CruiseControl/Error"]},"requestId":"237"},
{"action":"subscribe","path":"Vehicle/Cabin/Door/Row1/Right/IsOpen","filter":{"type":"timebased","parameter":{"period":"3"}},"requestId":"246"}]}
{"action":"subscribe","path":"Vehicle/Cabin/Door/Row1/PassengerSide/IsOpen","filter":{"type":"timebased","parameter":{"period":"3"}},"requestId":"246"}]}
57 changes: 6 additions & 51 deletions client/client-1.0/csv_client/csv_client.go
Original file line number Diff line number Diff line change
Expand Up @@ -131,10 +131,8 @@ func getResponse(conn *websocket.Conn, request []byte) []byte {

func performCommand(commandNumber int, conn *websocket.Conn, optionChannel chan string, unsubChannel chan string) {
fmt.Printf("Request: %s\n", requestList.Request[commandNumber])
if compression == "pbl1" || compression == "pbl2" {
if compression == "proto" {
performPbCommand(commandNumber, conn, optionChannel)
} else if compression == "prop" {
performPropCommand(commandNumber, conn, optionChannel)
} else {
performNoneCommand(commandNumber, conn, optionChannel, unsubChannel)
}
Expand Down Expand Up @@ -292,40 +290,6 @@ func saveInCsv(valArray []string, tsArray []string, arrayIndex int) {
treeFp.Close()
}

func performPropCommand(commandNumber int, conn *websocket.Conn, optionChannel chan string) {
compressedRequest := utils.CompressMessage([]byte(requestList.Request[commandNumber]))
fmt.Printf("JSON request size= %d, Compressed request size=%d\n", len(requestList.Request[commandNumber]), len(compressedRequest))
fmt.Printf("Compression= %d%\n", (100*len(requestList.Request[commandNumber]))/len(compressedRequest))
compressedResponse := getResponse(conn, compressedRequest)
jsonResponse := string(utils.DecompressMessage([]byte(compressedResponse)))
fmt.Printf("Response: %s\n", jsonResponse)
fmt.Printf("JSON response size= %d, Compressed response size=%d\n", len(jsonResponse), len(compressedResponse))
fmt.Printf("Compression= %d%\n", (100*len(jsonResponse))/len(compressedResponse))
if strings.Contains(requestList.Request[commandNumber], "subscribe") == true {
for {
_, msg, err := conn.ReadMessage()
if err != nil {
fmt.Printf("Notification error: %s\n", err)
return
}
jsonNotification := string(utils.DecompressMessage(msg))
fmt.Printf("Notification: %s\n", jsonNotification)
fmt.Printf("JSON notification size= %d, Compressed notification size=%d\n", len(jsonNotification), len(msg))
fmt.Printf("Compression= %d%\n", (100*len(jsonNotification))/len(msg))
select {
case <-optionChannel:
// issue unsubscribe request
subscriptionId := utils.ExtractSubscriptionId(jsonResponse)
unsubReq := `{"action":"unsubscribe", "subscriptionId":"` + subscriptionId + `"}`
compressedUnsubReq := utils.CompressMessage([]byte(unsubReq))
getResponse(conn, compressedUnsubReq)
return
default:
}
}
}
}

func performPbCommand(commandNumber int, conn *websocket.Conn, optionChannel chan string) {
compressedRequest := utils.JsonToProtobuf(requestList.Request[commandNumber], convertToCompression(compression))
fmt.Printf("JSON request size= %d, Protobuf request size=%d\n", len(requestList.Request[commandNumber]), len(compressedRequest))
Expand Down Expand Up @@ -360,14 +324,10 @@ func performPbCommand(commandNumber int, conn *websocket.Conn, optionChannel cha
}
}

func convertToCompression(compression string) utils.Compression {
func convertToCompression(compression string) utils.Encoding {
switch compression {
case "prop":
return utils.PROPRIETARY
case "pbl1":
return utils.PB_LEVEL1
case "pbl2":
return utils.PB_LEVEL2
case "proto":
return utils.PROTOBUF
}
return utils.NONE
}
Expand Down Expand Up @@ -404,8 +364,8 @@ func main() {
url_vissv2 := parser.String("v", "vissv2Url", &argparse.Options{Required: true, Help: "IP/url to VISSv2 server"})
prot := parser.Selector("p", "protocol", []string{"http", "ws"}, &argparse.Options{Required: false,
Help: "Protocol must be either http or websocket", Default: "ws"})
comp := parser.Selector("c", "compression", []string{"none", "prop", "pbl1", "pbl2"}, &argparse.Options{Required: false,
Help: "Compression must be either proprietary or protobuf level 1 or 2", Default: "none"})
comp := parser.Selector("c", "compression", []string{"none", "proto"}, &argparse.Options{Required: false,
Help: "Encoding must be either none or protobuf", Default: "none"})
logFile := parser.Flag("", "logfile", &argparse.Options{Required: false, Help: "outputs to logfile in ./logs folder"})
logLevel := parser.Selector("", "loglevel", []string{"trace", "debug", "info", "warn", "error", "fatal", "panic"}, &argparse.Options{
Required: false,
Expand Down Expand Up @@ -438,11 +398,6 @@ func main() {
os.Exit(1)
}

if compression != "none" && utils.InitCompression("vsspathlist.json") != true {
fmt.Printf("Failed in creating list from vsspathlist.json")
os.Exit(1)
}

conn := initVissV2WebSocket(compression)
defer conn.Close()
unsubChannel := make(chan string, 1)
Expand Down
Loading

0 comments on commit b3a0315

Please sign in to comment.