Question

I am trying to understand HTTP proxy server program. I wrote a simple C based socket which sends a response to as Message received. Please find the program below.

#include <stdio.h>   
#include <sys/socket.h> 
#include <netinet/in.h>    
#include <string.h>    
#include <sys/types.h>

int main(){
        int recvSocketFd = 0;
        struct sockaddr_in serv_input_addr;
        char inputBuff[1024];

        memset(&serv_input_addr,'0',sizeof(serv_input_addr));
        memset(&inputBuff, '0', sizeof(inputBuff));

        recvSocketFd = socket(AF_INET,SOCK_STREAM,0);

        if(recvSocketFd <= 0){
                printf("\nError occurred while creating a socket\n");
                return -1;
        }

        serv_input_addr.sin_family = AF_INET; 
        serv_input_addr.sin_addr.s_addr = htonl(INADDR_ANY);
        serv_input_addr.sin_port = htons(8080);
        bind(recvSocketFd, (struct sockaddr*)&serv_input_addr, sizeof(serv_input_addr));

        listen(recvSocketFd,5);

        int connFd = 0;
        int n = 0;
        int client_length = sizeof(serv_input_addr);

        while(1){
                connFd = accept(recvSocketFd, (struct sockaddr*)&serv_input_addr, &client_length);
                if(connFd <0){
                        printf("\nError in accepting messages from socket\n");
                        return -1;
                }

                n = read(connFd,inputBuff,1023);

                if(n>0){
                        printf("\nMessage : %s\n",inputBuff);   
                }
                write(connFd,"Message received",15);
                close(connFd);

        }
}

This program on running is responding properly for the below request http://<localhost>:8080/test.

I tried to set this as a proxy. So I tried to set this as manual proxy in Firefox as http://<localhost> and port as 8080.

But the request is not hitting this socket.

It would be really helpful if somebody could help me in understanding this.

Note: This is not a homework program and I am not a student. I am just trying to learn things. This statement is for our honorable disgraceful respondents.

Was it helpful?

Solution

Re-Edit:

Note the importance of checking success on bind(). There is various cases; where one could be that the socket is in a TIME_WAIT state. If one does not actually validate the bind() and abort on failure the program could possibly seemingly be running OK. listen() can be passed without error. Though on the client side Firefox most likely would report with a refused connection it is not a given.


URI-scheme-name

In your question you state that you have used http://<localhost> for proxy settings. If that is literal it will fail: You are not to include the scheme name in the proxy settings.

Note that Firefox does not validate the hostname. E.g. a4a6®←@ł´ªĸµª5d4a"#¤&%=)(=/)= fly by with no warnings.

Proxy foxy

If one include the scheme, http://, Firefox will fail to connect and one will get Server not found.


Original answer :-)

I'll leave it here even with comment on removed parts, as someone else might find it useful. (And that I used some time on writing it up.)


There are some issues here. I'll take them one by one.

First fix this, then report back if you want.

Missing header files and wrong types

read(), write() and close() are defined in <unistd.h>, but you do not include this file. It is presumably linked in, but best to add.

client_length is not signed int. You can use unsigned int, but best to use socklen_t as is defined in manual.

read() returns ssize_t, not int. Change this one as well.

Lack of error checking

No error checking where it should be. Rule #1: Always check for errors! Having trouble and not validating requests is … a big no no.

bind(), listen() and close() return int. 0 is success, -1 is error. On error errno is set.

The manual is very clear and easy to read on this. Read it for each function you use.

Include <errno.h> and use perror().

In simplest way. Aborting and no attempt to rescue we get:

int res;
...

res = bind(recvSocketFd, (struct sockaddr*)&serv_input_addr, sizeof(serv_input_addr));

if (res != 0) {
        perror("bind");
        return errno;
}

res = listen(recvSocketFd, 5);

if (res != 0) {
        perror("listen");
        return errno;
}

...

res = close(connFd);
if (res != 0) {
        perror("close");
        return errno;
}

write() returns ssize_t which on success is how many bytes was written, else -1 and errno set appropriately.

res_wr = write(connFd, ...);
if (res == -1) {
        perror("write");
        return errno;
}

/* Else check if entire buffer was written, if not, act accordingly. */

Write statement

Bad write statement:

write(connFd, "Message received", 15);

First: "Message received" is 17 bytes including terminating null. If you want to write this to connection use something like:

const char msg_received[] = "Message received";
...

write(connFd, msg_received, sizeof(msg_received));

Second: This is what you pass on to the client, in your case Firefox. Firefox would in other words get the characters:

{ 'M', 'e', 's', 's', 'a', 'g', 'e', ' ', 'r', 'e', 'c', 'e', 'i', 'v', 'e' }

Third: As you promptly do a close() after first read/write. Firefox will most likely reply with a The connection was reset. Normally you would write your inputBuff, and not some status message like this.

Print to stderr

As a side not: Whilst it is fair enough to write to stdout in this sample, it is a good habit to write errors and debugging data to stderr. Keep it as a habit. Example:

sz_buf = read(connFd, inputBuff, BUF_SIZE - 1)

inputBuff[sz_buf] = 0x00;

fprintf(stderr,
        "\n====================== Message (%4d) ================\n"
        "%s\n"
        "--------------------------------------------------------\n"
        ,
        sz_buf, inputBuff
);
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top