What is a proper HTTP status code that server returns when it limits total number of connections? - c

I have made a simple HTTP server that listens to socket connections. The server code limits total number of connections that it can hold simultaneously.
So, I have these lines:
do {
new_fd = accept(lfd, NULL, NULL);
nfds += 1;
...
if(nfds + 1 > ntotal){ // connection limit exceeded
set_headers( new_fd, /* HTTP status code here */ );
/* close socket after error had been sent */
}
}while(1);
In this situation I'm interested with HTTP status code that server should send before closing socket.

From this link, it appears 503 is the appropriate HTTP status code to send for an overloaded server.
10.5.4 503 Service Unavailable
The server is currently unable to handle the request due to a
temporary overloading or maintenance of the server. The implication is
that this is a temporary condition which will be alleviated after some
delay. If known, the length of the delay MAY be indicated in a
Retry-After header. If no Retry-After is given, the client SHOULD
handle the response as it would for a 500 response.
Note: The existence of the 503 status code does not imply that a
server must use it when becoming overloaded. Some servers may wish
to simply refuse the connection.
(bold emphasis mine)

Related

HTTP response message generated by server is not being recognized as a response

I'm programming a simple web server in C. The HTTP message the server generates is stored in a buffer and sent (via send()) as follows:
Scenario 1:
"200 OK\nContent-Type: text/html\nContent-Length: " + resource size in bytes + "\r\n\n"
where the resource size in bytes is converted to a char array using snprintf and then concatenated into the string.
Scenario 2:
"HTTP1.1 404 Not Found\r\nContent-Length: 0\r\n\n"
Scenario 3:
"HTTP1.1 405 Method Not Allowed\r\nAllow: GET, HEAD\r\n"
These are the headers, they are sent beforehand. The message body is sent afterwards as follows:
char resource[length];
int numRead;
while ( (numRead= read(filefd, resource, length)) > 0 )
send(client, resource, length, 0);
When I use wireshark, it doesn't recognize it as an HTTP response. When I use firefox, the web page continues loading until I shut down the server, at which point it displays the HTTP response instead of a webpage (index.html):
image
Do I have to encode the message before sending? Or is there something wrong with my message format?
There are many errors here which suggest that you just made up your own version of HTTP instead of reading the standard. Please refer to the standard for all the details if you want to implement HTTP.
In short:
"200 OK\nContent-Type: text/html\nContent-Length: " + resource size in bytes + "\r\n\n"
It should be HTTP/1.1 200 OK... and not just 200 OK.... All line ends must be \r\n and not \n and there must be a single \r\n at the end of the HTTP header.
"HTTP1.1 404 Not Found\r\nContent-Length: 0\r\n\n"
"HTTP1.1 405 Method Not Allowed\r\nAllow: GET, HEAD\r\n"
It should be HTTP/1.1 not HTTP1.1. And then all the other problems.
Again, if you really want to implement your own HTTP stack then study the standard. It is far more complex than you might think. Just because HTTP is a text based protocol does not mean that it is simple nor that any text is a correct HTTP message. Additionally implementations are tolerant in different ways, so just because it works with one client (i.e. browser) does not mean it is correct and that it will work with a different client too.

Kong: Client Closing keep-alive connections

I am writing a custom plugin for kong. The plugin will transform request/response in accordance with my server. I am getting [info] 27#0: *588 client <x> closed keepalive connection.
After some debugging, I found that the error occurs whenever I set the
ngx.arg[1] with my transformed response. I have followed the existing response-transformer plugin provided by kong.
This is the body of the kong body_filter function:
local ctx = ngx.ctx
local chunk, eof = ngx.arg[1], ngx.arg[2]
ctx.rt_body_chunks = ctx.rt_body_chunks or {}
ctx.rt_body_chunk_number = ctx.rt_body_chunk_number or 1
if eof then
local someChunks = concat(ctx.rt_body_chunks)
local aBody = responseTransformer.transform(theConf, someChunks)
aBody = unEscapeString(aBody)
ngx.arg[1] = aBody or someChunks
else
ctx.rt_body_chunks[ctx.rt_body_chunk_number] = chunk
ctx.rt_body_chunk_number = ctx.rt_body_chunk_number + 1
ngx.arg[1] = nil
end
I ran the same plugin with a local dummy server. It worked properly. But when I proxied to my actual server, I got the closed keepalive connection error.
From kong logs, I can see that the response got transformed properly.
Using curl, I get about half the body of the response.
Found the cause. The server was sending Content-Length header. During rewrite of body this remained unchanged. So, connection was being closed before the full content was being delivered.
To solve this, I had to clear the Content-Length header in the header_filter function:
kong.response.clear_header("Content-Length")

Windows RPC access denied even with RPC_C_AUTHN_NONE

