package com.tipcj.demos;

import java.math.BigInteger;

import com.tipcj.*;

public class Tipc_Java_Api_Server implements Runnable {

	public TipcConn rdmsd;
	public TipcConn strsd;
	public TipcConn pktsd;

	public TipcConn bind_service(int type, int scope, SocketType sktype, String sk_str) {
		TipcConn srv = new TipcConn(sktype);
		int ret = 0;

		if (srv.GetFd() <= 0) {
			System.out.println("failed to create " + sk_str +" socket");
			return null;
		}

		ret = srv.Bind(type, 0, ~0, scope);
		if (ret != 0) {
			System.err.println("failed to bind " + sk_str + " socket");
			srv.Close();
			return null;
		}

		System.out.println("Bound " + sk_str + " socket " + srv.Sockaddr() + " to " + new TipcServiceRange(type, 0, ~0, scope));
		return srv;
	}

	public void recv_rdm_msg() {
		byte[] msg = new byte[Common.BUF_SIZE];
		TipcAddr cli = new TipcAddr();
		Integer err = new Integer(0);

		int ret = 0;

		ret = rdmsd.Recvfrom(msg, cli, null, err);
		System.out.println("-------------------------------------");
		if (ret <= 0) {
			System.out.println("unexpected message on RDM socket");
			return;
		}

		System.out.println(String.format("Received msg: %s on SOCK_RDM <-- %s", new String(msg), cli));
		System.out.println(String.format("Responding with: %s --> %s", new String("Huh?"), cli));

		ret = rdmsd.Sendto(new String("Huh?").getBytes(), cli);
		if (ret <= 0) {
			System.out.println("Server: failed to send");
		}
		System.out.println("-------------------------------------");
	}

	public int recv_stream_setup() {
		int newsd;
		TipcAddr cli = new TipcAddr();
		byte[] msg = new byte[Common.BUF_SIZE];
		int ret = -1;

		System.out.println("-------------------------------------");

		strsd.Listen(32);
		newsd = strsd.Accept(cli);
		if (newsd <= 0) {
			System.out.println("accept on SOCK_STREAM failed");
			return -1;
		}

		ret = strsd.Recv(newsd, msg, false);
		if (ret <= 0) {
			System.out.println("unexpected message on STREAM socket\n");
			return -1;
		}

		System.out.println(String.format("Received msg: %s on STREAM connection", new String(msg)));
		System.out.println(String.format("SOCK_STREAM connection established --> %s", cli));

		System.out.println(String.format("Responding with: %s", new String("Huh?")));

		ret = strsd.Send(newsd, new String("Huh?").getBytes());
		if (ret <= 0) {
			System.out.println("failed to respond");
			return -1;
		}

		System.out.println("-------------------------------------");
		return newsd;
	}

	public int recv_seqpacket_setup() {
		int newsd;
		TipcAddr cli = new TipcAddr();
		byte[] msg = new byte[Common.BUF_SIZE];
		int ret = -1;

		System.out.println("-------------------------------------");
		pktsd.Listen(32);
		newsd = pktsd.Accept(cli);

		if (newsd <= 0) {
			System.out.println("accept on SOCK_SEQPACKET failed");
			return -1;
		}

		System.out.println(String.format("SOCK_SEQPACKET connection established <-- %s", cli));

		ret = pktsd.Recv(newsd, msg, true);
		if (ret <= 0) {
			System.out.println("unexpected message on SOCK_SEQPACKET socket\n");
			return -1;
		}
		System.out.println(String.format("Received msg: %s on SOCK_SEQPACKET connection", new String(msg)));
		System.out.println(String.format("Responding with: %s", new String("Huh?")));

		ret = pktsd.Send(newsd, new String("Huh?").getBytes());
		if (ret <= 0) {
			System.out.println("failed to respond");
			return -1;
		}

		System.out.println("-------------------------------------");
		return newsd;
	}

	public void run() {
		// TODO Auto-generated method stub
		final int[] fds = new int[] {0, 0};
		final short[] events = new short[] { Poll.EPOLLIN | Poll.EPOLLHUP, Poll.EPOLLIN | Poll.EPOLLHUP };
		final Integer[] revents = new Integer[fds.length];

		while (true) {
			recv_rdm_msg();
			fds[0] = recv_stream_setup();
			fds[1] = recv_seqpacket_setup();
			while (Poll.pollset(fds, events, revents, 3000000) >=0) {
				for (int i = 0; i<fds.length; i++) {
					if ((revents[i] & Poll.EPOLLHUP) != 0) {
						System.out.println("-------------------------------------");
						if (i == 0) {
							System.out.println("SOCK_STREAM Connection hangup");
						} else {
							System.out.println("SOCK_SEQPACKET Connection hangup");
						}
						TipcConn.Close(fds[i]);
					}
				}
				break;
			}
		}
	}

	public Tipc_Java_Api_Server() {
		this.rdmsd = bind_service(Common.RDM_SRV_TYPE, 0, SocketType.SOCK_RDM, "RDM");
		this.strsd = bind_service(Common.STREAM_SRV_TYPE, 0, SocketType.SOCK_STREAM, "STREAM");
		this.pktsd = bind_service(Common.SEQPKT_SRV_TYPE, 0, SocketType.SOCK_SEQPACKET, "SEQPACKET");
	}

	public static void main(String[] args) {
		System.out.println("****** TIPC JAVA API Demo Server Started ******");
		Tipc_Java_Api_Server demo = new Tipc_Java_Api_Server();

		// Looping handle
		demo.run();
		System.out.println("****** TIPC JAVA API Demo Server Finished ******");
	}

}
