I've made a simple SOCKS5 proxy RFC 1928 implementation using C sockets to communicate with my tor daemon running on localhost:9050. It compiles and works fine, but it is stuck blocking as it does not recv() anything.
The code is as follows:
#include <stdio.h>
#include <errno.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netdb.h>
#include <arpa/inet.h>
#include <netinet/in.h>
int main(int argc, char** argv) {
struct addrinfo hints, *res;
int sockfd;
memset(&hints,0,sizeof hints);
hints.ai_family = AF_UNSPEC;
hints.ai_socktype = SOCK_STREAM;
getaddrinfo("localhost","9050",&hints,&res);
sockfd = socket(res->ai_family,res->ai_socktype,res->ai_protocol);
int connected = connect(sockfd,res->ai_addr,res->ai_addrlen);
if (connected == -1) {
perror("Error");
}
char buffer[256];
char msginit[256];
msginit[0] = '\5'; //Protocol number
msginit[1] = '\2'; //# of authentication methods
msginit[2] = '\0'; //no authentication
msginit[3] = '\2'; //user+pass auth
//get dest
memset(&hints,0,sizeof hints);
memset(res,0,sizeof *res);
hints.ai_family = AF_UNSPEC;
hints.ai_socktype = SOCK_STREAM;
getaddrinfo("duckduckgo.com","80",&hints,&res);
struct sockaddr_in *ip = (struct sockaddr_in *)res->ai_addr;
uint32_t* addr=&(ip->sin_addr.s_addr);
//copy dest to request
memcpy (msginit+4,addr,sizeof (uint32_t));
send(sockfd, (void *)msginit, (size_t)strlen(msginit),0);
printf("Sent.\n");
recv(sockfd,buffer,256,0); //This is where it gets stuck!
printf("%s\n",buffer);
}
My response below is wrong. Looking more into it, there's a handshake process and more that needs to happen. I'll respond back in the next couple days with what I come up with. (this is something I'm working on for myself as well)
As it stands with your code, you will only be pulling the first 256 bytes from the response.
There are a couple of options, depending on how quickly you want your data. In the end, you will likely not see much, if any, difference. But you do have options.
1 - Place recv calls that immediately begin a loop that runs until you have the entire response. I would suggest this method if you need your data as quickly as possible. Be sure to have a sleep/usleep call in there, or you'll spin on CPU pretty hard.
It might look something like this:
2 - Use the MSG_WAITALL option, which will block on the receive call until it has received the entire message from the requested server, then pull all the data from the socket. This is how I do it for millions of socket requests a day.
Personally, in my code that runs quite fast (hundreds of millions of requests a day), I use the MSG_WAITALL option with a large enough buffer for my needs so that I don't loop my recv call. That may not work for you, but the benefit is that you don't have to think about extra cpu cycles in a loop. This is especially handy if you're doing a lot of requests or need to parse your data rather than just dumping the output.
If you can give me more details on how you're using this, I can put together more complete and tested code samples, and a more direct suggestion.