Skip to content

Commit 0ef6018

Browse files
committed
Fix handling of meta keys in client
1 parent 0c76634 commit 0ef6018

File tree

3 files changed

+58
-25
lines changed

3 files changed

+58
-25
lines changed

jsonrpc.go

Lines changed: 37 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ import (
1313
"time"
1414

1515
"github.com/pion/webrtc/v4"
16+
"github.com/rs/zerolog"
1617
"go.bug.st/serial"
1718

1819
"github.com/jetkvm/kvm/internal/usbgadget"
@@ -134,7 +135,7 @@ func onRPCMessage(message webrtc.DataChannelMessage, session *Session) {
134135
}
135136

136137
scopedLogger.Trace().Msg("Calling RPC handler")
137-
result, err := callRPCHandler(handler, request.Params)
138+
result, err := callRPCHandler(scopedLogger, handler, request.Params)
138139
if err != nil {
139140
scopedLogger.Error().Err(err).Msg("Error calling RPC handler")
140141
errorResponse := JSONRPCResponse{
@@ -472,7 +473,7 @@ type RPCHandler struct {
472473
}
473474

474475
// call the handler but recover from a panic to ensure our RPC thread doesn't collapse on malformed calls
475-
func callRPCHandler(handler RPCHandler, params map[string]interface{}) (result interface{}, err error) {
476+
func callRPCHandler(logger zerolog.Logger, handler RPCHandler, params map[string]interface{}) (result interface{}, err error) {
476477
// Use defer to recover from a panic
477478
defer func() {
478479
if r := recover(); r != nil {
@@ -486,11 +487,11 @@ func callRPCHandler(handler RPCHandler, params map[string]interface{}) (result i
486487
}()
487488

488489
// Call the handler
489-
result, err = riskyCallRPCHandler(handler, params)
490-
return result, err
490+
result, err = riskyCallRPCHandler(logger, handler, params)
491+
return result, err // do not combine these two lines into one, as it breaks the above defer function's setting of err
491492
}
492493

493-
func riskyCallRPCHandler(handler RPCHandler, params map[string]interface{}) (interface{}, error) {
494+
func riskyCallRPCHandler(logger zerolog.Logger, handler RPCHandler, params map[string]interface{}) (interface{}, error) {
494495
handlerValue := reflect.ValueOf(handler.Func)
495496
handlerType := handlerValue.Type()
496497

@@ -499,20 +500,24 @@ func riskyCallRPCHandler(handler RPCHandler, params map[string]interface{}) (int
499500
}
500501

501502
numParams := handlerType.NumIn()
502-
args := make([]reflect.Value, numParams)
503-
// Get the parameter names from the RPCHandler
504-
paramNames := handler.Params
503+
paramNames := handler.Params // Get the parameter names from the RPCHandler
505504

506505
if len(paramNames) != numParams {
507-
return nil, errors.New("mismatch between handler parameters and defined parameter names")
506+
err := fmt.Errorf("mismatch between handler parameters (%d) and defined parameter names (%d)", numParams, len(paramNames))
507+
logger.Error().Strs("paramNames", paramNames).Err(err).Msg("Cannot call RPC handler")
508+
return nil, err
508509
}
509510

511+
args := make([]reflect.Value, numParams)
512+
510513
for i := 0; i < numParams; i++ {
511514
paramType := handlerType.In(i)
512515
paramName := paramNames[i]
513516
paramValue, ok := params[paramName]
514517
if !ok {
515-
return nil, errors.New("missing parameter: " + paramName)
518+
err := fmt.Errorf("missing parameter: %s", paramName)
519+
logger.Error().Err(err).Msg("Cannot marshal arguments for RPC handler")
520+
return nil, err
516521
}
517522

518523
convertedValue := reflect.ValueOf(paramValue)
@@ -529,7 +534,7 @@ func riskyCallRPCHandler(handler RPCHandler, params map[string]interface{}) (int
529534
if elemValue.Kind() == reflect.Float64 && paramType.Elem().Kind() == reflect.Uint8 {
530535
intValue := int(elemValue.Float())
531536
if intValue < 0 || intValue > 255 {
532-
return nil, fmt.Errorf("value out of range for uint8: %v", intValue)
537+
return nil, fmt.Errorf("value out of range for uint8: %v for parameter %s", intValue, paramName)
533538
}
534539
newSlice.Index(j).SetUint(uint64(intValue))
535540
} else {
@@ -545,12 +550,12 @@ func riskyCallRPCHandler(handler RPCHandler, params map[string]interface{}) (int
545550
} else if paramType.Kind() == reflect.Struct && convertedValue.Kind() == reflect.Map {
546551
jsonData, err := json.Marshal(convertedValue.Interface())
547552
if err != nil {
548-
return nil, fmt.Errorf("failed to marshal map to JSON: %v", err)
553+
return nil, fmt.Errorf("failed to marshal map to JSON: %v for parameter %s", err, paramName)
549554
}
550555

551556
newStruct := reflect.New(paramType).Interface()
552557
if err := json.Unmarshal(jsonData, newStruct); err != nil {
553-
return nil, fmt.Errorf("failed to unmarshal JSON into struct: %v", err)
558+
return nil, fmt.Errorf("failed to unmarshal JSON into struct: %v for parameter %s", err, paramName)
554559
}
555560
args[i] = reflect.ValueOf(newStruct).Elem()
556561
} else {
@@ -561,30 +566,40 @@ func riskyCallRPCHandler(handler RPCHandler, params map[string]interface{}) (int
561566
}
562567
}
563568

569+
logger.Trace().Interface("args", args).Msg("Calling RPC handler")
564570
results := handlerValue.Call(args)
565571

566572
if len(results) == 0 {
567573
return nil, nil
568574
}
569575

570576
if len(results) == 1 {
571-
if results[0].Type().Implements(reflect.TypeOf((*error)(nil)).Elem()) {
572-
if !results[0].IsNil() {
573-
return nil, results[0].Interface().(error)
574-
}
575-
return nil, nil
577+
if ok, err := asError(results[0]); ok {
578+
return nil, err
576579
}
577580
return results[0].Interface(), nil
578581
}
579582

580-
if len(results) == 2 && results[1].Type().Implements(reflect.TypeOf((*error)(nil)).Elem()) {
581-
if !results[1].IsNil() {
582-
return nil, results[1].Interface().(error)
583+
if len(results) == 2 {
584+
if ok, err := asError(results[1]); ok {
585+
if err != nil {
586+
return nil, err
587+
}
583588
}
584589
return results[0].Interface(), nil
585590
}
586591

587-
return nil, errors.New("unexpected return values from handler")
592+
return nil, fmt.Errorf("too many return values from handler: %d", len(results))
593+
}
594+
595+
func asError(value reflect.Value) (bool, error) {
596+
if value.Type().Implements(reflect.TypeOf((*error)(nil)).Elem()) {
597+
if value.IsNil() {
598+
return true, nil
599+
}
600+
return true, value.Interface().(error)
601+
}
602+
return false, nil
588603
}
589604

590605
func rpcSetMassStorageMode(mode string) (string, error) {

ui/src/components/WebRTCVideo.tsx

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -337,17 +337,21 @@ export default function WebRTCVideo() {
337337
const code = getAdjustedKeyCode(e);
338338
const hidKey = keys[code];
339339

340+
if (hidKey === undefined) {
341+
console.warn(`Key down not mapped: ${code}`);
342+
return;
343+
}
344+
340345
// When pressing the meta key + another key, the key will never trigger a keyup
341346
// event, so we need to clear the keys after a short delay
342347
// https://bugs.chromium.org/p/chromium/issues/detail?id=28089
343348
// https://bugzilla.mozilla.org/show_bug.cgi?id=1299553
344-
if (e.metaKey) {
349+
if (e.metaKey && hidKey < 0xE0) {
345350
setTimeout(() => {
346351
sendKeypressEvent(hidKey, false);
347352
}, 10);
348353
}
349354
sendKeypressEvent(hidKey, true);
350-
351355
},
352356
[sendKeypressEvent],
353357
);
@@ -357,6 +361,12 @@ export default function WebRTCVideo() {
357361
e.preventDefault();
358362
const code = getAdjustedKeyCode(e);
359363
const hidKey = keys[code];
364+
365+
if (hidKey === undefined) {
366+
console.warn(`Key up not mapped: ${code}`);
367+
return;
368+
}
369+
360370
sendKeypressEvent(hidKey, false);
361371
},
362372
[sendKeypressEvent],

ui/src/keyboardMappings.ts

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ export const keys = {
1414
CapsLock: 0x39,
1515
Comma: 0x36,
1616
Compose: 0x65,
17-
ContextMenu: 0,
17+
ContextMenu: 0x65, // same as Compose
1818
Delete: 0x4c,
1919
Digit0: 0x27,
2020
Digit1: 0x1e,
@@ -121,6 +121,14 @@ export const keys = {
121121
Space: 0x2c,
122122
SystemRequest: 0x9a,
123123
Tab: 0x2b,
124+
ControlLeft: 0xe0,
125+
ControlRight: 0xe4,
126+
ShiftLeft: 0xe1,
127+
ShiftRight: 0xe5,
128+
AltLeft: 0xe2,
129+
AltRight: 0xe6,
130+
MetaLeft: 0xe3,
131+
MetaRight: 0xe7,
124132
} as Record<string, number>;
125133

126134
export const modifiers = {

0 commit comments

Comments
 (0)