I have this error while trying to connect my RPC client to my RPC server:
Error occurred:5
Some googling showed me the meaning of this error: access denied.
The trouble does not come from the firewall.
Here is the server part, where I specify RPC_C_AUTHN_NONE to let everyone connect:
RPC_STATUS status;
printf("RPC Server Starting...\n");
status = RpcServerUseProtseqEp(
(unsigned char *)"ncacn_ip_tcp",
RPC_C_PROTSEQ_MAX_REQS_DEFAULT,
(unsigned char *)"9191",
RPC_C_AUTHN_NONE);
if (status) { printf("Error:%d\n", status); exit(status); }
printf("RPC Server Configured\n");
Here is the client part raising the error:
RpcTryExcept {
unsigned char szMsg[] = "Client: I can RPC now!\n";
md5(szMsg);
} RpcExcept(1) {
printf("Error occurred:%d\n", RpcExceptionCode());
}
RpcEndExcept
How do I correct this issue, in order to let any RPC client connects?
And in the same order, do you know a good RPC documentation for Windows RPC authentication?
Many thanks!
I have spent some time figuring why this happened, and I provide this answer as I found a solution, in order to help those who might encounter this trouble:
By default, RPC connection are only granted to authenticated clients. This can be changed by editing a registry entry or applying a GPO to disable restrictions for unauthenticated users as specified here.

C HTTP Proxy, the browser shows "waiting for" indefinetely

I have a hard time implementing a proxy server in C. It works for a few first webpages but then I get blocked while waiting for a new request.
Design:
Firefox -> Proxy -> Webserver --.
Firefox <- Proxy <- Webserver <-'
So each request is a round-trip from the browser to the proxy and the server and then back. Until the response from the request comes back, nothing should happen. I use no pipelining, threads or anything like that but rather only recv() and send() in a linear serial manner (for simplicity and intuition). I also don't close any sockets as I want to have a persistent connection.
I expect to be able and fetch one whole webpage including subrequested resources like css, img, js, etc..
In my implementation I manage to fetch a few first requests for a webpage. Then it hangs at step 1.
Implementation:
puts("Waiting for user to connect..");
int sock_user = accept(sock, (struct sockaddr*)NULL, NULL);
int sock_host = -1;
printf("User connected.\n");
// Accept requests
while(1){
http_request req;
http_response resp;
// 1. Client ==> Proxy Server
http_parse_request(sock_user, &req); // uses recv()
// 2. Client Proxy ==> Server
if (sock_host < 0)
sock_host = proxy_connect_host(req.header->host);
write(sock_host, req.header->raw_data, req.header->raw_size);
// 3. Client Proxy <== Server
http_parse_response(sock_host, &resp); // uses recv()
// 4. Client <== Proxy Server
write(sock_user, resp.header->raw_data, resp.header->raw_size);
write(sock_user, resp.body ->first_block->data, resp.body ->first_block->size);
}
Log:
---- ......................................... ----
---- after succesfully responded to 4 requests ----
Client ==> Proxy Server
Received 389
Client Proxy ==> Server
Sending.. 389
Sent 389
Client Proxy <== Server
Got header 312
Got body 1437
Response total 1749
Client <== Proxy Server
Sending header.. 312
Sent 312
Sending body.. 1437
Sent 1437
Client ==> Proxy Server
---- Hangs/blocks here ----
Firebug:
Wireshark:
I have no intuition as to what the reason for that block is and I have spent a whole week trying to resolve this problem without a breakthrough.
Among things tried to resolve problem:
Sending some extra CRLF for each response body
Checked the return value from each recv() and send(). (in the log above,
the values getting printed are the return values from recv and
send)
I hope someone could give at least some direction as to how to troubleshoot this or my brain will soon explode :)
You have to be very careful not to read too much data. E.g. make sure that:
header is read only up to the double CRLF; store extra data and sent them with the body
sending of body starts not before the server has sent the complete header (does not apply to this GET case but is important for POST or CONNECT)
there are received and sent only Content-Length bytes from the body
This applies to both the client -> proxy request and the server -> proxy response.
Your sample code stays in an endless loop (while (1) ...). How do you abort this? Do you honor the "Proxy-Connection" header?

JGroups, TCP_NIO multiple messages sent to nowhere

Messages sent to ports I never specified in my configuration file.
this is my config:
[10-Jan-2011 11:02:22.917 GMT] ERROR org.jgroups.protocols.TCP_NIO - failed sending message to 192.168.50.41:8851 (116 bytes): java.lang.Exception: connection to 192.168.50.41:8851 could not be established
[10-Jan-2011 11:02:22.917 GMT] WARN org.jgroups.blocks.ConnectionTableNIO - Connection is not running, discarding message
Because you have a port_range of 2, so every discovery message is sent to all of the initial_hosts defined in TCPPING, plus port_range, e.g.
TCPPING.initial_hosts=A[1000],B[1000]
port_range=2
will send discovery requests to A:1000-1002, B:1000-1002.
TCPPING is used at startup for initial discovery and by MERGE2 (not in your stack)...

Resources