Simpler Proxyserver mit Purebasic - klappt nur nicht. Hilfe!
Verfasst: 02.03.2009 20:49
Hallo,
Ich versuche gerade einen simplen portablen Proxyserver zu schreiben.
Um ehrlich zu sein hab ich den legendären Atomic Webserver angepasst.
Nur ergeben sich hier zwei Probleme:
Die Funktionsweise ist wie folgt:
1. Listen nach HTTP-Requests
2. Anpassen des Requests
3. Weiterreichen des Requests an den Zielserver
4. Öffnen einer TCP connection zum Zielserver
5. Rückgabe der Response an den Browser
Leider klappt das mit der TCP-Connection nicht.
Zweites Problem:
Ich habe versucht den Requesthandler als Thread zu starten damit wartende Requests nicht den Gesamtladevorgang bremsen.
Auch hier mache ich was falsch mit dem Allokieren des Speichers.
Könnte bitte mal jemand über den Code schauen und helfende Tips geben?
Ich versuche gerade einen simplen portablen Proxyserver zu schreiben.
Um ehrlich zu sein hab ich den legendären Atomic Webserver angepasst.
Nur ergeben sich hier zwei Probleme:
Die Funktionsweise ist wie folgt:
1. Listen nach HTTP-Requests
2. Anpassen des Requests
3. Weiterreichen des Requests an den Zielserver
4. Öffnen einer TCP connection zum Zielserver
5. Rückgabe der Response an den Browser
Leider klappt das mit der TCP-Connection nicht.
Zweites Problem:
Ich habe versucht den Requesthandler als Thread zu starten damit wartende Requests nicht den Gesamtladevorgang bremsen.
Auch hier mache ich was falsch mit dem Allokieren des Speichers.
Könnte bitte mal jemand über den Code schauen und helfende Tips geben?
Code: Alles auswählen
Enumeration
#Window_0
#Panel_0
#Editor_0
#Editor_1
EndEnumeration
Port= 8080
AtomicTitle$ = "Atomic Proxy v1.0"
Global EOL$
EOL$ = Chr(13)+Chr(10)
Procedure.s GetParam (request$,param$)
Select param$
Case "Method"
ReturnVar$ = StringField(request$, 1, " ")
Case "Path"
ReturnVar$ = RemoveString(StringField(request$, 2, " "), StringField(StringField(request$, 2, " "),1,"/") + "//" + StringField(StringField(request$, 2, " "),3,"/"))
Case "Server"
ReturnVar$ = StringField(StringField(request$, 2, " "),1,"/") + "//" + StringField(StringField(request$, 2, " "),3,"/")
ReturnVar$ = StringField(ReturnVar$, 1, ":") + ":" + StringField(ReturnVar$, 2, ":")
Case "RequestOut"
Host$ = ""
Server$ = StringField(StringField(request$, 2, " "),1,"/") + "//" + StringField(StringField(request$, 2, " "),3,"/")
Port$ = StringField(Server$, 3, ":")
ReturnVar$ = ReplaceString(request$, Server$, Host$)
ReturnVar$ = RemoveString(ReturnVar$, ":"+Port$)
Case "Port"
Server$ = StringField(StringField(request$, 2, " "),1,"/") + "//" + StringField(StringField(request$, 2, " "),3,"/")
ReturnVar$ = StringField(Server$, 3, ":")
If ReturnVar$ = ""
ReturnVar$ = "80"
EndIf
EndSelect
ProcedureReturn ReturnVar$
EndProcedure
Procedure Open_Window_0()
If OpenWindow(#Window_0, 260, 282, 1065, 687, AtomicTitle$ + " (Port "+Str(Port)+")", #PB_Window_SystemMenu | #PB_Window_SizeGadget | #PB_Window_TitleBar )
PanelGadget(#Panel_0, 0, 0, 1070, 690)
AddGadgetItem(#Panel_0, -1, "Request_in")
EditorGadget(#Editor_0, 8, 8, 1050, 650)
AddGadgetItem(#Panel_0, -1, "Request_out")
EditorGadget(#Editor_1, 8, 8, 1050, 650)
EndIf
EndProcedure
Procedure.l BuildRequestHeader(*Buffer, DataLength.l, ContentType$)
Length = PokeS(*Buffer, "HTTP/1.1 200 OK"+EOL$) : *Buffer+Length
Length = PokeS(*Buffer, "Date: Wed, 07 Aug 1996 11:15:43 GMT"+EOL$) : *Buffer+Length
Length = PokeS(*Buffer, "Server: Atomic Web Server 0.2b"+EOL$) : *Buffer+Length
Length = PokeS(*Buffer, "Content-Length: "+Str(DataLength)+EOL$) : *Buffer+Length
Length = PokeS(*Buffer, "Content-Type: "+ContentType$+EOL$) : *Buffer+Length
Length = PokeS(*Buffer, EOL$) : *Buffer+Length
ProcedureReturn *Buffer
EndProcedure
Procedure ProcessRequests(ClientID)
*Buffer = AllocateMemory(10000)
BaseDirectory$ = "www/"
DefaultPage$ = "Index.html"
RequestLength.l = ReceiveNetworkData(ClientID, *Buffer, 2000)
request$ = PeekS(*Buffer)
SetGadgetText(#Editor_0,GetGadgetText(#Editor_0) + EOL$ + request$)
SetGadgetText(#Editor_1,GetGadgetText(#Editor_1) + EOL$ + "Server: " + GetParam(request$,"Server"))
SetGadgetText(#Editor_1,GetGadgetText(#Editor_1) + EOL$ + "Port: " + GetParam(request$,"Port"))
SetGadgetText(#Editor_1,GetGadgetText(#Editor_1) + EOL$ + GetParam(request$,"RequestOut"))
server$ = GetParam(request$,"Server")
RequestOut$ = GetParam(request$,"RequestOut") + EOL$
port = Val(GetParam(request$,"Port"))
ConnectionID = OpenNetworkConnection(server$, port)
If ConnectionID
*DataBuffer = AllocateMemory(10000)
SendNetworkString(ConnectionID, RequestOut$)
ResponseLength.l = ReceiveNetworkData(ConnectionID, *DataBuffer, 10000)
SendNetworkData(ClientID, *DataBuffer, ResponseLength.l)
FreeMemory(*DataBuffer)
EndIf
SetGadgetText(#Editor_1,GetGadgetText(#Editor_1) + EOL$ + "ConnectionID = " + server$ + " " + Str(ConnectionID))
If ReadFile(0, BaseDirectory$+"AtomicWebServer_Error.html")
FileLength = Lof(0)
ContentType$ = "text/html"
*FileBuffer = AllocateMemory(FileLength+200)
*BufferOffset = BuildRequestHeader(*FileBuffer, FileLength, ContentType$)
ReadData(0, *BufferOffset, FileLength)
CloseFile(0)
SendNetworkData(ClientID, *FileBuffer, *BufferOffset-*FileBuffer+FileLength)
FreeMemory(*FileBuffer)
EndIf
; EndIf
;EndIf
FreeMemory(*Buffer)
EndProcedure
If InitNetwork() = 0
MessageRequester("Error", "Can't initialize the network !", 0)
End
EndIf
If CreateNetworkServer(0, Port)
Open_Window_0()
Repeat
Repeat
WEvent = WindowEvent()
If WEvent = #PB_Event_CloseWindow : Quit = 1 : EndIf
Until WEvent = 0
SEvent = NetworkServerEvent()
If SEvent
ClientID.l = EventClient()
Select SEvent
Case 1 ; When a new client has been connected...
Case 4 ; When a client has closed the connection...
Default
ProcessRequests(ClientID)
; CreateThread(@ProcessRequests(),ClientID) <---------------- this would start the requesthandler as multithread.. if it would work.. :-(
EndSelect
Else
Delay(20) ; Don't stole the whole CPU !
EndIf
Until Quit = 1
CloseNetworkServer(0)
Else
MessageRequester(AtomicTitle$, "Error: can't create the server (port in use ?).", 0)
EndIf
End