/* 
 * 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.
 */
/* posix */
#include <sys/types.h>
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <fcntl.h>
#include <string.h>
#include <errno.h>

/* bsd extensions */
#include <sys/uio.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <sys/un.h>
#include <arpa/inet.h>

#include <sys/plan9_helpers.h>

/* Open a connection on socket FD to peer at ADDR (which LEN bytes long).
   For connectionless socket types, just set the default address to send to
   and the only address from which to accept transmissions.
   Return 0 on success, -1 for errors.  */
int __connect(int fd, __CONST_SOCKADDR_ARG addr, socklen_t alen)
{
	Rock *r;
	int n, nfd;
	char msg[8 + 256 + 1], file[8 + 256 + 1];
	struct sockaddr_in *lip, *rip;
	struct sockaddr_un *runix;
	static int vers;
	int open_flags;

	r = _sock_findrock(fd, 0);
	if (r == 0) {
		errno = ENOTSOCK;
		return -1;
	}
	if (alen > sizeof(r->raddr_stor)) {
		errno = ENAMETOOLONG;
		return -1;
	}
	memmove(&r->raddr, addr.__sockaddr__, alen);

	switch (r->domain) {
	case PF_INET:
		/* UDP sockets are already announced (during bind), so we can't
		 * issue a connect message.  Either connect or announce, not
		 * both.  All sends will later do a sendto, based off the
		 * contents of r->raddr, so we're already done here */
		if (r->stype == SOCK_DGRAM)
			return 0;
		/* whatever .. */
		rip = (struct sockaddr_in *)addr.__sockaddr_in__;
		lip = (struct sockaddr_in *)&r->addr;
		if (lip->sin_port)
			snprintf(msg, sizeof msg, "connect %s!%d%s %d",
				 inet_ntoa(rip->sin_addr), ntohs(rip->sin_port),
				 r->reserved ? "!r" : "", ntohs(lip->sin_port));
		else
			snprintf(msg, sizeof msg, "connect %s!%d%s",
				 inet_ntoa(rip->sin_addr), ntohs(rip->sin_port),
				 r->reserved ? "!r" : "");
		n = write(r->ctl_fd, msg, strlen(msg));
		if (n < 0)
			return -1;
		return 0;
	case PF_UNIX:
		/* null terminate the address */
		if (alen == sizeof(r->raddr))
			alen--;
		*(((char *)&r->raddr) + alen) = 0;

		if (r->other < 0) {
			errno = EINVAL;	//EGREG;
			return -1;
		}

		/* put far end of our pipe in /srv */
		snprintf(msg, sizeof msg, "UD.%d.%d", getpid(), vers++);
		if (_sock_srv(msg, r->other) < 0) {
			r->other = -1;
			return -1;
		}
		r->other = -1;

		/* tell server the /srv file to open */
		runix = (struct sockaddr_un *)&r->raddr;
		_sock_srvname(file, runix->sun_path);
		open_flags = O_RDWR;
		open_flags |= (r->sopts & SOCK_CLOEXEC ? O_CLOEXEC : 0);
		nfd = open(file, open_flags);
		if (nfd < 0) {
			unlink(msg);
			return -1;
		}
		if (write(nfd, msg, strlen(msg)) < 0) {
			close(nfd);
			unlink(msg);
			return -1;
		}
		close(nfd);

		/* wait for server to open it and then remove it */
		read(fd, file, sizeof(file));
		_sock_srvname(file, msg);
		unlink(file);
		return 0;
	default:
		errno = EAFNOSUPPORT;
		return -1;
	}
}
weak_alias(__connect, connect)
libc_hidden_def(__connect)
