/* minitalk サーバプログラム */
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netdb.h>
#include <netinet/in.h>


int CanIRecv(int fd){ 
	fd_set fdset;
	struct timeval timeout;
	FD_ZERO( &fdset ); 
	FD_SET( fd , &fdset );
	timeout.tv_sec = 0; 
	timeout.tv_usec = 0;
	return select( fd+1 , &fdset , NULL , NULL , &timeout );
}


int main(int argc, char *argv[])
{
	int srv_sock, *sock, port, m, i, j, size;
	struct sockaddr_in srv_addr, cli_addr;
	int addrlen, sendlen, recvlen;
	char buf[256];
	m = 0;
	size = 0;
	/* ポート番号を引数から取得 */
	port = strtol(argv[1], NULL, 10);

	/* ソケットの作成 */
	srv_sock = socket(AF_INET, SOCK_STREAM, 0);
	if (srv_sock < 0) {
		perror("cannot create socket");
		exit(-1);
	}

	/* サーバとしてバインド */
	srv_addr.sin_family = AF_INET;
	srv_addr.sin_port = htons(port);
	srv_addr.sin_addr.s_addr = INADDR_ANY;
	if (bind(srv_sock, (struct sockaddr*)&srv_addr, sizeof(srv_addr)) < 0) {
		perror("bind failed");
		exit(-1);
	}

	/* 待ち受け人数を1人に設定 */
	listen(srv_sock, 1);

	/* 実際の通信 */
	while (feof(stdin) == 0) {

		if(CanIRecv(srv_sock)){
			/* クライアントからの接続を受け付ける */
			addrlen = sizeof(cli_addr);
			sock = (int *)realloc(sock, (size + 1) * sizeof(int) * (m + 1));

			sock[m] = accept(srv_sock, (struct sockaddr*)&cli_addr, &addrlen);
			if (sock[m] == -1) {
				perror("accept failed");
				exit(-1);
			}
			printf("connected\n");
			m++;
		}

		if(CanIRecv(0)){
			/* 標準入力からキーボード入力された文字を読み込む */
			printf("message : ");
			fgets(buf, sizeof(buf), stdin);
			for(i = 0; i <= m; i++){
				/* 読み込んだ文字をソケットに書き込む */
				sendlen = write(sock[m], buf, strlen(buf) + 1);
				if (sendlen < 0) {
					perror("cannot send a message");
				}
			}
		}
			
		if (CanIRecv(sock[m])) {
			/* ソケットからのデータを読み込む */
			for(j = 0; j <= m; j++){
				recvlen = read(sock[m], buf, sizeof(buf));
				if (recvlen <= 0) {
				/* クライアント側が EOF */
					break;
				}
				printf(">> %s", buf);
			}
		}
		
	}
	/* これ以上クライアントを受け付けないので、サーバのソケットを閉じる */
	close(srv_sock);

	close(sock[m]);
}

