Compare commits

..

No commits in common. "e608a333e66c5d4d815a7045d759530306a0aa4b" and "19aed223d05b0cdcf20f32cab0403fb7461c3d33" have entirely different histories.

5 changed files with 185 additions and 270 deletions

View File

@ -1,10 +1,8 @@
add_executable(proxy
./proxy.cpp
./network.cpp
)
add_executable(web_server add_executable(web_server
./web_server.cpp ./web_server.cpp
./network.cpp )
add_executable(proxy
./proxy.cpp
) )

View File

@ -1,149 +0,0 @@
#include "network.hpp"
#include <arpa/inet.h>
#include <fcntl.h>
#include <stdlib.h> // Needed for exit()
#include <cstring>
#include <iostream>
void TestSockets(int sender_s, int receiver_s) {
char in_buf[BUF_SIZE]; // Input buffer for GET resquest
char out_buf[BUF_SIZE]; // Output buffer for HTML response
ssize_t buf_len; // Buffer length for file reads
//
// Pass GET along from browser to server
std::cout << "Attempting to send data to receiver" << std::endl;
do {
buf_len = recv(sender_s, in_buf, BUF_SIZE, 0);
std::cout << "LOG (info) - pipe packet recv size: " << buf_len << std::endl;
if (buf_len == -1) {
std::cout << "ERROR (info) - recv" << std::endl;
return;
}
if (buf_len == 0) { break; }
buf_len = send(receiver_s, in_buf, buf_len, 0);
std::cout << "LOG (info) - pipe packet send size: " << buf_len << std::endl;
} while (buf_len == BUF_SIZE);
std::cout << "Sent data to receiver" << std::endl;
// Pass response along from server to browser
std::cout << "Attempting to send to browser" << std::endl;
do {
buf_len = recv(sender_s, out_buf, BUF_SIZE, 0);
std::cout << "LOG (info) - proxy packet recv size: " << buf_len << std::endl;
if (buf_len == -1) {
std::cout << "ERROR (info) - recv" << std::endl;
return;
}
if (buf_len == 0) { break; }
buf_len = send(receiver_s, out_buf, buf_len, 0);
std::cout << "LOG (info) - proxy packet send size: " << buf_len << std::endl;
} while (buf_len == BUF_SIZE);
std::cout << "Sent to browser" << std::endl;
close(sender_s);
close(receiver_s);
}
void PipeSockets(int sender_s, int receiver_s) {
char in_buf[BUF_SIZE]; // Input buffer for GET resquest
ssize_t buf_len; // Buffer length for file reads
// Pass GET along from browser to server
std::cout << "Attempting to send data to receiver" << std::endl;
do {
// Receive
buf_len = recv(sender_s, in_buf, BUF_SIZE, 0);
std::cout << "LOG (info) - pipe packet recv size: " << buf_len << '\n';
if (buf_len == -1) {
std::cout << "ERROR (info) - recv" << std::endl;
close(sender_s);
close(receiver_s);
return;
}
if (buf_len == 0) { continue; }
// Send
buf_len = send(receiver_s, in_buf, buf_len, 0);
std::cout << "LOG (info) - pipe packet send size: " << buf_len << '\n';
} while (buf_len == BUF_SIZE);
std::cout << "Sent data to receiver" << std::endl;
}
void ProxySockets(int sender_s, int receiver_s) {
char out_buf[BUF_SIZE]; // Output buffer for HTML response
ssize_t buf_len; // Buffer length for file reads
// Pass response along from server to browser
std::cout << "Attempting to send to browser" << std::endl;
do {
// Receive
buf_len = recv(sender_s, out_buf, BUF_SIZE, 0);
std::cout << "LOG (info) - proxy packet recv size: " << buf_len << '\n';
if (buf_len == -1) {
std::cout << "ERROR (info) - recv -1" << std::endl;
return;
}
// Send
buf_len = send(receiver_s, out_buf, buf_len, 0);
if (buf_len == 96) { break; }
std::cout << "LOG (info) - proxy packet send size: " << buf_len << '\n';
} while ((buf_len == BUF_SIZE) || (buf_len == 40));
std::cout << "Sent to browser" << std::endl;
close(sender_s);
close(receiver_s);
}
Client::Client(void) {
addressLength = sizeof(address);
address.sin_family = AF_INET;
}
bool Client::ConnectFrom(int serverFD) {
socketFD = accept(serverFD, (struct sockaddr *)&address, &addressLength);
if (socketFD == -1) { return 1; }
return 0;
}
bool Client::ConnectTo(int portNumber) {
std::cout << "Attempting to connect to " << kWebserverIP << " on " << portNumber << std::endl;
address.sin_port = htons(portNumber);
if (inet_pton(address.sin_family, kWebserverIP, &address.sin_addr) <= 0) {
std::cerr << "ERROR (info) - inet_pton" << std::endl;
return 1;
}
socketFD = socket(address.sin_family, SOCK_STREAM, 0);
if (connect(socketFD, (struct sockaddr *)&address, addressLength) == -1) {
std::cerr << "ERROR (info) - connect" << std::endl;
return 1;
}
std::cout << "Connection successful" << std::endl;
return 0;
}
Server::Server(int portNumber) {
std::cout << "Opening the server" << std::endl;
socketFD = socket(AF_INET, SOCK_STREAM, 0);
if (socketFD == -1)
{
std::cerr << "ERROR - Unable to create socket on server" << std::endl;
exit(1);
}
address.sin_family = AF_INET;
address.sin_port = htons(portNumber);
address.sin_addr.s_addr = htonl(INADDR_ANY);
// Create a socket, fill-in address information, and then bind it
if (bind(socketFD, (struct sockaddr *)&address, sizeof(address)) == -1)
{
std::cerr << "ERROR - Unable to bind socket" << std::endl;
exit(1);
}
// Listen for connections and then accept
listen(socketFD, 100);
std::cout << "Server is now open" << std::endl;
}
void Server::Close(void) {
std::cout << "Closing the server" << std::endl;
close(socketFD);
}

