Advertisement
mabu

SocketProxy

Jun 15th, 2015
350
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. #ifndef unicode
  2.     #define unicode
  3. #endif
  4. #include "windows.bi"
  5. #include once "win\winsock2.bi"
  6. #include once "win\ws2tcpip.bi"
  7.  
  8. ' Инкапсуляция клиентского и серверного сокетов как параметр для процедуры потока
  9. Type ClientServerSocket
  10.     Dim InSock As SOCKET
  11.     Dim OutSock As SOCKET
  12. End Type
  13.  
  14. Declare Function CommandLineToArgv Alias "CommandLineToArgvW"(ByVal CommandLineString As WString Ptr, ByVal ArgsCount As Integer Ptr)As WString Ptr Ptr
  15. Declare Function ThreadProc(ByVal lpParam As LPVOID)As DWORD
  16. ' Соединиться с сервером и вернуть сокет
  17. Declare Function ConnectToServer(ByRef sServer As WString, ByVal mPort As Integer, ByRef localServer As WString, ByVal LocalPort As Integer)As SOCKET
  18. ' Создать сокет и привязать к адресу
  19. Declare Function CreateSocketAndBind(ByRef localServer As WString, ByVal LocalPort As Integer)As SOCKET
  20. ' Создать прослушивающий сокет
  21. Declare Function CreateSocketAndListen(ByRef localServer As WString, ByVal LocalPort As Integer)As SOCKET
  22. ' Получение данных от входящего соединения и отправка исходящему
  23. Declare Function SendReceiveData(ByVal Flag As Integer, ByVal InSock As SOCKET, ByVal OutSock As SOCKET) As Integer
  24.  
  25. ' Закрывает сокет
  26. Declare Sub CloseSocketConnection(ByVal mSock As SOCKET)
  27. ' Разрешение доменного имени
  28. Declare Function ResolveHost(ByRef sServer As WString)As Integer
  29. Extern "C"
  30.     ' Возвращает указатель на подстроку в строке
  31.     Declare Function wcsstrW Alias "wcsstr"(ByVal Instring As WString Ptr, ByVal Pattern As WString Ptr)As WString Ptr
  32.     ' Строку в Integer
  33.     Declare Function wtoi Alias "_wtoi"(ByVal s As WString Ptr)As Integer
  34. End Extern
  35.  
  36. ' Размер буфера
  37. Const MaxBytesCount As Integer = 2048
  38.  
  39. ' Разрешает доменное имя
  40. Function ResolveHost(ByRef sServer As WString)As Integer
  41.     Dim intDataLength As Integer = lstrlen(sServer)
  42.     ' Перекодируем в байты utf8
  43.     Dim intBytesCount As Integer = WideCharToMultiByte(CP_UTF8, 0, sServer, intDataLength, 0, 0, 0, 0)
  44.     Dim bytes As ZString*MaxBytesCount = Any
  45.     WideCharToMultiByte(CP_UTF8, 0, sServer, intDataLength, bytes, intBytesCount, 0, 0)
  46.     bytes[intBytesCount] = 0
  47.    
  48.     Dim ia As in_addr
  49.     Dim hostentry As hostent Ptr
  50.    
  51.     ia.S_addr = inet_addr(bytes)
  52.     If ia.S_addr = INADDR_NONE Then
  53.         hostentry = gethostbyname(bytes)
  54.         If hostentry <> 0 Then
  55.             Return *CPtr(Integer Ptr, *hostentry->h_addr_list)
  56.         End If
  57.     Else
  58.         Return ia.S_addr
  59.     End if
  60. End Function
  61.  
  62. ' Закрывает сокет
  63. Sub CloseSocketConnection(ByVal mSock As SOCKET)
  64.     Shutdown(mSock, 2)
  65.     closesocket(mSock)
  66. End Sub
  67.  
  68. Function CreateSocketAndBind(ByRef localServer As WString, ByVal LocalPort As Integer)As SOCKET
  69.     ' Открыть сокет
  70.     Dim iSocket As SOCKET = WSASocket(AF_INET, SOCK_STREAM, IPPROTO_TCP, 0, 0, WSA_FLAG_OVERLAPPED)
  71.     If iSocket <> INVALID_SOCKET Then
  72.         ' Привязать адрес к сокету
  73.         Dim localIp As Integer = ResolveHost(LocalServer)
  74.         Dim localSa As sockaddr_in
  75.         With localSa
  76.             .sin_port = htons(LocalPort)
  77.             .sin_family = AF_INET
  78.             .sin_addr.S_addr = localIp
  79.         End With
  80.         If bind(iSocket, Cast(PSOCKADDR, @localSa), SizeOf(localSa)) <> SOCKET_ERROR Then
  81.             Return iSocket
  82.         End If
  83.     End If
  84.     CloseSocketConnection(iSocket)
  85.     Return INVALID_SOCKET
  86. End Function
  87.  
  88. ' Открывает соединение с сервером
  89. Function ConnectToServer(ByRef sServer As WString, ByVal mPort As Integer, ByRef localServer As WString, ByVal LocalPort As Integer)As SOCKET
  90.     ' Открыть сокет
  91.     Dim iSocket As SOCKET = CreateSocketAndBind(localServer, LocalPort)
  92.     If iSocket <> INVALID_SOCKET Then
  93.         Dim ip As Integer = ResolveHost(sServer)
  94.         If ip <> 0 Then
  95.             Dim sa As sockaddr_in
  96.             With sa
  97.                 .sin_port = htons(mPort)
  98.                 .sin_family = AF_INET
  99.                 .sin_addr.S_addr = ip
  100.             End With
  101.             If WSAConnect(iSocket, Cast(PSOCKADDR, @sa), SizeOf(sa), 0, 0, 0, 0) = 0 Then
  102.                 Return iSocket
  103.             End If
  104.         End If
  105.     End If
  106.     CloseSocketConnection(iSocket)
  107.     Return INVALID_SOCKET
  108. End Function
  109.  
  110. Function CreateSocketAndListen(ByRef localServer As WString, ByVal LocalPort As Integer)As SOCKET
  111.     ' Открыть сокет
  112.     Dim iSocket As SOCKET = CreateSocketAndBind(localServer, LocalPort)
  113.     If iSocket <> INVALID_SOCKET Then
  114.         ' Начать прослушивание
  115.         If listen(iSocket, 1) <> SOCKET_ERROR Then
  116.             Return iSocket
  117.         End If
  118.     End If
  119.     CloseSocketConnection(iSocket)
  120.     Return INVALID_SOCKET
  121. End Function
  122.  
  123. ' Приём данных от сервера и отправка клиенту в отдельном потоке
  124. Function ThreadProc(ByVal lpParam As LPVOID)As DWORD
  125.     Dim objClientServerSocket As ClientServerSocket Ptr = lpParam
  126.     Return SendReceiveData(1, objClientServerSocket->InSock, objClientServerSocket->OutSock)
  127. End Function
  128.  
  129. Function SendReceiveData(ByVal Flag As Integer, ByVal InSock As SOCKET, ByVal OutSock As SOCKET) As Integer
  130.     Dim ReceiveBuffer As ZString*MaxBytesCount = Any
  131.     Do
  132.         ' Читать данные из входящего сокета, отправляю на исходящий
  133.         Dim intReceivedBytesCount As Integer = recv(InSock, ReceiveBuffer, MaxBytesCount, 0)
  134.         If intReceivedBytesCount > 0 Then
  135.             ' Отправить данные
  136.             If send(OutSock, ReceiveBuffer, intReceivedBytesCount, 0) = SOCKET_ERROR Then
  137.                 Return SOCKET_ERROR
  138.             End If
  139.         Else
  140.             Return SOCKET_ERROR
  141.         End If
  142.     Loop
  143.     Return 0
  144. End Function
  145.  
  146. /'
  147.     Параметры
  148.     1 — локальный адрес адаптера, через который будет идти соединение с сервером
  149.     2 — локальный порт
  150.     3 — адрес сервера
  151.     4 — порт сервер
  152.     5 — адрес, с которым будет соединяться клиент
  153.     6 — порт, с которым будет соединяться клиент
  154. '/
  155. Function ConsoleEntryPoint Alias "ConsoleEntryPoint"()As Integer
  156.     ' Параметры командной строки
  157.     Dim ArgsCount As Integer = Any
  158.     Dim Args As WString Ptr Ptr = CommandLineToArgv(GetCommandLine(), @ArgsCount)
  159.     ' Инициализация сокетов
  160.     Dim objWsaData As WSAData
  161.     If WSAStartup(MAKEWORD(2, 2), @objWsaData) = NO_ERROR Then
  162.         ' Открыть слушатель на локалхосте
  163.         Dim ListenSocket As SOCKET = CreateSocketAndListen(*Args[5], wtoi(Args[6]))
  164.         If ListenSocket = INVALID_SOCKET Then
  165.             ConsoleEntryPoint = 2
  166.         Else
  167.             ' Принять соединение
  168.             Dim AcceptSocket As SOCKET = accept(ListenSocket, 0, 0)
  169.             If AcceptSocket = INVALID_SOCKET Then
  170.                 ConsoleEntryPoint = 3
  171.             Else
  172.                 ' Соединиться с сервером
  173.                 Dim ClientSocket As SOCKET = ConnectToServer(*Args[3], wtoi(Args[4]), *Args[1], wtoi(Args[2]))
  174.                 If ClientSocket = INVALID_SOCKET Then
  175.                     ConsoleEntryPoint = 4
  176.                 Else
  177.                     Dim objClientServerSocket As ClientServerSocket = Any
  178.                     With objClientServerSocket
  179.                         .InSock = ClientSocket
  180.                         .OutSock = AcceptSocket
  181.                     End With
  182.                     ' Запустить поток чтения данных от сервера   , передать клиентский сокет в качестве параметра
  183.                     Dim hThread As HANDLE = CreateThread(NULL, 0, @ThreadProc, @objClientServerSocket, 0, NULL)
  184.                    
  185.                     ' Получить данные от клиента и отправить на сервер
  186.                     SendReceiveData(0, AcceptSocket, ClientSocket)
  187.                 End If
  188.                 CloseSocketConnection(ClientSocket)
  189.                 CloseSocketConnection(AcceptSocket)
  190.             End If
  191.         End If
  192.         CloseSocketConnection(ListenSocket)
  193.         ' При ошибках чтения‐записи закрывать соединение и выходить
  194.         WSACleanup()
  195.         ConsoleEntryPoint = 0
  196.     Else
  197.         ConsoleEntryPoint = 1
  198.     End If
  199.     ' Очистка памяти от параметров программы
  200.     LocalFree(Args)
  201. End Function
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement