/* 4m v2.15 (contoport.c)
 * (C) Copyright 1990 by Carrick Sean Casey
 * (C) Copyright 1993 by Scott Chasin and Michaeljon Miller
 *
 * 3-22-93 See file COPYING for copyright information.
 *
 * Remote socket connection
 *
 */

#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>

#ifdef NEEDS_SELECT
# include "select.h"
#endif

#include "../client/ctcp.h"
#include "ipcf.h"
#include "externs.h"
#include "../client/4m.h"
#include "../h/protocol.h"

extern SECURE secure_tab[MAX_XFERS];
extern XFER xfer_tab[MAX_XFERS];
struct in_addr *_getaddress();


extern int printf ();
/* extern void *memset ();  */
extern int close ();
extern int socket();
extern int setsockopt();
extern int bind();
extern int listen();
extern int connect();
extern int getsockname();

int connecttoport(host_name, port_number, flag)
     char *host_name;

#ifdef SOLARIS
     int port_number;
#else
     u_short port_number;
#endif

     int flag;
{
    int s, i;
    struct sockaddr_in saddr;
    struct in_addr *addr;

 /* get the client host inet address */
    if ((addr = _getaddress(host_name)) == 0) {
        fail = "can't lookup server INET address";
        printf("%s\n", fail);
        printf("attempting to lookup %s\n", host_name);
        return (-1);
    }
 /* insert hostname into address */
    memset((char *) &saddr, 0, sizeof(saddr));
    memcpy((char *) &saddr.sin_addr, (char *) addr, 4);

    if (!port_number) {
        struct sockaddr_in localaddr;

        memset(&localaddr, 0, sizeof(struct sockaddr_in));
        if ((s = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
            fail = "makenewport: gethostbyname";
            return (-1);
        }
        setsockopt(s, SOL_SOCKET, ~SO_LINGER, 0, 0);
        setsockopt(s, SOL_SOCKET, SO_REUSEADDR, 0, 0);
        setsockopt(s, SOL_SOCKET, SO_KEEPALIVE, 0, 0);

        localaddr.sin_family = AF_INET;
        localaddr.sin_addr.s_addr = INADDR_ANY;
        localaddr.sin_port = 0;
        if (bind(s, (struct sockaddr *) & localaddr, sizeof(localaddr)) == -1 ||
            (listen(s, 1) == -1)) {
            close(s);
            return (-1);
        }
        port_number = sizeof(localaddr);

#ifdef SOLARIS
        getsockname(s, (struct sockaddr *) & localaddr, &port_number);
#else
        getsockname(s, (struct sockaddr *) & localaddr, &port_number);
#endif

    /* Add this transfer socket to our set */
        for (i = 0; i < MAX_XFERS; i++)
            if (xfer_tab[i].size > 0 && !xfer_tab[i].port)
                break;
        xfer_tab[i].s = s;
        FD_SET(xfer_tab[i].s, &fdset);
        return (xfer_tab[i].s);
    }
 /* fill in socket domain and port number */
    saddr.sin_family = AF_INET;
    saddr.sin_port = htons((u_short) port_number);

 /* create a socket */
    if ((s = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
        fail = "couldn't create socket";
        return (-1);
    }
 /* connect it to the server inet address */
    if (connect(s, (struct sockaddr *) & saddr, sizeof(saddr)) < 0) {
        fail = "couldn't connect to server (not running?)";
        return (-1);
    }
    switch (flag) {
        case 1:
            for (i = 0; i < MAX_XFERS; i++)
                if (xfer_tab[i].size > 0 && port_number == xfer_tab[i].port)
                    break;
            xfer_tab[i].s = s;
            FD_SET(xfer_tab[i].s, &fdset);
            break;

        case 2:
            port_fd = s;
            break;

        case 3:
            for (i = 0; i < MAX_XFERS; i++)
                if (secure_tab[i].port == port_number) {
                   secure_tab[i].s = s;
                   FD_SET(secure_tab[i].s, &fdset);
                   break;
                }
            break;

        default:
            port_fd = s;
            break; 
    }
    return (0);
}
