xref: /unit/src/perl/nxt_perl_psgi_layer.c (revision 2060:a1991578c62e)
1 
2 /*
3  * Copyright (C) Alexander Borisov
4  * Copyright (C) NGINX, Inc.
5  */
6 
7 #include <perl/nxt_perl_psgi_layer.h>
8 
9 
10 typedef struct {
11     struct _PerlIO  base;
12 
13     SV              *var;
14 } nxt_perl_psgi_layer_stream_t;
15 
16 
17 static IV nxt_perl_psgi_layer_stream_pushed(pTHX_ PerlIO *f, const char *mode,
18     SV *arg, PerlIO_funcs *tab);
19 static IV nxt_perl_psgi_layer_stream_popped(pTHX_ PerlIO *f);
20 
21 static PerlIO *nxt_perl_psgi_layer_stream_open(pTHX_ PerlIO_funcs *self,
22     PerlIO_list_t *layers, IV n,
23     const char *mode, int fd, int imode, int perm,
24     PerlIO *f, int narg, SV **args);
25 
26 static IV nxt_perl_psgi_layer_stream_close(pTHX_ PerlIO *f);
27 
28 static SSize_t nxt_perl_psgi_layer_stream_read(pTHX_ PerlIO *f,
29     void *vbuf, Size_t count);
30 static SSize_t nxt_perl_psgi_layer_stream_write(pTHX_ PerlIO *f,
31     const void *vbuf, Size_t count);
32 
33 static IV nxt_perl_psgi_layer_stream_fileno(pTHX_ PerlIO *f);
34 static IV nxt_perl_psgi_layer_stream_seek(pTHX_ PerlIO *f,
35     Off_t offset, int whence);
36 static Off_t nxt_perl_psgi_layer_stream_tell(pTHX_ PerlIO *f);
37 static IV nxt_perl_psgi_layer_stream_fill(pTHX_ PerlIO *f);
38 static IV nxt_perl_psgi_layer_stream_flush(pTHX_ PerlIO *f);
39 
40 static SV *nxt_perl_psgi_layer_stream_arg(pTHX_ PerlIO *f,
41     CLONE_PARAMS *param, int flags);
42 
43 static PerlIO *nxt_perl_psgi_layer_stream_dup(pTHX_ PerlIO *f, PerlIO *o,
44     CLONE_PARAMS *param, int flags);
45 static IV nxt_perl_psgi_layer_stream_eof(pTHX_ PerlIO *f);
46 
47 static STDCHAR *nxt_perl_psgi_layer_stream_get_base(pTHX_ PerlIO *f);
48 static STDCHAR *nxt_perl_psgi_layer_stream_get_ptr(pTHX_ PerlIO *f);
49 static SSize_t nxt_perl_psgi_layer_stream_get_cnt(pTHX_ PerlIO *f);
50 static Size_t nxt_perl_psgi_layer_stream_buffersize(pTHX_ PerlIO *f);
51 static void nxt_perl_psgi_layer_stream_set_ptrcnt(pTHX_ PerlIO *f,
52     STDCHAR *ptr, SSize_t cnt);
53 
54 
55 static PERLIO_FUNCS_DECL(PerlIO_NGINX_Unit) = {
56     sizeof(PerlIO_funcs),
57     "NGINX_Unit_PSGI_Layer_Stream",
58     sizeof(nxt_perl_psgi_layer_stream_t),
59     PERLIO_K_BUFFERED | PERLIO_K_RAW,
60     nxt_perl_psgi_layer_stream_pushed,
61     nxt_perl_psgi_layer_stream_popped,
62     nxt_perl_psgi_layer_stream_open,
63     PerlIOBase_binmode,
64     nxt_perl_psgi_layer_stream_arg,
65     nxt_perl_psgi_layer_stream_fileno,
66     nxt_perl_psgi_layer_stream_dup,
67     nxt_perl_psgi_layer_stream_read,
68     NULL,
69     nxt_perl_psgi_layer_stream_write,
70     nxt_perl_psgi_layer_stream_seek,
71     nxt_perl_psgi_layer_stream_tell,
72     nxt_perl_psgi_layer_stream_close,
73     nxt_perl_psgi_layer_stream_flush,
74     nxt_perl_psgi_layer_stream_fill,
75     nxt_perl_psgi_layer_stream_eof,
76     PerlIOBase_error,
77     PerlIOBase_clearerr,
78     PerlIOBase_setlinebuf,
79     nxt_perl_psgi_layer_stream_get_base,
80     nxt_perl_psgi_layer_stream_buffersize,
81     nxt_perl_psgi_layer_stream_get_ptr,
82     nxt_perl_psgi_layer_stream_get_cnt,
83     nxt_perl_psgi_layer_stream_set_ptrcnt,
84 };
85 
86 
87 static IV
nxt_perl_psgi_layer_stream_pushed(pTHX_ PerlIO * f,const char * mode,SV * arg,PerlIO_funcs * tab)88 nxt_perl_psgi_layer_stream_pushed(pTHX_ PerlIO *f, const char *mode, SV *arg,
89     PerlIO_funcs *tab)
90 {
91     nxt_perl_psgi_layer_stream_t  *unit_stream;
92 
93     unit_stream = PerlIOSelf(f, nxt_perl_psgi_layer_stream_t);
94 
95     if (arg != NULL && SvOK(arg)) {
96         unit_stream->var = SvREFCNT_inc(arg);
97     }
98 
99     return PerlIOBase_pushed(aTHX_ f, mode, Nullsv, tab);
100 }
101 
102 
103 static IV
nxt_perl_psgi_layer_stream_popped(pTHX_ PerlIO * f)104 nxt_perl_psgi_layer_stream_popped(pTHX_ PerlIO *f)
105 {
106     nxt_perl_psgi_io_arg_t        *arg;
107     nxt_perl_psgi_layer_stream_t  *unit_stream;
108 
109     unit_stream = PerlIOSelf(f, nxt_perl_psgi_layer_stream_t);
110 
111     if (unit_stream->var != NULL) {
112         arg = (void *) (intptr_t) SvIV(SvRV(unit_stream->var));
113 
114         arg->io = NULL;
115         arg->fp = NULL;
116 
117         SvREFCNT_dec(unit_stream->var);
118         unit_stream->var = Nullsv;
119     }
120 
121     return 0;
122 }
123 
124 
125 static PerlIO *
nxt_perl_psgi_layer_stream_open(pTHX_ PerlIO_funcs * self,PerlIO_list_t * layers,IV n,const char * mode,int fd,int imode,int perm,PerlIO * f,int narg,SV ** args)126 nxt_perl_psgi_layer_stream_open(pTHX_ PerlIO_funcs *self,
127     PerlIO_list_t *layers, IV n,
128     const char *mode, int fd, int imode, int perm,
129     PerlIO *f, int narg, SV **args)
130 {
131     SV  *arg;
132 
133     arg = (narg > 0) ? *args : PerlIOArg;
134 
135     PERL_UNUSED_ARG(fd);
136     PERL_UNUSED_ARG(imode);
137     PERL_UNUSED_ARG(perm);
138 
139     if (SvROK(arg) || SvPOK(arg)) {
140 
141         if (f == NULL) {
142             f = PerlIO_allocate(aTHX);
143         }
144 
145         f = PerlIO_push(aTHX_ f, self, mode, arg);
146 
147         if (f != NULL) {
148             PerlIOBase(f)->flags |= PERLIO_F_OPEN;
149         }
150 
151         return f;
152     }
153 
154     return NULL;
155 }
156 
157 
158 static IV
nxt_perl_psgi_layer_stream_close(pTHX_ PerlIO * f)159 nxt_perl_psgi_layer_stream_close(pTHX_ PerlIO *f)
160 {
161     IV  code;
162 
163     code = PerlIOBase_close(aTHX_ f);
164     PerlIOBase(f)->flags &= ~(PERLIO_F_RDBUF | PERLIO_F_WRBUF);
165 
166     return code;
167 }
168 
169 
170 static IV
nxt_perl_psgi_layer_stream_fileno(pTHX_ PerlIO * f)171 nxt_perl_psgi_layer_stream_fileno(pTHX_ PerlIO *f)
172 {
173     PERL_UNUSED_ARG(f);
174     return -1;
175 }
176 
177 
178 static SSize_t
nxt_perl_psgi_layer_stream_read(pTHX_ PerlIO * f,void * vbuf,Size_t count)179 nxt_perl_psgi_layer_stream_read(pTHX_ PerlIO *f, void *vbuf, Size_t count)
180 {
181     nxt_perl_psgi_io_arg_t        *arg;
182     nxt_perl_psgi_layer_stream_t  *unit_stream;
183 
184     if (f == NULL) {
185         return 0;
186     }
187 
188     if ((PerlIOBase(f)->flags & PERLIO_F_CANREAD) == 0) {
189         PerlIOBase(f)->flags |= PERLIO_F_ERROR;
190 
191         SETERRNO(EBADF, SS_IVCHAN);
192 
193         return 0;
194     }
195 
196     unit_stream = PerlIOSelf(f, nxt_perl_psgi_layer_stream_t);
197     arg = (void *) (intptr_t) SvIV(SvRV(unit_stream->var));
198 
199     return arg->io_tab->read(PERL_GET_CONTEXT, arg, vbuf, count);
200 }
201 
202 
203 static SSize_t
nxt_perl_psgi_layer_stream_write(pTHX_ PerlIO * f,const void * vbuf,Size_t count)204 nxt_perl_psgi_layer_stream_write(pTHX_ PerlIO *f,
205     const void *vbuf, Size_t count)
206 {
207     nxt_perl_psgi_io_arg_t        *arg;
208     nxt_perl_psgi_layer_stream_t  *unit_stream;
209 
210     if (PerlIOBase(f)->flags & PERLIO_F_CANWRITE) {
211         unit_stream = PerlIOSelf(f, nxt_perl_psgi_layer_stream_t);
212         arg = (void *) (intptr_t) SvIV(SvRV(unit_stream->var));
213 
214         return arg->io_tab->write(PERL_GET_CONTEXT, arg, vbuf, count);
215     }
216 
217     return 0;
218 }
219 
220 
221 static IV
nxt_perl_psgi_layer_stream_seek(pTHX_ PerlIO * f,Off_t offset,int whence)222 nxt_perl_psgi_layer_stream_seek(pTHX_ PerlIO *f, Off_t offset, int whence)
223 {
224     PERL_UNUSED_ARG(f);
225     return 0;
226 }
227 
228 
229 static Off_t
nxt_perl_psgi_layer_stream_tell(pTHX_ PerlIO * f)230 nxt_perl_psgi_layer_stream_tell(pTHX_ PerlIO *f)
231 {
232     PERL_UNUSED_ARG(f);
233     return 0;
234 }
235 
236 
237 static IV
nxt_perl_psgi_layer_stream_fill(pTHX_ PerlIO * f)238 nxt_perl_psgi_layer_stream_fill(pTHX_ PerlIO *f)
239 {
240     PERL_UNUSED_ARG(f);
241     return -1;
242 }
243 
244 
245 static IV
nxt_perl_psgi_layer_stream_flush(pTHX_ PerlIO * f)246 nxt_perl_psgi_layer_stream_flush(pTHX_ PerlIO *f)
247 {
248     return 0;
249 }
250 
251 
252 static SV *
nxt_perl_psgi_layer_stream_arg(pTHX_ PerlIO * f,CLONE_PARAMS * param,int flags)253 nxt_perl_psgi_layer_stream_arg(pTHX_ PerlIO * f,
254     CLONE_PARAMS *param, int flags)
255 {
256     SV                            *var;
257     nxt_perl_psgi_layer_stream_t  *unit_stream;
258 
259     unit_stream = PerlIOSelf(f, nxt_perl_psgi_layer_stream_t);
260     var = unit_stream->var;
261 
262     if (flags & PERLIO_DUP_CLONE) {
263         var = PerlIO_sv_dup(aTHX_ var, param);
264 
265     } else if (flags & PERLIO_DUP_FD) {
266         var = newSVsv(var);
267 
268     } else {
269         var = SvREFCNT_inc(var);
270     }
271 
272     return var;
273 }
274 
275 
276 static PerlIO *
nxt_perl_psgi_layer_stream_dup(pTHX_ PerlIO * f,PerlIO * o,CLONE_PARAMS * param,int flags)277 nxt_perl_psgi_layer_stream_dup(pTHX_ PerlIO *f, PerlIO *o,
278     CLONE_PARAMS *param, int flags)
279 {
280     nxt_perl_psgi_layer_stream_t  *fs;
281 
282     f = PerlIOBase_dup(aTHX_ f, o, param, flags);
283 
284     if (f != NULL) {
285         fs = PerlIOSelf(f, nxt_perl_psgi_layer_stream_t);
286         fs->var = nxt_perl_psgi_layer_stream_arg(aTHX_ o, param, flags);
287     }
288 
289     return f;
290 }
291 
292 
293 static IV
nxt_perl_psgi_layer_stream_eof(pTHX_ PerlIO * f)294 nxt_perl_psgi_layer_stream_eof(pTHX_ PerlIO *f)
295 {
296     return 1;
297 }
298 
299 
300 static STDCHAR *
nxt_perl_psgi_layer_stream_get_base(pTHX_ PerlIO * f)301 nxt_perl_psgi_layer_stream_get_base(pTHX_ PerlIO *f)
302 {
303     return (STDCHAR *) NULL;
304 }
305 
306 
307 static STDCHAR *
nxt_perl_psgi_layer_stream_get_ptr(pTHX_ PerlIO * f)308 nxt_perl_psgi_layer_stream_get_ptr(pTHX_ PerlIO *f)
309 {
310     return (STDCHAR *) NULL;
311 }
312 
313 
314 static SSize_t
nxt_perl_psgi_layer_stream_get_cnt(pTHX_ PerlIO * f)315 nxt_perl_psgi_layer_stream_get_cnt(pTHX_ PerlIO *f)
316 {
317     return 0;
318 }
319 
320 
321 static Size_t
nxt_perl_psgi_layer_stream_buffersize(pTHX_ PerlIO * f)322 nxt_perl_psgi_layer_stream_buffersize(pTHX_ PerlIO *f)
323 {
324     return 0;
325 }
326 
327 
328 static void
nxt_perl_psgi_layer_stream_set_ptrcnt(pTHX_ PerlIO * f,STDCHAR * ptr,SSize_t cnt)329 nxt_perl_psgi_layer_stream_set_ptrcnt(pTHX_ PerlIO *f,
330     STDCHAR *ptr, SSize_t cnt)
331 {
332     /* Need some code. */
333 }
334 
335 
336 void
nxt_perl_psgi_layer_stream_init(pTHX)337 nxt_perl_psgi_layer_stream_init(pTHX)
338 {
339     PerlIO_define_layer(aTHX_ PERLIO_FUNCS_CAST(&PerlIO_NGINX_Unit));
340 }
341 
342 
343 PerlIO *
nxt_perl_psgi_layer_stream_fp_create(pTHX_ SV * arg_rv,const char * mode)344 nxt_perl_psgi_layer_stream_fp_create(pTHX_ SV *arg_rv,
345     const char *mode)
346 {
347     return PerlIO_openn(aTHX_ "NGINX_Unit_PSGI_Layer_Stream",
348                         mode, 0, 0, 0, NULL, 1, &arg_rv);
349 }
350 
351 
352 void
nxt_perl_psgi_layer_stream_fp_destroy(pTHX_ PerlIO * io)353 nxt_perl_psgi_layer_stream_fp_destroy(pTHX_ PerlIO *io)
354 {
355     PerlIO_close(io);
356 }
357 
358 
359 SV *
nxt_perl_psgi_layer_stream_io_create(pTHX_ PerlIO * fp)360 nxt_perl_psgi_layer_stream_io_create(pTHX_ PerlIO *fp)
361 {
362     SV  *rvio;
363     IO  *thatio;
364 
365     thatio = newIO();
366 
367     if (thatio == NULL) {
368         return NULL;
369     }
370 
371     IoOFP(thatio) = fp;
372     IoIFP(thatio) = fp;
373 
374     rvio = newRV_noinc((SV *) thatio);
375 
376     if (rvio == NULL) {
377         SvREFCNT_dec(thatio);
378         return NULL;
379     }
380 
381     return rvio;
382 }
383