/*
    Written by: Clinton Brandt and Michael Simmons
    Date: October 27, 2006
    Project 2
    CSCI 340
    Magic Number is 6

    Pthread tutorial from "www.llnl.gov/computing/pthread/#PassingArguments"
    Socket tutorial from "beej.us/guide/bgnet/output/htmlsingle/bgnet.html"
*/

#include <pthread.h>
#include <semaphore.h>
#include <stdio.h>
#include <iostream>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/socket.h>
#include <netinet/in.h>        //socket tutorial
#include <fcntl.h>
#include <string>

//These are our ports for listening
#define PORTA 6006
#define PORTB 6011

void* NewSocket(void *sock);

struct thread_args{
    int port;
    char tag;
};

using namespace std;

int main(int argc, char* argv[]){
    
    pthread_t threadA;
    pthread_t threadB;
    int statusA, statusB;  //return status for the threads
    
    
    //init attributes
    pthread_attr_t attr;         //pthread tutorial showed this
    pthread_attr_init(&attr);
    pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);
    
    int error;
    
    thread_args handle[2];
    
    handle[0].port = PORTA;
    handle[0].tag = 'A';
    handle[1].port = PORTB;
    handle[1].tag = 'B';
    
    
    error = pthread_create(&threadA, &attr, NewSocket, (void*)&handle[0]);
    if (error){
        fprintf(stderr, "%s\n", strerror(error));
    }
    
    error = pthread_create(&threadB, &attr, NewSocket, (void*)&handle[1]);
    if (error){
        fprintf(stderr, "%s\n", strerror(error));
    }
    
    pthread_attr_destroy(&attr);    //attr clean up from tutorial

    error = pthread_join(threadA, (void **) &statusA);
    if (error){
        fprintf(stderr, "%s\n", strerror(error));
    }
    
    error = pthread_join(threadB, (void **) &statusB);
    if (error){
        fprintf(stderr, "%s\n", strerror(error));
    }
    
    printf("Finished\n");
    fflush(STDIN_FILENO);
    return 0;
}

void *NewSocket(void *arg){
    int error = 1001;
    write(STDIN_FILENO, (string*) error , 4);
    thread_args* handle;
    handle = (thread_args *) arg;
    
    write(STDIN_FILENO,"New Socket Created it is socket", 31);
    printf("%c", (handle->tag));
    printf("\n");
    
    //char charBuff[255];
    char message[256] = {'>', 0};
    

    struct sockaddr_in hostAddressInfo;           //Socket tutorial
    struct sockaddr_in clientAddressInfo;
    int bufferSize = sizeof(struct sockaddr_in);

    hostAddressInfo.sin_family = AF_INET;
    hostAddressInfo.sin_port = htons(handle->port);
    hostAddressInfo.sin_addr.s_addr = htonl(INADDR_ANY);
    memset(&(hostAddressInfo.sin_zero),'\0', 8);
    
    int listenSockID = socket(PF_INET, SOCK_STREAM, 0);

    error = bind(listenSockID,(struct sockaddr *) &hostAddressInfo, sizeof(struct sockaddr));
    
    error = listen(listenSockID, 4);   //we have 2 MN's and so only two sockets can be open at once 
    
    int commSockID = accept(listenSockID, (struct sockaddr *) &clientAddressInfo, (socklen_t *) &bufferSize);

    int notDone = 5;
    while(notDone > 0){
        write(STDIN_FILENO, &message, strlen(message)); //printf waited for a return to main()
        if (message != ""){
            error = send(commSockID, message, strlen(message), 0);
            if(error < 0){
                printf("An error has occored with the send function\n");
            }
            message[0] = '\n';
            message[1] = '$';
            message[2] = (char) 0;
            error = send(commSockID, message, strlen(message), 0); 
        }
        message[0] = 0;
        error = recv(commSockID, &message, 128, MSG_TRUNC);
        if(error < 0){
            printf("An error has occored with the recv function\n");
        }

        if(error < 0){notDone = 0;}
        error += 1000;
        write(STDIN_FILENO, (string*) error , 4);
        notDone--;
    }
    
    close(listenSockID);
    close(commSockID);
    pthread_exit((void *) 0);
}


