Logo Search packages:      
Sourcecode: fair version File versions  Download package

conn.c

/******************************************************************************

      conn.c -- create outgoing network connections
      Copyright (C) 2004  Wessel Dankers <wsl@uvt.nl>

      This program is free software; you can redistribute it and/or modify
      it under the terms of the GNU General Public License as published by
      the Free Software Foundation; either version 2 of the License, or
      (at your option) any later version.

      This program is distributed in the hope that it will be useful,
      but WITHOUT ANY WARRANTY; without even the implied warranty of
      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      GNU General Public License for more details.

      You should have received a copy of the GNU General Public License
      along with this program; if not, write to the Free Software
      Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA

      $Id: conn.c 23144 2007-12-21 15:36:48Z wsl $
      $URL: https://infix.uvt.nl/its-id/trunk/sources/fair-0.5.1/src/conn.c $

******************************************************************************/

#include <stdio.h>
#include <string.h>
#include <errno.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/socket.h>

#include "fair.h"
#include "error.h"
#include "fd.h"

#include "conn.h"

static int ptrcmp(byte *a, byte *b) {
      return a - b;
}

static avl_tree_t connectors = {NULL, NULL, NULL, (avl_compare_t)ptrcmp, NULL};

unsigned int connector_count(void) {
      return avl_count(&connectors);
}

static connector_t *connector_alloc(connect_hook_t func, void *data) {
      connector_t *cn;
      cn = xalloc(sizeof *cn);
      cn->func = func;
      cn->data = data;
      avl_init_node(&cn->node, cn);
      avl_insert_node(&connectors, &cn->node);
      return cn;
}

void connector_delete(connector_t *cn) {
      unless(cn) return;
      avl_unlink_node(&connectors, &cn->node);
      if(cn->fd)
            fd_close(cn->fd);
      free(cn);
}

static void connector_event(fd_t *fd, fd_event_t evt) {
      int r;
      socklen_t rlen = sizeof r;
      connector_t *cn;

      unless(fd) return;
      cn = fd->wdata;
      unless(cn) return;
      
      if(evt != FD_EVENT_WRITE)
            return;

      if(getsockopt(fd->fd, SOL_SOCKET, SO_ERROR, &r, &rlen)) {
            r = errno;
            syslog(LOG_ERR, "Internal error: getsockopt(): %m");
      }
      if(r == EINPROGRESS)
            return;
      fd_write(fd, NULL, NULL);
      if(r)
            fd = NULL;
      else
            cn->fd = NULL;
      errno = r;
      if(cn->func)
            cn->func(cn, fd);
}

connector_t *connector_new(const address_t *addr, connect_hook_t func, void *data) {
      int f;
      connector_t *cn;
      const struct sockaddr *sa;

      unless(addr) return errno = EINVAL, NULL;

      sa = (const struct sockaddr *)(addr + 1);

      f = socket(sa->sa_family, SOCK_STREAM, 0);
      if(f == -1)
            return syslog(LOG_ERR, "Creating socket(SOCK_STREAM): %m"), NULL;

      cn = connector_alloc(func, data);
      assert(cn);

      connect(f, sa, addr->len);

      cn->fd = fd_new(f);
      assert(cn->fd);
      fd_write(cn->fd, connector_event, cn);

      return cn;
}

Generated by  Doxygen 1.6.0   Back to index