gecko-dev/extensions/irc/libbs/bsnetwork.c

376 строки
8.4 KiB
C

/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
*
* The contents of this file are subject to the Mozilla Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is Basic Socket Library
*
* The Initial Developer of the Original Code is New Dimensions Consulting,
* Inc. Portions created by New Dimensions Consulting, Inc. are
* Copyright (C) 1999 New Dimenstions Consulting, Inc. All
* Rights Reserved.
*
* Contributor(s):
*
*
* Contributor(s):
* Robert Ginda, rginda@ndcico.com, original author
*/
#include "prtypes.h"
#include "prmem.h"
#include "prlog.h"
#include "bsapi.h"
#include "bsconfig.h"
#include "bspubtd.h"
#include "bserror.h"
#include "bsserver.h"
#include "bsconnection.h"
PR_BEGIN_EXTERN_C
typedef struct BSServerLink BSServerLink;
struct BSServerLink {
PRCList list;
BSServerClass *server;
};
typedef struct BSServerList BSServerList;
BSNetworkClass *
bs_network_new (const char *name)
{
BSNetworkClass *new_network;
new_network = PR_NEW (BSNetworkClass);
if (!new_network)
return PR_FALSE;
new_network->name = PR_Malloc ((strlen (name) + 1) *
sizeof (bschar));
if (!new_network->name)
{
BS_ReportError (BSERR_OUT_OF_MEMORY);
return PR_FALSE;
}
strcpy (new_network->name, name);
new_network->event_queue = bs_queue_new();
if (!new_network->event_queue)
{
BS_ReportError (BSERR_OUT_OF_MEMORY);
return NULL;
}
new_network->events_per_step = BS_EVENTS_PER_STEP_DEFAULT;
new_network->server_count = 0;
PR_INIT_CLIST (&new_network->server_list);
return new_network;
}
void
bs_network_free (BSNetworkClass *network)
{
PRCList *head;
BSServerClass *server;
PR_ASSERT (network);
while (bs_queue_size (network->event_queue) > 0)
bs_queue_pop (network->event_queue, NULL);
bs_queue_free (network->event_queue);
while (!PR_CLIST_IS_EMPTY(&network->server_list))
{
head = PR_LIST_HEAD(&network->server_list);
if (head == &network->server_list)
break;
server = ((BSServerLink *)head)->server;
bs_server_free (server);
PR_REMOVE_AND_INIT_LINK(head);
network->server_count--;
}
PR_ASSERT (network->server_count == 0);
PR_FREEIF (server->hostname);
PR_Free (server);
}
BSServerClass *
bs_network_add_server (BSNetworkClass *network, const char *hostname)
{
BSServerLink *server_link;
server_link = PR_NEW(BSServerLink);
if (!server_link)
return NULL;
server_link->server = bs_server_new (network, hostname);
if (!server_link->server)
{
BS_ReportError (BSERR_OUT_OF_MEMORY);
return NULL;
}
PR_APPEND_LINK ((PRCList *)server_link, &network->server_list);
network->server_count++;
return server_link->server;
}
PRBool
bs_network_enumerate_servers (BSNetworkClass *network,
BSEnumerateCallback *enum_func, void *data)
{
PRCList *link;
BSServerClass *server;
bsuint i = 0;
PR_ASSERT (network);
if (PR_CLIST_IS_EMPTY(&network->server_list))
return PR_TRUE;
link = PR_LIST_HEAD(&network->server_list);
while (link != (PRCList *)network)
{
server = ((BSServerLink *)link)->server;
if (!enum_func (server, data, i++))
break;
link = PR_NEXT_LINK (link);
}
return PR_TRUE;
}
PRBool
bs_network_server_enumerator (void *server, void *event_queue,
bsuint i)
{
bs_server_poll_connections ((BSServerClass *)server,
(BSQueueClass *)event_queue);
return PR_TRUE;
}
PRBool
bs_network_poll_servers (BSNetworkClass *network)
{
bs_network_enumerate_servers (network, bs_network_server_enumerator,
network->event_queue);
return PR_TRUE;
}
BSEventClass *
bs_network_route (BSNetworkClass *network, BSEventClass *event)
{
if ((event->id < BSNETWORK_EVENT_COUNT) &&
(network->callback_table[event->id]))
return network->callback_table[event->id](network, event);
else
return NULL;
}
void
bs_network_step_events (BSNetworkClass *network, bsuint *event_count)
{
bsuint i;
BSEventClass *event;
if (event_count)
*event_count = 0;
for (i = 0; (i < network->events_per_step) &&
(bs_queue_size (network->event_queue) > 0); i++)
{
event = bs_queue_pop (network->event_queue, NULL);
bs_event_route (event, NULL);
if (event_count)
(*event_count)++;
}
}
PRBool
bs_network_set_handler (BSNetworkClass *network, BSNetworkEvent event_type,
BSNetworkEventCallback *handler)
{
PR_ASSERT (network);
network->callback_table[event_type] = handler;
return PR_TRUE;
}
PRBool
bs_network_set_property (BSNetworkClass *network, BSNetworkProperty prop,
bsint type, void *v)
{
PR_ASSERT (network);
switch (prop)
{
case BSPROP_NAME:
if (!BS_CHECK_TYPE (type, BSTYPE_STRING))
{
BS_ReportError (BSERR_PROPERTY_MISMATCH);
return PR_FALSE;
}
BS_ReportError (BSERR_READ_ONLY);
return PR_FALSE;
break;
case BSPROP_EVENTS_PER_STEP:
if (!BS_CHECK_TYPE (type, BSTYPE_UINT))
{
BS_ReportError (BSERR_PROPERTY_MISMATCH);
return PR_FALSE;
}
network->events_per_step = *(bsint *)v;
break;
default:
break;
}
return PR_TRUE;
}
PRBool
bs_network_set_uint_property (BSNetworkClass *network, BSNetworkProperty prop,
bsuint v)
{
return bs_network_set_property (network, prop, BSTYPE_UINT, &v);
}
PRBool
bs_network_set_string_property (BSNetworkClass *network,
BSNetworkProperty prop, bschar *v)
{
return bs_network_set_property (network, prop, BSTYPE_STRING, v);
}
PRBool
bs_network_set_bool_property (BSNetworkClass *network, BSNetworkProperty prop,
PRBool v)
{
return bs_network_set_property (network, prop, BSTYPE_BOOLEAN, &v);
}
PRBool
bs_network_set_object_property (BSNetworkClass *network,
BSNetworkProperty prop, void *v)
{
return bs_network_set_property (network, prop, BSTYPE_OBJECT, v);
}
PRBool
bs_network_get_property (BSNetworkClass *network, BSServerProperty prop,
bsint type, void **v)
{
PR_ASSERT (network);
switch (prop)
{
case BSPROP_NAME:
if (!BS_CHECK_TYPE (type, BSTYPE_STRING))
{
BS_ReportError (BSERR_PROPERTY_MISMATCH);
return PR_FALSE;
}
*(bschar **)v = network->name;
break;
case BSPROP_EVENTS_PER_STEP:
if (!BS_CHECK_TYPE (type, BSTYPE_UINT))
{
BS_ReportError (BSERR_PROPERTY_MISMATCH);
return PR_FALSE;
}
*(bsint *)v = network->events_per_step;
break;
default:
break;
}
return PR_TRUE;
}
PRBool
bs_network_get_uint_property (BSNetworkClass *network, BSNetworkProperty prop,
bsuint *v)
{
return bs_network_set_property (network, prop, BSTYPE_UINT, v);
}
PRBool
bs_network_get_string_property (BSNetworkClass *network,
BSNetworkProperty prop, bschar **v)
{
return bs_network_set_property (network, prop, BSTYPE_STRING, v);
}
PRBool
bs_network_get_bool_property (BSNetworkClass *network, BSNetworkProperty prop,
PRBool *v)
{
return bs_network_set_property (network, prop, BSTYPE_BOOLEAN, v);
}
PRBool
bs_network_get_object_property (BSNetworkClass *network,
BSNetworkProperty prop, BSNetworkClass **v)
{
return bs_network_set_property (network, prop, BSTYPE_OBJECT, v);
}
PR_END_EXTERN_C