示例#1
0
文件: inet.c 项目: 00farts/italc-1
int listen_tcp(int port, in_addr_t iface, int try6) {
	int fd = -1;
	int fail4 = noipv4;
	if (getenv("IPV4_FAILS")) {
		fail4 = 2;
	}

	if (port <= 0 || 65535 < port) {
		/* for us, invalid port means do not listen. */
		return -1;
	}

	if (fail4) {
		if (fail4 > 1) {
			rfbLog("TESTING: IPV4_FAILS for listen_tcp: port=%d try6=%d\n", port, try6);
		}
	} else {
		fd = rfbListenOnTCPPort(port, iface);
	}

	if (fd >= 0) {
		return fd;
	}
	if (fail4 > 1) {
		rfbLogPerror("listen_tcp: listen failed");
	}

	if (fd < 0 && try6 && ipv6_listen && !noipv6) {
#if X11VNC_IPV6
		char *save = listen_str6;
		if (iface == htonl(INADDR_LOOPBACK)) {
			listen_str6 = "localhost";
			rfbLog("listen_tcp: retrying on IPv6 in6addr_loopback ...\n");
			fd = listen6(port);
		} else if (iface == htonl(INADDR_ANY)) {
			listen_str6 = NULL;
			rfbLog("listen_tcp: retrying on IPv6 in6addr_any ...\n");
			fd = listen6(port);
		}
		listen_str6 = save;
#endif
	}
	return fd;
}
示例#2
0
//! handle matrix update message
rfbBool VncServer::handleMatricesMessage(rfbClientPtr cl, void *data,
      const rfbClientToServerMsg *message) {

   if (message->type != rfbMatrices)
      return FALSE;

   matricesMsg msg;

   int n = rfbReadExact(cl, ((char *)&msg)+1, sizeof(msg)-1);
   if (n <= 0) {
      if (n!= 0)
         rfbLogPerror("handleMatricesMessage: read");
      rfbCloseClient(cl);
      return TRUE;
   }

   size_t viewNum = msg.viewNum >= 0 ? msg.viewNum : 0;
   if (viewNum >= plugin->m_viewData.size()) {
       plugin->m_viewData.resize(viewNum+1);
   }
   
   plugin->resize(viewNum, msg.width, msg.height);

   ViewData &vd = plugin->m_viewData[viewNum];

   vd.nparam.matrixTime = msg.time;
   vd.nparam.requestNumber = msg.requestNumber;

   for (int i=0; i<16; ++i) {
      vd.nparam.proj.data()[i] = msg.proj[i];
      vd.nparam.view.data()[i] = msg.view[i];
      vd.nparam.model.data()[i] = msg.model[i];
   }

   //std::cerr << "handleMatrices: view " << msg.viewNum << ", proj: " << vd.nparam.proj << std::endl;

   if (msg.last) {
       for (int i=0; i<plugin->numViews(); ++i) {
           plugin->m_viewData[i].param = plugin->m_viewData[i].nparam;
       }
   }

   return TRUE;
}
示例#3
0
int
SkipExact(rfbClientPtr cl, int len)
{
    char *tmpbuf = NULL;
    int bufLen = min(len, 65536), i, retval = 1;

    tmpbuf = (char *)malloc(bufLen);
    if (tmpbuf == NULL) {
        rfbLogPerror("SkipExact: out of memory");
        return -1;
    }

    for (i = 0; i < len; i += bufLen) {
        retval = ReadExact(cl, tmpbuf, min(bufLen, len - i));
        if (retval <= 0) break;
    }

    free(tmpbuf);
    return retval;
}
示例#4
0
文件: main.c 项目: 21hub/libvncserver
static void*
listenerRun(void *data)
{
    rfbScreenInfoPtr screen=(rfbScreenInfoPtr)data;
    int client_fd;
    struct sockaddr_storage peer;
    rfbClientPtr cl = NULL;
    socklen_t len;
    fd_set listen_fds;  /* temp file descriptor list for select() */

    /* TODO: this thread wont die by restarting the server */
    /* TODO: HTTP is not handled */
    while (1) {
        client_fd = -1;
        FD_ZERO(&listen_fds);
	if(screen->listenSock >= 0) 
	  FD_SET(screen->listenSock, &listen_fds);
	if(screen->listen6Sock >= 0) 
	  FD_SET(screen->listen6Sock, &listen_fds);

        if (select(screen->maxFd+1, &listen_fds, NULL, NULL, NULL) == -1) {
            rfbLogPerror("listenerRun: error in select");
            return NULL;
        }
	
	/* there is something on the listening sockets, handle new connections */
	len = sizeof (peer);
	if (FD_ISSET(screen->listenSock, &listen_fds)) 
	    client_fd = accept(screen->listenSock, (struct sockaddr*)&peer, &len);
	else if (FD_ISSET(screen->listen6Sock, &listen_fds))
	    client_fd = accept(screen->listen6Sock, (struct sockaddr*)&peer, &len);

	if(client_fd >= 0)
	  cl = rfbNewClient(screen,client_fd);
	if (cl && !cl->onHold )
	  rfbStartOnHoldClient(cl);
    }
    return(NULL);
}
示例#5
0
static char *getsslscript(char *cdir, char *name, char *script) {
	char *openssl = find_openssl_bin();
	char *tmp, *scr, *cdir_use;
	FILE *out;

	if (! openssl || openssl[0] == '\0') {
		exit(1);
	}

	if (!name || !script) {
		exit(1);
	}

	cdir_use = get_Cert_dir(cdir, &tmp);
	if (!cdir_use || !tmp) {
		exit(1);
	}

	scr = (char *) malloc(strlen(tmp) + 1 + strlen(name) + 30);

	sprintf(scr, "%s/%s.%d.sh", tmp, name, getpid());
	out = fopen(scr, "w");
	if (! out) {
		rfbLog("could not open: %s\n", scr);
		rfbLogPerror("fopen");
		exit(1);
	}
	fprintf(out, "%s", script);
	fclose(out);

	rfbLog("Using openssl:   %s\n", openssl);
	rfbLog("Using certs dir: %s\n", cdir_use);
	fprintf(stderr, "\n");

	set_env("BASE_DIR", cdir_use);
	set_env("OPENSSL", openssl);

	return scr;
}
示例#6
0
文件: VNCServer.cpp 项目: crubia/wt
int VNCServer::Client::Connect(WebSocket *ws)
{
	Debug(">VNCServer::Client::Connect [ws:%p,this:%p]\n",ws,this);
	//Store websocekt
	this->ws = ws;

	rfbProtocolVersionMsg pv;
	sprintf(pv,rfbProtocolVersionFormat,cl->screen->protocolMajorVersion,cl->screen->protocolMinorVersion);

	//Write protocol version
	if (rfbWriteExact(cl, pv, sz_rfbProtocolVersionMsg) < 0)
	{
		rfbLogPerror("rfbNewClient: write");
		rfbCloseClient(cl);
		rfbClientConnectionGone(cl);
		return Error("-Could not write protocol version");
	}

	//Enable extension
	for(rfbProtocolExtension* extension = rfbGetExtensionIterator(); extension; extension=extension->next)
	{
		void* data = NULL;
		/* if the extension does not have a newClient method, it wants
		* to be initialized later. */
		if(extension->newClient && extension->newClient(cl, &data))
			rfbEnableExtension(cl, extension, data);
	}
	rfbReleaseExtensionIterator();

	cl->onHold = FALSE;

	//Start thread
	createPriorityThread(&thread,run,this,0);

	Debug("<VNCServer::Client::Connect [ws:%p,this:%p]\n",ws,this);

	//OK
	return 1;
}
示例#7
0
static void
rfbSendTunnelingCaps(rfbClientPtr cl)
{
    rfbTunnelingCapsMsg caps;
    uint32_t nTypes = 0;		/* we don't support tunneling yet */

    rfbLog("tightvnc-filetransfer/rfbSendTunnelingCaps\n");

    caps.nTunnelTypes = Swap32IfLE(nTypes);
    if (rfbWriteExact(cl, (char *)&caps, sz_rfbTunnelingCapsMsg) < 0) {
	rfbLogPerror("rfbSendTunnelingCaps: write");
	rfbCloseClient(cl);
	return;
    }

    if (nTypes) {
	/* Dispatch client input to rfbProcessClientTunnelingType(). */
	/* The flow should not reach here as tunneling is not implemented. */
	rfbProcessClientTunnelingType(cl);
    } else {
	rfbSendAuthCaps(cl);
    }
}
示例#8
0
void
rfbHttpInitSockets(rfbScreenInfoPtr rfbScreen)
{
    if (rfbScreen->httpInitDone)
	return;

    rfbScreen->httpInitDone = TRUE;

    if (!rfbScreen->httpDir)
	return;

    if (rfbScreen->httpPort == 0) {
	rfbScreen->httpPort = rfbScreen->port-100;
    }

    if ((rfbScreen->httpListenSock =
      rfbListenOnTCPPort(rfbScreen->httpPort, rfbScreen->listenInterface)) < 0) {
	rfbLogPerror("ListenOnTCPPort");
	return;
    }
    rfbLog("Listening for HTTP connections on TCP port %d\n", rfbScreen->httpPort);
    rfbLog("  URL http://%s:%d\n",rfbScreen->thisHost,rfbScreen->httpPort);

#ifdef LIBVNCSERVER_IPv6
    if (rfbScreen->http6Port == 0) {
	rfbScreen->http6Port = rfbScreen->ipv6port-100;
    }

    if ((rfbScreen->httpListen6Sock
	 = rfbListenOnTCP6Port(rfbScreen->http6Port, rfbScreen->listen6Interface)) < 0) {
      /* ListenOnTCP6Port has its own detailed error printout */
      return;
    }
    rfbLog("Listening for HTTP connections on TCP6 port %d\n", rfbScreen->http6Port);
    rfbLog("  URL http://%s:%d\n",rfbScreen->thisHost,rfbScreen->http6Port);
#endif
}
示例#9
0
文件: auth.c 项目: djyos/djyos
static void
rfbVncAuthNone(rfbClientPtr cl)
{
    /* The built-in Mac OS X VNC client behaves in a non-conforming fashion
     * when the server version is 3.7 or later AND the list of security types
     * sent to the OS X client contains the 'None' authentication type AND
     * the OS X client sends back the 'None' type as its choice.  In this case,
     * and this case ONLY, the built-in Mac OS X VNC client will NOT send the
     * ClientInit message and instead will behave as though an implicit
     * ClientInit message containing a shared-flag of true has been sent.
     * The special state RFB_INITIALISATION_SHARED represents this case.
     * The Mac OS X VNC client can be detected by checking protocolMinorVersion
     * for a value of 889.  No other VNC client is known to use this value
     * for protocolMinorVersion. */
    uint32_t authResult;

    /* The built-in Mac OS X VNC client expects to NOT receive a SecurityResult
     * message for authentication type 'None'.  Since its protocolMinorVersion
     * is greater than 7 (it is 889) this case must be tested for specially. */
    if (cl->protocolMajorVersion==3 && cl->protocolMinorVersion > 7 && cl->protocolMinorVersion != 889) {
        rfbLog("rfbProcessClientSecurityType: returning securityResult for client rfb version >= 3.8\n");
        authResult = Swap32IfLE(rfbVncAuthOK);
        if (rfbWriteExact(cl, (char *)&authResult, 4) < 0) {
            rfbLogPerror("rfbAuthProcessClientMessage: write");
            rfbCloseClient(cl);
            return;
        }
    }
    cl->state = cl->protocolMinorVersion == 889 ? RFB_INITIALISATION_SHARED : RFB_INITIALISATION;
    if (cl->state == RFB_INITIALISATION_SHARED)
        /* In this case we must call rfbProcessClientMessage now because
         * otherwise we would hang waiting for data to be received from the
         * client (the ClientInit message which will never come). */
        rfbProcessClientMessage(cl);
    return;
}
示例#10
0
//! handle generic application message
rfbBool VncServer::handleApplicationMessage(rfbClientPtr cl, void *data,
      const rfbClientToServerMsg *message) {

   if (message->type != rfbApplication)
      return FALSE;

   if (!cl->clientData) {
      cl->clientData = new ClientData();

      appAnimationTimestep app;
      app.current = plugin->m_imageParam.timestep;
      app.total = plugin->m_numTimesteps;
      sendApplicationMessage(cl, rfbAnimationTimestep, sizeof(app), (char *)&app);
   }
   ClientData *cd = static_cast<ClientData *>(cl->clientData);
   cd->supportsApplication = true;

   applicationMsg msg;
   int n = rfbReadExact(cl, ((char *)&msg)+1, sizeof(msg)-1);
   if (n <= 0) {
      if (n!= 0)
         rfbLogPerror("handleApplicationMessage: read");
      rfbCloseClient(cl);
      return TRUE;
   }
   std::vector<char> buf(msg.size);
   n = rfbReadExact(cl, &buf[0], msg.size);
   if (n <= 0) {
      if (n!= 0)
         rfbLogPerror("handleApplicationMessage: read data");
      rfbCloseClient(cl);
      return TRUE;
   }

   if (plugin->m_appHandler) {
      bool handled = plugin->m_appHandler(msg.appType, buf);
      if (handled)
         return TRUE;
   }

   switch (msg.appType) {
      case rfbScreenConfig:
      {
         appScreenConfig app;
         memcpy(&app, &buf[0], sizeof(app));
         plugin->resize(0, app.width, app.height);
         plugin->m_screenConfig.hsize = app.hsize;
         plugin->m_screenConfig.vsize = app.vsize;
         for (int i=0; i<3; ++i) {
            plugin->m_screenConfig.pos[i] = app.screenPos[i];
            plugin->m_screenConfig.hpr[i] = app.screenRot[i];
         }
      }
      break;
      case rfbFeedback:
      {
         // not needed: handled via vistle connection
      }
      break;
      case rfbAnimationTimestep: {
         appAnimationTimestep app;
         memcpy(&app, &buf[0], sizeof(app));
         plugin->m_imageParam.timestep = app.current;
      }
      break;
   }

   return TRUE;
}
示例#11
0
文件: httpd.c 项目: 00farts/italc-1
void
rfbHttpCheckFds(rfbScreenInfoPtr rfbScreen)
{
    int nfds;
    fd_set fds;
    struct timeval tv;
    struct sockaddr_in addr;
    socklen_t addrlen = sizeof(addr);

    if (!rfbScreen->httpDir)
	return;

    if (rfbScreen->httpListenSock < 0)
	return;

    FD_ZERO(&fds);
    FD_SET(rfbScreen->httpListenSock, &fds);
    if (rfbScreen->httpSock >= 0) {
	FD_SET(rfbScreen->httpSock, &fds);
    }
    tv.tv_sec = 0;
    tv.tv_usec = 0;
    nfds = select(max(rfbScreen->httpSock,rfbScreen->httpListenSock) + 1, &fds, NULL, NULL, &tv);
    if (nfds == 0) {
	return;
    }
    if (nfds < 0) {
#ifdef WIN32
		errno = WSAGetLastError();
#endif
	if (errno != EINTR)
		rfbLogPerror("httpCheckFds: select");
	return;
    }

    if ((rfbScreen->httpSock >= 0) && FD_ISSET(rfbScreen->httpSock, &fds)) {
	httpProcessInput(rfbScreen);
    }

    if (FD_ISSET(rfbScreen->httpListenSock, &fds)) {
	if (rfbScreen->httpSock >= 0) close(rfbScreen->httpSock);

	if ((rfbScreen->httpSock = accept(rfbScreen->httpListenSock,
			       (struct sockaddr *)&addr, &addrlen)) < 0) {
	    rfbLogPerror("httpCheckFds: accept");
	    return;
	}
#ifdef USE_LIBWRAP
	if(!hosts_ctl("vnc",STRING_UNKNOWN,inet_ntoa(addr.sin_addr),
		      STRING_UNKNOWN)) {
	  rfbLog("Rejected HTTP connection from client %s\n",
		 inet_ntoa(addr.sin_addr));
	  close(rfbScreen->httpSock);
	  rfbScreen->httpSock=-1;
	  return;
	}
#endif
        if(!rfbSetNonBlocking(rfbScreen->httpSock)) {
	    close(rfbScreen->httpSock);
	    rfbScreen->httpSock=-1;
	    return;
	}
	/*AddEnabledDevice(httpSock);*/
    }
}
示例#12
0
void VncServer::encodeAndSend(int viewNum, int x0, int y0, int w, int h, const VncServer::ViewParameters &param, bool lastView) {

    //std::cerr << "encodeAndSend: view=" << viewNum << ", c=" << (void *)rgba(viewNum) << ", d=" << depth(viewNum) << std::endl;
    if (!m_resizeBlocked) {
        m_firstTile = true;
    }
    m_resizeBlocked = true;

    //vistle::StopWatch timer("encodeAndSend");
    const int tileWidth = m_tileWidth, tileHeight = m_tileHeight;
    static int framecount=0;
    ++framecount;

    for (int y=y0; y<y0+h; y+=tileHeight) {
        for (int x=x0; x<x0+w; x+=tileWidth) {

            // depth
            auto dt = new(tbb::task::allocate_root()) EncodeTask(m_resultQueue,
                    viewNum,
                    x, y,
                    std::min(tileWidth, x0+w-x),
                    std::min(tileHeight, y0+h-y),
                    depth(viewNum), m_imageParam, param);
            tbb::task::enqueue(*dt);
            ++m_queuedTiles;

            // color
            auto ct = new(tbb::task::allocate_root()) EncodeTask(m_resultQueue,
                    viewNum,
                    x, y,
                    std::min(tileWidth, x0+w-x),
                    std::min(tileHeight, y0+h-y),
                    rgba(viewNum), m_imageParam, param);
            tbb::task::enqueue(*ct);
            ++m_queuedTiles;
        }
    }

    bool tileReady = false;
    do {
        VncServer::EncodeResult result;
        tileReady = false;
        if (m_resultQueue.try_pop(result)) {
            --m_queuedTiles;
            tileReady = true;
            if (result.message) {
                tileMsg &msg = *result.message;
                if (m_firstTile) {
                    msg.flags |= rfbTileFirst;
                    //std::cerr << "first tile: req=" << msg.requestNumber << std::endl;
                }
                m_firstTile = false;
                if (m_queuedTiles == 0 && lastView) {
                    msg.flags |= rfbTileLast;
                    //std::cerr << "last tile: req=" << msg.requestNumber << std::endl;
                }
                msg.frameNumber = framecount;

                rfbCheckFds(m_screen, 0);
                rfbHttpCheckFds(m_screen);
                rfbClientIteratorPtr i = rfbGetClientIterator(m_screen);
                while (rfbClientPtr cl = rfbClientIteratorNext(i)) {
                    if (cl->clientData) {
                        rfbUpdateClient(cl);
                        if (rfbWriteExact(cl, (char *)&msg, sizeof(msg)) < 0) {
                            rfbLogPerror("sendTileMessage: write header");
                        }
                        if (result.payload && msg.size > 0) {
                            if (rfbWriteExact(cl, result.payload, msg.size) < 0) {
                                rfbLogPerror("sendTileMessage: write paylod");
                            }
                        }
                    }
                    rfbUpdateClient(cl);
                }
                rfbReleaseClientIterator(i);
            }
            delete[] result.payload;
            delete result.message;
        }
    } while (m_queuedTiles > 0 && (tileReady || lastView));

    if (lastView) {
        vassert(m_queuedTiles == 0);
        m_resizeBlocked = false;
        deferredResize();
    }
    //sleep(1);
}
示例#13
0
void
rfbInitSockets(rfbScreenInfoPtr rfbScreen)
{
    in_addr_t iface = rfbScreen->listenInterface;

    if (rfbScreen->socketState == RFB_SOCKET_READY) {
        return;
    }

    rfbScreen->socketState = RFB_SOCKET_READY;

    if (rfbScreen->inetdSock != -1) {
	const int one = 1;

        if(!rfbSetNonBlocking(rfbScreen->inetdSock))
	    return;

	if (setsockopt(rfbScreen->inetdSock, IPPROTO_TCP, TCP_NODELAY,
		       (char *)&one, sizeof(one)) < 0) {
	    rfbLogPerror("setsockopt");
	    return;
	}

    	FD_ZERO(&(rfbScreen->allFds));
    	FD_SET(rfbScreen->inetdSock, &(rfbScreen->allFds));
    	rfbScreen->maxFd = rfbScreen->inetdSock;
	return;
    }

    if(rfbScreen->autoPort) {
        int i;
        FD_ZERO(&(rfbScreen->allFds));

        rfbLog("Autoprobing TCP port \n");
        for (i = 5900; i < 6000; i++) {
            if ((rfbScreen->listenSock = rfbListenOnTCPPort(i, iface)) >= 0) {
		rfbScreen->port = i;
		break;
	    }
        }

        if (i >= 6000) {
	    rfbLogPerror("Failure autoprobing");
	    return;
        }

        rfbLog("Autoprobing selected TCP port %d\n", rfbScreen->port);
        FD_SET(rfbScreen->listenSock, &(rfbScreen->allFds));
        rfbScreen->maxFd = rfbScreen->listenSock;

#ifdef LIBVNCSERVER_IPv6
        rfbLog("Autoprobing TCP6 port \n");
	for (i = 5900; i < 6000; i++) {
            if ((rfbScreen->listen6Sock = rfbListenOnTCP6Port(i, rfbScreen->listen6Interface)) >= 0) {
		rfbScreen->ipv6port = i;
		break;
	    }
        }

        if (i >= 6000) {
	    rfbLogPerror("Failure autoprobing");
	    return;
        }

        rfbLog("Autoprobing selected TCP6 port %d\n", rfbScreen->ipv6port);
	FD_SET(rfbScreen->listen6Sock, &(rfbScreen->allFds));
	rfbScreen->maxFd = max((int)rfbScreen->listen6Sock,rfbScreen->maxFd);
#endif
    }
    else
    {
	    if(rfbScreen->port>0) {
      FD_ZERO(&(rfbScreen->allFds));

      if ((rfbScreen->listenSock = rfbListenOnTCPPort(rfbScreen->port, iface)) < 0) {
	rfbLogPerror("ListenOnTCPPort");
	return;
      }
      rfbLog("Listening for VNC connections on TCP port %d\n", rfbScreen->port);  
  
      FD_SET(rfbScreen->listenSock, &(rfbScreen->allFds));
      rfbScreen->maxFd = rfbScreen->listenSock;
	    }

#ifdef LIBVNCSERVER_IPv6
	    if (rfbScreen->ipv6port>0) {
      if ((rfbScreen->listen6Sock = rfbListenOnTCP6Port(rfbScreen->ipv6port, rfbScreen->listen6Interface)) < 0) {
	/* ListenOnTCP6Port has its own detailed error printout */
	return;
      }
      rfbLog("Listening for VNC connections on TCP6 port %d\n", rfbScreen->ipv6port);  
	
      FD_SET(rfbScreen->listen6Sock, &(rfbScreen->allFds));
      rfbScreen->maxFd = max((int)rfbScreen->listen6Sock,rfbScreen->maxFd);
	    }
#endif

    }

    if (rfbScreen->udpPort != 0) {
	rfbLog("rfbInitSockets: listening for input on UDP port %d\n",rfbScreen->udpPort);

	if ((rfbScreen->udpSock = rfbListenOnUDPPort(rfbScreen->udpPort, iface)) < 0) {
	    rfbLogPerror("ListenOnUDPPort");
	    return;
	}
	rfbLog("Listening for VNC connections on TCP port %d\n", rfbScreen->port);  

	FD_SET(rfbScreen->udpSock, &(rfbScreen->allFds));
	rfbScreen->maxFd = max((int)rfbScreen->udpSock,rfbScreen->maxFd);
    }
}
示例#14
0
文件: main.c 项目: 21hub/libvncserver
static void *
clientInput(void *data)
{
    rfbClientPtr cl = (rfbClientPtr)data;
    pthread_t output_thread;
    pthread_create(&output_thread, NULL, clientOutput, (void *)cl);

    while (1) {
	fd_set rfds, wfds, efds;
	struct timeval tv;
	int n;

	if (cl->sock == -1) {
	  /* Client has disconnected. */
            break;
        }

	FD_ZERO(&rfds);
	FD_SET(cl->sock, &rfds);
	FD_ZERO(&efds);
	FD_SET(cl->sock, &efds);

	/* Are we transferring a file in the background? */
	FD_ZERO(&wfds);
	if ((cl->fileTransfer.fd!=-1) && (cl->fileTransfer.sending==1))
	    FD_SET(cl->sock, &wfds);

	tv.tv_sec = 60; /* 1 minute */
	tv.tv_usec = 0;
	n = select(cl->sock + 1, &rfds, &wfds, &efds, &tv);
	if (n < 0) {
	    rfbLogPerror("ReadExact: select");
	    break;
	}
	if (n == 0) /* timeout */
	{
            rfbSendFileTransferChunk(cl);
	    continue;
        }
        
        /* We have some space on the transmit queue, send some data */
        if (FD_ISSET(cl->sock, &wfds))
            rfbSendFileTransferChunk(cl);

        if (FD_ISSET(cl->sock, &rfds) || FD_ISSET(cl->sock, &efds))
        {
#ifdef LIBVNCSERVER_WITH_WEBSOCKETS
            do {
                rfbProcessClientMessage(cl);
            } while (webSocketsHasDataInBuffer(cl));
#else
            rfbProcessClientMessage(cl);
#endif
        }
    }

    /* Get rid of the output thread. */
    LOCK(cl->updateMutex);
    TSIGNAL(cl->updateCond);
    UNLOCK(cl->updateMutex);
    IF_PTHREADS(pthread_join(output_thread, NULL));

    rfbClientConnectionGone(cl);

    return NULL;
}
示例#15
0
static void
AuthPAMUserPwdRspFunc(rfbClientPtr cl)
{
    CARD32      userLen;
    CARD32      pwdLen;
    char        userBuf[MAX_USER_LEN + 1];
    char        pwdBuf[MAX_PWD_LEN + 1];
    int         n;
    const char* emsg;

    n = ReadExact(cl->sock, (char*) &userLen, sizeof(userLen));
    if (n <= 0) {
        if (n != 0)
            rfbLogPerror("AuthPAMUserPwdRspFunc: read error");

        rfbCloseSock(cl->sock);
        return;
    }

    userLen = Swap32IfLE(userLen);
    n = ReadExact(cl->sock, (char*) &pwdLen, sizeof(pwdLen));
    if (n <= 0) {
        if (n != 0)
            rfbLogPerror("AuthPAMUserPwdRspFunc: read error");

        rfbCloseSock(cl->sock);
        return;
    }

    pwdLen = Swap32IfLE(pwdLen);
    if ((userLen > MAX_USER_LEN) || (pwdLen > MAX_PWD_LEN)) {
        rfbLogPerror("AuthPAMUserPwdRspFunc: excessively large user name or password in response");
        rfbCloseSock(cl->sock);
        return;
    }

    n = ReadExact(cl->sock, userBuf, userLen);
    if (n <= 0) {
        if (n != 0)
            rfbLogPerror("AuthPAMUserPwdRspFunc: error reading user name");

        rfbCloseSock(cl->sock);
        return;
    }

    userBuf[userLen] = '\0';
    n = ReadExact(cl->sock, pwdBuf, pwdLen);
    if (n <= 0) {
        if (n != 0)
            rfbLogPerror("AuthPAMUserPwdRspFunc: error reading password");

        rfbCloseSock(cl->sock);
        return;
    }

    pwdBuf[pwdLen] = '\0';
    if (rfbAuthUserACL) {
        UserList* p = userACL;

        if (p == NULL)
            rfbLog("WARNING: User ACL is empty.  No users will be allowed to log in with Unix login authentication.\n");

        while (p != NULL) {
            if (!strcmp(p->name, userBuf))
                break;

            p = p->next;
        }

        if (p == NULL) {
            rfbLog("User '%s' is not in the ACL and has been denied access\n",
                   userBuf);
            rfbClientAuthFailed(cl, "User denied access");
            return;
        }

        cl->viewOnly = p->viewOnly;
    }

    if (rfbPAMAuthenticate(pamServiceName, cl->host, userBuf, pwdBuf, &emsg)) {
        rfbClientAuthSucceeded(cl, rfbAuthUnixLogin);

    } else {
        rfbClientAuthFailed(cl, (char*)emsg);
    }
}
示例#16
0
int
rfbCheckFds(rfbScreenInfoPtr rfbScreen,long usec)
{
    int nfds;
    fd_set fds;
    struct timeval tv;
    struct sockaddr_in addr;
    socklen_t addrlen = sizeof(addr);
    char buf[6];
    rfbClientIteratorPtr i;
    rfbClientPtr cl;
    int result = 0;

    if (!rfbScreen->inetdInitDone && rfbScreen->inetdSock != -1) {
	rfbNewClientConnection(rfbScreen,rfbScreen->inetdSock); 
	rfbScreen->inetdInitDone = TRUE;
    }

    do {
	memcpy((char *)&fds, (char *)&(rfbScreen->allFds), sizeof(fd_set));
	tv.tv_sec = 0;
	tv.tv_usec = usec;
	nfds = select(rfbScreen->maxFd + 1, &fds, NULL, NULL /* &fds */, &tv);
	if (nfds == 0) {
	    /* timed out, check for async events */
            i = rfbGetClientIterator(rfbScreen);
            while((cl = rfbClientIteratorNext(i))) {
                if (cl->onHold)
                    continue;
                if (FD_ISSET(cl->sock, &(rfbScreen->allFds)))
                    rfbSendFileTransferChunk(cl);
            }
            rfbReleaseClientIterator(i);
	    return result;
	}

	if (nfds < 0) {
#ifdef WIN32
	    errno = WSAGetLastError();
#endif
	    if (errno != EINTR)
		rfbLogPerror("rfbCheckFds: select");
	    return -1;
	}

	result += nfds;

	if (rfbScreen->listenSock != -1 && FD_ISSET(rfbScreen->listenSock, &fds)) {

	    if (!rfbProcessNewConnection(rfbScreen))
                return -1;

	    FD_CLR(rfbScreen->listenSock, &fds);
	    if (--nfds == 0)
		return result;
	}

	if (rfbScreen->listen6Sock != -1 && FD_ISSET(rfbScreen->listen6Sock, &fds)) {

	    if (!rfbProcessNewConnection(rfbScreen))
                return -1;

	    FD_CLR(rfbScreen->listen6Sock, &fds);
	    if (--nfds == 0)
		return result;
	}

	if ((rfbScreen->udpSock != -1) && FD_ISSET(rfbScreen->udpSock, &fds)) {
	    if(!rfbScreen->udpClient)
		rfbNewUDPClient(rfbScreen);
	    if (recvfrom(rfbScreen->udpSock, buf, 1, MSG_PEEK,
			(struct sockaddr *)&addr, &addrlen) < 0) {
		rfbLogPerror("rfbCheckFds: UDP: recvfrom");
		rfbDisconnectUDPSock(rfbScreen);
		rfbScreen->udpSockConnected = FALSE;
	    } else {
		if (!rfbScreen->udpSockConnected ||
			(memcmp(&addr, &rfbScreen->udpRemoteAddr, addrlen) != 0))
		{
		    /* new remote end */
		    rfbLog("rfbCheckFds: UDP: got connection\n");

		    memcpy(&rfbScreen->udpRemoteAddr, &addr, addrlen);
		    rfbScreen->udpSockConnected = TRUE;

		    if (connect(rfbScreen->udpSock,
				(struct sockaddr *)&addr, addrlen) < 0) {
			rfbLogPerror("rfbCheckFds: UDP: connect");
			rfbDisconnectUDPSock(rfbScreen);
			return -1;
		    }

		    rfbNewUDPConnection(rfbScreen,rfbScreen->udpSock);
		}

		rfbProcessUDPInput(rfbScreen);
	    }

	    FD_CLR(rfbScreen->udpSock, &fds);
	    if (--nfds == 0)
		return result;
	}

	i = rfbGetClientIterator(rfbScreen);
	while((cl = rfbClientIteratorNext(i))) {

	    if (cl->onHold)
		continue;

            if (FD_ISSET(cl->sock, &(rfbScreen->allFds)))
            {
                if (FD_ISSET(cl->sock, &fds))
                    rfbProcessClientMessage(cl);
                else
                    rfbSendFileTransferChunk(cl);
            }
	}
	rfbReleaseClientIterator(i);
    } while(rfbScreen->handleEventsEagerly);
    return result;
}
示例#17
0
文件: inet.c 项目: 00farts/italc-1
int connect_tcp(char *host, int port) {
	double t0 = dnow();
	int fd = -1;
	int fail4 = noipv4;
	if (getenv("IPV4_FAILS")) {
		fail4 = 2;
	}

	rfbLog("connect_tcp: trying:   %s %d\n", host, port);

	if (fail4) {
		if (fail4 > 1) {
			rfbLog("TESTING: IPV4_FAILS for connect_tcp.\n");
		}
	} else {
		fd = rfbConnectToTcpAddr(host, port);
	}

	if (fd >= 0) {
		return fd;
	}
	rfbLogPerror("connect_tcp: connection failed");

	if (dnow() - t0 < 4.0) {
		rfbLog("connect_tcp: re-trying %s %d\n", host, port);
		usleep (100 * 1000);
		if (!fail4) {
			fd = rfbConnectToTcpAddr(host, port);
		}
		if (fd < 0) {
			rfbLogPerror("connect_tcp: connection failed");
		}
	}

	if (fd < 0 && !noipv6) {
#if X11VNC_IPV6
		int err;
		struct addrinfo *ai;
		struct addrinfo hints;
		char service[32], *host2, *q;

		rfbLog("connect_tcp: trying IPv6 %s %d\n", host, port);

		memset(&hints, 0, sizeof(hints));
		sprintf(service, "%d", port);

		hints.ai_family = AF_UNSPEC;
		hints.ai_socktype = SOCK_STREAM;
#ifdef AI_ADDRCONFIG
		hints.ai_flags |= AI_ADDRCONFIG;
#endif
		if(ipv6_ip(host)) {
#ifdef AI_NUMERICHOST
			rfbLog("connect_tcp[ipv6]: setting AI_NUMERICHOST for %s\n", host);
			hints.ai_flags |= AI_NUMERICHOST;
#endif
		}
#ifdef AI_NUMERICSERV
		hints.ai_flags |= AI_NUMERICSERV;
#endif

		if (!strcmp(host, "127.0.0.1")) {
			host2 = strdup("::1");
		} else if (host[0] == '[') {
			host2 = strdup(host+1);
		} else {
			host2 = strdup(host);
		}
		q = strrchr(host2, ']');
		if (q) {
			*q = '\0';
		}

		err = getaddrinfo(host2, service, &hints, &ai);
		if (err != 0) {
			rfbLog("connect_tcp[ipv6]: getaddrinfo[%d]: %s\n", err, gai_strerror(err));
			usleep(100 * 1000);
			err = getaddrinfo(host2, service, &hints, &ai);
		}
		free(host2);

		if (err != 0) {
			rfbLog("connect_tcp[ipv6]: getaddrinfo[%d]: %s\n", err, gai_strerror(err));
		} else {
			struct addrinfo *ap = ai;
			while (ap != NULL) {
				int sock;

				if (fail4) {
					struct sockaddr_in6 *s6ptr;
					if (ap->ai_family != AF_INET6) {
						rfbLog("connect_tcp[ipv6]: skipping AF_INET address under -noipv4\n");
						ap = ap->ai_next;
						continue;
					}
#ifdef IN6_IS_ADDR_V4MAPPED
					s6ptr = (struct sockaddr_in6 *) ap->ai_addr;
					if (IN6_IS_ADDR_V4MAPPED(&(s6ptr->sin6_addr))) {
						rfbLog("connect_tcp[ipv6]: skipping V4MAPPED address under -noipv4\n");
						ap = ap->ai_next;
						continue;
					}
#endif
				}

				sock = socket(ap->ai_family, ap->ai_socktype, ap->ai_protocol);

				if (sock == -1) {
					rfbLogPerror("connect_tcp[ipv6]: socket");
					if (0) rfbLog("(Ignore the above error if this system is IPv4-only.)\n");
				} else {
					int res = -1, dmsg = 0;
					char *s = ipv6_getipaddr(ap->ai_addr, ap->ai_addrlen);
					if (!s) s = strdup("unknown");

					rfbLog("connect_tcp[ipv6]: trying sock=%d fam=%d proto=%d using %s\n",
					    sock, ap->ai_family, ap->ai_protocol, s);
					res = connect(sock, ap->ai_addr, ap->ai_addrlen);
#if defined(SOL_IPV6) && defined(IPV6_V6ONLY)
					if (res != 0) {
						int zero = 0;
						rfbLogPerror("connect_tcp[ipv6]: connect");
						dmsg = 1;
						if (setsockopt(sock, SOL_IPV6, IPV6_V6ONLY, (char *)&zero, sizeof(zero)) == 0) {
							rfbLog("connect_tcp[ipv6]: trying again with IPV6_V6ONLY=0\n");
							res = connect(sock, ap->ai_addr, ap->ai_addrlen);
							dmsg = 0;
						} else {
							rfbLogPerror("connect_tcp[ipv6]: setsockopt IPV6_V6ONLY");
						}
					}
#endif
					if (res == 0) {
						rfbLog("connect_tcp[ipv6]: connect OK\n");
						fd = sock;
						if (!ipv6_client_ip_str) {
							ipv6_client_ip_str = strdup(s);
						}
						free(s);
						break;
					} else {
						if (!dmsg) rfbLogPerror("connect_tcp[ipv6]: connect");
						close(sock);
					}
					free(s);
				}
				ap = ap->ai_next;
			}
			freeaddrinfo(ai);
		}
#endif
	}
	if (fd < 0 && !fail4) {
		/* this is a kludge for IPv4-only machines getting v4mapped string. */
		char *q, *host2;
		if (host[0] == '[') {
			host2 = strdup(host+1);
		} else {
			host2 = strdup(host);
		}
		q = strrchr(host2, ']');
		if (q) {
			*q = '\0';
		}
		if (strstr(host2, "::ffff:") == host2 || strstr(host2, "::FFFF:") == host2) {
			char *host3 = host2 + strlen("::ffff:");
			if (dotted_ip(host3, 0)) {
				rfbLog("connect_tcp[ipv4]: trying fallback to IPv4 for %s\n", host2);
				fd = rfbConnectToTcpAddr(host3, port);
				if (fd < 0) {
					rfbLogPerror("connect_tcp[ipv4]: connection failed");
				}
			}
		}
		free(host2);
	}
	return fd;
}
示例#18
0
void
rfbHttpCheckFds(rfbScreenInfoPtr rfbScreen)
{
    int nfds;
    fd_set fds;
    struct timeval tv;
#ifdef LIBVNCSERVER_IPv6
    struct sockaddr_storage addr;
#else
    struct sockaddr_in addr;
#endif
    socklen_t addrlen = sizeof(addr);

    if (!rfbScreen->httpDir)
	return;

    if (rfbScreen->httpListenSock < 0)
	return;

    FD_ZERO(&fds);
    FD_SET(rfbScreen->httpListenSock, &fds);
    if (rfbScreen->httpListen6Sock >= 0) {
	FD_SET(rfbScreen->httpListen6Sock, &fds);
    }
    if (rfbScreen->httpSock >= 0) {
	FD_SET(rfbScreen->httpSock, &fds);
    }
    tv.tv_sec = 0;
    tv.tv_usec = 0;
    nfds = select(max(rfbScreen->httpListen6Sock, max(rfbScreen->httpSock,rfbScreen->httpListenSock)) + 1, &fds, NULL, NULL, &tv);
    if (nfds == 0) {
	return;
    }
    if (nfds < 0) {
#ifdef WIN32
		errno = WSAGetLastError();
#endif
	if (errno != EINTR)
		rfbLogPerror("httpCheckFds: select");
	return;
    }

    if ((rfbScreen->httpSock >= 0) && FD_ISSET(rfbScreen->httpSock, &fds)) {
	httpProcessInput(rfbScreen);
    }

    if (FD_ISSET(rfbScreen->httpListenSock, &fds) || FD_ISSET(rfbScreen->httpListen6Sock, &fds)) {
	if (rfbScreen->httpSock >= 0) close(rfbScreen->httpSock);

	if(FD_ISSET(rfbScreen->httpListenSock, &fds)) {
	    if ((rfbScreen->httpSock = accept(rfbScreen->httpListenSock, (struct sockaddr *)&addr, &addrlen)) < 0) {
	      rfbLogPerror("httpCheckFds: accept");
	      return;
	    }
	}
	else if(FD_ISSET(rfbScreen->httpListen6Sock, &fds)) {
	    if ((rfbScreen->httpSock = accept(rfbScreen->httpListen6Sock, (struct sockaddr *)&addr, &addrlen)) < 0) {
	      rfbLogPerror("httpCheckFds: accept");
	      return;
	    }
	}

#ifdef USE_LIBWRAP
	char host[1024];
#ifdef LIBVNCSERVER_IPv6
	if(getnameinfo((struct sockaddr*)&addr, addrlen, host, sizeof(host), NULL, 0, NI_NUMERICHOST) != 0) {
	  rfbLogPerror("httpCheckFds: error in getnameinfo");
	  host[0] = '\0';
	}
#else
	memcpy(host, inet_ntoa(addr.sin_addr), sizeof(host));
#endif
	if(!hosts_ctl("vnc",STRING_UNKNOWN, host,
		      STRING_UNKNOWN)) {
	  rfbLog("Rejected HTTP connection from client %s\n",
		 host);
	  close(rfbScreen->httpSock);
	  rfbScreen->httpSock=-1;
	  return;
	}
#endif
        if(!rfbSetNonBlocking(rfbScreen->httpSock)) {
	    close(rfbScreen->httpSock);
	    rfbScreen->httpSock=-1;
	    return;
	}
	/*AddEnabledDevice(httpSock);*/
    }
}
示例#19
0
int
rfbConnectToTcpAddr(char *host,
                    int port)
{
    int sock;
#ifdef LIBVNCSERVER_IPv6
    struct addrinfo hints, *servinfo, *p;
    int rv;
    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;

    if ((rv = getaddrinfo(host, port_str, &hints, &servinfo)) != 0) {
        rfbErr("rfbConnectToTcpAddr: error in getaddrinfo: %s\n", gai_strerror(rv));
        return -1;
    }

    /* loop through all the results and connect 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;

        if (connect(sock, p->ai_addr, p->ai_addrlen) < 0) {
            closesocket(sock);
            continue;
        }

        break;
    }

    /* all failed */
    if (p == NULL) {
        rfbLogPerror("rfbConnectToTcoAddr: failed to connect\n");
        sock = -1; /* set return value */
    }

    /* all done with this structure now */
    freeaddrinfo(servinfo);
#else
    struct hostent *hp;
    struct sockaddr_in addr;

    memset(&addr, 0, sizeof(addr));
    addr.sin_family = AF_INET;
    addr.sin_port = htons(port);

    if ((addr.sin_addr.s_addr = inet_addr(host)) == htonl(INADDR_NONE))
    {
	if (!(hp = gethostbyname(host))) {
	    errno = EINVAL;
	    return -1;
	}
	addr.sin_addr.s_addr = *(unsigned long *)hp->h_addr;
    }

    if ((sock = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
	return -1;
    }

    if (connect(sock, (struct sockaddr *)&addr, (sizeof(addr))) < 0) {
	closesocket(sock);
	return -1;
    }
#endif
    return sock;
}
示例#20
0
int
rfbListenOnTCP6Port(int port,
                    const char* iface)
{
#ifndef LIBVNCSERVER_IPv6
    rfbLogPerror("This LibVNCServer does not have IPv6 support");
    return -1;
#else
    int sock;
    int one = 1;
    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_INET6;
    hints.ai_socktype = SOCK_STREAM;
    hints.ai_flags = AI_PASSIVE; /* fill in wildcard address if iface == NULL */

    if ((rv = getaddrinfo(iface, port_str, &hints, &servinfo)) != 0) {
        rfbErr("rfbListenOnTCP6Port 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 (setsockopt(sock, IPPROTO_IPV6, IPV6_V6ONLY, (char *)&one, sizeof(one)) < 0) {
	  rfbLogPerror("rfbListenOnTCP6Port error in setsockopt IPV6_V6ONLY");
	  closesocket(sock);
	  freeaddrinfo(servinfo);
	  return -1;
	}
#endif

	if (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (char *)&one, sizeof(one)) < 0) {
	  rfbLogPerror("rfbListenOnTCP6Port: error in setsockopt SO_REUSEADDR");
	  closesocket(sock);
	  freeaddrinfo(servinfo);
	  return -1;
	}

	if (bind(sock, p->ai_addr, p->ai_addrlen) < 0) {
	  closesocket(sock);
	  continue;
	}

        break;
    }

    if (p == NULL)  {
        rfbLogPerror("rfbListenOnTCP6Port: error in bind IPv6 socket");
        freeaddrinfo(servinfo);
        return -1;
    }

    /* all done with this structure now */
    freeaddrinfo(servinfo);

    if (listen(sock, 32) < 0) {
        rfbLogPerror("rfbListenOnTCP6Port: error in listen on IPv6 socket");
	closesocket(sock);
	return -1;
    }

    return sock;
#endif
}
示例#21
0
int
rfbPeekExactTimeout(rfbClientPtr cl, char* buf, int len, int timeout)
{
    int sock = cl->sock;
    int n;
    fd_set fds;
    struct timeval tv;

    while (len > 0) {
#ifdef LIBVNCSERVER_WITH_WEBSOCKETS
	if (cl->sslctx)
	    n = rfbssl_peek(cl, buf, len);
	else
#endif
	    n = recv(sock, buf, len, MSG_PEEK);

        if (n == len) {

            break;

        } else if (n == 0) {

            return 0;

        } else {
#ifdef WIN32
	    errno = WSAGetLastError();
#endif
	    if (errno == EINTR)
		continue;

#ifdef LIBVNCSERVER_ENOENT_WORKAROUND
	    if (errno != ENOENT)
#endif
            if (errno != EWOULDBLOCK && errno != EAGAIN) {
                return n;
            }

#ifdef LIBVNCSERVER_WITH_WEBSOCKETS
	    if (cl->sslctx) {
		if (rfbssl_pending(cl))
		    continue;
	    }
#endif
            FD_ZERO(&fds);
            FD_SET(sock, &fds);
            tv.tv_sec = timeout / 1000;
            tv.tv_usec = (timeout % 1000) * 1000;
            n = select(sock+1, &fds, NULL, &fds, &tv);
            if (n < 0) {
                rfbLogPerror("PeekExact: select");
                return n;
            }
            if (n == 0) {
                errno = ETIMEDOUT;
                return -1;
            }
        }
    }
#undef DEBUG_READ_EXACT
#ifdef DEBUG_READ_EXACT
    rfbLog("PeekExact %d bytes\n",len);
    for(n=0;n<len;n++)
	    fprintf(stderr,"%02x ",(unsigned char)buf[n]);
    fprintf(stderr,"\n");
#endif

    return 1;
}
示例#22
0
rfbBool
rfbProcessNewConnection(rfbScreenInfoPtr rfbScreen)
{
    const int one = 1;
    int sock = -1;
#ifdef LIBVNCSERVER_IPv6
    struct sockaddr_storage addr;
#else
    struct sockaddr_in addr;
#endif
    socklen_t addrlen = sizeof(addr);
    fd_set listen_fds; 
    int chosen_listen_sock = -1;

    /* Do another select() call to find out which listen socket
       has an incoming connection pending. We know that at least 
       one of them has, so this should not block for too long! */
    FD_ZERO(&listen_fds);  
    if(rfbScreen->listenSock >= 0) 
      FD_SET(rfbScreen->listenSock, &listen_fds);
    if(rfbScreen->listen6Sock >= 0) 
      FD_SET(rfbScreen->listen6Sock, &listen_fds);
    if (select(rfbScreen->maxFd+1, &listen_fds, NULL, NULL, NULL) == -1) {
      rfbLogPerror("rfbProcessNewConnection: error in select");
      return FALSE;
    }
    if (rfbScreen->listenSock >= 0 && FD_ISSET(rfbScreen->listenSock, &listen_fds))
      chosen_listen_sock = rfbScreen->listenSock;
    if (rfbScreen->listen6Sock >= 0 && FD_ISSET(rfbScreen->listen6Sock, &listen_fds))
      chosen_listen_sock = rfbScreen->listen6Sock;

    if ((sock = accept(chosen_listen_sock,
		       (struct sockaddr *)&addr, &addrlen)) < 0) {
      rfbLogPerror("rfbCheckFds: accept");
      return FALSE;
    }

    if(!rfbSetNonBlocking(sock)) {
      closesocket(sock);
      return FALSE;
    }

    if (setsockopt(sock, IPPROTO_TCP, TCP_NODELAY,
		   (char *)&one, sizeof(one)) < 0) {
      rfbLogPerror("rfbCheckFds: setsockopt");
      closesocket(sock);
      return FALSE;
    }

#ifdef USE_LIBWRAP
    if(!hosts_ctl("vnc",STRING_UNKNOWN,inet_ntoa(addr.sin_addr),
		  STRING_UNKNOWN)) {
      rfbLog("Rejected connection from client %s\n",
	     inet_ntoa(addr.sin_addr));
      closesocket(sock);
      return FALSE;
    }
#endif

#ifdef LIBVNCSERVER_IPv6
    {
        char host[1024];
        if(getnameinfo((struct sockaddr*)&addr, addrlen, host, sizeof(host), NULL, 0, NI_NUMERICHOST) != 0) {
            rfbLogPerror("rfbProcessNewConnection: error in getnameinfo");
        }
        rfbLog("Got connection from client %s\n", host);
    }
#else
    rfbLog("Got connection from client %s\n", inet_ntoa(addr.sin_addr));
#endif

    rfbNewClient(rfbScreen,sock);

    return TRUE;
}
示例#23
0
static void
httpProcessInput(rfbScreenInfoPtr rfbScreen)
{
#ifdef LIBVNCSERVER_IPv6
    struct sockaddr_storage addr;
    char host[1024];
#else
    struct sockaddr_in addr;
#endif
    socklen_t addrlen = sizeof(addr);
    char fullFname[512];
    char params[1024];
    char *ptr;
    char *fname;
    unsigned int maxFnameLen;
    FILE* fd;
    rfbBool performSubstitutions = FALSE;
    char str[256+32];
#ifndef WIN32
    char* user=getenv("USER");
#endif
   
    cl.sock=rfbScreen->httpSock;

    if (strlen(rfbScreen->httpDir) > 255) {
	rfbErr("-httpd directory too long\n");
	httpCloseSock(rfbScreen);
	return;
    }
    strcpy(fullFname, rfbScreen->httpDir);
    fname = &fullFname[strlen(fullFname)];
    maxFnameLen = 511 - strlen(fullFname);

    buf_filled=0;

    /* Read data from the HTTP client until we get a complete request. */
    while (1) {
	ssize_t got;

        if (buf_filled > sizeof (buf)) {
	    rfbErr("httpProcessInput: HTTP request is too long\n");
	    httpCloseSock(rfbScreen);
	    return;
	}

	got = read (rfbScreen->httpSock, buf + buf_filled,
			    sizeof (buf) - buf_filled - 1);

	if (got <= 0) {
	    if (got == 0) {
		rfbErr("httpd: premature connection close\n");
	    } else {
#ifdef WIN32
	        errno=WSAGetLastError();
#endif
		if (errno == EAGAIN) {
		    return;
		}
		rfbLogPerror("httpProcessInput: read");
	    }
	    httpCloseSock(rfbScreen);
	    return;
	}

	buf_filled += got;
	buf[buf_filled] = '\0';

	/* Is it complete yet (is there a blank line)? */
	if (strstr (buf, "\r\r") || strstr (buf, "\n\n") ||
	    strstr (buf, "\r\n\r\n") || strstr (buf, "\n\r\n\r"))
	    break;
    }


    /* Process the request. */
    if(rfbScreen->httpEnableProxyConnect) {
	const static char* PROXY_OK_STR = "HTTP/1.0 200 OK\r\nContent-Type: octet-stream\r\nPragma: no-cache\r\n\r\n";
	if(!strncmp(buf, "CONNECT ", 8)) {
	    if(atoi(strchr(buf, ':')+1)!=rfbScreen->port) {
		rfbErr("httpd: CONNECT format invalid.\n");
		rfbWriteExact(&cl,INVALID_REQUEST_STR, strlen(INVALID_REQUEST_STR));
		httpCloseSock(rfbScreen);
		return;
	    }
	    /* proxy connection */
	    rfbLog("httpd: client asked for CONNECT\n");
	    rfbWriteExact(&cl,PROXY_OK_STR,strlen(PROXY_OK_STR));
	    rfbNewClientConnection(rfbScreen,rfbScreen->httpSock);
	    rfbScreen->httpSock = -1;
	    return;
	}
	if (!strncmp(buf, "GET ",4) && !strncmp(strchr(buf,'/'),"/proxied.connection HTTP/1.", 27)) {
	    /* proxy connection */
	    rfbLog("httpd: client asked for /proxied.connection\n");
	    rfbWriteExact(&cl,PROXY_OK_STR,strlen(PROXY_OK_STR));
	    rfbNewClientConnection(rfbScreen,rfbScreen->httpSock);
	    rfbScreen->httpSock = -1;
	    return;
	}	   
    }

    if (strncmp(buf, "GET ", 4)) {
	rfbErr("httpd: no GET line\n");
	httpCloseSock(rfbScreen);
	return;
    } else {
	/* Only use the first line. */
	buf[strcspn(buf, "\n\r")] = '\0';
    }

    if (strlen(buf) > maxFnameLen) {
	rfbErr("httpd: GET line too long\n");
	httpCloseSock(rfbScreen);
	return;
    }

    if (sscanf(buf, "GET %s HTTP/1.", fname) != 1) {
	rfbErr("httpd: couldn't parse GET line\n");
	httpCloseSock(rfbScreen);
	return;
    }

    if (fname[0] != '/') {
	rfbErr("httpd: filename didn't begin with '/'\n");
	rfbWriteExact(&cl, NOT_FOUND_STR, strlen(NOT_FOUND_STR));
	httpCloseSock(rfbScreen);
	return;
    }


    getpeername(rfbScreen->httpSock, (struct sockaddr *)&addr, &addrlen);
#ifdef LIBVNCSERVER_IPv6
    if(getnameinfo((struct sockaddr*)&addr, addrlen, host, sizeof(host), NULL, 0, NI_NUMERICHOST) != 0) {
      rfbLogPerror("httpProcessInput: error in getnameinfo");
    }
    rfbLog("httpd: get '%s' for %s\n", fname+1, host);
#else
    rfbLog("httpd: get '%s' for %s\n", fname+1,
	   inet_ntoa(addr.sin_addr));
#endif

    /* Extract parameters from the URL string if necessary */

    params[0] = '\0';
    ptr = strchr(fname, '?');
    if (ptr != NULL) {
       *ptr = '\0';
       if (!parseParams(&ptr[1], params, 1024)) {
           params[0] = '\0';
           rfbErr("httpd: bad parameters in the URL\n");
       }
    }


    /* If we were asked for '/', actually read the file index.vnc */

    if (strcmp(fname, "/") == 0) {
	strcpy(fname, "/index.vnc");
	rfbLog("httpd: defaulting to '%s'\n", fname+1);
    }

    /* Substitutions are performed on files ending .vnc */

    if (strlen(fname) >= 4 && strcmp(&fname[strlen(fname)-4], ".vnc") == 0) {
	performSubstitutions = TRUE;
    }

    /* Open the file */

    if ((fd = fopen(fullFname, "r")) == 0) {
        rfbLogPerror("httpProcessInput: open");
        rfbWriteExact(&cl, NOT_FOUND_STR, strlen(NOT_FOUND_STR));
        httpCloseSock(rfbScreen);
        return;
    }

    if(performSubstitutions) /* is the 'index.vnc' file */
      rfbWriteExact(&cl, OK_STR_HTML, strlen(OK_STR_HTML));
    else
      rfbWriteExact(&cl, OK_STR, strlen(OK_STR));

    while (1) {
	int n = fread(buf, 1, BUF_SIZE-1, fd);
	if (n < 0) {
	    rfbLogPerror("httpProcessInput: read");
	    fclose(fd);
	    httpCloseSock(rfbScreen);
	    return;
	}

	if (n == 0)
	    break;

	if (performSubstitutions) {

	    /* Substitute $WIDTH, $HEIGHT, etc with the appropriate values.
	       This won't quite work properly if the .vnc file is longer than
	       BUF_SIZE, but it's reasonable to assume that .vnc files will
	       always be short. */

	    char *ptr = buf;
	    char *dollar;
	    buf[n] = 0; /* make sure it's null-terminated */

	    while ((dollar = strchr(ptr, '$'))!=NULL) {
		rfbWriteExact(&cl, ptr, (dollar - ptr));

		ptr = dollar;

		if (compareAndSkip(&ptr, "$WIDTH")) {

		    sprintf(str, "%d", rfbScreen->width);
		    rfbWriteExact(&cl, str, strlen(str));

		} else if (compareAndSkip(&ptr, "$HEIGHT")) {

		    sprintf(str, "%d", rfbScreen->height);
		    rfbWriteExact(&cl, str, strlen(str));

		} else if (compareAndSkip(&ptr, "$APPLETWIDTH")) {

		    sprintf(str, "%d", rfbScreen->width);
		    rfbWriteExact(&cl, str, strlen(str));

		} else if (compareAndSkip(&ptr, "$APPLETHEIGHT")) {

		    sprintf(str, "%d", rfbScreen->height + 32);
		    rfbWriteExact(&cl, str, strlen(str));

		} else if (compareAndSkip(&ptr, "$PORT")) {

		    sprintf(str, "%d", rfbScreen->port);
		    rfbWriteExact(&cl, str, strlen(str));

		} else if (compareAndSkip(&ptr, "$DESKTOP")) {

		    rfbWriteExact(&cl, rfbScreen->desktopName, strlen(rfbScreen->desktopName));

		} else if (compareAndSkip(&ptr, "$DISPLAY")) {

		    sprintf(str, "%s:%d", rfbScreen->thisHost, rfbScreen->port-5900);
		    rfbWriteExact(&cl, str, strlen(str));

		} else if (compareAndSkip(&ptr, "$USER")) {
#ifndef WIN32
		    if (user) {
			rfbWriteExact(&cl, user,
				   strlen(user));
		    } else
#endif
			rfbWriteExact(&cl, "?", 1);
		} else if (compareAndSkip(&ptr, "$PARAMS")) {
		    if (params[0] != '\0')
			rfbWriteExact(&cl, params, strlen(params));
		} else {
		    if (!compareAndSkip(&ptr, "$$"))
			ptr++;

		    if (rfbWriteExact(&cl, "$", 1) < 0) {
			fclose(fd);
			httpCloseSock(rfbScreen);
			return;
		    }
		}
	    }
	    if (rfbWriteExact(&cl, ptr, (&buf[n] - ptr)) < 0)
		break;

	} else {

	    /* For files not ending .vnc, just write out the buffer */

	    if (rfbWriteExact(&cl, buf, n) < 0)
		break;
	}
    }

    fclose(fd);
    httpCloseSock(rfbScreen);
}
示例#24
0
void
rfbCheckFds()
{
    int nfds;
    fd_set fds;
    struct timeval tv;
    struct sockaddr_storage addr;
    socklen_t addrlen = sizeof(addr);
    char addrStr[INET6_ADDRSTRLEN];
    char buf[6];
    const int one = 1;
    int sock;
    rfbClientPtr cl;
    static Bool inetdInitDone = FALSE;

    if (!inetdInitDone && inetdSock != -1) {
        rfbNewClientConnection(inetdSock);
        inetdInitDone = TRUE;
    }

    memcpy((char *)&fds, (char *)&allFds, sizeof(fd_set));
    tv.tv_sec = 0;
    tv.tv_usec = 0;
    nfds = select(maxFd + 1, &fds, NULL, NULL, &tv);
    if (nfds == 0) {
        return;
    }
    if (nfds < 0) {
        rfbLogPerror("rfbCheckFds: select");
        return;
    }

    if (rfbListenSock != -1 && FD_ISSET(rfbListenSock, &fds)) {

        if ((sock = accept(rfbListenSock,
                           (struct sockaddr *)&addr, &addrlen)) < 0) {
            rfbLogPerror("rfbCheckFds: accept");
            return;
        }

        if (fcntl(sock, F_SETFL, O_NONBLOCK) < 0) {
            rfbLogPerror("rfbCheckFds: fcntl");
            close(sock);
            return;
        }

        if (setsockopt(sock, IPPROTO_TCP, TCP_NODELAY,
                       (char *)&one, sizeof(one)) < 0) {
            rfbLogPerror("rfbCheckFds: setsockopt");
            close(sock);
            return;
        }

        fprintf(stderr, "\n");

#if USE_LIBWRAP
        if (!hosts_ctl("Xvnc", STRING_UNKNOWN,
                       sockaddr_string(&addr, addrStr, INET6_ADDRSTRLEN),
                       STRING_UNKNOWN)) {
          rfbLog("Rejected connection from client %s\n",
                 sockaddr_string(&addr, addrStr, INET6_ADDRSTRLEN))
          close(sock);
          return;
        }
#endif

        rfbLog("Got connection from client %s\n",
               sockaddr_string(&addr, addrStr, INET6_ADDRSTRLEN));

        AddEnabledDevice(sock);
        FD_SET(sock, &allFds);
        maxFd = max(sock, maxFd);

        rfbNewClientConnection(sock);

        FD_CLR(rfbListenSock, &fds);
        if (--nfds == 0)
            return;
    }

    if ((udpSock != -1) && FD_ISSET(udpSock, &fds)) {

        if (recvfrom(udpSock, buf, 1, MSG_PEEK,
                     (struct sockaddr *)&addr, &addrlen) < 0) {

            rfbLogPerror("rfbCheckFds: UDP: recvfrom");
            rfbDisconnectUDPSock();

        } else {

            if (!udpSockConnected ||
                (memcmp(&addr, &udpRemoteAddr, addrlen) != 0))
            {
                /* new remote end */
                rfbLog("rfbCheckFds: UDP: got connection\n");

                memcpy(&udpRemoteAddr, &addr, addrlen);
                udpSockConnected = TRUE;

                if (connect(udpSock,
                            (struct sockaddr *)&addr, addrlen) < 0) {
                    rfbLogPerror("rfbCheckFds: UDP: connect");
                    rfbDisconnectUDPSock();
                    return;
                }

                rfbNewUDPConnection(udpSock);
            }

            rfbProcessUDPInput(udpSock);
        }

        FD_CLR(udpSock, &fds);
        if (--nfds == 0)
            return;
    }

    for (cl = rfbClientHead; cl; cl = cl->next) {
        if (FD_ISSET(cl->sock, &fds) && FD_ISSET(cl->sock, &allFds)) {
            rfbClientPtr cl2;
#if USETLS
            do {
                rfbProcessClientMessage(cl);
                /* Make sure cl hasn't been freed */
                for (cl2 = rfbClientHead; cl2; cl2 = cl2->next) {
                    if (cl2 == cl)
                        break;
                }
                if (cl2 == NULL) return;
            } while (cl->sslctx && rfbssl_pending(cl) > 0);
#else
            rfbProcessClientMessage(cl);
            for (cl2 = rfbClientHead; cl2; cl2 = cl2->next) {
                if (cl2 == cl)
                    break;
            }
            if (cl2 == NULL) return;
#endif
        }
    }
}
示例#25
0
文件: inet.c 项目: 00farts/italc-1
int listen6(int port) {
#if X11VNC_IPV6
	struct sockaddr_in6 sin;
	int fd = -1, one = 1;

	if (noipv6) {
		return -1;
	}
	if (port <= 0 || 65535 < port) {
		/* for us, invalid port means do not listen. */
		return -1;
	}

	fd = socket(AF_INET6, SOCK_STREAM, 0);
	if (fd < 0) {
		rfbLogPerror("listen6: socket");
		rfbLog("(Ignore the above error if this system is IPv4-only.)\n");
		return -1;
	}

	if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (char *)&one, sizeof(one)) < 0) {
		rfbLogPerror("listen6: setsockopt SO_REUSEADDR"); 
		close(fd);
		return -1;
	}

