--- sa.c 2001/10/07 14:16:47 1.10
+++ sa.c 2001/10/07 15:21:17 1.11
@@ -59,6 +59,105 @@
socklen_t slBuf; /* the length of "struct sockaddr_xx" */
};
+/* system call structure declaration macros */
+#define SA_SC_DECLARE_0(rc_t, fn) \
+ struct { \
+ union { void (*any)(); \
+ rc_t (*std)(void); \
+ rc_t (*ctx)(void *); } fptr; \
+ void *fctx; \
+ } sc_##fn;
+#define SA_SC_DECLARE_1(rc_t, fn, a1_t) \
+ struct { \
+ union { void (*any)(); \
+ rc_t (*std)(a1_t); \
+ rc_t (*ctx)(void *, a1_t); } fptr; \
+ void *fctx; \
+ } sc_##fn;
+#define SA_SC_DECLARE_2(rc_t, fn, a1_t, a2_t) \
+ struct { \
+ union { void (*any)(); \
+ rc_t (*std)(a1_t, a2_t); \
+ rc_t (*ctx)(void *, a1_t, a2_t); } fptr; \
+ void *fctx; \
+ } sc_##fn;
+#define SA_SC_DECLARE_3(rc_t, fn, a1_t, a2_t, a3_t) \
+ struct { \
+ union { void (*any)(); \
+ rc_t (*std)(a1_t, a2_t, a3_t); \
+ rc_t (*ctx)(void *, a1_t, a2_t, a3_t); } fptr; \
+ void *fctx; \
+ } sc_##fn;
+#define SA_SC_DECLARE_4(rc_t, fn, a1_t, a2_t, a3_t, a4_t) \
+ struct { \
+ union { void (*any)(); \
+ rc_t (*std)(a1_t, a2_t, a3_t, a4_t); \
+ rc_t (*ctx)(void *, a1_t, a2_t, a3_t, a4_t); } fptr; \
+ void *fctx; \
+ } sc_##fn;
+#define SA_SC_DECLARE_5(rc_t, fn, a1_t, a2_t, a3_t, a4_t, a5_t) \
+ struct { \
+ union { void (*any)(); \
+ rc_t (*std)(a1_t, a2_t, a3_t, a4_t, a5_t); \
+ rc_t (*ctx)(void *, a1_t, a2_t, a3_t, a4_t, a5_t); } fptr; \
+ void *fctx; \
+ } sc_##fn;
+#define SA_SC_DECLARE_6(rc_t, fn, a1_t, a2_t, a3_t, a4_t, a5_t, a6_t) \
+ struct { \
+ union { void (*any)(); \
+ rc_t (*std)(a1_t, a2_t, a3_t, a4_t, a5_t, a6_t); \
+ rc_t (*ctx)(void *, a1_t, a2_t, a3_t, a4_t, a5_t, a6_t); } fptr; \
+ void *fctx; \
+ } sc_##fn;
+
+/* system call structure assignment macro */
+#define SA_SC_ASSIGN(sa, fn, ptr, ctx) \
+ do { \
+ (sa)->scSysCall.sc_##fn.fptr.any = (void (*)())(ptr); \
+ (sa)->scSysCall.sc_##fn.fctx = (ctx); \
+ } while(0)
+
+/* system call function call macros */
+#define SA_SC_CALL_0(sa, fn) \
+ ( (sa)->scSysCall.sc_##fn.fctx != NULL \
+ ? ((sa)->scSysCall.sc_##fn.fptr.ctx)((sa)->scSysCall.sc_##fn.fctx) \
+ : ((sa)->scSysCall.sc_##fn.fptr.std)() )
+#define SA_SC_CALL_1(sa, fn, a1) \
+ ( (sa)->scSysCall.sc_##fn.fctx != NULL \
+ ? ((sa)->scSysCall.sc_##fn.fptr.ctx)((sa)->scSysCall.sc_##fn.fctx, a1) \
+ : ((sa)->scSysCall.sc_##fn.fptr.std)(a1) )
+#define SA_SC_CALL_2(sa, fn, a1, a2) \
+ ( (sa)->scSysCall.sc_##fn.fctx != NULL \
+ ? ((sa)->scSysCall.sc_##fn.fptr.ctx)((sa)->scSysCall.sc_##fn.fctx, a1, a2) \
+ : ((sa)->scSysCall.sc_##fn.fptr.std)(a1, a2) )
+#define SA_SC_CALL_3(sa, fn, a1, a2, a3) \
+ ( (sa)->scSysCall.sc_##fn.fctx != NULL \
+ ? ((sa)->scSysCall.sc_##fn.fptr.ctx)((sa)->scSysCall.sc_##fn.fctx, a1, a2, a3) \
+ : ((sa)->scSysCall.sc_##fn.fptr.std)(a1, a2, a3) )
+#define SA_SC_CALL_4(sa, fn, a1, a2, a3, a4) \
+ ( (sa)->scSysCall.sc_##fn.fctx != NULL \
+ ? ((sa)->scSysCall.sc_##fn.fptr.ctx)((sa)->scSysCall.sc_##fn.fctx, a1, a2, a3, a4) \
+ : ((sa)->scSysCall.sc_##fn.fptr.std)(a1, a2, a3, a4) )
+#define SA_SC_CALL_5(sa, fn, a1, a2, a3, a4, a5) \
+ ( (sa)->scSysCall.sc_##fn.fctx != NULL \
+ ? ((sa)->scSysCall.sc_##fn.fptr.ctx)((sa)->scSysCall.sc_##fn.fctx, a1, a2, a3, a4, a5) \
+ : ((sa)->scSysCall.sc_##fn.fptr.std)(a1, a2, a3, a4, a5) )
+#define SA_SC_CALL_6(sa, fn, a1, a2, a3, a4, a5, a6) \
+ ( (sa)->scSysCall.sc_##fn.fctx != NULL \
+ ? ((sa)->scSysCall.sc_##fn.fptr.ctx)((sa)->scSysCall.sc_##fn.fctx, a1, a2, a3, a4, a5, a6) \
+ : ((sa)->scSysCall.sc_##fn.fptr.std)(a1, a2, a3, a4, a5, a6) )
+
+/* system call table */
+typedef struct {
+ SA_SC_DECLARE_3(int, connect, int, const struct sockaddr *, socklen_t)
+ SA_SC_DECLARE_3(int, accept, int, struct sockaddr *, socklen_t *)
+ SA_SC_DECLARE_5(int, select, int, fd_set *, fd_set *, fd_set *, struct timeval *)
+ SA_SC_DECLARE_3(ssize_t, read, int, void *, size_t)
+ SA_SC_DECLARE_3(ssize_t, write, int, const void *, size_t)
+ SA_SC_DECLARE_6(ssize_t, recvfrom, int, void *, size_t, int, struct sockaddr *, socklen_t *)
+ SA_SC_DECLARE_6(ssize_t, sendto, int, const void *, size_t, int, const struct sockaddr *, socklen_t)
+} sa_syscall_tab_t;
+
/* socket abstraction object */
struct sa_st {
sa_type_t eType; /* socket type (stream or datagram) */
@@ -73,6 +172,7 @@
char szError[256];
char szErrorInfo[128];
sa_rc_t rvErrorInfo;
+ sa_syscall_tab_t scSysCall;
};
/* boolean values */
@@ -681,21 +781,34 @@
/* allocate and initialize socket object */
if ((sa = (sa_t *)malloc(sizeof(sa_t))) == NULL)
return SA_ERR_MEM;
- sa->eType = SA_TYPE_STREAM;
- sa->fdSocket = -1;
+
+ /* init object attributes */
+ sa->eType = SA_TYPE_STREAM;
+ sa->fdSocket = -1;
+ sa->nReadLen = 0;
+ sa->nReadSize = 0;
+ sa->cpReadBuf = NULL;
+ sa->nWriteLen = 0;
+ sa->nWriteSize = 0;
+ sa->cpWriteBuf = NULL;
+ sa->szError[0] = '\0';
+ sa->szErrorInfo[0] = '\0';
+ sa->rvErrorInfo = SA_OK;
+
+ /* init timeval object attributes */
for (i = 0; i < (sizeof(sa->tvTimeout)/sizeof(sa->tvTimeout[0])); i++) {
sa->tvTimeout[i].tv_sec = 0;
sa->tvTimeout[i].tv_usec = 0;
}
- sa->nReadLen = 0;
- sa->nReadSize = 0;
- sa->cpReadBuf = NULL;
- sa->nWriteLen = 0;
- sa->nWriteSize = 0;
- sa->cpWriteBuf = NULL;
- sa->szError[0] = '\0';
- sa->szErrorInfo[0] = '\0';
- sa->rvErrorInfo = SA_OK;
+
+ /* init syscall object attributes */
+ SA_SC_ASSIGN(sa, connect, connect, NULL);
+ SA_SC_ASSIGN(sa, accept, accept, NULL);
+ SA_SC_ASSIGN(sa, select, select, NULL);
+ SA_SC_ASSIGN(sa, read, read, NULL);
+ SA_SC_ASSIGN(sa, write, write, NULL);
+ SA_SC_ASSIGN(sa, recvfrom, recvfrom, NULL);
+ SA_SC_ASSIGN(sa, sendto, sendto, NULL);
/* pass object to caller */
*sap = sa;
@@ -817,6 +930,30 @@
return SA_OK;
}
+/* override system call */
+sa_rc_t sa_syscall(sa_t *sa, sa_syscall_t id, void (*fptr)(), void *fctx)
+{
+ if (sa == NULL || fptr == NULL)
+ return SA_ERR_ARG;
+ if (id == SA_SYSCALL_CONNECT)
+ SA_SC_ASSIGN(sa, connect, fptr, fctx);
+ else if (id == SA_SYSCALL_ACCEPT)
+ SA_SC_ASSIGN(sa, accept, fptr, fctx);
+ else if (id == SA_SYSCALL_SELECT)
+ SA_SC_ASSIGN(sa, select, fptr, fctx);
+ else if (id == SA_SYSCALL_READ)
+ SA_SC_ASSIGN(sa, read, fptr, fctx);
+ else if (id == SA_SYSCALL_WRITE)
+ SA_SC_ASSIGN(sa, write, fptr, fctx);
+ else if (id == SA_SYSCALL_RECVFROM)
+ SA_SC_ASSIGN(sa, recvfrom, fptr, fctx);
+ else if (id == SA_SYSCALL_SENDTO)
+ SA_SC_ASSIGN(sa, sendto, fptr, fctx);
+ else
+ return SA_ERR_ARG;
+ return SA_OK;
+}
+
/* bind socket to a local address */
sa_rc_t sa_bind(sa_t *sa, sa_addr_t *laddr)
{
@@ -869,7 +1006,7 @@
rv = SA_OK;
if (SA_TVISZERO(sa->tvTimeout[SA_TIMEOUT_CONNECT])) {
/* standard/non-timeout-aware connect operation */
- if (connect(sa->fdSocket, raddr->saBuf, raddr->slBuf) < 0)
+ if (SA_SC_CALL_3(sa, connect, sa->fdSocket, raddr->saBuf, raddr->slBuf) < 0)
rv = SA_ERR_SYS;
}
else {
@@ -881,7 +1018,7 @@
fcntl(sa->fdSocket, F_SETFL, flags|O_NONBLOCK);
/* perform the connect operation */
- if ((n = connect(sa->fdSocket, raddr->saBuf, raddr->slBuf)) < 0) {
+ if ((n = SA_SC_CALL_3(sa, connect, sa->fdSocket, raddr->saBuf, raddr->slBuf)) < 0) {
if (errno != EINPROGRESS) {
error = errno;
goto done;
@@ -898,8 +1035,8 @@
FD_SET(sa->fdSocket, &rset);
FD_SET(sa->fdSocket, &wset);
do {
- n = select(sa->fdSocket+1, &rset, &wset, NULL,
- &sa->tvTimeout[SA_TIMEOUT_CONNECT]);
+ n = SA_SC_CALL_5(sa, select, sa->fdSocket+1, &rset, &wset, NULL,
+ &sa->tvTimeout[SA_TIMEOUT_CONNECT]);
} while (n == -1 && errno == EINTR);
/* decide on return semantic */
@@ -985,8 +1122,8 @@
FD_ZERO(&fds);
FD_SET(sa->fdSocket, &fds);
do {
- n = select(sa->fdSocket+1, &fds, NULL, NULL,
- &sa->tvTimeout[SA_TIMEOUT_ACCEPT]);
+ n = SA_SC_CALL_5(sa, select, sa->fdSocket+1, &fds, NULL, NULL,
+ &sa->tvTimeout[SA_TIMEOUT_ACCEPT]);
} while (n == -1 && errno == EINTR);
if (n == 0)
errno = ETIMEDOUT;
@@ -996,7 +1133,7 @@
/* perform accept operation on underlying socket */
sa_len = sizeof(sa_buf);
- if ((s = accept(sa->fdSocket, (struct sockaddr *)&sa_buf, &sa_len)) == -1)
+ if ((s = SA_SC_CALL_3(sa, accept, sa->fdSocket, (struct sockaddr *)&sa_buf, &sa_len)) == -1)
return SA_ERR_SYS;
/* create result address object */
@@ -1122,8 +1259,8 @@
FD_ZERO(&fds);
FD_SET(sa->fdSocket, &fds);
do {
- rv = select(sa->fdSocket+1, &fds, NULL, NULL,
- &sa->tvTimeout[SA_TIMEOUT_READ]);
+ rv = SA_SC_CALL_5(sa, select, sa->fdSocket+1, &fds, NULL, NULL,
+ &sa->tvTimeout[SA_TIMEOUT_READ]);
} while (rv == -1 && errno == EINTR);
if (rv == 0) {
errno = ETIMEDOUT;
@@ -1133,7 +1270,7 @@
/* perform read operation on underlying socket */
do {
- rv = read(sa->fdSocket, cpBuf, nBufLen);
+ rv = SA_SC_CALL_3(sa, read, sa->fdSocket, cpBuf, nBufLen);
} while (rv == -1 && errno == EINTR);
return rv;
@@ -1281,8 +1418,8 @@
FD_ZERO(&fds);
FD_SET(sa->fdSocket, &fds);
do {
- rv = select(sa->fdSocket+1, NULL, &fds, NULL,
- &sa->tvTimeout[SA_TIMEOUT_WRITE]);
+ rv = SA_SC_CALL_5(sa, select, sa->fdSocket+1, NULL, &fds, NULL,
+ &sa->tvTimeout[SA_TIMEOUT_WRITE]);
} while (rv == -1 && errno == EINTR);
if (rv == 0) {
errno = ETIMEDOUT;
@@ -1292,7 +1429,7 @@
/* perform write operation on underlying socket */
do {
- rv = write(sa->fdSocket, cpBuf, nBufLen);
+ rv = SA_SC_CALL_3(sa, write, sa->fdSocket, cpBuf, nBufLen);
} while (rv == -1 && errno == EINTR);
return rv;
@@ -1492,8 +1629,8 @@
FD_ZERO(&fds);
FD_SET(sa->fdSocket, &fds);
do {
- n = select(sa->fdSocket+1, &fds, NULL, NULL,
- &sa->tvTimeout[SA_TIMEOUT_RECV]);
+ n = SA_SC_CALL_5(sa, select, sa->fdSocket+1, &fds, NULL, NULL,
+ &sa->tvTimeout[SA_TIMEOUT_RECV]);
} while (n == -1 && errno == EINTR);
if (n == 0)
errno = ETIMEDOUT;
@@ -1503,8 +1640,8 @@
/* perform receive operation on underlying socket */
sa_len = sizeof(sa_buf);
- if ((n = recvfrom(sa->fdSocket, buf, buflen, 0,
- (struct sockaddr *)&sa_buf, &sa_len)) == -1)
+ if ((n = SA_SC_CALL_6(sa, recvfrom, sa->fdSocket, buf, buflen, 0,
+ (struct sockaddr *)&sa_buf, &sa_len)) == -1)
return SA_ERR_SYS;
/* create result address object */
@@ -1548,8 +1685,8 @@
FD_ZERO(&fds);
FD_SET(sa->fdSocket, &fds);
do {
- n = select(sa->fdSocket+1, NULL, &fds, NULL,
- &sa->tvTimeout[SA_TIMEOUT_SEND]);
+ n = SA_SC_CALL_5(sa, select, sa->fdSocket+1, NULL, &fds, NULL,
+ &sa->tvTimeout[SA_TIMEOUT_SEND]);
} while (n == -1 && errno == EINTR);
if (n == 0)
errno = ETIMEDOUT;
@@ -1558,7 +1695,7 @@
}
/* perform send operation on underlying socket */
- if ((n = sendto(sa->fdSocket, buf, buflen, 0, raddr->saBuf, raddr->slBuf)) == -1)
+ if ((n = SA_SC_CALL_6(sa, sendto, sa->fdSocket, buf, buflen, 0, raddr->saBuf, raddr->slBuf)) == -1)
return SA_ERR_SYS;
/* pass actual number of sent bytes to caller */
|