Windows의 UltraVNC와 Linux의 TigerVNC 간 파일 전송 - rfbFileTransferMsg 구조 전송 및 수신
rfbFileTransferMsg 구조 정의
UltraVNC의 구조 정의, 총 12바이트
typedef struct _rfbFileTransferMsg {
CARD8 type; /* always rfbFileTransfer */
CARD8 contentType; // See defines below
CARD16 contentParam;// Other possible content classification (Dir or File name, etc..)
CARD32 size; // FileSize or packet index or error or other
// CARD32 sizeH; // Additional 32Bits params to handle big values. Only for V2 (we want backward compatibility between all V1 versions)
CARD32 length;
/* followed by data char text[length] */
} rfbFileTransferMsg;
TigerVNC에는 그러한 구조가 없으므로 다음과 같이 직접 정의해야 하며, 이 역시 총 12바이트입니다.
typedef struct _rfbFileTransferMsg {
rdr::U8 type; /* always rfbFileTransfer */
rdr::U8 contentType; // See defines below
rdr::U16 contentParam;// Other possible content classification (Dir or File name, etc..)
rdr::U32 size; // FileSize or packet index or error or other
// rdr::U32 sizeH; // Additional 32Bits params to handle big values. Only for V2 (we want backward compatibility between all V1 versions)
rdr::U32 length;
/* followed by data char text[length] */
} rfbFileTransferMsg;
Windows의 UltraVNC는 Linux의 TigerVNC에 구조를 보냅니다.
1. Windows를 통해 보냅니다. 예를 들어:
if (m_client->fFTRequest)
{
rfbFileTransferMsg ft;
ft.type = rfbFileTransfer;
ft.contentType = rfbAbortFileTransfer;
bool bOldFTProtocole = (msg.ft.contentParam == 0);
if (bOldFTProtocole)
ft.contentType = rfbAbortFileTransfer; // Viewer with New V2 FT protocole
else
ft.contentType = rfbFileTransferAccess; // Viewer with old FT protocole
if (!bOldFTProtocole && m_server->FileTransferEnabled() && m_client->m_server->RemoteInputsEnabled() && fUserOk)
ft.size = Swap32IfLE(1);
else
ft.size = Swap32IfLE(-1);
m_client->m_socket->SendExact((char *)&ft, sz_rfbFileTransferMsg, rfbFileTransfer);
m_client->fFTRequest = false;
}
2. Linux 수신은
Windows와 같이 다음과 같은 방법으로는 수신할 수 없습니다. 수신된 구조의 각 필드에 바이트 순서 문제가 있기 때문입니다.
rfbFileTransferMsg ft;
is->readBytes(((char *)&ft), sz_rfbFileTransferMsg);
여기서는 TigerVNC에서 제공하는 readU8(), readU16(), readU32()를 사용하여 아래와 같이 순서대로 12바이트를 읽고 읽습니다.
int type = is->readU8();
int c_contentType = is->readU8();
int c_contentParam = is->readU8();
int c_contentParam_sub = is->readU8();
int c_size = is->readU32();
int c_length = is->readU32();
Linux의 TigerVNC는 Windows의 UltraVNC에 구조를 보냅니다.
1. Linux 측에서 보내기
바이트 순서 문제로 인해 Windows와 같이 다음과 같은 방법으로는 보낼 수 없습니다.
rfbFileTransferMsg ft;
ft.type = msgTypeFileTransfer;
ft.contentType = rfbDirContentRequest;
ft.contentParam = rfbRDrivesList; // List of Remote Drives please
ft.length = 0;
char *char_ft = (char *)&ft;
os->writeBytes(char_ft, sz_rfbFileTransferMsg);
여기서는 TigerVNC에서 제공하는 writeU8(), writeU16(), writeU32()를 사용하여 아래와 같이 12바이트를 순서대로 전송합니다.
os->writeU8(7);
os->writeU8(1);
os->writeU8(1);
os->writeU8(0);
os->writeU32(0);
os->writeU32(1022);
2. Windows 측에서 읽기,
먼저 1바이트 읽기
rfbClientToServerMsg msg;
if (!m_socket->ReadExact((char *)&msg.type, sizeof(msg.type)))
{
m_client->cl_connected = FALSE;
break;
}
또 다른 11바이트 읽기
if (m_socket->ReadExact(((char *) &msg) + 1, sz_rfbFileTransferMsg - 1))
{
}
rfbClientToServerMsg 구조는 rfbFileTransferMsg를 포함하여 다음과 같습니다.
typedef union {
CARD8 type;
rfbSetPixelFormatMsg spf;
rfbFixColourMapEntriesMsg fcme;
rfbSetEncodingsMsg se;
rfbFramebufferUpdateRequestMsg fur;
rfbKeyEventMsg ke;
rfbPointerEventMsg pe;
rfbClientCutTextMsg cct;
rfbSetScaleMsg ssc;
rfbPalmVNCSetScaleFactorMsg pssf;
rfbSetServerInputMsg sim;
rfbFileTransferMsg ft;
rfbSetSWMsg sw;
rfbTextChatMsg tc;
rfbKeepAliveMsg kp;
rfbRequestSessionMsg rs;
rfbSetSessionMsg ss;
rfbUserCloseMsg close;
} rfbClientToServerMsg;