freeswitch/libs/xmlrpc-c/lib/abyss/src/channel.c

198 lines
4.5 KiB
C

/*============================================================================
socket.c
==============================================================================
Implementation of TChannel class: A generic channel over which one can
transport a bidirectional stream of bytes.
A TChannel is a lot like a POSIX stream socket in "connected" state.
============================================================================*/
#include <sys/types.h>
#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
#include "bool.h"
#include "int.h"
#include "mallocvar.h"
#include "xmlrpc-c/util_int.h"
#include "xmlrpc-c/abyss.h"
#ifdef WIN32
#include "socket_win.h"
#else
#include "socket_unix.h"
#endif
#include "channel.h"
static void
socketOsInit(const char ** const errorP) {
#ifdef WIN32
SocketWinInit(errorP);
#else
SocketUnixInit(errorP);
#endif
}
static void
socketOsTerm(void) {
#ifdef WIN32
SocketWinTerm();
#else
SocketUnixTerm();
#endif
}
bool ChannelTraceIsActive;
void
ChannelInit(const char ** const errorP) {
socketOsInit(errorP);
if (!*errorP) {
ChannelTraceIsActive = (getenv("ABYSS_TRACE_CHANNEL") != NULL);
if (ChannelTraceIsActive)
fprintf(stderr, "Abyss channel layer will trace channel traffic "
"due to ABYSS_TRACE_CHANNEL environment variable\n");
}
}
void
ChannelTerm(void) {
socketOsTerm();
}
/* ChannelCreate() is not exported to the Abyss user. It is meant to
be used by an implementation-specific TChannel generator which is
exported to the Abyss user, e.g. ChannelCreateUnix() in
socket_unix.c
The TChannel generator functions are the _only_ user-accessible
functions that are particular to an implementation.
*/
static unsigned int const channelSignature = 0x06060B;
void
ChannelCreate(const struct TChannelVtbl * const vtblP,
void * const implP,
TChannel ** const channelPP) {
TChannel * channelP;
MALLOCVAR(channelP);
if (channelP) {
channelP->implP = implP;
channelP->vtbl = *vtblP;
channelP->signature = channelSignature;
*channelPP = channelP;
if (ChannelTraceIsActive)
fprintf(stderr, "Created channel %p\n", channelP);
}
}
void
ChannelDestroy(TChannel * const channelP) {
if (ChannelTraceIsActive)
fprintf(stderr, "Destroying channel %p\n", channelP);
assert(channelP->signature == channelSignature);
channelP->vtbl.destroy(channelP);
channelP->signature = 0; /* For debuggability */
free(channelP);
}
void
ChannelWrite(TChannel * const channelP,
const unsigned char * const buffer,
uint32_t const len,
bool * const failedP) {
if (ChannelTraceIsActive)
fprintf(stderr, "Writing %u bytes to channel %p\n", len, channelP);
(*channelP->vtbl.write)(channelP, buffer, len, failedP);
}
void
ChannelRead(TChannel * const channelP,
unsigned char * const buffer,
uint32_t const len,
uint32_t * const bytesReceivedP,
bool * const failedP) {
if (ChannelTraceIsActive)
fprintf(stderr, "Reading %u bytes from channel %p\n", len, channelP);
(*channelP->vtbl.read)(channelP, buffer, len, bytesReceivedP, failedP);
}
void
ChannelWait(TChannel * const channelP,
bool const waitForRead,
bool const waitForWrite,
uint32_t const timems,
bool * const readyToReadP,
bool * const readyToWriteP,
bool * const failedP) {
if (ChannelTraceIsActive) {
if (waitForRead)
fprintf(stderr, "Waiting %u milliseconds for data from "
"channel %p\n", timems, channelP);
if (waitForWrite)
fprintf(stderr, "Waiting %u milliseconds for channel %p "
"to be writable\n", timems, channelP);
}
(*channelP->vtbl.wait)(channelP, waitForRead, waitForWrite, timems,
readyToReadP, readyToWriteP, failedP);
}
void
ChannelInterrupt(TChannel * const channelP) {
if (ChannelTraceIsActive)
fprintf(stderr, "Interrupting channel waits");
(*channelP->vtbl.interrupt)(channelP);
}
void
ChannelFormatPeerInfo(TChannel * const channelP,
const char ** const peerStringP) {
(*channelP->vtbl.formatPeerInfo)(channelP, peerStringP);
}