summaryrefslogtreecommitdiff
path: root/ext/socket/constants.c
blob: f0e210246d60052aeebab55d04ef4519badcd207 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
/************************************************

  constants.c -

  created at: Thu Mar 31 12:21:29 JST 1994

  Copyright (C) 1993-2007 Yukihiro Matsumoto

************************************************/

#include "rubysocket.h"

static void sock_define_const(const char *name, int value, VALUE mConst);
static void sock_define_uconst(const char *name, unsigned int value, VALUE mConst);
#define sock_define_const(name, value) sock_define_const(name, value, mConst)
#define sock_define_uconst(name, value) sock_define_uconst(name, value, mConst)
#include "constdefs.c"
#undef sock_define_const
#undef sock_define_uconst

static int
constant_arg(VALUE arg, int (*str_to_int)(const char*, int, int*), const char *errmsg)
{
    VALUE tmp;
    char *ptr;
    int ret;

    if (SYMBOL_P(arg)) {
        arg = rb_sym_to_s(arg);
        goto str;
    }
    else if (!NIL_P(tmp = rb_check_string_type(arg))) {
	arg = tmp;
      str:
	rb_check_safe_obj(arg);
        ptr = RSTRING_PTR(arg);
        if (str_to_int(ptr, RSTRING_LEN(arg), &ret) == -1)
	    rb_raise(rb_eSocket, "%s: %s", errmsg, ptr);
    }
    else {
	ret = NUM2INT(arg);
    }
    return ret;
}

int
family_arg(VALUE domain)
{
    /* convert AF_INET, etc. */
    return constant_arg(domain, family_to_int, "unknown socket domain");
}

int
socktype_arg(VALUE type)
{
    /* convert SOCK_STREAM, etc. */
    return constant_arg(type, socktype_to_int, "unknown socket type");
}

int
level_arg(int family, VALUE level)
{
    /* convert SOL_SOCKET, IPPROTO_TCP, etc. */
    if (IS_IP_FAMILY(family)) {
        return constant_arg(level, ip_level_to_int, "unknown protocol level");
    }
    else {
        return constant_arg(level, unknown_level_to_int, "unknown protocol level");
    }
}

int
optname_arg(int family, int level, VALUE optname)
{
    if (IS_IP_FAMILY(family)) {
        switch (level) {
          case SOL_SOCKET:
            return constant_arg(optname, so_optname_to_int, "unknown socket level option name");
          case IPPROTO_IP:
            return constant_arg(optname, ip_optname_to_int, "unknown IP level option name");
#ifdef IPPROTO_IPV6
          case IPPROTO_IPV6:
            return constant_arg(optname, ipv6_optname_to_int, "unknown IPv6 level option name");
#endif
          case IPPROTO_TCP:
            return constant_arg(optname, tcp_optname_to_int, "unknown TCP level option name");
          case IPPROTO_UDP:
            return constant_arg(optname, udp_optname_to_int, "unknown UDP level option name");
          default:
            return NUM2INT(optname);
        }
    }
    else {
        switch (level) {
          case SOL_SOCKET:
            return constant_arg(optname, so_optname_to_int, "unknown socket level option name");
          default:
            return NUM2INT(optname);
        }
    }
}

int
cmsg_type_arg(int family, int level, VALUE type)
{
    if (IS_IP_FAMILY(family)) {
        switch (level) {
          case SOL_SOCKET:
            return constant_arg(type, scm_optname_to_int, "unknown UNIX control message");
          case IPPROTO_IP:
            return constant_arg(type, ip_optname_to_int, "unknown IP control message");
#ifdef INET6
          case IPPROTO_IPV6:
            return constant_arg(type, ipv6_optname_to_int, "unknown IPv6 control message");
#endif
          case IPPROTO_TCP:
            return constant_arg(type, tcp_optname_to_int, "unknown TCP control message");
          case IPPROTO_UDP:
            return constant_arg(type, udp_optname_to_int, "unknown UDP control message");
          default:
            return NUM2INT(type);
        }
    }
    else {
        switch (level) {
          case SOL_SOCKET:
            return constant_arg(type, scm_optname_to_int, "unknown UNIX control message");
          default:
            return NUM2INT(type);
        }
    }
}

int
shutdown_how_arg(VALUE how)
{
    /* convert SHUT_RD, SHUT_WR, SHUT_RDWR. */
    return constant_arg(how, shutdown_how_to_int, "unknown shutdown argument");
}

static void
sock_define_const(const char *name, int value, VALUE mConst)
{
    rb_define_const(rb_cSocket, name, INT2NUM(value));
    rb_define_const(mConst, name, INT2NUM(value));
}

static void
sock_define_uconst(const char *name, unsigned int value, VALUE mConst)
{
    rb_define_const(rb_cSocket, name, UINT2NUM(value));
    rb_define_const(mConst, name, UINT2NUM(value));
}

/*
 * Socket::Constants module
 */
void
Init_socket_constants(void)
{
    VALUE mConst;

    /* constants */
    mConst = rb_define_module_under(rb_cSocket, "Constants");
    init_constants(mConst);
}