/*
** where it all happens
*/
int main(int argc, char **argv)
{
        srand(time(NULL));
        getConfig(argc, argv);

        say ("\n%s (%s): started\n", TITLE, VERSION);

        if (Xgetaddrinfo(DGRAM_NAME, NULL, NULL, &ai) != 0)
                die(-1, "unable to lookup name %s\n", DGRAM_NAME);
        sa = (sockaddr_x*)ai->ai_addr;

        Graph g(sa);
        printf("\n%s\n", g.dag_string().c_str());

        if (threads == 1)
                // just do it
                mainLoop(NULL);
        else {
                pthread_t *clients = (pthread_t*)malloc(threads * sizeof(pthread_t));

                if (!clients)
                        die(-5, "Unable to allocate threads\n");

                for (int i = 0; i < threads; i++) {
                        pthread_create(&clients[i], NULL, mainLoop, NULL);
                }
                for (int i = 0; i < threads; i++) {
                        pthread_join(clients[i], NULL);
                }

                free(clients);
        }

        return 0;
}
Esempio n. 2
0
void echo_dgram()
{
	int sock;
	char buf[XIA_MAXBUF];
	sockaddr_x cdag;
	socklen_t dlen;
	int n;

	say("Datagram service started\n");

	if ((sock = Xsocket(AF_XIA, SOCK_DGRAM, 0)) < 0)
		die(-2, "unable to create the datagram socket\n");

	struct addrinfo *ai;
	if (Xgetaddrinfo(NULL, SID_DGRAM, NULL, &ai) != 0)
		die(-1, "getaddrinfo failure!\n");

	sockaddr_x *sa = (sockaddr_x*)ai->ai_addr;

	Graph g((sockaddr_x*)ai->ai_addr);
	printf("\nDatagram DAG\n%s\n", g.dag_string().c_str());

    if (XregisterName(DGRAM_NAME, sa) < 0 )
    	die(-1, "error registering name: %s\n", DGRAM_NAME);
	say("registered name: \n%s\n", DGRAM_NAME);

	if (Xbind(sock, (sockaddr *)sa, sizeof(sa)) < 0) {
		die(-3, "unable to bind to the dag\n");
	}

	pid_t pid = 0;

	// only need to fork if doing stream echo at the same time
	if (stream == 1)
		pid = fork();

	if (pid == 0) {
		while (1) {
			say("Dgram Server waiting\n");

			dlen = sizeof(cdag);
			memset(buf, 0, sizeof(buf));
			if ((n = Xrecvfrom(sock, buf, sizeof(buf), 0, (struct sockaddr *)&cdag, &dlen)) < 0) {
				warn("Recv error on socket %d, closing connection\n", pid);
				break;
			}

			say("dgram received %d bytes\n", n);

			if ((n = Xsendto(sock, buf, n, 0, (struct sockaddr *)&cdag, dlen)) < 0) {
				warn("%5d send error\n", pid);
				break;
			}

			say("dgram sent %d bytes\n", n);
		}

		Xclose(sock);
	}
}
Esempio n. 3
0
TEST_F(XgetaddrinfoTest, RawHints)
{
	struct addrinfo hints;
	memset(&hints, 0, sizeof(hints));
	hints.ai_socktype = SOCK_RAW;
	ASSERT_NE(Xgetaddrinfo(FULL_NAME, NULL, &hints, &ai), 0);
}
Esempio n. 4
0
//Just registering the service and openning the necessary sockets
int registerReceiver()
{
    int sock;
	say ("\n%s (%s): started\n", TITLE, VERSION);

	// create a socket, and listen for incoming connections
	if ((sock = Xsocket(AF_XIA, SOCK_STREAM, 0)) < 0)
		 die(-1, "Unable to create the listening socket\n");

    // read the localhost AD and HID
    if ( XreadLocalHostAddr(sock, myAD, sizeof(myAD), myHID, sizeof(myHID), my4ID, sizeof(my4ID)) < 0 )
    	die(-1, "Reading localhost address\n");

	struct addrinfo *ai;
    //FIXME: SID is hardcoded
	if (Xgetaddrinfo(NULL, SID, NULL, &ai) != 0)
		die(-1, "getaddrinfo failure!\n");

	sockaddr_x *dag = (sockaddr_x*)ai->ai_addr;
	//FIXME NAME is hard coded
    if (XregisterName(NAME, dag) < 0 )
    	die(-1, "error registering name: %s\n", NAME);

	if (Xbind(sock, (struct sockaddr*)dag, sizeof(dag)) < 0) {
		Xclose(sock);
		 die(-1, "Unable to bind to the dag: %s\n", dag);
	}

	Graph g(dag);
	say("listening on dag: %s\n", g.dag_string().c_str());
  return sock;
  
}
Esempio n. 5
0
TEST_F(XgetaddrinfoTest, Protocol)
{
	struct addrinfo hints;
	memset(&hints, 0, sizeof(hints));
	hints.ai_protocol = 1;
	ASSERT_NE(Xgetaddrinfo(FULL_NAME, NULL, &hints, &ai), 0);
}
Esempio n. 6
0
TEST_F(XgetaddrinfoTest, InvalidFamily)
{
	struct addrinfo hints;
	memset(&hints, 0, sizeof(hints));
	hints.ai_family = AF_INET;
	ASSERT_NE(Xgetaddrinfo(FULL_NAME, NULL, &hints, &ai), 0);
}
Esempio n. 7
0
TEST_F(XgetaddrinfoTest, DgramHints)
{
	struct addrinfo hints;
	memset(&hints, 0, sizeof(hints));
	hints.ai_socktype = SOCK_DGRAM;
	ASSERT_EQ(0, Xgetaddrinfo(FULL_NAME, NULL, &hints, &ai));
}
Esempio n. 8
0
TEST_F(XgetaddrinfoTest, NullNameDagInHints)
{
	struct addrinfo hints;
	memset(&hints, 0, sizeof(hints));
	hints.ai_flags = XAI_DAGHOST;
	ASSERT_NE(Xgetaddrinfo(NULL, NULL, &hints, &ai), 0);
}
Esempio n. 9
0
TEST_F(XgetaddrinfoTest, UnspecFamily)
{
	struct addrinfo hints;
	memset(&hints, 0, sizeof(hints));
	hints.ai_family = AF_UNSPEC;
	ASSERT_EQ(0, Xgetaddrinfo(FULL_NAME, NULL, &hints, &ai));
}
Esempio n. 10
0
TEST_F(XgetaddrinfoTest, ChunkHints)
{
	struct addrinfo hints;
	memset(&hints, 0, sizeof(hints));
	hints.ai_socktype = XSOCK_CHUNK;
	ASSERT_EQ(0, Xgetaddrinfo(FULL_NAME, NULL, &hints, &ai));
}
Esempio n. 11
0
TEST_F(XgetaddrinfoTest, HintsWithNullSid)
{
	struct addrinfo hints;
	memset(&hints, 0, sizeof(hints));
	hints.ai_flags = XAI_XIDSERV;
	ASSERT_NE(Xgetaddrinfo(HOST_NAME, NULL, &hints, &ai), 0);
}
Esempio n. 12
0
TEST_F(XgetaddrinfoTest, CanonNameError)
{
	// can't be set with a NULL name
	struct addrinfo hints;
	memset(&hints, 0, sizeof(hints));
	hints.ai_flags = AI_CANONNAME;
	ASSERT_NE(Xgetaddrinfo(NULL, NULL, &hints, &ai), 0);
}
Esempio n. 13
0
TEST_F(XgetaddrinfoTest, EmptyName)
{
	// FIXME: should this act the same as a NULL name?
	struct addrinfo hints;
	memset(&hints, 0, sizeof(hints));
	hints.ai_flags = XAI_XIDSERV;
	ASSERT_NE(Xgetaddrinfo("", NULL, &hints, &ai), 0);
}
Esempio n. 14
0
TEST_F(XgetaddrinfoTest, HostDag)
{
	sockaddr_x *sa;
	ASSERT_EQ(0, Xgetaddrinfo(HOST_NAME, NULL, NULL, &ai));
	sa = (sockaddr_x*)ai->ai_addr;
	EXPECT_EQ(AF_XIA, sa->sx_family);
	Graph g(sa);
	EXPECT_EQ(2, g.num_nodes());
}
Esempio n. 15
0
TEST_F(XgetaddrinfoTest, LocalAddr)
{
	sockaddr_x *sa;
	ASSERT_EQ(Xgetaddrinfo(NULL, NULL, NULL, &ai), 0);
	sa = (sockaddr_x*)ai->ai_addr;
	Graph g(sa);
	EXPECT_EQ(2, g.num_nodes());
	EXPECT_EQ(g.get_node(0).id_string(), nad->id_string());
	EXPECT_EQ(g.get_node(1).id_string(), nhid->id_string());
}
Esempio n. 16
0
TEST_F(XgetaddrinfoTest, DagInHintsiPlusSid)
{
	struct addrinfo hints;
	sockaddr_x *sa;
	memset(&hints, 0, sizeof(hints));
	hints.ai_flags = XAI_DAGHOST | XAI_XIDSERV;
	ASSERT_EQ(Xgetaddrinfo(hdag, SID, &hints, &ai), 0);
	sa = (sockaddr_x*)ai->ai_addr;
	Graph g(sa);
	EXPECT_EQ(3, g.num_nodes());
}
Esempio n. 17
0
TEST_F(XgetaddrinfoTest, EmptyHints)
{
	struct addrinfo hints;
	sockaddr_x *sa;
	memset(&hints, 0, sizeof(hints));
	ASSERT_EQ(0, Xgetaddrinfo(FULL_NAME, NULL, &hints, &ai));
	sa = (sockaddr_x*)ai->ai_addr;
	EXPECT_EQ(AF_XIA, sa->sx_family);
	Graph g(sa);
	EXPECT_EQ(3, g.num_nodes());
}
Esempio n. 18
0
TEST_F(XgetaddrinfoTest, SidInHints)
{
	struct addrinfo hints;
	sockaddr_x *sa;
	memset(&hints, 0, sizeof(hints));
	hints.ai_flags = XAI_XIDSERV;
	ASSERT_EQ(0, Xgetaddrinfo(HOST_NAME, SID, &hints, &ai));
	sa = (sockaddr_x*)ai->ai_addr;
	EXPECT_EQ(AF_XIA, sa->sx_family);
	Graph g(sa);
	EXPECT_EQ(3, g.num_nodes());
}
Esempio n. 19
0
TEST_F(XgetaddrinfoTest, EmptyHintsPlusSid)
{
	// FIXME: same question as HostPlusSid above
	struct addrinfo hints;
	sockaddr_x *sa;
	memset(&hints, 0, sizeof(hints));
	ASSERT_EQ(0, Xgetaddrinfo(HOST_NAME, SID, &hints, &ai));
	sa = (sockaddr_x*)ai->ai_addr;
	EXPECT_EQ(AF_XIA, sa->sx_family);
	Graph g(sa);
	EXPECT_EQ(3, g.num_nodes());
}
Esempio n. 20
0
TEST_F(XgetaddrinfoTest, HostPlusSid)
{
	// FIXME: should this fail if the hints struct isn't configured?
	sockaddr_x *sa;
	ASSERT_EQ(0, Xgetaddrinfo(HOST_NAME, SID, NULL, &ai));
	sa = (sockaddr_x*)ai->ai_addr;
	EXPECT_EQ(AF_XIA, sa->sx_family);
	Graph g(sa);
	EXPECT_EQ(3, g.num_nodes());
	EXPECT_EQ(g.get_node(0).id_string(), nad->id_string());
	EXPECT_EQ(g.get_node(1).id_string(), nhid->id_string());
	EXPECT_EQ(g.get_node(2).id_string(), nsid->id_string());
}
Esempio n. 21
0
TEST_F(XgetaddrinfoTest, LocalAddrPlusPassive)
{
	struct addrinfo hints;
	sockaddr_x *sa;
	memset(&hints, 0, sizeof(hints));
	hints.ai_flags = AI_PASSIVE;
	ASSERT_EQ(Xgetaddrinfo(NULL, NULL, &hints, &ai), 0);
	sa = (sockaddr_x*)ai->ai_addr;
	Graph g(sa);
	EXPECT_EQ(2, g.num_nodes());
	EXPECT_EQ(g.get_node(0).id_string(), nad->id_string());
	EXPECT_EQ(g.get_node(1).id_string(), nhid->id_string());
}
Esempio n. 22
0
TEST_F(XgetaddrinfoTest, LocalAddrPlusFallback)
{
	struct addrinfo hints;
	sockaddr_x *sa;
	memset(&hints, 0, sizeof(hints));
	hints.ai_flags = XAI_FALLBACK;
	ASSERT_EQ(0, Xgetaddrinfo(NULL, NULL, &hints, &ai));
	sa = (sockaddr_x*)ai->ai_addr;
	Graph g(sa);
	EXPECT_EQ(2, g.num_nodes());
	EXPECT_EQ(g.get_node(0).id_string(), nad->id_string());
	EXPECT_EQ(g.get_node(1).id_string(), nhid->id_string());
}
Esempio n. 23
0
TEST_F(XgetaddrinfoTest, LocalAddrPlusSid)
{
	struct addrinfo hints;
	sockaddr_x *sa;
	memset(&hints, 0, sizeof(hints));
	hints.ai_flags = XAI_XIDSERV;
	ASSERT_EQ(Xgetaddrinfo(NULL, SID, &hints, &ai), 0);
	sa = (sockaddr_x*)ai->ai_addr;
	Graph g(sa);
	EXPECT_EQ(3, g.num_nodes());
	EXPECT_EQ(g.get_node(0).id_string(), nad->id_string());
	EXPECT_EQ(g.get_node(1).id_string(), nhid->id_string());
	EXPECT_EQ(g.get_node(2).id_string(), nsid->id_string());
}
Esempio n. 24
0
int linphone_core_get_local_ip_for(int type, const char *dest, char *result){
	struct addrinfo hints={0};
	struct addrinfo *res=NULL;
	socklen_t s;
	int err;
	hints.ai_flags = AI_PASSIVE;
	hints.ai_family = AF_XIA;
	err=Xgetaddrinfo(NULL, NULL, &hints, &res);
	if (err!=0){
		ms_error("getaddrinfo() error: %s",gai_strerror(err));
		return -1;
	} 
	s=sizeof(sockaddr_x);
	err=Xgetnameinfo(res->ai_addr,s,result,LINPHONE_IPADDR_SIZE,NULL,0,NI_NUMERICHOST);
//	printf("getnameinfo: %s\n", result);
	Xfreeaddrinfo(res);
    return 0;  
}
Esempio n. 25
0
static belle_sip_socket_t create_udp_socket(const char *addr, int port, int *family){
/*	struct addrinfo hints={0}; */
	struct addrinfo *res=NULL;
	int err;
	belle_sip_socket_t sock;
	char portnum[10];
/*	int optval=1; */

	snprintf(portnum,sizeof(portnum),"%i",port);
/*	hints.ai_family=AF_UNSPEC;
	hints.ai_socktype=SOCK_DGRAM;
	hints.ai_protocol=IPPROTO_UDP;
	hints.ai_flags=AI_NUMERICSERV; */
	err=Xgetaddrinfo(addr,NULL,NULL,&res);
	if (err!=0){
		printf("getaddrinfo() failed for %s port %i: %s",addr,port,gai_strerror(err));
		return -1;
	}
	*family=res->ai_family;
/*	sock=Xsocket(res->ai_family,res->ai_socktype,res->ai_protocol); */
	sock=Xsocket(AF_XIA, SOCK_DGRAM, 0);
	if (sock==-1){
		printf("Cannot create UDP socket: %s",belle_sip_get_socket_error_string());
		Xfreeaddrinfo(res);
		return -1;
	}
/*	err = setsockopt(sock, SOL_SOCKET, SO_REUSEADDR,
			(char*)&optval, sizeof (optval)); 
	if (err == -1){
		belle_sip_warning ("Fail to set SIP/UDP address reusable: %s.", belle_sip_get_socket_error_string());
	} */
	
	err=Xbind(sock,res->ai_addr,res->ai_addrlen);
	if (err==-1){
		printf("udp bind() failed for %s port %i: %s",addr,port,belle_sip_get_socket_error_string());
		close_socket(sock);
		Xfreeaddrinfo(res);
		return -1;
	}
	Xfreeaddrinfo(res);
	return sock;
}
Esempio n. 26
0
int parse_hostname_to_addr(const char *server, sockaddr_x *ss, socklen_t *socklen){
/*	struct addrinfo hints,*res=NULL;
	int family = PF_INET;
	int port_int = 3478;
	int ret;
	char port[6];
	char host[NI_MAXHOST];
	char *p1, *p2;
	if ((sscanf(server, "[%64[^]]]:%d", host, &port_int) == 2) || (sscanf(server, "[%64[^]]]", host) == 1)) {
		family = PF_INET6;
	} else {
		p1 = strchr(server, ':');
		p2 = strrchr(server, ':');
		if (p1 && p2 && (p1 != p2)) {
			family = PF_INET6;
			host[NI_MAXHOST-1]='\0';
			strncpy(host, server, sizeof(host) - 1);
		} else if (sscanf(server, "%[^:]:%d", host, &port_int) != 2) {
			host[NI_MAXHOST-1]='\0';
			strncpy(host, server, sizeof(host) - 1);
		}
	}
	snprintf(port, sizeof(port), "%d", port_int);
	memset(&hints,0,sizeof(hints));
	hints.ai_family=family;
	hints.ai_socktype=SOCK_DGRAM;
	hints.ai_protocol=IPPROTO_UDP; */
	int ret;
	struct addrinfo *res=NULL;
	ret=Xgetaddrinfo(server,NULL,NULL,&res);
	if (ret!=0){
/*		ms_error("getaddrinfo() failed for %s:%s : %s",host,port,gai_strerror(ret)); */
		return -1;
	}
	if (!res) return -1;
	memcpy(ss,res->ai_addr,res->ai_addrlen);
	*socklen=res->ai_addrlen;
	Xfreeaddrinfo(res);
	return 0;
}
Esempio n. 27
0
int main(int argc, char **argv)
{
	int sock = -1;
	int peer = -1;
	struct addrinfo hints, *ai;

// FIXME: put signal handlers back into code once Xselect is working
//	signal(SIGINT, handler);
//	signal(SIGTERM, handler);

	configure(argc, argv);
	say("XIA firehose listening on %s\n", name);

	// get our local AD/HID and append the SID to the resultant dag
	memset(&hints, 0, sizeof(hints));
	hints.ai_flags = XAI_XIDSERV;
	int rc = Xgetaddrinfo(NULL, SID, &hints, &ai);
	if (rc != 0)
		die("%s\n", Xgai_strerror(rc));

	sockaddr_x *sa = (sockaddr_x*)ai->ai_addr;
	if ( XregisterName(NAME, sa) < 0)
		die("Unable to register name %s\n", name);

	if ((sock = Xsocket(AF_XIA, SOCK_STREAM, 0)) < 0)
		die("Unable to create socket\n");
	if (Xbind(sock, (struct sockaddr*)sa, sizeof(sockaddr_x)) < 0) {
		Xclose(sock);
		die("Unable to bind to DAG\n");
	}

	while (!timetodie) {

		fd_set fds;
		FD_ZERO(&fds);
		FD_SET(sock, &fds);

		struct timeval tv;
		tv.tv_sec = 2;
		tv.tv_usec = 0;
		if ((rc = Xselect(sock + 1, &fds, NULL, NULL, &tv)) < 0) {
			printf("select failed\n");
			break;
	
		} else if (rc == 0) {
			// timed out, try again
			continue;
	
		} else if (!FD_ISSET(sock, &fds)) {
			// this shouldn't happen!
			printf("something is really wrong, exiting\n");
			break;
		}

		peer = Xaccept(sock, NULL, NULL);
		if (peer < 0) {
			printf("Xaccept failed\n");
			break;
		}

		say("peer connected...\n");
		pid_t pid = fork();

		if (pid == -1) { 
			printf("fork failed\n");
			break;
		}
		else if (pid == 0) {
			process(peer);
			exit(0);
		}
		else {
			// use regular close so we don't rip out the Xsocket state from under the child
			close(peer);
		}
	}

	say("firehose exiting\n");
	Xclose(sock);
	return 0;
}
Esempio n. 28
0
void echo_stream()
{
	int acceptor, sock;

	if (signal(SIGCHLD, reaper) == SIG_ERR) {
		die(-1, "unable to catch SIGCHLD");
	}
	say("Stream service started\n");

	/* Prepare XSSL context and get SID (based on RSA key) */
	XSSL_CTX *ctx = XSSL_CTX_new();
	if (ctx == NULL) {
		die(-5, "Unable to create new XSSL_CTX\n");
	}
	char *SID = SID_from_keypair(ctx->keypair);

	/* Prepare listen socket, binding to generated SID */
	if ((acceptor = Xsocket(AF_XIA, SOCK_STREAM, 0)) < 0)
		die(-2, "unable to create the stream socket\n");

	struct addrinfo *ai;
	if (Xgetaddrinfo(NULL, SID, NULL, &ai) != 0)
		die(-1, "getaddrinfo failure!\n");

	Graph g((sockaddr_x*)ai->ai_addr);

	sockaddr_x *sa = (sockaddr_x*)ai->ai_addr;

	printf("\nStream DAG\n%s\n", g.dag_string().c_str());

    if (XregisterName(STREAM_NAME, sa) < 0 )
    	die(-1, "error registering name: %s\n", STREAM_NAME);
	say("registered name: \n%s\n", STREAM_NAME);

	if (Xbind(acceptor, (struct sockaddr *)sa, sizeof(sockaddr_x)) < 0) {
		die(-3, "unable to bind to the dag\n");
	}

	Xlisten(acceptor, 5);

	while (1) {

		say("Xsock %4d waiting for a new connection.\n", acceptor);
		if ((sock = Xaccept(acceptor, NULL, 0)) < 0) {
			warn("Xsock %d accept failure! error = %d\n", acceptor, errno);
			// FIXME: should we die here instead or try and recover?
			continue;
		}

		say ("Xsock %4d new session\n", sock);

		pid_t pid = fork();

		if (pid == -1) {
			die(-1, "FORK FAILED\n");

		} else if (pid == 0) {
			process(sock, ctx);
			exit(0);

		} else {
			// FIXME: we need to close the socket in the main process or the file
			// descriptor limit will be hit. But if Xclose is called, the connection
			// is torn down in click as well keeping the child process from using it.
			// for now use a regular close to shut it here without affecting the child.
			close(sock);
		}
	}

	Xclose(acceptor);
	XSSL_CTX_free(ctx);
	free(SID);
}
Esempio n. 29
0
int main(int argc, char **argv)
{
	struct addrinfo *ai;
	sockaddr_x *sa;
	int seq = 0;

// FIXME: put signal handlers back into code once Xselect is working
//	signal(SIGINT, handler);
//	signal(SIGTERM, handler);
	getConfig(argc, argv);

	if (Xgetaddrinfo(NAME, NULL, NULL, &ai) < 0)
		die("Unable to lookup address for  %s\n", NAME);
	sa = (sockaddr_x*)ai->ai_addr;

	if ((sock = Xsocket(AF_XIA, SOCK_STREAM, 0)) < 0)
		die("Unable to create a socket\n");

	say("Opening firehose: %s\n", NAME);
	if (Xconnect(sock, (struct sockaddr*)sa, sizeof(sockaddr_x)) < 0) {
		Xclose(sock);
		die("Unable to connect to %s\n", NAME);
	}

	// tell firehose how many packets we expect
	if (Xsend(sock, &fhc, sizeof(fhc), 0) < 0) {
		Xclose(sock);
		die("Unable to send config information to the firehose\n");
	}

	int count = 0;
	char  *buf = (char *)malloc(pktSize);

	while (!timetodie) {
		int n;
		fd_set fds;
		FD_ZERO(&fds);
		FD_SET(sock, &fds);

		struct timeval tv;
		tv.tv_sec = 2;
		tv.tv_usec = 0;

		if ((n = Xselect(sock + 1, &fds, NULL, NULL, &tv)) < 0) {
			printf("select failed\n");
			break;

		} else if (n == 0) {
			printf("recv timeout\n");
			break;
		} else if (!FD_ISSET(sock, &fds)) {
			// this shouldn't happen!
			printf("something is really wrong, exiting\n");
			break;
		}

		int rc = Xrecv(sock, buf, sizeof(buf), 0);
		if (rc < 0)
			die("Receive failure\n");
		memcpy(&seq, buf, sizeof(int));

		say("expecting %d, got %d", count, seq);
		if (count == seq)
			say("\n");
		else
			say(" lost %d\n", seq - count);
		count++;
		if (count == numPkts)
			break;
		if (delay)
			usleep(delay);
	}

	seq++;
	if (count != seq)
		printf("lost %d packets, received %d, expected %d\n", seq - count, count, seq); 
	else
		printf("success!\n");
	Xclose(sock);
}
Esempio n. 30
0
int main()
{
    int sock;
    socklen_t len;
    char buf[XIA_MAXBUF];
	sockaddr_x client;
	time_t now;
	struct tm *t;

    // create a datagram socket
    if ((sock = Xsocket(AF_XIA, SOCK_DGRAM, 0)) < 0) {
		printf("error: unable to create the listening socket.\n");
		exit(1);
	}

	struct addrinfo *ai;
	if (Xgetaddrinfo(NULL, SID0, NULL, &ai) != 0) {
    	printf("error: unable to create source dag.");
		exit(1);
	}

	sockaddr_x *sa = (sockaddr_x*)ai->ai_addr;

    //Register this service name to the name server
    if (XregisterName(SNAME, sa) < 0) {
    	printf("error: unable to register name/dag combo");
		exit(1);
	}

    // bind to the DAG
    if (Xbind(sock, (struct sockaddr*)sa, sizeof(sockaddr_x)) < 0) {
		Xclose(sock);
		printf("error: unable to bind to %s\n", SNAME);
		exit(1);
	}

    while (1) {
		len = sizeof(client);
		if (Xrecvfrom(sock, buf, sizeof(buf), 0, (struct sockaddr*)&client, &len) < 0) {
			printf("error receiving client request\n");
			// assume it's ok, and just keep listening
			continue;
		}

		// we don't care what the client said, so we'll just ignore it

		now = time(NULL);
		t = gmtime(&now);
		strftime(buf, sizeof(buf), "%c %Z", t);
		
		Graph g(&client);
		printf("request from:\n%s\n", g.dag_string().c_str());
			
		//Reply to client
		if (Xsendto(sock, buf, strlen(buf) + 1, 0, (struct sockaddr*)&client, sizeof(client)) < 0)
			printf("error sending time to the client\n");
    }

	Xclose(sock);
    return 0;
}