Index: ossp-pkg/sa/TODO RCS File: /v/ossp/cvs/ossp-pkg/sa/TODO,v rcsdiff -q -kk '-r1.12' '-r1.13' -u '/v/ossp/cvs/ossp-pkg/sa/TODO,v' 2>/dev/null --- TODO 2001/10/07 14:17:13 1.12 +++ TODO 2001/10/07 15:21:17 1.13 @@ -10,18 +10,3 @@ SA_BUFFER_KREAD SA_BUFFER_KWRITE SA_BUFFER_WRITEF -- sa_syscall(sa, |, func, ctx); - SA_SYSCALL_CTX - SA_SYSCALL_SOCKET - SA_SYSCALL_BIND - SA_SYSCALL_CONNECT - SA_SYSCALL_LISTEN - SA_SYSCALL_ACCEPT - SA_SYSCALL_READ - SA_SYSCALL_WRITE - SA_SYSCALL_RECVFROM - SA_SYSCALL_SENDTO - SA_SYSCALL_SHUTDOWN - SA_SYSCALL_CLOSE - : - Index: ossp-pkg/sa/sa.c RCS File: /v/ossp/cvs/ossp-pkg/sa/sa.c,v rcsdiff -q -kk '-r1.10' '-r1.11' -u '/v/ossp/cvs/ossp-pkg/sa/sa.c,v' 2>/dev/null --- 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 */ Index: ossp-pkg/sa/sa.h RCS File: /v/ossp/cvs/ossp-pkg/sa/sa.h,v rcsdiff -q -kk '-r1.11' '-r1.12' -u '/v/ossp/cvs/ossp-pkg/sa/sa.h,v' 2>/dev/null --- sa.h 2001/10/07 14:16:47 1.11 +++ sa.h 2001/10/07 15:21:17 1.12 @@ -113,6 +113,17 @@ SA_TIMEOUT_SEND = 5 } sa_timeout_t; +/* list of system calls */ +typedef enum { + SA_SYSCALL_CONNECT, + SA_SYSCALL_ACCEPT, + SA_SYSCALL_SELECT, + SA_SYSCALL_READ, + SA_SYSCALL_WRITE, + SA_SYSCALL_RECVFROM, + SA_SYSCALL_SENDTO +} sa_syscall_t; + /* error handling operations */ sa_rc_t sa_error (sa_t *sa, sa_rc_t rv, char **str); @@ -134,6 +145,7 @@ sa_rc_t sa_type (sa_t *sa, sa_type_t type); sa_rc_t sa_timeout (sa_t *sa, sa_timeout_t id, long sec, long usec); sa_rc_t sa_buffers (sa_t *sa, size_t rsize, size_t wsize); +sa_rc_t sa_syscall (sa_t *sa, sa_syscall_t id, void (*fptr)(), void *fctx); /* socket connection operations */ sa_rc_t sa_bind (sa_t *sa, sa_addr_t *laddr);