/*
 * This file is part of the UCB release of Plan 9. It is subject to the license
 * terms in the LICENSE file found in the top-level directory of this
 * distribution and at http://akaros.cs.berkeley.edu/files/Plan9License. No
 * part of the UCB release of Plan 9, including this file, may be copied,
 * modified, propagated, or distributed except according to the terms contained
 * in the LICENSE file.
 */

#include <u.h>
#include <libc.h>

static char *unknown = "???";

static void
getendpoint(char *dir, char *file, char **sysp, char **servp)
{
	int fd, n;
	char buf[128];
	char *sys, *serv;

	sys = serv = 0;

	jehanne_snprint(buf, sizeof buf, "%s/%s", dir, file);
	fd = open(buf, OREAD);
	if(fd >= 0){
		n = read(fd, buf, sizeof(buf)-1);
		if(n>0){
			buf[n-1] = 0;
			serv = jehanne_strchr(buf, '!');
			if(serv){
				*serv++ = 0;
				serv = jehanne_strdup(serv);
			}
			sys = jehanne_strdup(buf);
		}
		close(fd);
	}
	if(serv == 0)
		serv = unknown;
	if(sys == 0)
		sys = unknown;
	*servp = serv;
	*sysp = sys;
}

NetConnInfo*
jehanne_getnetconninfo(const char *dir, int fd)
{
	NetConnInfo *nci;
	char *cp;
	Dir *d;
	char spec[10];
	char path[128];
	char netname[128], *p;

	/* get a directory address via fd */
	if(dir == nil || *dir == 0){
		if(fd2path(fd, path, sizeof(path)) < 0)
			return nil;
		cp = jehanne_strrchr(path, '/');
		if(cp == nil)
			return nil;
		*cp = 0;
		dir = path;
	}

	nci = jehanne_mallocz(sizeof *nci, 1);
	if(nci == nil)
		return nil;

	/* copy connection directory */
	nci->dir = jehanne_strdup(dir);
	if(nci->dir == nil)
		goto err;

	/* get netroot */
	nci->root = jehanne_strdup(dir);
	if(nci->root == nil)
		goto err;
	cp = jehanne_strchr(nci->root+1, '/');
	if(cp == nil)
		goto err;
	*cp = 0;

	/* figure out bind spec */
	d = jehanne_dirstat(nci->dir);
	if(d != nil){
		jehanne_sprint(spec, "#%C%d", d->type, d->dev);
		nci->spec = jehanne_strdup(spec);
	}
	if(nci->spec == nil)
		nci->spec = unknown;
	jehanne_free(d);

	/* get the two end points */
	getendpoint(nci->dir, "local", &nci->lsys, &nci->lserv);
	if(nci->lsys == nil || nci->lserv == nil)
		goto err;
	getendpoint(nci->dir, "remote", &nci->rsys, &nci->rserv);
	if(nci->rsys == nil || nci->rserv == nil)
		goto err;

	jehanne_strecpy(netname, netname+sizeof netname, nci->dir);
	if((p = jehanne_strrchr(netname, '/')) != nil)
		*p = 0;
	if(jehanne_strncmp(netname, "/net/", 5) == 0)
		jehanne_memmove(netname, netname+5, jehanne_strlen(netname+5)+1);
	nci->laddr = jehanne_smprint("%s!%s!%s", netname, nci->lsys, nci->lserv);
	nci->raddr = jehanne_smprint("%s!%s!%s", netname, nci->rsys, nci->rserv);
	if(nci->laddr == nil || nci->raddr == nil)
		goto err;
	return nci;
err:
	jehanne_freenetconninfo(nci);
	return nil;
}

static void
xfree(char *x)
{
	if(x == nil || x == unknown)
		return;
	jehanne_free(x);
}

void
jehanne_freenetconninfo(NetConnInfo *nci)
{
	if(nci == nil)
		return;
	xfree(nci->root);
	xfree(nci->dir);
	xfree(nci->spec);
	xfree(nci->lsys);
	xfree(nci->lserv);
	xfree(nci->rsys);
	xfree(nci->rserv);
	xfree(nci->laddr);
	xfree(nci->raddr);
	jehanne_free(nci);
}
