Update of /cvsroot/moodns/moodns/src
In directory usw-pr-cvs1:/tmp/cvs-serv27471/src
Modified Files:
util.c spawn.c socket.h socket.c
Log Message:
lots of changes
Index: util.c
===================================================================
RCS file: /cvsroot/moodns/moodns/src/util.c,v
retrieving revision 1.1
retrieving revision 1.2
diff -C2 -d -r1.1 -r1.2
*** util.c 19 Jun 2002 14:01:05 -0000 1.1
--- util.c 20 Jul 2002 17:02:11 -0000 1.2
***************
*** 9,13 ****
#include "util.h"
!
/* die is meant to alert user errors. */
--- 9,13 ----
#include "util.h"
! #define DEBUG
/* die is meant to alert user errors. */
Index: spawn.c
===================================================================
RCS file: /cvsroot/moodns/moodns/src/spawn.c,v
retrieving revision 1.1
retrieving revision 1.2
diff -C2 -d -r1.1 -r1.2
*** spawn.c 19 Jun 2002 14:01:18 -0000 1.1
--- spawn.c 20 Jul 2002 17:02:11 -0000 1.2
***************
*** 1,5 ****
! /* Copyright (c) 2002 Ximian, Inc. All rights reserved. */
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
--- 1,26 ----
! /* Copyright (c) 2002 Ximian, Inc. All rights reserved.
! Copyright (c) 2002 Michael Wolf. All rights reserved.
!
! This file is part of moodns.
!
! moodns is free software; you can redistribute it and/or modify
! it under the terms of the GNU General Public License as published by
! the Free Software Foundation; either version 2 of the License, or
! (at your option) any later version.
!
! moodns is distributed in the hope that it will be useful,
! but WITHOUT ANY WARRANTY; without even the implied warranty of
! MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
! GNU General Public License for more details.
!
! You should have received a copy of the GNU General Public License
! along with moodns; if not, write to the Free Software
! Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
! */
#include <stdlib.h>
+ #include <stdio.h>
+ #include <string.h>
+ #include <errno.h>
#include <unistd.h>
#include <sys/types.h>
***************
*** 8,11 ****
--- 29,34 ----
#include <sys/resource.h>
+ extern char **environ; /* Aarrgh! */
+
#include "safewait.h"
#include "spawn.h"
***************
*** 17,20 ****
--- 40,44 ----
pid_t pid;
int status;
+ int ret;
struct rusage ru;
***************
*** 25,29 ****
break;
case 0:
! exect(command[0], command, envp);
break;
default:
--- 49,59 ----
break;
case 0:
! // exect(command[0], command, envp);
! if (envp != NULL) {
! environ = envp;
! }
! ret = execv(command[0], command);
! printf("unable to launch %s: %s\n", command[0], strerror(errno));
! exit(EXIT_FAILURE);
break;
default:
Index: socket.h
===================================================================
RCS file: /cvsroot/moodns/moodns/src/socket.h,v
retrieving revision 1.10
retrieving revision 1.11
diff -C2 -d -r1.10 -r1.11
*** socket.h 19 Jun 2002 13:55:51 -0000 1.10
--- socket.h 20 Jul 2002 17:02:11 -0000 1.11
***************
*** 32,37 ****
enum socket_domain { SOCKET_INTERNET = 0, SOCKET_LOCAL };
! enum socket_type { SOCKET_STREAM = 0, SOCKET_DATAGRAM };
enum socket_job { SOCKET_LISTENER = 0, SOCKET_SENDER, SOCKET_CLIENT };
typedef union socket_address_t {
--- 32,42 ----
enum socket_domain { SOCKET_INTERNET = 0, SOCKET_LOCAL };
! enum socket_type { SOCKET_STREAM = 0, SOCKET_DATAGRAM, SOCKET_SEQPACKET };
enum socket_job { SOCKET_LISTENER = 0, SOCKET_SENDER, SOCKET_CLIENT };
+ enum socket_blocking { SOCKET_BLOCKING = 0, SOCKET_NONBLOCKING };
+ /* maybe other attributes would be useful */
+ enum socket_close { SOCKET_READING = SHUT_RD, SOCKET_WRITING = SHUT_WR,
+ SOCKET_BOTH = SHUT_RDWR };
+
typedef union socket_address_t {
***************
*** 52,55 ****
--- 57,61 ----
enum socket_type type;
enum socket_job job;
+ enum socket_blocking blocking;
union {
struct sockaddr dummy;
***************
*** 59,67 ****
--- 65,76 ----
} socket_t;
+ /*@null@*/
socket_t *socket_listener(socket_address_t *addr, enum socket_domain domain,
enum socket_type type);
+ /*@null@*/
socket_t *socket_sender(socket_address_t *addr, enum socket_domain domain,
enum socket_type type);
socket_t *socket_accept(socket_t *s);
+ int socket_close(socket_t *s, enum socket_close sc);
size_t socket_recv(socket_t *s, byte_array *ba, size_t maxlen);
***************
*** 73,76 ****
--- 82,89 ----
size_t socket_send_poll(socket_t *s, byte_array *ba);
size_t socket_send_timeout(socket_t *s, byte_array *ba, int secs, int usecs);
+
+
+ /* attributes */
+ void socket_set_attribute_blocking(socket_t *, enum socket_blocking);
#endif
Index: socket.c
===================================================================
RCS file: /cvsroot/moodns/moodns/src/socket.c,v
retrieving revision 1.13
retrieving revision 1.14
diff -C2 -d -r1.13 -r1.14
*** socket.c 21 Feb 2002 05:16:21 -0000 1.13
--- socket.c 20 Jul 2002 17:02:11 -0000 1.14
***************
*** 39,42 ****
--- 39,45 ----
#include <arpa/inet.h>
#include <errno.h>
+ #include <assert.h>
+
+ #include "util.h"
#include "byte_array.h"
#include "mtime.h"
***************
*** 48,51 ****
--- 51,59 ----
#endif
+ static void socket_set_minimum(socket_t *, size_t);
+ static int socket_seqpacket_handshake(socket_t *);
+ static int handshake_send(const char *, socket_t *);
+ static int handshake_recv(char *, const char *, size_t, socket_t *s);
+
/* Handy shorthand. */
***************
*** 66,85 ****
return NULL;
! if (domain == SOCKET_INTERNET) {
sdomain = PF_INET;
! } else if (domain == SOCKET_LOCAL) {
sdomain = PF_LOCAL;
! } else {
abort();
! }
!
! if (type == SOCKET_STREAM) {
stype = SOCK_STREAM;
! } else if (type == SOCKET_DATAGRAM) {
stype = SOCK_DGRAM;
! } else {
abort();
! }
!
if ((s->fd = socket(sdomain, stype, 0)) == -1) {
perror("socket failed");
--- 74,93 ----
return NULL;
! if (domain == SOCKET_INTERNET)
sdomain = PF_INET;
! else if (domain == SOCKET_LOCAL)
sdomain = PF_LOCAL;
! else
abort();
!
! if (type == SOCKET_STREAM)
stype = SOCK_STREAM;
! else if (type == SOCKET_DATAGRAM)
stype = SOCK_DGRAM;
! else if (type == SOCKET_SEQPACKET)
! stype = SOCK_STREAM;
! else
abort();
!
if ((s->fd = socket(sdomain, stype, 0)) == -1) {
perror("socket failed");
***************
*** 88,92 ****
}
! if (setsockopt(s->fd, SOL_SOCKET, SO_REUSEADDR, &reuse, sizeof(reuse)) < 0)
fprintf(stderr, "setsockopt error.\n");
--- 96,100 ----
}
! if (setsockopt(s->fd, SOL_SOCKET, SO_REUSEADDR, &reuse, (socklen_t) sizeof(reuse)) < 0)
fprintf(stderr, "setsockopt error.\n");
***************
*** 109,132 ****
}
! if (domain == SOCKET_INTERNET) {
ret = bind(s->fd, (struct sockaddr *) &s->socket_address.internet,
! sizeof(struct sockaddr_in));
! } else if (domain == SOCKET_LOCAL) {
ret = bind(s->fd, (struct sockaddr *) &s->socket_address.local,
! sizeof(struct sockaddr_un));
! } else {
abort();
! }
!
if (ret == -1) {
perror("bind failed");
! close(s->fd);
xfree(s);
return NULL;
}
! if (type == SOCKET_STREAM && listen(s->fd, 40) == -1) {
perror("listen failed");
! close(s->fd);
xfree(s);
return NULL;
--- 117,144 ----
}
! if (domain == SOCKET_INTERNET)
ret = bind(s->fd, (struct sockaddr *) &s->socket_address.internet,
! (socklen_t) sizeof(struct sockaddr_in));
! else if (domain == SOCKET_LOCAL)
ret = bind(s->fd, (struct sockaddr *) &s->socket_address.local,
! (socklen_t) sizeof(struct sockaddr_un));
! else
abort();
!
if (ret == -1) {
perror("bind failed");
! ret = close(s->fd);
! if (ret == -1)
! perror("close failed too");
xfree(s);
return NULL;
}
! if ((type == SOCKET_STREAM || type == SOCKET_SEQPACKET)
! && listen(s->fd, 40) == -1) {
perror("listen failed");
! ret = close(s->fd);
! if (ret == -1)
! perror("close failed too");
xfree(s);
return NULL;
***************
*** 150,168 ****
int ret;
! if (domain == SOCKET_INTERNET) {
sdomain = PF_INET;
! } else if (domain == SOCKET_LOCAL) {
sdomain = PF_LOCAL;
! } else {
abort();
- }
! if (type == SOCKET_STREAM) {
stype = SOCK_STREAM;
! } else if (type == SOCKET_DATAGRAM) {
stype = SOCK_DGRAM;
! } else {
abort();
- }
if ((s->fd = socket(sdomain, stype, 0)) == -1) {
--- 162,180 ----
int ret;
! if (domain == SOCKET_INTERNET)
sdomain = PF_INET;
! else if (domain == SOCKET_LOCAL)
sdomain = PF_LOCAL;
! else
abort();
! if (type == SOCKET_STREAM)
stype = SOCK_STREAM;
! else if (type == SOCKET_DATAGRAM)
stype = SOCK_DGRAM;
! else if (type == SOCKET_SEQPACKET)
! stype = SOCK_STREAM;
! else
abort();
if ((s->fd = socket(sdomain, stype, 0)) == -1) {
***************
*** 175,181 ****
struct in_addr in;
u32 remote;
! if (!inet_aton(addr->internet.address, &in)) {
! xfree(s);
! return NULL;
}
remote = (u32) in.s_addr;
--- 187,197 ----
struct in_addr in;
u32 remote;
! if (addr->internet.address != NULL) {
! if (inet_aton(addr->internet.address, /*@out@*/ &in) == 0) {
! xfree(s);
! return NULL;
! }
! } else {
! in.s_addr = addr->internet.ip;
}
remote = (u32) in.s_addr;
***************
*** 210,213 ****
--- 226,238 ----
s->job = SOCKET_SENDER;
+ if (s->type == SOCKET_SEQPACKET) {
+ ret = socket_seqpacket_handshake(s);
+ if (ret == 0) {
+ /* XXX: Clean up. */
+ goto done;
+ }
+ }
+
+ done:
return s;
}
***************
*** 220,223 ****
--- 245,251 ----
if (!client)
return NULL;
+ client->domain = s->domain;
+ client->type = s->type;
+ client->job = SOCKET_CLIENT;
if (s->type == SOCKET_STREAM) {
***************
*** 233,247 ****
} else if (s->type == SOCKET_DATAGRAM) {
client->fd = s->fd;
} else {
abort();
}
- client->domain = s->domain;
- client->type = s->type;
- client->job = SOCKET_CLIENT;
-
return client;
}
/* Receive data from a socket. The data that is received is appended to the
provided byte_array. (I think that's the most useful. Do you?) A maximum
--- 261,302 ----
} else if (s->type == SOCKET_DATAGRAM) {
client->fd = s->fd;
+ } else if (s->type == SOCKET_SEQPACKET) {
+ size_t size;
+ int h;
+ client->fd = accept(s->fd, (sa *) &client->socket_address.internet,
+ &size);
+ h = socket_seqpacket_handshake(client);
+ /* XXX: check h */
} else {
abort();
}
return client;
}
+ /* close a socket */
+
+ int
+ socket_close(socket_t *s, enum socket_close how)
+ {
+ /* XXX: fix this */
+ int ret;
+ assert(how == SOCKET_READING || how == SOCKET_WRITING ||
+ how == SOCKET_BOTH);
+ ret = shutdown(s->fd, how);
+ if (ret == -1 && errno != ENOTCONN) {
+ perror("shutdown failed");
+ abort();
+ }
+ if (s->domain == SOCKET_LOCAL && s->job == SOCKET_LISTENER) {
+ ret = unlink(s->socket_address.local.sun_path);
+ if (ret == -1)
+ abort(); /* XXX: not sure if this is correct behaviour. */
+ }
+
+ xfree(s);
+ return 1;
+ }
+
/* Receive data from a socket. The data that is received is appended to the
provided byte_array. (I think that's the most useful. Do you?) A maximum
***************
*** 249,252 ****
--- 304,309 ----
available will be read. */
+ /* Block indefinitely. */
+
size_t
socket_recv(socket_t *s, byte_array *data, size_t maxlen)
***************
*** 255,258 ****
--- 312,317 ----
}
+ /* Don't block. */
+
size_t
socket_recv_poll(socket_t *s, byte_array *data, size_t maxlen)
***************
*** 261,264 ****
--- 320,325 ----
}
+ /* Block for the specified amount of time. */
+
size_t
socket_recv_timeout(socket_t *s, byte_array *data, size_t maxlen,
***************
*** 313,322 ****
if (s->type == SOCKET_STREAM) {
if (maxlen > 0) {
! buf = (u8 *) malloc(maxlen * sizeof(u8));
t = recv(s->fd, buf, maxlen, 0);
byte_array_cats(n, buf, t);
} else {
/* XXX: 512 is a magic number. */
! buf = (u8 *) malloc(512 * sizeof(u8));
do {
t = recv(s->fd, buf, 512, 0);
--- 374,387 ----
if (s->type == SOCKET_STREAM) {
if (maxlen > 0) {
! buf = (u8 *) alloca(maxlen * sizeof(u8));
t = recv(s->fd, buf, maxlen, 0);
+ if (t == 0) {
+ byte_array_destroy(n);
+ goto done;
+ }
byte_array_cats(n, buf, t);
} else {
/* XXX: 512 is a magic number. */
! buf = (u8 *) alloca(512 * sizeof(u8));
do {
t = recv(s->fd, buf, 512, 0);
***************
*** 335,346 ****
if (maxlen == 0 || maxlen > 512)
maxlen = 512;
! buf = (u8 *) malloc(maxlen * sizeof(u8));
t = recvfrom(s->fd, buf, maxlen, 0, (sa *) &s->socket_address.dummy,
&f);
if (t == -1) {
perror("recvfrom failed");
return 0;
}
byte_array_cats(n, buf, t);
} else {
abort();
--- 400,431 ----
if (maxlen == 0 || maxlen > 512)
maxlen = 512;
! buf = (u8 *) alloca(maxlen * sizeof(u8));
t = recvfrom(s->fd, buf, maxlen, 0, (sa *) &s->socket_address.dummy,
&f);
if (t == -1) {
perror("recvfrom failed");
+ byte_array_destroy(n);
return 0;
}
byte_array_cats(n, buf, t);
+ } else if (s->type == SOCKET_SEQPACKET) {
+ ssize_t len;
+ socket_set_minimum(s, 4);
+ buf = (u8 *) alloca(4 * sizeof(u8));
+ t = recv(s->fd, buf, 4, 0);
+ if (t == 0) {
+ byte_array_destroy(n);
+ goto done;
+ }
+ len = ntohl(((u32 *) buf)[0]);
+ socket_set_minimum(s, len);
+ buf = (u8 *) alloca(len * sizeof(u8));
+ t = recv(s->fd, buf, len, 0);
+ if (t != len) {
+ byte_array_destroy(n);
+ goto done;
+ }
+ printf_on_debug("read '%s'\n", buf);
+ byte_array_cats(n, buf, len);
} else {
abort();
***************
*** 349,353 ****
byte_array_cat(data, n);
byte_array_destroy(n);
! free(buf);
l = t;
--- 434,438 ----
byte_array_cat(data, n);
byte_array_destroy(n);
! // free(buf);
l = t;
***************
*** 380,383 ****
--- 465,470 ----
int ret;
+ byte_array *seq_ba = (byte_array *) 0x123;
+
if (secs == -1 && usecs == -1) {
tv = NULL;
***************
*** 455,458 ****
--- 542,566 ----
abort();
}
+ } else if (s->type == SOCKET_SEQPACKET) {
+ // byte_array *t;
+ static int foo = 1;
+
+ #ifdef WITH_DMALLOC
+ int dmv_ret = 0;
+ // dmv_ret = dmalloc_verify(seq_ba);
+ #endif
+
+
+ // printf("been here %d times now\n", foo); ++foo;
+ /* The line immediately below causes a failure when some forms
+ of malloc checking (dmalloc, glibc's MALLOC_CHECK_) but not
+ others (efence). I do not know why. */
+ seq_ba = (byte_array *) xcalloc(1, sizeof(byte_array));
+ byte_array_catu32(seq_ba, htonl(data->len));
+ printf_on_debug("length is %d\n", seq_ba->len);
+ // printf_on_debug("appending this: '%s'\n", data->data);
+ byte_array_cat(seq_ba, data);
+ ll = send(s->fd, seq_ba->data, seq_ba->len, 0);
+ byte_array_destroy(seq_ba);
} else {
abort();
***************
*** 460,463 ****
--- 568,774 ----
return ll;
+ }
+ void
+ socket_set_minimum(socket_t *s, size_t min)
+ {
+ int ret;
+
+ ret = setsockopt(s->fd, SOL_SOCKET, SO_RCVLOWAT, &min, sizeof(min));
+ if (ret == -1) {
+ perror("setsockopt failed");
+ abort();
+ }
+ }
+
+ int
+ socket_seqpacket_handshake(socket_t *s)
+ {
+ int retval;
+ const u8 *msg1 = "SOCKET_SEQPACKET";
+ const u8 *msg2 = "SOCKET_SEQPACKET ACCEPTED";
+ const u8 *msg3 = "OK";
+ int state;
+ u8 *buf;
+ size_t buflen;
+ int ret;
+
+ assert(s->type == SOCKET_SEQPACKET);
+ if (s->job == SOCKET_SENDER)
+ state = 0;
+ else if (s->job == SOCKET_CLIENT)
+ state = 10;
+ else
+ abort();
+
+ buflen = strlen(msg2);
+ buf = (u8 *) alloca(buflen + 1);
+
+ while (1) {
+ switch (state) {
+ case 0:
+ ret = handshake_send(msg1, s);
+ if (ret == 0)
+ state = 999;
+ else
+ state = 1;
+ break;
+ case 1:
+ ret = handshake_recv(buf, msg2, buflen, s);
+ if (ret == 0)
+ state = 999;
+ else
+ state = 2;
+ break;
+ case 2:
+ ret = handshake_send(msg3, s);
+ if (ret == 0)
+ state = 999;
+ else
+ state = 3;
+ break;
+ case 3:
+ ret = handshake_recv(buf, msg3, strlen(msg3), s);
+ if (ret == 0)
+ state = 999;
+ else
+ state = 4;
+ break;
+ case 4:
+ /* I think we're all set. */
+ state = 1000;
+ break;
+ case 10:
+ ret = handshake_recv(buf, msg1, strlen(msg1), s);
+ if (ret == 0)
+ state = 999;
+ else
+ state = 11;
+ break;
+ case 11:
+ ret = handshake_send(msg2, s);
+ if (ret == 0)
+ state = 999;
+ else
+ state = 12;
+ break;
+ case 12:
+ ret = handshake_recv(buf, msg3, strlen(msg3), s);
+ if (ret == 0)
+ state = 999;
+ else
+ state = 13;
+ break;
+ case 13:
+ ret = handshake_send(msg3, s);
+ if (ret == 0)
+ state = 999;
+ else
+ state = 14;
+ break;
+ case 14:
+ /* I think we're all set. */
+ state = 1000;
+ break;
+ case 999:
+ /* Cleanup on failure. */
+ /* XXX: actually do this. */
+ goto done;
+ break;
+ case 1000:
+ retval = 1;
+ /* Cleanup after success. */
+ /* XXX: actually do this. */
+ goto done;
+ break;
+ default:
+ fprintf(stderr, "screwed up state\n");
+ abort();
+ }
+ }
+
+ done:
+ return retval;
+ }
+
+ int
+ handshake_send(const char *msg, socket_t *s)
+ {
+ int retval;
+ int ret;
+ fd_set wset;
+ struct timeval tv;
+ ssize_t ll;
+ ssize_t mlen;
+
+
+
+ mlen = strlen(msg);
+ FD_ZERO(&wset);
+ FD_SET(s->fd, &wset);
+ tv.tv_sec = 2000;
+ tv.tv_usec = 0;
+ while ((ret = select(s->fd + 1, NULL, &wset, NULL, &tv)) <= 0) {
+ if (errno == EINTR)
+ continue;
+ else {
+ perror("select failed");
+ abort();
+ }
+ }
+ ll = send(s->fd, msg, mlen, 0);
+ if (ll < mlen)
+ retval = 0;
+ else
+ retval = 1;
+
+ return retval;
+ }
+
+ int
+ handshake_recv(char *msg, const char *expected_text,
+ size_t expected_len, socket_t *s)
+ {
+ int retval;
+ int ret;
+ fd_set rset;
+ struct timeval tv;
+ ssize_t ll;
+
+ socket_set_minimum(s, expected_len);
+
+ FD_ZERO(&rset);
+ FD_SET(s->fd, &rset);
+ tv.tv_sec = 2000;
+ tv.tv_usec = 0;
+ memset(msg, '\0', expected_len);
+ while ((ret = select(s->fd + 1, &rset, NULL, NULL, &tv)) <= 0) {
+ if (errno == EINTR)
+ continue;
+ else {
+ perror("select failed");
+ abort();
+ }
+ }
+ if (ret == 0) {
+ retval = 0;
+ goto done;
+ }
+ ll = recv(s->fd, msg, expected_len, 0);
+ /* This shouldn't be necessary due to the socket option set above. */
+ /* if (ll != expected_len)
+ retval = 0; */
+ if (strncmp(msg, expected_text, expected_len) == 0)
+ retval = 1;
+ else
+ retval = 0;
+ done:
+ return retval;
+ }
+
+
+ void
+ socket_set_attribute_blocking(socket_t *s, enum socket_blocking sab)
+ {
+ s->blocking_attribute = sab;
}
|