//Deian Stefan
//Problem 4 -- im_recv
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <signal.h>
#include <errno.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include "util.h"


int main(int argc, char *argv[]) {
	char buf[512];
	char *pname, *sport,*host_from;
	int sfd,rc,readno;
	unsigned short port;
	unsigned len;
	struct sockaddr_in sock_in,sock_from;
	struct hostent *he;
	rc=readno=0;

	pname=*argv++;
	if(argc<2||argc>2) {
		fprintf(stderr, "Usage: %s port.\n",pname);
		return -1;
	}
	sport=*argv;


	if((sfd=socket(AF_INET,SOCK_DGRAM,0))<0) {
		fprintf(stderr,"Could not create socket: %s\n",
				strerror(errno));
		return -1;
	}

	sock_in.sin_family=AF_INET;
	sock_in.sin_addr.s_addr=INADDR_ANY;
	port=(unsigned short)strtol(sport,0,10);
	sock_in.sin_port=htons(port);
	if(bind(sfd,(struct sockaddr*)&sock_in,sizeof(sock_in))<0) {
		fprintf(stderr,"Could not bind(2): %s\n",strerror(errno));
		close(sfd);
		return -1;
	}

	len=sizeof(sock_from);
	while((readno=recvfrom(sfd,buf,sizeof(buf)-1,0,
			(struct sockaddr*)&sock_from,&len))>0) {
		buf[readno]='\0';
		if(!(host_from=inet_ntoa(sock_from.sin_addr))) {
			fprintf(stderr,"Failed to convert address: %s\n",
					strerror(errno));
			return -1;
		}
		if(!(he=gethostbyaddr((char*)&sock_from.sin_addr.s_addr,
				sizeof(sock_from.sin_addr.s_addr),AF_INET))){
			fprintf(stderr,"gethostbyaddr(3) failed: %s\n",
					hstrerror(h_errno));
			fprintf(stdout,"[%s] unknown: %s\n",host_from,buf);
			rc=-1;
		} else {
			fprintf(stdout,"[%s] %s: %s\n",
					host_from,he->h_name,buf);
		}
	}
	if(readno<=0) {
		fprintf(stderr, "Failed to read from socket: %s\n",
				strerror(errno));
		close(sfd);
		return -1;
	}
	close(sfd);

	return rc;
}

