Commit 5698ad1d authored by lahiker42's avatar lahiker42

rpc impl


git-svn-id: https://protobuf-c.googlecode.com/svn/trunk@114 00440858-1255-0410-a3e6-75ea37f81c3a
parent db15bf48
......@@ -22,6 +22,8 @@ protoc_c_LDADD = \
-lprotoc
libprotobuf_c_la_SOURCES = \
google/protobuf-c/protobuf-c-dispatch.c \
google/protobuf-c/protobuf-c-rpc.c \
google/protobuf-c/protobuf-c.c
noinst_HEADERS = \
......
......@@ -136,7 +136,7 @@
G_STMT_START{ \
type _gsk_last = NULL; \
type _gsk_at = (top); \
gboolean _gsk_last_was_left = FALSE; \
protobuf_c_boolean _gsk_last_was_left = 0; \
collision_node = NULL; \
while (_gsk_at != NULL) \
{ \
......@@ -145,12 +145,12 @@ G_STMT_START{ \
comparator(_gsk_at, (node), _gsk_compare_rv); \
if (_gsk_compare_rv > 0) \
{ \
_gsk_last_was_left = TRUE; \
_gsk_last_was_left = 1; \
_gsk_at = _gsk_at->left; \
} \
else if (_gsk_compare_rv < 0) \
{ \
_gsk_last_was_left = FALSE; \
_gsk_last_was_left = 0; \
_gsk_at = _gsk_at->right; \
} \
else \
......@@ -241,7 +241,7 @@ G_STMT_START{ \
type _gsk_rb_del_x; \
type _gsk_rb_del_y; \
type _gsk_rb_del_nullpar = NULL; /* Used to emulate sentinel nodes */ \
gboolean _gsk_rb_del_fixup; \
protobuf_c_boolean _gsk_rb_del_fixup; \
if (_gsk_rb_del_z->left == NULL || _gsk_rb_del_z->right == NULL) \
_gsk_rb_del_y = _gsk_rb_del_z; \
else \
......@@ -502,7 +502,7 @@ G_STMT_START{ \
#define GSK_RBTREE_NEXT_(top,type,is_red,set_is_red,parent,left,right,comparator, in, out) \
G_STMT_START{ \
type _gsk_next_at = (in); \
g_assert (_gsk_next_at != NULL); \
protobuf_c_assert (_gsk_next_at != NULL); \
if (_gsk_next_at->right != NULL) \
{ \
_gsk_next_at = _gsk_next_at->right; \
......@@ -585,7 +585,7 @@ G_STMT_START{ \
G_STMT_START{ \
type _gsk_last = NULL; \
type _gsk_at = (top); \
gboolean _gsk_last_was_left = FALSE; \
protobuf_c_boolean _gsk_last_was_left = 0; \
collision_node = NULL; \
while (_gsk_at != NULL) \
{ \
......@@ -594,12 +594,12 @@ G_STMT_START{ \
comparator(_gsk_at, (node), _gsk_compare_rv); \
if (_gsk_compare_rv > 0) \
{ \
_gsk_last_was_left = TRUE; \
_gsk_last_was_left = 1; \
_gsk_at = _gsk_at->left; \
} \
else if (_gsk_compare_rv < 0) \
{ \
_gsk_last_was_left = FALSE; \
_gsk_last_was_left = 0; \
_gsk_at = _gsk_at->right; \
} \
else \
......@@ -699,7 +699,7 @@ G_STMT_START{ \
type _gsk_rb_del_x; \
type _gsk_rb_del_y; \
type _gsk_rb_del_nullpar = NULL; /* Used to emulate sentinel nodes */ \
gboolean _gsk_rb_del_fixup; \
protobuf_c_boolean _gsk_rb_del_fixup; \
if (_gsk_rb_del_z->left == NULL || _gsk_rb_del_z->right == NULL) \
_gsk_rb_del_y = _gsk_rb_del_z; \
else \
......
#include <assert.h>
#include <alloca.h>
#include <sys/time.h>
#include <unistd.h>
#include <string.h>
#include <stdio.h>
#include <sys/poll.h>
#include <limits.h>
#include <errno.h>
#include "protobuf-c-dispatch.h"
#include "gskrbtreemacros.h"
#define protobuf_c_assert(condition) assert(condition)
#define ALLOC_WITH_ALLOCATOR(allocator, size) ((allocator)->alloc ((allocator)->allocator_data, (size)))
#define FREE_WITH_ALLOCATOR(allocator, ptr) ((allocator)->free ((allocator)->allocator_data, (ptr)))
#define ALLOC(size) ALLOC_WITH_ALLOCATOR(&protobuf_c_system_allocator, size)
#define FREE(ptr) FREE_WITH_ALLOCATOR(&protobuf_c_system_allocator, ptr)
/* macros that assume you have a ProtobufCAllocator* named
allocator in scope */
#define ALLOC(size) ALLOC_WITH_ALLOCATOR((allocator), size)
#define FREE(ptr) FREE_WITH_ALLOCATOR((allocator), ptr)
typedef struct _Callback Callback;
struct _Callback
......@@ -32,10 +46,17 @@ struct _RealDispatch
size_t fd_map_size; /* number of elements of fd_map */
ProtobufCDispatchTimer *timer_tree;
ProtobufCAllocator *allocator;
ProtobufCDispatchTimer *recycled_timeouts;
ProtobufCDispatchIdle *first_idle, *last_idle;
ProtobufCDispatchIdle *recycled_idles;
};
struct _ProtobufCDispatchTimer
{
RealDispatch *dispatch;
/* the actual timeout time */
unsigned long timeout_secs;
unsigned timeout_usecs;
......@@ -67,7 +88,7 @@ struct _ProtobufCDispatchTimer
TIMERS_COMPARE
/* Create or destroy a Dispatch */
ProtobufCDispatch *protobuf_c_dispatch_new (void)
ProtobufCDispatch *protobuf_c_dispatch_new (ProtobufCAllocator *allocator)
{
RealDispatch *rv = ALLOC (sizeof (RealDispatch));
rv->base.n_changes = 0;
......@@ -86,6 +107,7 @@ void
protobuf_c_dispatch_free(ProtobufCDispatch *dispatch)
{
RealDispatch *d = (RealDispatch *) dispatch;
ProtobufCAllocator *allocator = d->allocator;
FREE (d->base.notifies_desired);
FREE (d->callbacks);
FREE (d->fd_map);
......@@ -98,6 +120,7 @@ enlarge_fd_map (RealDispatch *d,
{
size_t new_size = d->fd_map_size * 2;
FDMap *new_map;
ProtobufCAllocator *allocator = d->allocator;
while (fd >= new_size)
new_size *= 2;
new_map = ALLOC (sizeof (FDMap) * new_size);
......@@ -122,6 +145,7 @@ static unsigned
allocate_notifies_desired_index (RealDispatch *d)
{
unsigned rv = d->base.n_notifies_desired++;
ProtobufCAllocator *allocator = d->allocator;
if (rv == d->notifies_desired_alloced)
{
unsigned new_size = d->notifies_desired_alloced * 2;
......@@ -139,6 +163,7 @@ allocate_change_index (RealDispatch *d)
unsigned rv = d->base.n_changes++;
if (rv == d->changes_alloced)
{
ProtobufCAllocator *allocator = d->allocator;
unsigned new_size = d->changes_alloced * 2;
ProtobufC_FDNotify *n = ALLOC (new_size * sizeof (ProtobufC_FDNotify));
memcpy (n, d->base.changes, d->changes_alloced * sizeof (ProtobufC_FDNotify));
......@@ -153,17 +178,17 @@ deallocate_change_index (RealDispatch *d,
int fd)
{
unsigned ch_ind = d->fd_map[fd].change_index;
unsigned from = d->n_changes - 1;
unsigned from = d->base.n_changes - 1;
unsigned from_fd;
if (ch_ind == from)
{
d->n_changes--;
d->base.n_changes--;
return;
}
from_fd = d->base.changes[ch_ind].fd;
d->fd_map[from_fd].change_index = ch_ind;
d->changes[ch_ind] = d->changes[from];
d->n_changes--;
d->base.changes[ch_ind] = d->base.changes[from];
d->base.n_changes--;
}
static void
......@@ -171,17 +196,17 @@ deallocate_notify_desired_index (RealDispatch *d,
int fd)
{
unsigned nd_ind = d->fd_map[fd].notify_desired_index;
unsigned from = d->n_notifies_desired - 1;
unsigned from = d->base.n_notifies_desired - 1;
unsigned from_fd;
if (nd_ind == from)
{
d->n_notifies_desired--;
d->base.n_notifies_desired--;
return;
}
from_fd = d->base.notifies_desired[nd_ind].fd;
d->fd_map[from_fd].notify_desired_index = nd_ind;
d->notifies_desired[nd_ind] = d->notifies_desired[from];
d->n_notifies_desired--;
d->base.notifies_desired[nd_ind] = d->base.notifies_desired[from];
d->base.n_notifies_desired--;
}
......@@ -195,7 +220,7 @@ protobuf_c_dispatch_watch_fd (ProtobufCDispatch *dispatch,
{
RealDispatch *d = (RealDispatch *) dispatch;
unsigned f = fd; /* avoid tiring compiler warnings: "comparison of signed versus unsigned" */
guint nd_ind, change_ind;
unsigned nd_ind, change_ind;
if (callback == NULL)
assert (events == 0);
else
......@@ -225,8 +250,8 @@ protobuf_c_dispatch_watch_fd (ProtobufCDispatch *dispatch,
d->fd_map[f].change_index = allocate_change_index (d);
change_ind = d->fd_map[f].change_index;
d->base.changes[ch_ind].fd = fd;
d->base.changes[ch_ind].events = events;
d->base.changes[change_ind].fd = fd;
d->base.changes[change_ind].events = events;
d->base.notifies_desired[nd_ind].fd = fd;
d->base.notifies_desired[nd_ind].events = events;
d->callbacks[nd_ind].func = callback;
......@@ -271,6 +296,8 @@ protobuf_c_dispatch_dispatch (ProtobufCDispatch *dispatch,
RealDispatch *d = (RealDispatch *) dispatch;
unsigned fd_max;
unsigned i;
FDMap *fd_map = d->fd_map;
struct timeval tv;
if (n_notifies == 0)
return;
fd_max = 0;
......@@ -296,13 +323,15 @@ protobuf_c_dispatch_dispatch (ProtobufCDispatch *dispatch,
/* handle timers */
gettimeofday (&tv, NULL);
dispatch->last_dispatch_secs = tv.tv_sec;
dispatch->last_dispatch_usecs = tv.tv_usec;
while (d->timer_tree != NULL)
{
ProtobufCDispatchTimer *min_timer;
GSK_RBTREE_FIRST (GET_TIMER_TREE (d), min_timer);
if (min_timer.timeout_secs < tv.tv_secs
|| (min_timer.timeout_secs == tv.tv_secs
&& min_timer.timeout_usecs <= tv.tv_usecs))
if (min_timer->timeout_secs < (unsigned long) tv.tv_sec
|| (min_timer->timeout_secs == (unsigned long) tv.tv_sec
&& min_timer->timeout_usecs <= (unsigned) tv.tv_usec))
{
ProtobufCDispatchTimerFunc func = min_timer->func;
void *func_data = min_timer->func_data;
......@@ -333,18 +362,38 @@ protobuf_c_dispatch_clear_changes (ProtobufCDispatch *dispatch)
unsigned i;
for (i = 0; i < dispatch->n_changes; i++)
{
assert (fd_map[dispatch->changes[i].fd].change_index == (int) i);
fd_map[dispatch->changes[i].fd].change_index = -1;
assert (d->fd_map[dispatch->changes[i].fd].change_index == (int) i);
d->fd_map[dispatch->changes[i].fd].change_index = -1;
}
dispatch->n_changes = 0;
}
static inline unsigned
events_to_pollfd_events (unsigned ev)
{
return ((ev & PROTOBUF_C_EVENT_READABLE) ? POLLIN : 0)
| ((ev & PROTOBUF_C_EVENT_WRITABLE) ? POLLOUT : 0)
;
}
static inline unsigned
pollfd_events_to_events (unsigned ev)
{
return ((ev & POLLIN) ? PROTOBUF_C_EVENT_READABLE : 0)
| ((ev & POLLOUT) ? PROTOBUF_C_EVENT_WRITABLE : 0)
;
}
void
protobuf_c_dispatch_run (ProtobufCDispatch *dispatch)
{
struct pollfd *fds;
void *to_free = NULL;
void *to_free = NULL, *to_free2 = NULL;
size_t n_events;
RealDispatch *d = (RealDispatch *) dispatch;
ProtobufCAllocator *allocator = d->allocator;
unsigned i;
int timeout;
ProtobufC_FDNotify *events;
if (dispatch->n_notifies_desired < 128)
fds = alloca (sizeof (struct pollfd) * dispatch->n_notifies_desired);
else
......@@ -356,10 +405,43 @@ protobuf_c_dispatch_run (ProtobufCDispatch *dispatch)
fds[i].revents = 0;
}
/* compute timeout */
if (d->first_idle != NULL)
timeout = 0;
else if (d->timer_tree == NULL)
timeout = -1;
else
{
ProtobufCDispatchTimer *min_timer;
GSK_RBTREE_FIRST (GET_TIMER_TREE (d), min_timer);
struct timeval tv;
gettimeofday (&tv, NULL);
if (min_timer->timeout_secs < (unsigned long) tv.tv_sec
|| (min_timer->timeout_secs == (unsigned long) tv.tv_sec
&& min_timer->timeout_usecs <= (unsigned) tv.tv_usec))
timeout = 0;
else
{
int du = min_timer->timeout_usecs - tv.tv_usec;
int ds = min_timer->timeout_secs - tv.tv_sec;
if (du < 0)
{
du += 1000000;
ds -= 1;
}
if (ds > INT_MAX / 1000)
timeout = INT_MAX / 1000 * 1000;
else
/* Round up, so that we ensure that something can run
if they just wait the full duration */
timeout = ds * 1000 + (du + 999) / 1000;
}
}
if (poll (fds, dispatch->n_notifies_desired, timeout) < 0)
{
if (errno == EINTR)
return; /* probably a signal interrupted the poll-- let the user have control */
return; /* probably a signal interrupted the poll-- let the user have control */
/* i don't really know what would plausibly cause this */
fprintf (stderr, "error polling: %s\n", strerror (errno));
......@@ -370,9 +452,9 @@ protobuf_c_dispatch_run (ProtobufCDispatch *dispatch)
if (fds[i].revents)
n_events++;
if (n_events < 128)
to_free2 = events = alloca (sizeof (ProtobufC_FDNotify) * n_events);
events = alloca (sizeof (ProtobufC_FDNotify) * n_events);
else
events = ALLOC (sizeof (ProtobufC_FDNotify) * n_events);
to_free2 = events = ALLOC (sizeof (ProtobufC_FDNotify) * n_events);
n_events = 0;
for (i = 0; i < dispatch->n_notifies_desired; i++)
if (fds[i].revents)
......@@ -401,6 +483,8 @@ protobuf_c_dispatch_add_timer(ProtobufCDispatch *dispatch,
void *func_data)
{
RealDispatch *d = (RealDispatch *) dispatch;
ProtobufCDispatchTimer *rv;
ProtobufCDispatchTimer *conflict;
protobuf_c_assert (func != NULL);
if (d->recycled_timeouts != NULL)
{
......@@ -420,6 +504,25 @@ protobuf_c_dispatch_add_timer(ProtobufCDispatch *dispatch,
return rv;
}
ProtobufCDispatchTimer *
protobuf_c_dispatch_add_timer_millis
(ProtobufCDispatch *dispatch,
unsigned millis,
ProtobufCDispatchTimerFunc func,
void *func_data)
{
unsigned tsec = dispatch->last_dispatch_secs;
unsigned tusec = dispatch->last_dispatch_usecs;
tusec += 1000 * (millis % 1000);
tsec += millis / 1000;
if (tusec >= 1000*1000)
{
tusec -= 1000*1000;
tsec += 1;
}
return protobuf_c_dispatch_add_timer (dispatch, tsec, tusec, func, func_data);
}
void protobuf_c_dispatch_remove_timer (ProtobufCDispatchTimer *timer)
{
protobuf_c_boolean may_be_first;
......@@ -442,8 +545,8 @@ void protobuf_c_dispatch_remove_timer (ProtobufCDispatchTimer *timer)
{
ProtobufCDispatchTimer *min;
GSK_RBTREE_FIRST (GET_TIMER_TREE (d), min);
d->timeout_secs = min->timeout_secs;
d->timeout_usecs = min->timeout_usecs;
d->base.timeout_secs = min->timeout_secs;
d->base.timeout_usecs = min->timeout_usecs;
}
}
}
#ifndef __PROTOBUF_C_DISPATCH_H_
#define __PROTOBUF_C_DISPATCH_H_
typedef struct _ProtobufCDispatch ProtobufCDispatch;
typedef struct _ProtobufCDispatchTimer ProtobufCDispatchTimer;
typedef struct _ProtobufCDispatchIdle ProtobufCDispatchIdle;
#include "protobuf-c.h"
typedef enum
{
PROTOBUF_C_EVENT_READABLE = (1<<0),
......@@ -5,7 +14,7 @@ typedef enum
} ProtobufC_Events;
/* Create or destroy a Dispatch */
ProtobufCDispatch *protobuf_c_dispatch_new (ProtobufCAllocator *allocator);
ProtobufCDispatch *protobuf_c_dispatch_new (ProtobufCAllocator *allocator);
void protobuf_c_dispatch_free(ProtobufCDispatch *dispatch);
ProtobufCAllocator *protobuf_c_dispatch_peek_allocator (ProtobufCDispatch *);
......@@ -34,6 +43,12 @@ ProtobufCDispatchTimer *
unsigned timeout_usecs,
ProtobufCDispatchTimerFunc func,
void *func_data);
ProtobufCDispatchTimer *
protobuf_c_dispatch_add_timer_millis
(ProtobufCDispatch *dispatch,
unsigned milliseconds,
ProtobufCDispatchTimerFunc func,
void *func_data);
void protobuf_c_dispatch_remove_timer (ProtobufCDispatchTimer *);
/* Idle functions */
......@@ -56,11 +71,6 @@ void protobuf_c_dispatch_run (ProtobufCDispatch *dispatch);
/* --- API for those who want to embed a dispatch into their own main-loop --- */
void protobuf_c_dispatch_dispatch (ProtobufCDispatch *dispatch,
size_t n_notifies,
ProtobufC_FDNotify *notifies);
void protobuf_c_dispatch_clear_changes (ProtobufCDispatch *);
#ifdef WIN32
typedef SOCKET ProtobufC_FD;
#else
......@@ -72,6 +82,11 @@ typedef struct {
ProtobufC_Events events;
} ProtobufC_FDNotify;
void protobuf_c_dispatch_dispatch (ProtobufCDispatch *dispatch,
size_t n_notifies,
ProtobufC_FDNotify *notifies);
void protobuf_c_dispatch_clear_changes (ProtobufCDispatch *);
struct _ProtobufCDispatch
{
......@@ -92,6 +107,11 @@ struct _ProtobufCDispatch
timeout 0 is appropriate */
protobuf_c_boolean has_idle;
unsigned long last_dispatch_secs;
unsigned last_dispatch_usecs;
/* private data follows */
};
#endif
......@@ -13,6 +13,16 @@ typedef enum
PROTOBUF_C_CLIENT_STATE_FAILED /* if no autoretry */
} ProtobufC_ClientState;
struct _Closure
{
/* these will be NULL for unallocated request ids */
const ProtobufCMessageDescriptor *response_type;
ProtobufCClosure closure;
/* this is the next request id, or 0 for none */
void *closure_data;
};
struct _ProtobufC_RPC_Client
{
ProtobufCService base_service;
......@@ -32,9 +42,18 @@ struct _ProtobufC_RPC_Client
ProtobufCDispatch_Idle *idle;
} init;
struct {
ProtobufCDispatch_Timer *timer;
protobuf_c_boolean pending;
} name_lookup;
struct {
ProtobufCDispatchTimer *timer;
char *error_message;
} failed_waiting;
struct {
unsigned closures_alloced;
unsigned first_free_request_id;
/* indexed by (request_id-1) */
Closure *closures;
} connected;
struct {
char *error_message;
} failed;
......@@ -54,7 +73,59 @@ client_failed (ProtobufC_RPC_Client *client,
const char *format_str,
...)
{
...
va_list args;
switch (client->state)
{
case PROTOBUF_C_CLIENT_STATE_NAME_LOOKUP:
protobuf_c_assert (!client->info.name_lookup.pending);
break;
case PROTOBUF_C_CLIENT_STATE_CONNECTING:
/* nothing to do */
break;
case PROTOBUF_C_CLIENT_STATE_CONNECTED:
/* nothing to do */
break;
/* should not get here */
case PROTOBUF_C_CLIENT_STATE_INIT:
case PROTOBUF_C_CLIENT_STATE_FAILED_WAITING:
case PROTOBUF_C_CLIENT_STATE_FAILED:
protobuf_c_assert (FALSE);
break;
}
if (client->fd >= 0)
{
protobuf_c_dispatch_close (client->dispatch, client->fd);
client->fd = -1;
}
protobuf_c_data_buffer_reset (&client->incoming);
protobuf_c_data_buffer_reset (&client->outgoing);
/* Compute the message */
va_start (args, format_str);
vsnprintf (buf, sizeof (buf), format_str, args);
va_end (args);
buf[sizeof(buf)-1] = 0;
msg_len = strlen (buf);
msg = client->allocator->alloc (client->allocator, msg_len + 1);
strcpy (msg, buf);
/* go to one of the failed states */
if (client->autoretry)
{
client->state = PROTOBUF_C_CLIENT_STATE_FAILED_WAITING;
client->info.failed_waiting.timer
= protobuf_c_dispatch_add_timer_millis (client->dispatch,
client->autoretry_millis,
handle_autoretry_timeout,
client);
client->info.failed_waiting.error_message = msg;
}
else
{
client->state = PROTOBUF_C_CLIENT_STATE_FAILED;
client->info.failed.error_message = msg;
}
}
static void
......@@ -89,17 +160,15 @@ begin_connecting (ProtobufC_RPC_Client *client,
client_failed (client, "error connecting to remote host: %s", strerror (errno));
return;
}
client->state = PROTOBUF_C_CLIENT_STATE_CONNECTED;
if (client->first_outgoing_request != NULL)
{
/* register interest in writing to fd (there can be no pending requests, of course,
since we just connected) */
protobuf_c_dispatch_watch_fd (client->dispatch,
client->fd,
PROTOBUF_C_EVENT_WRITABLE,
handle_connected_client_fd_events,
client);
}
client->info.connected.closures_alloced = 1;
client->info.connected.first_free_request_id = 1;
client->info.connected.closures = client->allocator->alloc (client->allocator, sizeof (Closure));
client->info.connected.closures[0].closure = NULL;
client->info.connected.closures[0].response_type = NULL;
client->info.connected.closures[0].closure_data = UINT_TO_POINTER (0);
}
static void
handle_name_lookup_success (const uint8_t *address,
......@@ -189,6 +258,33 @@ handle_init_idle (ProtobufCDispatch *dispatch,
ProtobufC_RPC_Client *client = data;
}
static void
grow_closure_array (ProtobufC_RPC_Client *client)
{
/* resize array */
unsigned old_size = client->info.connected.closures_alloced;
unsigned new_size = old_size * 2;
Closure *new_closures = client->allocator->alloc (client->allocator, sizeof (Closure) * new_size);
memcpy (new_closures,
client->info.connected.closures,
sizeof (Closure) * old_size);
/* build new free list */
for (i = old_size; i < new_size - 1; i++)
{
new_closures[i].response_type = NULL;
new_closures[i].closure = NULL;
new_closures[i].closure_data = UINT_TO_POINTER (i+2);
}
new_closures[i].closure_data = client->info.connected.first_free_request_id;
new_closures[i].response_type = NULL;
new_closures[i].closure = NULL;
client->allocator->free (client->allocator, client->info.connected.closures);
client->info.connected.closures = new_closures;
client->info.connected.closures_alloced = new_size;
}
static void
enqueue_request (ProtobufC_RPC_Client *client,
unsigned method_index,
......@@ -196,7 +292,52 @@ enqueue_request (ProtobufC_RPC_Client *client,
ProtobufCClosure closure,
void *closure_data)
{
...
uint32_t request_id;
struct {
uint32_t method_index;
uint32_t packed_size;
uint32_t request_id;
} header;
size_t packed_size;
uint8_t *packed_data;
Closure *closure;
const ProtobufCServiceDescriptor *desc = client->base_service.descriptor;
const ProtobufCMethodDescriptor *method = descriptor->methods + method_index;
protobuf_c_assert (method_index < desc->n_methods);
/* Allocate request_id */
protobuf_c_assert (client->state == PROTOBUF_C_CLIENT_STATE_CONNECTED);
if (client->info.connected.first_free_request_id == 0)
grow_closure_array (client);
request_id = client->info.connected.first_free_request_id;
closure = client->info.connected.closures + (request_id - 1);
client->info.connected.first_free_request_id = POINTER_TO_UINT (closure->closure_data);
/* Pack message */
packed_size = protobuf_c_message_get_packed_size (input);
if (packed_size < client->allocator->max_alloca)
packed_data = alloca (packed_size);
else
packed_data = client->allocator->alloc (client->allocator, packed_size);
protobuf_c_message_pack (input, packed_data);
/* Append to buffer */
protobuf_c_assert (sizeof (header) == 16);
header.method_index = uint32_to_le (method_index);
header.packed_size = uint32_to_le (packed_size);
header.request_id = request_id;
protobuf_c_data_buffer_append (&client->outgoing, &header, 16);
protobuf_c_data_buffer_append (&client->outgoing, packed_data, packed_size);
/* Clean up if not using alloca() */
if (packed_size >= client->allocator->max_alloca)
client->allocator->free (client->allocator, packed_data);
/* Add closure to request-tree */
client->info.connected.closures[request_id-1].response_type = client->descriptor->methods[method_index].output;
client->info.connected.closures[request_id-1].closure = closure;
client->info.connected.closures[request_id-1].closure_data = closure_data;
}
static void
......
......@@ -3,15 +3,15 @@
/* Protocol is:
* client issues request with header:
* service_index
* request_id
* message_length
* service_index 32-bit little-endian
* message_length 32-bit little-endian
* request_id 64-bit any-endian
* server responds with header:
* service_index
* request_id
* message_length
* service_index 32-bit little-endian
* message_length 32-bit little-endian
* request_id 64-bit any-endian
*/
typedef struct _ProtobufC_Dispatch ProtobufC_Dispatch;
#include "protobuf-c-dispatch.h"
typedef enum
{
......@@ -19,6 +19,12 @@ typedef enum
PROTOBUF_C_RPC_ADDRESS_TCP /* host/port tcp socket */
} ProtobufC_RPC_AddressType;
typedef enum
{
PROTOBUF_C_ERROR_CODE_HOST_NOT_FOUND,
PROTOBUF_C_ERROR_CODE_CONNECTION_REFUSED
} ProtobufC_RPC_Error_Code;
typedef void (*ProtobufC_RPC_Error_Func) (ProtobufC_RPC_Error_Code code,
const char *message,
void *error_func_data);
......@@ -29,7 +35,7 @@ typedef void (*ProtobufC_RPC_Error_Func) (ProtobufC_RPC_Error_Code code,
ProtobufCService *protobuf_c_rpc_client_new (ProtobufC_RPC_AddressType type,
const char *name,
const ProtobufCServiceDescriptor *descriptor,
ProtobufC_Dispatch *dispatch);
ProtobufCDispatch *dispatch);
/* --- configuring the client */
typedef struct _ProtobufC_RPC_Client ProtobufC_RPC_Client;
......@@ -45,7 +51,7 @@ typedef void (*ProtobufC_NameLookup_Func) (ProtobufCDispatch *dispatch,
const char *name,
ProtobufC_NameLookup_Found found_func,
ProtobufC_NameLookup_Failed failed_func,
gpointer callback_data);
void *callback_data);
void protobuf_c_rpc_client_set_name_resolver (ProtobufC_RPC_Client *client,
ProtobufC_NameLookup_Func resolver);
......@@ -66,11 +72,12 @@ void protobuf_c_rpc_client_set_autoretry_period (ProtobufC_RPC_Client *client,
so you may configure the client immediately after creation */
/* --- Server API --- */
typedef struct _ProtobufC_RPC_Server ProtobufC_RPC_Server;
ProtobufC_RPC_Server *
protobuf_c_rpc_server_new (ProtobufC_RPC_AddressType type,
const char *name,
ProtobufCService *service,
ProtobufC_Dispatch *dispatch);
ProtobufCDispatch *dispatch);
ProtobufCService *
protobuf_c_rpc_server_destroy (ProtobufC_RPC_Server *server,
protobuf_c_boolean free_underlying_service);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment