--- sa.c 2001/10/04 11:25:44 1.3
+++ sa.c 2001/10/05 11:40:22 1.4
@@ -55,14 +55,14 @@
/* socket address abstraction object */
struct sa_addr_st {
+ int nFamily;
struct sockaddr *saBuf;
socklen_t slBuf;
- int nFamily;
- int nProto;
};
/* socket abstraction object */
struct sa_st {
+ sa_type_t eType;
int sSocket;
int bTimeout;
struct timeval tvTimeout;
@@ -199,7 +199,6 @@
(*saa)->saBuf = NULL;
(*saa)->slBuf = 0;
(*saa)->nFamily = 0;
- (*saa)->nProto = 0;
return SA_OK;
}
@@ -219,19 +218,20 @@
int nPort;
socklen_t sl;
struct sockaddr *sa;
+ struct sockaddr_un un;
struct sockaddr_in sa4;
#ifdef AF_INET6
struct sockaddr_in6 sa6;
#endif
struct hostent *he;
struct servent *se;
- struct protoent *pe;
int bNumeric;
int i;
+ int n;
char *cpProto;
- int nProto;
char *cpHost;
char *cpPort;
+ char *cpPath;
char uribuf[1024];
char *cp;
int sf;
@@ -245,42 +245,52 @@
sa_mvsnprintf(uribuf, sizeof(uribuf), uri, ap);
va_end(ap);
- /* parse URI into protocol, host and port parts */
+ /* parse URI into parts */
uri = uribuf;
- cpProto = "tcp";
- if ((cp = strstr(uri, "://")) != NULL) {
+ cpProto = "unix";
+ if ((cp = strchr(uri, ':')) != NULL) {
cpProto = (char *)uri;
*cp = '\0';
- uri = cp+3;
+ uri = cp+1;
}
- cpHost = (char *)uri;
- if ((cp = strchr(uri, ':')) == NULL)
- return SA_ERR_ARG;
- *cp++ = '\0';
- cpPort = cp;
-
- /* resolve protocol */
- if ((pe = getprotobyname(cpProto)) == NULL)
- return SA_ERR_SYS;
- nProto = pe->p_proto;
+ cpHost = "";
+ cpPort = "";
+ if (strncmp(uri, "//", 2) == 0) {
+ uri += 2;
+ cpHost = (char *)uri;
+ if ((cp = strchr(uri, ':')) == NULL)
+ return SA_ERR_ARG;
+ *cp++ = '\0';
+ cpPort = cp;
+ uri = cp;
+ if ((cp = strchr(uri, '/')) != NULL)
+ uri = cp;
+ else
+ uri = strchr(uri, '\0');
+ }
+ cpPath = (char *)uri;
/* resolve port */
- bNumeric = 1;
- for (i = 0; cpPort[i] != '\0'; i++) {
- if (!isdigit((int)cpPort[i])) {
- bNumeric = 0;
- break;
+ nPort = 0;
+ if (strcmp(cpProto, "inet") == 0) {
+ bNumeric = 1;
+ for (i = 0; cpPort[i] != '\0'; i++) {
+ if (!isdigit((int)cpPort[i])) {
+ bNumeric = 0;
+ break;
+ }
+ }
+ if (bNumeric)
+ nPort = atoi(cpPort);
+ else {
+ if ((se = getservbyname(cpPort, cpProto)) == NULL)
+ return SA_ERR_SYS;
+ nPort = ntohs(se->s_port);
}
- }
- if (bNumeric)
- nPort = atoi(cpPort);
- else {
- if ((se = getservbyname(cpPort, cpProto)) == NULL)
- return SA_ERR_SYS;
- nPort = ntohs(se->s_port);
}
/* mandatory(!) socket address structure initialization */
+ memset(&un, 0, sizeof(un));
memset(&sa4, 0, sizeof(sa4));
#ifdef AF_INET6
memset(&sa6, 0, sizeof(sa6));
@@ -291,41 +301,55 @@
sa = NULL;
sl = 0;
sf = 0;
- if (inet_pton(AF_INET, cpHost, &sa4.sin_addr.s_addr) == 1) {
- sa4.sin_family = AF_INET;
- sa4.sin_port = htons(nPort);
- sa = (struct sockaddr *)&sa4;
- sl = sizeof(sa4);
- sf = AF_INET;
- }
-#ifdef AF_INET6
- else if (inet_pton(AF_INET6, cpHost, &sa6.sin6_addr.s6_addr) == 1) {
- sa6.sin6_family = AF_INET6;
- sa6.sin6_port = htons(nPort);
- sa = (struct sockaddr *)&sa6;
- sl = sizeof(sa6);
- sf = AF_INET6;
+ if (strcmp(cpProto, "unix") == 0) {
+ if (cpProto[0] != '/')
+ return SA_ERR_ARG;
+ n = strlen(cpProto);
+ if ((n+1) > sizeof(un.sun_path))
+ return SA_ERR_MEM;
+ memcpy(un.sun_path, cpPath, n+1);
+ un.sun_family = AF_LOCAL;
+ sa = (struct sockaddr *)&un;
+ sl = sizeof(un);
+ sf = AF_LOCAL;
}
-#endif
- else if ((he = gethostbyname(cpHost)) != NULL) {
- if (he->h_addrtype == AF_INET) {
+ else if (strcmp(cpProto, "inet") == 0) {
+ if (inet_pton(AF_INET, cpHost, &sa4.sin_addr.s_addr) == 1) {
sa4.sin_family = AF_INET;
sa4.sin_port = htons(nPort);
- memcpy(&sa4.sin_addr.s_addr, he->h_addr_list[0], sizeof(sa4.sin_addr.s_addr));
sa = (struct sockaddr *)&sa4;
sl = sizeof(sa4);
sf = AF_INET;
}
#ifdef AF_INET6
- else if (he->h_addrtype == AF_INET6) {
+ else if (inet_pton(AF_INET6, cpHost, &sa6.sin6_addr.s6_addr) == 1) {
sa6.sin6_family = AF_INET6;
sa6.sin6_port = htons(nPort);
- memcpy(&sa6.sin6_addr.s6_addr, he->h_addr_list[0], sizeof(sa6.sin6_addr.s6_addr));
sa = (struct sockaddr *)&sa6;
sl = sizeof(sa6);
sf = AF_INET6;
}
#endif
+ else if ((he = gethostbyname(cpHost)) != NULL) {
+ if (he->h_addrtype == AF_INET) {
+ sa4.sin_family = AF_INET;
+ sa4.sin_port = htons(nPort);
+ memcpy(&sa4.sin_addr.s_addr, he->h_addr_list[0], sizeof(sa4.sin_addr.s_addr));
+ sa = (struct sockaddr *)&sa4;
+ sl = sizeof(sa4);
+ sf = AF_INET;
+ }
+#ifdef AF_INET6
+ else if (he->h_addrtype == AF_INET6) {
+ sa6.sin6_family = AF_INET6;
+ sa6.sin6_port = htons(nPort);
+ memcpy(&sa6.sin6_addr.s6_addr, he->h_addr_list[0], sizeof(sa6.sin6_addr.s6_addr));
+ sa = (struct sockaddr *)&sa6;
+ sl = sizeof(sa6);
+ sf = AF_INET6;
+ }
+#endif
+ }
}
if (sa == NULL)
return SA_ERR_ARG;
@@ -336,17 +360,16 @@
memcpy(saa->saBuf, sa, sl);
saa->slBuf = sl;
saa->nFamily = sf;
- saa->nProto = nProto;
return SA_OK;
}
sa_rc_t sa_addr_s2a(sa_addr_t *saa, const struct sockaddr *sabuf, socklen_t salen)
{
+ struct sockaddr_un *un;
struct sockaddr_in *sa4;
#ifdef AF_INET6
struct sockaddr_in6 *sa6;
#endif
- struct protoent *pe;
int sf;
if (saa == NULL || sabuf == NULL || salen == 0)
@@ -360,32 +383,34 @@
/* fill in family */
sf = 0;
- if (sizeof(struct sockaddr_in) == salen) {
+ if (sizeof(struct sockaddr_un) == salen) {
+ un = (struct sockaddr_un *)((void *)sabuf);
+ if (un->sun_family == AF_LOCAL)
+ sf = AF_LOCAL;
+ }
+ if (sf == 0 && sizeof(struct sockaddr_in) == salen) {
sa4 = (struct sockaddr_in *)((void *)sabuf);
if (sa4->sin_family == AF_INET)
sf = AF_INET;
}
#ifdef AF_INET6
- else if (sizeof(struct sockaddr_in6) == salen) {
+ if (sf == 0 && sizeof(struct sockaddr_in6) == salen) {
sa6 = (struct sockaddr_in6 *)((void *)sabuf);
if (sa6->sin6_family == AF_INET6)
sf = AF_INET6;
}
#endif
+ if (sf == 0)
+ return SA_ERR_ARG;
saa->nFamily = sf;
- /* fill in protocol */
- if ((pe = getprotobyname("tcp")) != NULL)
- saa->nProto = pe->p_proto;
- else
- saa->nProto = 0;
return SA_OK;
}
sa_rc_t sa_addr_a2u(sa_addr_t *saa, char **uri)
{
char uribuf[1024];
- struct protoent *pe;
+ struct sockaddr_un *un;
struct sockaddr_in *sa4;
#ifdef AF_INET6
struct sockaddr_in6 *sa6;
@@ -395,23 +420,27 @@
if (saa == NULL || uri == NULL)
return SA_ERR_ARG;
- if ((pe = getprotobynumber(saa->nProto)) == NULL)
- return SA_ERR_SYS;
- if (saa->nFamily == AF_INET) {
- sa4 = (struct sockaddr_in *)((void *)saa->saBuf);
- inet_ntop(AF_INET, &sa4->sin_addr.s_addr, caHost, sizeof(caHost));
- nPort = ntohs(sa4->sin_port);
+ if (saa->nFamily == AF_LOCAL) {
+ un = (struct sockaddr_un *)((void *)saa->saBuf);
+ sa_msnprintf(uribuf, sizeof(uribuf), "unix:%s", un->sun_path);
}
+ else {
+ if (saa->nFamily == AF_INET) {
+ sa4 = (struct sockaddr_in *)((void *)saa->saBuf);
+ inet_ntop(AF_INET, &sa4->sin_addr.s_addr, caHost, sizeof(caHost));
+ nPort = ntohs(sa4->sin_port);
+ }
#ifdef AF_INET6
- else if (saa->nFamily == AF_INET6) {
- sa6 = (struct sockaddr_in6 *)((void *)saa->saBuf);
- inet_ntop(AF_INET6, &sa6->sin6_addr.s6_addr, caHost, sizeof(caHost));
- nPort = ntohs(sa6->sin6_port);
- }
+ else if (saa->nFamily == AF_INET6) {
+ sa6 = (struct sockaddr_in6 *)((void *)saa->saBuf);
+ inet_ntop(AF_INET6, &sa6->sin6_addr.s6_addr, caHost, sizeof(caHost));
+ nPort = ntohs(sa6->sin6_port);
+ }
#endif
- else
- return SA_ERR_ARG;
- sa_msnprintf(uribuf, sizeof(uribuf), "%s://%s:%d", pe->p_name, caHost, nPort);
+ else
+ return SA_ERR_ARG;
+ sa_msnprintf(uribuf, sizeof(uribuf), "inet://%s:%d", caHost, nPort);
+ }
*uri = strdup(uribuf);
return SA_OK;
}
@@ -428,22 +457,53 @@
return SA_OK;
}
-static sa_rc_t sa_socket_init(sa_t *sa, int family, int proto)
+static sa_rc_t sa_socket_init(sa_t *sa, int nFamily)
{
- int type;
+ int nType;
+ int nProto;
+ struct protoent *pe;
+ char *cpProto;
if (sa == NULL)
return SA_ERR_ARG;
- if (proto == IPPROTO_TCP)
- type = SOCK_STREAM;
- else if (proto == IPPROTO_UDP)
- type = SOCK_DGRAM;
- else
- return SA_ERR_ARG;
+
+ /* only perform operation if socket still do not exists */
if (sa->sSocket != -1)
return SA_ERR_USE;
- if ((sa->sSocket = socket(family, type, proto)) == -1)
+
+ /* determine socket type */
+ if (sa->eType == SA_TYPE_STREAM)
+ nType = SOCK_STREAM;
+ else if (sa->eType == SA_TYPE_DATAGRAM)
+ nType = SOCK_DGRAM;
+ else
+ return SA_ERR_ARG;
+
+ /* determine socket protocol */
+ if (nFamily == AF_LOCAL)
+ nProto = 0;
+#ifdef AF_INET6
+ else if (nFamily == AF_INET || nFamily == AF_INET6) {
+#else
+ else if (nFamily == AF_INET) {
+#endif
+ if (nType == SOCK_STREAM)
+ cpProto = "tcp";
+ else if (nType == SOCK_DGRAM)
+ cpProto = "udp";
+ else
+ return SA_ERR_INT;
+ if ((pe = getprotobyname(cpProto)) == NULL)
+ return SA_ERR_SYS;
+ nProto = pe->p_proto;
+ }
+ else
+ return SA_ERR_ARG;
+
+ /* create the socket */
+ if ((sa->sSocket = socket(nFamily, nType, nProto)) == -1)
return SA_ERR_SYS;
+
return SA_OK;
}
@@ -464,6 +524,7 @@
if ((sa = (sa_t *)malloc(sizeof(sa_t))) == NULL)
return SA_ERR_MEM;
+ sa->eType = SA_TYPE_STREAM;
sa->sSocket = -1;
sa->bTimeout = 0;
sa->nReadLen = 0;
@@ -496,6 +557,16 @@
return SA_OK;
}
+sa_rc_t sa_type(sa_t *sa, sa_type_t type)
+{
+ if (sa == NULL)
+ return SA_ERR_ARG;
+ if (type != SA_TYPE_STREAM && type != SA_TYPE_DATAGRAM)
+ return SA_ERR_ARG;
+ sa->eType = type;
+ return SA_OK;
+}
+
sa_rc_t sa_timeout(sa_t *sa, long sec, long usec)
{
if (sa == NULL)
@@ -557,12 +628,17 @@
sa_rc_t sa_bind(sa_t *sa, sa_addr_t *laddr)
{
sa_rc_t rv;
+ struct sockaddr_un *un;
if (sa == NULL || laddr == NULL)
return SA_ERR_ARG;
if (sa->sSocket == -1)
- if ((rv = sa_socket_init(sa, laddr->nFamily, laddr->nProto)) != SA_OK)
+ if ((rv = sa_socket_init(sa, laddr->nFamily)) != SA_OK)
return rv;
+ if (laddr->nFamily == AF_LOCAL) {
+ un = (struct sockaddr_un *)((void *)laddr->saBuf);
+ unlink(un->sun_path);
+ }
if (bind(sa->sSocket, laddr->saBuf, laddr->slBuf) == -1)
return SA_ERR_SYS;
return SA_OK;
@@ -577,9 +653,10 @@
if (sa == NULL)
return SA_ERR_ARG;
-
+ if (sa->eType != SA_TYPE_STREAM)
+ return SA_ERR_USE;
if (sa->sSocket == -1)
- if ((rv = sa_socket_init(sa, raddr->nFamily, raddr->nProto)) != SA_OK)
+ if ((rv = sa_socket_init(sa, raddr->nFamily)) != SA_OK)
return rv;
if (!sa->bTimeout)
@@ -648,6 +725,8 @@
{
if (sa == NULL)
return SA_ERR_ARG;
+ if (sa->eType != SA_TYPE_STREAM)
+ return SA_ERR_USE;
if (sa->sSocket == -1)
/* at least sa_bind() has to be already performed */
return SA_ERR_USE;
@@ -672,6 +751,8 @@
if (sa == NULL)
return SA_ERR_ARG;
+ if (sa->eType != SA_TYPE_STREAM)
+ return SA_ERR_USE;
if (sa->sSocket == -1)
/* at least sa_listen() has to be already performed */
return SA_ERR_USE;
@@ -717,6 +798,8 @@
if (sa == NULL)
return SA_ERR_ARG;
sa_len = sizeof(sa_buf);
+ if (sa->sSocket == -1)
+ return SA_ERR_USE;
if (getpeername(sa->sSocket, (struct sockaddr *)&sa_buf, &sa_len) < 0)
return SA_ERR_SYS;
if ((rv = sa_addr_create(raddr)) != SA_OK)
@@ -741,6 +824,8 @@
if (sa == NULL)
return SA_ERR_ARG;
+ if (sa->sSocket == -1)
+ return SA_ERR_USE;
sa_len = sizeof(sa_buf);
if (getsockname(sa->sSocket, (struct sockaddr *)&sa_buf, &sa_len) < 0)
return SA_ERR_SYS;
@@ -757,6 +842,8 @@
{
if (sa == NULL || fd == NULL)
return SA_ERR_ARG;
+ if (sa->sSocket == -1)
+ return SA_ERR_USE;
*fd = sa->sSocket;
return SA_OK;
}
@@ -790,8 +877,12 @@
size_t res;
if (sa == NULL || cpBuf == NULL || nBufReq == 0)
- return 0;
-
+ return SA_ERR_ARG;
+ if (sa->eType != SA_TYPE_STREAM)
+ return SA_ERR_USE;
+ if (sa->sSocket == -1)
+ return SA_ERR_USE;
+
/* flush write buffer */
if (sa->nWriteLen > 0)
sa_flush(sa);
@@ -855,6 +946,10 @@
if (sa == NULL || buf == NULL || buflen == 0 || raddr == NULL)
return SA_ERR_ARG;
+ if (sa->eType != SA_TYPE_DATAGRAM)
+ return SA_ERR_USE;
+ if (sa->sSocket == -1)
+ return SA_ERR_USE;
if (sa->bTimeout) {
FD_ZERO(&fds);
FD_SET(sa->sSocket, &fds);
@@ -888,6 +983,10 @@
if (sa == NULL)
return SA_ERR_ARG;
+ if (sa->eType != SA_TYPE_STREAM)
+ return SA_ERR_USE;
+ if (sa->sSocket == -1)
+ return SA_ERR_USE;
res = 0;
while (res < (nBufReq-1)) {
sa_read(sa, &c, 1, &n);
@@ -932,6 +1031,10 @@
if (sa == NULL)
return SA_ERR_ARG;
+ if (sa->eType != SA_TYPE_STREAM)
+ return SA_ERR_USE;
+ if (sa->sSocket == -1)
+ return SA_ERR_USE;
if (nBufReq > (sa->nWriteSize - sa->nWriteLen)) {
/* not enough space in buffer, so flush buffer */
@@ -964,9 +1067,17 @@
{
size_t n;
fd_set fds;
+ sa_rc_t rv;
if (sa == NULL || buf == NULL || buflen == 0 || raddr == NULL)
return SA_ERR_ARG;
+ if (sa->eType != SA_TYPE_DATAGRAM)
+ return SA_ERR_USE;
+ if (sa->sSocket == -1)
+ if ((rv = sa_socket_init(sa, raddr->nFamily)) != SA_OK)
+ return rv;
+ if (sa->sSocket == -1)
+ return SA_ERR_USE;
if (sa->bTimeout) {
FD_ZERO(&fds);
FD_SET(sa->sSocket, &fds);
@@ -1006,6 +1117,10 @@
if (sa == NULL)
return SA_ERR_ARG;
+ if (sa->eType != SA_TYPE_STREAM)
+ return SA_ERR_USE;
+ if (sa->sSocket == -1)
+ return SA_ERR_USE;
while (sa->nWriteLen > 0) {
n = sa_write_raw(sa, sa->cpWriteBuf, sa->nWriteLen);
if (n <= 0)
@@ -1023,6 +1138,10 @@
if (sa == NULL || flags == NULL)
return SA_ERR_ARG;
+ if (sa->eType != SA_TYPE_STREAM)
+ return SA_ERR_USE;
+ if (sa->sSocket == -1)
+ return SA_ERR_USE;
how = 0;
if (strcmp(flags, "r") == 0)
how = SHUT_RD;
|