/*
 * Copyright (C) 2008-2009, Google Inc. and others
 *
 * This program and the accompanying materials are made available under the
 * terms of the Eclipse Distribution License v. 1.0 which is available at
 * https://www.eclipse.org/org/documents/edl-v10.php.
 *
 * SPDX-License-Identifier: BSD-3-Clause
 */

package org.eclipse.jgit.transport;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.net.ServerSocket;
import java.net.Socket;
import java.net.SocketAddress;
import java.net.SocketException;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.Collection;

import org.eclipse.jgit.annotations.Nullable;
import org.eclipse.jgit.errors.RepositoryNotFoundException;
import org.eclipse.jgit.internal.JGitText;
import org.eclipse.jgit.lib.PersonIdent;
import org.eclipse.jgit.lib.Repository;
import org.eclipse.jgit.storage.pack.PackConfig;
import org.eclipse.jgit.transport.resolver.ReceivePackFactory;
import org.eclipse.jgit.transport.resolver.RepositoryResolver;
import org.eclipse.jgit.transport.resolver.ServiceNotAuthorizedException;
import org.eclipse.jgit.transport.resolver.ServiceNotEnabledException;
import org.eclipse.jgit.transport.resolver.UploadPackFactory;

/**
 * Basic daemon for the anonymous <code>git://</code> transport protocol.
 */
public class Daemon {
	/** 9418: IANA assigned port number for Git. */
	public static final int DEFAULT_PORT = 9418;

	private static final int BACKLOG = 5;

	private InetSocketAddress myAddress;

	private final DaemonService[] services;

	private final ThreadGroup processors;

	private Acceptor acceptThread;

	private int timeout;

	private PackConfig packConfig;

	private volatile RepositoryResolver<DaemonClient> repositoryResolver;

	volatile UploadPackFactory<DaemonClient> uploadPackFactory;

	volatile ReceivePackFactory<DaemonClient> receivePackFactory;

	/**
	 * Configure a daemon to listen on any available network port.
	 */
	public Daemon() {
		this(null);
	}

	/**
	 * Configure a new daemon for the specified network address.
	 *
	 * @param addr
	 *            address to listen for connections on. If null, any available
	 *            port will be chosen on all network interfaces.
	 */
	@SuppressWarnings("unchecked")
	public Daemon(InetSocketAddress addr) {
		myAddress = addr;
		processors = new ThreadGroup("Git-Daemon"); //$NON-NLS-1$

		repositoryResolver = (RepositoryResolver<DaemonClient>) RepositoryResolver.NONE;

		uploadPackFactory = (DaemonClient req, Repository db) -> {
			UploadPack up = new UploadPack(db);
			up.setTimeout(getTimeout());
			up.setPackConfig(getPackConfig());
			return up;
		};

		receivePackFactory = (DaemonClient req, Repository db) -> {
			ReceivePack rp = new ReceivePack(db);

			InetAddress peer = req.getRemoteAddress();
			String host = peer.getCanonicalHostName();
			if (host == null)
				host = peer.getHostAddress();
			String name = "anonymous"; //$NON-NLS-1$
			String email = name + "@" + host; //$NON-NLS-1$
			rp.setRefLogIdent(new PersonIdent(name, email));
			rp.setTimeout(getTimeout());

			return rp;
		};

		services = new DaemonService[] {
				new DaemonService("upload-pack", "uploadpack") { //$NON-NLS-1$ //$NON-NLS-2$
					{
						setEnabled(true);
					}

					@Override
					protected void execute(final DaemonClient dc,
							final Repository db,
							@Nullable Collection<String> extraParameters)
							throws IOException,
							ServiceNotEnabledException,
							ServiceNotAuthorizedException {
						UploadPack up = uploadPackFactory.create(dc, db);
						InputStream in = dc.getInputStream();
						OutputStream out = dc.getOutputStream();
						if (extraParameters != null) {
							up.setExtraParameters(extraParameters);
						}
						up.upload(in, out, null);
					}
				}, new DaemonService("receive-pack", "receivepack") { //$NON-NLS-1$ //$NON-NLS-2$
					{
						setEnabled(false);
					}

					@Override
					protected void execute(final DaemonClient dc,
							final Repository db,
							@Nullable Collection<String> extraParameters)
							throws IOException,
							ServiceNotEnabledException,
							ServiceNotAuthorizedException {
						ReceivePack rp = receivePackFactory.create(dc, db);
						InputStream in = dc.getInputStream();
						OutputStream out = dc.getOutputStream();
						rp.receive(in, out, null);
					}
				} };
	}

