/*
*  C Implementation: dateserv
*
* Description: waits for connections and then sends the current date/time
* back to the client.
*
*
* Author: Konrad Rosenbaum <konrad@silmor.de>, (C) 2006
*
* Copyright: See COPYING file that comes with this distribution
*
*/

#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netinet/tcp.h>
#include <netinet/ip.h>
#include <unistd.h>

#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <time.h>
#include <string.h>

void senddate(int hdl)
{
	char*ctm;
	time_t tm;
	int val;
	/*get current date/time*/
	tm=time(0);
	ctm=ctime(&tm);
	/*configure socket - switch off Nagle algorithm
	The Nagle algorithm normally tries to lower network traffic by waiting
	200ms whether there is more data that could be sent in the same packet.
	*/
	val=1;
	setsockopt(hdl,SOL_TCP,TCP_NODELAY,&val,sizeof(val));
	/*send data*/
	write(hdl,ctm,strlen(ctm));
	/*close connection (actually: this makes the kernel flush all buffers 
	and close in the background)*/
	close(hdl);
}

int main(int argc,char**argv)
{
	int port,sock,val;
	char*tmp;
	struct sockaddr_in sa;
	/*check arguments*/
	if(argc!=2){
		fprintf(stderr,"Usage: %s <port>\n",*argv);
		return 1;
	}
	port=strtol(argv[1],&tmp,0);
	if(*tmp!=0 || port<1024 || port>65535){
		fprintf(stderr,"Port must be a number in the range 1024<=x<=65535!\n");
		return 1;
	}
	/*create socket*/
	sock=socket(PF_INET,SOCK_STREAM,0);
	if(sock<0){
		fprintf(stderr,"Failed to retrieve socket: %s\n",strerror(errno));
		return 1;
	}
	/*make sure we can bind (re-use the port even if we just closed the program using it)*/
	val=1;
	setsockopt(sock,SOL_SOCKET,SO_REUSEADDR,&val,sizeof(val));
	/*bind it to port*/
	sa.sin_family=AF_INET;
	sa.sin_addr.s_addr=htonl(INADDR_ANY);
	sa.sin_port=htons(port);
	if(bind(sock,&sa,sizeof(sa))){
		fprintf(stderr,"Failed to bind socket: %s\n",strerror(errno));
		return 1;
	}
	/*make it listen: server socket*/
	if(listen(sock,5)){
		fprintf(stderr,"Cannot turn socket to listen: %s\n",strerror(errno));
		return 1;
	}
	/*endless loop: wait for new connections*/
	for(;;){
		int hdl=accept(sock,0,0);
		if(hdl<0){
			fprintf(stderr,"Ooops. Unable to accept: %s\n",strerror(errno));
			continue;
		}
		senddate(hdl);
	}
	/*never reached*/
	return -1;
}
