diff --git a/include/rfbclient.h b/include/rfbclient.h index 37b3bb9..a8bfc2f 100644 --- a/include/rfbclient.h +++ b/include/rfbclient.h @@ -225,6 +225,9 @@ typedef char* (*GetUserProc)(struct _rfbClient* client); typedef char* (*GetSASLMechanismProc)(struct _rfbClient* client, char* mechlist); #endif /* LIBVNCSERVER_HAVE_SASL */ +typedef void (*NtpEventProc)(struct _rfbClient* client, uint32_t t0, + uint32_t t1, uint32_t t2, uint32_t t3); + typedef struct _rfbClient { uint8_t* frameBuffer; int width, height; @@ -467,6 +470,8 @@ typedef struct _rfbClient { StartingFrameBufferUpdateProc StartingFrameBufferUpdate; CancelledFrameBufferUpdateProc CancelledFrameBufferUpdate; + + NtpEventProc NtpEvent; } rfbClient; /* cursor.c */ @@ -612,6 +617,9 @@ extern rfbBool HandleRFBServerMessage(rfbClient* client); extern rfbBool ReadToBuffer(rfbClient* client); +extern rfbBool SendClientNtpEvent(rfbClient* client, uint32_t t0, uint32_t t1, + uint32_t t2, uint32_t t3); + /** * Sends a text chat message to the server. * @param client The client through which to send the message diff --git a/include/rfbproto.h b/include/rfbproto.h index dbf3967..ffbceb4 100644 --- a/include/rfbproto.h +++ b/include/rfbproto.h @@ -398,8 +398,7 @@ typedef struct { #define rfbSetDesktopSize 251 #define rfbQemuEvent 255 - - +#define rfbNtpEvent 160 /***************************************************************************** * @@ -499,6 +498,7 @@ typedef struct { #define rfbEncodingServerIdentity 0xFFFE0003 #define rfbEncodingPts -1000 +#define rfbEncodingNtp -1001 /***************************************************************************** * @@ -1139,6 +1139,12 @@ typedef struct rfbExtDesktopScreen { uint32_t flags; } rfbExtDesktopScreen; +struct rfbNtpMsg { + uint8_t type; + uint8_t padding[3]; + uint32_t t0, t1, t2, t3; +}; + #define sz_rfbExtDesktopSizeMsg (4) #define sz_rfbExtDesktopScreen (16) @@ -1218,17 +1224,18 @@ typedef struct { */ typedef union { - uint8_t type; - rfbFramebufferUpdateMsg fu; - rfbSetColourMapEntriesMsg scme; - rfbBellMsg b; - rfbServerCutTextMsg sct; + uint8_t type; + rfbFramebufferUpdateMsg fu; + rfbSetColourMapEntriesMsg scme; + rfbBellMsg b; + rfbServerCutTextMsg sct; rfbResizeFrameBufferMsg rsfb; rfbPalmVNCReSizeFrameBufferMsg prsfb; rfbFileTransferMsg ft; rfbTextChatMsg tc; rfbXvpMsg xvp; rfbExtDesktopSizeMsg eds; + struct rfbNtpMsg ntp; } rfbServerToClientMsg; diff --git a/include/vnc.h b/include/vnc.h index bd36831..8c66811 100644 --- a/include/vnc.h +++ b/include/vnc.h @@ -45,6 +45,8 @@ struct vnc_client { int (*alloc_fb)(struct vnc_client*); void (*update_fb)(struct vnc_client*); void (*cut_text)(struct vnc_client*, const char*, size_t); + void (*ntp_event)(struct vnc_client*, uint32_t t0, uint32_t t1, + uint32_t t2, uint32_t t3); void* userdata; struct pixman_region16 damage; @@ -79,3 +81,5 @@ void vnc_client_set_compression_level(struct vnc_client* self, int value); void vnc_client_send_cut_text(struct vnc_client* self, const char* text, size_t len); void vnc_client_clear_av_frames(struct vnc_client* self); +void vnc_client_send_ntp_event(struct vnc_client* self, uint32_t t0, + uint32_t t1, uint32_t t2, uint32_t t3); diff --git a/src/rfbproto.c b/src/rfbproto.c index 4ca8115..677d0be 100644 --- a/src/rfbproto.c +++ b/src/rfbproto.c @@ -1398,6 +1398,10 @@ rfbBool SetFormatAndEncodings(rfbClient* client) if (se->nEncodings < MAX_ENCODINGS) encs[se->nEncodings++] = rfbClientSwap32IfLE(rfbEncodingPts); + /* ntp */ + if (se->nEncodings < MAX_ENCODINGS) + encs[se->nEncodings++] = rfbClientSwap32IfLE(rfbEncodingNtp); + len = sz_rfbSetEncodingsMsg + se->nEncodings * 4; se->nEncodings = rfbClientSwap16IfLE(se->nEncodings); @@ -1742,6 +1746,22 @@ rfbBool SendClientCutText(rfbClient* client, char* str, int len) WriteToRFBServer(client, str, len)); } +rfbBool SendClientNtpEvent(rfbClient* client, uint32_t t0, uint32_t t1, + uint32_t t2, uint32_t t3) +{ + if (!SupportsClient2Server(client, rfbNtpEvent)) + return FALSE; + + struct rfbNtpMsg msg = { + .type = rfbNtpEvent, + .t0 = rfbClientSwap32IfLE(t0), + .t1 = rfbClientSwap32IfLE(t1), + .t2 = rfbClientSwap32IfLE(t2), + .t3 = rfbClientSwap32IfLE(t3), + }; + return WriteToRFBServer(client, (char*)&msg, sizeof(msg)); +} + static rfbBool HandleFramebufferUpdate(rfbClient* client, rfbServerToClientMsg* msg) { @@ -2300,6 +2320,10 @@ static rfbBool HandleFramebufferUpdate(rfbClient* client, SetClient2Server(client, rfbQemuEvent); break; + case rfbEncodingNtp: + SetClient2Server(client, rfbNtpEvent); + break; + default: { rfbBool handled = FALSE; rfbClientProtocolExtension* e; @@ -2339,6 +2363,22 @@ failure: return FALSE; } +rfbBool handleNtpEvent(rfbClient* client, struct rfbNtpMsg* msg) +{ + if (!ReadFromRFBServer(client, (char*)msg + 1, sizeof(*msg) - 1)) + return FALSE; + + uint32_t t0 = rfbClientSwap32IfLE(msg->t0); + uint32_t t1 = rfbClientSwap32IfLE(msg->t1); + uint32_t t2 = rfbClientSwap32IfLE(msg->t2); + uint32_t t3 = rfbClientSwap32IfLE(msg->t3); + + if (client->NtpEvent) + client->NtpEvent(client, t0, t1, t2, t3); + + return TRUE; +} + /* * HandleRFBServerMessage. */ @@ -2527,6 +2567,9 @@ rfbBool HandleRFBServerMessage(rfbClient* client) break; } + case rfbNtpEvent: + return handleNtpEvent(client, &msg.ntp); + default: { rfbBool handled = FALSE; rfbClientProtocolExtension* e; diff --git a/src/vnc.c b/src/vnc.c index 100ec35..f7ebc8f 100644 --- a/src/vnc.c +++ b/src/vnc.c @@ -136,6 +136,16 @@ static void vnc_client_got_cut_text(rfbClient* client, const char* text, self->cut_text(self, text, len); } +static void vnc_client_ntp_event(rfbClient* client, uint32_t t0, uint32_t t1, + uint32_t t2, uint32_t t3) +{ + struct vnc_client* self = rfbClientGetClientData(client, NULL); + assert(self); + + if (self->ntp_event) + self->ntp_event(self, t0, t1, t2, t3); +} + static rfbBool vnc_client_handle_open_h264_rect(rfbClient* client, rfbFramebufferUpdateRectHeader* rect_header) { @@ -246,6 +256,7 @@ struct vnc_client* vnc_client_create(void) client->StartingFrameBufferUpdate = vnc_client_start_update; client->CancelledFrameBufferUpdate = vnc_client_cancel_update; client->GotXCutText = vnc_client_got_cut_text; + client->NtpEvent = vnc_client_ntp_event; self->pts = NO_PTS; @@ -443,3 +454,9 @@ void vnc_client_send_cut_text(struct vnc_client* self, const char* text, // libvncclient doesn't modify text, so typecast is OK. SendClientCutText(self->client, (char*)text, len); } + +void vnc_client_send_ntp_event(struct vnc_client* self, uint32_t t0, + uint32_t t1, uint32_t t2, uint32_t t3) +{ + SendClientNtpEvent(self->client, t0, t1, t2, t3); +}