#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <stdio.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <sys/errno.h>
#include <sys/socket.h>
#include <net/if_types.h>
#include <syslog.h>
#include "dynarray.h"
#include "FDSet.h"
static void
FDSet_process(CFSocketRef s, CFSocketCallBackType type,
CFDataRef address, const void *data, void *info);
FDCallout_t *
FDSet_add_callout(FDSet_t * set, int fd, FDCallout_func_t * func,
void * arg1, void * arg2)
{
CFSocketContext context = { 0, NULL, NULL, NULL, NULL };
FDCallout_t * callout;
callout = malloc(sizeof(*callout));
if (callout == NULL)
return (NULL);
bzero(callout, sizeof(*callout));
if (dynarray_add(&set->callouts, callout) == FALSE) {
free(callout);
return (NULL);
}
context.info = callout;
callout->socket
= CFSocketCreateWithNative(NULL, fd, kCFSocketReadCallBack,
FDSet_process, &context);
callout->rls = CFSocketCreateRunLoopSource(NULL, callout->socket, 0);
CFRunLoopAddSource(CFRunLoopGetCurrent(), callout->rls,
kCFRunLoopDefaultMode);
callout->fd = fd;
callout->func = func;
callout->arg1 = arg1;
callout->arg2 = arg2;
return (callout);
}
void
FDSet_remove_callout(FDSet_t * set, FDCallout_t * * callout_p)
{
int i;
FDCallout_t * callout = *callout_p;
i = dynarray_index(&set->callouts, callout);
if (i == -1) {
syslog(LOG_ERR, "FDSet_remove_callout: got back -1 index");
return;
}
dynarray_free_element(&set->callouts, i);
*callout_p = NULL;
return;
}
static void
FDSet_callout_free(void * arg)
{
FDCallout_t * callout = arg;
if (callout->rls) {
CFRunLoopRemoveSource(CFRunLoopGetCurrent(), callout->rls,
kCFRunLoopDefaultMode);
CFSocketInvalidate(callout->socket);
CFRelease(callout->socket);
callout->socket = NULL;
CFRelease(callout->rls);
callout->rls = NULL;
}
free(callout);
return;
}
FDSet_t *
FDSet_init()
{
FDSet_t * set = malloc(sizeof(*set));
if (set == NULL)
return (NULL);
bzero(set, sizeof(*set));
dynarray_init(&set->callouts, FDSet_callout_free, NULL);
return (set);
}
void
FDSet_free(FDSet_t * * set_p)
{
FDSet_t * set = *set_p;
dynarray_free(&set->callouts);
bzero(set, sizeof(*set));
free(set);
*set_p = NULL;
return;
}
static void
FDSet_process(CFSocketRef s, CFSocketCallBackType type,
CFDataRef address, const void *data, void *info)
{
FDCallout_t * callout = (FDCallout_t *)info;
if (callout->func) {
(*callout->func)(callout->arg1, callout->arg2);
}
return;
}