rfbBool WriteToRFBServer(rfbClient* client, char *buf, int n) { fd_set fds; int i = 0; int j; if (client->serverPort==-1) return TRUE; /* vncrec playing */ if (client->tlsSession) { /* WriteToTLS() will guarantee either everything is written, or error/eof returns */ i = WriteToTLS(client, buf, n); if (i <= 0) return FALSE; return TRUE; } while (i < n) { j = write(client->sock, buf + i, (n - i)); if (j <= 0) { if (j < 0) { #ifdef WIN32 errno=WSAGetLastError(); #endif if (errno == EWOULDBLOCK || #ifdef LIBVNCSERVER_ENOENT_WORKAROUND errno == ENOENT || #endif errno == EAGAIN) { FD_ZERO(&fds); FD_SET(client->sock,&fds); if (select(client->sock+1, NULL, &fds, NULL, NULL) <= 0) { rfbClientErr("select\n"); return FALSE; } j = 0; } else { rfbClientErr("write\n"); return FALSE; } } else { rfbClientLog("write failed\n"); return FALSE; } } i += j; } return TRUE; }
int ConnectClientToTcpAddr(unsigned int host, int port) { int sock; struct sockaddr_in addr; int one = 1; #ifdef WIN32 WSADATA trash; static rfbBool WSAinitted=FALSE; if(!WSAinitted) { WSAinitted=TRUE; int i=WSAStartup(MAKEWORD(2,0),&trash); if(i!=0) { rfbClientErr("Couldn't init Windows Sockets\n"); return -1; } } #endif addr.sin_family = AF_INET; addr.sin_port = htons(port); addr.sin_addr.s_addr = host; sock = socket(AF_INET, SOCK_STREAM, 0); if (sock < 0) { #ifdef WIN32 errno=WSAGetLastError(); #endif rfbClientErr("ConnectToTcpAddr: socket (%s)\n",strerror(errno)); return -1; } if (connect(sock, (struct sockaddr *)&addr, sizeof(addr)) < 0) { rfbClientErr("ConnectToTcpAddr: connect\n"); close(sock); return -1; } if (setsockopt(sock, IPPROTO_TCP, TCP_NODELAY, (char *)&one, sizeof(one)) < 0) { rfbClientErr("ConnectToTcpAddr: setsockopt\n"); close(sock); return -1; } return sock; }
int FindFreeTcpPort(void) { int sock, port; struct sockaddr_in addr; addr.sin_family = AF_INET; addr.sin_addr.s_addr = htonl(INADDR_ANY); if (!initSockets()) return -1; sock = socket(AF_INET, SOCK_STREAM, 0); if (sock < 0) { rfbClientErr(": FindFreeTcpPort: socket\n"); return 0; } for (port = TUNNEL_PORT_OFFSET + 99; port > TUNNEL_PORT_OFFSET; port--) { addr.sin_port = htons((unsigned short)port); if (bind(sock, (struct sockaddr *)&addr, sizeof(addr)) == 0) { close(sock); return port; } } close(sock); return 0; }
static void* clientLoop(void* data) { rfbClient* client=(rfbClient*)data; clientData* cd=(clientData*)client->clientData; client->appData.encodingsString=strdup(testEncodings[cd->encodingIndex].str); sleep(1); rfbClientLog("Starting client (encoding %s, display %s)\n", testEncodings[cd->encodingIndex].str, cd->display); if(!rfbInitClient(client,NULL,NULL)) { rfbClientErr("Had problems starting client (encoding %s)\n", testEncodings[cd->encodingIndex].str); updateStatistics(cd->encodingIndex,TRUE); return NULL; } while(1) { if(WaitForMessage(client,50)>=0) if(!HandleRFBServerMessage(client)) break; } free(((clientData*)client->clientData)->display); free(client->clientData); if(client->frameBuffer) free(client->frameBuffer); rfbClientCleanup(client); return NULL; }
static char* ReadPassword(rfbClient* client) { #ifdef __MINGW32__ /* FIXME */ rfbClientErr("ReadPassword on MinGW32 NOT IMPLEMENTED\n"); return NoPassword(client); #else int i; char* p=malloc(9); struct termios save,noecho; p[0]=0; if(tcgetattr(fileno(stdin),&save)!=0) return p; noecho=save; noecho.c_lflag &= ~ECHO; if(tcsetattr(fileno(stdin),TCSAFLUSH,&noecho)!=0) return p; fprintf(stderr,"Password: "); i=0; while(1) { int c=fgetc(stdin); if(c=='\n') break; if(i<8) { p[i]=c; i++; p[i]=0; } } tcsetattr(fileno(stdin),TCSAFLUSH,&save); return p; #endif }
int ListenAtTcpPort(int port) { int sock; struct sockaddr_in addr; int one = 1; addr.sin_family = AF_INET; addr.sin_port = htons(port); addr.sin_addr.s_addr = htonl(INADDR_ANY); if (!initSockets()) return -1; sock = socket(AF_INET, SOCK_STREAM, 0); if (sock < 0) { rfbClientErr("ListenAtTcpPort: socket\n"); return -1; } if (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (const char *)&one, sizeof(one)) < 0) { rfbClientErr("ListenAtTcpPort: setsockopt\n"); close(sock); return -1; } if (bind(sock, (struct sockaddr *)&addr, sizeof(addr)) < 0) { rfbClientErr("ListenAtTcpPort: bind\n"); close(sock); return -1; } if (listen(sock, 5) < 0) { rfbClientErr("ListenAtTcpPort: listen\n"); close(sock); return -1; } return sock; }
rfbBool WriteToRFBServer(rfbClient* client, char *buf, int n) { fd_set fds; int i = 0; int j; if (client->serverPort==-1) return TRUE; /* vncrec playing */ while (i < n) { j = write(client->sock, buf + i, (n - i)); if (j <= 0) { if (j < 0) { if (errno == EWOULDBLOCK || #ifdef LIBVNCSERVER_ENOENT_WORKAROUND errno == ENOENT || #endif errno == EAGAIN) { FD_ZERO(&fds); FD_SET(client->sock,&fds); if (select(client->sock+1, NULL, &fds, NULL, NULL) <= 0) { rfbClientErr("select\n"); return FALSE; } j = 0; } else { rfbClientErr("write\n"); return FALSE; } } else { rfbClientLog("write failed\n"); return FALSE; } } i += j; } return TRUE; }
int ConnectClientToTcpAddr(unsigned int host, int port) { int sock; struct sockaddr_in addr; int one = 1; if (!initSockets()) return -1; addr.sin_family = AF_INET; addr.sin_port = htons(port); addr.sin_addr.s_addr = host; sock = socket(AF_INET, SOCK_STREAM, 0); if (sock < 0) { #ifdef WIN32 errno=WSAGetLastError(); #endif rfbClientErr("ConnectToTcpAddr: socket (%s)\n",strerror(errno)); return -1; } if (connect(sock, (struct sockaddr *)&addr, sizeof(addr)) < 0) { rfbClientErr("ConnectToTcpAddr: connect\n"); close(sock); return -1; } if (setsockopt(sock, IPPROTO_TCP, TCP_NODELAY, (char *)&one, sizeof(one)) < 0) { rfbClientErr("ConnectToTcpAddr: setsockopt\n"); close(sock); return -1; } return sock; }
int AcceptTcpConnection(int listenSock) { int sock; struct sockaddr_in addr; socklen_t addrlen = sizeof(addr); int one = 1; sock = accept(listenSock, (struct sockaddr *) &addr, &addrlen); if (sock < 0) { rfbClientErr("AcceptTcpConnection: accept\n"); return -1; } if (setsockopt(sock, IPPROTO_TCP, TCP_NODELAY, (char *)&one, sizeof(one)) < 0) { rfbClientErr("AcceptTcpConnection: setsockopt\n"); close(sock); return -1; } return sock; }
static int initSockets() { #ifdef WIN32 WSADATA trash; static rfbBool WSAinitted=FALSE; if(!WSAinitted) { int i=WSAStartup(MAKEWORD(2,0),&trash); if(i!=0) { rfbClientErr("Couldn't init Windows Sockets\n"); return 0; } WSAinitted=TRUE; } #endif return 1; }
static rfbBool MallocFrameBuffer(rfbClient* client) { uint64_t allocSize; if(client->frameBuffer) free(client->frameBuffer); /* SECURITY: promote 'width' into uint64_t so that the multiplication does not overflow 'width' and 'height' are 16-bit integers per RFB protocol design SIZE_MAX is the maximum value that can fit into size_t */ allocSize = (uint64_t)client->width * client->height * client->format.bitsPerPixel/8; if (allocSize >= SIZE_MAX) { rfbClientErr("CRITICAL: cannot allocate frameBuffer, requested size is too large\n"); return FALSE; } client->frameBuffer=malloc( (size_t)allocSize ); if (client->frameBuffer == NULL) rfbClientErr("CRITICAL: frameBuffer allocation failed, requested size too large or not enough memory?\n"); return client->frameBuffer?TRUE:FALSE; }
static void SaveFramebufferAsPPM(rfbClient* client, int x, int y, int w, int h) { static time_t t=0,t1; FILE* f; int i,j; rfbPixelFormat* pf=&client->format; int bpp=pf->bitsPerPixel/8; int row_stride=client->width*bpp; /* save one picture only if the last is older than 2 seconds */ t1=time(NULL); if(t1-t>2) t=t1; else return; /* assert bpp=4 */ if(bpp!=4 && bpp!=2) { rfbClientLog("bpp = %d (!=4)\n",bpp); return; } f=fopen("framebuffer.ppm","wb"); if(!f) { rfbClientErr("Could not open framebuffer.ppm\n"); return; } fprintf(f,"P6\n# %s\n%d %d\n255\n",client->desktopName,client->width,client->height); for(j=0;j<client->height*row_stride;j+=row_stride) for(i=0;i<client->width*bpp;i+=bpp) { unsigned char* p=client->frameBuffer+j+i; unsigned int v; if(bpp==4) v=*(unsigned int*)p; else if(bpp==2) v=*(unsigned short*)p; else v=*(unsigned char*)p; fputc((v>>pf->redShift)*256/(pf->redMax+1),f); fputc((v>>pf->greenShift)*256/(pf->greenMax+1),f); fputc((v>>pf->blueShift)*256/(pf->blueMax+1),f); } fclose(f); }
rfbClient* rfbGetClient(int bitsPerSample,int samplesPerPixel, int bytesPerPixel) { rfbClient* client=(rfbClient*)calloc(sizeof(rfbClient),1); if(!client) { rfbClientErr("Couldn't allocate client structure!\n"); return NULL; } initAppData(&client->appData); client->endianTest = 1; client->programName=""; client->serverHost=strdup(""); client->serverPort=5900; client->destHost = NULL; client->destPort = 5900; client->CurrentKeyboardLedState = 0; client->HandleKeyboardLedState = (HandleKeyboardLedStateProc)DummyPoint; /* default: use complete frame buffer */ client->updateRect.x = -1; client->format.bitsPerPixel = bytesPerPixel*8; client->format.depth = bitsPerSample*samplesPerPixel; client->appData.requestedDepth=client->format.depth; client->format.bigEndian = *(char *)&client->endianTest?FALSE:TRUE; client->format.trueColour = TRUE; if (client->format.bitsPerPixel == 8) { client->format.redMax = 7; client->format.greenMax = 7; client->format.blueMax = 3; client->format.redShift = 0; client->format.greenShift = 3; client->format.blueShift = 6; } else { client->format.redMax = (1 << bitsPerSample) - 1; client->format.greenMax = (1 << bitsPerSample) - 1; client->format.blueMax = (1 << bitsPerSample) - 1; if(!client->format.bigEndian) { client->format.redShift = 0; client->format.greenShift = bitsPerSample; client->format.blueShift = bitsPerSample * 2; } else { if(client->format.bitsPerPixel==8*3) { client->format.redShift = bitsPerSample*2; client->format.greenShift = bitsPerSample*1; client->format.blueShift = 0; } else { client->format.redShift = bitsPerSample*3; client->format.greenShift = bitsPerSample*2; client->format.blueShift = bitsPerSample; } } } client->bufoutptr=client->buf; client->buffered=0; #ifdef LIBVNCSERVER_HAVE_LIBZ client->raw_buffer_size = -1; client->decompStreamInited = FALSE; #ifdef LIBVNCSERVER_HAVE_LIBJPEG memset(client->zlibStreamActive,0,sizeof(rfbBool)*4); client->jpegSrcManager = NULL; #endif #endif client->HandleCursorPos = DummyPoint; client->SoftCursorLockArea = DummyRect; client->SoftCursorUnlockScreen = Dummy; client->GotFrameBufferUpdate = DummyRect; client->FinishedFrameBufferUpdate = NULL; client->GetPassword = ReadPassword; client->MallocFrameBuffer = MallocFrameBuffer; client->Bell = Dummy; client->CurrentKeyboardLedState = 0; client->HandleKeyboardLedState = (HandleKeyboardLedStateProc)DummyPoint; client->QoS_DSCP = 0; client->authScheme = 0; client->subAuthScheme = 0; client->GetCredential = NULL; client->tlsSession = NULL; client->sock = -1; client->listenSock = -1; client->listenAddress = NULL; client->listen6Sock = -1; client->listen6Address = NULL; client->clientAuthSchemes = NULL; return client; }
int ListenAtTcpPortAndAddress(int port, const char *address) { int sock; int one = 1; #ifndef LIBVNCSERVER_IPv6 struct sockaddr_in addr; addr.sin_family = AF_INET; addr.sin_port = htons(port); if (address) { addr.sin_addr.s_addr = inet_addr(address); } else { addr.sin_addr.s_addr = htonl(INADDR_ANY); } if (!initSockets()) return -1; sock = socket(AF_INET, SOCK_STREAM, 0); if (sock < 0) { rfbClientErr("ListenAtTcpPort: socket\n"); return -1; } if (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (const char *)&one, sizeof(one)) < 0) { rfbClientErr("ListenAtTcpPort: setsockopt\n"); close(sock); return -1; } if (bind(sock, (struct sockaddr *)&addr, sizeof(addr)) < 0) { rfbClientErr("ListenAtTcpPort: bind\n"); close(sock); return -1; } #else int rv; struct addrinfo hints, *servinfo, *p; char port_str[8]; snprintf(port_str, 8, "%d", port); memset(&hints, 0, sizeof(hints)); hints.ai_family = AF_UNSPEC; hints.ai_socktype = SOCK_STREAM; hints.ai_flags = AI_PASSIVE; /* fill in wildcard address if address == NULL */ if (!initSockets()) return -1; if ((rv = getaddrinfo(address, port_str, &hints, &servinfo)) != 0) { rfbClientErr("ListenAtTcpPortAndAddress: error in getaddrinfo: %s\n", gai_strerror(rv)); return -1; } /* loop through all the results and bind to the first we can */ for(p = servinfo; p != NULL; p = p->ai_next) { if ((sock = socket(p->ai_family, p->ai_socktype, p->ai_protocol)) < 0) { continue; } #ifdef IPV6_V6ONLY /* we have seperate IPv4 and IPv6 sockets since some OS's do not support dual binding */ if (p->ai_family == AF_INET6 && setsockopt(sock, IPPROTO_IPV6, IPV6_V6ONLY, (char *)&one, sizeof(one)) < 0) { rfbClientErr("ListenAtTcpPortAndAddress: error in setsockopt IPV6_V6ONLY: %s\n", strerror(errno)); close(sock); freeaddrinfo(servinfo); return -1; } #endif if (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (char *)&one, sizeof(one)) < 0) { rfbClientErr("ListenAtTcpPortAndAddress: error in setsockopt SO_REUSEADDR: %s\n", strerror(errno)); close(sock); freeaddrinfo(servinfo); return -1; } if (bind(sock, p->ai_addr, p->ai_addrlen) < 0) { close(sock); continue; } break; } if (p == NULL) { rfbClientErr("ListenAtTcpPortAndAddress: error in bind: %s\n", strerror(errno)); return -1; } /* all done with this structure now */ freeaddrinfo(servinfo); #endif if (listen(sock, 5) < 0) { rfbClientErr("ListenAtTcpPort: listen\n"); close(sock); return -1; } return sock; }
int ConnectClientToTcpAddr6(const char *hostname, int port) { #ifdef LIBVNCSERVER_IPv6 int sock; int n; struct addrinfo hints, *res, *ressave; char port_s[10]; int one = 1; if (!initSockets()) return -1; snprintf(port_s, 10, "%d", port); memset(&hints, 0, sizeof(struct addrinfo)); hints.ai_family = AF_UNSPEC; hints.ai_socktype = SOCK_STREAM; if ((n = getaddrinfo(hostname, port_s, &hints, &res))) { rfbClientErr("ConnectClientToTcpAddr6: getaddrinfo (%s)\n", gai_strerror(n)); return -1; } ressave = res; sock = -1; while (res) { sock = socket(res->ai_family, res->ai_socktype, res->ai_protocol); if (sock >= 0) { if (connect(sock, res->ai_addr, res->ai_addrlen) == 0) break; close(sock); sock = -1; } res = res->ai_next; } freeaddrinfo(ressave); if (sock == -1) { rfbClientErr("ConnectClientToTcpAddr6: connect\n"); return -1; } if (setsockopt(sock, IPPROTO_TCP, TCP_NODELAY, (char *)&one, sizeof(one)) < 0) { rfbClientErr("ConnectToTcpAddr: setsockopt\n"); close(sock); return -1; } return sock; #else rfbClientErr("ConnectClientToTcpAddr6: IPv6 disabled\n"); return -1; #endif }
static void h264_init_decoder(int width, int height) { VAStatus va_status; if (va_context_id) { rfbClientLog("%s: va_dpy already initialized\n", __FUNCTION__); } if (va_dpy != NULL) { rfbClientLog("%s: Re-initializing H.264 decoder\n", __FUNCTION__); } else { rfbClientLog("%s: initializing H.264 decoder\n", __FUNCTION__); /* Attach VA display to local X display */ Display *win_display = (Display *)XOpenDisplay(":0.0"); if (win_display == NULL) { rfbClientErr("Can't connect to local display\n"); exit(-1); } int major_ver, minor_ver; va_dpy = vaGetDisplay(win_display); va_status = vaInitialize(va_dpy, &major_ver, &minor_ver); CHECK_VASTATUS(va_status, "vaInitialize"); rfbClientLog("%s: libva version %d.%d found\n", __FUNCTION__, major_ver, minor_ver); } /* Check for VLD entrypoint */ int num_entrypoints; VAEntrypoint entrypoints[5]; int vld_entrypoint_found = 0; /* Change VAProfileH264High if needed */ VAProfile profile = VAProfileH264High; va_status = vaQueryConfigEntrypoints(va_dpy, profile, entrypoints, &num_entrypoints); CHECK_VASTATUS(va_status, "vaQueryConfigEntrypoints"); int i; for (i = 0; i < num_entrypoints; ++i) { if (entrypoints[i] == VAEntrypointVLD) { vld_entrypoint_found = 1; break; } } if (vld_entrypoint_found == 0) { rfbClientErr("VLD entrypoint not found\n"); exit(1); } /* Create configuration for the decode pipeline */ VAConfigAttrib attrib; attrib.type = VAConfigAttribRTFormat; va_status = vaCreateConfig(va_dpy, profile, VAEntrypointVLD, &attrib, 1, &va_config_id); CHECK_VASTATUS(va_status, "vaCreateConfig"); /* Create VA surfaces */ for (i = 0; i < SURFACE_NUM; ++i) { va_surface_id[i] = VA_INVALID_ID; va_pic_param_buf_id[i] = VA_INVALID_ID; va_mat_param_buf_id[i] = VA_INVALID_ID; va_sp_param_buf_id[i] = VA_INVALID_ID; va_d_param_buf_id[i] = VA_INVALID_ID; } va_status = vaCreateSurfaces(va_dpy, width, height, VA_RT_FORMAT_YUV420, SURFACE_NUM, &va_surface_id[0]); CHECK_VASTATUS(va_status, "vaCreateSurfaces"); for (i = 0; i < SURFACE_NUM; ++i) { DebugLog(("%s: va_surface_id[%d] = %p\n", __FUNCTION__, i, va_surface_id[i])); } /* Create VA context */ va_status = vaCreateContext(va_dpy, va_config_id, width, height, 0/*VA_PROGRESSIVE*/, &va_surface_id[0], SURFACE_NUM, &va_context_id); CHECK_VASTATUS(va_status, "vaCreateContext"); DebugLog(("%s: VA context created (id: %d)\n", __FUNCTION__, va_context_id)); /* Instantiate decode pipeline */ va_status = vaBeginPicture(va_dpy, va_context_id, va_surface_id[0]); CHECK_VASTATUS(va_status, "vaBeginPicture"); rfbClientLog("%s: H.264 decoder initialized\n", __FUNCTION__); }
int CreateMulticastSocket(struct sockaddr_storage multicastSockAddr, int so_recvbuf) { int sock; struct sockaddr_storage localAddr; int optval; socklen_t optval_len = sizeof(optval); int dfltrcvbuf; if (!initSockets()) return -1; localAddr = multicastSockAddr; /* set source addr of localAddr to ANY, the rest is the same as in multicastSockAddr */ if(localAddr.ss_family == AF_INET) ((struct sockaddr_in*) &localAddr)->sin_addr.s_addr = htonl(INADDR_ANY); else if(localAddr.ss_family == AF_INET6) ((struct sockaddr_in6*) &localAddr)->sin6_addr = in6addr_any; else { rfbClientErr("CreateMulticastSocket: neither IPv4 nor IPv6 address received\n"); return -1; } optval = 1; if((sock = socket(localAddr.ss_family, SOCK_DGRAM, 0)) < 0) { #ifdef WIN32 errno=WSAGetLastError(); #endif rfbClientErr("CreateMulticastSocket: error creating socket: %s\n", strerror(errno)); return -1; } optval = 1; if(setsockopt(sock,SOL_SOCKET,SO_REUSEADDR,(char*)&optval,sizeof(optval)) < 0) { #ifdef WIN32 errno=WSAGetLastError(); #endif rfbClientErr("CreateMulticastSocket: error setting reuse addr: %s\n", strerror(errno)); close(sock); return -1; } /* get/set socket receive buffer */ if(getsockopt(sock, SOL_SOCKET, SO_RCVBUF,(char*)&optval, &optval_len) <0) { #ifdef WIN32 errno=WSAGetLastError(); #endif rfbClientErr("CreateMulticastSocket: error getting rcv buf size: %s\n", strerror(errno)); close(sock); return -1; } dfltrcvbuf = optval; optval = so_recvbuf; if(setsockopt(sock,SOL_SOCKET,SO_RCVBUF,(char*)&optval,sizeof(optval)) < 0) { #ifdef WIN32 errno=WSAGetLastError(); #endif rfbClientErr("CreateMulticastSocket: error setting rcv buf size: %s\n", strerror(errno)); close(sock); return -1; } if(getsockopt(sock, SOL_SOCKET, SO_RCVBUF,(char*)&optval, &optval_len) <0) { #ifdef WIN32 errno=WSAGetLastError(); #endif rfbClientErr("CreateMulticastSocket: error getting set rcv buf size: %s\n", strerror(errno)); close(sock); return -1; } rfbClientLog("MulticastVNC: tried to set socket receive buffer from %d to %d, got %d\n", dfltrcvbuf, so_recvbuf, optval); if(bind(sock, (struct sockaddr*)&localAddr, sizeof(localAddr)) < 0) { #ifdef WIN32 errno=WSAGetLastError(); #endif rfbClientErr("CreateMulticastSocket: error binding socket: %s\n", strerror(errno)); close(sock); return -1; } /* Join the multicast group. We do this seperately for IPv4 and IPv6. */ if(multicastSockAddr.ss_family == AF_INET) { struct ip_mreq multicastRequest; memcpy(&multicastRequest.imr_multiaddr, &((struct sockaddr_in*) &multicastSockAddr)->sin_addr, sizeof(multicastRequest.imr_multiaddr)); multicastRequest.imr_interface.s_addr = htonl(INADDR_ANY); if(setsockopt(sock, IPPROTO_IP, IP_ADD_MEMBERSHIP, (char*) &multicastRequest, sizeof(multicastRequest)) < 0) { #ifdef WIN32 errno=WSAGetLastError(); #endif rfbClientErr("CreateMulticastSocket: error joining IPv4 multicast group: %s\n", strerror(errno)); close(sock); return -1; } } else if(multicastSockAddr.ss_family == AF_INET6) { struct ipv6_mreq multicastRequest; memcpy(&multicastRequest.ipv6mr_multiaddr, &((struct sockaddr_in6*) &multicastSockAddr)->sin6_addr, sizeof(multicastRequest.ipv6mr_multiaddr)); multicastRequest.ipv6mr_interface = 0; if(setsockopt(sock, IPPROTO_IPV6, IPV6_JOIN_GROUP, (char*) &multicastRequest, sizeof(multicastRequest)) < 0) { #ifdef WIN32 errno=WSAGetLastError(); #endif rfbClientErr("CreateMulticastSocket: error joining IPv6 multicast group: %s\n", strerror(errno)); close(sock); return -1; } } else { rfbClientErr("CreateMulticastSocket: neither IPv6 nor IPv6 specified"); close(sock); return -1; } /* this is important for ReadFromRFBServerMulticast() */ if(!SetNonBlocking(sock)) { close(sock); return -1; } return sock; }
rfbBool ReadFromRFBServerMulticast(rfbClient* client, char *out, unsigned int n) { ghpringbuf *pbuf = client->multicastPacketBuf; Packet p; if(client->multicastSock < 0 || !pbuf) return FALSE; /* read until packet buffer (potentially) full or nothing more to read */ while(client->multicastRcvBufLen + MULTICAST_READBUF_SZ <= client->multicastRcvBufSize && ghpringbuf_count(pbuf) < pbuf->capacity) { int r; r = recvfrom(client->multicastSock, client->multicastReadBuf, MULTICAST_READBUF_SZ, 0, NULL, NULL); if (r <= 0) { if (r < 0) { /* some error */ #ifdef WIN32 errno=WSAGetLastError(); #endif if (errno == EWOULDBLOCK || errno == EAGAIN) { /* nothing more to read */ r = 0; break; } else { rfbClientErr("ReadFromRFBServerMulticast (%d: %s)\n", errno, strerror(errno)); return FALSE; } } else { /* read returned 0 */ if (errorMessageOnReadFailure) rfbClientLog("VNC server closed connection\n"); return FALSE; } } /* successfully read a packet at this point */ client->multicastBytesRcvd += r; p.datalen = r; p.data = malloc(p.datalen); memcpy(p.data, client->multicastReadBuf, p.datalen); ghpringbuf_put(pbuf, &p); client->multicastRcvBufLen += p.datalen; #ifdef MULTICAST_DEBUG rfbClientLog("MulticastVNC DEBUG: ReadFromRFBServerMulticast() read %d bytes from socket.\n", r); rfbClientLog("MulticastVNC DEBUG: ReadFromRFBServerMulticast() %d packets buffered now.\n", pbuf->count); #endif } /* now service the request of n bytes (which have to be <= what's buffered of the packet) */ #ifdef MULTICAST_DEBUG rfbClientLog("MulticastVNC DEBUG: ReadFromRFBServerMulticast() bytes requested: %d \n", n); rfbClientLog("MulticastVNC DEBUG: ReadFromRFBServerMulticast() bytes in buffer: %d \n", client->multicastRcvBufLen); rfbClientLog("MulticastVNC DEBUG: ReadFromRFBServerMulticast() pckts in buffer: %d \n", ghpringbuf_count(pbuf)); #endif if (n) { if(ghpringbuf_at(pbuf, 0, &p) && n <= p.datalen && (client->multicastbuffered ? n <= client->multicastbuffered : 1)) { if(client->multicastbuffered == 0) { /* new packet to be consumed */ client->multicastbuffered = p.datalen; client->multicastbufoutptr = p.data; } /* copy requested number of bytes to out buffer */ memcpy(out, client->multicastbufoutptr, n); client->multicastbufoutptr += n; client->multicastbuffered -= n; if(client->multicastbuffered == 0) { /* packet consumed */ client->multicastRcvBufLen -= p.datalen; ghpringbuf_pop(pbuf); #ifdef MULTICAST_DEBUG rfbClientLog("MulticastVNC DEBUG: ReadFromRFBServerMulticast() packet consumed, now %d packets in buffer.\n", pbuf->count); #endif } } else return FALSE; } return TRUE; }
rfbBool ReadFromRFBServer(rfbClient* client, char *out, unsigned int n) { #undef DEBUG_READ_EXACT #ifdef DEBUG_READ_EXACT char* oout=out; int nn=n; rfbClientLog("ReadFromRFBServer %d bytes\n",n); #endif /* Handle attempts to write to NULL out buffer that might occur when an outside malloc() fails. For instance, memcpy() to NULL results in undefined behaviour and probably memory corruption.*/ if(!out) return FALSE; if (client->serverPort==-1) { /* vncrec playing */ rfbVNCRec* rec = client->vncRec; struct timeval tv; if (rec->readTimestamp) { rec->readTimestamp = FALSE; if (!fread(&tv,sizeof(struct timeval),1,rec->file)) return FALSE; tv.tv_sec = rfbClientSwap32IfLE (tv.tv_sec); tv.tv_usec = rfbClientSwap32IfLE (tv.tv_usec); if (rec->tv.tv_sec!=0 && !rec->doNotSleep) { struct timeval diff; diff.tv_sec = tv.tv_sec - rec->tv.tv_sec; diff.tv_usec = tv.tv_usec - rec->tv.tv_usec; if(diff.tv_usec<0) { diff.tv_sec--; diff.tv_usec+=1000000; } #ifndef WIN32 sleep (diff.tv_sec); usleep (diff.tv_usec); #else Sleep (diff.tv_sec * 1000 + diff.tv_usec/1000); #endif } rec->tv=tv; } return (fread(out,1,n,rec->file) != n ? FALSE : TRUE); } if (n <= client->buffered) { memcpy(out, client->bufoutptr, n); client->bufoutptr += n; client->buffered -= n; #ifdef DEBUG_READ_EXACT goto hexdump; #endif return TRUE; } memcpy(out, client->bufoutptr, client->buffered); out += client->buffered; n -= client->buffered; client->bufoutptr = client->buf; client->buffered = 0; if (n <= RFB_BUF_SIZE) { while (client->buffered < n) { int i; if (client->tlsSession) i = ReadFromTLS(client, client->buf + client->buffered, RFB_BUF_SIZE - client->buffered); else #ifdef LIBVNCSERVER_HAVE_SASL if (client->saslconn) i = ReadFromSASL(client, client->buf + client->buffered, RFB_BUF_SIZE - client->buffered); else { #endif /* LIBVNCSERVER_HAVE_SASL */ i = read(client->sock, client->buf + client->buffered, RFB_BUF_SIZE - client->buffered); #ifdef WIN32 if (i < 0) errno=WSAGetLastError(); #endif #ifdef LIBVNCSERVER_HAVE_SASL } #endif if (i <= 0) { if (i < 0) { if (errno == EWOULDBLOCK || errno == EAGAIN) { /* TODO: ProcessXtEvents(); */ WaitForMessage(client, 100000); i = 0; } else { rfbClientErr("read (%d: %s)\n",errno,strerror(errno)); return FALSE; } } else { if (errorMessageOnReadFailure) { rfbClientLog("VNC server closed connection\n"); } return FALSE; } } client->buffered += i; } memcpy(out, client->bufoutptr, n); client->bufoutptr += n; client->buffered -= n; } else { while (n > 0) { int i; if (client->tlsSession) i = ReadFromTLS(client, out, n); else #ifdef LIBVNCSERVER_HAVE_SASL if (client->saslconn) i = ReadFromSASL(client, out, n); else #endif i = read(client->sock, out, n); if (i <= 0) { if (i < 0) { #ifdef WIN32 errno=WSAGetLastError(); #endif if (errno == EWOULDBLOCK || errno == EAGAIN) { /* TODO: ProcessXtEvents(); */ WaitForMessage(client, 100000); i = 0; } else { rfbClientErr("read (%s)\n",strerror(errno)); return FALSE; } } else { if (errorMessageOnReadFailure) { rfbClientLog("VNC server closed connection\n"); } return FALSE; } } out += i; n -= i; } } #ifdef DEBUG_READ_EXACT hexdump: { int ii; for(ii=0;ii<nn;ii++) fprintf(stderr,"%02x ",(unsigned char)oout[ii]); fprintf(stderr,"\n"); } #endif return TRUE; }
rfbBool SetNonBlocking(int sock) { #ifdef WIN32 unsigned long block=1; if(ioctlsocket(sock, FIONBIO, &block) == SOCKET_ERROR) { errno=WSAGetLastError(); #else int flags = fcntl(sock, F_GETFL); if(flags < 0 || fcntl(sock, F_SETFL, flags | O_NONBLOCK) < 0) { #endif rfbClientErr("Setting socket to non-blocking failed: %s\n",strerror(errno)); return FALSE; } return TRUE; } /* * SetDSCP sets a socket's IP QoS parameters aka Differentiated Services Code Point field */ rfbBool SetDSCP(int sock, int dscp) { #ifdef WIN32 rfbClientErr("Setting of QoS IP DSCP not implemented for Windows\n"); return TRUE; #else int level, cmd; struct sockaddr addr; socklen_t addrlen = sizeof(addr); if(getsockname(sock, &addr, &addrlen) != 0) { rfbClientErr("Setting socket QoS failed while getting socket address: %s\n",strerror(errno)); return FALSE; } switch(addr.sa_family) { #if defined LIBVNCSERVER_IPv6 && defined IPV6_TCLASS case AF_INET6: level = IPPROTO_IPV6; cmd = IPV6_TCLASS; break; #endif case AF_INET: level = IPPROTO_IP; cmd = IP_TOS; break; default: rfbClientErr("Setting socket QoS failed: Not bound to IP address"); return FALSE; } if(setsockopt(sock, level, cmd, (void*)&dscp, sizeof(dscp)) != 0) { rfbClientErr("Setting socket QoS failed: %s\n", strerror(errno)); return FALSE; } return TRUE; #endif }
rfbBool ReadFromRFBServer(rfbClient* client, char *out, unsigned int n) { #undef DEBUG_READ_EXACT #ifdef DEBUG_READ_EXACT char* oout=out; int nn=n; rfbClientLog("ReadFromRFBServer %d bytes\n",n); #endif if (client->serverPort==-1) { /* vncrec playing */ rfbVNCRec* rec = client->vncRec; struct timeval tv; if (rec->readTimestamp) { rec->readTimestamp = FALSE; if (!fread(&tv,sizeof(struct timeval),1,rec->file)) return FALSE; tv.tv_sec = rfbClientSwap32IfLE (tv.tv_sec); tv.tv_usec = rfbClientSwap32IfLE (tv.tv_usec); if (rec->tv.tv_sec!=0 && !rec->doNotSleep) { struct timeval diff; diff.tv_sec = tv.tv_sec - rec->tv.tv_sec; diff.tv_usec = tv.tv_usec - rec->tv.tv_usec; if(diff.tv_usec<0) { diff.tv_sec--; diff.tv_usec+=1000000; } #ifndef __MINGW32__ sleep (diff.tv_sec); usleep (diff.tv_usec); #else Sleep (diff.tv_sec * 1000 + diff.tv_usec/1000); #endif } rec->tv=tv; } return (fread(out,1,n,rec->file) != n ? FALSE : TRUE); } if (n <= client->buffered) { memcpy(out, client->bufoutptr, n); client->bufoutptr += n; client->buffered -= n; #ifdef DEBUG_READ_EXACT goto hexdump; #endif return TRUE; } memcpy(out, client->bufoutptr, client->buffered); out += client->buffered; n -= client->buffered; client->bufoutptr = client->buf; client->buffered = 0; if (n <= RFB_BUF_SIZE) { while (client->buffered < n) { int i; if (client->tlsSession) { i = ReadFromTLS(client, client->buf + client->buffered, RFB_BUF_SIZE - client->buffered); } else { i = read(client->sock, client->buf + client->buffered, RFB_BUF_SIZE - client->buffered); } if (i <= 0) { if (i < 0) { #ifdef WIN32 errno=WSAGetLastError(); #endif if (errno == EWOULDBLOCK || errno == EAGAIN) { /* TODO: ProcessXtEvents(); */ WaitForMessage(client, 100000); i = 0; } else { rfbClientErr("read (%d: %s)\n",errno,strerror(errno)); return FALSE; } } else { if (errorMessageOnReadFailure) { rfbClientLog("VNC server closed connection\n"); } return FALSE; } } client->buffered += i; } memcpy(out, client->bufoutptr, n); client->bufoutptr += n; client->buffered -= n; } else { while (n > 0) { int i; if (client->tlsSession) { i = ReadFromTLS(client, out, n); } else { i = read(client->sock, out, n); } if (i <= 0) { if (i < 0) { #ifdef WIN32 errno=WSAGetLastError(); #endif if (errno == EWOULDBLOCK || errno == EAGAIN) { /* TODO: ProcessXtEvents(); */ WaitForMessage(client, 100000); i = 0; } else { rfbClientErr("read (%s)\n",strerror(errno)); return FALSE; } } else { if (errorMessageOnReadFailure) { rfbClientLog("VNC server closed connection\n"); } return FALSE; } } out += i; n -= i; } } #ifdef DEBUG_READ_EXACT hexdump: { int ii; for(ii=0;ii<nn;ii++) fprintf(stderr,"%02x ",(unsigned char)oout[ii]); fprintf(stderr,"\n"); } #endif return TRUE; }
rfbBool WriteToRFBServer(rfbClient* client, char *buf, int n) { fd_set fds; int i = 0; int j; const char *obuf = buf; #ifdef LIBVNCSERVER_HAVE_SASL const char *output; unsigned int outputlen; int err; #endif /* LIBVNCSERVER_HAVE_SASL */ if (client->serverPort==-1) return TRUE; /* vncrec playing */ if (client->tlsSession) { /* WriteToTLS() will guarantee either everything is written, or error/eof returns */ i = WriteToTLS(client, buf, n); if (i <= 0) return FALSE; return TRUE; } #ifdef LIBVNCSERVER_HAVE_SASL if (client->saslconn) { err = sasl_encode(client->saslconn, buf, n, &output, &outputlen); if (err != SASL_OK) { rfbClientLog("Failed to encode SASL data %s", sasl_errstring(err, NULL, NULL)); return FALSE; } obuf = output; n = outputlen; } #endif /* LIBVNCSERVER_HAVE_SASL */ while (i < n) { j = write(client->sock, obuf + i, (n - i)); if (j <= 0) { if (j < 0) { #ifdef WIN32 errno=WSAGetLastError(); #endif if (errno == EWOULDBLOCK || #ifdef LIBVNCSERVER_ENOENT_WORKAROUND errno == ENOENT || #endif errno == EAGAIN) { FD_ZERO(&fds); FD_SET(client->sock,&fds); if (select(client->sock+1, NULL, &fds, NULL, NULL) <= 0) { rfbClientErr("select\n"); return FALSE; } j = 0; } else { rfbClientErr("write\n"); return FALSE; } } else { rfbClientLog("write failed\n"); return FALSE; } } i += j; } return TRUE; }