Hello everybody
I am developping web services and client test applications.
One of my client test is running on Windows with gsoap.
I tested my web services with this gsoap client in different configurations.
One of these configurations is to access the web services thru a reverse proxy
....which is pound !
A. SYMPTOMS
The client can not access the web services in this configuration.
In the log file :
"Aug 19 11:06:17 (none) pound[17826]: error read from 172.26.172.37:
Input/output error"
or
"Aug 19 11:06:17 (none) pound[17826]: error flush headers to 172.26.172.37:
Connection reset by peer"
B. ANALYZE
I tried to understand more precisely what happened
If the client is configured to use an HTTP persistent socket, OK
BUT, If the client is configured to not use an HTTP persistent socket, NOK
I used tcpdump to compare the difference between the 2 modes
(persistent/non-persistent).
In the case of the non persistent socket, the client sends:
HTTP : POST <the content>
TCP : bit FIN is set
In the case of the persistent socket, the client does not send the TCP FIN
packet (normal, it is persistent !)
Let's go deeper !
I used strace on pound with the non persistent socket
The following strace traces describes the 2nd case ("Connection reset by
peer")
And the result is (I suppressed some system calls ...)
poll([{fd=9, events=POLLIN|POLLPRI, revents=POLLIN}], 1, 10000) = 1
read(9, "POST /services/mgtsrv HTTP/1.1\r\n"..., 4096) = 925
...
socket(PF_INET, SOCK_STREAM, IPPROTO_IP) = 10
...
connect(10, {sin_family=AF_INET, sin_port=htons(56000),
...
poll([{fd=9, events=POLLOUT, revents=POLLOUT|POLLHUP}], 1, 10000) = 1
shutdown(10, 2 /* send and receive */) = 0
close(10) = 0
In this case, pound tries to send back the back-end reponse to the client
The last call to the poll system call is to flush the headers to the client
(call to function BIO_flush in the http.c file)
The poll function returns POLLOUT|POLLHUP, meaning: "writing now will not
block" and "Hung up" (see man poll(2))
The POLLHUP is due to the fact that the linux kernel received the TCP FIN bit.
In these condition, the BIO_flush returns != 1 => pound fails to send the
response to the client
C. WHO IS THE GUILTY ?
The GSOAP behaviour seems to be normal. The fact to send a FIN is appeared in
version GSOAP 2.6
When looking at the generated stubs, we have:
<code>
if (soap_valid_socket(soap->socket) && !soap->keep_alive)
shutdown((SOAP_SOCKET)soap->socket, 1); /* Send TCP FIN */
</code>
According to the TCP RFC, the bit FIN indicates that half on the connection is
closed (from sender to receiver)
I tried the same GSOAP client with the following configuration :
Client ----> Apache ----> Pound ---->Back-end
and it works !
I am not (at all) a specialist of the openssl library (which defines the
BIO_xxx functions), but it seems that this function is not correctly called
in Pound (maybe a BIO_xxx function with a finest behaviour has to be called)
D. CONCLUSION
The pound web site mentions that the tested clients are browsers .... but not
soap client
But is this limitation not too restrictive (due to the development of the WS)
on the WEB ?
Has anyone already encountered this problem and corrected it ?
Thanks
Gaëtan
[...]
|