#if defined(SOL_IPV6) && defined(IPV6_V6ONLY)
	if (setsockopt(fd, SOL_IPV6, IPV6_V6ONLY, (char *)&one, sizeof(one)) < 0) {
		rfbLogPerror("listen6: setsockopt IPV6_V6ONLY"); 
		close(fd);
		return -1;
	}
#endif

	memset((char *)&sin, 0, sizeof(sin));
	sin.sin6_family = AF_INET6;
	sin.sin6_port   = htons(port);
	sin.sin6_addr   = in6addr_any;

	if (listen_str6) {
		if (!strcmp(listen_str6, "localhost") || !strcmp(listen_str6, "::1")) {
			sin.sin6_addr = in6addr_loopback;
		} else {
			int err;
			struct addrinfo *ai;
			struct addrinfo hints;
			char service[32];

			memset(&hints, 0, sizeof(hints));
			sprintf(service, "%d", port);

			hints.ai_family = AF_INET6;
			hints.ai_socktype = SOCK_STREAM;
#ifdef AI_ADDRCONFIG
			hints.ai_flags |= AI_ADDRCONFIG;
#endif
#ifdef AI_NUMERICHOST
			if(ipv6_ip(listen_str6)) {
				hints.ai_flags |= AI_NUMERICHOST;
			}
#endif
#ifdef AI_NUMERICSERV
			hints.ai_flags |= AI_NUMERICSERV;
#endif
			err = getaddrinfo(listen_str6, service, &hints, &ai);
			if (err == 0) {
				struct addrinfo *ap = ai;
				err = 1;
				while (ap != NULL) {
					char *s = ipv6_getipaddr(ap->ai_addr, ap->ai_addrlen);
					if (!s) s = strdup("unknown");

					rfbLog("listen6: checking: %s family: %d\n", s, ap->ai_family); 
					if (ap->ai_family == AF_INET6) {
						memcpy((char *)&sin, ap->ai_addr, sizeof(sin));
						rfbLog("listen6: using:    %s scope_id: %d\n", s, sin.sin6_scope_id); 
						err = 0;
						free(s);
						break;
					}
					free(s);
					ap = ap->ai_next;
				}
				freeaddrinfo(ai);
			}

			if (err != 0) {
				rfbLog("Invalid or Unsupported -listen6 string: %s\n", listen_str6);
				close(fd);
				return -1;
			}
		}
	} else if (allow_list && !strcmp(allow_list, "127.0.0.1")) {
		sin.sin6_addr = in6addr_loopback;
	} else if (listen_str) {
		if (!strcmp(listen_str, "localhost")) {
			sin.sin6_addr = in6addr_loopback;
		}
	}

	if (bind(fd, (struct sockaddr *) &sin, sizeof(sin)) < 0) {
		rfbLogPerror("listen6: bind"); 
		close(fd);
		return -1;
	}
	if (listen(fd, 32) < 0) {
		rfbLogPerror("listen6: listen");
		close(fd);
		return -1;
	}
	return fd;
