RDP tunnel размер пакетов?

Тема в разделе "WASM.NETWORKS", создана пользователем Aids, 18 дек 2011.

  1. Aids

    Aids New Member

    Публикаций:
    0
    Регистрация:
    30 ноя 2007
    Сообщения:
    275
    Пытаюсь сделать туннель. Но вот возникли проблемы. Пакеты фрагментируются и к тому же пакеты rdp могут идти друг за другом, вот тут то и возникли проблемы. Если размер одного пакета я знаю, это WORD по смещению 2, и используя размер читаю его без проблем, а вот если начну проверять следующий то могу заблокировать сокет.
    Но похоже ещё не только в этом проблема. Может кто то подобное делал? Может есть у кого описание протокола?

    Код (Text):
    1. #include "Tunneling.h"
    2. #define DEFAULT_BUFLEN 0x8000
    3.  
    4.  
    5. DWORD recv_data(char *recvbuf,SOCKET hsock1,SOCKET hsock2){
    6.     int count=0;
    7.     int iResult;
    8.     int recvbuflen=0x8000;
    9.     int iSendResult=0;
    10.     memset(recvbuf,0,DEFAULT_BUFLEN);
    11.     DWORD size=0;
    12.     iResult = recv(hsock1, &recvbuf[count], 4, 0);
    13.     if ((iResult==-1) || (iResult==0))
    14.         return 0;
    15.     count+=iResult;
    16.     do{
    17.         size+=(((*(WORD*)&recvbuf[size+2]&0xFF00)>>8)|((*(WORD*)&recvbuf[size+2]&0x00FF)<<8));
    18.         while(count<size){
    19.             if ((count>0x2400)&&(count<0x2700)){
    20.                 _asm nop;
    21.             }
    22.             iResult = recv(hsock1, &recvbuf[count], recvbuflen, 0);
    23.             if ((iResult==SOCKET_ERROR) || (iResult==0))
    24.                 return 0;
    25.             count+=iResult;
    26.         }
    27.     }while (count!=size);
    28.     if (size==46){
    29.         _asm nop
    30.     }
    31.     iSendResult = send(hsock2, recvbuf, size, 0);
    32.     return count;
    33. }
    34.  
    35. struct Tsock{
    36.     SOCKET s1,s2;
    37. };
    38.  
    39. DWORD __stdcall ThreadTunnel(LPVOID param){
    40.     Tsock *s=(Tsock*)param;
    41.     char *mem=new char[DEFAULT_BUFLEN];
    42.     int a=1;
    43.     while(a>0){
    44.         a=recv_data(mem,s->s1,s->s2);
    45.         printf("s: %d\n",a);
    46.         if (a==0){
    47.             _asm nop
    48.         }
    49.     }
    50.     delete []mem;
    51.     ExitThread(0);
    52.     return 0;
    53. }
    54.  
    55. DWORD recv_send(SOCKET ClientSocket,SOCKET ServerSocket){
    56.     // Receive until the peer shuts down the connection
    57.     int iSendResult=0;
    58.     int count=0;
    59.     HANDLE t[2];
    60.     Tsock s1,s2;
    61.     s1.s1=ClientSocket;
    62.     s1.s2=ServerSocket;
    63.     t[0]=CreateThread(0,0,ThreadTunnel,&s1,0,0);
    64.     s2.s2=ClientSocket;
    65.     s2.s1=ServerSocket;
    66.     t[1]=CreateThread(0,0,ThreadTunnel,&s2,0,0);
    67.     WaitForMultipleObjects(2,t,TRUE,-1);
    68.     return 1;
    69. }
    70.  
    71. DWORD server_tunnel(){
    72.     //----------------------
    73.     // Initialize Winsock.
    74.     WSADATA wsaData;
    75.     int iResult = WSAStartup(MAKEWORD(2, 2), &wsaData);
    76.     if (iResult != NO_ERROR) {
    77.         printf("WSAStartup failed with error: %ld\n", iResult);
    78.         return 1;
    79.     }
    80.     //----------------------
    81.     // Create a SOCKET for listening for
    82.     // incoming connection requests.
    83.     SOCKET ListenSocket;
    84.     ListenSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
    85.  
    86.     if (ListenSocket == INVALID_SOCKET) {
    87.         printf("socket failed with error: %ld\n", WSAGetLastError());
    88.         WSACleanup();
    89.         return 1;
    90.     }
    91.     //----------------------
    92.     // The sockaddr_in structure specifies the address family,
    93.     // IP address, and port for the socket that is being bound.
    94.     sockaddr_in service;
    95.     service.sin_family = AF_INET;
    96.     service.sin_addr.s_addr = inet_addr("127.0.0.1");
    97.     service.sin_port = htons(4444);
    98.  
    99.     if (bind(ListenSocket,
    100.              (SOCKADDR *) & service, sizeof (service)) == SOCKET_ERROR) {
    101.         printf("bind failed with error: %ld\n", WSAGetLastError());
    102.         closesocket(ListenSocket);
    103.         WSACleanup();
    104.         return 1;
    105.     }
    106.     //----------------------
    107.     // Listen for incoming connection requests.
    108.     // on the created socket
    109.     if (listen(ListenSocket, 1) == SOCKET_ERROR) {
    110.         printf("listen failed with error: %ld\n", WSAGetLastError());
    111.         closesocket(ListenSocket);
    112.         WSACleanup();
    113.         return 1;
    114.     }
    115.     //----------------------
    116.     // Create a SOCKET for accepting incoming requests.
    117.     SOCKET AcceptSocket;
    118.     printf("Waiting for client to connect...\n");
    119.  
    120.     //----------------------
    121.     // Accept the connection.
    122.     while(1){
    123.     AcceptSocket = accept(ListenSocket, NULL, NULL);
    124.     //DWORD opt=10000;
    125.     //setsockopt(AcceptSocket,SOL_SOCKET,SO_SNDTIMEO,(char*)&opt,4);
    126.     //setsockopt(AcceptSocket,SOL_SOCKET,SO_RCVTIMEO,(char*)&opt,4);
    127.  
    128.     if (AcceptSocket == INVALID_SOCKET) {
    129.         printf("accept failed with error: %ld\n", WSAGetLastError());
    130.         closesocket(ListenSocket);
    131.         WSACleanup();
    132.         return 1;
    133.     } else{
    134.         printf("Client connected.\n");
    135.         SOCKET hserv_rdp=connect_tunnel();
    136.         if (hserv_rdp!=INVALID_SOCKET){
    137.             //тут туннель !!!
    138.             recv_send(AcceptSocket,hserv_rdp);
    139.             //recv_send(AcceptSocket,hserv_rdp);
    140.            
    141.         }
    142.         iResult = closesocket(hserv_rdp);
    143.         if (iResult == SOCKET_ERROR) {
    144.             printf("closesocket function failed with error: %ld\n", WSAGetLastError());
    145.             WSACleanup();
    146.             return 1;
    147.         }
    148.     }
    149.     }
    150.  
    151.     // No longer need server socket
    152.     closesocket(ListenSocket);
    153.  
    154.     WSACleanup();
    155.     return 0;
    156. }
    157.  
    158. SOCKET connect_tunnel(){
    159.    //----------------------
    160.     // Initialize Winsock
    161.     WSADATA wsaData;
    162.     int iResult = WSAStartup(MAKEWORD(2, 2), &wsaData);
    163.     if (iResult != NO_ERROR) {
    164.         printf("WSAStartup function failed with error: %d\n", iResult);
    165.         return 0;
    166.     }
    167.     //----------------------
    168.     // Create a SOCKET for connecting to server
    169.     SOCKET ConnectSocket;
    170.     ConnectSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
    171.     //DWORD opt=10000;
    172.     //setsockopt(ConnectSocket,SOL_SOCKET,SO_SNDTIMEO,(char*)&opt,4);
    173. //  setsockopt(ConnectSocket,SOL_SOCKET,SO_RCVTIMEO,(char*)&opt,4);
    174.  
    175.     if (ConnectSocket == INVALID_SOCKET) {
    176.         printf("socket function failed with error: %ld\n", WSAGetLastError());
    177.         WSACleanup();
    178.         return 0;
    179.     }
    180.     //----------------------
    181.     // The sockaddr_in structure specifies the address family,
    182.     // IP address, and port of the server to be connected to.
    183.     sockaddr_in clientService;
    184.     clientService.sin_family = AF_INET;
    185.     clientService.sin_addr.s_addr = inet_addr("192.168.75.128");
    186.     clientService.sin_port = htons(3389);
    187.  
    188.     //----------------------
    189.     // Connect to server.
    190.     iResult = connect(ConnectSocket, (SOCKADDR *) & clientService, sizeof (clientService));
    191.     if (iResult == SOCKET_ERROR) {
    192.         printf("connect function failed with error: %ld\n", WSAGetLastError());
    193.         iResult = closesocket(ConnectSocket);
    194.         if (iResult == SOCKET_ERROR)
    195.             printf("closesocket function failed with error: %ld\n", WSAGetLastError());
    196.         //WSACleanup();
    197.         return 0;
    198.     }
    199.  
    200.     printf("Connected to server.\n");
    201.     return ConnectSocket;
    202. }
    203.  
    204. int main(int n,char ** arg){
    205.     server_tunnel();
    206.     //connect_tunnel();
    207.     return 0;
    208. }
     
  2. Aids

    Aids New Member

    Публикаций:
    0
    Регистрация:
    30 ноя 2007
    Сообщения:
    275
  3. Aids

    Aids New Member

    Публикаций:
    0
    Регистрация:
    30 ноя 2007
    Сообщения:
    275
    Все заработало. Помогли неблокируемые сокеты.
    Исправленный вариант если кому понадобится.
     
  4. punxer

    punxer Андрей

    Публикаций:
    0
    Регистрация:
    16 окт 2006
    Сообщения:
    1.327
    Адрес:
    Ржев
    Спросил-нашел-решил-отпостил
    вот спасибо
    в пример многим
     
  5. ASMatic

    ASMatic New Member

    Публикаций:
    0
    Регистрация:
    5 окт 2010
    Сообщения:
    233
    punxer
    поддерживаю!
     
  6. Aids

    Aids New Member

    Публикаций:
    0
    Регистрация:
    30 ноя 2007
    Сообщения:
    275
    функцию send нужно тоже контролировать, а то не всегда отправляла данные в сокет.
    Код (Text):
    1. bool tunnel(SOCKET hsock1,SOCKET hsock2){
    2.     int iResult;
    3.     int count=0;
    4.     char *data=new char[DEFAULT_BUFLEN];
    5.     fd_set  read_s;
    6.     timeval time_out;
    7.     time_out.tv_sec = 0;
    8.     time_out.tv_usec = 0;
    9.     FD_ZERO (&read_s);   
    10.     FD_SET (hsock1, &read_s);
    11.     bool flag=true;
    12.     while (SOCKET_ERROR == (iResult = select (0, &read_s, NULL, NULL, &time_out) ) );
    13.     do{
    14.         iResult = recv(hsock1, &data[count], SIZE_RECV, 0);
    15.         if (iResult>0){
    16.             count+=iResult;
    17.             if (count>DEFAULT_BUFLEN)
    18.                 flag=false;
    19.         }else{
    20.             if (iResult==0){
    21.                 flag=false;
    22.             }
    23.         }
    24.     }while((iResult>0)&&(flag));
    25.  
    26.     if (count>0)
    27.         printf("count: %d\n",count);
    28.     int i=0;
    29.     bool f=true;
    30.     while((count>0) && f){
    31.         if (count>=SIZE_SEND)
    32.             iResult=send(hsock2,&data[i],SIZE_SEND,0);
    33.         else
    34.             iResult=send(hsock2,&data[i],count,0);
    35.         if (iResult>0){
    36.             i+=iResult;
    37.             count-=iResult;
    38.         }
    39.         if (iResult==0)
    40.             f=false;
    41.         FD_ZERO (&read_s);   
    42.         FD_SET (hsock2, &read_s);
    43.         while (SOCKET_ERROR == (iResult = select (0, NULL,&read_s, NULL, &time_out) ) );
    44.         if (iResult==0)
    45.             f=false;
    46.     }
    47.     delete [] data;
    48.     return flag;
    49. }
     
  7. Runcorn

    Runcorn New Member

    Публикаций:
    0
    Регистрация:
    21 дек 2011
    Сообщения:
    1
    Какой то странный код:
    Зачем здесь используется таймаут и разве хорошо писать такой цикл?
     
  8. Aids

    Aids New Member

    Публикаций:
    0
    Регистрация:
    30 ноя 2007
    Сообщения:
    275
    Runcorn
    Да вы правы цикл тут вообще лишний! Я пока эксперементировал намудрил немного. Удивительно что это не приводило к зависанию.

    надо просто так использовать.
    FD_ZERO (&read_s);
    FD_SET (hsock1, &read_s);
    iResult = select (0, &read_s, NULL, NULL, &time_out);

    FD_ZERO (&read_s);
    FD_SET (hsock2, &read_s);
    iResult = select (0, NULL,&read_s, NULL, &time_out);
    таймаут тут обязателен т.к. сокеты неблокируемые, хоть и равен нулю
     
  9. ziral2088

    ziral2088 New Member

    Публикаций:
    0
    Регистрация:
    16 авг 2009
    Сообщения:
    283
    ну так не ставьте его в 0.
    и делайте 1 select на 2 сокета сразу, так же удобней.