First commit
commit
d204627b73
@ -0,0 +1,155 @@
|
|||||||
|
#include <sys/socket.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <netinet/in.h>
|
||||||
|
#include <arpa/inet.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <errno.h>
|
||||||
|
int create_socket(int network, char transport) {
|
||||||
|
|
||||||
|
/* 'network' contains 4 for ipv4 or 6 for ipv6.
|
||||||
|
'transport' contains 'T' for TCP or 'U' for UDP.
|
||||||
|
The function returns -1 if the paramters do not match the above statement. */
|
||||||
|
|
||||||
|
int domain;
|
||||||
|
int type;
|
||||||
|
|
||||||
|
if (network == 4) {
|
||||||
|
domain = AF_INET;
|
||||||
|
} else if (network == 6) {
|
||||||
|
domain = AF_INET6;
|
||||||
|
} else {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (transport == 'T') {
|
||||||
|
type = SOCK_STREAM;
|
||||||
|
} else if (transport == 'U') {
|
||||||
|
type = SOCK_DGRAM;
|
||||||
|
} else {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int newSock = socket(domain,type,0);
|
||||||
|
return newSock;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void create_addr(int network, char* address, int port,struct sockaddr* dest) {
|
||||||
|
/* Takes the relevant values - network (4 or 6), address, port - and fills them
|
||||||
|
into dest */
|
||||||
|
|
||||||
|
if (network == 4) {
|
||||||
|
struct sockaddr_in listen_address;
|
||||||
|
|
||||||
|
listen_address.sin_family = AF_INET;
|
||||||
|
listen_address.sin_port = htons(port);
|
||||||
|
inet_pton(AF_INET,address,&listen_address.sin_addr);
|
||||||
|
memcpy(dest,&listen_address,sizeof(listen_address));
|
||||||
|
return;
|
||||||
|
|
||||||
|
} else if (network == 6) {
|
||||||
|
struct sockaddr_in6 listen_ipv6;
|
||||||
|
listen_ipv6.sin6_family = AF_INET6;
|
||||||
|
listen_ipv6.sin6_port = htons(port);
|
||||||
|
inet_pton(AF_INET6,address,&listen_ipv6.sin6_addr);
|
||||||
|
memcpy(dest,&listen_ipv6,sizeof(listen_ipv6));
|
||||||
|
return;
|
||||||
|
|
||||||
|
} else {
|
||||||
|
exit(-2);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
int create_and_bind (int network, char transport, char* address, int port,struct sockaddr* addr_struct) {
|
||||||
|
/* combines the socket creation and address creation into one
|
||||||
|
function - simply pass the required values, and a structure,
|
||||||
|
and this function does the legwork for you */
|
||||||
|
|
||||||
|
int socket = create_socket(network,transport);
|
||||||
|
if (socket == -1) {
|
||||||
|
exit(-1);
|
||||||
|
}
|
||||||
|
create_addr(network,address,port,addr_struct);
|
||||||
|
int addrlen = sizeof(*addr_struct);
|
||||||
|
int i = bind (socket,addr_struct,(socklen_t)addrlen);
|
||||||
|
if (i < 0) {
|
||||||
|
exit(-3);
|
||||||
|
}
|
||||||
|
return socket;
|
||||||
|
}
|
||||||
|
|
||||||
|
int create_remote (int network,char transport,char* address,int port) {
|
||||||
|
/* same as 'create_and_bind', but for remote sockets - client rather
|
||||||
|
than server sockets */
|
||||||
|
|
||||||
|
int socket = create_socket(network,transport);
|
||||||
|
if (socket == -1) {
|
||||||
|
exit(-1);
|
||||||
|
}
|
||||||
|
struct sockaddr remote_addr_struct;
|
||||||
|
create_addr(network,address,port,&remote_addr_struct);
|
||||||
|
int addrlen = sizeof(remote_addr_struct);
|
||||||
|
int i = connect(socket,&remote_addr_struct,(socklen_t)addrlen);
|
||||||
|
if (i < 0) {
|
||||||
|
printf("Something went wrong: %s\n",strerror(errno));
|
||||||
|
exit(-3);
|
||||||
|
}
|
||||||
|
return socket;
|
||||||
|
}
|
||||||
|
|
||||||
|
void forward_data(int from_fd, int to_fd) {
|
||||||
|
int n = 0;
|
||||||
|
char* buffer = malloc(3000*sizeof(char));
|
||||||
|
while ((n = recv(to_fd, buffer, 3000, 0)) > 0) { // read data from input socket
|
||||||
|
send(to_fd, buffer, n, 0); // send data to output socket
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int main() {
|
||||||
|
|
||||||
|
int preferred_network = 4;
|
||||||
|
char preferred_transport = 'T';
|
||||||
|
struct sockaddr addr_struct;
|
||||||
|
int server_sock = create_and_bind(preferred_network,preferred_transport,"127.0.0.1",3000,&addr_struct);
|
||||||
|
int addrlen = sizeof(addr_struct);
|
||||||
|
|
||||||
|
listen(server_sock,50); /* Arbitrary number, change later */
|
||||||
|
|
||||||
|
while (1) {
|
||||||
|
int from_client = accept(server_sock,&addr_struct,(socklen_t *)&addrlen);
|
||||||
|
int to_server = create_remote(preferred_network,preferred_transport,"127.0.0.1",5000);
|
||||||
|
|
||||||
|
if (fork() == 0) {
|
||||||
|
|
||||||
|
/* fork returns 0 for a child, so we're in the child's execution
|
||||||
|
right now */
|
||||||
|
close(server_sock);
|
||||||
|
if (fork() == 0) {
|
||||||
|
forward_data(from_client,to_server);
|
||||||
|
exit(0);
|
||||||
|
}
|
||||||
|
if (fork() == 0) {
|
||||||
|
forward_data(to_server,from_client);
|
||||||
|
exit(0);
|
||||||
|
}
|
||||||
|
exit(0);
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
// recv(from_client,buffer,3000,0);
|
||||||
|
|
||||||
|
|
||||||
|
// printf("%s",buffer);
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue