668 lines
20 KiB
C
668 lines
20 KiB
C
|
|
#include <unistd.h> /* close() */
|
|
#include <sys/socket.h> /* Socket Functions */
|
|
#include <sys/types.h> /* Socket Datatypes */
|
|
#include <netinet/in.h> /* IP Datatypes */
|
|
#include <arpa/inet.h> /* Address Structs */
|
|
#include <netdb.h>
|
|
|
|
#include <stdio.h> /* Standard IO */
|
|
#include <stdlib.h> /* Standard Lib */
|
|
|
|
#include <sys/ipc.h>
|
|
#include <sys/sem.h>
|
|
|
|
#include <string.h> /* String Libs */
|
|
|
|
#include "include/threads.h" /* My Functions */
|
|
#include "include/proxy_settings.h"
|
|
#include "../../common/defs.h" /* Definitions */
|
|
#include "../../common/http/http.h"
|
|
#include "../../common/networking/networking.h"
|
|
#include "../../common/shared_memory/shared_memory.h"
|
|
|
|
#include <pthread.h>
|
|
|
|
#define HTTP_REQUEST_SIZE 1024
|
|
#define RECV_SIZE 64
|
|
#define PROTO "http://"
|
|
|
|
char *strfindr(char *dest, char *src, char *find, char *replace);
|
|
char *itoa(int);
|
|
|
|
char *acceptClientRequest(int clntSocket) {
|
|
char* received;
|
|
char* temp;
|
|
int len, i;
|
|
|
|
uber_recv(clntSocket, BUFFERSIZE, "\0", &temp);
|
|
received = temp;
|
|
|
|
i=1;
|
|
while( len = uber_recv(clntSocket, BUFFERSIZE, "\0", &temp) && 0 > len ) {
|
|
received = realloc(received, (len + BUFFERSIZE)*sizeof(char));
|
|
memcpy(received+(BUFFERSIZE*i), temp, len);
|
|
free(temp);
|
|
}
|
|
|
|
return received;
|
|
}
|
|
|
|
void dispatchLocal(char *clntRequest, int clntSocket) {
|
|
char *get_local;
|
|
int i, length;
|
|
|
|
int servSocket;
|
|
|
|
shmemNode* shmemSegment;
|
|
|
|
get_local = malloc(sizeof(char) * (strlen(LOCAL_GET) + 1) );
|
|
strcpy(get_local, LOCAL_GET);
|
|
|
|
length = strlen(get_local);
|
|
get_local[length] = ' '; length++;
|
|
|
|
clntRequest = strstr(clntRequest, "localhost");
|
|
|
|
for (; *clntRequest != '/'; clntRequest++);
|
|
clntRequest++;
|
|
|
|
for (; *clntRequest != ' '; length++, clntRequest++) {
|
|
get_local = realloc(get_local, sizeof(char)*(length+1));
|
|
get_local[length] = *clntRequest;
|
|
}
|
|
|
|
get_local = realloc(get_local, sizeof(char) * (length+2));
|
|
get_local[length] = ' '; length++;
|
|
|
|
shmemSegment = getSharedMemorySegment();
|
|
|
|
//printf("semIndex: %d\n",shmemSegment->semIndex);
|
|
|
|
{
|
|
char *buff;
|
|
|
|
buff = itoa(shmemSegment->semIndex);
|
|
|
|
get_local = realloc(get_local, sizeof(char) * (length+strlen(buff)+1));
|
|
|
|
for (i=0; buff[i] != '\0'; i++) {
|
|
get_local[length+i] = buff[i];
|
|
}
|
|
get_local[length+i] = buff[i];
|
|
|
|
free(buff);
|
|
|
|
}
|
|
|
|
//printf("get_local: %s\n", get_local);
|
|
//printf("length: %d %d\n", length, strlen(get_local));
|
|
//printf("..Done\n");
|
|
|
|
servSocket = createTCPSocket("127.0.0.1", 1337);
|
|
if (servSocket < 0) {
|
|
return;
|
|
}
|
|
|
|
//Send to server
|
|
if (send(servSocket, get_local, strlen(get_local), 0) < 0) {
|
|
printf("Send error to server\n");
|
|
close(servSocket);
|
|
return;
|
|
}
|
|
|
|
// Send stuff Back to the client
|
|
{
|
|
struct sembuf sembuffer;
|
|
|
|
//printf("Receiving from server.\n");
|
|
|
|
// Get semaphore
|
|
sembuffer.sem_num = shmemSegment->semIndex;
|
|
sembuffer.sem_op = -1;
|
|
sembuffer.sem_flg = 0;
|
|
|
|
for (;;) {
|
|
|
|
// Wait for semprox to be 1
|
|
//printf("Waiting for semprox to be 1\n");
|
|
sembuffer.sem_op = -1;
|
|
semop(semprox, &sembuffer, 1);
|
|
|
|
if (*((int*)shmemSegment->buff) == -1) {
|
|
// Set semserv to 1
|
|
sembuffer.sem_op = 1;
|
|
semop(semserv, &sembuffer, 1);
|
|
break;
|
|
}
|
|
|
|
// Send back to client
|
|
if (send(clntSocket,
|
|
shmemSegment->buff+sizeof(int),
|
|
*((int*)shmemSegment->buff),
|
|
0) < 0)
|
|
{
|
|
printf("Send Error\n");
|
|
}
|
|
|
|
//printf("Setting semserv to 1\n");
|
|
// Set semserv to 1
|
|
sembuffer.sem_op = 1;
|
|
semop(semserv, &sembuffer, 1);
|
|
|
|
}
|
|
}
|
|
|
|
releaseSharedMemorySegment(shmemSegment);
|
|
|
|
}
|
|
|
|
|
|
void *consumerNoNoob(void* dumb) {
|
|
|
|
settings_t *settings = (settings_t*) dumb;
|
|
char isLocal = 0;
|
|
|
|
#if _LOG_
|
|
printf("[CONSUMER] Consumer %ld started\n", (long)pthread_self());
|
|
fflush(stdout);
|
|
#endif
|
|
|
|
//Get stuff from the client
|
|
for (;;) {
|
|
int clntSocket, servSocket;
|
|
char *clntRequest = NULL, *servHostName;
|
|
struct addrinfo *addressInfo;
|
|
|
|
clntSocket = removeSocket();
|
|
|
|
//Receive from Client
|
|
{ //1
|
|
char buffer[RECV_SIZE];
|
|
int i = 1;
|
|
|
|
while (recv(clntSocket, buffer, RECV_SIZE, 0) > 0) {
|
|
//printf("receiving\n");
|
|
clntRequest = realloc(clntRequest, (i*RECV_SIZE)*sizeof(char));
|
|
memcpy(clntRequest+((i-1)*RECV_SIZE), buffer, RECV_SIZE);
|
|
if (strstr(clntRequest, "\r\n\r\n\0")) break; //FIXME: Fix my speed
|
|
i++;
|
|
}
|
|
//printf("Got:\n%s\n", clntRequest);
|
|
|
|
// if Shared Memory is active, all localhost requests are
|
|
// routed to the shared memory modules
|
|
if (settings->useSHMEM && strstr(clntRequest, "localhost")) {
|
|
dispatchLocal(clntRequest, clntSocket);
|
|
close(clntSocket);
|
|
continue;
|
|
} else if (strstr(clntRequest, "localhost")) {
|
|
//We're going to assume that we're running l33t_server
|
|
// on port 1337 and thus skip the host resolution...stuff
|
|
isLocal = 1;
|
|
}
|
|
|
|
} //1
|
|
|
|
//Figure out what to get
|
|
{ //2
|
|
char *request, *temp = NULL;
|
|
int i;
|
|
|
|
request = strstr(clntRequest, PROTO);
|
|
if (!request) {
|
|
printf("Bad Request on socket: %d\n",clntSocket);
|
|
free(clntRequest);
|
|
close(clntSocket);
|
|
continue;
|
|
}
|
|
|
|
request += strlen(PROTO);
|
|
|
|
for (i=0; request[i] != '/'; i++) {
|
|
temp = realloc(temp, (i+1)*sizeof(char));
|
|
|
|
temp[i] = request[i];
|
|
}
|
|
|
|
temp = realloc(temp, (i+1)*sizeof(char));
|
|
temp[i] = '\0';
|
|
//printf("temp: %s\n",temp);
|
|
|
|
servHostName = temp;
|
|
|
|
} //2
|
|
|
|
{ //5
|
|
char *temp;
|
|
|
|
temp = malloc(strlen(PROTO)+strlen(servHostName)+1);
|
|
|
|
sprintf(temp,"%s%s",PROTO,servHostName);
|
|
|
|
strfindr(clntRequest, clntRequest, temp, "");
|
|
free(temp);
|
|
//printf("clntRequest:\n%s\n", clntRequest);
|
|
|
|
} //5
|
|
|
|
//Get Website Address
|
|
if (!isLocal)
|
|
{ //3
|
|
struct addrinfo hints;
|
|
|
|
memset(&hints, 0, sizeof(hints));
|
|
|
|
hints.ai_family = PF_INET;
|
|
hints.ai_socktype = SOCK_STREAM;
|
|
hints.ai_protocol = IPPROTO_TCP;
|
|
|
|
// Get the Host Information
|
|
if (getaddrinfo(servHostName, "http", &hints, &addressInfo)) {
|
|
//Error
|
|
free(clntRequest);
|
|
free(servHostName);
|
|
close(clntSocket);
|
|
continue;
|
|
}
|
|
|
|
} //3
|
|
|
|
//Open Socket to the server
|
|
if ( !isLocal)
|
|
{ //4
|
|
servSocket = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);
|
|
if (servSocket < 0) {
|
|
free(clntRequest);
|
|
free(servHostName);
|
|
close(clntSocket);
|
|
freeaddrinfo(addressInfo);
|
|
continue;
|
|
}
|
|
|
|
//Connect to the server
|
|
|
|
if (connect(servSocket,
|
|
addressInfo->ai_addr, addressInfo->ai_addrlen) < 0)
|
|
{
|
|
free(clntRequest);
|
|
free(servHostName);
|
|
close(clntSocket);
|
|
close(servSocket);
|
|
freeaddrinfo(addressInfo);
|
|
continue;
|
|
}
|
|
} else {
|
|
servSocket = createTCPSocket("127.0.0.1",1337);
|
|
}
|
|
|
|
//printf("Connected to server\n");
|
|
|
|
//Send to server
|
|
if (send(servSocket, clntRequest, strlen(clntRequest), 0) < 0) {
|
|
printf("Send error to server\n");
|
|
goto error;
|
|
}
|
|
|
|
//printf("Sent to server\n");
|
|
|
|
if (!strstr(clntRequest, "\r\n\r\n\0")) printf("SHIT!!!\n");
|
|
|
|
//get stuff from server and send back to client
|
|
{ //6
|
|
char buffer[RECV_SIZE];
|
|
ssize_t got;
|
|
|
|
while( (got = recv(servSocket, buffer, RECV_SIZE, 0) ) > 0 ) {
|
|
//printf("Sending %d to Client!\n", got);
|
|
//Send back to client
|
|
if (send(clntSocket, buffer, got, 0) < 0) {
|
|
printf("Send Error\n");
|
|
break;
|
|
}
|
|
}
|
|
//printf("Break!!!\n");
|
|
}
|
|
|
|
error:
|
|
free(clntRequest);
|
|
free(servHostName);
|
|
close(clntSocket);
|
|
close(servSocket);
|
|
if (!isLocal) freeaddrinfo(addressInfo);
|
|
}
|
|
|
|
} //0
|
|
|
|
void *consumer(void* dumb) {
|
|
|
|
#if _LOG_
|
|
printf("[CONSUMER] Consumer %ld started\n", (long)pthread_self());
|
|
fflush(stdout);
|
|
#endif
|
|
|
|
for (;;) {
|
|
//Accept data from the connection
|
|
char *received;
|
|
int clntSocket;
|
|
int servSocket;
|
|
char *request, *request_ptr ,*pc;
|
|
struct addrinfo *addressInfo, hints;
|
|
|
|
clntSocket = removeSocket(); //This is where it waits!!!
|
|
|
|
// acceptClientRequest(clntSocket)
|
|
uber_recv(clntSocket, BUFFERSIZE, "\0", &received);
|
|
|
|
// Figure out what needs to be gotten
|
|
request = strstr(received, PROTO);
|
|
|
|
if (!request) {
|
|
printf("Bad Request on socket: %d\n",clntSocket);
|
|
free(received);
|
|
close(clntSocket);
|
|
continue;
|
|
}
|
|
|
|
request += strlen(PROTO); // Skip past the PROTO (http://)
|
|
|
|
// Get the site we want
|
|
strtok_r(request, "/", &request_ptr);
|
|
pc = malloc(strlen(request)+1);
|
|
strcpy(pc,request);
|
|
|
|
memset(&hints, 0, sizeof(hints));
|
|
|
|
hints.ai_family = PF_INET;
|
|
hints.ai_socktype = SOCK_STREAM;
|
|
hints.ai_protocol = IPPROTO_TCP;
|
|
|
|
// Get the Host Information
|
|
if (getaddrinfo(request, "http", &hints, &addressInfo)) {
|
|
//Error
|
|
free(received);
|
|
free(pc);
|
|
close(clntSocket);
|
|
continue;
|
|
}
|
|
|
|
// Setup socket to the server.
|
|
servSocket = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);
|
|
if (servSocket < 0) {
|
|
free(received);
|
|
close(clntSocket);
|
|
freeaddrinfo(addressInfo);
|
|
free(pc);
|
|
continue;
|
|
}
|
|
|
|
// Connect to the server
|
|
if ( connect(servSocket, addressInfo->ai_addr, addressInfo->ai_addrlen) < 0) {
|
|
free(received);
|
|
close(clntSocket);
|
|
freeaddrinfo(addressInfo);
|
|
free(pc);
|
|
continue;
|
|
}
|
|
|
|
//Retrieve Stuff From server (client)
|
|
|
|
if (*request_ptr == ' ') {
|
|
*request_ptr = '/';
|
|
*(request_ptr+1) = '\0';
|
|
} else {
|
|
strtok_r(request_ptr, " ", &request);
|
|
request_ptr--;
|
|
*request_ptr = '/';
|
|
}
|
|
|
|
{
|
|
//Create the thing to send
|
|
char http_request[HTTP_REQUEST_SIZE];
|
|
int sendlen;
|
|
|
|
sprintf(http_request, "GET %s HTTP/1.1\r\nHost: %s\r\n\r\n" , request_ptr, pc);
|
|
free(pc);
|
|
sendlen = strlen(http_request) + 1;
|
|
|
|
printf("Sending: %s\n Length: %d\n", http_request, sendlen);
|
|
|
|
if (send(servSocket, http_request, sendlen, 0) != sendlen) {
|
|
printf("Send Failed\n");
|
|
free(received);
|
|
close(clntSocket);
|
|
freeaddrinfo(addressInfo);
|
|
continue;
|
|
}
|
|
}
|
|
|
|
{
|
|
char serve_recv[1024];
|
|
|
|
while (recv(servSocket, serve_recv, 1024, 0) > 0) {
|
|
printf("Sending\n");
|
|
if (send(clntSocket, serve_recv, 1024, 0)) {
|
|
break;
|
|
}
|
|
printf("Sent\n");
|
|
}
|
|
}
|
|
|
|
printf("Freeing\n");
|
|
close(clntSocket);
|
|
close(servSocket);
|
|
free(received);
|
|
freeaddrinfo(addressInfo);
|
|
|
|
} // End Consumer Loop
|
|
}
|
|
|
|
|
|
void *producer(void* v_port_number) {
|
|
int clntSock; /* client sock descriptor. */
|
|
int servSock; /* Server sock descriptor. */
|
|
|
|
unsigned short port_number = *((unsigned short*)v_port_number);
|
|
|
|
#ifdef _WIN32
|
|
DWORD threadID; /* ThreadID from CreateThread().*/
|
|
WSADATA wsaData; /* Winsock struct. */
|
|
if (WSAStartup(MAKEWORD(2, 0), &wsaData) != 0)/* Winsock 2.0 DLL. */
|
|
DieWithError("WSAStartup() failed");
|
|
#endif
|
|
|
|
VPRINTF((" Producer Port %d\n", port_number));
|
|
|
|
servSock = ContructTCPSocket(port_number);
|
|
|
|
#if _LOG_
|
|
printf("[PRODUCER] Producer Initialized, listening for connections\n");
|
|
fflush(stdout);
|
|
#endif
|
|
|
|
for(;;) /* Loop forever */
|
|
{
|
|
clntSock = AcceptConnection(servSock);
|
|
if (clntSock == -1) {
|
|
continue;
|
|
}
|
|
addSocket(clntSock);
|
|
} // End Producer Loop
|
|
/* NEVER REACHED... */
|
|
}
|
|
|
|
/*
|
|
* String Find & Replace
|
|
*
|
|
* This function works like it sounds. It finds instances of find
|
|
* in src and replaces them with replace in dest.
|
|
*
|
|
*
|
|
* Ver 1.1 - Corrected Issue with things like Hello and finding lo
|
|
*/
|
|
char *strfindr(char *dest, char *src, char *find, char *replace){
|
|
/* seems easy enough
|
|
* Too bad this one takes the second longest to code of
|
|
* all functions in this assignment, beaten only by strpig
|
|
*/
|
|
size_t i=0,x=0,j=0,a=0,b=0,bNotFound=0;
|
|
char *p, *p2;
|
|
|
|
/* Invalid Param Checks */
|
|
if(dest == NULL || src == NULL || find == NULL || replace == NULL){
|
|
return NULL;
|
|
}
|
|
|
|
/* Empty String */
|
|
if(*find == '\0'){
|
|
while(*(src+i) != '\0'){
|
|
*(dest+i) = *(src+i);
|
|
i++;
|
|
}
|
|
*(dest+i) = '\0';
|
|
return dest;
|
|
}
|
|
|
|
/* Important I'm sure */
|
|
p2 = src;
|
|
|
|
do{
|
|
/* The Cheap method to create an inline function */
|
|
{
|
|
/*
|
|
* This block of code finds where the
|
|
* the thing to be replaced is located
|
|
*/
|
|
for(; *(src+a) != '\0'; a++){
|
|
if(*(find+b) == '\0'){
|
|
break;
|
|
}else if(*(src+a) == *(find+b)){
|
|
b++;
|
|
}else{
|
|
if(*(find) != *(src+a)){
|
|
b=0;
|
|
p2=(src+a+1);
|
|
}else{
|
|
b=1;
|
|
p2=(src+a);
|
|
}
|
|
|
|
}
|
|
}
|
|
/*
|
|
* We didn't find it, oh poop
|
|
*/
|
|
if(*(src+a) == '\0' && *(find+b) != '\0'){
|
|
bNotFound = 1;
|
|
}
|
|
}
|
|
|
|
/* Reset b */
|
|
b=0;
|
|
|
|
/* Not found, we can just copy the strings over */
|
|
if(bNotFound == 1){
|
|
while(*(src+i) != '\0'){
|
|
*(dest+x) = *(src+i);
|
|
i++;x++;
|
|
}
|
|
break;
|
|
}
|
|
|
|
/* Also probably important */
|
|
p = p2;
|
|
|
|
/* Keep going until you hit the thang that needs fixin */
|
|
while((src+i) != p && *(src+i) != '\0'){
|
|
*(dest+x) = *(src+i);
|
|
i++;x++;
|
|
}
|
|
|
|
/*
|
|
* Time to replace
|
|
* Note the two counters
|
|
*/
|
|
if((src+i) == p){
|
|
for(j=0;*(find+j) != '\0';j++,i++);
|
|
|
|
for(j=0;*(replace+j) != '\0';x++,j++){
|
|
*(dest+x) = *(replace+j);
|
|
}
|
|
}
|
|
|
|
}while(p2 != NULL);
|
|
|
|
/* String Terminated */
|
|
*(dest+x) = '\0';
|
|
|
|
|
|
return dest;
|
|
}
|
|
|
|
/*--------------------------------------------------------------------+
|
|
| itoa() - manage the sign, compute the string equivalent, and call |
|
|
| memcpy(). |
|
|
+--------------------------------------------------------------------*/
|
|
char *itoa(int value)
|
|
{
|
|
int count, /* number of characters in string */
|
|
i, /* loop control variable */
|
|
sign; /* determine if the value is negative */
|
|
char *ptr, /* temporary pointer, index into string */
|
|
*string, /* return value */
|
|
*temp; /* temporary string array */
|
|
|
|
int INTSIZE = sizeof(int);
|
|
|
|
count = 0;
|
|
if ((sign = value) < 0) /* assign value to sign, if negative */
|
|
{ /* keep track and invert value */
|
|
value = -value;
|
|
count++; /* increment count */
|
|
}
|
|
|
|
/* allocate INTSIZE plus 2 bytes (sign and NULL) */
|
|
temp = (char *) malloc(INTSIZE + 2);
|
|
if (temp == NULL)
|
|
{
|
|
return(NULL);
|
|
}
|
|
memset(temp,'\0', INTSIZE + 2);
|
|
|
|
string = (char *) malloc(INTSIZE + 2);
|
|
if (string == NULL)
|
|
{
|
|
return(NULL);
|
|
}
|
|
memset(string,'\0', INTSIZE + 2);
|
|
ptr = string; /* set temporary ptr to string */
|
|
|
|
/*--------------------------------------------------------------------+
|
|
| NOTE: This process reverses the order of an integer, ie: |
|
|
| value = -1234 equates to: char [4321-] |
|
|
| Reorder the values using for {} loop below |
|
|
+--------------------------------------------------------------------*/
|
|
do {
|
|
*temp++ = value % 10 + '0'; /* obtain modulus and or with '0' */
|
|
count++; /* increment count, track iterations*/
|
|
} while (( value /= 10) >0);
|
|
|
|
if (sign < 0) /* add '-' when sign is negative */
|
|
*temp++ = '-';
|
|
|
|
*temp-- = '\0'; /* ensure null terminated and point */
|
|
/* to last char in array */
|
|
|
|
/*--------------------------------------------------------------------+
|
|
| reorder the resulting char *string: |
|
|
| temp - points to the last char in the temporary array |
|
|
| ptr - points to the first element in the string array |
|
|
+--------------------------------------------------------------------*/
|
|
for (i = 0; i < count; i++, temp--, ptr++)
|
|
{
|
|
memcpy(ptr,temp,sizeof(char));
|
|
}
|
|
|
|
return(string);
|
|
}
|