Skip to content

Commit

Permalink
Merge pull request #12 from Goddchen/feature/set-pixel-format-and-enc…
Browse files Browse the repository at this point in the history
…odings

feat: set pixel format and encodings
  • Loading branch information
Goddchen authored Dec 22, 2022
2 parents 2c68f3f + e6ce60c commit ce1cb66
Show file tree
Hide file tree
Showing 21 changed files with 656 additions and 131 deletions.
6 changes: 6 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,3 +22,9 @@
## 0.3.1

- Fix a minor typo issue

## 0.4.0

- Add CopyRect encoding support
- Add SetEncodings message support
- Add SetPixelFormat message support
8 changes: 4 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ And here we are, after a weekend, with the first, minimal, protocol implementati
### Encodings

- ✅ Raw
- CopyRect
- CopyRect
- ⬜ RRE (obsolescent)
- ⬜ Hextile (obsolescent)
- ⬜ TRLE
Expand All @@ -48,8 +48,8 @@ And here we are, after a weekend, with the first, minimal, protocol implementati
- ✅ ClientInit
- ✅ ServerInit
- Client-to-Server
- SetPixelFormat
- SetEncodings
- SetPixelFormat
- SetEncodings
- ✅ FramebufferUpdateRequest
- ⬜ KeyEvent
- ✅ PointerEvent
Expand All @@ -64,7 +64,7 @@ And here we are, after a weekend, with the first, minimal, protocol implementati

As simple as `dart pub add dart_rfb`.

Or manually add `dart_rfb: ^0.3.1` to your `pubspec.yaml`.
Or manually add `dart_rfb: ^<latest-version>` to your `pubspec.yaml`.

## Usage

Expand Down
45 changes: 43 additions & 2 deletions lib/src/client/remote_frame_buffer_client.dart
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import 'dart:convert';
import 'dart:io';
import 'dart:typed_data';

import 'package:collection/collection.dart';
import 'package:dart_des/dart_des.dart';
import 'package:dart_rfb/src/client/config.dart';
import 'package:dart_rfb/src/client/remote_frame_buffer_client_pointer_event.dart';
Expand All @@ -11,14 +12,18 @@ import 'package:dart_rfb/src/constants.dart';
import 'package:dart_rfb/src/extensions/byte_data_extensions.dart';
import 'package:dart_rfb/src/extensions/int_extensions.dart';
import 'package:dart_rfb/src/protocol/client_init_message.dart';
import 'package:dart_rfb/src/protocol/encoding_type.dart';
import 'package:dart_rfb/src/protocol/frame_buffer_update_message.dart';
import 'package:dart_rfb/src/protocol/frame_buffer_update_request_message.dart';
import 'package:dart_rfb/src/protocol/pixel_format.dart';
import 'package:dart_rfb/src/protocol/pointer_event_message.dart';
import 'package:dart_rfb/src/protocol/protocol_version_handshake_message.dart';
import 'package:dart_rfb/src/protocol/security_handshake_message.dart';
import 'package:dart_rfb/src/protocol/security_result_handshake_message.dart';
import 'package:dart_rfb/src/protocol/security_type.dart';
import 'package:dart_rfb/src/protocol/server_init_message.dart';
import 'package:dart_rfb/src/protocol/set_encodings_message.dart';
import 'package:dart_rfb/src/protocol/set_pixel_format_message.dart';
import 'package:fpdart/fpdart.dart';
import 'package:logging/logging.dart';