View File

@ -1,33 +0,0 @@
#ifndef NETWORK_HPP
#define NETWORK_HPP
#include <netinet/in.h>
#include <unistd.h>
#define BUF_SIZE 4096 // Buffer size (big enough for a GET)
#define kProxyPort 9080
#define kWebserverIP "127.0.0.1"
#define kWebserverPort 7080
void TestSockets(int sender_s, int receiver_s);
void PipeSockets(int sender_s, int receiver_s);
void ProxySockets(int sender_s, int receiver_s);
struct Client {
unsigned int socketFD; // Client socket descriptor
sockaddr_in address; // Client IP address
socklen_t addressLength; // Internet address length
Client(void);
bool ConnectFrom(int serverFD);
bool ConnectTo(int portNumber);
};
struct Server {
unsigned int socketFD; // Server socket descriptor
sockaddr_in address; // Server Internet address
Server(int portNumber);
void Close(void);
};
#endif

View File

@ -1,9 +1,17 @@
//----- Include files --------------------------------------------------------- //----- Include files ---------------------------------------------------------
#include <algorithm> #include <stdio.h> // Needed for printf()
#include <stdlib.h> // Needed for exit()
#include <string.h> // Needed for strcpy() and strlen()
#include <fcntl.h> // Needed for file i/o constants
#include <sys/stat.h> // Needed for file i/o constants
#include <future> #include <future>
#include <iostream>
#include <vector> #include <sys/types.h> //
#include "network.hpp" #include <netinet/in.h> //
#include <sys/socket.h> //
#include <arpa/inet.h> //
#include <unistd.h>
//----- HTTP response messages ---------------------------------------------- //----- HTTP response messages ----------------------------------------------
#define OK_IMAGE "HTTP/1.0 200 OK\nContent-Type:image/gif\n\n" #define OK_IMAGE "HTTP/1.0 200 OK\nContent-Type:image/gif\n\n"
@ -11,38 +19,104 @@
#define NOTOK_404 "HTTP/1.0 404 Not Found\nContent-Type:text/html\n\n" #define NOTOK_404 "HTTP/1.0 404 Not Found\nContent-Type:text/html\n\n"
#define MESS_404 "<html><body><h1>FILE NOT FOUND</h1></body></html>" #define MESS_404 "<html><body><h1>FILE NOT FOUND</h1></body></html>"
//----- Defines -------------------------------------------------------------
#define BUF_SIZE 4096 // Buffer size (big enough for a GET)
#define PORT_NUM 9080 // Port number for a Web server
//----- Function prototypes -------------------------------------------------
void BrowserToProxy(int server_s, int client_s);
void ProxyToServer(int server_s, int client_s);
//===== modeule main ========================================================
int main(void) int main(void)
{ {
std::vector<std::future<void>> pending_futures; unsigned int proxy_s; // Server socket descriptor
Server proxy(kProxyPort); struct sockaddr_in proxy_addr; // Server Internet address
Client browser; unsigned int browser_s; // Client socket descriptor
Client webserver; struct sockaddr_in browser_addr; // Client Internet address
struct in_addr browser_ip_addr; // Client IP address
unsigned int server_s; // Client socket descriptor
struct sockaddr_in server_addr; // Client Internet address
struct in_addr server_ip_addr; // Client IP address
socklen_t addr_len; // Internet address length
// Create a socket, fill-in address information, and then bind it
proxy_s = socket(AF_INET, SOCK_STREAM, 0);
if (proxy_s == -1)
{
printf("ERROR - Unable to create socket on server\n");
exit(1);
}
proxy_addr.sin_family = AF_INET;
proxy_addr.sin_port = htons(PORT_NUM);
proxy_addr.sin_addr.s_addr = htonl(INADDR_ANY);
int bindRet = bind(proxy_s, (struct sockaddr *)&proxy_addr, sizeof(proxy_addr));
if (bindRet == -1)
{
printf("ERROR - Unable to bind socket\n");
exit(1);
}
// Listen for connections and then accept
listen(proxy_s, 100);
// Main loop to listen, accept, and then spin-off a thread to handle the GET // Main loop to listen, accept, and then spin-off a thread to handle the GET
while (1) while (1)
{ {
if (browser.ConnectFrom(proxy.socketFD) != 0) addr_len = sizeof(browser_addr);
{
std::cerr << "ERROR - Unable to create socket to client" << std::endl; browser_s = accept(proxy_s, (struct sockaddr *)&browser_addr, &addr_len);
if (browser_s == -1)
{
perror("ERROR - Unable to create socket to client\n");
continue; continue;
} }
if (webserver.ConnectTo(kWebserverPort) != 0) unsigned int server_s = socket(AF_INET, SOCK_STREAM, 0);
{ connect(server_s, (struct sockaddr *)&server_addr, addr_len);
std::cerr << "ERROR - Unable to connect to webserver" << std::endl;
continue; std::async(std::launch::async, BrowserToProxy, browser_s, server_s);
} std::async(std::launch::async, ProxyToServer, server_s, browser_s);
auto newThreadRequest1 = std::async(std::launch::async, PipeSockets, browser.socketFD, webserver.socketFD);
auto newThreadRequest2 = std::async(std::launch::async, ProxySockets, webserver.socketFD, browser.socketFD);
pending_futures.push_back(std::move(newThreadRequest1));
pending_futures.push_back(std::move(newThreadRequest2));
/*
auto newThreadRequest = std::async(std::launch::async, TestSockets, browser.socketFD, webserver.socketFD);
pending_futures.push_back(std::move(newThreadRequest));
std::cout << "Returned from creating threads, continuing..." << std::endl;
*/
//TestSockets(browser.socketFD, webserver.socketFD);
} }
proxy.Close(); close(browser_s);
return 0; return (1);
} }
void BrowserToProxy(int server_s, int client_s) {
char in_buf[BUF_SIZE]; // Input buffer for GET resquest
char out_buf[BUF_SIZE]; // Output buffer for HTML response
char *file_name; // File name
unsigned int fh; // File handle
ssize_t buf_len; // Buffer length for file reads
unsigned int retcode; // Return code
// Receive the GET request from the Web browser
do {
buf_len = recv(server_s, in_buf, BUF_SIZE, 0);
send(client_s, in_buf, buf_len, 0);
} while (buf_len != 0);
}
void ProxyToServer(int server_s, int client_s) {
/*
loop {
recv from browser
send to server
}
*/
char in_buf[BUF_SIZE]; // Input buffer for GET resquest
char out_buf[BUF_SIZE]; // Output buffer for HTML response
char *file_name; // File name
unsigned int fh; // File handle
ssize_t buf_len; // Buffer length for file reads
unsigned int retcode; // Return code
// Receive the GET request from the Web browser
do {
buf_len = recv(server_s, in_buf, BUF_SIZE, 0);
send(client_s, in_buf, buf_len, 0);
} while (buf_len != 0);
close(server_s);
close(client_s);
}

