Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 14 additions & 7 deletions web/packages/teleport/src/DesktopSession/DesktopSession.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ import {
ButtonSecondary,
ButtonPrimary,
} from 'design';
import { Danger } from 'design/Alert';
import { Danger, Info } from 'design/Alert';
import Dialog, {
DialogHeader,
DialogTitle,
Expand Down Expand Up @@ -86,7 +86,7 @@ export function DesktopSession(props: State) {

const computeErrorDialog = () => {
// Websocket is closed but we haven't
// closed it on purpose or registered a fatal tdp error.
// closed it on purpose or registered a fatal TDP error.
const unknownConnectionError =
wsConnection === 'closed' &&
!disconnected &&
Expand All @@ -96,7 +96,7 @@ export function DesktopSession(props: State) {
if (fetchAttempt.status === 'failed') {
errorText = fetchAttempt.statusText || 'fetch attempt failed';
} else if (tdpConnection.status === 'failed') {
errorText = tdpConnection.statusText || 'tdp connection failed';
errorText = tdpConnection.statusText || 'TDP connection failed';
} else if (tdpConnection.status === '') {
errorText = tdpConnection.statusText || 'encountered a non-fatal error';
} else if (unknownConnectionError) {
Expand All @@ -112,10 +112,15 @@ export function DesktopSession(props: State) {
}
const open = errorText !== '';

return { open, text: errorText };
return {
open,
text: errorText,
isError: unknownConnectionError || errorText === 'RDP connection failed',
Comment thread
zmb3 marked this conversation as resolved.
Outdated
};
};

const errorDialog = computeErrorDialog();
const Alert = errorDialog.isError ? Danger : Info;

if (errorDialog.open) {
return (
Expand All @@ -126,12 +131,14 @@ export function DesktopSession(props: State) {
open={errorDialog.open}
>
<DialogHeader style={{ flexDirection: 'column' }}>
<DialogTitle>Error</DialogTitle>
<DialogTitle>
{errorDialog.isError ? 'Error' : 'Disconnected'}
</DialogTitle>
</DialogHeader>
<DialogContent>
<>
<Danger children={<>{errorDialog.text}</>} />
Refresh the page to try again.
<Alert children={<>{errorDialog.text}</>} />
Refresh the page to reconnect.
</>
</DialogContent>
<DialogFooter>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -874,7 +874,7 @@ exports[`connection error 1`] = `
overflow: auto;
word-break: break-word;
line-height: 1.5;
background: #FF6257;
background: #039be5;
color: #000000;
}

Expand Down Expand Up @@ -985,19 +985,19 @@ exports[`connection error 1`] = `
class="c5"
color="text.main"
>
Error
Disconnected
</div>
</div>
<div
class="c6"
>
<div
class="c7"
kind="danger"
kind="info"
>
some connection error
</div>
Refresh the page to try again.
Refresh the page to reconnect.
</div>
<div
class="c8"
Expand Down Expand Up @@ -1393,7 +1393,7 @@ exports[`fetch error 1`] = `
overflow: auto;
word-break: break-word;
line-height: 1.5;
background: #FF6257;
background: #039be5;
color: #000000;
}

Expand Down Expand Up @@ -1504,19 +1504,19 @@ exports[`fetch error 1`] = `
class="c5"
color="text.main"
>
Error
Disconnected
</div>
</div>
<div
class="c6"
>
<div
class="c7"
kind="danger"
kind="info"
>
some fetch error
</div>
Refresh the page to try again.
Refresh the page to reconnect.
</div>
<div
class="c8"
Expand Down Expand Up @@ -1590,7 +1590,7 @@ exports[`invalid processing 1`] = `
overflow: auto;
word-break: break-word;
line-height: 1.5;
background: #FF6257;
background: #039be5;
color: #000000;
}

Expand Down Expand Up @@ -1701,19 +1701,19 @@ exports[`invalid processing 1`] = `
class="c5"
color="text.main"
>
Error
Disconnected
</div>
</div>
<div
class="c6"
>
<div
class="c7"
kind="danger"
kind="info"
>
The application has detected an invalid internal application state. Please file a bug report for this issue at https://github.com/gravitational/teleport/issues/new?assignees=&labels=bug&template=bug_report.md
</div>
Refresh the page to try again.
Refresh the page to reconnect.
</div>
<div
class="c8"
Expand Down Expand Up @@ -2530,7 +2530,7 @@ exports[`unintended disconnect 1`] = `
>
Session disconnected for an unknown reason.
</div>
Refresh the page to try again.
Refresh the page to reconnect.
</div>
<div
class="c8"
Expand Down
15 changes: 13 additions & 2 deletions web/packages/teleport/src/lib/tdp/codec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -825,12 +825,17 @@ export default class Codec {
decodeNotification(buffer: ArrayBuffer): Notification {
const dv = new DataView(buffer);
let offset = 0;

offset += byteLength; // eat message type

const messageLength = dv.getUint32(offset);
offset += uint32Length; // eat messageLength

const message = this.decodeStringMessage(buffer);
offset += messageLength; // eat message

const severity = dv.getUint8(offset);

return {
message,
severity: toSeverity(severity),
Expand Down Expand Up @@ -858,8 +863,14 @@ export default class Codec {
// decodeStringMessage decodes a tdp message of the form
// | message type (N) | message_length uint32 | message []byte
private decodeStringMessage(buffer: ArrayBuffer): string {
const offset = byteLength + uint32Length; // eat message type and message_length
return this.decoder.decode(new Uint8Array(buffer.slice(offset)));
const dv = new DataView(buffer);
let offset = byteLength; // eat message type
const msgLength = dv.getUint32(offset);
Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This has been a bug for a loooong time. We ignore the length that the server sends and just assume the rest of the message is one giant string. (Which is why we often see unprintable characters at the end of the error message).

offset += uint32Length; // eat messageLength

return this.decoder.decode(
new Uint8Array(buffer.slice(offset, offset + msgLength))
);
}

// decodePngFrame decodes a raw tdp PNG frame message and returns it as a PngFrame
Expand Down