|
|
|
@ -82,6 +82,8 @@ static void on_encode_frame_done(struct encoder*, struct rcbuf*, uint64_t pts);
|
|
|
|
|
static bool client_has_encoding(const struct nvnc_client* client,
|
|
|
|
|
enum rfb_encodings encoding);
|
|
|
|
|
static void process_fb_update_requests(struct nvnc_client* client);
|
|
|
|
|
static void sockaddr_to_string(char* dst, size_t sz,
|
|
|
|
|
const struct sockaddr* addr);
|
|
|
|
|
|
|
|
|
|
#if defined(GIT_VERSION)
|
|
|
|
|
EXPORT const char nvnc_version[] = GIT_VERSION;
|
|
|
|
@ -141,6 +143,8 @@ static void client_close(struct nvnc_client* client)
|
|
|
|
|
client->encoder->on_done = NULL;
|
|
|
|
|
}
|
|
|
|
|
encoder_unref(client->encoder);
|
|
|
|
|
encoder_unref(client->zrle_encoder);
|
|
|
|
|
encoder_unref(client->tight_encoder);
|
|
|
|
|
pixman_region_fini(&client->damage);
|
|
|
|
|
free(client->cut_text.buffer);
|
|
|
|
|
free(client);
|
|
|
|
@ -494,7 +498,6 @@ static int on_apple_dh_response(struct nvnc_client* client)
|
|
|
|
|
} else {
|
|
|
|
|
nvnc_log(NVNC_LOG_INFO, "User \"%s\" rejected", username);
|
|
|
|
|
security_handshake_failed(client, "Invalid username or password");
|
|
|
|
|
crypto_cipher_del(cipher);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return sizeof(*msg) + key_len;
|
|
|
|
@ -945,7 +948,7 @@ static int on_client_set_encodings(struct nvnc_client* client)
|
|
|
|
|
(struct rfb_client_set_encodings_msg*)(client->msg_buffer +
|
|
|
|
|
client->buffer_index);
|
|
|
|
|
|
|
|
|
|
size_t n_encodings = MIN(MAX_ENCODINGS, ntohs(msg->n_encodings));
|
|
|
|
|
size_t n_encodings = ntohs(msg->n_encodings);
|
|
|
|
|
size_t n = 0;
|
|
|
|
|
|
|
|
|
|
if (client->buffer_len - client->buffer_index <
|
|
|
|
@ -954,7 +957,7 @@ static int on_client_set_encodings(struct nvnc_client* client)
|
|
|
|
|
|
|
|
|
|
client->quality = 10;
|
|
|
|
|
|
|
|
|
|
for (size_t i = 0; i < n_encodings; ++i) {
|
|
|
|
|
for (size_t i = 0; i < n_encodings && n < MAX_ENCODINGS; ++i) {
|
|
|
|
|
enum rfb_encodings encoding = htonl(msg->encodings[i]);
|
|
|
|
|
|
|
|
|
|
switch (encoding) {
|
|
|
|
@ -970,9 +973,10 @@ static int on_client_set_encodings(struct nvnc_client* client)
|
|
|
|
|
case RFB_ENCODING_DESKTOPSIZE:
|
|
|
|
|
case RFB_ENCODING_EXTENDEDDESKTOPSIZE:
|
|
|
|
|
case RFB_ENCODING_QEMU_EXT_KEY_EVENT:
|
|
|
|
|
client->encodings[n++] = encoding;
|
|
|
|
|
case RFB_ENCODING_PTS:
|
|
|
|
|
case RFB_ENCODING_NTP:
|
|
|
|
|
client->encodings[n++] = encoding;
|
|
|
|
|
;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (RFB_ENCODING_JPEG_LOWQ <= encoding &&
|
|
|
|
@ -1109,7 +1113,32 @@ static void process_fb_update_requests(struct nvnc_client* client)
|
|
|
|
|
client->encoder->on_done = NULL;
|
|
|
|
|
}
|
|
|
|
|
encoder_unref(client->encoder);
|
|
|
|
|
|
|
|
|
|
/* Zlib streams need to be saved so we keep encoders around that
|
|
|
|
|
* use them.
|
|
|
|
|
*/
|
|
|
|
|
switch (encoding) {
|
|
|
|
|
case RFB_ENCODING_ZRLE:
|
|
|
|
|
if (!client->zrle_encoder) {
|
|
|
|
|
client->zrle_encoder = encoder_new(encoding,
|
|
|
|
|
width, height);
|
|
|
|
|
}
|
|
|
|
|
client->encoder = client->zrle_encoder;
|
|
|
|
|
encoder_ref(client->encoder);
|
|
|
|
|
break;
|
|
|
|
|
case RFB_ENCODING_TIGHT:
|
|
|
|
|
if (!client->tight_encoder) {
|
|
|
|
|
client->tight_encoder = encoder_new(encoding,
|
|
|
|
|
width, height);
|
|
|
|
|
}
|
|
|
|
|
client->encoder = client->tight_encoder;
|
|
|
|
|
encoder_ref(client->encoder);
|
|
|
|
|
break;
|
|
|
|
|
default:
|
|
|
|
|
client->encoder = encoder_new(encoding, width, height);
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!client->encoder) {
|
|
|
|
|
nvnc_log(NVNC_LOG_ERROR, "Failed to allocate new encoder");
|
|
|
|
|
return;
|
|
|
|
@ -1673,21 +1702,23 @@ static void on_client_event(struct stream* stream, enum stream_event event)
|
|
|
|
|
client->buffer_index = 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// TODO: Remove this when nvnc_client_get_hostname gets renamed.
|
|
|
|
|
static void record_peer_hostname(int fd, struct nvnc_client* client)
|
|
|
|
|
{
|
|
|
|
|
struct sockaddr_storage storage;
|
|
|
|
|
struct sockaddr* peer = (struct sockaddr*)&storage;
|
|
|
|
|
socklen_t peerlen = sizeof(storage);
|
|
|
|
|
if (getpeername(fd, peer, &peerlen) == 0) {
|
|
|
|
|
if (getpeername(fd, peer, &peerlen) < 0) {
|
|
|
|
|
nvnc_log(NVNC_LOG_WARNING, "Failed to get address for client: %m");
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (peer->sa_family == AF_UNIX) {
|
|
|
|
|
snprintf(client->hostname, sizeof(client->hostname),
|
|
|
|
|
"unix domain socket");
|
|
|
|
|
} else {
|
|
|
|
|
getnameinfo(peer, peerlen,
|
|
|
|
|
client->hostname, sizeof(client->hostname),
|
|
|
|
|
NULL, 0, // no need for port
|
|
|
|
|
0);
|
|
|
|
|
}
|
|
|
|
|
sockaddr_to_string(client->hostname, sizeof(client->hostname),
|
|
|
|
|
peer);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@ -1774,6 +1805,11 @@ static void sockaddr_to_string(char* dst, size_t sz, const struct sockaddr* addr
|
|
|
|
|
case AF_INET6:
|
|
|
|
|
inet_ntop(addr->sa_family, &sa_in6->sin6_addr, dst, sz);
|
|
|
|
|
break;
|
|
|
|
|
default:
|
|
|
|
|
nvnc_log(NVNC_LOG_DEBUG,
|
|
|
|
|
"Don't know how to convert sa_family %d to string",
|
|
|
|
|
addr->sa_family);
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@ -2265,6 +2301,8 @@ struct nvnc* nvnc_client_get_server(const struct nvnc_client* client)
|
|
|
|
|
return client->server;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// TODO: This function should be renamed to nvnc_client_get_address and it
|
|
|
|
|
// should return the sockaddr.
|
|
|
|
|
EXPORT
|
|
|
|
|
const char* nvnc_client_get_hostname(const struct nvnc_client* client) {
|
|
|
|
|
if (client->hostname[0] == '\0')
|
|
|
|
|