Esempio n. 1
0
static void connection_handler(IOCHAN iochan, int event)
{
    struct connection *co = iochan_getdata(iochan);
    struct client *cl;
    struct host *host = co->host;

    yaz_mutex_enter(host->mutex);
    cl = co->client;
    if (!cl) 
    {
        /* no client associated with it.. We are probably getting
           a closed connection from the target.. Or, perhaps, an unexpected
           package.. We will just close the connection */
        yaz_log(YLOG_LOG, "timeout connection %p event=%d", co, event);
        remove_connection_from_host(co);
        yaz_mutex_leave(host->mutex);
        connection_destroy(co);
    }
    else if (event & EVENT_TIMEOUT)
    {
        if (co->state == Conn_Connecting)
        {
            yaz_log(YLOG_WARN, "%p connect timeout %s", co, client_get_id(cl));

            client_set_state(cl, Client_Error);
            remove_connection_from_host(co);
            yaz_mutex_leave(host->mutex);
            connection_destroy(co);
        }
        else
        {
            yaz_log(YLOG_LOG,  "%p Connection idle timeout %s", co, client_get_id(cl));
            remove_connection_from_host(co);
            yaz_mutex_leave(host->mutex);
            connection_destroy(co);
        }
    }
    else
    {
        yaz_mutex_leave(host->mutex);

        client_lock(cl);
        non_block_events(co);

        ZOOM_connection_fire_event_socket(co->link, event);
        
        non_block_events(co);
        client_unlock(cl);

        if (co->link)
        {
            iochan_setflags(iochan, ZOOM_connection_get_mask(co->link));
            iochan_setfd(iochan, ZOOM_connection_get_socket(co->link));
        }
    }
}
Esempio n. 2
0
/* ==================== server_free() ==================== */ 
void server_free(server_t *server)
{
    /* FIXME */
    exit_server_work_queue(server);

    int i;
    for ( i = 0 ; i < VNODES ; i++ ){
        vnode_t *vnode = server->vnodes[i];
        if ( vnode != NULL ){
            vnode_free(vnode);
            server->vnodes[i] = NULL;
        }
    }

    for ( i = 0 ; i < LOGFILES ; i++ ) {
        logfile_t *logfile = server->logfiles[i];
        if ( logfile != NULL ) {
            logfile_close(logfile);
            logfile_free(logfile);
            server->logfiles[i] = NULL;
        }
    }

    connection_destroy(&server->connection);

    pthread_mutex_destroy(&server->send_pending_lock);
    pthread_cond_destroy(&server->send_pending_cond);

    zfree(server);
}
Esempio n. 3
0
/**
   Load or save all variables
*/
static bool load_or_save_variables_at_path(bool save, const std::string &path)
{
    bool result = false;

    debug(4, L"Open file for %s: '%s'",
          save?"saving":"loading",
          path.c_str());

    /* OK to not use CLO_EXEC here because fishd is single threaded */
    int fd = open(path.c_str(), save?(O_CREAT | O_TRUNC | O_WRONLY):O_RDONLY, 0600);
    if (fd >= 0)
    {
        /* Success */
        result = true;
        connection_t c(fd);

        if (save)
        {
            /* Save to the file */
            write_loop(c.fd, SAVE_MSG, strlen(SAVE_MSG));
            enqueue_all(&c);
        }
        else
        {
            /* Read from the file */
            read_message(&c);
        }

        connection_destroy(&c);
    }
    return result;
}
Esempio n. 4
0
static void
annotation_destroy(Annotation *annotation)
{
  connection_destroy(&annotation->connection);

  text_destroy(annotation->text);
}
Esempio n. 5
0
static void
message_destroy(Message *message)
{
  connection_destroy(&message->connection);

  g_free(message->text);
}
Esempio n. 6
0
static void client_destroy(Client *a_client)
{
    if (a_client) {
        free(a_client->name);
        connection_destroy(a_client->conn);
        free(a_client);
    }
}
Esempio n. 7
0
void remove_client(struct connection *c,int32_t reason)
{	
	HANDLE sock = c->socket;
	if(0 == connection_destroy(&c))
	{
		ReleaseSocketWrapper(sock);
	}
}
Esempio n. 8
0
static void
constraint_destroy(Constraint *constraint)
{
  connection_destroy(&constraint->connection);
  dia_font_unref(constraint->font);
  g_free(constraint->brtext);
  g_free(constraint->text);
}
Esempio n. 9
0
static void
lifeline_destroy(Lifeline *lifeline)
{
  connpointline_destroy(lifeline->southeast);
  connpointline_destroy(lifeline->northwest);
  connpointline_destroy(lifeline->northeast);
  connpointline_destroy(lifeline->southwest);
  connection_destroy(&lifeline->connection);
}
Esempio n. 10
0
static void disconnect_cb(struct btd_device *device, gboolean removal,
				void *user_data)
{
	struct network_conn *nc = user_data;

	info("Network: disconnect %s", nc->peer->path);

	connection_destroy(NULL, user_data);
}
Esempio n. 11
0
void connect_resolver_host(struct host *host, iochan_man_t iochan_man)
{
    struct connection *con;

start:
    yaz_mutex_enter(host->mutex);
    con = host->connections;
    while (con)
    {
        if (con->state == Conn_Closed)
        {
            if (!host->ipport) /* unresolved */
            {
                remove_connection_from_host(con);
                yaz_mutex_leave(host->mutex);
                connection_destroy(con);
                goto start;
                /* start all over .. at some point it will be NULL */
            }
            else if (!con->client)
            {
                remove_connection_from_host(con);
                yaz_mutex_leave(host->mutex);
                connection_destroy(con);
                /* start all over .. at some point it will be NULL */
                goto start;
            }
            else
            {
                yaz_mutex_leave(host->mutex);
                connection_connect(con, iochan_man);
                client_start_search(con->client);
                goto start;
            }
        }
        else
        {
            yaz_log(YLOG_LOG, "connect_resolver_host: state=%d", con->state);
            con = con->next;
        }
    }
    yaz_mutex_leave(host->mutex);
}
Esempio n. 12
0
static void
bus_destroy(Bus *bus)
{
  int i;
  connection_destroy(&bus->connection);
  for (i=0;i<bus->num_handles;i++)
    g_free(bus->handles[i]);
  g_free(bus->handles);
  g_free(bus->parallel_points);
}
Esempio n. 13
0
static void connection_free(struct network_conn *nc)
{
	if (nc->dc_id)
		device_remove_disconnect_watch(nc->peer->device, nc->dc_id);

	connection_destroy(connection, nc);

	g_free(nc);
	nc = NULL;
}
Esempio n. 14
0
int connection_disconnect(struct btd_service *service)
{
	struct network_conn *nc = btd_service_get_user_data(service);

	if (nc->state == DISCONNECTED)
		return 0;

	connection_destroy(NULL, nc);

	return 0;
}
Esempio n. 15
0
static void
implements_destroy(Implements *implements)
{
  connection_destroy(&implements->connection);
  g_free(implements->text);

  if (implements->properties_dialog != NULL) {
    gtk_widget_destroy(implements->properties_dialog->dialog);
    g_free(implements->properties_dialog);
  }
}
Esempio n. 16
0
static void
constraint_destroy(Constraint *constraint)
{
  connection_destroy(&constraint->connection);

  g_free(constraint->text);

  if (constraint->properties_dialog != NULL) {
    gtk_widget_destroy(constraint->properties_dialog->dialog);
    g_free(constraint->properties_dialog);
  }
}
Esempio n. 17
0
/* this user-defined function is called after the user program makes the connection */
static void*
mbtcp_client_open(MHANDLE conp, void *param, unsigned int *timer_interval)
{
	CLNTPRM *p = (CLNTPRM*) param;
	MBTCPHDR *mb;

	printf("tcp_client_open: host (%s) local port (%d)\n", p->host, p->local_port);
	mb = calloc(1, sizeof(MBTCPHDR));
	if (mb == NULL) connection_destroy(conp);

	return mb;
}
Esempio n. 18
0
static DBusMessage *connection_cancel(DBusConnection *conn,
						DBusMessage *msg, void *data)
{
	struct network_conn *nc = data;
	const char *owner = dbus_message_get_sender(nc->msg);
	const char *caller = dbus_message_get_sender(msg);

	if (!g_str_equal(owner, caller))
		return btd_error_not_authorized(msg);

	connection_destroy(conn, nc);

	return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
}
Esempio n. 19
0
/* this user-defined function is called after the server accepts a client connection */
static void*
udp_server_accept_client(MHANDLE conp, void *param, unsigned int *timer_interval)
{
	UDPXPRM *p = (UDPXPRM*) param;
	char *buf = malloc(256);

	(void) timer_interval;

	if (buf==NULL)
		connection_destroy(conp);
	else
		sprintf(buf, "IP %d", p->ip);
	return buf;
}
Esempio n. 20
0
/* this user-defined function is called after the server accepts a client connection */
static void*
mbrtu_slave_open(MHANDLE conp, void *param, unsigned int *timer_interval)
{
	UARTPRM *uart = (UARTPRM*) param;
	char *buf = malloc(256);

	(void) timer_interval;

	if (buf==NULL)
		connection_destroy(conp);
	else
		printf("Port %d\n", uart->port);
	return buf;
}
Esempio n. 21
0
static void connection_free(void *data)
{
	struct network_conn *nc = data;

	if (nc->dc_id)
		device_remove_disconnect_watch(nc->peer->device, nc->dc_id);

	connection_destroy(NULL, nc);

	if (nc->connect)
		dbus_message_unref(nc->connect);

	btd_service_unref(nc->service);
	g_free(nc);
}
Esempio n. 22
0
/**
   Load or save all variables
*/
static void load_or_save( int save)
{
	const wcstring wdir = fishd_get_config();
	char hostname[HOSTNAME_LEN];
	connection_t c;
	int fd;
	
	if (wdir.empty())
		return;
	
	std::string dir = wcs2string( wdir );
	
	gethostname( hostname, HOSTNAME_LEN );
	
    std::string name;
    name.append(dir);
    name.append("/");
    name.append(FILE);
    name.append(hostname);
	
	debug( 4, L"Open file for %s: '%s'", 
		   save?"saving":"loading", 
		   name.c_str() );
	
    /* OK to not use CLO_EXEC here because fishd is single threaded */
	fd = open(name.c_str(), save?(O_CREAT | O_TRUNC | O_WRONLY):O_RDONLY, 0600);
	
	if( fd == -1 )
	{
		debug( 1, L"Could not open load/save file. No previous saves?" );
		wperror( L"open" );
		return;		
	}
	debug( 4, L"File open on fd %d", c.fd );

	connection_init( &c, fd );

	if( save )
	{
		
		write_loop( c.fd, SAVE_MSG, strlen(SAVE_MSG) );
		enqueue_all( &c );
	}
	else
		read_message( &c );

	connection_destroy( &c );	
}
void amqp_connection_destroy(AMQP_CONNECTION_HANDLE conn_handle)
{
    // Codes_SRS_IOTHUBTRANSPORT_AMQP_CONNECTION_09_035: [If `conn_handle` is NULL, amqp_connection_destroy() shall fail and return]
    if (conn_handle != NULL)
    {
        AMQP_CONNECTION_INSTANCE* instance = (AMQP_CONNECTION_INSTANCE*)conn_handle;

        // Codes_SRS_IOTHUBTRANSPORT_AMQP_CONNECTION_09_036: [amqp_connection_destroy() shall destroy `instance->cbs_handle` if set using cbs_destroy()]
        if (instance->cbs_handle != NULL)
        {
            cbs_destroy(instance->cbs_handle);
        }

        // Codes_SRS_IOTHUBTRANSPORT_AMQP_CONNECTION_09_037: [amqp_connection_destroy() shall destroy `instance->session_handle` if set using session_destroy()]
        if (instance->session_handle != NULL)
        {
            session_destroy(instance->session_handle);
        }

        // Codes_SRS_IOTHUBTRANSPORT_AMQP_CONNECTION_09_067: [amqp_connection_destroy() shall destroy `instance->connection_handle` if set using connection_destroy()]
        if (instance->connection_handle != NULL)
        {
            connection_destroy(instance->connection_handle);
        }

        // Codes_SRS_IOTHUBTRANSPORT_AMQP_CONNECTION_09_038: [amqp_connection_destroy() shall destroy `instance->sasl_io` if set using xio_destroy()]
        if (instance->sasl_io != NULL)
        {
            xio_destroy(instance->sasl_io);
        }

        // Codes_SRS_IOTHUBTRANSPORT_AMQP_CONNECTION_09_039: [amqp_connection_destroy() shall destroy `instance->sasl_mechanism` if set using saslmechanism_destroy()]
        if (instance->sasl_mechanism != NULL)
        {
            saslmechanism_destroy(instance->sasl_mechanism);
        }

        // Codes_SRS_IOTHUBTRANSPORT_AMQP_CONNECTION_09_059: [amqp_connection_destroy() shall destroy `instance->iothub_host_fqdn` if set using STRING_delete()]
        if (instance->iothub_fqdn != NULL)
        {
            STRING_delete(instance->iothub_fqdn);
        }

        // Codes_SRS_IOTHUBTRANSPORT_AMQP_CONNECTION_09_040: [amqp_connection_destroy() shall free the memory allocated for the connection instance]
        free(instance);
    }
}
static void channel_destroy(SpiceSession *s, SpiceChannel *channel, gpointer data)
{
	__android_log_write(ANDROID_LOG_INFO, "android-spice", "channel_destroy called");

    spice_connection *conn = data;
    int id;

    g_object_get(channel, "channel-id", &id, NULL);
    if (SPICE_IS_MAIN_CHANNEL(channel)) {
        SPICE_DEBUG("zap main channel");
        conn->main = NULL;
    }

    if (SPICE_IS_DISPLAY_CHANNEL(channel)) {
        if (id >= SPICE_N_ELEMENTS(conn->wins))
            return;
        if (conn->wins[id] == NULL)
            return;
        SPICE_DEBUG("zap display channel (#%d)", id);
        destroy_spice_window(conn->wins[id]);
        conn->wins[id] = NULL;
    }

    if (SPICE_IS_PLAYBACK_CHANNEL(channel)) {
        SPICE_DEBUG("zap audio channel");
    }

    if (SPICE_IS_USBREDIR_CHANNEL(channel)) {
        __android_log_write(ANDROID_LOG_INFO, "android-spice", "Destroyed USB channel.");
        //update_auto_usbredir_sensitive(conn);
    }

    //if (SPICE_IS_PORT_CHANNEL(channel)) {
    //    if (SPICE_PORT_CHANNEL(channel) == stdin_port)
    //        stdin_port = NULL;
    //}
    conn->channels--;
    char buf[100];
    snprintf (buf, 100, "Number of channels: %d", conn->channels);
    __android_log_write(ANDROID_LOG_INFO, "android-spice", buf);
    if (conn->channels > 0) {
        return;
    }

    connection_destroy(conn);
}
Esempio n. 25
0
void remove_client(struct connection *c,int32_t reason)
{
	uint32_t i = 0;
	for(; i < MAX_CLIENT; ++i)
	{
		if(clients[i] == c)
		{
			clients[i] = 0;
			break;
		}
	}	
	HANDLE sock = c->socket;
	if(0 == connection_destroy(&c))
	{
		ReleaseSocketWrapper(sock);
	}
}
Esempio n. 26
0
void env_universal_destroy()
{
    /*
      Go into blocking mode and send all data before exiting
    */
    if (env_universal_server.fd >= 0)
    {
        if (fcntl(env_universal_server.fd, F_SETFL, 0) != 0)
        {
            wperror(L"fcntl");
        }
        try_send_all(&env_universal_server);
    }

    connection_destroy(&env_universal_server);
    env_universal_server.fd =-1;
    s_env_univeral_inited = false;
}
Esempio n. 27
0
File: flow.c Progetto: brunetton/dia
static void
flow_destroy(Flow *flow)
{
  connection_destroy(&flow->connection);
  text_destroy(flow->text) ;
}
Esempio n. 28
0
int main(int argc, char** argv)
{
	int result;

    (void)argc, argv;
	amqpalloc_set_memory_tracing_enabled(true);

	if (platform_init() != 0)
	{
		result = -1;
	}
	else
	{
		XIO_HANDLE sasl_io;
		CONNECTION_HANDLE connection;
		SESSION_HANDLE session;
		LINK_HANDLE link;
		MESSAGE_SENDER_HANDLE message_sender;
		MESSAGE_HANDLE message;

		size_t last_memory_used = 0;

		/* create SASL PLAIN handler */
		SASL_PLAIN_CONFIG sasl_plain_config = { EH_KEY_NAME, EH_KEY, NULL };
		SASL_MECHANISM_HANDLE sasl_mechanism_handle = saslmechanism_create(saslplain_get_interface(), &sasl_plain_config);
		XIO_HANDLE tls_io;

		/* create the TLS IO */
        TLSIO_CONFIG tls_io_config = { EH_HOST, 5671 };
		const IO_INTERFACE_DESCRIPTION* tlsio_interface = platform_get_default_tlsio();
		tls_io = xio_create(tlsio_interface, &tls_io_config);

		/* create the SASL client IO using the TLS IO */
		SASLCLIENTIO_CONFIG sasl_io_config;
        sasl_io_config.underlying_io = tls_io;
        sasl_io_config.sasl_mechanism = sasl_mechanism_handle;
		sasl_io = xio_create(saslclientio_get_interface_description(), &sasl_io_config);

		/* create the connection, session and link */
		connection = connection_create(sasl_io, EH_HOST, "some", NULL, NULL);
		session = session_create(connection, NULL, NULL);
		session_set_incoming_window(session, 2147483647);
		session_set_outgoing_window(session, 65536);

		AMQP_VALUE source = messaging_create_source("ingress");
		AMQP_VALUE target = messaging_create_target("amqps://" EH_HOST "/" EH_NAME);
		link = link_create(session, "sender-link", role_sender, source, target);
		link_set_snd_settle_mode(link, sender_settle_mode_unsettled);
		(void)link_set_max_message_size(link, 65536);

		amqpvalue_destroy(source);
		amqpvalue_destroy(target);

		message = message_create();
		unsigned char hello[] = { 'H', 'e', 'l', 'l', 'o' };
		BINARY_DATA binary_data;
        binary_data.bytes = hello;
        binary_data.length = sizeof(hello);
		message_add_body_amqp_data(message, binary_data);

		/* create a message sender */
		message_sender = messagesender_create(link, NULL, NULL);
		if (messagesender_open(message_sender) == 0)
		{
			uint32_t i;

#if _WIN32
			unsigned long startTime = (unsigned long)GetTickCount64();
#endif

			for (i = 0; i < msg_count; i++)
			{
				(void)messagesender_send(message_sender, message, on_message_send_complete, message);
			}

			message_destroy(message);

			while (true)
			{
				size_t current_memory_used;
				size_t maximum_memory_used;
				connection_dowork(connection);

				current_memory_used = amqpalloc_get_current_memory_used();
				maximum_memory_used = amqpalloc_get_maximum_memory_used();

				if (current_memory_used != last_memory_used)
				{
					(void)printf("Current memory usage:%lu (max:%lu)\r\n", (unsigned long)current_memory_used, (unsigned long)maximum_memory_used);
					last_memory_used = current_memory_used;
				}

				if (sent_messages == msg_count)
				{
					break;
				}
			}

#if _WIN32
			unsigned long endTime = (unsigned long)GetTickCount64();

			(void)printf("Send %zu messages in %lu ms: %.02f msgs/sec\r\n", msg_count, (endTime - startTime), (float)msg_count / ((float)(endTime - startTime) / 1000));
#endif
		}

		messagesender_destroy(message_sender);
		link_destroy(link);
		session_destroy(session);
		connection_destroy(connection);
		xio_destroy(sasl_io);
		xio_destroy(tls_io);
		saslmechanism_destroy(sasl_mechanism_handle);
		platform_deinit();

		(void)printf("Max memory usage:%lu\r\n", (unsigned long)amqpalloc_get_maximum_memory_used());
		(void)printf("Current memory usage:%lu\r\n", (unsigned long)amqpalloc_get_current_memory_used());

		result = 0;
	}

#ifdef _CRTDBG_MAP_ALLOC
	_CrtDumpMemoryLeaks();
#endif

	return result;
}
Esempio n. 29
0
int main(int argc, char** argv)
{
	int result;
	XIO_HANDLE sasl_io = NULL;
	CONNECTION_HANDLE connection = NULL;
	SESSION_HANDLE session = NULL;
	LINK_HANDLE link = NULL;
	MESSAGE_RECEIVER_HANDLE message_receiver = NULL;

	amqpalloc_set_memory_tracing_enabled(true);

	if (platform_init() != 0)
	{
		result = -1;
	}
	else
	{
		size_t last_memory_used = 0;

		/* create SASL plain handler */
		SASL_PLAIN_CONFIG sasl_plain_config = { EH_KEY_NAME, EH_KEY, NULL };
		SASL_MECHANISM_HANDLE sasl_mechanism_handle = saslmechanism_create(saslplain_get_interface(), &sasl_plain_config);
		XIO_HANDLE tls_io;

		/* create the TLS IO */
        TLSIO_CONFIG tls_io_config = { EH_HOST, 5671 };
		const IO_INTERFACE_DESCRIPTION* tlsio_interface = platform_get_default_tlsio();
		tls_io = xio_create(tlsio_interface, &tls_io_config, NULL);

		/* create the SASL client IO using the TLS IO */
		SASLCLIENTIO_CONFIG sasl_io_config = { tls_io, sasl_mechanism_handle };
		sasl_io = xio_create(saslclientio_get_interface_description(), &sasl_io_config, NULL);

		/* create the connection, session and link */
		connection = connection_create(sasl_io, EH_HOST, "whatever", NULL, NULL);
		session = session_create(connection, NULL, NULL);

		/* set incoming window to 100 for the session */
		session_set_incoming_window(session, 100);
		AMQP_VALUE source = messaging_create_source("amqps://" EH_HOST "/ingress/ConsumerGroups/$Default/Partitions/0");
		AMQP_VALUE target = messaging_create_target("ingress-rx");
		link = link_create(session, "receiver-link", role_receiver, source, target);
		link_set_rcv_settle_mode(link, receiver_settle_mode_first);
		amqpvalue_destroy(source);
		amqpvalue_destroy(target);

		/* create a message receiver */
		message_receiver = messagereceiver_create(link, NULL, NULL);
		if ((message_receiver == NULL) ||
			(messagereceiver_open(message_receiver, on_message_received, message_receiver) != 0))
		{
			result = -1;
		}
		else
		{
			while (true)
			{
				size_t current_memory_used;
				size_t maximum_memory_used;
				connection_dowork(connection);

				current_memory_used = amqpalloc_get_current_memory_used();
				maximum_memory_used = amqpalloc_get_maximum_memory_used();

				if (current_memory_used != last_memory_used)
				{
					printf("Current memory usage:%lu (max:%lu)\r\n", (unsigned long)current_memory_used, (unsigned long)maximum_memory_used);
					last_memory_used = current_memory_used;
				}
			}

			result = 0;
		}

		messagereceiver_destroy(message_receiver);
		link_destroy(link);
		session_destroy(session);
		connection_destroy(connection);
		platform_deinit();

		printf("Max memory usage:%lu\r\n", (unsigned long)amqpalloc_get_maximum_memory_used());
		printf("Current memory usage:%lu\r\n", (unsigned long)amqpalloc_get_current_memory_used());

#ifdef _CRTDBG_MAP_ALLOC
		_CrtDumpMemoryLeaks();
#endif
	}

	return result;
}
Esempio n. 30
0
/**
   Main function for fishd
*/
int main( int argc, char ** argv )
{
	int child_socket;
	struct sockaddr_un remote;
	socklen_t t;
	int max_fd;
	int update_count=0;
	
	fd_set read_fd, write_fd;

	set_main_thread();
    setup_fork_guards();
	
	program_name=L"fishd";
	wsetlocale( LC_ALL, L"" );	

	/*
	  Parse options
	*/
	while( 1 )
	{
		static struct option
			long_options[] =
			{
				{
					"help", no_argument, 0, 'h' 
				}
				,
				{
					"version", no_argument, 0, 'v' 
				}
				,
				{ 
					0, 0, 0, 0 
				}
			}
		;
		
		int opt_index = 0;
		
		int opt = getopt_long( argc,
							   argv, 
							   GETOPT_STRING,
							   long_options, 
							   &opt_index );
		
		if( opt == -1 )
			break;
		
		switch( opt )
		{
			case 0:
				break;				

			case 'h':
				print_help( argv[0], 1 );
				exit(0);				
								
			case 'v':
				debug( 0, L"%ls, version %s\n", program_name, PACKAGE_VERSION );
				exit( 0 );				
				
			case '?':
				return 1;
				
		}		
	}
	
	init();
	while(1) 
	{
		connection_t *c;
		int res;

		t = sizeof( remote );		
		
		FD_ZERO( &read_fd );
		FD_ZERO( &write_fd );
		FD_SET( sock, &read_fd );
		max_fd = sock+1;
		for( c=conn; c; c=c->next )
		{
			FD_SET( c->fd, &read_fd );
			max_fd = maxi( max_fd, c->fd+1);
			
			if( ! c->unsent->empty() )
			{
				FD_SET( c->fd, &write_fd );
			}
		}

		while( 1 )
		{
			res=select( max_fd, &read_fd, &write_fd, 0, 0 );

			if( quit )
			{
				save();
				exit(0);
			}
			
			if( res != -1 )
				break;
			
			if( errno != EINTR )
			{
				wperror( L"select" );
				exit(1);
			}
		}
				
		if( FD_ISSET( sock, &read_fd ) )
		{
			if( (child_socket = 
				 accept( sock, 
						 (struct sockaddr *)&remote, 
						 &t) ) == -1) {
				wperror( L"accept" );
				exit(1);
			}
			else
			{
				debug( 4, L"Connected with new child on fd %d", child_socket );

				if( fcntl( child_socket, F_SETFL, O_NONBLOCK ) != 0 )
				{
					wperror( L"fcntl" );
					close( child_socket );		
				}
				else
				{
					connection_t *newc = (connection_t *)malloc( sizeof(connection_t));
					connection_init( newc, child_socket );					
					newc->next = conn;
					send( newc->fd, GREETING, strlen(GREETING), MSG_DONTWAIT );
					enqueue_all( newc );				
					conn=newc;
				}
			}
		}
		
		for( c=conn; c; c=c->next )
		{
			if( FD_ISSET( c->fd, &write_fd ) )
			{
				try_send_all( c );
			}
		}
		
		for( c=conn; c; c=c->next )
		{
			if( FD_ISSET( c->fd, &read_fd ) )
			{
				read_message( c );

				/*
				  Occasionally we save during normal use, so that we
				  won't lose everything on a system crash
				*/
				update_count++;
				if( update_count >= 64 )
				{
					save();
					update_count = 0;
				}
			}
		}
		
		connection_t *prev=0;
		c=conn;
		
		while( c )
		{
			if( c->killme )
			{
				debug( 4, L"Close connection %d", c->fd );

				while( ! c->unsent->empty() )
				{
					message_t *msg = c->unsent->front();
                    c->unsent->pop();
					msg->count--;
					if( !msg->count )
						free( msg );
				}
				
				connection_destroy( c );
				if( prev )
				{
					prev->next=c->next;
				}
				else
				{
					conn=c->next;
				}
				
				free(c);
				
				c=(prev?prev->next:conn);
				
			}
			else
			{
				prev=c;
				c=c->next;
			}
		}

		if( !conn )
		{
			debug( 0, L"No more clients. Quitting" );
			save();			
			env_universal_common_destroy();
			break;
		}		

	}
}