File Coverage

Lookup.xs
Criterion Covered Total %
statement 97 132 73.4
branch 40 90 44.4
condition n/a
subroutine n/a
pod n/a
total 137 222 61.7


line stmt bran cond sub pod time code
1             #define PERL_NO_GET_CONTEXT
2             #include "EXTERN.h"
3             #include "perl.h"
4             #include "XSUB.h"
5              
6             #include "ppport.h"
7              
8             #include "const-c.inc"
9              
10              
11             #ifdef WIN32
12             #include
13             #include
14             #else
15             #include
16             #include
17             #include
18             #include
19             #include
20             #endif
21              
22             #define AV_FLAGS 0
23             #define AV_FAMILY 1
24             #define AV_TYPE 2
25             #define AV_PROTOCOL 3
26             #define AV_ADDR 4
27             #define AV_CANONNAME 5
28              
29             MODULE = Socket::More::Lookup PACKAGE = Socket::More::Lookup
30              
31             INCLUDE: const-xs.inc
32              
33              
34             BOOT:
35             #ifdef WIN32
36             // Initialize Winsock or nothing works
37             WSADATA wsaData;
38             int iResult;
39             iResult = WSAStartup(MAKEWORD(2, 2), &wsaData);
40             if (iResult != 0) {
41             Perl_croak(aTHX_ "WSAStartup failed: %d\n", iResult);
42             }
43             #endif
44              
45             SV*
46             getaddrinfo(hostname, servicename, hints, results)
47             SV *hostname
48             SV *servicename
49             SV *hints
50             AV *results
51              
52             PROTOTYPE: $$$\@
53              
54             INIT:
55             int ret;
56 4           char *hname=NULL;
57 4           char *sname=NULL;
58             struct addrinfo *res;
59             struct addrinfo h;
60 4           struct addrinfo *hh=NULL;
61             struct addrinfo *next;
62             int len;
63             SV *temp;
64             bool return_av;
65            
66              
67             PPCODE:
68 4           h.ai_flags=0;
69 4           h.ai_family=0;
70 4           h.ai_socktype=0;
71 4           h.ai_protocol=0;
72 4           h.ai_addrlen=0;
73 4           h.ai_addr=NULL;
74 4           h.ai_canonname=NULL;
75 4           h.ai_next=NULL;
76              
77             // First check that output array is doable
78            
79             //expectiong a hostname
80              
81 4           return_av=false; //Default to a hash return
82              
83 4 50         if(SvOK(hostname) && SvPOK(hostname)){
    50          
84 4           len=SvCUR(hostname);
85 4           hname=SvPVX(hostname);//SvGROW(hostname,1);
86 4           hname[len]='\0';
87             //Perl_croak(aTHX_ "This croaked because: %" SVf "\n", SVfARG(hostname));
88             }
89             else{
90             }
91 4 50         if(SvOK(servicename)){
92 4 50         if(SvPOK(servicename)){
93 4           len=SvCUR(servicename);
94 4           sname=SvPVX(servicename);//SvGROW(servicename,1);
95 4           sname[len]='\0';
96             }
97 0 0         else if (SvIOK(servicename)){
98 0           temp=newSVpvf("%" SVf , SVfARG(servicename));
99 0           len=SvCUR(temp);
100 0           sname=SvPVX(temp);
101 0           sname[len]='\0';
102             }
103              
104              
105             }
106              
107 4 100         if(SvOK(hints) && SvROK(hints)){
    50          
108             SV** temp;
109             SV** key;
110             SV** val;
111             AV* av;
112             HV* hv;
113             int len;
114 2           int i=0;
115              
116 2           switch(SvTYPE(SvRV(hints))){
117 2           case SVt_PVAV:
118             // Treat as 'array struct'
119            
120 2           return_av=true;
121 2           av=(AV *)SvRV(hints);
122              
123 2 50         len=av_top_index(av)+1;
124 2 100         if(len){
125              
126              
127 1           val=av_fetch(av,i++,0);
128 1 50         if((val != NULL) && SvOK(*val)){
    50          
129             //fprintf(stderr, "FLAGS: %ld\n",SvIV(*val));
130 1           h.ai_flags = SvIV(*val);
131             }
132              
133 1           val=av_fetch(av,i++,0);
134 1 50         if((val != NULL) && SvOK(*val)){
    50          
135             //fprintf(stderr, "family: %ld\n",SvIV(*val));
136 1           h.ai_family = SvIV(*val);
137             }
138              
139 1           val=av_fetch(av,i++,0);
140 1 50         if((val != NULL) && SvOK(*val)){
    50          
141             //fprintf(stderr, "sock type: %ld\n",SvIV(*val));
142 1           h.ai_socktype = SvIV(*val);
143             }
144              
145 1           val=av_fetch(av,i++,0);
146 1 50         if((val != NULL) && SvOK(*val)){
    0          
147             //fprintf(stderr, "protocol: %ld\n",SvIV(*val));
148 0           h.ai_protocol = SvIV(*val);
149             }
150 1           hh=&h;
151             }
152             else {
153             //Empty array, treat as default, but still want array
154 1           hh=NULL;
155             }
156              
157 2           break;
158              
159 0           case SVt_PVHV:
160 0           return_av=false;
161 0           hv=(HV *)SvRV(hints);
162 0           temp=hv_fetch(hv,"flags",5,1);
163 0 0         if((temp != NULL ) && SvIOK(*temp)){
    0          
164 0           h.ai_flags = SvIV(*temp);
165             }
166 0           temp=hv_fetch(hv,"family",6,1);
167 0 0         if((temp != NULL ) && SvIOK(*temp)){
    0          
168 0           h.ai_family = SvIV(*temp);
169             }
170 0           temp=hv_fetch(hv,"socktype",8,1);
171 0 0         if((temp != NULL ) && SvIOK(*temp)){
    0          
172 0           h.ai_socktype = SvIV(*temp);
173             }
174 0           temp=hv_fetch(hv,"protocol",8,1);
175 0 0         if((temp != NULL ) && SvIOK(*temp)){
    0          
176 0           h.ai_protocol = SvIV(*temp);
177             }
178 0           hh=&h;
179              
180 0           break;
181              
182 0           default:
183             //Perl_croak(aTHX_ "%s", "Hints must be an array or hash ref");
184             // Assume no hints. Let getaddrinfo work with the default hints by setting to NULL
185 0           hh=NULL;
186 0           break;
187             }
188             }
189              
190              
191 4           ret=getaddrinfo(hname, sname, hh, &res);
192              
193              
194 4 50         if(ret!=0){
195             // The return array to error?
196 0           errno=ret;
197 0           XSRETURN_UNDEF;
198             }
199             else{
200             // Copy results into output array
201             HV *h;
202             AV *a;
203 4           int count=0;
204 4           next=res;
205 64 100         while(next){
206 60           count++;
207 60           next=next->ai_next;
208             }
209 4           av_extend(results,count);
210             //Resize output array to fit count
211 4           int i=0;
212 4           next=res;
213 4 100         if(return_av){
214 26 100         while(next){
215 24           a=newAV();
216 24           av_store(a, AV_FLAGS, newSViv(0));
217 24           av_store(a, AV_FAMILY, newSViv(next->ai_family));
218 24           av_store(a, AV_TYPE, newSViv(next->ai_socktype));
219 24           av_store(a, AV_PROTOCOL, newSViv(next->ai_protocol));
220 24           av_store(a, AV_ADDR, newSVpv((char *) next->ai_addr, next->ai_addrlen));
221 24 100         if(next->ai_canonname == NULL){
222 23           av_store(a, AV_CANONNAME, newSVpv("",0));
223             }
224             else {
225 1           av_store(a, AV_CANONNAME, newSVpv((char *)next->ai_canonname,0));
226             }
227             //Push results to return stack
228 24           next=next->ai_next;
229 24           av_store(results, i, newRV_noinc((SV *)a));
230 24           i++;
231             }
232             }
233             else {
234 38 100         while(next){
235 36           h=newHV();
236 36           hv_store(h, "family", 6, newSViv(next->ai_family), 0);
237 36           hv_store(h, "socktype", 8, newSViv(next->ai_socktype), 0);
238 36           hv_store(h, "protocol", 8, newSViv(next->ai_protocol), 0);
239 36           hv_store(h, "addr", 4, newSVpv((char *)(next->ai_addr), next->ai_addrlen), 0);
240 36 50         if(next->ai_canonname == NULL){
241 36           hv_store(h, "canonname", 9, newSVpv("",0), 0);
242             }
243             else {
244 0           hv_store(h, "canonname", 9, newSVpv(next->ai_canonname,0), 0);
245             }
246              
247              
248             //Push results to return stack
249 36           next=next->ai_next;
250 36           av_store(results,i,newRV_noinc((SV *)h));
251 36           i++;
252              
253             }
254             }
255 4           freeaddrinfo(res);
256 4           XSRETURN_IV(1);
257             }
258              
259             const char *
260             gai_strerror(code)
261             int code;
262              
263              
264             SV*
265             getnameinfo(address, IN_OUT hostname, IN_OUT servicename, flags)
266             SV *address
267             SV *hostname
268             SV *servicename
269             SV *flags
270              
271             PROTOTYPE: $$$$
272            
273             INIT:
274             int ret;
275             char *host;
276             char *service;
277             int fl;
278             int addrlen;
279             struct sockaddr *addr;
280              
281             PPCODE:
282              
283             //Ensure outputs are not readonly
284            
285 1 50         if(SvREADONLY(hostname) || SvREADONLY(servicename)){
    50          
286 0           Perl_croak(aTHX_ "%s", PL_no_modify);
287             }
288              
289 1 50         if(SvOK(address) && SvPOK(address)){
    50          
290 1           addrlen=SvCUR(address);
291 1           addr=(struct sockaddr *)SvPVX(address);//SvGROW(address,0);
292             }
293              
294 1 50         if(!SvOK(hostname)){
295 0           hostname=sv_2mortal(newSV(NI_MAXHOST+1));
296              
297             }
298              
299 1           SvPOK_on(hostname);
300 1 50         host=SvGROW(hostname, NI_MAXHOST+1);
    0          
301              
302 1 50         if(!SvOK(servicename)){
303 0           servicename=sv_2mortal(newSV(NI_MAXSERV+1));
304             }
305              
306 1           SvPOK_on(servicename);
307 1 50         service=SvGROW(servicename, NI_MAXSERV+1);
    0          
308              
309              
310 1 50         if(SvOK(flags) && SvIOK(flags)){
    50          
311 1           fl=SvIV(flags);
312             }
313             else {
314 0           fl=0;
315             }
316            
317 1           ret=getnameinfo(addr, addrlen, host, NI_MAXHOST, service, NI_MAXSERV, fl);
318              
319 1 50         if(ret==0){
320             //Update the actual length used
321 1           SvCUR_set(hostname, strlen(host));
322 1           SvCUR_set(servicename, strlen(service));
323              
324             //Return as no error (true)
325 1           XSRETURN_IV(1);
326              
327             }
328             else {
329             //return as error, and set errno
330 0           errno=ret;
331             //SV * e=get_sv("!",GV_ADD);
332             //sv_setiv(e, ret);
333             //sv_setpv(e, gai_strerror(ret));
334 0           XSRETURN_UNDEF;
335             }
336