#include "comn.h"

void UserConnServer();		// user connect to server
void UserDisConnServer();	// user disconnect to server
void MatchUserChat();		// users matching chat
void ServerStop();		// server stop

void setSignal();

int main(int argc, char* argv[]) {
	printf("\n [ server process ]\n");
	// regist signal(user conn, user disconn, server stop, chat)
	setSignal();
	if (strcmp(argv[0], "start") == 0) {
		shmid = shmget((key_t)0301, sizeof(shData), IPC_CREAT | 0666);
		printf("shmid :: %d\n", shmid);
		if (shmid == -1) {
			printf("### shmget fail ###\n");
			exit(1);
		}

		shmaddr = shmat(shmid, (void*)0, 0);
		if (shmaddr == (void*)-1) {
			printf("### shmat fail ###\n");
			exit(1);
		}

		shData = (struct SharedData*)shmaddr;

		shData->pid = getpid();

		if(shData == NULL) {
			printf("### start server. shData NULL ###\n");
		}

		int i = 0;
		for (i = 0; i < MAX_USER_CNT; i++) {
			shData->client[i].pid = 0;
			memset(shData->client[i].name, 0, sizeof(shData->client[i].name));
		}

		printf("========================\n");
		printf("\tServer Start\n");
		printf("========================\n");

		while (1) {
			while (1) {
				if (info.shm_nattch == 3) {
					break;
				}

				if (shmctl(shmid, IPC_STAT, &info) == -1) {
					printf("### shmctl fail ###");
					exit(1);
				}

				sleep(1);
			}

			MatchUserChat();

			while (1) {
				if (shmctl(shmid, IPC_STAT, &info) == -1) {
					printf("### shmctl fail ###");
					exit(1);
				}

				// waiting
				if (info.shm_nattch < 3) {
					break;
				}

				sleep(1);
			}
		}

	}
	return 0;
}

void UserConnServer() {
	printf("\n==================================\n");
	if (shData->client[1].pid != 0) {
		printf("Connect Success : %s [%d]\n", shData->client[1].name, shData->client[1].pid);
	}
	else {
		printf("Connect Success : %s [%d]\n", shData->client[0].name, shData->client[0].pid);
	}
	printf("==================================\n");
}

void MatchUserChat() {
	kill(shData->client[0].pid, SIGUSR1);
	printf("%d %d \n", strlen(shData->client[0].name), strlen(shData->client[1].name));
	printf("%s %s chatting match\n", shData->client[0].name, shData->client[1].name);
	printf("==================================\n");
}

void UserDisConnServer() {
	int i = 0;
	for (i = 0; i < MAX_USER_CNT; i++) {
		if (shData->client[i].pid == -1) {
			printf("DisConnect : %s\n", shData->client[i].name);
			shData->client[i].pid = 0;
			memset(shData->client[i].name, 0, sizeof(shData->client[i].name));

		}
	}
}

void ServerStop() {

	int i = 0;
	for (i = 0; i < MAX_USER_CNT; i++) {
		if (shData->client[i].pid != 0) {
			kill(shData->client[i].pid, SIGINT);
		}
	}

	if (shmdt(shmaddr) == -1) {
		printf("shmdt fail\n");
		exit(1);
	}
	if (shmctl(shmid, IPC_RMID, 0) == -1) {
		printf("shmctl fail\n");
		exit(1);
	}

	printf("========================\n");
	printf("\tServer Stop\n");
	printf("========================\n");
	exit(1);
}

void setSignal() {
	struct sigaction conn_sign;
	struct sigaction disconn_sign;
	struct sigaction server_stop_sign;

	conn_sign.sa_handler = UserConnServer;
	sigemptyset(&conn_sign.sa_mask);
	conn_sign.sa_flags = 0;
	sigaction(SIGUSR1, &conn_sign, NULL);

	disconn_sign.sa_handler = UserDisConnServer;
	sigemptyset(&disconn_sign.sa_mask);
	disconn_sign.sa_flags = 0;
	sigaction(SIGALRM, &disconn_sign, NULL);

	server_stop_sign.sa_handler = ServerStop;
	sigemptyset(&server_stop_sign.sa_mask);
	server_stop_sign.sa_flags = 0;
	sigaction(SIGINT, &server_stop_sign, NULL);
}
