C linux proxy server - c++

I'm trying to build a client -> proxy server -> server application.
I need help with the proxy server, how do i make it send data to the server right now it can only communicate with the client.
Here is my codef or the proxy server, I modified it from an example. I'm new at this.
int main(int argc, char *argv[])
{
int sockfd, newsockfd, portno, pid;
socklen_t clilen;
struct sockaddr_in serv_addr, cli_addr;
if (argc < 2) {
fprintf(stderr,"ERROR, no port provided\n");
exit(1);
}
sockfd = socket(AF_INET, SOCK_STREAM, 0);
if (sockfd < 0)
error("ERROR opening socket");
bzero((char *) &serv_addr, sizeof(serv_addr));
portno = atoi(argv[1]);
serv_addr.sin_family = AF_INET;
serv_addr.sin_addr.s_addr = INADDR_ANY;
serv_addr.sin_port = htons(portno);
if (bind(sockfd, (struct sockaddr *) &serv_addr,
sizeof(serv_addr)) < 0)
error("ERROR on binding");
listen(sockfd,5);
clilen = sizeof(cli_addr);
while (1) {
newsockfd = accept(sockfd,
(struct sockaddr *) &cli_addr, &clilen);
if (newsockfd < 0)
error("ERROR on accept");
pid = fork();
if (pid < 0)
error("ERROR on fork");
if (pid == 0) {
close(sockfd);
dostuff(newsockfd);
exit(0);
}
else close(newsockfd);
} /* end of while */
close(sockfd);
return 0; /* we never get here */
}
/******** DOSTUFF() *********************
There is a separate instance of this function
for each connection. It handles all communication
once a connnection has been established.
*****************************************/
void dostuff (int sock)
{
int n, p;
char buffer[256];
char request;
FILE *file;
file = fopen("process.log","a+");
do
{
//here the proxy server receives data from the client
bzero(buffer,256);
p = read(sock,buffer,255);
if (n < 0) error("ERROR reading from socket");
printf("num: %s\n",buffer);
//here the proxy servers replies to the client.
n = write(sock,buffer,sizeof(buffer));
//here the process should send data to the server
//...codes i need help with...
if (n < 0) error("ERROR writing to socket");
fprintf(file,"%s\n",buffer); /*writes*/
}while(p != 0); //this runs the process +1 more than it should. wonder why?
fclose(file);
}
DoStuff() .... you can also check the comments I added.
Also how do I send a message to the client as soon as the client is connected to the server, something like a welcome client message? :)
note: the proxy server sends a GET request to a HTTP 1.1 server.
I would really appreciate it. Thanks :)

To connect to the server, you're going to have to call socket and then connect to get that socket connected to your real server from the proxy. See section 5 here:
http://beej.us/guide/bgnet/output/html/singlepage/bgnet.html
Additionally, check p instead of n 4 lines into your do-while loop in DoStuff().

Related

ERROR on accept: Bad file descriptor

