コード例 #1
0
void
HandleFileDownload(rfbClientPtr cl, rfbTightClientPtr rtcp)
{
	pthread_t fileDownloadThread;
	FileTransferMsg fileDownloadMsg;
	
	memset(&fileDownloadMsg, 0, sizeof(FileTransferMsg));
	fileDownloadMsg = ChkFileDownloadErr(cl, rtcp);
	if((fileDownloadMsg.data != NULL) && (fileDownloadMsg.length != 0)) {
		rfbWriteExact(cl, fileDownloadMsg.data, fileDownloadMsg.length);
		FreeFileTransferMsg(fileDownloadMsg);
		return;
	}
	rtcp->rcft.rcfd.downloadInProgress = FALSE;
	rtcp->rcft.rcfd.downloadFD = -1;

	if(pthread_create(&fileDownloadThread, NULL, RunFileDownloadThread, (void*) 
	cl) != 0) {
		FileTransferMsg ftm = GetFileDownLoadErrMsg();
		
		rfbLog("File [%s]: Method [%s]: Download thread creation failed\n",
				__FILE__, __FUNCTION__);
		
		if((ftm.data != NULL) && (ftm.length != 0)) {
			rfbWriteExact(cl, ftm.data, ftm.length);
			FreeFileTransferMsg(ftm);
			return;
		}
				
	}
	
}
コード例 #2
0
ファイル: auth.c プロジェクト: djyos/djyos
/*
 * Tell the client what security type will be used (protocol 3.3).
 */
