Author: iratqq
Date: Sun Jan 18 19:49:34 2009
New Revision: 5750
Modified:
trunk/uim/uim-posix.c
Log:
* uim/uim-posix.c (find_flags_equal, ref_args_or, c_make_addrinfo)
(c_delete_addrinfo, c_addrinfo_set_ai_flags, c_addrinfo_ref_ai_flags)
(c_addrinfo_set_ai_family, c_addrinfo_ref_ai_family)
(c_addrinfo_set_ai_socktype, c_addrinfo_ref_ai_socktype)
(c_addrinfo_set_ai_protocol, c_addrinfo_ref_ai_protocol)
(c_addrinfo_ref_ai_addrlen, c_addrinfo_ref_ai_addr, c_getaddrinfo)
(c_freeaddrinfo, c_socket, c_connect):
- New functions.
Import low-level socket functions.
Now, uim-scm will read/write network packet immediately.
Modified: trunk/uim/uim-posix.c
==============================================================================
--- trunk/uim/uim-posix.c (original)
+++ trunk/uim/uim-posix.c Sun Jan 18 19:49:34 2009
@@ -46,6 +46,9 @@
#include <errno.h>
#include <assert.h>
#include <fcntl.h>
+#include <sys/socket.h>
+#include <netdb.h>
+#include <netinet/in.h>
#include "uim.h"
#include "uim-internal.h"
@@ -328,6 +331,28 @@
char *arg;
} opt_args;
+static const char *
+find_flags_equal(const opt_args *list, int flag, const char **errstrp)
+{
+ char *arg = NULL;
+ int i = 0;
+ const static char *err = N_("Invalid argument");
+
+ *errstrp = NULL;
+ while (1) {
+ if (list[i].arg == 0) {
+ *errstrp = err;
+ return 0;
+ }
+ if (list[i].flag == flag) {
+ arg = list[i].arg;
+ break;
+ }
+ i++;
+ }
+ return arg;
+}
+
static int
find_args_equal(const opt_args *list, char *arg, const char **errstrp)
{
@@ -351,6 +376,21 @@
}
static uim_lisp
+ref_args_or(const opt_args *list, int flags)
+{
+ int i = 0;
+ uim_lisp ret_ = uim_scm_null();
+
+ while (list[i].arg != 0) {
+ if (list[i].flag & flags) {
+ ret_ = CONS(MAKE_SYM(list[i].arg), ret_);
+ }
+ i++;
+ }
+ return uim_scm_callf("reverse", "o", ret_);
+}
+
+static uim_lisp
make_arg_list(const opt_args *list)
{
uim_lisp ret_;
@@ -488,6 +528,271 @@
return ret_;
}
+static uim_lisp
+c_make_addrinfo()
+{
+ struct addrinfo *addrinfo = uim_malloc(sizeof(struct addrinfo));
+
+ memset(addrinfo, 0, sizeof(struct addrinfo));
+ return MAKE_PTR(addrinfo);
+}
+
+static uim_lisp
+c_delete_addrinfo(uim_lisp addrinfo_)
+{
+ free(C_PTR(addrinfo_));
+ return uim_scm_t();
+}
+
+const static opt_args ai_flags[] = {
+ { AI_CANONNAME, "$AI_CANONNAME" },
+ { AI_NUMERICHOST, "$AI_NUMERICHOST" },
+ { AI_PASSIVE, "$AI_PASSIVE" },
+ { 0, 0 }
+};
+static uim_lisp
+c_addrinfo_set_ai_flags(uim_lisp addrinfo_, uim_lisp ai_flags_)
+{
+ struct addrinfo *addrinfo = C_PTR(addrinfo_);
+ int flags = 0;
+ const char *errstr;
+
+ while (!NULLP(ai_flags_)) {
+ char *f = C_SYM(CAR(ai_flags_));
+
+ flags |= find_args_equal(ai_flags, f, &errstr);
+ free(f);
+ if (errstr) {
+ uim_notify_fatal("addrinfo-set-ai-flags!: %s", errstr);
+ ERROR_OBJ(errstr, CAR(ai_flags_));
+ }
+ ai_flags_ = CDR(ai_flags_);
+ }
+
+ addrinfo->ai_flags = flags;
+ return uim_scm_t();
+}
+static uim_lisp
+c_addrinfo_ref_ai_flags(uim_lisp addrinfo_)
+{
+ struct addrinfo *addrinfo = C_PTR(addrinfo_);
+
+ return ref_args_or(ai_flags, addrinfo->ai_flags);
+}
+
+const static opt_args ai_family[] = {
+ { PF_UNSPEC, "$PF_UNSPEC" },
+ { PF_LOCAL, "$PF_LOCAL" },
+ { PF_INET, "$PF_INET" },
+ { PF_INET6, "$PF_INET6" },
+ { 0, 0 }
+};
+
+static uim_lisp
+c_addrinfo_set_ai_family(uim_lisp addrinfo_, uim_lisp ai_family_)
+{
+ struct addrinfo *addrinfo = C_PTR(addrinfo_);
+ char *f = C_SYM(ai_family_);
+ int family;
+ const char *errstr;
+
+ family = find_args_equal(ai_family, f, &errstr);
+ free(f);
+ if (errstr) {
+ uim_notify_fatal("addrinfo-set-ai-family!: %s", errstr);
+ ERROR_OBJ(errstr, ai_family_);
+ }
+ addrinfo->ai_family = family;
+ return uim_scm_t();
+}
+static uim_lisp
+c_addrinfo_ref_ai_family(uim_lisp addrinfo_)
+{
+ struct addrinfo *addrinfo = C_PTR(addrinfo_);
+ const char *family;
+ const char *errstr;
+
+ family = find_flags_equal(ai_family, addrinfo->ai_family, &errstr);
+ if (errstr) {
+ uim_notify_fatal("addrinfo-ai-family?: %s", errstr);
+ ERROR_OBJ(errstr, addrinfo_);
+ }
+ return MAKE_SYM(family);
+}
+
+const static opt_args ai_socktype[] = {
+ { SOCK_STREAM, "$SOCK_STREAM" },
+ { SOCK_DGRAM, "$SOCK_DGRAM" },
+ { SOCK_RAW, "$SOCK_RAW" },
+ { 0, 0 }
+};
+
+static uim_lisp
+c_addrinfo_set_ai_socktype(uim_lisp addrinfo_, uim_lisp ai_socktype_)
+{
+ struct addrinfo *addrinfo = C_PTR(addrinfo_);
+ char *f = C_SYM(ai_socktype_);
+ int socktype;
+ const char *errstr;
+
+ socktype = find_args_equal(ai_socktype, f, &errstr);
+ free(f);
+ if (errstr) {
+ uim_notify_fatal("addrinfo-set-ai-socktype!: %s", errstr);
+ ERROR_OBJ(errstr, ai_socktype_);
+ }
+ addrinfo->ai_socktype = socktype;
+ return uim_scm_t();
+}
+static uim_lisp
+c_addrinfo_ref_ai_socktype(uim_lisp addrinfo_)
+{
+ struct addrinfo *addrinfo = C_PTR(addrinfo_);
+ const char *socktype;
+ const char *errstr;
+
+ socktype = find_flags_equal(ai_socktype, addrinfo->ai_socktype, &errstr);
+ if (errstr) {
+ uim_notify_fatal("addrinfo-ai-socktype?: %s", errstr);
+ ERROR_OBJ(errstr, addrinfo_);
+ }
+ return MAKE_SYM(socktype);
+}
+
+const static opt_args ai_protocol[] = {
+ { IPPROTO_UDP, "$IPPROTO_UDP" },
+ { IPPROTO_TCP, "$IPPROTO_TCP" },
+ { 0, 0 }
+};
+
+static uim_lisp
+c_addrinfo_set_ai_protocol(uim_lisp addrinfo_, uim_lisp ai_protocol_)
+{
+ struct addrinfo *addrinfo = C_PTR(addrinfo_);
+ char *f = C_SYM(ai_protocol_);
+ int protocol;
+ const char *errstr;
+
+ protocol = find_args_equal(ai_protocol, f, &errstr);
+ free(f);
+ if (errstr) {
+ uim_notify_fatal("addrinfo-set-ai-protocol!: %s", errstr);
+ ERROR_OBJ(errstr, ai_protocol_);
+ }
+ addrinfo->ai_protocol = protocol;
+ return uim_scm_t();
+}
+static uim_lisp
+c_addrinfo_ref_ai_protocol(uim_lisp addrinfo_)
+{
+ struct addrinfo *addrinfo = C_PTR(addrinfo_);
+ const char *protocol;
+ const char *errstr;
+
+ protocol = find_flags_equal(ai_protocol, addrinfo->ai_protocol, &errstr);
+ if (errstr) {
+ uim_notify_fatal("addrinfo-ai-protocol?: %s", errstr);
+ ERROR_OBJ(errstr, addrinfo_);
+ }
+ return MAKE_SYM(protocol);
+}
+
+static uim_lisp
+c_addrinfo_ref_ai_addrlen(uim_lisp addrinfo_)
+{
+ struct addrinfo *addrinfo = C_PTR(addrinfo_);
+
+ return MAKE_INT(addrinfo->ai_addrlen);
+}
+
+static uim_lisp
+c_addrinfo_ref_ai_addr(uim_lisp addrinfo_)
+{
+ struct addrinfo *addrinfo = C_PTR(addrinfo_);
+
+ return MAKE_PTR(addrinfo->ai_addr);
+}
+
+static uim_lisp
+c_getaddrinfo(uim_lisp hostname_, uim_lisp servname_, uim_lisp hint_)
+{
+ const char *hostname = REFER_C_STR(hostname_);
+ char *servname = NULL;
+ struct addrinfo *hints = C_PTR(hint_);
+ struct addrinfo *res, *res0;
+ uim_lisp ret_ = uim_scm_null();
+ int error;
+
+ if (INTP(servname_)) {
+ uim_asprintf(&servname, "%d", C_INT(servname_));
+ } else {
+ servname = C_STR(servname_);
+ }
+
+ error = getaddrinfo(hostname, servname, hints, &res0);
+ if (error) {
+ const char *errstr = gai_strerror(error);
+
+ free(servname);
+ uim_notify_fatal("getaddrinfo: %s", gai_strerror(error));
+ ERROR_OBJ(errstr, CONS(hostname_, servname_));
+ }
+
+ free(servname);
+ for (res = res0; res; res = res->ai_next) {
+ ret_ = CONS(MAKE_PTR(res) , ret_);
+ }
+ return uim_scm_callf("reverse", "o", ret_);
+}
+
+
+static uim_lisp
+c_freeaddrinfo(uim_lisp addrinfo_)
+{
+ freeaddrinfo(C_PTR(addrinfo_));
+ return uim_scm_t();
+}
+
+static uim_lisp
+c_socket(uim_lisp domain_, uim_lisp type_, uim_lisp protocol_)
+{
+ int domain;
+ int type;
+ int protocol;
+ char *sym;
+ const char *errstr;
+
+ sym = C_SYM(domain_);
+ domain = find_args_equal(ai_family, sym, &errstr);
+ free(sym);
+ if (errstr) {
+ uim_notify_fatal("socket: %s", errstr);
+ ERROR_OBJ(errstr, domain_);
+ }
+ sym = C_SYM(type_);
+ type = find_args_equal(ai_socktype, sym, &errstr);
+ free(sym);
+ if (errstr) {
+ uim_notify_fatal("socket: %s", errstr);
+ ERROR_OBJ(errstr, type_);
+ }
+ sym = C_SYM(protocol_);
+ protocol = find_args_equal(ai_protocol, sym, &errstr);
+ free(sym);
+ if (errstr) {
+ uim_notify_fatal("socket: %s", errstr);
+ ERROR_OBJ(errstr, protocol_);
+ }
+
+ return MAKE_INT(socket(domain, type, protocol));
+}
+
+static uim_lisp
+c_connect(uim_lisp s_, uim_lisp name_, uim_lisp namelen_)
+{
+ return MAKE_INT(connect(C_INT(s_), C_PTR(name_), C_INT(namelen_)));
+}
+
void
uim_init_posix_subrs(void)
{
@@ -524,4 +829,23 @@
uim_scm_init_proc0("file-open-flags?", c_file_open_flags);
uim_scm_init_proc0("file-open-mode?", c_file_open_mode);
+
+ uim_scm_init_proc0("make-addrinfo", c_make_addrinfo);
+ uim_scm_init_proc1("delete-addrinfo", c_delete_addrinfo);
+
+ uim_scm_init_proc2("addrinfo-set-ai-flags!", c_addrinfo_set_ai_flags);
+ uim_scm_init_proc1("addrinfo-ai-flags?", c_addrinfo_ref_ai_flags);
+ uim_scm_init_proc2("addrinfo-set-ai-family!", c_addrinfo_set_ai_family);
+ uim_scm_init_proc1("addrinfo-ai-family?", c_addrinfo_ref_ai_family);
+ uim_scm_init_proc2("addrinfo-set-ai-socktype!",
c_addrinfo_set_ai_socktype);
+ uim_scm_init_proc1("addrinfo-ai-socktype?", c_addrinfo_ref_ai_socktype);
+ uim_scm_init_proc2("addrinfo-set-ai-protocol!",
c_addrinfo_set_ai_protocol);
+ uim_scm_init_proc1("addrinfo-ai-protocol?", c_addrinfo_ref_ai_protocol);
+ uim_scm_init_proc1("addrinfo-ai-addrlen?", c_addrinfo_ref_ai_addrlen);
+ uim_scm_init_proc1("addrinfo-ai-addr?", c_addrinfo_ref_ai_addr);
+
+ uim_scm_init_proc3("getaddrinfo", c_getaddrinfo);
+ uim_scm_init_proc1("freeaddrinfo", c_freeaddrinfo);
+ uim_scm_init_proc3("socket", c_socket);
+ uim_scm_init_proc3("connect", c_connect);
}