/* GNet - Networking library
* Copyright (C) 2000-2002 David Helder
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library 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
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
* License along with this library; if not, write to the
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
*/
#include <memory.h>
#include "gnet-private.h"
#include "server.h"
static void server_accept_cb (GTcpSocket* server_socket, GTcpSocket* client, gpointer data);
/**
* gnet_server_new:
* @iface: interface to bind to (NULL for all interfaces)
* @port: port to bind to (0 for an arbitrary port)
* @func: callback to call when a connection is accepted
* @user_data: data to pass to callback
*
* Creates a new #GServer object representing a server. Usually,
* @iface is set to NULL to bind to all interfaces and @port is a
* specific number. The callback is called whenever a new connection
* arrives or if there is a server error. The callback is not called
* again after a server error.
*
* Returns: a new #GServer.
*
**/
GServer*
gnet_server_new (const GInetAddr* iface, gint port,
GServerFunc func, gpointer user_data)
{
GTcpSocket* socket;
GServer* server = NULL;
g_return_val_if_fail (func, NULL);
socket = gnet_tcp_socket_server_new_full (iface, port);
if (!socket)
return NULL;
server = g_new0 (GServer, 1);
server->ref_count = 1;
server->func = func;
server->user_data = user_data;
server->socket = socket;
server->iface = gnet_tcp_socket_get_local_inetaddr (server->socket);
server->port = gnet_tcp_socket_get_port (server->socket);
/* Wait for new connections */
gnet_tcp_socket_server_accept_async (server->socket,
server_accept_cb, server);
return server;
}
/**
* gnet_server_delete:
* @server: #GServer to delete.
*
* Closes and deletes a #GServer.
*
**/
void
gnet_server_delete (GServer* server)
{
if (server != NULL)
gnet_server_unref (server);
}
/**
* gnet_server_ref
* @server: a #GServer
*
* Adds a reference to a #GServer.
*
**/
void
gnet_server_ref (GServer* server)
{
g_return_if_fail (server);
server->ref_count++;
}
/**
* gnet_server_unref
* @server: a #GServer
*
* Removes a reference from a #GServer. A #GServer is deleted when
* the reference count reaches 0.
*
**/
void
gnet_server_unref (GServer* server)
{
server->ref_count--;
if (server->ref_count > 0)
return;
if (server->socket)
gnet_tcp_socket_delete (server->socket);
if (server->iface)
gnet_inetaddr_delete (server->iface);
g_free (server);
}
static void
server_accept_cb (GTcpSocket* server_socket, GTcpSocket* client, gpointer data)
{
GServer* server = (GServer*) data;
g_return_if_fail (server);
if (client)
{
GConn* conn;
conn = gnet_conn_new_socket (client, NULL, NULL);
(server->func)(server, conn, server->user_data);
}
else
{
gnet_tcp_socket_server_accept_async_cancel (server_socket);
(server->func)(server, NULL, server->user_data);
}
}
syntax highlighted by Code2HTML, v. 0.9.1