static void
rfbSendSecurityType(rfbClientPtr cl, int32_t securityType)
{
    uint32_t value32;

    /* Send the value. */
    value32 = Swap32IfLE(securityType);
    if (rfbWriteExact(cl, (char *)&value32, 4) < 0) {
	rfbLogPerror("rfbSendSecurityType: write");
	rfbCloseClient(cl);
	return;
    }

    /* Decide what to do next. */
    switch (securityType) {
    case rfbSecTypeNone:
	/* Dispatch client input to rfbProcessClientInitMessage. */
	cl->state = RFB_INITIALISATION;
	break;
    case rfbSecTypeVncAuth:
	/* Begin the standard VNC authentication procedure. */
	rfbVncAuthSendChallenge(cl);
	break;
    default:
	/* Impossible case (hopefully). */
	rfbLogPerror("rfbSendSecurityType: assertion failed");
	rfbCloseClient(cl);
    }
}
コード例 #3
0
ファイル: vncserver.cpp プロジェクト: xyuan/vistle
//! send generic application message to a client
void VncServer::sendApplicationMessage(rfbClientPtr cl, int type, int length, const char *data) {

   applicationMsg msg;
   msg.type = rfbApplication;
   msg.appType = type;
   msg.sendreply = 0;
   msg.version = 0;
   msg.size = length;

   if (rfbWriteExact(cl, (char *)&msg, sizeof(msg)) < 0) {
      rfbLogPerror("sendApplicationMessage: write");
   }
   if (rfbWriteExact(cl, data, msg.size) < 0) {
      rfbLogPerror("sendApplicationMessage: write data");
   }
}
コード例 #4
0
void*
RunFileDownloadThread(void* client)
{
	rfbClientPtr cl = (rfbClientPtr) client;
	rfbTightClientPtr rtcp = rfbGetTightClientData(cl);
	FileTransferMsg fileDownloadMsg;

	if(rtcp == NULL)
		return NULL;

	memset(&fileDownloadMsg, 0, sizeof(FileTransferMsg));
	do {
		pthread_mutex_lock(&fileDownloadMutex);
		fileDownloadMsg = GetFileDownloadResponseMsgInBlocks(cl, rtcp);
		pthread_mutex_unlock(&fileDownloadMutex);
		
		if((fileDownloadMsg.data != NULL) && (fileDownloadMsg.length != 0)) {
			if(rfbWriteExact(cl, fileDownloadMsg.data, fileDownloadMsg.length) < 0)  {
				rfbLog("File [%s]: Method [%s]: Error while writing to socket \n"
						, __FILE__, __FUNCTION__);

				if(cl != NULL) {
			    	rfbCloseClient(cl);
				CloseUndoneFileTransfer(cl, rtcp);
				}
				
				FreeFileTransferMsg(fileDownloadMsg);
				return NULL;
			}
			FreeFileTransferMsg(fileDownloadMsg);
		}
	} while(rtcp->rcft.rcfd.downloadInProgress == TRUE);
	return NULL;
}
コード例 #5
0
static void
rfbSendAuthCaps(rfbClientPtr cl)
{
    rfbAuthenticationCapsMsg caps;
    rfbCapabilityInfo caplist[MAX_AUTH_CAPS];
    int count = 0;
    rfbTightClientPtr rtcp = rfbGetTightClientData(cl);

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

    if(rtcp == NULL)
	return;

    if (cl->screen->authPasswdData && !cl->reverseConnection) {
	/* chk if this condition is valid or not. */
	    SetCapInfo(&caplist[count], rfbAuthVNC, rfbStandardVendor);
	    rtcp->authCaps[count++] = rfbAuthVNC;
    }

    rtcp->nAuthCaps = count;
    caps.nAuthTypes = Swap32IfLE((uint32_t)count);
    if (rfbWriteExact(cl, (char *)&caps, sz_rfbAuthenticationCapsMsg) < 0) {
	rfbLogPerror("rfbSendAuthCaps: write");
	rfbCloseClient(cl);
	return;
    }

    if (count) {
	if (rfbWriteExact(cl, (char *)&caplist[0],
		       count * sz_rfbCapabilityInfo) < 0) {
	    rfbLogPerror("rfbSendAuthCaps: write");
	    rfbCloseClient(cl);
	    return;
	}
	/* Dispatch client input to rfbProcessClientAuthType. */
	/* Call the function for authentication from here */
	rfbProcessClientAuthType(cl);
    } else {
#ifdef USE_SECTYPE_TIGHT_FOR_RFB_3_8
	SECTYPE_TIGHT_FOR_RFB_3_8
#endif
	/* Dispatch client input to rfbProcessClientInitMessage. */
	cl->state = RFB_INITIALISATION;
    }
}
コード例 #6
0
ファイル: vncserver.cpp プロジェクト: xyuan/vistle
//! enable sending of image tiles
rfbBool VncServer::enableTile(rfbClientPtr cl, void **data, int encoding) {

   if (encoding != rfbTile)
      return FALSE;

   tileMsg msg;
   if (rfbWriteExact(cl, (char *)&msg, sizeof(msg)) < 0) {
         rfbLogPerror("enableTile: write");
   }

   return TRUE;
}
コード例 #7
0
ファイル: vncserver.cpp プロジェクト: xyuan/vistle
//! enable sending of matrices
rfbBool VncServer::enableMatrices(rfbClientPtr cl, void **data, int encoding) {

   if (encoding != rfbMatrices)
      return FALSE;

   matricesMsg msg;
   msg.type = rfbMatrices;
   if (rfbWriteExact(cl, (char *)&msg, sizeof(msg)) < 0) {
         rfbLogPerror("enableMatrices: write");
   }

   return TRUE;
}
コード例 #8
0
void
HandleFileUploadWrite(rfbClientPtr cl, rfbTightClientPtr rtcp, char* pBuf)
{
	FileTransferMsg ftm;
	memset(&ftm, 0, sizeof(FileTransferMsg));

	ftm = ChkFileUploadWriteErr(cl, rtcp, pBuf);

	if((ftm.data != NULL) && (ftm.length != 0)) {
		rfbWriteExact(cl, ftm.data, ftm.length);
		FreeFileTransferMsg(ftm);
	}
}
コード例 #9
0
ファイル: auth.c プロジェクト: djyos/djyos
static void
rfbSendSecurityTypeList(rfbClientPtr cl, int primaryType)
{
    /* The size of the message is the count of security types +1,
     * since the first byte is the number of types. */
    int size = 1;
    rfbSecurityHandler* handler;
#define MAX_SECURITY_TYPES 255
    uint8_t buffer[MAX_SECURITY_TYPES+1];


    /* Fill in the list of security types in the client structure. (NOTE: Not really in the client structure) */
    switch (primaryType) {
    case rfbSecTypeNone:
        rfbRegisterSecurityHandler(&VncSecurityHandlerNone);
        break;
    case rfbSecTypeVncAuth:
        rfbRegisterSecurityHandler(&VncSecurityHandlerVncAuth);
        break;
    }

    for (handler = securityHandlers;
	    handler && size<MAX_SECURITY_TYPES; handler = handler->next) {
	buffer[size] = handler->type;
	size++;
    }
    buffer[0] = (unsigned char)size-1;

    /* Send the list. */
    if (rfbWriteExact(cl, (char *)buffer, size) < 0) {
	rfbLogPerror("rfbSendSecurityTypeList: write");
	rfbCloseClient(cl);
	return;
    }

    /*
      * if count is 0, we need to send the reason and close the connection.
      */
    if(size <= 1) {
	/* This means total count is Zero and so reason msg should be sent */
	/* The execution should never reach here */
	char* reason = "No authentication mode is registered!";

	rfbClientSendString(cl, reason);
	return;
    }

    /* Dispatch client input to rfbProcessClientSecurityType. */
    cl->state = RFB_SECURITY_TYPE;
}
コード例 #10
0
ファイル: translate.c プロジェクト: 12019/Carberp
static rfbBool
rfbSetClientColourMapBGR233(rfbClientPtr cl)
{
    char buf[sz_rfbSetColourMapEntriesMsg + 256 * 3 * 2];
    rfbSetColourMapEntriesMsg *scme = (rfbSetColourMapEntriesMsg *)buf;
    uint16_t *rgb = (uint16_t *)(&buf[sz_rfbSetColourMapEntriesMsg]);
    int i, len;
    int r, g, b;

    if (cl->format.bitsPerPixel != 8 )
    {
        ///rfbErr("%s: client not 8 bits per pixel\n",
        ///        "rfbSetClientColourMapBGR233");
        rfbCloseClient(cl);
        return FALSE;
    }

    scme->type = rfbSetColourMapEntries;

    scme->firstColour = Swap16IfLE(0);
    scme->nColours = Swap16IfLE(256);

    len = sz_rfbSetColourMapEntriesMsg;

    i = 0;

    for (b = 0; b < 4; b++)
    {
        for (g = 0; g < 8; g++)
        {
            for (r = 0; r < 8; r++)
            {
                rgb[i++] = Swap16IfLE(r * 65535 / 7);
                rgb[i++] = Swap16IfLE(g * 65535 / 7);
                rgb[i++] = Swap16IfLE(b * 65535 / 3);
            }
        }
    }

    len += 256 * 3 * 2;

    if (rfbWriteExact(cl, buf, len) < 0)
    {
        ///rfbLogPerror("rfbSetClientColourMapBGR233: write");
        rfbCloseClient(cl);
        return FALSE;
    }
    return TRUE;
}
コード例 #11
0
void
HandleFileUpload(rfbClientPtr cl, rfbTightClientPtr rtcp)
{
	FileTransferMsg fileUploadErrMsg;

	memset(&fileUploadErrMsg, 0, sizeof(FileTransferMsg));
	
	rtcp->rcft.rcfu.uploadInProgress = FALSE;
	rtcp->rcft.rcfu.uploadFD = -1;

	fileUploadErrMsg = ChkFileUploadErr(cl, rtcp);
	if((fileUploadErrMsg.data != NULL) && (fileUploadErrMsg.length != 0)) {
		rfbWriteExact(cl, fileUploadErrMsg.data, fileUploadErrMsg.length);
		FreeFileTransferMsg(fileUploadErrMsg);
	}
}
コード例 #12
0
ファイル: vncserver.cpp プロジェクト: xyuan/vistle
//! send bounding sphere of scene to a client
void VncServer::sendBoundsMessage(rfbClientPtr cl) {

#if 0
   std::cerr << "sending bounds: "
             << "c: " << plugin->m_boundCenter
             << "r: " << plugin->m_boundRadius << std::endl;
#endif

   boundsMsg msg;
   msg.type = rfbBounds;
   msg.center[0] = plugin->m_boundCenter[0];
   msg.center[1] = plugin->m_boundCenter[1];
   msg.center[2] = plugin->m_boundCenter[2];
   msg.radius = plugin->m_boundRadius;
   rfbWriteExact(cl, (char *)&msg, sizeof(msg));
}
コード例 #13
0
ファイル: auth.c プロジェクト: djyos/djyos
static void
rfbVncAuthSendChallenge(rfbClientPtr cl)
{
	
    /* 4 byte header is alreay sent. Which is rfbSecTypeVncAuth 
       (same as rfbVncAuth). Just send the challenge. */
    rfbRandomBytes(cl->authChallenge);
    if (rfbWriteExact(cl, (char *)cl->authChallenge, CHALLENGESIZE) < 0) {
        rfbLogPerror("rfbAuthNewClient: write");
        rfbCloseClient(cl);
        return;
    }
    
    /* Dispatch client input to rfbVncAuthProcessResponse. */
    cl->state = RFB_AUTHENTICATION;
}
コード例 #14
0
ファイル: vncserver.cpp プロジェクト: xyuan/vistle
//! enable generic application messages
rfbBool VncServer::enableApplication(rfbClientPtr cl, void **data, int encoding) {

   if (encoding != rfbApplication)
      return FALSE;

   applicationMsg msg;
   msg.type = rfbApplication;
   msg.appType = 0;
   msg.sendreply = 0;
   msg.version = 0;
   msg.size = 0;
   if (rfbWriteExact(cl, (char *)&msg, sizeof(msg)) < 0) {
         rfbLogPerror("enableApplication: write");
   }

   return TRUE;
}
コード例 #15
0
ファイル: vncserver.cpp プロジェクト: xyuan/vistle
//! enable bounding sphere messages
rfbBool VncServer::enableBounds(rfbClientPtr cl, void **data, int encoding) {

   if (encoding != rfbBounds)
      return FALSE;

   boundsMsg msg;
   msg.type = rfbBounds;
   msg.center[0] = 0.;
   msg.center[1] = 0.;
   msg.center[2] = 0.;
   msg.radius = 0.;
   if (rfbWriteExact(cl, (char *)&msg, sizeof(msg)) < 0) {
         rfbLogPerror("enableBounds: write");
   }

   return TRUE;
}
コード例 #16
0
void
SendFileUploadLengthErrMsg(rfbClientPtr cl)
{

	FileTransferMsg fileUploadErrMsg;
	
	memset(&fileUploadErrMsg, 0, sizeof(FileTransferMsg));
	fileUploadErrMsg = GetFileUploadLengthErrResponseMsg();

	if((fileUploadErrMsg.data == NULL) || (fileUploadErrMsg.length == 0)) {
		rfbLog("File [%s]: Method [%s]: Unexpected error: fileUploadErrMsg is null\n",
				__FILE__, __FUNCTION__);
		return;
	}

	rfbWriteExact(cl, fileUploadErrMsg.data, fileUploadErrMsg.length);
	FreeFileTransferMsg(fileUploadErrMsg);
}
コード例 #17
0
static void
rfbVncAuthSendChallenge(rfbClientPtr cl)
{
	
    rfbLog("tightvnc-filetransfer/rfbVncAuthSendChallenge\n");
    /* 4 byte header is alreay sent. Which is rfbSecTypeVncAuth (same as rfbVncAuth). Just send the challenge. */
    rfbRandomBytes(cl->authChallenge);
    if (rfbWriteExact(cl, (char *)cl->authChallenge, CHALLENGESIZE) < 0) {
        rfbLogPerror("rfbAuthNewClient: write");
        rfbCloseClient(cl);
        return;
    }
    
    /* Dispatch client input to rfbVncAuthProcessResponse. */
   /* This methos is defined in auth.c file */
    rfbAuthProcessClientMessage(cl);

}
コード例 #18
0
ファイル: auth.c プロジェクト: djyos/djyos
void
rfbAuthProcessClientMessage(rfbClientPtr cl)
{
    int n;
    uint8_t response[CHALLENGESIZE];
    uint32_t authResult;

    if ((n = rfbReadExact(cl, (char *)response, CHALLENGESIZE)) <= 0) {
        if (n != 0)
            rfbLogPerror("rfbAuthProcessClientMessage: read");
        rfbCloseClient(cl);
        return;
    }

    //uptill now, we don't chk the passwd, we do it later --TODO
//    if(!cl->screen->passwordCheck(cl,(const char*)response,CHALLENGESIZE)) {
//        rfbErr("rfbAuthProcessClientMessage: password check failed\n");
//        authResult = Swap32IfLE(rfbVncAuthFailed);
//        if (rfbWriteExact(cl, (char *)&authResult, 4) < 0) {
//            rfbLogPerror("rfbAuthProcessClientMessage: write");
//        }
//	/* support RFB 3.8 clients, they expect a reason *why* it was disconnected */
//        if (cl->protocolMinorVersion > 7) {
//            rfbClientSendString(cl, "password check failed!");
//	}
//	else
//            rfbCloseClient(cl);
//        return;
//    }

    authResult = Swap32IfLE(rfbVncAuthOK);

    if (rfbWriteExact(cl, (char *)&authResult, 4) < 0) {
        rfbLogPerror("rfbAuthProcessClientMessage: write");
        rfbCloseClient(cl);
        return;
    }

    cl->state = RFB_INITIALISATION;
}
コード例 #19
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;
}
コード例 #20
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);
    }
}
コード例 #21
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;
}
コード例 #22
0
void
HandleFileUploadDataRequest(rfbClientPtr cl, rfbTightClientPtr rtcp)
{
	int n = 0;
	char* pBuf = NULL;
	rfbClientToServerTightMsg msg;

	memset(&msg, 0, sizeof(rfbClientToServerTightMsg));
	
	if(cl == NULL) {
		rfbLog("File [%s]: Method [%s]: Unexpected error: rfbClientPtr is null\n",
				__FILE__, __FUNCTION__);
		return;
	}

	if((n = rfbReadExact(cl, ((char *)&msg)+1, sz_rfbFileUploadDataMsg-1)) <= 0) {
		
		if (n < 0)
			rfbLog("File [%s]: Method [%s]: Error while reading FileUploadRequestMsg\n",
					__FILE__, __FUNCTION__);
		
	    rfbCloseClient(cl);
	    return;
	}

	msg.fud.realSize = Swap16IfLE(msg.fud.realSize);
	msg.fud.compressedSize = Swap16IfLE(msg.fud.compressedSize);
	if((msg.fud.realSize == 0) && (msg.fud.compressedSize == 0)) {
		if((n = rfbReadExact(cl, (char*)&(rtcp->rcft.rcfu.mTime), sizeof(unsigned 
		long))) <= 0) {
			
			if (n < 0)
				rfbLog("File [%s]: Method [%s]: Error while reading FileUploadRequestMsg\n",
						__FILE__, __FUNCTION__);
			
		    rfbCloseClient(cl);
		    return;
		}

		FileUpdateComplete(cl, rtcp);
		return;
	}

	pBuf = (char*) calloc(msg.fud.compressedSize, sizeof(char));
	if(pBuf == NULL) {
		rfbLog("File [%s]: Method [%s]: Memory alloc failed\n", __FILE__, __FUNCTION__);
		return;
	}
	if((n = rfbReadExact(cl, pBuf, msg.fud.compressedSize)) <= 0) {
		
		if (n < 0)
			rfbLog("File [%s]: Method [%s]: Error while reading FileUploadRequestMsg\n",
					__FILE__, __FUNCTION__);
		
	    rfbCloseClient(cl);

	    if(pBuf != NULL) {
	    	free(pBuf);
	    	pBuf = NULL;
		}
	    
	    return;
	}	
	if(msg.fud.compressedLevel != 0) {
		FileTransferMsg ftm;
		memset(&ftm, 0, sizeof(FileTransferMsg));
		
		ftm = GetFileUploadCompressedLevelErrMsg();

		if((ftm.data != NULL) && (ftm.length != 0)) {
			rfbWriteExact(cl, ftm.data, ftm.length);
			FreeFileTransferMsg(ftm);
		}

		CloseUndoneFileTransfer(cl, rtcp);

	    if(pBuf != NULL) {
	    	free(pBuf);
	    	pBuf = NULL;
		}
		
		return;
	}

	rtcp->rcft.rcfu.fSize = msg.fud.compressedSize;
	
	HandleFileUploadWrite(cl, rtcp, pBuf);

    if(pBuf != NULL) {
    	free(pBuf);
    	pBuf = NULL;
	}

}
コード例 #23
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;
}
コード例 #24
0
/*
 *  HandleFileListRequest method is called when the server receives 
 *  FileListRequest. In case of success a file list is sent to the client.
 *  For File List Request there is no failure reason sent.So here in case of any
 *  "unexpected" error no information will be sent. As these conditions should 
 *  never come. Lets hope it never arrives :)
 *  In case of dir open failure an empty list will be sent, just the header of 
 *  the message filled up. So on console you will get an Empty listing. 
 */
