1/************************************************
2
3  constants.c -
4
5  created at: Thu Mar 31 12:21:29 JST 1994
6
7  Copyright (C) 1993-2007 Yukihiro Matsumoto
8
9************************************************/
10
11#include "rubysocket.h"
12
13static VALUE rb_mSockConst;
14
15#include "constdefs.c"
16
17static int
18constant_arg(VALUE arg, int (*str_to_int)(const char*, long, int*), const char *errmsg)
19{
20    VALUE tmp;
21    char *ptr;
22    int ret;
23
24    if (SYMBOL_P(arg)) {
25        arg = rb_sym_to_s(arg);
26        goto str;
27    }
28    else if (!NIL_P(tmp = rb_check_string_type(arg))) {
29	arg = tmp;
30      str:
31	rb_check_safe_obj(arg);
32        ptr = RSTRING_PTR(arg);
33        if (str_to_int(ptr, RSTRING_LEN(arg), &ret) == -1)
34	    rb_raise(rb_eSocket, "%s: %s", errmsg, ptr);
35    }
36    else {
37	ret = NUM2INT(arg);
38    }
39    return ret;
40}
41
42int
43rsock_family_arg(VALUE domain)
44{
45    /* convert AF_INET, etc. */
46    return constant_arg(domain, rsock_family_to_int, "unknown socket domain");
47}
48
49int
50rsock_socktype_arg(VALUE type)
51{
52    /* convert SOCK_STREAM, etc. */
53    return constant_arg(type, rsock_socktype_to_int, "unknown socket type");
54}
55
56int
57rsock_level_arg(int family, VALUE level)
58{
59    /* convert SOL_SOCKET, IPPROTO_TCP, etc. */
60    if (IS_IP_FAMILY(family)) {
61        return constant_arg(level, rsock_ip_level_to_int, "unknown protocol level");
62    }
63    else {
64        return constant_arg(level, rsock_unknown_level_to_int, "unknown protocol level");
65    }
66}
67
68int
69rsock_optname_arg(int family, int level, VALUE optname)
70{
71    if (IS_IP_FAMILY(family)) {
72        switch (level) {
73          case SOL_SOCKET:
74            return constant_arg(optname, rsock_so_optname_to_int, "unknown socket level option name");
75          case IPPROTO_IP:
76            return constant_arg(optname, rsock_ip_optname_to_int, "unknown IP level option name");
77#ifdef IPPROTO_IPV6
78          case IPPROTO_IPV6:
79            return constant_arg(optname, rsock_ipv6_optname_to_int, "unknown IPv6 level option name");
80#endif
81          case IPPROTO_TCP:
82            return constant_arg(optname, rsock_tcp_optname_to_int, "unknown TCP level option name");
83          case IPPROTO_UDP:
84            return constant_arg(optname, rsock_udp_optname_to_int, "unknown UDP level option name");
85          default:
86            return NUM2INT(optname);
87        }
88    }
89    else {
90        switch (level) {
91          case SOL_SOCKET:
92            return constant_arg(optname, rsock_so_optname_to_int, "unknown socket level option name");
93          default:
94            return NUM2INT(optname);
95        }
96    }
97}
98
99int
100rsock_cmsg_type_arg(int family, int level, VALUE type)
101{
102    if (IS_IP_FAMILY(family)) {
103        switch (level) {
104          case SOL_SOCKET:
105            return constant_arg(type, rsock_scm_optname_to_int, "unknown UNIX control message");
106          case IPPROTO_IP:
107            return constant_arg(type, rsock_ip_optname_to_int, "unknown IP control message");
108#ifdef INET6
109          case IPPROTO_IPV6:
110            return constant_arg(type, rsock_ipv6_optname_to_int, "unknown IPv6 control message");
111#endif
112          case IPPROTO_TCP:
113            return constant_arg(type, rsock_tcp_optname_to_int, "unknown TCP control message");
114          case IPPROTO_UDP:
115            return constant_arg(type, rsock_udp_optname_to_int, "unknown UDP control message");
116          default:
117            return NUM2INT(type);
118        }
119    }
120    else {
121        switch (level) {
122          case SOL_SOCKET:
123            return constant_arg(type, rsock_scm_optname_to_int, "unknown UNIX control message");
124          default:
125            return NUM2INT(type);
126        }
127    }
128}
129
130int
131rsock_shutdown_how_arg(VALUE how)
132{
133    /* convert SHUT_RD, SHUT_WR, SHUT_RDWR. */
134    return constant_arg(how, rsock_shutdown_how_to_int, "unknown shutdown argument");
135}
136
137/*
138 * Socket::Constants module
139 */
140void
141rsock_init_socket_constants(void)
142{
143    /* constants */
144    init_constants();
145}
146