Reputation: 1244
I'm trying to write a proxy server and right now I want to implement pipelining. I came across a problem though and need assistance. I checked this question but I think it doesn't apply since I do have data to read from the socket.
The main idea is the following. For each connection I create a thread that handles it and for each request in this connection I want to create a thread that handles that request. So far I have managed to write the code for the first part and it works properly (the thread also handles all the requests of the connection).
Now when I'm trying to read from the socket, from a request handling thread, it hangs. The function that I use to read data is the same as before (in the working version).
void copydata(int from, int to, int len)
{
char tbuff[BSIZ];
int n;
while (len > 0)
{
if ((n = read(from, tbuff, BSIZ)) <= 0) break;
if (write(to, tbuff, n) < n) break;
len -= n;
}
}
The from, to and len variables have appropriate values (I checked them). Is there anything that can cause such behaviour?
PS: If more code is required for something please let me know.
EDIT
Here is how the len is acquired:
int contentlength(char *header)
{
int len = INT_MAX;
char line[MAX_LINE];
if (HTTPheadervalue_case(header, "Content-Length", line)) sscanf(line, "%d", &len);
return len;
}
Calling copydata (where activesocket is a function that opens the socket):
if ((srv = activesocket(host, portno)) < 0)
{
sprintf(reshead, "HTTP/1.1 503\r\nContent-Length: 12\r\nConnection: close\r\n\r\nNon-existent");
write(cli, reshead, strlen(reshead));
} else
{
sprintf(reqhead1, "%s %s HTTP/1.1\r\n", "GET", path);
if (HTTPheadervalue_case(reqhead1, "Connection", result)) if (strcasecmp(result, "close") == 0) cli_terminate[cli] = TRUE;
strcat(reqhead1, reqhead);
write(srv, reqhead1, strlen(reqhead1));
while (completed[cli] != id)
;
copydata(cli, srv, contentlength(reqhead));
parseResponse(&srv, cli);
completed[cli] = (completed[cli] + 1) % ULONG_MAX;
}
EDIT
One example request header is the following:
Host: www.google.com
User-Agent: Mozilla/5.0 (X11; U; Linux i686; en-GB; rv:1.9.1.16) Gecko/20120421 Iceweasel/3.5.16 (like Firefox/3.5.16)
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: en-gb,en;q=0.5
Accept-Encoding: gzip,deflate
Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7
Keep-Alive: 300
Proxy-Connection: keep-alive
Cookie: cookie content
I tried to also strip the keep-alive flag but still the same happens.
Upvotes: 1
Views: 1743
Reputation: 84151
I am guessing this is your problem (from accept(2)
):
On Linux, the new socket returned byaccept()
does not inherit file status flags such asO_NONBLOCK
andO_ASYNC
from the listening socket.
I.e. you need to explicitly make every new accepted socket non-blocking.
Upvotes: 2