1/*
2Copyright (C) 2008-2014, Parrot Foundation.
3
4=head1 NAME
5
6src/pmc/sockaddr.pmc - Sockaddr PMC
7
8=head1 DESCRIPTION
9
10The Sockaddr PMC holds a C<sockaddr> struct and saves its length (to
11distinguish C<sockaddr_in> and C<sockaddr_in6>).
12
13=head2 Vtable Functions
14
15These are the vtable functions for the Sockaddr class.
16
17=over 4
18
19=cut
20
21*/
22
23/* HEADERIZER HFILE: none */
24/* HEADERIZER BEGIN: static */
25/* HEADERIZER END: static */
26
27pmclass Sockaddr auto_attrs {
28    ATTR INTVAL  family;
29    ATTR INTVAL  type;
30    ATTR INTVAL  protocol;
31    ATTR INTVAL  len;     /* Length of the sockaddr struct */
32    ATTR void   *pointer; /* Pointer to a sockaddr struct */
33
34/*
35
36=item C<void init()>
37
38Initializes the PMC.
39
40=cut
41
42*/
43
44    VTABLE void init() {
45        Parrot_Sockaddr_attributes * const attrs =
46            (Parrot_Sockaddr_attributes *) PMC_data(SELF);
47
48        attrs->type     = 0;
49        attrs->protocol = 0;
50        attrs->pointer  = NULL;
51        attrs->len      = 0;
52
53        PObj_custom_destroy_SET(SELF);
54    }
55
56/*
57
58=item C<void destroy()>
59
60Destroys the PMC and frees all allocated memory.
61
62=cut
63
64*/
65
66    VTABLE void destroy() :no_wb {
67        Parrot_Sockaddr_attributes * const data = PARROT_SOCKADDR(SELF);
68
69        if (data) {
70            if (data->pointer)
71                mem_gc_free(INTERP, data->pointer);
72            data->pointer = NULL;
73        }
74    }
75
76/*
77
78=item C<PMC *clone()>
79
80Creates a new Sockaddr PMC with the same contents and length as the current
81one.
82
83=cut
84
85*/
86
87    VTABLE PMC *clone() :no_wb {
88        PMC * const dest = Parrot_pmc_new(INTERP, SELF->vtable->base_type);
89        const Parrot_Sockaddr_attributes * const old_attrs = PARROT_SOCKADDR(SELF);
90        Parrot_Sockaddr_attributes * const new_attrs = PARROT_SOCKADDR(dest);
91
92        new_attrs->type     = old_attrs->type;
93        new_attrs->protocol = old_attrs->protocol;
94        new_attrs->len      = old_attrs->len;
95
96        if (old_attrs->len) {
97            new_attrs->pointer = Parrot_gc_allocate_memory_chunk(INTERP,
98                                    old_attrs->len);
99            memcpy(new_attrs->pointer, old_attrs->pointer, old_attrs->len);
100        }
101
102        return dest;
103    }
104
105/*
106
107=item C<INTVAL get_bool()>
108
109Returns true if the Sockaddr is defined.
110
111=cut
112
113*/
114
115    VTABLE INTVAL get_bool() :no_wb {
116        const Parrot_Sockaddr_attributes * const data = PARROT_SOCKADDR(SELF);
117        UNUSED(INTERP)
118
119        return data->pointer ? 1 : 0;
120    }
121
122/*
123
124=item C<INTVAL get_integer()>
125
126Returns the length of the sockaddr struct.
127
128=cut
129
130*/
131
132    VTABLE INTVAL get_integer() :no_wb {
133        INTVAL len;
134
135        GET_ATTR_len(INTERP, SELF, len);
136        return len;
137    }
138
139/*
140
141=item C<void *get_pointer()>
142
143Returns a pointer to the C<sockaddr_in> or C<sockaddr_in6>.
144
145=cut
146
147*/
148
149    VTABLE void *get_pointer() :no_wb {
150        const Parrot_Sockaddr_attributes * const data = PARROT_SOCKADDR(SELF);
151        UNUSED(INTERP)
152        return data->pointer;
153    }
154
155/*
156
157=item C<STRING *get_string()>
158
159Returns the string representation of this sockaddr by calling C<getnameinfo(3)>.
160
161=cut
162
163*/
164    VTABLE STRING *get_string() :no_wb {
165        const Parrot_Sockaddr_attributes * const data = PARROT_SOCKADDR(SELF);
166
167        if (!data->pointer)
168            return Parrot_sprintf_c(INTERP, "(?)");
169
170        return Parrot_io_internal_getnameinfo(INTERP, data->pointer, data->len);
171    }
172
173/*
174
175=item C<INTVAL get_integer_keyed_int(INTVAL what)>
176
177Returns family, type or protocol. Used for debugging.
178
179=cut
180
181*/
182    VTABLE INTVAL get_integer_keyed_int(INTVAL what) :no_wb {
183        const Parrot_Sockaddr_attributes * const data = PARROT_SOCKADDR(SELF);
184        UNUSED(INTERP)
185
186        switch (what) {
187          case 0:
188            return data->family;
189          case 1:
190            return data->type;
191          case 2:
192            return data->protocol;
193          default:
194            return -1;
195        }
196    }
197
198}
199
200/*
201
202=back
203
204=cut
205
206*/
207
208/*
209 * Local variables:
210 *   c-file-style: "parrot"
211 * End:
212 * vim: expandtab shiftwidth=4 cinoptions='\:2=2' :
213 */
214