/*
* Copyright (c) Likewise Software. All rights Reserved.
*
* This library is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation; either version 2.1 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 Lesser
* General Public License for more details. You should have received a copy
* of the GNU Lesser General Public License along with this program. If
* not, see .
*
* LIKEWISE SOFTWARE MAKES THIS SOFTWARE AVAILABLE UNDER OTHER LICENSING
* TERMS AS WELL. IF YOU HAVE ENTERED INTO A SEPARATE LICENSE AGREEMENT
* WITH LIKEWISE SOFTWARE, THEN YOU MAY ELECT TO USE THE SOFTWARE UNDER THE
* TERMS OF THAT SOFTWARE LICENSE AGREEMENT INSTEAD OF THE TERMS OF THE GNU
* LESSER GENERAL PUBLIC LICENSE, NOTWITHSTANDING THE ABOVE NOTICE. IF YOU
* HAVE QUESTIONS, OR WISH TO REQUEST A COPY OF THE ALTERNATE LICENSING
* TERMS OFFERED BY LIKEWISE SOFTWARE, PLEASE CONTACT LIKEWISE SOFTWARE AT
* license@likewisesoftware.com
*/
/*
* Module Name:
*
* peer-private.h
*
* Abstract:
*
* Multi-threaded peer API (private header)
*
* Authors: Brian Koropoff (bkoropoff@likewisesoftware.com)
*
*/
#ifndef __LWMSG_PEER_PRIVATE_H__
#define __LWMSG_PEER_PRIVATE_H__
#include
#include
#include
#include
#include
#include
#include "context-private.h"
#include "util-private.h"
#include "call-private.h"
#include
#include
#include
#include
#include
typedef enum PeerAssocTaskType
{
PEER_TASK_BEGIN_ACCEPT,
PEER_TASK_FINISH_ACCEPT,
PEER_TASK_BEGIN_CONNECT,
PEER_TASK_FINISH_CONNECT,
PEER_TASK_DISPATCH,
PEER_TASK_BEGIN_CLOSE,
PEER_TASK_FINISH_CLOSE,
PEER_TASK_BEGIN_RESET,
PEER_TASK_FINISH_RESET,
PEER_TASK_DROP
} PeerAssocTaskType;
typedef struct PeerCall
{
LWMsgCall base;
LWMsgRing ring;
struct PeerAssocTask* task;
LWMsgBool is_outgoing;
enum
{
PEER_CALL_NONE = 0x0,
PEER_CALL_DISPATCHED = 0x1,
PEER_CALL_PENDED = 0x2,
PEER_CALL_COMPLETED = 0x4,
PEER_CALL_CANCELLED = 0x8,
PEER_CALL_RELEASED = 0x10
} volatile state;
LWMsgCookie cookie;
LWMsgStatus volatile status;
union
{
struct
{
LWMsgCancelFunction cancel;
void* cancel_data;
LWMsgDispatchSpec* spec;
void* dispatch_data;
LWMsgParams in;
LWMsgParams out;
} incoming;
struct
{
LWMsgCompleteFunction complete;
void* complete_data;
const LWMsgParams* in;
LWMsgParams* out;
} outgoing;
} params;
} PeerCall;
typedef struct PeerListenTask
{
LWMsgPeer* peer;
LWMsgTask* event_task;
LWMsgEndpointType type;
char* endpoint;
mode_t perms;
int fd;
} PeerListenTask;
typedef struct PeerAssocTask
{
LWMsgPeer* peer;
LWMsgTask* event_task;
PeerAssocTaskType type;
LWMsgAssoc* assoc;
LWMsgSession* session;
LWMsgRing calls;
LWMsgMessage incoming_message;
LWMsgMessage outgoing_message;
unsigned incoming:1;
unsigned outgoing:1;
unsigned destroy_outgoing:1;
LWMsgCookie volatile next_cookie;
unsigned int volatile refcount;
LWMsgStatus volatile status;
pthread_mutex_t call_lock;
pthread_cond_t call_event;
} PeerAssocTask;
typedef enum PeerState
{
PEER_STATE_STOPPED = 0,
PEER_STATE_STARTING,
PEER_STATE_STARTED,
PEER_STATE_STOPPING,
PEER_STATE_ERROR
} PeerState;
typedef struct PeerEndpoint
{
LWMsgEndpointType type;
char* endpoint;
mode_t permissions;
int fd;
LWMsgRing ring;
} PeerEndpoint;
struct LWMsgPeer
{
LWMsgErrorContext error;
const LWMsgContext* context;
LWMsgProtocol* protocol;
LWMsgSessionManager* session_manager;
LWMsgTaskManager* task_manager;
size_t max_clients;
size_t max_dispatch;
size_t max_backlog;
struct
{
LWMsgTime message;
LWMsgTime establish;
LWMsgTime idle;
} timeout;
void* dispatch_data;
LWMsgSessionConstructFunction session_construct;
LWMsgSessionDestructFunction session_destruct;
void* session_construct_data;
LWMsgPeerExceptionFunction except;
void* except_data;
struct
{
LWMsgDispatchSpec** vector;
size_t vector_length;
} dispatch;
/* Listen task group */
LWMsgTaskGroup* listen_tasks;
/* Connect task group */
LWMsgTaskGroup* connect_tasks;
LWMsgRing listen_endpoints;
LWMsgRing connect_endpoints;
PeerAssocTask* connect_task;
LWMsgSession* connect_session;
PeerState connect_state;
LWMsgStatus connect_status;
/* Total number of connected clients */
size_t num_clients;
pthread_mutex_t lock;
pthread_cond_t event;
PeerState state;
LWMsgStatus status;
};
#define PEER_RAISE_ERROR(_peer_, _status_, ...) \
RAISE_ERROR((_peer_), (_status_), __VA_ARGS__)
#define PEER_LOCK(_peer_, _lock_) \
do \
{ \
if (!(_lock_)) \
{ \
(_lock_) = 1; \
lwmsg_peer_lock((_peer_)); \
} \
} while (0)
#define PEER_UNLOCK(_peer_, _lock_) \
do \
{ \
if ((_lock_)) \
{ \
(_lock_) = 0; \
lwmsg_peer_unlock((_peer_)); \
} \
} while (0)
#define PEER_CALL(h) ((PeerCall*) (h))
void
lwmsg_peer_lock(
LWMsgPeer* peer
);
void
lwmsg_peer_unlock(
LWMsgPeer* peer
);
LWMsgStatus
lwmsg_peer_assoc_task_new(
LWMsgPeer* peer,
LWMsgTaskGroup* group,
PeerAssocTaskType type,
PeerAssocTask** task
);
LWMsgStatus
lwmsg_peer_assoc_task_new_connect(
LWMsgPeer* peer,
LWMsgAssoc* assoc,
PeerAssocTask** task
);
LWMsgStatus
lwmsg_peer_listen_task_new(
LWMsgPeer* peer,
LWMsgEndpointType type,
const char* endpoint,
mode_t perms,
int fd,
PeerListenTask** task
);
void
lwmsg_peer_listen_task_delete(
PeerListenTask* task
);
void
lwmsg_peer_task_cancel_and_unref(
PeerAssocTask* task
);
void
lwmsg_peer_task_unref(
PeerAssocTask* task
);
void
lwmsg_peer_task_ref(
PeerAssocTask* task
);
LWMsgStatus
lwmsg_peer_task_perform(
LWMsgPeer* peer,
PeerAssocTask* task,
LWMsgBool shutdown,
LWMsgTime* current_time,
LWMsgTime* next_deadline
);
LWMsgStatus
lwmsg_peer_task_prepare_select(
LWMsgPeer* peer,
PeerAssocTask* task,
int* nfds,
fd_set* readset,
fd_set* writeset
);
LWMsgBool
lwmsg_peer_acquire_client_slot(
LWMsgPeer* peer
);
void
lwmsg_peer_release_client_slot(
LWMsgPeer* peer
);
size_t
lwmsg_peer_get_num_clients(
LWMsgPeer* peer
);
void
lwmsg_peer_call_delete(
PeerCall* call
);
LWMsgStatus
lwmsg_peer_call_new(
PeerAssocTask* task,
PeerCall** call
);
LWMsgStatus
lwmsg_peer_call_dispatch_incoming(
PeerCall* call,
LWMsgDispatchSpec* spec,
void* dispatch_data,
LWMsgMessage* incoming_message
);
LWMsgStatus
lwmsg_peer_call_complete_outgoing(
PeerCall* call,
LWMsgMessage* incoming_message
);
LWMsgStatus
lwmsg_peer_call_cancel_incoming(
PeerCall* call
);
#endif