	/**
	 * Get the address connections are received on.
	 *
	 * @return the address connections are received on.
	 */
	public synchronized InetSocketAddress getAddress() {
		return myAddress;
	}

	/**
	 * Lookup a supported service so it can be reconfigured.
	 *
	 * @param name
	 *            name of the service; e.g. "receive-pack"/"git-receive-pack" or
	 *            "upload-pack"/"git-upload-pack".
	 * @return the service; null if this daemon implementation doesn't support
	 *         the requested service type.
	 */
	public synchronized DaemonService getService(String name) {
		if (!name.startsWith("git-")) //$NON-NLS-1$
			name = "git-" + name; //$NON-NLS-1$
		for (DaemonService s : services) {
			if (s.getCommandName().equals(name))
				return s;
		}
		return null;
	}

	/**
	 * Get timeout (in seconds) before aborting an IO operation.
	 *
	 * @return timeout (in seconds) before aborting an IO operation.
	 */
	public int getTimeout() {
		return timeout;
	}

	/**
	 * Set the timeout before willing to abort an IO call.
	 *
	 * @param seconds
	 *            number of seconds to wait (with no data transfer occurring)
	 *            before aborting an IO read or write operation with the
	 *            connected client.
	 */
	public void setTimeout(int seconds) {
		timeout = seconds;
	}

	/**
	 * Get configuration controlling packing, may be null.
	 *
	 * @return configuration controlling packing, may be null.
	 */
	public PackConfig getPackConfig() {
		return packConfig;
	}

	/**
	 * Set the configuration used by the pack generator.
	 *
	 * @param pc
	 *            configuration controlling packing parameters. If null the
	 *            source repository's settings will be used.
	 */
	public void setPackConfig(PackConfig pc) {
		this.packConfig = pc;
	}

	/**
	 * Set the resolver used to locate a repository by name.
	 *
	 * @param resolver
	 *            the resolver instance.
	 */
	public void setRepositoryResolver(RepositoryResolver<DaemonClient> resolver) {
		repositoryResolver = resolver;
	}

	/**
	 * Set the factory to construct and configure per-request UploadPack.
	 *
	 * @param factory
	 *            the factory. If null upload-pack is disabled.
	 */
	@SuppressWarnings("unchecked")
	public void setUploadPackFactory(UploadPackFactory<DaemonClient> factory) {
		if (factory != null)
			uploadPackFactory = factory;
		else
			uploadPackFactory = (UploadPackFactory<DaemonClient>) UploadPackFactory.DISABLED;
	}

	/**
	 * Get the factory used to construct per-request ReceivePack.
	 *
	 * @return the factory.
	 * @since 4.3
	 */
	public ReceivePackFactory<DaemonClient> getReceivePackFactory() {
		return receivePackFactory;
	}

	/**
	 * Set the factory to construct and configure per-request ReceivePack.
	 *
	 * @param factory
	 *            the factory. If null receive-pack is disabled.
	 */
	@SuppressWarnings("unchecked")
	public void setReceivePackFactory(ReceivePackFactory<DaemonClient> factory) {
		if (factory != null)
			receivePackFactory = factory;
		else
			receivePackFactory = (ReceivePackFactory<DaemonClient>) ReceivePackFactory.DISABLED;
	}

	private class Acceptor extends Thread {

		private final ServerSocket listenSocket;

		private final AtomicBoolean running = new AtomicBoolean(true);

		public Acceptor(ThreadGroup group, String name, ServerSocket socket) {
			super(group, name);
			this.listenSocket = socket;
		}

		@Override
		public void run() {
			setUncaughtExceptionHandler((thread, throwable) -> terminate());
			while (isRunning()) {
				try {
					startClient(listenSocket.accept());
				} catch (SocketException e) {
					// Test again to see if we should keep accepting.
				} catch (IOException e) {
					break;
				}
			}

			terminate();
		}