EDIT: Minimal, Complete, and Verifiable example is in comment lower and the code actually works, problem was in different area. Sorry for bad posting, I cannot delete it now.
I know, that there are some pages about this already, but I really tried everything and nothing works. Im having this error all the time and my code looks like this:
int server_socket, new_socket;
struct sockaddr_in server;
bzero((char *) &server, sizeof(server));
server_socket = socket(AF_INET, SOCK_STREAM | SOCK_NONBLOCK, 0);
if(server_socket < 0) error("ERROR opening socket");
server.sin_family = AF_INET;
server.sin_addr.s_addr = htonl(INADDR_ANY);
server.sin_port = htons(port_number);
if(bind(server_socket, (struct sockaddr *) &server, sizeof(struct sockaddr_in)) < 0) error("ERROR on binding");
if(listen(server_socket, 5) < 0) error("Failed to listen for connections.");
while(1)
{
struct sockaddr_in client;
unsigned int client_len = sizeof(struct sockaddr_in);
bzero((char *) &client, client_len);
if((new_socket = accept(server_socket, (struct sockaddr *) &client, &client_len)) < 0)
{
if(errno == EAGAIN) continue;
else error("ERROR on accept");
}
if((pid = fork()) > 0)
{ // this is parent process
close(new_socket);
}
else if(pid == 0)
{ // this is a child process that will handle an incoming request
long_pid = (long) getpid(); // current child's PID
close(server_socket);
server_socket = -1; //closing parent socket
printf("A new connection accepted from blablabla, port %d by process %ld\n", port_number, long_pid);
// ---- doing some staff, running the program
EDIT: while((msg_size = read(new_socket, received_data, BUFFER_SIZE)) >0)
// ---- when Im done:
printf("closing newsock\n");
close(new_socket); // close the new socket
new_socket = -1;
exit(0);
}
}
else error("fork() failed");
}
// close the server
printf("closing an original socket\n");
close(server_socket); // close an original server socket
return 0;
}
I didnt have this problem before, when I was using nonblocking sockets. So problem is probably connected to them.
If I fill in the blanks to make this into a compilable example (please post an mcve next time)
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <stdlib.h>
#include <stdio.h>
#include <strings.h>
#include <errno.h>
#include <arpa/inet.h>
#define port_number 2222
void error(char const *Msg)
{
perror(Msg);
exit(1);
}
int main()
{
pid_t pid; long long_pid;
int server_socket, new_socket;
struct sockaddr_in server;
bzero((char *) &server, sizeof(server));
server_socket = socket(AF_INET, SOCK_STREAM | SOCK_NONBLOCK, 0);
if(server_socket < 0) error("ERROR opening socket");
server.sin_family = AF_INET;
server.sin_addr.s_addr = htonl(INADDR_ANY);
server.sin_port = htons(port_number);
if(bind(server_socket, (struct sockaddr *) &server, sizeof(struct sockaddr_in)) < 0) error("ERROR on binding");
if(listen(server_socket, 5) < 0) error("Failed to listen for connections.");
while(1)
{
struct sockaddr_in client;
unsigned int client_len = sizeof(struct sockaddr_in);
bzero((char *) &client, client_len);
if((new_socket = accept(server_socket, (struct sockaddr *) &client, &client_len)) < 0)
{
if(errno == EAGAIN) continue;
else error("ERROR on accept");
}
if((pid = fork()) > 0)
{ // this is parent process
close(new_socket);
}
else if(pid == 0)
{ // this is a child process that will handle an incoming request
long_pid = (long) getpid(); // current child's PID
close(server_socket);
server_socket = -1; //closing parent socket
printf("A new connection accepted from blablabla, port %d by process %ld\n", port_number, long_pid);
// ---- doing some staff, running the program
// ---- when Im done:
printf("closing newsock\n");
close(new_socket); // close the new socket
new_socket = -1;
_exit(0);
}
else error("fork() failed");
}
// close the server
printf("closing an original socket\n");
close(server_socket); // close an original server socket
return 0;
}
it seems to work without any issues.
Obviously you're establishing the listening socket with error checks in the parent process and the parent process then isn't doing anything with the listening socket that closes it, so you shouldn't be getting that error from the parent process.
My guess is you're probably mistakenly continuing the loop in the child (in the part you're not showing).

Looping TCP Communication C++

I have a C++ application which receives 1 char and runs a function dependent on which char it has received. The problem is that the application stops as soon as it has received one message.
I need the application to start listening on the same port again after it has received a message but I haven't managed to do so. I tried looping it with a "while (true)" loop but I get errors.
It may also be worth noting that after the server has ran successfully it gives the message:
** * stack smashing detected ***: terminated
Aborted (core dumped)
And if I try to run the server again on the same port after it has successfully completed I get:
ERROR on binding: Address already in use
Significant code:
int main(int argc, char *argv[]) {
int sockfd, newsockfd, portno;
socklen_t clilen;
char buffer[1];
struct sockaddr_in serv_addr, cli_addr;
int n;
if (argc < 2) {
fprintf(stderr,"ERROR, no port provided\n");
exit(1);
}
sockfd = socket(AF_INET, SOCK_STREAM, 0);
if (sockfd < 0)
error("ERROR opening socket");
bzero((char *) &serv_addr, sizeof(serv_addr));
portno = atoi(argv[1]);
serv_addr.sin_family = AF_INET;
serv_addr.sin_addr.s_addr = INADDR_ANY;
serv_addr.sin_port = htons(portno);
if (bind(sockfd, (struct sockaddr *) &serv_addr,
sizeof(serv_addr)) < 0)
error("ERROR on binding");
listen(sockfd,5);
clilen = sizeof(cli_addr);
newsockfd = accept(sockfd,
(struct sockaddr *) &cli_addr,
&clilen);
if (newsockfd < 0)
error("ERROR on accept");
bzero(buffer,256);
n = read(newsockfd,buffer,255);
if (n < 0) error("ERROR reading from socket");
if (buffer[0] == '0') {
lamp();
}
else {
printf("No valid input from client.\n");
}
if (n < 0) error("ERROR writing to socket");
close(newsockfd);
close(sockfd);
return 0;
}
EDIT: I should've mentioned that I am very new to C++. Please give an example with your solution.
char buffer[1]; ... bzero(buffer,256);
Of course, after you've corrupted the whole stack it's understandable that other reasonable code is suddenly failing.