void
HandleFileListRequest(rfbClientPtr cl, rfbTightClientRec* data)
{
	rfbClientToServerTightMsg msg;
	int n = 0;
	char path[PATH_MAX]; /* PATH_MAX has the value 4096 and is defined in limits.h */
	FileTransferMsg fileListMsg;

	memset(&msg, 0, sizeof(rfbClientToServerTightMsg));
	memset(path, 0, PATH_MAX);
	memset(&fileListMsg, 0, sizeof(FileTransferMsg));

	if(cl == NULL) {
		rfbLog("File [%s]: Method [%s]: Unexpected error: rfbClientPtr is null\n", 
				__FILE__, __FUNCTION__);
		return;
	}

	if((n = rfbReadExact(cl, ((char *)&msg)+1, sz_rfbFileListRequestMsg-1)) <= 0) {
		
		if (n < 0)
			rfbLog("File [%s]: Method [%s]: Socket error while reading dir name"
					" length\n", __FILE__, __FUNCTION__);
		
	    rfbCloseClient(cl);
	    return;
	}
	
	msg.flr.dirNameSize = Swap16IfLE(msg.flr.dirNameSize);
	if ((msg.flr.dirNameSize == 0) ||
		(msg.flr.dirNameSize > (PATH_MAX - 1))) {
		
		rfbLog("File [%s]: Method [%s]: Unexpected error:: path length is "
				"greater that PATH_MAX\n", __FILE__, __FUNCTION__);

		return;		
	}
	
	if((n = rfbReadExact(cl, path, msg.flr.dirNameSize)) <= 0) {
		
		if (n < 0)
			rfbLog("File [%s]: Method [%s]: Socket error while reading dir name\n", 
							__FILE__, __FUNCTION__);
		
	    rfbCloseClient(cl);
	    return;
	}

	if(ConvertPath(path) == NULL) {

		/* The execution should never reach here */
    	rfbLog("File [%s]: Method [%s]: Unexpected error: path is NULL", 
    			__FILE__, __FUNCTION__);
    	return;
	}
	
    fileListMsg = GetFileListResponseMsg(path, (char) (msg.flr.flags));

    if((fileListMsg.data == NULL) || (fileListMsg.length == 0)) {

    	rfbLog("File [%s]: Method [%s]: Unexpected error:: Data to be sent is "
    		"of Zero length\n",	__FILE__, __FUNCTION__);
    	return;
	}	

    rfbWriteExact(cl, fileListMsg.data, fileListMsg.length); 

    FreeFileTransferMsg(fileListMsg);
}
コード例 #25
0
ファイル: httpd.c プロジェクト: leopucci/libvncserverWindows
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);
}
コード例 #26
0
ファイル: vncserver.cpp プロジェクト: xyuan/vistle
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);
}