/*      CSCI 4830	*/
/*     Talk Program	*/
/*        by Paul	*/
/*         talk.c      	*/

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
#include <unistd.h>
#include <pthread.h>

#define MAX_MESSAGE_SIZE 512
#define PORT 5000

  pthread_t tid1, tid2;
  void sendMessage();
  void receiveMessage();

    int GLOBALKILL = 0;
    int skt, port;
    int active, activeLen, buflen;
    char sendText[MAX_MESSAGE_SIZE];
    char receiveText[MAX_MESSAGE_SIZE];
    char serverHostName[MAX_MESSAGE_SIZE];
    char* exitstring = "exit";
    struct hostent* host;
    struct sockaddr_in passive;
    struct protoent *protocol;

int main() 
{	
    switch(menu())
    {	  /* option 1 :: wait for somebody to connect */
	case 1:
	    system("clear");
	    printf("Currently listening for someone to connect...\n");
	      /* setup the socket for listening */
	    skt = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
	    bzero(&passive, sizeof(passive));
	    passive.sin_family = AF_INET;
	    passive.sin_addr.s_addr = htonl(INADDR_ANY);
	    port = PORT;
	    passive.sin_port = htons(port);
	    bind(skt, (struct sockaddr *) &passive, sizeof(passive));
	    listen(skt, 50);
	    activeLen = sizeof(active);
	    skt = accept(skt, (struct sockaddr *) &active, &activeLen);
	      /* create two communication threads so that we can send and receive concurrently */
	    pthread_create(&tid1, NULL, (void*(*)(void*))sendMessage, NULL);
	    pthread_create(&tid2, NULL, (void*(*)(void*))receiveMessage, NULL);
	    pthread_join(tid1, NULL);
	    pthread_join(tid2, NULL);
			
	    close(skt);
	    break;
			
	  /* option 2 :: connect to somebody */
	case 2:
	    printf("Who would like to talk with? (hostname) : ");
	    scanf("%s", serverHostName);
	    host = gethostbyname(serverHostName);
	      /* setup the socket for connection */
	    skt = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
	    bzero(&passive, sizeof(passive));
	    passive.sin_family = AF_INET;
	    bcopy(host->h_addr, &passive.sin_addr, host->h_length);
	    port = PORT;
	    passive.sin_port = htons(port);

	    if(connect(skt, (struct sockaddr *) &passive, sizeof(passive)) < 0) 
	    {
	        printf("Connect error ... restart\n");
	        printf("(Nobody is listening to you on port %d)\n",port);
	        exit(1);
	    }
			
	    system("clear");
	    printf("Connection successful to host %s\n",serverHostName);
	      /* create two communication threads so that we can send and receive concurrently */
	    pthread_create(&tid1, NULL, (void*(*)(void*))sendMessage, NULL);
	    pthread_create(&tid2, NULL, (void*(*)(void*))receiveMessage, NULL);
	    pthread_join(tid1, NULL);
	    pthread_join(tid2, NULL);
	    close(skt);
	    break;
		
	default:
	    break;
	}
    printf("The client is now closing down\n\n");
    return 0;
}

int menu()
{
    int choice;
    system("clear");
    printf("\n\n");
    printf("  Welcome to the pjTalk instant messenger program...\n\n");
    printf("	Select an option below:\n\n");
    printf("	    [ 1 ] Listen for connection\n");
    printf("	    [ 2 ] Connect to client\n");
    printf("	    [ 3 ] Exit\n");
    scanf("%i", &choice);
    return choice;
}

void sendMessage()
{
    while(GLOBALKILL != 1)
    {
	fgets(sendText, sizeof(sendText), stdin);
	buflen = strlen(sendText) + 1;
	if (strcmp(sendText, exitstring) == 0)
	{
	    GLOBALKILL = 1;
	    write(skt, sendText, buflen);
	    break;
	}
	write(skt, sendText, buflen);
    }
    return;
}

void receiveMessage()
{
    while(GLOBALKILL != 1)
    {
	read(skt, receiveText, MAX_MESSAGE_SIZE);
	printf("> %s\n", receiveText); 
	if (strcmp(receiveText, exitstring) == 0)
	{
	    GLOBALKILL = 1;
	    break;
	}
    }
    return;
}