View File

@ -31,14 +31,12 @@
#define UNIX // WIN for Windows environment, UNIX for BSD or LINUX env. #define UNIX // WIN for Windows environment, UNIX for BSD or LINUX env.
//----- Include files --------------------------------------------------------- //----- Include files ---------------------------------------------------------
#include <stdio.h> // Needed for printf()
#include <stdlib.h> // Needed for exit()
#include <string.h> // Needed for strcpy() and strlen() #include <string.h> // Needed for strcpy() and strlen()
#include <fcntl.h> // Needed for file i/o constants #include <fcntl.h> // Needed for file i/o constants
#include <sys/stat.h> // Needed for file i/o constants #include <sys/stat.h> // Needed for file i/o constants
#include <errno.h>
#include <future> #include <future>
#include <iostream>
#include <vector>
#include "network.hpp"
/* FOR BSD UNIX/LINUX ---------------------------------------------------- */ /* FOR BSD UNIX/LINUX ---------------------------------------------------- */
#ifdef UNIX #ifdef UNIX
@ -86,9 +84,19 @@ int main(void)
#endif #endif
/* --------------------------------------------------------------------- */ /* --------------------------------------------------------------------- */
std::vector<std::future<void>> pending_futures; unsigned int server_s; // Server socket descriptor
Server webserver(kWebserverPort); struct sockaddr_in server_addr; // Server Internet address
Client proxy; unsigned int client_s; // Client socket descriptor
struct sockaddr_in client_addr; // Client Internet address
struct in_addr client_ip_addr; // Client IP address
socklen_t addr_len; // Internet address length
/* FOR UNIX/LINUX ------------------------------------------------------ */
#ifdef UNIX
int nChild_proc_id; // New child process ID.
#endif
/* --------------------------------------------------------------------- */
/* FOR WIN ------------------------------------------------------------- */ /* FOR WIN ------------------------------------------------------------- */
#ifdef WIN #ifdef WIN
// Initialize winsock // Initialize winsock
@ -96,19 +104,41 @@ int main(void)
#endif #endif
/* --------------------------------------------------------------------- */ /* --------------------------------------------------------------------- */
// Create a socket, fill-in address information, and then bind it
server_s = socket(AF_INET, SOCK_STREAM, 0);
if (server_s == -1)
{
printf("ERROR - Unable to create socket on server\n");
exit(1);
}
server_addr.sin_family = AF_INET;
server_addr.sin_port = htons(PORT_NUM);
server_addr.sin_addr.s_addr = htonl(INADDR_ANY);
int bindRet = bind(server_s, (struct sockaddr *)&server_addr, sizeof(server_addr));
if (bindRet == -1)
{
printf("ERROR - Unable to bind socket\n");
exit(1);
}
// Listen for connections and then accept
listen(server_s, 100);
// Main loop to listen, accept, and then spin-off a thread to handle the GET // Main loop to listen, accept, and then spin-off a thread to handle the GET
while (1) while (1)
{ {
if (proxy.ConnectFrom(webserver.socketFD) != 0) addr_len = sizeof(client_addr);
{
std::cerr << "ERROR - Unable to create socket to client" << std::endl; client_s = accept(server_s, (struct sockaddr *)&client_addr, &addr_len);
if (client_s == -1)
{
perror("ERROR - Unable to create socket to client\n");
continue; continue;
} }
auto newThreadRequest = std::async(std::launch::async, ClientRequest, proxy.socketFD);
pending_futures.push_back(std::move(newThreadRequest)); std::async(std::launch::async, ClientRequest, client_s);
} }
webserver.Close(); close(server_s);
return 0; return (1);
} }
void ClientRequest(int client_s) { void ClientRequest(int client_s) {
@ -122,51 +152,46 @@ void ClientRequest(int client_s) {
// Receive the GET request from the Web browser // Receive the GET request from the Web browser
retcode = recv(client_s, in_buf, BUF_SIZE, 0); retcode = recv(client_s, in_buf, BUF_SIZE, 0);
if (retcode == -1) { std::cerr << "ERROR (info) - recv" << std::endl; }
// Handle the GET if there is one (see note #3 in the header) // Handle the GET if there is one (see note #3 in the header)
// Parse out the filename from the GET request if (retcode != -1)
strtok(in_buf, " "); {
file_name = strtok(NULL, " "); // Parse out the filename from the GET request
strtok(in_buf, " ");
file_name = strtok(NULL, " ");
// Open the requested file // Open the requested file
// - Start at 2nd char to get rid of leading "\" // - Start at 2nd char to get rid of leading "\"
#ifdef WIN #ifdef WIN
fh = open(&file_name[1], O_RDONLY | O_BINARY, S_IREAD | S_IWRITE); fh = open(&file_name[1], O_RDONLY | O_BINARY, S_IREAD | S_IWRITE);
#endif #endif
#ifdef UNIX #ifdef UNIX
fh = open(&file_name[1], O_RDONLY, S_IREAD | S_IWRITE); fh = open(&file_name[1], O_RDONLY, S_IREAD | S_IWRITE);
#endif #endif
// Generate and send the response (404 if could not open the file) // Generate and send the response (404 if could not open the file)
if (fh == -1) if (fh == -1)
{ {
printf("File %s not found - sending an HTTP 404 \n", &file_name[1]); printf("File %s not found - sending an HTTP 404 \n", &file_name[1]);
strcpy(out_buf, NOTOK_404); strcpy(out_buf, NOTOK_404);
send(client_s, out_buf, strlen(out_buf), 0); send(client_s, out_buf, strlen(out_buf), 0);
strcpy(out_buf, MESS_404); strcpy(out_buf, MESS_404);
send(client_s, out_buf, strlen(out_buf), 0); send(client_s, out_buf, strlen(out_buf), 0);
} else { }
printf("File %s is being sent \n", &file_name[1]); else
if (strstr(file_name, ".gif") != NULL) {
strcpy(out_buf, OK_IMAGE); printf("File %s is being sent \n", &file_name[1]);
else if (strstr(file_name, ".gif") != NULL)
strcpy(out_buf, OK_TEXT); strcpy(out_buf, OK_IMAGE);
send(client_s, out_buf, strlen(out_buf), 0); else
do { strcpy(out_buf, OK_TEXT);
buf_len = read(fh, out_buf, BUF_SIZE); send(client_s, out_buf, strlen(out_buf), 0);
buf_len = send(client_s, out_buf, buf_len, 0); do {
if (buf_len == -1) { buf_len = read(fh, out_buf, BUF_SIZE);
std::cerr << "ERROR (info) - send -1\n"; send(client_s, out_buf, buf_len, 0);
std::cerr << "File causing error: " << &file_name[1] << '\n'; } while (buf_len != 0);
std::cerr << "Errno: " << errno << '\n'; close(fh);
std::cout << std::endl; }
return; }
}
std::cout << "LOG (info) - webserver send size: " << buf_len << '\n';
} while (buf_len == BUF_SIZE);
std::cout << std::endl;
close(fh);
}
// Close the client socket and end the thread // Close the client socket and end the thread
close(client_s); close(client_s);
} }