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