Re: [twsocket] GpHTTPProxy doesn't work correctly
Oh, it is that bug :(( Sorry for not including in the debate sooner, but I lost contact with GpHttpProxy years ago when I started to work on a custom version for one of my customers. Now I had no idea which of the problems I fixed years ago this was (yes, I was not using source control at the time :( ). The trick was to destroy remote socket and recreate it if host or port changed. I think this are the two most important parts: procedure TGpHttpProxy.ProcessHeader(Client: TGpHttpProxyClient); var ahost: string; aport: string; header : string; returnContent: string; resetSocket : boolean; begin resetSocket := false; returnContent := ''; header := Client.Received; if SameText(FirstEl(header,' ',-1),'CONNECT') then begin // TCP Tunnel proxy request HttpData(Client).ProxyType := ptTCPTunnel; if not IPSec.IsAllowed(Client.PeerAddr) then returnContent := Response.sTCPTunnelIPForbidden.Text else if not (ptTCPTunnel in EnabledTypes) then returnContent := Response.sTCPTunnelClosed.Text else if not ProcessTCPTunnelHeader(Client,header,ahost,aport,returnContent) then returnContent := Response.sTCPTunnelBadRequest.Text; end else begin // HTTP proxy request HttpData(Client).ProxyType := ptHTTP; if not IPSec.IsAllowed(Client.PeerAddr) then returnContent := Response.sHTTPIPForbidden.Text else if not (ptHTTP in EnabledTypes) then returnContent := Response.sHTTPClosed.Text else if not ProcessHTTPHeader(Client,header,ahost,aport,returnContent,resetSocket) then returnContent := Response.sHTTPBadRequest.Text; end; //else SameText() // Header parsed, create remote socket. if returnContent = '' then begin if resetSocket then begin {$IFDEF LogHttpFlow} LogFlow(Client, 'Destroyed connection to %s:%s due to host/port change', [Client.RemoteHost, Client.RemoteSocket.Port]); {$ENDIF LogHttpFlow} Client.DestroyRemoteSocket; Client.NumRequests := 1; end; if not assigned(Client.RemoteSocket) then with Client do begin {$IFDEF LogHttpFlow} LogFlow(Client, 'Opening connection to %s:%s', [ahost, aport]); {$ENDIF LogHttpFlow} CreateRemoteSocket; RemoteHost:= ahost; RemoteSocket.Port := aport; RemoteSocket.LineMode := false; HookRemoteEvents(RemoteSocket); RemoteSocket.DnsLookup(ahost); DoRemoteSocketPrepared(Client); end //with/if else begin {$IFDEF LogHttpFlow} LogFlow(Client, 'Reusing connection to %s:%s', [Client.RemoteHost, Client.RemoteSocket.Port]); {$ENDIF LogHttpFlow} end; {$IFDEF LogHttpFlow} LogFlow(Client, 'Request: %s', [FirstEl(header, #13, -1)]); {$ENDIF LogHttpFlow} Client.Received := header; end else begin Client.DestroyRemoteSocket; Client.RemoteContent := returnContent; end; Client.GotHeader := true; end; { TGpHttpProxy.ProcessHeader } function TGpHttpProxy.ProcessHTTPHeader(Client: TGpHttpProxyClient; var header, ahost, aport, returnContent: string; var socketResetRequired: boolean): boolean; function MakeUrl(aproto, auser, apass, ahost, aport, apath: string): string; begin Result := aproto; if Last(Result,1) = ':' then Result := Result + '//' else if Last(Result,1) '/' then Result := Result + '://'; if auser '' then begin Result := Result + auser; if apass '' then Result := Result + ':' + apass; Result := Result + '@'; end; Result := Result + ahost; if (aport '') and (aport '80') then Result := Result + ':' + aport; Result := Result + apath; end; { MakeUrl } var apass : string; apath : string; aproto: string; auser : string; command : string; hdrHost : string; ignoreNextHopProxy: boolean; p1: integer; p2: integer; s : string; url : string; begin { TGpHttpProxy.ProcessHTTPHeader } Result := false; socketResetRequired := false; // extract url from GET/POST header s := header; p1 := Pos(' ',s); if p1 0 then begin command := First(s,p1-1); Delete(s,1,p1); s := TrimLeft(s); p2 := Pos(' ',s); if p2 0 then begin url := Copy(s,1,p2-1); ParseURL(url,aproto,auser,apass,ahost,aport,apath); if aport = '' then aport := '80'; hdrHost := ExtractHeader(header,'Host'); returnContent := ''; ignoreNextHopProxy := false; DoClientHeaderAvailable(Client,url,header,aproto,auser,apass,ahost,aport, apath,hdrHost,ignoreNextHopProxy,returnContent); if (NextHopHTTP.Address '') and (not ignoreNextHopProxy) and (returnContent = '') then //replace host information with proxy begin Delete(header,p1+1,p2-1);
Re: [twsocket] GpHTTPProxy doesn't work correctly
Hello, Primoz! I think the modified code can not solve the problem on its own, without further modifications. The reason for this is that ProcessHeader procedure is called from ReceivedFromClient if and only if Client.GotHeader is false, but it is set to true after the very first invocation of the ProcessHeader, so it will not be called for all subsequent requests in a given connection. Best wishes, Stanislav Korotky. - Original Message - From: Primož Gabrijelčič [EMAIL PROTECTED] To: 'ICS support mailing' twsocket@elists.org Sent: Monday, September 22, 2008 10:06 AM Subject: Re: [twsocket] GpHTTPProxy doesn't work correctly Oh, it is that bug :(( Sorry for not including in the debate sooner, but I lost contact with GpHttpProxy years ago when I started to work on a custom version for one of my customers. Now I had no idea which of the problems I fixed years ago this was (yes, I was not using source control at the time :( ). The trick was to destroy remote socket and recreate it if host or port changed. I think this are the two most important parts: procedure TGpHttpProxy.ProcessHeader(Client: TGpHttpProxyClient); var ahost: string; aport: string; header : string; returnContent: string; resetSocket : boolean; begin resetSocket := false; returnContent := ''; header := Client.Received; if SameText(FirstEl(header,' ',-1),'CONNECT') then begin // TCP Tunnel proxy request HttpData(Client).ProxyType := ptTCPTunnel; if not IPSec.IsAllowed(Client.PeerAddr) then returnContent := Response.sTCPTunnelIPForbidden.Text else if not (ptTCPTunnel in EnabledTypes) then returnContent := Response.sTCPTunnelClosed.Text else if not ProcessTCPTunnelHeader(Client,header,ahost,aport,returnContent) then returnContent := Response.sTCPTunnelBadRequest.Text; end else begin // HTTP proxy request HttpData(Client).ProxyType := ptHTTP; if not IPSec.IsAllowed(Client.PeerAddr) then returnContent := Response.sHTTPIPForbidden.Text else if not (ptHTTP in EnabledTypes) then returnContent := Response.sHTTPClosed.Text else if not ProcessHTTPHeader(Client,header,ahost,aport,returnContent,resetSocket) then returnContent := Response.sHTTPBadRequest.Text; end; //else SameText() // Header parsed, create remote socket. if returnContent = '' then begin if resetSocket then begin {$IFDEF LogHttpFlow} LogFlow(Client, 'Destroyed connection to %s:%s due to host/port change', [Client.RemoteHost, Client.RemoteSocket.Port]); {$ENDIF LogHttpFlow} Client.DestroyRemoteSocket; Client.NumRequests := 1; end; if not assigned(Client.RemoteSocket) then with Client do begin {$IFDEF LogHttpFlow} LogFlow(Client, 'Opening connection to %s:%s', [ahost, aport]); {$ENDIF LogHttpFlow} CreateRemoteSocket; RemoteHost:= ahost; RemoteSocket.Port := aport; RemoteSocket.LineMode := false; HookRemoteEvents(RemoteSocket); RemoteSocket.DnsLookup(ahost); DoRemoteSocketPrepared(Client); end //with/if else begin {$IFDEF LogHttpFlow} LogFlow(Client, 'Reusing connection to %s:%s', [Client.RemoteHost, Client.RemoteSocket.Port]); {$ENDIF LogHttpFlow} end; {$IFDEF LogHttpFlow} LogFlow(Client, 'Request: %s', [FirstEl(header, #13, -1)]); {$ENDIF LogHttpFlow} Client.Received := header; end else begin Client.DestroyRemoteSocket; Client.RemoteContent := returnContent; end; Client.GotHeader := true; end; { TGpHttpProxy.ProcessHeader } function TGpHttpProxy.ProcessHTTPHeader(Client: TGpHttpProxyClient; var header, ahost, aport, returnContent: string; var socketResetRequired: boolean): boolean; function MakeUrl(aproto, auser, apass, ahost, aport, apath: string): string; begin Result := aproto; if Last(Result,1) = ':' then Result := Result + '//' else if Last(Result,1) '/' then Result := Result + '://'; if auser '' then begin Result := Result + auser; if apass '' then Result := Result + ':' + apass; Result := Result + '@'; end; Result := Result + ahost; if (aport '') and (aport '80') then Result := Result + ':' + aport; Result := Result + apath; end; { MakeUrl } var apass : string; apath : string; aproto: string; auser : string; command : string; hdrHost : string; ignoreNextHopProxy: boolean; p1: integer; p2: integer; s : string; url : string; begin { TGpHttpProxy.ProcessHTTPHeader } Result := false; socketResetRequired := false; // extract url from GET/POST header s := header; p1 := Pos(' ',s); if p1 0 then begin command := First(s,p1-1); Delete(s,1,p1); s := TrimLeft(s); p2 := Pos(' ',s); if
Re: [twsocket] TWSocket Digest, Vol 287, Issue 11
Date: Sun, 21 Sep 2008 10:32:35 +0200 From: Francois PIETTE [EMAIL PROTECTED] Subject: Re: [twsocket] Updating to C++Buulder2009 To: ICS support mailing twsocket@elists.org Message-ID: [EMAIL PROTECTED] Content-Type: text/plain; format=flowed; charset=iso-8859-1; reply-type=original I am trying to get ICS to compile for C++Builder 2009. I am using the V7 Alpha as my base. Are your using it from SVN repository ? If not, please do it. The repository has newer files compared to C++Builder Partner DVD which has files working with latest fieldtest while you use RTM. I am now using the icsv7 branch from the SVN repository. I have built the project, using OverbyteIcsBcb120Package.cbproj, but had to remove OverbyteIcsPools.pas from the package. There where a few references to implicit casts from AnsiString to string and one implicit cast from string to AnsiString. It looks good so far , but I still need to get my own project converted before I can give it a try. John. -- To unsubscribe or change your settings for TWSocket mailing list please goto http://lists.elists.org/cgi-bin/mailman/listinfo/twsocket Visit our website at http://www.overbyte.be
Re: [twsocket] Early web server response
On Sep 21, 2008, at 18:53, Maurizio Lotauro wrote: HTTP is stateless, but this has nothing to do with keeping the connection open. I don't think that a browser reopen the connection for every part that compose a web page. And I don't think also that you close and reopen the connection for every file you want upload or download to/from an ftp server :-) I'm sorry but you are confused. HTTP is not like FTP. In HTTP 1.1, persistent connections were defined but it was a matter of convenience and they are not required (RFC #2616, Section 8 uses the term SHOULD instead of MUST when discussing the negotiation of persistent connections). As of HTTP 1.1, persistent connections are the default. But still, browsers do open multiple connections otherwise all retrieval would be synchronized, and it's not. They may not create a new connection for each resource, but the reuse of the connections is pretty much arbitrary. For the record, prior to 1.1, most servers did not support persistent connections, and browsers did in fact had to close and reopen the connection for every file they wanted to upload or download. Some servers supported the Keep-Alive mechanism, but--again--it was more of a convenience, and could never be expected to be supported by either side. This is why, in my opinion, coercing HTTP as the de facto standard protocol for all communications in the Internet (as a lot of people are trying to make it) is stupid. There are better transfer protocols out there. But this is a rant for another day. From what I understand now about NTLM (still need to learn about it!), it requires the cycle to happen within the same session, which counters the RFC, and thus is an exceptional case. The basic is the only one that is handled in one step. All others needs a negotiation. IIRC the NTLM is anomaly is that it is the server that starts it with the first 401 answer. Again, wrong. All HTTP authentication uses the same negotiation mechanism (even since the days of HTTP 1.0), because they authenticate the *request*: 1. The client requests a resource from the server for the very first time and it doesn't know it requires authentication. 2. The server responds with an appropriate error code specifying the authentication mechanism(s) supported (including Basic and Digest). (At this point, servers or clients using older versions of the HTTP protocol would have closed the connection.) 3. The client re-sends the request with the appropriate credentials and the server performs the authorization. 4. On every subsequent request, the client includes the same credentials and the server re-authenticates the request. (Digest has some differences, but generally fits this scheme). Notice that since the protocol is absolutely stateless, the server has no idea at any point how many requests have been sent, and it doesn't care. So, the client can remember the specific server's requirements and send them in subsequent visits. And in fact, this is what browsers do: from then on, the authentication can be done in a single request, without the error step. Now, NTLM (yes, finally I read some on it) authenticates the *connection*, not the request as the HTTP authentications mechanisms do. This requires that the entire challenge-response cycle be performed in a single persistent connection. As noted in that link you sent me, it's actually a bastardization of the protocol: it's not really part of the HTTP 1.1 protocol, but it uses the standard mechanisms in a weird way. Another way that NTLM breaks away from the protocol is that, once the connection is authenticated, subsequent requests within the same connection need not perform the challenge-response. Because of its unique nature (damn you, Microsoft!) I'm sure browsers treat it as a special case. (I seem to remember having problems with Firefox 1.x connecting to my office's intranet site, while IE worked fine. I always knew it had to be some MS extension to the protocol but didn't know what. Now I do.) Of course, IE will work fine with IIS. However, it'll be more interesting to find out how IE copes when dealing with Tomcat, which seems to return an error response right after the headers. In my case the server answers not after the headers but rigth after the client has sent the first 8193 byte of the SendStream (that is the size of the THttpCli send buffer). My guess is that, technically, it's after the headers that the server reacts, but the first stream buffer (8193 bytes) is already on its way, since the client didn't stop to check, so they cross in transit. It could also be that the HttpCli component does not acknowledge the response until after if finishes sending the buffer (which makes sense, since it's a single-threaded operation), and this causes the delay in the receipt of the response. In any case, I'll see if I can do some experiments with IE and Tomcat and let you
Re: [twsocket] Early web server response [OT]
DZ-Jay said... coercing HTTP as the de facto standard protocol for all communications in the Internet (as a lot of people are trying to make it) is stupid. There are better transfer protocols out there. Preach it! The Commodore 64 implemented better protocols... ;) But this is a rant for another day. I tend to make that rant about five times a day. But, who's counting? ... :) Go DZ! -- To unsubscribe or change your settings for TWSocket mailing list please goto http://lists.elists.org/cgi-bin/mailman/listinfo/twsocket Visit our website at http://www.overbyte.be
Re: [twsocket] Early web server response
Scrive DZ-Jay [EMAIL PROTECTED]: [...] I'll answer asap (probably this night). In any case, I'll see if I can do some experiments with IE and Tomcat and let you know what I find. Please wait, I asked to our server admin to prepare a test environment public available (I need it for myself). Probably it will be ready tomorrow. Bye, Maurizio. This mail has been sent using Alpikom webmail system http://www.alpikom.it -- To unsubscribe or change your settings for TWSocket mailing list please goto http://lists.elists.org/cgi-bin/mailman/listinfo/twsocket Visit our website at http://www.overbyte.be
Re: [twsocket] TSyncSmtpCli and hotmail
Is it possible to send outgoing mail through hotmail.com using TSyncSmtpCli? If hotmail support SMTP, then yes. Otherwise, no. -- [EMAIL PROTECTED] The author of the freeware multi-tier middleware MidWare The author of the freeware Internet Component Suite (ICS) http://www.overbyte.be -- To unsubscribe or change your settings for TWSocket mailing list please goto http://lists.elists.org/cgi-bin/mailman/listinfo/twsocket Visit our website at http://www.overbyte.be