		private void terminate() {
			try {
				shutDown();
			} finally {
				clearThread();
			}
		}

		public boolean isRunning() {
			return running.get();
		}

		public void shutDown() {
			running.set(false);
			try {
				listenSocket.close();
			} catch (IOException err) {
				//
			}
		}

	}

	/**
	 * Start this daemon on a background thread.
	 *
	 * @throws java.io.IOException
	 *             the server socket could not be opened.
	 * @throws java.lang.IllegalStateException
	 *             the daemon is already running.
	 */
	public synchronized void start() throws IOException {
		if (acceptThread != null) {
			throw new IllegalStateException(JGitText.get().daemonAlreadyRunning);
		}
		ServerSocket socket = new ServerSocket();
		socket.setReuseAddress(true);
		if (myAddress != null) {
			socket.bind(myAddress, BACKLOG);
		} else {
			socket.bind(new InetSocketAddress((InetAddress) null, 0), BACKLOG);
		}
		myAddress = (InetSocketAddress) socket.getLocalSocketAddress();

		acceptThread = new Acceptor(processors, "Git-Daemon-Accept", socket); //$NON-NLS-1$
		acceptThread.start();
	}

	private synchronized void clearThread() {
		acceptThread = null;
	}

	/**
	 * Whether this daemon is receiving connections.
	 *
	 * @return {@code true} if this daemon is receiving connections.
	 */
	public synchronized boolean isRunning() {
		return acceptThread != null && acceptThread.isRunning();
	}

	/**
	 * Stop this daemon.
	 */
	public synchronized void stop() {
		if (acceptThread != null) {
			acceptThread.shutDown();
		}
	}

	/**
	 * Stops this daemon and waits until it's acceptor thread has finished.
	 *
	 * @throws java.lang.InterruptedException
	 *             if waiting for the acceptor thread is interrupted
	 * @since 4.9
	 */
	public void stopAndWait() throws InterruptedException {
		Thread acceptor = null;
		synchronized (this) {
			acceptor = acceptThread;
			stop();
		}
		if (acceptor != null) {
			acceptor.join();
		}
	}

	void startClient(Socket s) {
		final DaemonClient dc = new DaemonClient(this);

		final SocketAddress peer = s.getRemoteSocketAddress();
		if (peer instanceof InetSocketAddress)
			dc.setRemoteAddress(((InetSocketAddress) peer).getAddress());

		new Thread(processors, "Git-Daemon-Client " + peer.toString()) { //$NON-NLS-1$
			@Override
			public void run() {
				try {
					dc.execute(s);
				} catch (ServiceNotEnabledException e) {
					// Ignored. Client cannot use this repository.
				} catch (ServiceNotAuthorizedException e) {
					// Ignored. Client cannot use this repository.
				} catch (IOException e) {
					// Ignore unexpected IO exceptions from clients
				} finally {
					try {
						s.getInputStream().close();
					} catch (IOException e) {
						// Ignore close exceptions
					}
					try {
						s.getOutputStream().close();
					} catch (IOException e) {
						// Ignore close exceptions
					}
				}
			}
		}.start();
	}

	synchronized DaemonService matchService(String cmd) {
		for (DaemonService d : services) {
			if (d.handles(cmd))
				return d;
		}
		return null;
	}

	Repository openRepository(DaemonClient client, String name)
			throws ServiceMayNotContinueException {
		// Assume any attempt to use \ was by a Windows client
		// and correct to the more typical / used in Git URIs.
		//
		name = name.replace('\\', '/');

		// git://thishost/path should always be name="/path" here
		//
		if (!name.startsWith("/")) //$NON-NLS-1$
			return null;

		try {
			return repositoryResolver.open(client, name.substring(1));
		} catch (RepositoryNotFoundException e) {
			// null signals it "wasn't found", which is all that is suitable
			// for the remote client to know.
			return null;
		} catch (ServiceNotAuthorizedException e) {
			// null signals it "wasn't found", which is all that is suitable
			// for the remote client to know.
			return null;
		} catch (ServiceNotEnabledException e) {
			// null signals it "wasn't found", which is all that is suitable
			// for the remote client to know.
			return null;
		}
	}
}
