i decided to take a jab at creating a http proxy server in ddt.
the first step is just to get things working in a single thread.
here is my stumbling block
i need some help with an alternative way other than ddt of sending a request to a web server and getting the whole returned data back so it can be sent back to the browser on the client os.
the end result is to have the proxy running on the same machine that is accessing the internet, maybe and most likely where a user on a virtual(guest) os is accessing the internet on port 80(http), but going through a proxy server on the host os. the host machine will log sites visited through the proxy server.
the only speed problems i have with ddt is a very slight slowness in establishing a connection to the website, but where the speed is really reduced, is where the ddt program is trying to find out if it has received all the data from the web server. In order to speed things along, i have to reduce the timeout period down to a very small time on the tcp open line.
i am going to list the ddt proxy server for those interested, i have tweaked it the best i can time wise.
being i do not see any way of recoding the program using straight ddt and i have another way by counting characters being sent, that still does not work, because you will get a few extra charcaters back from the web request and the number of extra characters is always different.
i need an alternative way of requesting information from a web server and returning that same information back the os that originated the request to the proxy server.
i started with code from the echo server sample program provide by powerbasic.
ddt proxy server
the current wininet code i am trying but not quiet having all the success.
code using ddt and wininet
i am sure there are ways other than wininet but i was just trying that to see what the outcome would be.
the first step is just to get things working in a single thread.
here is my stumbling block
i need some help with an alternative way other than ddt of sending a request to a web server and getting the whole returned data back so it can be sent back to the browser on the client os.
the end result is to have the proxy running on the same machine that is accessing the internet, maybe and most likely where a user on a virtual(guest) os is accessing the internet on port 80(http), but going through a proxy server on the host os. the host machine will log sites visited through the proxy server.
the only speed problems i have with ddt is a very slight slowness in establishing a connection to the website, but where the speed is really reduced, is where the ddt program is trying to find out if it has received all the data from the web server. In order to speed things along, i have to reduce the timeout period down to a very small time on the tcp open line.
i am going to list the ddt proxy server for those interested, i have tweaked it the best i can time wise.
being i do not see any way of recoding the program using straight ddt and i have another way by counting characters being sent, that still does not work, because you will get a few extra charcaters back from the web request and the number of extra characters is always different.
i need an alternative way of requesting information from a web server and returning that same information back the os that originated the request to the proxy server.
i started with code from the echo server sample program provide by powerbasic.
ddt proxy server
Code:
'proxy.bas 'compiled with pbcc 4.04 #COMPILE EXE #DIM ALL '------------------------------------------------------------------------------ ' Include files and settings ' %CCWIN = 1 ' Include GUI API calls %USEMACROS = 1 #INCLUDE "WIN32API.INC" #INCLUDE "WS2_32.INC" %TCP_ACCEPT = %WM_USER + 4093 ' Any value larger than %WM_USER + 500 %TCP_proxy = %WM_USER + 4094 ' Any value larger than %WM_USER + 500 '------------------------------------------------------------------------------ ' Global variables ' GLOBAL hproxy AS LONG GLOBAL hwebpage AS LONG GLOBAL hServer AS LONG GLOBAL hwndTCP AS LONG GLOBAL hThread AS LONG GLOBAL gpriorserverlocation AS STRING '------------------------------------------------------------------------------ ' Callback function to handle events for the GUI window ' FUNCTION TcpProc (BYVAL hWnd AS LONG, BYVAL wMsg AS LONG, _ BYVAL wParam AS LONG, BYVAL lParam AS LONG) EXPORT AS LONG STATIC hServer AS LONG STATIC hproxy AS LONG LOCAL endofheader, contentlength AS LONG LOCAL sBuffer AS STRING LOCAL sPacket AS STRING LOCAL serverlocation,buffer,received AS STRING LOCAL RECEIVEdCOUNT AS LONG LOCAL temp AS LONG LOCAL blocksize,loftemp AS LONG SELECT CASE wMsg CASE %WM_CREATE hServer = FREEFILE TCP OPEN SERVER PORT 998 AS hServer TIMEOUT 60000 IF ERR THEN sBuffer = "proxy Couldn't create socket!" ELSE TCP NOTIFY hServer, ACCEPT TO hWnd AS %TCP_ACCEPT sBuffer = "proxy Connected to Port 998" END IF ' STDOUT sbuffer hproxy = %INVALID_SOCKET FUNCTION = 1 CASE %TCP_ACCEPT SELECT CASE LO(WORD, lParam) CASE %FD_ACCEPT hproxy = FREEFILE TCP ACCEPT hServer AS hproxy TCP NOTIFY hproxy, RECV CLOSE TO hWnd AS %TCP_proxy END SELECT FUNCTION = 1 CASE %TCP_proxy SELECT CASE LO(WORD, lParam) CASE %FD_READ IF hproxy <> %INVALID_SOCKET THEN ' Perform a receive-loop until there is no data left (ie, the end of stream) sPacket = "" sbuffer = "" ERRCLEAR DO TCP RECV hproxy, 4096*2, sBuffer sPacket = sPacket & sBuffer LOOP UNTIL sBuffer = "" OR ISTRUE EOF(hproxy) OR ISTRUE ERR ' MONITOR the header from the client ' CLs ' stdout MID$(spacket,1,INSTR(spacket, $crlf+$crlf)) IF LEN(spacket) THEN serverlocation=MID$(spacket,12,INSTR(6,spacket, " HTTP/")-13) IF TALLY(serverlocation,"/") THEN serverlocation=MID$(serverlocation,1,INSTR(serverlocation, "/")-1) ERRCLEAR TCP CLOSE hwebpage hwebpage=FREEFILE STDOUT "trying to connect"+STR$(hwebpage) STDOUT serverlocation TCP OPEN PORT 80 AT TRIM$(serverlocation) AS #hwebpage TIMEOUT 2000 'Open server STDOUT "CONNECTED" TCP PRINT hwebpage, spacket STDOUT "sent to web server" SLEEP 30 received="" receivedcount=1& ERRCLEAR DO INCR receivedcount STDOUT STR$(receivedcount) buffer="" TCP RECV hwebpage,4096*2,buffer IF LEN(buffer)=0& OR ERR THEN EXIT DO received = received & buffer SLEEP 10 LOOP STDOUT "done web server reading" TCP SEND hproxy, received TCP CLOSE #hwebpage 'Disconnect from webserver hwebpage=0& STDOUT "closed connection to webserver" ' stdout received TCP CLOSE hproxy ' log web server received for testing ' TEMP&=FREEFILE ' OPEN "proxy.txt" FOR APPEND AS #TEMP& ' PRINT #TEMP&,USING$("&",".........................................."+$CRLF+$CRLF) ' PRINT #TEMP&,USING$("&",RECEIVED+$CRLF+$CRLF) ' CLOSE #TEMP& END IF END IF CASE %FD_CLOSE TCP CLOSE hproxy hproxy = %INVALID_SOCKET END SELECT FUNCTION = 1 CASE %WM_DESTROY TCP CLOSE hServer END SELECT FUNCTION = DefWindowProc(hWnd, wMsg, wParam, lParam) END FUNCTION '------------------------------------------------------------------------------ ' Create the GUI window to receive TCP event notification messages ' FUNCTION MakeWindow () AS LONG LOCAL wce AS WndClassEx LOCAL szClassName AS ASCIIZ * 64 LOCAL hWnd AS LONG LOCAL hInst AS LONG STATIC registered AS LONG hInst = GetModuleHandle(BYVAL %NULL) IF ISFALSE registered THEN szClassName = "PBTCPCOMM" wce.cbSize = SIZEOF(wce) wce.style = %CS_HREDRAW OR %CS_VREDRAW wce.lpfnWndProc = CODEPTR(TcpProc) wce.cbClsExtra = 0 wce.cbWndExtra = 0 wce.hInstance = hInst wce.hIcon = %NULL wce.hCursor = %NULL wce.hbrBackground = %NULL wce.lpszMenuName = %NULL wce.lpszClassName = VARPTR(szClassName) wce.hIconSm = %NULL RegisterClassEx wce registered = %TRUE END IF hWnd = CreateWindow(szClassName, _ "TCP Handler", _ %WS_OVERLAPPEDWINDOW, _ 5, 5, 10, 10, _ %NULL, _ %NULL, _ hInst, _ BYVAL %NULL) IF ISFALSE hWnd THEN hWnd = GetLastError ELSE ShowWindow hWnd, %SW_HIDE UpdateWindow hWnd END IF FUNCTION = hWnd END FUNCTION '------------------------------------------------------------------------------ ' Spawn a thread to create/own the GUI window and run a thread message pump. ' Each thread must operate it's own pump the GUI windows it owns. ' FUNCTION WindowThread (BYVAL nIgnored AS LONG) AS LONG LOCAL Msg AS tagMsg hwndTCP = MakeWindow DO WHILE IsWindow(hwndTCP) AND GetMessage(Msg, %NULL, 0, 0) TranslateMessage Msg DispatchMessage Msg LOOP END FUNCTION '------------------------------------------------------------------------------ ' Main program entry point... ' FUNCTION PBMAIN () AS LONG CONSOLE SCREEN 51,80 ' Process socket messages in a separate thread THREAD CREATE WindowThread(%NULL) TO hThread ' If the user presses the Esc key, exit the server PRINT "Press ESC to end the proxy Server" DO UNTIL WAITKEY$ = $ESC LOOP SendMessage hwndTCP, %WM_CLOSE, 0, 0 END FUNCTION
code using ddt and wininet
i am sure there are ways other than wininet but i was just trying that to see what the outcome would be.
Code:
proxy.bas 'compiled with pbcc 4.04 #COMPILE EXE #DIM ALL '------------------------------------------------------------------------------ ' Include files and settings ' %CCWIN = 1 ' Include GUI API calls %USEMACROS = 1 #INCLUDE "WIN32API.INC" #INCLUDE "WS2_32.INC" #INCLUDE "WININET.INC" %TCP_ACCEPT = %WM_USER + 4093 ' Any value larger than %WM_USER + 500 %TCP_proxy = %WM_USER + 4094 ' Any value larger than %WM_USER + 500 '------------------------------------------------------------------------------ ' Global variables ' GLOBAL hproxy AS LONG GLOBAL hwebpage AS LONG GLOBAL hServer AS LONG GLOBAL hwndTCP AS LONG GLOBAL hThread AS LONG %HTTP_BUFFER_LENGTH=4096 '16000 FUNCTION WEBREQUEST(rpacket AS STRING) AS STRING LOCAL iReturn AS LONG LOCAL iRead AS LONG LOCAL hInternet AS DWORD LOCAL hConn AS DWORD LOCAL hRequest AS DWORD LOCAL sHeaders AS ASCIIZ*3000 LOCAL sData AS STRING LOCAL sBuffer AS STRING LOCAL ErrMsg AS STRING LOCAL sReturnData AS STRING LOCAL myurl AS ASCIIZ*%MAX_PATH LOCAL formdata AS STRING LOCAL sMethod AS ASCIIZ*%MAX_PATH LOCAL ws AS ASCIIZ*%MAX_PATH LOCAL spacketheader AS STRING LOCAL serverlocation AS STRING LOCAL smainheader AS STRING smainheader=MID$(rpacket,1,INSTR(rpacket, $CRLF)+1) sMethod=MID$(smainheader,1,INSTR(smainheader," ")-1) spacketheader=TRIM$(MID$(rpacket,1,INSTR(1,rpacket, $CRLF+$CRLF)+3)) serverlocation=TRIM$(MID$(spacketheader,12,INSTR(6,spacketheader, " HTTP/")-13)) IF TALLY(serverlocation,"/") THEN serverlocation=MID$(serverlocation,1,INSTR(serverlocation, "/")-1) sheaders=TRIM$(RIGHT$(spacketheader,(LEN(spacketheader)-LEN(smainheader)))) formdata=RIGHT$(rpacket,LEN(rpacket)-LEN(spacketheader)) ws="http://"+serverlocation ws = REMAIN$(ws,"://") ws = MID$(ws,INSTR(ws,"/")+1) hInternet = InternetOpen(BYVAL %NULL, %INTERNET_OPEN_TYPE_PRECONFIG, BYVAL %NULL, BYVAL %NULL, 0) IF hInternet = 0 THEN ErrMsg = "InternetOpen failed" GOTO Finish END IF STDOUT "internet open" PRINT ws hConn = InternetConnect(hInternet, ws, 80, "", "", %INTERNET_SERVICE_HTTP, 0, 0) IF hConn = 0 THEN ErrMsg = "InternetConnect failed" WAITKEY$ GOTO Finish END IF STDOUT "connected to web" hRequest = httpOpenRequest(hConn, sMethod, ws, "HTTP/1.1", BYVAL %NULL, BYVAL %NULL, %INTERNET_FLAG_RELOAD OR _ %INTERNET_FLAG_NO_CACHE_WRITE OR %INTERNET_FLAG_PRAGMA_NOCACHE,%NULL) IF hRequest = 0 THEN ErrMsg = "httpOpenRequest failed." GOTO Finish END IF STDOUT "ready for data part" sData=formdata STDOUT "----------------------------" PRINT sheaders STDOUT "----------------------------" IF LEN(sdata)=0& THEN sdata=" " STDOUT "----------------------------" IF httpSendRequest(hRequest, sHeaders, LEN(sHeaders), BYVAL STRPTR(sData), LEN(sData)) = 0 THEN ErrMsg = "httpSendRequest failed." GOTO Finish END IF ' stdout "sdata" iRead = 0 sReturnData = "" sBuffer = SPACE$(%HTTP_BUFFER_LENGTH) iReturn = InternetReadFile(hRequest, BYVAL STRPTR(sBuffer), %HTTP_BUFFER_LENGTH, iRead) DO IF iRead = 0 THEN IF iReturn <> 0 THEN EXIT DO END IF END IF sReturnData = sReturnData + LEFT$(sBuffer, iRead) iRead = 0 sBuffer = SPACE$(%HTTP_BUFFER_LENGTH) iReturn = InternetReadFile(hRequest, BYVAL STRPTR(sBuffer), %HTTP_BUFFER_LENGTH, iRead) LOOP STDOUT sreturndata Finish: IF hRequest<>0 THEN InternetCloseHandle hRequest END IF IF hConn<>0 THEN InternetCloseHandle hConn END IF IF hInternet<>0 THEN InternetCloseHandle hInternet END IF FUNCTION = sReturnData END FUNCTION '------------------------------------------------------------------------------ ' Callback function to handle events for the GUI window ' FUNCTION TcpProc (BYVAL hWnd AS LONG, BYVAL wMsg AS LONG, _ BYVAL wParam AS LONG, BYVAL lParam AS LONG) EXPORT AS LONG STATIC hServer AS LONG STATIC hproxy AS LONG LOCAL endofheader, contentlength AS LONG LOCAL sBuffer AS STRING LOCAL sPacket AS STRING LOCAL serverlocation,buffer,received AS STRING LOCAL RECEIVEdCOUNT AS LONG LOCAL temp AS LONG LOCAL blocksize,loftemp AS LONG SELECT CASE wMsg CASE %WM_CREATE hServer = FREEFILE TCP OPEN SERVER PORT 998 AS hServer TIMEOUT 60000 IF ERR THEN sBuffer = "proxy Couldn't create socket!" ELSE TCP NOTIFY hServer, ACCEPT TO hWnd AS %TCP_ACCEPT sBuffer = "proxy Connected to Port 998" END IF STDOUT sbuffer hproxy = %INVALID_SOCKET FUNCTION = 1 CASE %TCP_ACCEPT SELECT CASE LO(WORD, lParam) CASE %FD_ACCEPT hproxy = FREEFILE TCP ACCEPT hServer AS hproxy TCP NOTIFY hproxy, RECV CLOSE TO hWnd AS %TCP_proxy END SELECT FUNCTION = 1 CASE %TCP_proxy SELECT CASE LO(WORD, lParam) CASE %FD_READ IF hproxy <> %INVALID_SOCKET THEN ' Perform a receive-loop until there is no data left (ie, the end of stream) sPacket = "" sbuffer = "" ERRCLEAR DO TCP RECV hproxy, 4096*2, sBuffer sPacket = sPacket & sBuffer LOOP UNTIL sBuffer = "" OR ISTRUE EOF(hproxy) OR ISTRUE ERR IF LEN(spacket) THEN received=webrequest(spacket) TCP SEND hproxy, received TCP CLOSE hproxy END IF ' stdout received END IF CASE %FD_CLOSE TCP CLOSE hproxy hproxy = %INVALID_SOCKET END SELECT FUNCTION = 1 CASE %WM_DESTROY TCP CLOSE hServer END SELECT FUNCTION = DefWindowProc(hWnd, wMsg, wParam, lParam) END FUNCTION '------------------------------------------------------------------------------ ' Create the GUI window to receive TCP event notification messages ' FUNCTION MakeWindow () AS LONG LOCAL wce AS WndClassEx LOCAL szClassName AS ASCIIZ * 64 LOCAL hWnd AS LONG LOCAL hInst AS LONG STATIC registered AS LONG hInst = GetModuleHandle(BYVAL %NULL) IF ISFALSE registered THEN szClassName = "PBTCPCOMM" wce.cbSize = SIZEOF(wce) wce.style = %CS_HREDRAW OR %CS_VREDRAW wce.lpfnWndProc = CODEPTR(TcpProc) wce.cbClsExtra = 0 wce.cbWndExtra = 0 wce.hInstance = hInst wce.hIcon = %NULL wce.hCursor = %NULL wce.hbrBackground = %NULL wce.lpszMenuName = %NULL wce.lpszClassName = VARPTR(szClassName) wce.hIconSm = %NULL RegisterClassEx wce registered = %TRUE END IF hWnd = CreateWindow(szClassName, _ "TCP Handler", _ %WS_OVERLAPPEDWINDOW, _ 5, 5, 10, 10, _ %NULL, _ %NULL, _ hInst, _ BYVAL %NULL) IF ISFALSE hWnd THEN hWnd = GetLastError ELSE ShowWindow hWnd, %SW_HIDE UpdateWindow hWnd END IF FUNCTION = hWnd END FUNCTION '------------------------------------------------------------------------------ ' Spawn a thread to create/own the GUI window and run a thread message pump. ' Each thread must operate it's own pump the GUI windows it owns. ' FUNCTION WindowThread (BYVAL nIgnored AS LONG) AS LONG LOCAL Msg AS tagMsg hwndTCP = MakeWindow DO WHILE IsWindow(hwndTCP) AND GetMessage(Msg, %NULL, 0, 0) TranslateMessage Msg DispatchMessage Msg LOOP END FUNCTION '------------------------------------------------------------------------------ ' Main program entry point... ' FUNCTION PBMAIN () AS LONG ' CONSOLE SCREEN 51,80 ' Process socket messages in a separate thread THREAD CREATE WindowThread(%NULL) TO hThread ' If the user presses the Esc key, exit the server PRINT "Press ESC to end the proxy Server" DO UNTIL WAITKEY$ = $ESC LOOP SendMessage hwndTCP, %WM_CLOSE, 0, 0 END FUNCTION
Comment