Simple UDP socket code, sending and receiving messages

I am just learning UDP sockets and this is my first code involving it. I have two programs which send and receive messages back and forth. My question is it seems I have to declare which IP address I am sending/receiving from multiple times throughout the code as it changes but I feel there is a better way to do this without changing the inet_addr manually within the codes. From my reading it looks like sendto and recvfrom may be able to help but I am unsure how to use them in this context. If anyone could show me how to fix my simple problem I would greatly appreciate it! Thanks
CODE 1: Send then Receive
int main(int argc, char *argv[])
{
//initialize socket and structure
int socket_info;
struct sockaddr_in server;
char message[100];
char incoming_message[100];
printf("Input Message: ");
fgets(message, 100, stdin);
//create socket
socket_info = socket(AF_INET, SOCK_DGRAM, 0);
if (socket_info == -1) {
printf("Could not create socket");
}
//assign local values
server.sin_addr.s_addr = inet_addr("172.21.8.178");
server.sin_family = AF_INET;
server.sin_port = htons( 1100 );
//binds connection
if (bind(socket_info, (struct sockaddr *)&server, sizeof(server)) < 0) {
perror("Connection error");
return 1;
}
puts("Bind");
//assign new value to connect to
server.sin_addr.s_addr = inet_addr("172.21.8.179");
//checks connection
if (connect(socket_info, (struct sockaddr *)&server, sizeof(server)) < 0) {
perror("Connection error");
return 1;
}
puts("Connected");
//sends message
if(send(socket_info, message, strlen(message), 0) <0) {
perror("Send failed");
return 1;
}
puts("Message Sent");
//receives message back
if(recv(socket_info, incoming_message, sizeof(incoming_message), 0) <0) {
puts("Received failed");
return 1;
}
puts("Message received");
puts(incoming_message);
close(socket_info);
}
CODE 2: Receive then Send
int main(int argc, char *argv[])
{
//initialize socket and structure
int socket_info;
struct sockaddr_in server;
char incoming_message[100];
//create socket
socket_info = socket(AF_INET, SOCK_DGRAM, 0);
if (socket_info == -1) {
printf("Could not create socket");
}
//assign values
server.sin_addr.s_addr = inet_addr("172.21.8.179");
server.sin_family = AF_INET;
server.sin_port = htons( 1100 );
//checks connection
if (bind(socket_info, (struct sockaddr *)&server, sizeof(server)) < 0) {
perror("Connection error");
return 1;
}
puts("Bind");
//Receive an incoming message
if( recv(socket_info, incoming_message, sizeof(incoming_message), 0) < 0) {
puts("Received failed");
return 1;
}
puts("Message received");
puts(incoming_message);
server.sin_addr.s_addr = inet_addr("172.21.8.178");
if (connect(socket_info, (struct sockaddr *)&server, sizeof(server)) < 0) {
perror("Connection error");
return 1;
}
puts("Connected");
//Sends message back
char message[100];
printf("Input Message: ");
fgets(message, 100, stdin);
if(send(socket_info, message, strlen(message), 0) <0) {
perror("Send failed");
return 1;
}
puts("Message Sent");
close(socket_info);
}
If you use the function recvfrom()
ssize_t recvfrom(int sockfd, void *buf, size_t len, int flags,
struct sockaddr *src_addr, socklen_t *addrlen);
What this function does is it fills a structure of sockaddr with the IP and port information of the packet that it has just received. For example, if your code that sends first then receives sends a packet to the receiver, the receiver should be able to fill the structure values of sin_addr and sin_port with the correct values. You can then make a call of sendto() with this information in order to send it to the correct machine.
Here's the man pages for these functions:
https://linux.die.net/man/2/recvfrom
https://linux.die.net/man/2/sendto
Try using this:
inet_pton(AF_INET, "127.0.0.1", &serv_addr.sin_addr)
127.0.0.1 is the loopback IP. The address is used to establish an IP connection to the same machine, which seems to be your case.
A detailed way to solve the problem can be found here