#else
	if (port) {}
	return -1;
#endif
}
示例#26
0
int
rfbCheckFds(rfbScreenInfoPtr rfbScreen,long usec)
{
    int nfds;
    fd_set fds;
    struct timeval tv;
    struct sockaddr_in addr;
    socklen_t addrlen = sizeof(addr);
    char buf[6];
    const int one = 1;
    int sock;
    rfbClientIteratorPtr i;
    rfbClientPtr cl;
    struct timeval tv_msg;
    fd_set fds_msg;
    int nfds_msg;
    int result = 0;

    if (!rfbScreen->inetdInitDone && rfbScreen->inetdSock != -1) {
        rfbNewClientConnection(rfbScreen,rfbScreen->inetdSock);
        rfbScreen->inetdInitDone = TRUE;
    }

    do {
        memcpy((char *)&fds, (char *)&(rfbScreen->allFds), sizeof(fd_set));
        tv.tv_sec = 0;
        tv.tv_usec = usec;
        nfds = select(rfbScreen->maxFd + 1, &fds, NULL, NULL /* &fds */, &tv);
        if (nfds == 0) {
            /* timed out, check for async events */
            i = rfbGetClientIterator(rfbScreen);
            while((cl = rfbClientIteratorNext(i))) {
                if (cl->onHold)
                    continue;
                if (FD_ISSET(cl->sock, &(rfbScreen->allFds)))
                    rfbSendFileTransferChunk(cl);
            }
            rfbReleaseClientIterator(i);
            return result;
        }

        if (nfds < 0) {
#ifdef WIN32
            errno = WSAGetLastError();
#endif
            if (errno != EINTR)
                rfbLogPerror("rfbCheckFds: select");
            return -1;
        }

        result += nfds;

        if (rfbScreen->listenSock != -1 && FD_ISSET(rfbScreen->listenSock, &fds)) {
            if ((sock = accept(rfbScreen->listenSock,
                               (struct sockaddr *)&addr, &addrlen)) < 0) {
                rfbLogPerror("rfbCheckFds: accept");
                return -1;
            }

#ifndef WIN32
            if (fcntl(sock, F_SETFL, O_NONBLOCK) < 0) {
                rfbLogPerror("rfbCheckFds: fcntl");
                closesocket(sock);
                return -1;
            }
#endif

            if (setsockopt(sock, IPPROTO_TCP, TCP_NODELAY,
                           (char *)&one, sizeof(one)) < 0) {
                rfbLogPerror("rfbCheckFds: setsockopt");
                closesocket(sock);
                return -1;
            }

#ifdef USE_LIBWRAP
            if(!hosts_ctl("vnc",STRING_UNKNOWN,inet_ntoa(addr.sin_addr),
                          STRING_UNKNOWN)) {
                rfbLog("Rejected connection from client %s\n",
                       inet_ntoa(addr.sin_addr));
                closesocket(sock);
                return -1;
            }
#endif

            rfbLog("Got connection from client %s\n", inet_ntoa(addr.sin_addr));

            rfbNewClient(rfbScreen,sock);

            FD_CLR(rfbScreen->listenSock, &fds);
            if (--nfds == 0)
                return result;
        }

        if ((rfbScreen->udpSock != -1) && FD_ISSET(rfbScreen->udpSock, &fds)) {
            if(!rfbScreen->udpClient)
                rfbNewUDPClient(rfbScreen);
            if (recvfrom(rfbScreen->udpSock, buf, 1, MSG_PEEK,
                         (struct sockaddr *)&addr, &addrlen) < 0) {
                rfbLogPerror("rfbCheckFds: UDP: recvfrom");
                rfbDisconnectUDPSock(rfbScreen);
                rfbScreen->udpSockConnected = FALSE;
            } else {
                if (!rfbScreen->udpSockConnected ||
                        (memcmp(&addr, &rfbScreen->udpRemoteAddr, addrlen) != 0))
                {
                    /* new remote end */
                    rfbLog("rfbCheckFds: UDP: got connection\n");

                    memcpy(&rfbScreen->udpRemoteAddr, &addr, addrlen);
                    rfbScreen->udpSockConnected = TRUE;

                    if (connect(rfbScreen->udpSock,
                                (struct sockaddr *)&addr, addrlen) < 0) {
                        rfbLogPerror("rfbCheckFds: UDP: connect");
                        rfbDisconnectUDPSock(rfbScreen);
                        return -1;
                    }

                    rfbNewUDPConnection(rfbScreen,rfbScreen->udpSock);
                }

                rfbProcessUDPInput(rfbScreen);
            }

            FD_CLR(rfbScreen->udpSock, &fds);
            if (--nfds == 0)
                return result;
        }

        i = rfbGetClientIterator(rfbScreen);
        while((cl = rfbClientIteratorNext(i))) {

            if (cl->onHold)
                continue;

            if (FD_ISSET(cl->sock, &(rfbScreen->allFds)))
            {
                if (FD_ISSET(cl->sock, &fds)) {
                    tv_msg.tv_sec = 0;
                    tv_msg.tv_usec = 0;
                    FD_ZERO(&fds_msg);
                    FD_SET(cl->sock, &fds_msg);
                    do {
                        /* drain all messages, speed up mouse move processing */
                        rfbProcessClientMessage(cl);
                        nfds_msg = select(cl->sock + 1, &fds_msg, NULL, NULL, &tv_msg);
                    } while (nfds_msg > 0);
                }
                else
                    rfbSendFileTransferChunk(cl);
            }
        }
        rfbReleaseClientIterator(i);
    } while(rfbScreen->handleEventsEagerly);
    return result;
}
示例#27
0
int
WriteExact(rfbClientPtr cl, char *buf, int len)
{
    int n, bytesWritten = 0;
    fd_set fds;
    struct timeval tv;
    int totalTimeWaited = 0;
    int sock = cl->sock;

    while (len > 0) {
        do {
#if USETLS
            if (cl->sslctx)
                n = rfbssl_write(cl, buf, len);
            else
#endif
            n = write(sock, buf, len);
        } while (n < 0 && errno == EINTR);

        if (n > 0) {

            buf += n;
            len -= n;
            bytesWritten += n;
            sendBytes += n;

        } else if (n == 0) {

            rfbLog("WriteExact: write returned 0?\n");
            exit(1);

        } else {
            if (errno != EWOULDBLOCK && errno != EAGAIN && errno != 0) {
                return n;
            }

            /* Retry every 5 seconds until we exceed rfbMaxClientWait.  We
               need to do this because select doesn't necessarily return
               immediately when the other end has gone away */

            FD_ZERO(&fds);
            FD_SET(sock, &fds);
            tv.tv_sec = 5;
            tv.tv_usec = 0;
            do {
              n = select(sock + 1, NULL, &fds, NULL, &tv);
            } while (n < 0 && errno == EINTR);
            if (n < 0) {
                rfbLogPerror("WriteExact: select");
                return n;
            }
            if (n == 0) {
                totalTimeWaited += 5000;
                if (totalTimeWaited >= rfbMaxClientWait) {
                    errno = ETIMEDOUT;
                    return -1;
                }
            } else {
                totalTimeWaited = 0;
            }
        }
    }

    gettimeofday(&cl->lastWrite, NULL);
    cl->sockOffset += bytesWritten;

    return 1;
}
示例#28
0
int
rfbWriteExact(rfbClientPtr cl,
              const char *buf,
              int len)
{
    int sock = cl->sock;
    int n;
    fd_set fds;
    struct timeval tv;
    int totalTimeWaited = 0;

#undef DEBUG_WRITE_EXACT
#ifdef DEBUG_WRITE_EXACT
    rfbLog("WriteExact %d bytes\n",len);
    for(n=0; n<len; n++)
        fprintf(stderr,"%02x ",(unsigned char)buf[n]);
    fprintf(stderr,"\n");
#endif

    LOCK(cl->outputMutex);
    while (len > 0) {
        n = write(sock, buf, len);

        if (n > 0) {

            buf += n;
            len -= n;

        } else if (n == 0) {

            rfbErr("WriteExact: write returned 0?\n");
            return 0;

        } else {
#ifdef WIN32
            errno = WSAGetLastError();
#endif
            if (errno == EINTR)
                continue;

            if (errno != EWOULDBLOCK && errno != EAGAIN) {
                UNLOCK(cl->outputMutex);
                return n;
            }

            /* Retry every 5 seconds until we exceed rfbMaxClientWait.  We
               need to do this because select doesn't necessarily return
               immediately when the other end has gone away */

            FD_ZERO(&fds);
            FD_SET(sock, &fds);
            tv.tv_sec = 5;
            tv.tv_usec = 0;
            n = select(sock+1, NULL, &fds, NULL /* &fds */, &tv);
            if (n < 0) {
                if(errno==EINTR)
                    continue;
                rfbLogPerror("WriteExact: select");
                UNLOCK(cl->outputMutex);
                return n;
            }
            if (n == 0) {
                totalTimeWaited += 5000;
                if (totalTimeWaited >= rfbMaxClientWait) {
                    errno = ETIMEDOUT;
                    UNLOCK(cl->outputMutex);
                    return -1;
                }
            } else {
                totalTimeWaited = 0;
            }
        }
    }
    UNLOCK(cl->outputMutex);
    return 1;
}
示例#29
0
void
rfbInitSockets(rfbScreenInfoPtr rfbScreen)
{
    in_addr_t iface = rfbScreen->listenInterface;

    if (rfbScreen->socketState!=RFB_SOCKET_INIT)
        return;

    rfbScreen->socketState = RFB_SOCKET_READY;

    if (rfbScreen->inetdSock != -1) {
        const int one = 1;

#ifndef WIN32
        if (fcntl(rfbScreen->inetdSock, F_SETFL, O_NONBLOCK) < 0) {
            rfbLogPerror("fcntl");
            return;
        }
#endif

        if (setsockopt(rfbScreen->inetdSock, IPPROTO_TCP, TCP_NODELAY,
                       (char *)&one, sizeof(one)) < 0) {
            rfbLogPerror("setsockopt");
            return;
        }

        FD_ZERO(&(rfbScreen->allFds));
        FD_SET(rfbScreen->inetdSock, &(rfbScreen->allFds));
        rfbScreen->maxFd = rfbScreen->inetdSock;
        return;
    }

    if(rfbScreen->autoPort) {
        int i;
        rfbLog("Autoprobing TCP port \n");
        for (i = 5900; i < 6000; i++) {
            if ((rfbScreen->listenSock = rfbListenOnTCPPort(i, iface)) >= 0) {
                rfbScreen->port = i;
                break;
            }
        }

        if (i >= 6000) {
            rfbLogPerror("Failure autoprobing");
            return;
        }

        rfbLog("Autoprobing selected port %d\n", rfbScreen->port);
        FD_ZERO(&(rfbScreen->allFds));
        FD_SET(rfbScreen->listenSock, &(rfbScreen->allFds));
        rfbScreen->maxFd = rfbScreen->listenSock;
    }
    else if(rfbScreen->port>0) {
        rfbLog("Listening for VNC connections on TCP port %d\n", rfbScreen->port);

        if ((rfbScreen->listenSock = rfbListenOnTCPPort(rfbScreen->port, iface)) < 0) {
            rfbLogPerror("ListenOnTCPPort");
            return;
        }

        FD_ZERO(&(rfbScreen->allFds));
        FD_SET(rfbScreen->listenSock, &(rfbScreen->allFds));
        rfbScreen->maxFd = rfbScreen->listenSock;
    }

    if (rfbScreen->udpPort != 0) {
        rfbLog("rfbInitSockets: listening for input on UDP port %d\n",rfbScreen->udpPort);

        if ((rfbScreen->udpSock = rfbListenOnUDPPort(rfbScreen->udpPort, iface)) < 0) {
            rfbLogPerror("ListenOnUDPPort");
            return;
        }
        FD_SET(rfbScreen->udpSock, &(rfbScreen->allFds));
        rfbScreen->maxFd = max((int)rfbScreen->udpSock,rfbScreen->maxFd);
    }
}
示例#30
0
void
rfbSendInteractionCaps(rfbClientPtr cl)
{
    rfbInteractionCapsMsg intr_caps;
    rfbCapabilityInfo smsg_list[N_SMSG_CAPS];
    rfbCapabilityInfo cmsg_list[N_CMSG_CAPS];
    rfbCapabilityInfo enc_list[N_ENC_CAPS];
    int i, n_enc_caps = N_ENC_CAPS;

    /* Fill in the header structure sent prior to capability lists. */
    intr_caps.nServerMessageTypes = Swap16IfLE(N_SMSG_CAPS);
    intr_caps.nClientMessageTypes = Swap16IfLE(N_CMSG_CAPS);
    intr_caps.nEncodingTypes = Swap16IfLE(N_ENC_CAPS);
    intr_caps.pad = 0;

    rfbLog("tightvnc-filetransfer/rfbSendInteractionCaps\n");

    /* Supported server->client message types. */
    /* For file transfer support: */
    i = 0;
	if((IsFileTransferEnabled() == TRUE) && ( cl->viewOnly == FALSE)) {
	    SetCapInfo(&smsg_list[i++], rfbFileListData,           rfbTightVncVendor);
	    SetCapInfo(&smsg_list[i++], rfbFileDownloadData,       rfbTightVncVendor);
	    SetCapInfo(&smsg_list[i++], rfbFileUploadCancel,       rfbTightVncVendor);
	    SetCapInfo(&smsg_list[i++], rfbFileDownloadFailed,     rfbTightVncVendor);
	    if (i != N_SMSG_CAPS) {
			rfbLog("rfbSendInteractionCaps: assertion failed, i != N_SMSG_CAPS\n");
			rfbCloseClient(cl);
			return;
	    }
	}

    /* Supported client->server message types. */
    /* For file transfer support: */
    i = 0;
	if((IsFileTransferEnabled() == TRUE) && ( cl->viewOnly == FALSE)) {
	    SetCapInfo(&cmsg_list[i++], rfbFileListRequest,        rfbTightVncVendor);
	    SetCapInfo(&cmsg_list[i++], rfbFileDownloadRequest,    rfbTightVncVendor);
	    SetCapInfo(&cmsg_list[i++], rfbFileUploadRequest,      rfbTightVncVendor);
	    SetCapInfo(&cmsg_list[i++], rfbFileUploadData,         rfbTightVncVendor);
	    SetCapInfo(&cmsg_list[i++], rfbFileDownloadCancel,     rfbTightVncVendor);
	    SetCapInfo(&cmsg_list[i++], rfbFileUploadFailed,       rfbTightVncVendor);
	    if (i != N_CMSG_CAPS) {
			rfbLog("rfbSendInteractionCaps: assertion failed, i != N_CMSG_CAPS\n");
			rfbCloseClient(cl);
			return;
	    }		
	}
	
    /* Encoding types. */
    i = 0;
    SetCapInfo(&enc_list[i++],  rfbEncodingCopyRect,       rfbStandardVendor);
    SetCapInfo(&enc_list[i++],  rfbEncodingRRE,            rfbStandardVendor);
    SetCapInfo(&enc_list[i++],  rfbEncodingCoRRE,          rfbStandardVendor);
    SetCapInfo(&enc_list[i++],  rfbEncodingHextile,        rfbStandardVendor);
#ifdef LIBVNCSERVER_HAVE_LIBZ
    SetCapInfo(&enc_list[i++],  rfbEncodingZlib,           rfbTridiaVncVendor);
    SetCapInfo(&enc_list[i++],  rfbEncodingTight,          rfbTightVncVendor);
#else
    n_enc_caps -= 2;
#endif
    SetCapInfo(&enc_list[i++],  rfbEncodingCompressLevel0, rfbTightVncVendor);
    SetCapInfo(&enc_list[i++],  rfbEncodingQualityLevel0,  rfbTightVncVendor);
    SetCapInfo(&enc_list[i++],  rfbEncodingXCursor,        rfbTightVncVendor);
    SetCapInfo(&enc_list[i++],  rfbEncodingRichCursor,     rfbTightVncVendor);
    SetCapInfo(&enc_list[i++],  rfbEncodingPointerPos,     rfbTightVncVendor);
    SetCapInfo(&enc_list[i++],  rfbEncodingLastRect,       rfbTightVncVendor);
    if (i != n_enc_caps) {
	rfbLog("rfbSendInteractionCaps: assertion failed, i != N_ENC_CAPS\n");
	rfbCloseClient(cl);
	return;
    }

    /* Send header and capability lists */
    if (rfbWriteExact(cl, (char *)&intr_caps,
		   sz_rfbInteractionCapsMsg) < 0 ||
	rfbWriteExact(cl, (char *)&smsg_list[0],
		   sz_rfbCapabilityInfo * N_SMSG_CAPS) < 0 || 
	rfbWriteExact(cl, (char *)&cmsg_list[0],
		   sz_rfbCapabilityInfo * N_CMSG_CAPS) < 0  ||
	rfbWriteExact(cl, (char *)&enc_list[0],
		   sz_rfbCapabilityInfo * N_ENC_CAPS) < 0) {
	rfbLogPerror("rfbSendInteractionCaps: write");
	rfbCloseClient(cl);	
	return;
    }

    /* Dispatch client input to rfbProcessClientNormalMessage(). */
    cl->state = RFB_NORMAL;
}