Expand Down Expand Up @@ -190,7 +195,7 @@ class RemoteFrameBufferClient {
) {
logger.log(
Level.INFO,
'< ${updateMessage.rectangles.length} update rectangles',
'< update rectangles: ${updateMessage.rectangles.groupListsBy((final RemoteFrameBufferFrameBufferUpdateMessageRectangle rectangle) => rectangle.encodingType).mapValue((final List<RemoteFrameBufferFrameBufferUpdateMessageRectangle> list) => list.length)}',
);
_updateStreamController.add(
RemoteFrameBufferClientUpdate(
Expand All @@ -201,6 +206,7 @@ class RemoteFrameBufferClient {
) =>
RemoteFrameBufferClientUpdateRectangle(
byteData: rectangle.pixelData,
encodingType: rectangle.encodingType,
height: rectangle.height,
width: rectangle.width,
x: rectangle.x,
Expand Down Expand Up @@ -340,7 +346,9 @@ class RemoteFrameBufferClient {
.andThen(() => _handleSecurityType(socket: socket))
.andThen(() => _readSecurityResultMessage(socket: socket))
.andThen(() => _sendClientInitMessage(socket: socket))
.andThen(() => _readServerInitMessage(socket: socket)),
.andThen(() => _readServerInitMessage(socket: socket))
.andThen(() => _setPixelFormat(socket: socket))
.andThen(() => _setEncodingTypes(socket: socket)),
);

TaskEither<Object, void> _readProtocolVersionMessage({
Expand Down Expand Up @@ -670,4 +678,37 @@ class RemoteFrameBufferClient {
v3_8: (final _) => taskEither,
);
}

TaskEither<Object, void> _setEncodingTypes({
required final RawSocket socket,
}) =>
TaskEither<Object, void>.tryCatch(
() async {
const RemoteFrameBufferSetEncodingsMessage message =
RemoteFrameBufferSetEncodingsMessage(
encodingTypes: <RemoteFrameBufferEncodingType>[
RemoteFrameBufferEncodingType.copyRect(),
RemoteFrameBufferEncodingType.raw(),
],
);
logger.info('> $message');
socket.write(message.toBytes().buffer.asUint8List());
},
(final Object error, final _) => error,
);

TaskEither<Object, void> _setPixelFormat({
required final RawSocket socket,
}) =>
TaskEither<Object, void>.tryCatch(
() async {
final RemoteFrameBufferSetPixelFormatMessage message =
RemoteFrameBufferSetPixelFormatMessage(
pixelFormat: RemoteFrameBufferPixelFormat.bgra8888,
);
logger.info('> $message');
socket.write(message.toBytes().buffer.asUint8ClampedList());
},
(final Object error, final _) => error,
);
}
4 changes: 4 additions & 0 deletions lib/src/client/remote_frame_buffer_client_update.dart
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import 'dart:typed_data';

import 'package:dart_rfb/src/protocol/encoding_type.dart';
import 'package:freezed_annotation/freezed_annotation.dart';

part 'remote_frame_buffer_client_update.freezed.dart';
Expand Down Expand Up @@ -31,6 +32,9 @@ class RemoteFrameBufferClientUpdateRectangle
/// The [ByteData] that holds the pixel data of this rectangle.
required final ByteData byteData,

/// The encoding used to interpret the bytes in [byteData].
required final RemoteFrameBufferEncodingType encodingType,

/// The height in pixels.
required final int height,

Expand Down
61 changes: 57 additions & 4 deletions lib/src/client/remote_frame_buffer_client_update.freezed.dart
Original file line number Diff line number Diff line change
Expand Up @@ -303,6 +303,10 @@ mixin _$RemoteFrameBufferClientUpdateRectangle {
/// The [ByteData] that holds the pixel data of this rectangle.
ByteData get byteData => throw _privateConstructorUsedError;

/// The encoding used to interpret the bytes in [byteData].
RemoteFrameBufferEncodingType get encodingType =>
throw _privateConstructorUsedError;

/// The height in pixels.
int get height => throw _privateConstructorUsedError;

Expand All @@ -329,7 +333,15 @@ abstract class $RemoteFrameBufferClientUpdateRectangleCopyWith<$Res> {
_$RemoteFrameBufferClientUpdateRectangleCopyWithImpl<$Res,
RemoteFrameBufferClientUpdateRectangle>;
@useResult
$Res call({ByteData byteData, int height, int width, int x, int y});
$Res call(
{ByteData byteData,
RemoteFrameBufferEncodingType encodingType,
int height,
int width,
int x,
int y});

$RemoteFrameBufferEncodingTypeCopyWith<$Res> get encodingType;
}

/// @nodoc
Expand All @@ -347,6 +359,7 @@ class _$RemoteFrameBufferClientUpdateRectangleCopyWithImpl<$Res,
@override
$Res call({
Object? byteData = null,
Object? encodingType = null,
Object? height = null,
Object? width = null,
Object? x = null,
Expand All @@ -357,6 +370,10 @@ class _$RemoteFrameBufferClientUpdateRectangleCopyWithImpl<$Res,
? _value.byteData
: byteData // ignore: cast_nullable_to_non_nullable
as ByteData,
encodingType: null == encodingType
? _value.encodingType
: encodingType // ignore: cast_nullable_to_non_nullable
as RemoteFrameBufferEncodingType,
height: null == height
? _value.height
: height // ignore: cast_nullable_to_non_nullable
Expand All @@ -375,6 +392,15 @@ class _$RemoteFrameBufferClientUpdateRectangleCopyWithImpl<$Res,
as int,
) as $Val);
}

@override
@pragma('vm:prefer-inline')
$RemoteFrameBufferEncodingTypeCopyWith<$Res> get encodingType {
return $RemoteFrameBufferEncodingTypeCopyWith<$Res>(_value.encodingType,
(value) {
return _then(_value.copyWith(encodingType: value) as $Val);
});
}
}

/// @nodoc
Expand All @@ -386,7 +412,16 @@ abstract class _$$_RemoteFrameBufferClientUpdateRectangleCopyWith<$Res>
__$$_RemoteFrameBufferClientUpdateRectangleCopyWithImpl<$Res>;
@override
@useResult
$Res call({ByteData byteData, int height, int width, int x, int y});
$Res call(
{ByteData byteData,
RemoteFrameBufferEncodingType encodingType,
int height,
int width,
int x,
int y});

@override
$RemoteFrameBufferEncodingTypeCopyWith<$Res> get encodingType;
}

/// @nodoc
Expand All @@ -403,6 +438,7 @@ class __$$_RemoteFrameBufferClientUpdateRectangleCopyWithImpl<$Res>
@override
$Res call({
Object? byteData = null,
Object? encodingType = null,
Object? height = null,
Object? width = null,
Object? x = null,
Expand All @@ -413,6 +449,10 @@ class __$$_RemoteFrameBufferClientUpdateRectangleCopyWithImpl<$Res>
? _value.byteData
: byteData // ignore: cast_nullable_to_non_nullable
as ByteData,
encodingType: null == encodingType
? _value.encodingType
: encodingType // ignore: cast_nullable_to_non_nullable
as RemoteFrameBufferEncodingType,
height: null == height
? _value.height
: height // ignore: cast_nullable_to_non_nullable
Expand All @@ -439,6 +479,7 @@ class _$_RemoteFrameBufferClientUpdateRectangle
implements _RemoteFrameBufferClientUpdateRectangle {
const _$_RemoteFrameBufferClientUpdateRectangle(
{required this.byteData,
required this.encodingType,
required this.height,
required this.width,
required this.x,
Expand All @@ -448,6 +489,10 @@ class _$_RemoteFrameBufferClientUpdateRectangle
@override
final ByteData byteData;

/// The encoding used to interpret the bytes in [byteData].
@override
final RemoteFrameBufferEncodingType encodingType;

/// The height in pixels.
@override
final int height;
Expand All @@ -466,7 +511,7 @@ class _$_RemoteFrameBufferClientUpdateRectangle

@override
String toString() {
return 'RemoteFrameBufferClientUpdateRectangle(byteData: $byteData, height: $height, width: $width, x: $x, y: $y)';
return 'RemoteFrameBufferClientUpdateRectangle(byteData: $byteData, encodingType: $encodingType, height: $height, width: $width, x: $x, y: $y)';
}

@override
Expand All @@ -476,14 +521,17 @@ class _$_RemoteFrameBufferClientUpdateRectangle
other is _$_RemoteFrameBufferClientUpdateRectangle &&
(identical(other.byteData, byteData) ||
other.byteData == byteData) &&
(identical(other.encodingType, encodingType) ||
other.encodingType == encodingType) &&
(identical(other.height, height) || other.height == height) &&
(identical(other.width, width) || other.width == width) &&
(identical(other.x, x) || other.x == x) &&
(identical(other.y, y) || other.y == y));
}

@override
int get hashCode => Object.hash(runtimeType, byteData, height, width, x, y);
int get hashCode =>
Object.hash(runtimeType, byteData, encodingType, height, width, x, y);

@JsonKey(ignore: true)
@override
Expand All @@ -498,6 +546,7 @@ abstract class _RemoteFrameBufferClientUpdateRectangle
implements RemoteFrameBufferClientUpdateRectangle {
const factory _RemoteFrameBufferClientUpdateRectangle(
{required final ByteData byteData,
required final RemoteFrameBufferEncodingType encodingType,
required final int height,
required final int width,
required final int x,
Expand All @@ -509,6 +558,10 @@ abstract class _RemoteFrameBufferClientUpdateRectangle
ByteData get byteData;
@override

/// The encoding used to interpret the bytes in [byteData].
RemoteFrameBufferEncodingType get encodingType;
@override

/// The height in pixels.
int get height;
@override
Expand Down
15 changes: 15 additions & 0 deletions lib/src/protocol/encoding_type.dart
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@ part 'encoding_type.freezed.dart';
/// See: https://www.rfc-editor.org/rfc/rfc6143.html#section-7.7
@freezed
class RemoteFrameBufferEncodingType with _$RemoteFrameBufferEncodingType {
const factory RemoteFrameBufferEncodingType.copyRect() =
RemoteFrameBufferEncodingTypeCopyRect;
const factory RemoteFrameBufferEncodingType.raw() =
RemoteFrameBufferEncodingTypeRaw;
const factory RemoteFrameBufferEncodingType.unsupported({
Expand All @@ -22,10 +24,23 @@ class RemoteFrameBufferEncodingType with _$RemoteFrameBufferEncodingType {
switch (bytes.getInt32(0)) {
case 0:
return const RemoteFrameBufferEncodingType.raw();
case 1:
return const RemoteFrameBufferEncodingType.copyRect();
default:
return RemoteFrameBufferEncodingType.unsupported(bytes: bytes);
}
}

/// Generate byte representation of thie encoding type.
ByteData toBytes() => ByteData(4)
..setInt32(
0,
map(
copyRect: (final _) => 1,
raw: (final _) => 0,
unsupported: (final _) => -1,
),
);

const RemoteFrameBufferEncodingType._();
}
Loading

0 comments on commit ce1cb66

Please sign in to comment.