Program not entering while loop with only condition being 1

Hi I am writing a simple web server in C that will just handle simple get and post requests sent from a browser. I am not that familiar with C so debugging has been painful but I have gotten it to compile but continually I am getting a err_connection_reset response from my browser when trying to view webpage. I have narrowed it down to not entering the main loop that used to listen on the open socket but it will not enter it, here is my main function
int main(int argc, char *argv[])
{
printf("in main");
int portno; // port number passed as parameter
portno = atoi(argv[1]); // convert port num to integer
if (portno < 24)
{
portno = portno + 2000;
}
else if ((portno > 24) && (portno < 1024))
{
portno = portno + 1000;
}
else
{
;
}
// Signal SigCatcher to eliminate zombies
// a zombie is a thread that has ended but must
// be terminated to remove it
signal(SIGCHLD, SigCatcher);
int sockfd; // socket for binding
int newsockfd; // socket for this connection
int clilen; // size of client address
int pid; // PID of created thread
// socket structures used in socket creation
struct sockaddr_in serv_addr, cli_addr;
// Create a socket for the connection
sockfd = socket(AF_INET, SOCK_STREAM, 0);
if (sockfd < 0)
{
error("ERROR opening socket\n");
}
// bzero zeroes buffers, zero the server address buffer
bzero((char *)&serv_addr, sizeof(serv_addr));
// set up the server address
serv_addr.sin_family = AF_INET;
serv_addr.sin_addr.s_addr = INADDR_ANY;
serv_addr.sin_port = htons(portno);
// bind to the socket
if (bind(sockfd, (struct sockaddr *)&serv_addr, sizeof(serv_addr)) < 0)
error("ERROR on binding. Did you forget to kill the last server?\n");
listen(sockfd, 5); // Listen on socket
clilen = sizeof(cli_addr); // size of client address
while (1)
{ // loop forever listening on socket
newsockfd = accept(sockfd, (struct sockaddr *)&cli_addr, (socklen_t *) & clilen);
if (newsockfd < 0)
error("ERROR on accept");
// Server waits on accept waiting for client request
// When request received fork a new thread to handle it
pid = fork();
if (pid < 0)
error("ERROR on fork\n");
if (pid == 0)
{ // request received
close(sockfd);
// Create thread and socket to handle
httpthread(newsockfd, cli_addr);
exit(0);
}
else
close(newsockfd);
} /* end of while */
return 0; /* we never get here */
}
The loop executes exactly once, and then the program terminates because you call exit(0) in the parent process. When you call exit, the entire process dies, including active threads. This includes the thread that is created by calling httpthread(newsockfd, cli_addr).
Besides, the child process is closing the socket. Check that you really want to do this, and do not terminate the program inside the parent process.

Having issues with chat program over TCP using C++ on Ubuntu 12.10

