[Author Prev][Author Next][Thread Prev][Thread Next][Author Index][Thread Index]
[or-cvs] r8495: added some changes to epoll() version. (bsockets/trunk/contrib/liboverlapped)
Author: chiussi
Date: 2006-09-24 22:45:45 -0400 (Sun, 24 Sep 2006)
New Revision: 8495
Modified:
bsockets/trunk/contrib/liboverlapped/cmd.c
bsockets/trunk/contrib/liboverlapped/cmd.h
bsockets/trunk/contrib/liboverlapped/env.c
bsockets/trunk/contrib/liboverlapped/env.h
bsockets/trunk/contrib/liboverlapped/file.c
bsockets/trunk/contrib/liboverlapped/file.h
bsockets/trunk/contrib/liboverlapped/list.c
bsockets/trunk/contrib/liboverlapped/misc.c
bsockets/trunk/contrib/liboverlapped/overlapped.c
bsockets/trunk/contrib/liboverlapped/overlapped.h
bsockets/trunk/contrib/liboverlapped/socket.c
bsockets/trunk/contrib/liboverlapped/socket.h
bsockets/trunk/contrib/liboverlapped/test.c
bsockets/trunk/contrib/liboverlapped/test.h
Log:
added some changes to epoll() version.
Modified: bsockets/trunk/contrib/liboverlapped/cmd.c
===================================================================
--- bsockets/trunk/contrib/liboverlapped/cmd.c 2006-09-25 02:31:56 UTC (rev 8494)
+++ bsockets/trunk/contrib/liboverlapped/cmd.c 2006-09-25 02:45:45 UTC (rev 8495)
@@ -7,6 +7,7 @@
#include "misc.h"
#include "list.h"
#include "socket.h"
+#include "file.h"
void cmd_post(struct _cmd *cmd, struct _file_env *env) {
@@ -56,47 +57,62 @@
cmd->ret = ret;
cmd->err = err;
+
ASSERT(SetEvent(cmd->done_e));
}
+void cmd_defer(struct _cmd *cmd, int code) {
+
+ if (cmd->f->blocking)
+ cmd->wait = TRUE;
+
+ if (!code) {
+ code = EAGAIN;
+ }
+
+ cmd_done(cmd,-1,code);
+
+}
+
//cmd2 is ignored
void cmd_dispatch(struct _cmd *cmd2, struct _file_env *env) {
struct _cmd *cmd;
- struct _file *f;
- struct _socket *s;
-
int err;
int out;
cmd_next(&cmd,env);
+
if (cmd == NULL)
return;
+ cmd->wait = FALSE;
+
if (cmd->fd != -1) {
- f = file_get(cmd->fd,env);
- if (f == NULL) {
+ cmd->f = file_get(cmd->fd,env);
+ if (cmd->f == NULL) {
cmd_done(cmd,-1,errno);
cmd = NULL;
}
- switch (f->type) {
+ switch (cmd->f->type) {
case FT_SOCKET:
- s = f->data;
+ cmd->s = cmd->f->data;
+ ASSERT(cmd->s != NULL);
break;
default:
ASSERT(FALSE);
break;
}
+ }
+ //todo -- check if is socket before using socket function
- }
-
if (cmd != NULL) {
switch (cmd->type) {
@@ -115,25 +131,45 @@
break;
case CMD_SOCKET_CONNECT:
- socket_connect(f,s,cmd,env);
+ socket_connect(cmd,env);
break;
case CMD_FILE_CLOSE:
- //if there is an outstanding error, be sure to report it
- if (f->err) {
+ //if there is an outstanding error, report it
+ if (cmd->f->err) {
out = -1;
- err = f->err;
+ err = cmd->f->err;
} else {
out = 0;
}
- file_close(f,env);
-
+ file_close(cmd->f,env);
cmd_done(cmd,out,err);
break;
+ case CMD_SOCKET_BIND:
+ socket_bind(cmd,env);
+ break;
+
+ case CMD_SOCKET_LISTEN:
+ socket_listen(cmd,env);
+ break;
+
+ case CMD_SOCKET_GET_NAME:
+ socket_get_name(cmd,env);
+ break;
+
+ case CMD_FILE_WAIT:
+ file_wait(cmd,(int)cmd->arg[0],env);
+ break;
+
+ case CMD_FILE_ERROR:
+ file_last_error(cmd->f,cmd->arg[0]);
+ cmd_done(cmd,0,0);
+ break;
+
default:
ASSERT(FALSE);
break;
Modified: bsockets/trunk/contrib/liboverlapped/cmd.h
===================================================================
--- bsockets/trunk/contrib/liboverlapped/cmd.h 2006-09-25 02:31:56 UTC (rev 8494)
+++ bsockets/trunk/contrib/liboverlapped/cmd.h 2006-09-25 02:45:45 UTC (rev 8495)
@@ -2,36 +2,30 @@
#define _CMD_H_
#include <windows.h>
+
#include "env.h"
-struct _cmd {
-
- HANDLE done_e;
-
- void *arg[32];
-
- int type;
-
- int ret;
- int err;
-
- int fd;
-};
-
void cmd_post(struct _cmd*, struct _file_env*);
void cmd_next(struct _cmd**, struct _file_env*);
void cmd_done(struct _cmd*, int, int);
+void cmd_defer(struct _cmd*, int);
void cmd_dispatch(struct _cmd *cmd, struct _file_env*);
#define CMD_PING 1
#define CMD_FILE_CLOSE 10
+#define CMD_FILE_ERROR 11 //get last file error, if any
+#define CMD_FILE_WAIT 19
-
#define CMD_SOCKET_NEW 20
#define CMD_SOCKET_CONNECT 21
+#define CMD_SOCKET_BIND 22
+#define CMD_SOCKET_LISTEN 23
+#define CMD_SOCKET_ACCEPT 24
+#define CMD_SOCKET_GET_NAME 40
+
#define CMD_SHUTDOWN 100
Modified: bsockets/trunk/contrib/liboverlapped/env.c
===================================================================
--- bsockets/trunk/contrib/liboverlapped/env.c 2006-09-25 02:31:56 UTC (rev 8494)
+++ bsockets/trunk/contrib/liboverlapped/env.c 2006-09-25 02:45:45 UTC (rev 8495)
@@ -6,12 +6,20 @@
#include "env.h"
#include "cmd.h"
#include "list.h"
+#include "file.h"
static struct _file_env_options default_env_options = {
1000,
- 1000
+ 1000,
+ 10,
+ 10
};
+//make sure nothing is wrong with the options the user gave
+int env_check_options(struct _file_env_options *opt) {
+ return -1;
+}
+
void env_main_loop(struct _file_env *env) {
int i;
@@ -38,12 +46,13 @@
default:
i = r - WAIT_OBJECT_0;
- env->ev_callback[i](env->cmd[i],env);
+ env->ev_callback[i](env->ev_data[i],env);
break;
}
}
}
+
void env_ping(struct _file_env *env) {
struct _cmd cmd;
@@ -89,12 +98,12 @@
}
if (env->fd != NULL) {
- for (i=0; i<env->opt.maxfiles; i++)
+ for (i=0; i<env->opt.max_files; i++)
if (env->fd[i] != NULL) {
file_close(env->fd[i],env);
}
- for (i=0; i<env->opt.maxfiles; i++)
+ for (i=0; i<env->opt.max_files; i++)
ASSERT(env->fd[i] == NULL);
}
@@ -110,6 +119,9 @@
list_free(env->cmd_q);
}
+ if (env->waiting_to_connect != NULL) {
+ list_free(env->waiting_to_connect);
+ }
for (i=0; i<WSA_MAXIMUM_WAIT_EVENTS; i++) {
if (env->ev[i] != NULL) {
@@ -132,7 +144,6 @@
int out;
//note: the user is responsible for manually init'ing winsock
-
if (opt == NULL) {
opt = &default_env_options;
}
@@ -149,27 +160,35 @@
env->post_m = NULL;
env->cmd_q = NULL;
env->thread = NULL;
+ env->waiting_to_connect = NULL;
+ env->connections_half_open = 0;
+
for (i=0; i<WSA_MAXIMUM_WAIT_EVENTS;i++) {
env->ev[i] = NULL;
}
memcpy(&env->opt,opt, sizeof(struct _file_env_options));
- env->fd = malloc(sizeof(struct _file*)*opt->maxfiles);
+ env->fd = malloc(sizeof(struct _file*)*opt->max_files);
- for (i=0; i<opt->maxfiles; i++) {
+ for (i=0; i<opt->max_files; i++) {
env->fd[i] = NULL;
}
env->free_q = list_new();
+ CHECK(env->free_q != NULL,0);
- for (i=0; i<opt->maxfiles; i++) {
+ env->waiting_to_connect = list_new();
+ CHECK(env->waiting_to_connect != NULL,0);
+
+ for (i=0; i<opt->max_files; i++) {
list_enqueue((void*) i,env->free_q);
}
for (i=0; i<WSA_MAXIMUM_WAIT_EVENTS; i++) {
env->ev[i] = WSACreateEvent();
+ env->ev_callback[i] = NULL;
CHECK0(env->ev[i] != WSA_INVALID_EVENT);
}
Modified: bsockets/trunk/contrib/liboverlapped/env.h
===================================================================
--- bsockets/trunk/contrib/liboverlapped/env.h 2006-09-25 02:31:56 UTC (rev 8494)
+++ bsockets/trunk/contrib/liboverlapped/env.h 2006-09-25 02:45:45 UTC (rev 8495)
@@ -2,10 +2,73 @@
#define _ENV_H_
#include "overlapped.h"
-#include "file.h"
+#include "list.h"
-struct _cmd;
+struct _file {
+ /*system file identifier*/
+ void *handle;
+
+ /*local file identifier*/
+ int fd;
+
+ /*what time of file are we (ie, disk file, socket, epoll, etc)*/
+ int type;
+ void *data; //pointer to type specific data
+
+ /*input and output streams*/
+ struct _list *in_buf;
+ struct _list *out_buf;
+
+ /*the last error that occured during file processin
+ (should be reset everytime it is looked at) */
+ int err;
+
+ /*set if we are open/connected to something*/
+ int open;
+
+ /*true if we are in blocking mode*/
+ int blocking;
+
+ /*state - is the socket currently one of the above*/
+ int ready[32];
+
+ /*lists of callbacks to be executed if and when the socket becomes available*/
+ struct _list *read_callbacks;
+ struct _list *write_callbacks;
+
+ /*records the value of the last error that occured*/
+ int error;
+
+
+};
+
+struct _cmd {
+
+ HANDLE done_e;
+
+ void *arg[32];
+
+ int type;
+
+ int ret;
+ int err;
+
+ int fd;
+
+ /*these can only be touched after command as been dispatched*/
+ struct _file *f;
+ struct _socket *s;
+
+ /*a helper member, makes code prettier in some places*/
+ int i;
+
+ /*true if command as been defered (ie, tell user EAGAIN)*/
+ int wait;
+
+};
+
+
struct _file_env {
/*environment options*/
@@ -34,9 +97,16 @@
(struct _cmd*, struct _file_env *);
//holds the command associated with that spot on ev
- struct _cmd *cmd[WSA_MAXIMUM_WAIT_EVENTS];
+ void *ev_data[WSA_MAXIMUM_WAIT_EVENTS];
+
+ /* */
+ int connections_half_open;
+ struct _list *waiting_to_connect;
+
};
+void env_watch_socket_event(struct _cmd *, void *, struct _file_env *);
+void env_unwatch_socket_event(SOCKET s, int i, struct _file_env *);
#endif
Modified: bsockets/trunk/contrib/liboverlapped/file.c
===================================================================
--- bsockets/trunk/contrib/liboverlapped/file.c 2006-09-25 02:31:56 UTC (rev 8494)
+++ bsockets/trunk/contrib/liboverlapped/file.c 2006-09-25 02:45:45 UTC (rev 8495)
@@ -5,35 +5,112 @@
#include "misc.h"
#include "env.h"
#include "list.h"
+#include "cmd.h"
+struct _callback {
+ void (*fun)();
+ void *data;
+};
+
+struct _callback *cb_new(void *fun, void *data) {
+
+ struct _callback *out;
+
+ out = (struct _callback*) malloc(sizeof(struct _callback));
+
+ if (out != NULL) {
+
+ out->fun = fun;
+ out->data = data;
+ } else {
+ errno = ENOMEM;
+ }
+ return out;
+}
+
+void cb_free(struct _callback *cb) {
+ free(cb);
+}
+
struct _file *file_get(int fd, struct _file_env *env) {
struct _file *out;
- if (fd < 0 || fd >= env->opt.maxfiles) {
-
+ if (fd < 0 || fd >= env->opt.max_files) {
errno = EINVAL;
out = NULL;
-
} else {
-
out = env->fd[fd];
-
if (out == NULL) {
errno = EBADF;
}
+ }
+ return out;
+}
+void file_control(struct _cmd *cmd, struct _file_env *env) {
+
+}
+
+void file_wait(struct _cmd *cmd, int state, struct _file_env *env) {
+
+ struct _callback *cb;
+ struct _list *l;
+
+ int out = 0;
+
+ if (!cmd->f->ready[state]) {
+
+ cb = cb_new(cmd_done,cmd);
+ CHECK(cb != NULL,0);
+
+ switch (state) {
+
+ case FILE_IS_READABLE:
+ l = cmd->f->read_callbacks;
+ break;
+
+ case FILE_IS_WRITABLE:
+ l = cmd->f->write_callbacks;
+ break;
+
+ default:
+ ASSERT(FALSE);
+ break;
+ }
+ CHECK(list_enqueue(cb,l) != NULL,0);
+ } else {
+ cmd_done(cmd,0,0);
}
- return out;
+ fail:
+ if (out == -1) {
+
+ cmd_done(cmd,-1,errno);
+
+ if (cb != NULL)
+ cb_free(cb);
+
+ }
+
+
}
-void file_exception(struct _file *f, int code) {
+//get and set the last error for this file
+void file_last_error(struct _file *f, int *r) {
+ *r = f->error;
+ f->error = 0;
+}
+void file_exception(struct _file *f, int code, struct _file_env *env) {
+
+ //raise readable and writable
+
switch (f->type) {
case FT_SOCKET:
+ //todo -- unwatch socket events
closesocket((SOCKET) f->handle);
break;
@@ -43,18 +120,50 @@
}
}
+void file_raise(struct _file *f, int type, int code, struct _file_env *env) {
+
+ struct _callback *cb;
+ struct _list *l;
+
+ /*set status bit*/
+ f->ready[type] = TRUE;
+
+
+ switch (type) {
+
+ case FILE_IS_READABLE:
+ l = f->read_callbacks;
+ break;
+
+ case FILE_IS_WRITABLE:
+ l = f->write_callbacks;
+ break;
+
+ default:
+ ASSERT(FALSE);
+ break;
+ }
+
+ /*does anyone want to know we are ready?*/
+ //todo -- iterate through list, dont use queue interface
+ while (list_dequeue(&cb,l) == 0) {
+ //todo -- if an epoll pointer, requeue, do not free
+ cb->fun(cb->data,0,0);
+ cb_free(cb);
+ }
+}
+
void file_close(struct _file *f, struct _file_env *env) {
if (f->fd != -1) {
- file_exception(f,ECLOSED);
- ASSERT(env->fd[f->fd] = f);
+ file_exception(f,ECLOSED,env);
+ ASSERT(env->fd[f->fd] == f);
env->fd[f->fd] = NULL;
}
if (f->in_buf != NULL) {
//todo dump in buffer
list_free(f->in_buf);
-
}
if (f->out_buf != NULL) {
@@ -62,6 +171,18 @@
list_free(f->out_buf);
}
+ if (f->read_callbacks != NULL) {
+ //todo -- assert list is empty
+ list_free(f->read_callbacks);
+ }
+
+ if (f->write_callbacks != NULL) {
+ //todo -- assert list is empty
+ list_free(f->write_callbacks);
+ }
+
+ //todo
+ /*if file is in the middle of doing something interrupt it */
if (f->data != NULL)
free(f->data);
@@ -72,6 +193,7 @@
struct _file *f;
+ int i;
int out;
f = (struct _file*) malloc(sizeof(struct _file));
@@ -83,12 +205,21 @@
f->in_buf = NULL;
f->out_buf = NULL;
f->open = FALSE;
+ f->data = NULL;
+ f->blocking = TRUE;
+ f->read_callbacks = NULL;
+ f->write_callbacks = NULL;
+
/*find a fd for our new friend*/
CHECK(list_dequeue(&f->fd,env->free_q) == 0, ENFILE);
+ for (i=0; i<5; i++) {
+ f->ready[i] = FALSE;
+ }
+
ASSERT(f->fd >= 0);
- ASSERT(f->fd < env->opt.maxfiles);
+ ASSERT(f->fd < env->opt.max_files);
env->fd[f->fd] = f;
@@ -98,6 +229,12 @@
f->out_buf = list_new();
CHECK(f->out_buf != NULL,0);
+ f->read_callbacks = list_new();
+ CHECK(f->read_callbacks != NULL,0);
+
+ f->write_callbacks = list_new();
+ CHECK(f->write_callbacks != NULL,0);
+
fail:
if (out == -1) {
Modified: bsockets/trunk/contrib/liboverlapped/file.h
===================================================================
--- bsockets/trunk/contrib/liboverlapped/file.h 2006-09-25 02:31:56 UTC (rev 8494)
+++ bsockets/trunk/contrib/liboverlapped/file.h 2006-09-25 02:45:45 UTC (rev 8495)
@@ -1,40 +1,22 @@
#ifndef _FILE_H_
#define _FILE_H_
+#include "env.h"
-struct _file {
+#define FILE_IS_READABLE 1
+#define FILE_IS_WRITABLE 2
- /*system file identifier*/
- void *handle;
- /*local file identifier*/
- int fd;
-
- /*what time of file are we (ie, disk file, socket, epoll, etc)*/
- int type;
- void *data; //pointer to type specific data
-
- /*input and output streams*/
- struct _list *in_buf;
- struct _list *out_buf;
-
- /*the last error that occured during file processin
- (should be reset everytime it is looked at) */
- int err;
-
- /*set if we are open/connected to something*/
- int open;
-
- /*true if we are in blocking mode*/
- int blocking;
-
-};
-
-void file_close(struct _file *, struct _file_env *env);
-struct _file *file_new(struct _file_env *env);
-struct _file *file_get(int fd, struct _file_env *env);
-
#define FT_SOCKET 1
#define FT_EPOLL 2
+
+void file_close(struct _file *, struct _file_env *);
+struct _file *file_new(struct _file_env *);
+struct _file *file_get(int fd, struct _file_env *);
+void file_exception(struct _file*, int, struct _file_env *);
+void file_wait(struct _cmd*, int, struct _file_env *);
+
+void file_raise(struct _file *, int, int, struct _file_env *);
+void file_last_error(struct _file *, int*);
#endif
Modified: bsockets/trunk/contrib/liboverlapped/list.c
===================================================================
--- bsockets/trunk/contrib/liboverlapped/list.c 2006-09-25 02:31:56 UTC (rev 8494)
+++ bsockets/trunk/contrib/liboverlapped/list.c 2006-09-25 02:45:45 UTC (rev 8495)
@@ -132,7 +132,6 @@
void list_free(struct _list *list) {
int n;
-
while (list_dequeue(&n,list) == 0);
free(list);
}
Modified: bsockets/trunk/contrib/liboverlapped/misc.c
===================================================================
--- bsockets/trunk/contrib/liboverlapped/misc.c 2006-09-25 02:31:56 UTC (rev 8494)
+++ bsockets/trunk/contrib/liboverlapped/misc.c 2006-09-25 02:45:45 UTC (rev 8495)
@@ -8,17 +8,10 @@
switch (err) {
-
-
-
default:
out = err;
break;
-
-
}
-
return out;
-
}
Modified: bsockets/trunk/contrib/liboverlapped/overlapped.c
===================================================================
--- bsockets/trunk/contrib/liboverlapped/overlapped.c 2006-09-25 02:31:56 UTC (rev 8494)
+++ bsockets/trunk/contrib/liboverlapped/overlapped.c 2006-09-25 02:45:45 UTC (rev 8495)
@@ -4,6 +4,7 @@
#include "overlapped.h"
#include "cmd.h"
+#include "file.h"
struct _file_env *__GLOBAL_FILE_ENV_;
@@ -41,11 +42,89 @@
CMD_PROC(CMD_SOCKET_NEW,-1,3,af,type,protocol);
}
-
int bclose(int fd) {
CMD_PROC(CMD_FILE_CLOSE,fd,0,NULL);
}
int bconnect(int fd, struct sockaddr *name, int namelen) {
- CMD_PROC(CMD_SOCKET_CONNECT,fd,2,name,namelen);
+
+ struct _cmd cmd;
+ struct _cmd cmd2;
+
+ int r;
+
+ cmd.type = CMD_SOCKET_CONNECT;
+ cmd.fd = fd;
+ cmd.arg[0] = name;
+ cmd.arg[1] = (void*) namelen;
+
+ cmd_post(&cmd,__GLOBAL_FILE_ENV_);
+
+ if (cmd.ret == -1) {
+
+ if (cmd.wait) {
+
+ cmd2.type = CMD_FILE_WAIT;
+ cmd2.fd = fd;
+ cmd2.arg[0] = (void*) FILE_IS_WRITABLE;
+ cmd_post(&cmd2,__GLOBAL_FILE_ENV_);
+
+ cmd2.type = CMD_FILE_ERROR;
+ cmd2.fd = fd;
+ cmd2.arg[0] = &r;
+ cmd_post(&cmd2,__GLOBAL_FILE_ENV_);
+
+ if (r) {
+ errno = r;
+ return -1;
+ } else {
+ return 0;
+ }
+
+ } else {
+ errno = cmd.err;
+ return cmd.ret;
+ }
+ } else {
+ return cmd.ret;
+ }
}
+
+int baccept(int fd, struct sockaddr* name, int *namelen) {
+
+ struct _cmd cmd;
+
+ cmd.type = CMD_SOCKET_ACCEPT;
+ cmd.fd = fd;
+ cmd.arg[0] = name;
+ cmd.arg[1] = namelen;
+
+ cmd_post(&cmd,__GLOBAL_FILE_ENV_);
+
+ if (cmd.ret == -1) {
+
+ if (cmd.wait) {
+
+ } else {
+ errno = cmd.err;
+ }
+
+ } else {
+ return cmd.ret;
+ }
+
+ return -1;
+}
+
+int bbind(int fd, struct sockaddr *name, int namelen) {
+ CMD_PROC(CMD_SOCKET_BIND,fd,2,name,namelen);
+}
+
+int blisten(int fd, int backlog) {
+ CMD_PROC(CMD_SOCKET_LISTEN,fd,1,backlog);
+}
+
+int bgetsockname(int fd, struct sockaddr *name, int *namelen) {
+ CMD_PROC(CMD_SOCKET_GET_NAME,fd,2,name,namelen);
+}
+
Modified: bsockets/trunk/contrib/liboverlapped/overlapped.h
===================================================================
--- bsockets/trunk/contrib/liboverlapped/overlapped.h 2006-09-25 02:31:56 UTC (rev 8494)
+++ bsockets/trunk/contrib/liboverlapped/overlapped.h 2006-09-25 02:45:45 UTC (rev 8495)
@@ -1,6 +1,7 @@
#ifndef _OVERLAPPED_H_
#define _OVERLAPPED_H_
+#include <windows.h>
#include <errno.h>
extern struct _file_env *__GLOBAL_FILE_ENV_;
@@ -8,39 +9,52 @@
/* */
struct _file_env_options {
- int maxfiles;
- int maxsockets;
+ int max_files;
+ int max_sockets;
+ int max_half_open_connections;
+ int max_listeners;
};
-/*user functions*/
+/***user functions***/
+/*environment functions*/
int env_init(struct _file_env_options *);
void env_shutdown();
-/**/
+/*socket functions*/
int bsocket(int, int, int );
+int bbind(int, struct sockaddr*, int);
+int blisten(int, int);
+int baccept(int, struct sockaddr*, int*);
+int bconnect(int, struct sockaddr*, int);
+int bgetsockname(int, struct sockaddr*, int*);
-/*provide some unix errno values, in case your win32 compiler doesn't have them*/
+/*provide some unix errno values, in case your win32 compiler doesn't have them
+ feel free to add more.*/
-#define LOVERLAPPED_PRIVATE_ERRNO 100000
+#define LOVERLAPPED_PRIVATE_ERRNO(X) (1010000+X)
#ifndef ENOMEM
-#define ENOMEM LOVERLAPPED_PRIVATE_ERRNO+1
+#define ENOMEM LOVERLAPPED_PRIVATE_ERRNO(1)
#endif
#ifndef ECLOSED
-#define ECLOSED LOVERLAPPED_PRIVATE_ERRNO+2
+#define ECLOSED LOVERLAPPED_PRIVATE_ERRNO(2)
#endif
#ifndef EISCONN
-#define EISCONN LOVERLAPPED_PRIVATE_ERRNO+3
+#define EISCONN LOVERLAPPED_PRIVATE_ERRNO(3)
#endif
#ifndef EALREADY
-#define EALREADY LOVERLAPPED_PRIVATE_ERRNO+3
+#define EALREADY LOVERLAPPED_PRIVATE_ERRNO(4)
#endif
+#ifndef EINPROGRESS
+#define EINPROGRESS LOVERLAPPED_PRIVATE_ERRNO(5)
+#endif
+
#endif
Modified: bsockets/trunk/contrib/liboverlapped/socket.c
===================================================================
--- bsockets/trunk/contrib/liboverlapped/socket.c 2006-09-25 02:31:56 UTC (rev 8494)
+++ bsockets/trunk/contrib/liboverlapped/socket.c 2006-09-25 02:45:45 UTC (rev 8495)
@@ -7,36 +7,278 @@
#include "env.h"
#include "misc.h"
#include "cmd.h"
+#include "list.h"
-void socket_exception( ) {
+//todo -- make sure we implment ALL system calls
+struct __connect_data {
+ struct _file *f;
+ struct _socket *s;
+ void *name;
+ int namelen;
+};
+
+static
+void cd_free(struct __connect_data *cd) {
+
+ if (cd == NULL)
+ return;
+
+ if (cd->name != NULL) {
+ free(cd->name);
+ }
+
+ free(cd);
+
}
-void socket_connect(struct _file *f, struct _socket *s, struct _cmd *cmd, struct _file_env *env) {
+static
+struct __connect_data* cd_new(struct _file *f, struct _socket *s, void *name, int namelen) {
+ struct __connect_data *cd;
+
int out;
- out = 0;
+ cd = (struct __connect_data*) malloc(sizeof(struct __connect_data));
- CHECK(!f->open,EISCONN);
- CHECK(!s->connecting,EALREADY);
+ CHECK(cd != NULL,ENOMEM);
+ cd->name = malloc(namelen);
+ CHECK(cd->name != NULL,ENOMEM);
+ memcpy(cd->name,name,namelen);
+ cd->f = f;
+ cd->s = s;
+
+ return cd;
+
fail:
+ cd_free(cd);
+ return NULL;
+}
- cmd_done(cmd,out,errno);
+void socket_unwatch_event(struct _file *f, struct _socket *s, struct _file_env *env) {
+ int r;
+
+ r = WSAEventSelect((SOCKET) f->handle,env->ev[s->watch_index],0);
+ ASSERT(r == 0);
+
+ r = WSAResetEvent(env->ev[s->watch_index]);
+ ASSERT(r == TRUE);
+
+ env->ev_callback[s->watch_index] = NULL;
+
}
+void socket_watch_event(struct _file *f, struct _socket *s,
+ void *callback, void *data, int eventflag, struct _file_env *env ) {
+
+ int i;
+ int r;
+
+ for (i=0; i<WSA_MAXIMUM_WAIT_EVENTS; i++) {
+
+ if (env->ev_callback[i] == NULL) {
+
+ env->ev_callback[i] = callback;
+ env->ev_data[i] = data;
+
+ r = WSAEventSelect((SOCKET) f->handle,env->ev[i],eventflag);
+ ASSERT(r == 0);
+
+ s->watch_index = i;
+
+ return;
+ }
+
+ }
+
+ ASSERT(FALSE);
+
+}
+
+void socket_get_name(struct _cmd *cmd, struct _file_env *env) {
+
+ int r;
+
+ r = getsockname((SOCKET) cmd->f->handle, cmd->arg[0], cmd->arg[1]);
+
+ if (r != SOCKET_ERROR){
+ cmd_done(cmd,0,0);
+ } else {
+ cmd_done(cmd,-1,unixify_w32err(WSAGetLastError()));
+ }
+
+}
+
+void socket_listen(struct _cmd *cmd, struct _file_env *env) {
+
+ int r;
+
+ r = listen((SOCKET) cmd->f->handle, (int) cmd->arg[0]);
+
+ if (r != SOCKET_ERROR) {
+ cmd_done(cmd,0,0);
+ } else {
+ cmd_done(cmd,-1,unixify_w32err(WSAGetLastError()));
+ }
+}
+
+void socket_bind(struct _cmd *cmd, struct _file_env *env) {
+
+ int r;
+
+ r = bind((SOCKET) cmd->f->handle,cmd->arg[0],(int) cmd->arg[1]);
+
+ if (r != SOCKET_ERROR) {
+ cmd_done(cmd,0,0);
+ } else {
+ cmd_done(cmd,-1,unixify_w32err(WSAGetLastError()));
+ }
+
+}
+
+static
+int socket_queue_connection(struct _cmd *cmd,struct _file_env *env) {
+
+ struct __connect_data *cd;
+
+ cd = cd_new(cmd->f,cmd->s,cmd->arg[0],(int)cmd->arg[1]);
+
+ if (cd != NULL) {
+ if (list_enqueue(cd,env->waiting_to_connect) != NULL) {
+ return 0;
+ } else {
+ cd_free(cd);
+ return -1;
+ }
+ } else {
+ return -1;
+ }
+
+}
+
+static
+void socket_start_reading(struct _file *f,struct _socket *s, struct _file_env *env) {
+ //add something to cmd_q that says "begin the reading"
+}
+
+static
+void socket_make_connected(struct _file *f, struct _socket *s, struct _file_env *env) {
+
+ file_raise(f,FILE_IS_READABLE,FALSE,env);
+ file_raise(f,FILE_IS_WRITABLE,TRUE,env);
+
+ f->open = TRUE;
+ s->connecting = FALSE;
+
+ socket_start_reading(f,s,env);
+
+}
+
+void socket_connect_callback(struct __connect_data *c, struct _file_env *env) {
+
+ WSANETWORKEVENTS we;
+
+ int err;
+ int r;
+
+ r = WSAEnumNetworkEvents((SOCKET) c->f->handle,NULL,&we);
+ //failure indicates a programming error, not a copeable network error
+ ASSERT(r == 0);
+ //we must have trigged a FD_CONNECT event
+ ASSERT(we.lNetworkEvents & FD_CONNECT);
+ //.. and nothing else
+ ASSERT((we.lNetworkEvents & (~FD_CONNECT)) == 0 );
+
+ if ( (err = we.iErrorCode[FD_CONNECT_BIT]) == 0) {
+ socket_make_connected(c->f,c->s,env);
+ } else {
+ file_exception(c->f,unixify_w32err(err),env);
+ }
+
+ env->connections_half_open--;
+ socket_unwatch_event(c->f,c->s,env);
+ cd_free(c);
+
+}
+
+static
+void socket_process_connections(struct _file_env *env) {
+
+ struct __connect_data *cd;
+
+ int err;
+ int out;
+ int r;
+
+ CHECK(env->connections_half_open <= env->opt.max_half_open_connections,0);
+
+ while (TRUE) {
+
+ CHECK(list_dequeue(&cd,env->waiting_to_connect ) == 0,0);
+
+ r = connect((SOCKET) cd->f->handle,cd->name,cd->namelen);
+
+ if (r == SOCKET_ERROR) {
+
+ switch(err = WSAGetLastError()) {
+
+ case WSAEWOULDBLOCK:
+ case WSAEINVAL:
+ socket_watch_event
+ (cd->f,cd->s,socket_connect_callback,cd,FD_CONNECT,env);
+ env->connections_half_open++;
+ break;
+
+ default:
+ file_exception(cd->f,unixify_w32err(err), env);
+ break;
+ }
+
+ } else {
+ socket_make_connected(cd->f,cd->s,env);
+ }
+
+ }
+
+ fail:
+ return;
+}
+
+void socket_connect(struct _cmd *cmd, struct _file_env *env) {
+
+ int out;
+
+ CHECK(!cmd->f->open,EISCONN);
+ CHECK(!cmd->s->connecting,EALREADY);
+
+ CHECK(socket_queue_connection(cmd,env) == 0,0);
+
+ cmd_defer(cmd,EINPROGRESS);
+
+ socket_process_connections(env);
+
+ return;
+
+ fail:
+
+ cmd_done(cmd,-1,errno);
+
+}
+
void socket_new(struct _cmd *cmd, struct _file_env *env) {
+ struct _file *f;
struct _socket *s;
- struct _file *f;
int out;
+ int nb;
out = 0;
+ nb = 1;
f = file_new(env);
CHECK(f != NULL,0);
@@ -44,6 +286,7 @@
s = (struct _socket*) malloc(sizeof(struct _socket));
CHECK(s != NULL,ENOMEM);
+ //todo -- set tcp stack size to zero
f->handle = (void*)
WSASocket( (int) cmd->arg[0],
@@ -54,12 +297,16 @@
WSA_FLAG_OVERLAPPED);
CHECK_(f->handle != (void*) INVALID_SOCKET);
+ //the underlying socket is always non-blocking
+ //there is no reason for this operation to fail
+ ASSERT(ioctlsocket((SOCKET) f->handle,FIONBIO,(DWORD*) &nb) == 0);
+
f->type = FT_SOCKET;
-
s->connecting = FALSE;
-
f->data = s;
+ out = f->fd;
+
fail:
if (out == -1 && f != NULL) {
Modified: bsockets/trunk/contrib/liboverlapped/socket.h
===================================================================
--- bsockets/trunk/contrib/liboverlapped/socket.h 2006-09-25 02:31:56 UTC (rev 8494)
+++ bsockets/trunk/contrib/liboverlapped/socket.h 2006-09-25 02:45:45 UTC (rev 8495)
@@ -3,14 +3,17 @@
struct _socket {
int connecting;
+ int watch_index;
};
-
struct _cmd;
struct _file_env;
void socket_new(struct _cmd *, struct _file_env *);
+void socket_connect(struct _cmd *, struct _file_env *);
+void socket_bind(struct _cmd *, struct _file_env *);
+void socket_listen(struct _cmd*, struct _file_env *);
+void socket_get_name(struct _cmd*, struct _file_env *);
-
#endif
Modified: bsockets/trunk/contrib/liboverlapped/test.c
===================================================================
--- bsockets/trunk/contrib/liboverlapped/test.c 2006-09-25 02:31:56 UTC (rev 8494)
+++ bsockets/trunk/contrib/liboverlapped/test.c 2006-09-25 02:45:45 UTC (rev 8495)
@@ -3,19 +3,24 @@
#include "overlapped.h"
#include "test.h"
+ #include "env.h"
-#define MAX_FILES 2000
-//todo -- implement maximum sockets checking
-#define MAX_SOCKETS 1500
+#define MAX_FILES 2000
+#define MAX_SOCKETS 1500
-struct _file_env_options fo = {
+struct sockaddr_in lh;
+
+static struct _file_env_options fo = {
MAX_FILES,
- MAX_SOCKETS
+ MAX_SOCKETS,
+ 100,
+ 100
};
int test_fileinit() {
- int mega_tests = 10;
+ //crank this up to be more thorough
+ int mega_tests = 1;
int fd;
int i;
@@ -39,27 +44,75 @@
return 0;
}
-//make sure connect/accept behave properly
+//do some simple stuff with connect
int test_connect() {
- //const int n = 500;
+ struct sockaddr_in lh2;
+ int client;
+ int server;
+ int tests = 100;
+ int r;
+ int z;
+
TESTeq(env_init(&fo),0);
+ while (tests--) {
+
+ /*simple blocking server*/
+ server = bsocket(AF_INET,SOCK_STREAM,0);
+ TEST(server != -1);
+
+ client = bsocket(AF_INET,SOCK_STREAM,0);
+ TEST(client != -1);
+
+ r = bbind(server,(struct sockaddr*) &lh,sizeof(lh));
+ TEST(r != -1);
+
+ r = blisten(server,10);
+ TEST(r != -1);
+
+ z = sizeof(lh2);
+ r = bgetsockname(server,(struct sockaddr*) &lh2,&z);
+ TEST(r != -1);
+
+ r = bconnect(client,(struct sockaddr*) &lh2,sizeof(lh2));
+ TEST(r != -1);
+
+ r = baccept(server,NULL,NULL);
+ TEST(r != -1);
+
+
+ }
+
env_shutdown();
return 0;
+}
+//make sure connect/accept behave properly
+int test_blocking_server() {
+ TEST(FALSE);
+ return 0;
+}
+int test_nonblocking_server() {
+ TEST(FALSE);
+ return 0;
}
+
struct test_case {
int (*fun)();
char *desc;
};
struct test_case tc[] = {
- {test_fileinit,"Test creating and destroying some sockets"},
+// {test_fileinit,"Test creating and destroying some sockets"},
+ {test_connect,"Test usage of connect()"},
+// {test_basic_epoll,"Test basic usage of epoll()"},
+// {test_blocking_server,"Test blocking implementation of echo server."},
+// {test_nonblocking_server,"\t(non-blocking"},
//{test_socketconnect,"Test connection to ."},
{NULL,NULL}
@@ -98,6 +151,10 @@
int good=0;
int bad=0;
+ lh.sin_family = AF_INET;
+ lh.sin_addr.s_addr = inet_addr("127.0.0.1");
+ lh.sin_port = 0;
+
if ( winsock_start() != 0) {
printf("Couldn't init winsock: %d",WSAGetLastError());
fflush(stdout);
Modified: bsockets/trunk/contrib/liboverlapped/test.h
===================================================================
--- bsockets/trunk/contrib/liboverlapped/test.h 2006-09-25 02:31:56 UTC (rev 8494)
+++ bsockets/trunk/contrib/liboverlapped/test.h 2006-09-25 02:45:45 UTC (rev 8495)
@@ -5,8 +5,8 @@
int res2_;
#define TESTeq(A,B) if ( (res_ = A) != (res2_ = B) ) {\
- printf("\nTest failed: %s [%d] != %s [%d]\n\tline:%d errno:%d\n"\
- ,#A,res_,#B,res2_,__LINE__,errno\
+ printf("\nTest failed: %s [%d] != %s [%d]\n\tline:%d errno:%d w32err:%d\n"\
+ ,#A,res_,#B,res2_,__LINE__,errno,(int) WSAGetLastError()\
);\
return 1;\
}\