I'm developing a chat program over TCP to allow me to communicate between two machines over WAN. I'm pretty new to C++ (coming from Java) and am very new to TCP, so don't go too hard on me! (: I've looked around on a fair amount of tutorials and continue to find only Echo programs, nothing that can leave a connection open for an extended amount of time to allow a chat like function. My current code looks like this:
#include "ClientManager.h"
ClientManager::ClientManager() {
}
void ClientManager::connectCom(char* ipAdd) {
portno = atoi(PORT);
sockfd = socket(AF_INET, SOCK_STREAM, 0);
if (sockfd < 0)
error("ERROR opening socket");
server = gethostbyname(ipAdd);
if (server == NULL) {
fprintf(stderr,"ERROR, no such host\n");
exit(0);
}
bzero((char *) &serv_addr, sizeof(serv_addr));
serv_addr.sin_family = AF_INET;
bcopy((char *)server->h_addr,
(char *)&serv_addr.sin_addr.s_addr,
server->h_length);
serv_addr.sin_port = htons(portno);
if (connect(sockfd,(struct sockaddr *) &serv_addr,sizeof(serv_addr)) < 0)
error("ERROR connecting");
}
void ClientManager::message(std::string msg) {
// printf("Please enter the message: ");
char * buffer = new char[msg.size() + 1];
std::copy(msg.begin(), msg.end(), buffer);
buffer[msg.size()] = '\0';
// bzero(buffer,256);
// fgets(buffer,255,stdin);
n = write(sockfd,buffer,strlen(buffer));
if (n < 0)
error("ERROR writing to socket");
bzero(buffer,256);
n = read(sockfd,buffer,255);
if (n < 0)
error("ERROR reading from socket");
printf("%s\n",buffer);
bzero(buffer,256);
}
void ClientManager::closeCom() {
close(sockfd);
}
void ClientManager::error(const char *msg)
{
perror(msg);
exit(0);
}
and my server manager looks like this:
#include "ServerManager.h"
ServerManager::ServerManager() {
// int sockfd, portno, n;
// struct sockaddr_in serv_addr;
// struct hostent *server;
}
void ServerManager::openCom() {
char buffer[256];
struct sockaddr_in serv_addr, cli_addr;
int n;
socklen_t clilen;
sockfd = socket(AF_INET, SOCK_STREAM, 0);
if (sockfd < 0)
error("ERROR opening socket");
bzero((char *) &serv_addr, sizeof(serv_addr));
portno = atoi(PORT);
serv_addr.sin_family = AF_INET;
serv_addr.sin_addr.s_addr = INADDR_ANY;
serv_addr.sin_port = htons(portno);
if (bind(sockfd, (struct sockaddr *) &serv_addr,
sizeof(serv_addr)) < 0)
error("ERROR on binding");
listen(sockfd,5);
clilen = sizeof(cli_addr);
newsockfd = accept(sockfd,
(struct sockaddr *) &cli_addr,
&clilen);
if (newsockfd < 0)
error("ERROR on accept");
bzero(buffer,256);
// n = read(newsockfd,buffer,255);
// if (n < 0) error("ERROR reading from socket");
// printf("Here is the message: %s\n",buffer);
// n = write(newsockfd,"I got your message",18);
// if (n < 0) error("ERROR writing to socket");
}
int ServerManager::readCom() {
bzero(buffer,256);
n = read(newsockfd,buffer,255);
if (n < 0) error("ERROR reading from socket");
printf("Here is the message: %s\n",buffer);
n = write(newsockfd,"I got your message",18);
if (n < 0) error("ERROR writing to socket");
if (buffer[0] == '0')
return 1;
return 0;
}
void ServerManager::closeCom() {
close(newsockfd);
close(sockfd);
}
void ServerManager::error(const char *msg) {
perror(msg);
exit(1);
}
Both of these classes are implemented by separate main functions who call the functions necessary. I know that the code itself is ok for sending a single message- its been doing that for awhile now. Its just when client calls more than one message() that I experience errors, specifically, a segmentation fault. This only happens on the second message, the first one is sent and received appropriately.
If anyone could help me out, it would be greatly appreciated. Thanks!
In ClientManager::message you forget to delete the buffer at the end of the method.
ALternatively, you should declare the buffer on the local stack as this:
char buffer[msg.size() + 1];
As such, the buffer will be automatically deallocated by the end of the call.
And reading later code, you better do:
char buffer[256];
I think the code for reading the server's reply causes buffer overrun if your msg.size() < serverReply.size, even if you think you have 256 characters (you simply didn't allocated them at method start) . Please take care to this buffer length declaration and later handling, as C++ would let you write beyond it's end, corrupting neighbouring variables and leading to segfaults.