.\" Automatically generated by Pod::Man 4.09 (Pod::Simple 3.35) .\" .\" Standard preamble: .\" ======================================================================== .de Sp \" Vertical space (when we can't use .PP) .if t .sp .5v .if n .sp .. .de Vb \" Begin verbatim text .ft CW .nf .ne \\$1 .. .de Ve \" End verbatim text .ft R .fi .. .\" Set up some character translations and predefined strings. \*(-- will .\" give an unbreakable dash, \*(PI will give pi, \*(L" will give a left .\" double quote, and \*(R" will give a right double quote. \*(C+ will .\" give a nicer C++. Capital omega is used to do unbreakable dashes and .\" therefore won't be available. \*(C` and \*(C' expand to `' in nroff, .\" nothing in troff, for use with C<>. .tr \(*W- .ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p' .ie n \{\ . ds -- \(*W- . ds PI pi . if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch . if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\" diablo 12 pitch . ds L" "" . ds R" "" . ds C` "" . ds C' "" 'br\} .el\{\ . ds -- \|\(em\| . ds PI \(*p . ds L" `` . ds R" '' . ds C` . ds C' 'br\} .\" .\" Escape single quotes in literal strings from groff's Unicode transform. .ie \n(.g .ds Aq \(aq .el .ds Aq ' .\" .\" If the F register is >0, we'll generate index entries on stderr for .\" titles (.TH), headers (.SH), subsections (.SS), items (.Ip), and index .\" entries marked with X<> in POD. Of course, you'll have to process the .\" output yourself in some meaningful fashion. .\" .\" Avoid warning from groff about undefined register 'F'. .de IX .. .if !\nF .nr F 0 .if \nF>0 \{\ . de IX . tm Index:\\$1\t\\n%\t"\\$2" .. . if !\nF==2 \{\ . nr % 0 . nr F 2 . \} .\} .\" .\" Accent mark definitions (@(#)ms.acc 1.5 88/02/08 SMI; from UCB 4.2). .\" Fear. Run. Save yourself. No user-serviceable parts. . \" fudge factors for nroff and troff .if n \{\ . ds #H 0 . ds #V .8m . ds #F .3m . ds #[ \f1 . ds #] \fP .\} .if t \{\ . ds #H ((1u-(\\\\n(.fu%2u))*.13m) . ds #V .6m . ds #F 0 . ds #[ \& . ds #] \& .\} . \" simple accents for nroff and troff .if n \{\ . ds ' \& . ds ` \& . ds ^ \& . ds , \& . ds ~ ~ . ds / .\} .if t \{\ . ds ' \\k:\h'-(\\n(.wu*8/10-\*(#H)'\'\h"|\\n:u" . ds ` \\k:\h'-(\\n(.wu*8/10-\*(#H)'\`\h'|\\n:u' . ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'^\h'|\\n:u' . ds , \\k:\h'-(\\n(.wu*8/10)',\h'|\\n:u' . ds ~ \\k:\h'-(\\n(.wu-\*(#H-.1m)'~\h'|\\n:u' . ds / \\k:\h'-(\\n(.wu*8/10-\*(#H)'\z\(sl\h'|\\n:u' .\} . \" troff and (daisy-wheel) nroff accents .ds : \\k:\h'-(\\n(.wu*8/10-\*(#H+.1m+\*(#F)'\v'-\*(#V'\z.\h'.2m+\*(#F'.\h'|\\n:u'\v'\*(#V' .ds 8 \h'\*(#H'\(*b\h'-\*(#H' .ds o \\k:\h'-(\\n(.wu+\w'\(de'u-\*(#H)/2u'\v'-.3n'\*(#[\z\(de\v'.3n'\h'|\\n:u'\*(#] .ds d- \h'\*(#H'\(pd\h'-\w'~'u'\v'-.25m'\f2\(hy\fP\v'.25m'\h'-\*(#H' .ds D- D\\k:\h'-\w'D'u'\v'-.11m'\z\(hy\v'.11m'\h'|\\n:u' .ds th \*(#[\v'.3m'\s+1I\s-1\v'-.3m'\h'-(\w'I'u*2/3)'\s-1o\s+1\*(#] .ds Th \*(#[\s+2I\s-2\h'-\w'I'u*3/5'\v'-.3m'o\v'.3m'\*(#] .ds ae a\h'-(\w'a'u*4/10)'e .ds Ae A\h'-(\w'A'u*4/10)'E . \" corrections for vroff .if v .ds ~ \\k:\h'-(\\n(.wu*9/10-\*(#H)'\s-2\u~\d\s+2\h'|\\n:u' .if v .ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'\v'-.4m'^\v'.4m'\h'|\\n:u' . \" for low resolution devices (crt and lpr) .if \n(.H>23 .if \n(.V>19 \ \{\ . ds : e . ds 8 ss . ds o a . ds d- d\h'-1'\(ga . ds D- D\h'-1'\(hy . ds th \o'bp' . ds Th \o'LP' . ds ae ae . ds Ae AE .\} .rm #[ #] #H #V #F C .\" ======================================================================== .\" .IX Title "IO::Stream 3pm" .TH IO::Stream 3pm "2018-05-18" "perl v5.26.2" "User Contributed Perl Documentation" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l .nh .SH "NAME" IO::Stream \- ease non\-blocking I/O streams based on EV .SH "VERSION" .IX Header "VERSION" This document describes IO::Stream version v2.0.3 .SH "SYNOPSIS" .IX Header "SYNOPSIS" .Vb 2 \& use EV; \& use IO::Stream; \& \& IO::Stream\->new({ \& host => \*(Aqgoogle.com\*(Aq, \& port => 80, \& cb => \e&client, \& wait_for => SENT|EOF, \& in_buf_limit=> 102400, \& out_buf => "GET / HTTP/1.0\enHost: google.com\en\en", \& }); \& \& $EV::DIED = sub { warn $@; EV::unloop }; \& EV::loop; \& \& sub client { \& my ($io, $e, $err) = @_; \& if ($err) { \& $io\->close(); \& die $err; \& } \& if ($e & SENT) { \& print "request sent, waiting for reply...\en"; \& } \& if ($e & EOF) { \& print "server reply:\en", $io\->{in_buf}; \& $io\->close(); \& EV::unloop; # ALL DONE \& } \& } .Ve .SH "DESCRIPTION" .IX Header "DESCRIPTION" Non-blocking event-based low-level I/O is hard to get right. Code usually error-prone and complex... and it very similar in all applications. Things become much worse when you need to alter I/O stream in some way \- use proxies, encryption, \s-1SSL,\s0 etc. .PP This module designed to give user ability to work with I/O streams on higher level, using input/output buffers (just scalars) and high-level events like \s-1CONNECTED, SENT\s0 or \s-1EOF.\s0 As same time it doesn't hide low-level things, and user still able to work on low-level without any limitations. .SS "\s-1PLUGINS\s0" .IX Subsection "PLUGINS" Architecture of this module make it ease to write plugins, which will alter I/O stream in any way \- route it through proxies, encrypt, log, etc. .PP Here are few available plugins, you may find more on \s-1CPAN:\s0 IO::Stream::Crypt::RC4, IO::Stream::Proxy::HTTPS, IO::Stream::MatrixSSL::Client, IO::Stream::MatrixSSL::Server. .PP If you interested in writing own plugin, check source for \*(L"skeleton\*(R" plugins: IO::Stream::Noop and IO::Stream::NoopAlias. .SH "EXPORTS" .IX Header "EXPORTS" This modules doesn't export any functions/methods/variables, but it exports a lot of constants. There two groups of constants: events and errors (which can be imported using tags ':Event' and ':Error'). By default all constants are exported. .PP Events: .PP .Vb 1 \& RESOLVED CONNECTED IN OUT EOF SENT .Ve .PP Errors: .PP .Vb 4 \& EINBUFLIMIT \& ETORESOLVE ETOCONNECT ETOWRITE \& EDNS EDNSNXDOMAIN EDNSNODATA \& EREQINBUFLIMIT EREQINEOF .Ve .PP Errors are similar to $! \- they're dualvars, having both textual and numeric values. .PP \&\fB\s-1NOTE:\s0\fR Since v2.0.0 \f(CW\*(C`ETORESOLVE\*(C'\fR, \f(CW\*(C`EDNSNXDOMAIN\*(C'\fR and \f(CW\*(C`EDNSNODATA\*(C'\fR are not used anymore (\f(CW\*(C`EDNS\*(C'\fR is used instead), but they're still exported for compatibility. .SH "OVERVIEW" .IX Header "OVERVIEW" You can create IO::Stream object using any \*(L"stream\*(R" fh (file, \s-1TTY, UNIX\s0 socket, \s-1TCP\s0 socket, pipe, \s-1FIFO\s0). Or, if you need \s-1TCP\s0 socket, you can create IO::Stream object using host+port instead of fh (in this case IO::Stream will do non-blocking host resolving, create \s-1TCP\s0 socket and do non-blocking connect). .PP After you created IO::Stream object, it will handle read/write on this fh, and deliver only high-level events you asked for into your callback, where you will be able to operate with in/out buffers instead of doing \&\fIsysread()\fR/\fIsyswrite()\fR manually. .PP There no limitations on what you can do with fh after you've created IO::Stream object \- you can even do \fIsysread()\fR/\fIsyswrite()\fR (but there no reasons for you to do this anymore). .PP \&\fB\s-1IMPORTANT\s0!\fR When you want to close this fh, \&\fByou \s-1MUST\s0 use \f(CB$io\fB\->\f(BIclose()\fB method for closing fh\fR instead of doing close($fh). This is because IO::Stream doesn't require from you to keep object returned by \fInew()\fR, and without call to \f(CW$io\fR\->\fIclose()\fR IO::Stream object will continue to exists and may receive/generate some events, which is not what you expect after closing fh. Also, if you keep object returned by IO::Stream\->\fInew()\fR somewhere in your variables, you should either undef all such variables after you called \f(CW$io\fR\->\fIclose()\fR, or you should use \fIScalar::Util::weaken()\fR on these variables after storing IO::Stream object. (The same is applicable for all plugin objects too.) .SS "\s-1EVENTS\s0" .IX Subsection "EVENTS" .IP "\s-1RESOLVED\s0" 4 .IX Item "RESOLVED" If you created IO::Stream object using {host}+{port} instead of {fh}, this event will be generated after resolving {host}. Resolved \s-1IP\s0 address will be stored in {ip}. .IP "\s-1CONNECTED\s0" 4 .IX Item "CONNECTED" If you created IO::Stream object using {host}+{port} instead of {fh}, this event will be generated after connecting socket to {ip}:{port}. .IP "\s-1IN\s0" 4 .IX Item "IN" Generated after each successful read. IO::Stream may execute several \&\fIsysread()\fR at once before generating \s-1IN\s0 event for optimization. Read data will be stored in {in_buf}, and {in_bytes} counter will be incremented by amount of bytes read. .IP "\s-1EOF\s0" 4 .IX Item "EOF" Generated only \fB\s-1ONCE\s0\fR when \s-1EOF\s0 reached (\fIsysread()\fR return 0). Also will set {is_eof} to true. .IP "\s-1OUT\s0" 4 .IX Item "OUT" Generated when some data from {out_buf} was written. Written bytes either removed from {out_buf} or just increment {out_pos} by amount of bytes written (see documentation about these fields below for more details). Also increment {out_bytes} counter by amount of bytes written. .Sp Here 'written' may be somewhat virtual, while {out_buf}/{out_pos} changes, the real data still can be in plugin buffers (if you use plugins) and real \&\fIsyswrite()\fR may not be called yet. To detect when all data is \fBreally\fR written you should use \s-1SENT\s0 event, not \s-1OUT.\s0 .IP "\s-1SENT\s0" 4 .IX Item "SENT" Generated when all data from {out_buf} was written. It's usual and safe to call \f(CW$io\fR\->\fIclose()\fR on \s-1SENT\s0 event. .SS "\s-1TIMEOUTS\s0" .IX Subsection "TIMEOUTS" IO::Stream has 30\-second timeouts for connect and write, to timeout \s-1DNS\s0 resolve it use default AnyEvent::DNS timeout. If you need to timeout other operations, you have to create own timers using \fIEV::timer()\fR. .PP Current version doesn't allow you to change these timeouts. .SS "\s-1SERVER\s0" .IX Subsection "SERVER" If you need to run TCP/UNIX\-server socket, then you should handle that socket manually. But you can create IO::Stream object for \fIaccept()\fR'ed socket: .PP .Vb 10 \& my ($host, $port) = (\*(Aq0.0.0.0\*(Aq, 1234); \& socket my $srv_sock, AF_INET, SOCK_STREAM, 0; \& setsockopt $srv_sock, SOL_SOCKET, SO_REUSEADDR, 1; \& bind $srv_sock, sockaddr_in($port, inet_aton($host)); \& listen $srv_sock, SOMAXCONN; \& fcntl $srv_sock, F_SETFL, O_NONBLOCK; \& $srv_w = EV::io($srv_sock, EV::READ, sub { \& if (accept my $sock, $srv_sock) { \& IO::Stream\->new({ \& fh => $sock, \& cb => \e&server, \& wait_for => IN, \& }); \& } \& elsif ($! != EAGAIN) { \& die "accept: $!"; \& } \& }); .Ve .SH "INTERFACE" .IX Header "INTERFACE" IO::Stream provide only three public methods: \fInew()\fR, \fIwrite()\fR and \fIclose()\fR. \&\fInew()\fR will create new object, \fIclose()\fR will destroy it and \fIwrite()\fR must be called when you want to modify (or just modified) output buffer. .PP All other operations are done using IO::Stream object fields \- for simplicity and performance reasons. Moreover, you can keep your own data in it. There convention on field names, to avoid conflicts: .IP "/^_/" 4 .IX Item "/^_/" Fields with names started with underscore are for internal use by IO::Stream, you shouldn't touch them or create your own field with such names. .IP "/^[a\-z]/" 4 .IX Item "/^[a-z]/" Fields with names started with lower-case letter are part of IO::Stream public interface \- you allowed to read/write these fields, but you should not store incorrect values in these fields. Check \*(L"\s-1PUBLIC FIELDS\*(R"\s0 below for description of available fields and their format. .IP "/^[A\-Z]/" 4 .IX Item "/^[A-Z]/" You can store your own data in IO::Stream object using field names started with upper-case letter. IO::Stream will not touch these fields. .PP When some event arise which you're waited for, your callback will be called with 3 parameters: IO::Stream object, event mask, and error (if any): .PP .Vb 3 \& sub callback { \& my ($io, $e, $err) = @_; \& } .Ve .SH "METHODS" .IX Header "METHODS" .SS "new" .IX Subsection "new" .Vb 1 \& IO::Stream\->new( \e%opt ); .Ve .PP Create and return IO::Stream object. You may not keep returned object \- you will get it in your callback (in first parameter) when some interesting for your event happens, and will exists until to call method \fIclose()\fR. See \s-1OVERVIEW\s0 for more details. .PP Fields of \f(CW%opt\fR become fields of created IO::Stream object. There only few fields required, but you can set any other fields too, and can also set your custom fields (with names starting from upper-case letter). .PP Only required fields in \f(CW%opt\fR are {cb} and either {fh} or {host}+{port}. The {wait_for} field also highly recommended to set when creating object. .PP If {out_buf} will be set, then \fInew()\fR will automatically call \fIwrite()\fR after creating object. .PP .Vb 5 \& IO::Stream\->new({ \& fh => \e*STDIN, \& cb => \e&console, \& wait_for => IN, \& }); .Ve .SS "write" .IX Subsection "write" .Vb 2 \& $io\->write(); \& $io\->write($data); .Ve .PP Method \fIwrite()\fR \fB\s-1MUST\s0\fR be called after any modifications of {out_buf} field, to ensure data in {out_buf} will be written to {fh} as soon as it will be possible. .PP If {fh} available for writing when calling \fIwrite()\fR, then it will write (may be partially) {out_buf} and may immediately call your callback function delivering OUT|SENT events there. So, if you call \fIwrite()\fR from that callback (as it usually happens), keep in mind it may be called again while executing \&\fIwrite()\fR, and object state may significantly change (it even may be \fIclose()\fR'd) after it return from \fIwrite()\fR into your callback. .PP The write($data) is just a shortcut for: .PP .Vb 2 \& $io\->{out_buf} .= $data; \& $io\->write(); .Ve .SS "close" .IX Subsection "close" .Vb 1 \& $io\->close() .Ve .PP Method \fIclose()\fR will close {fh} and destroy IO::Stream object. See \s-1OVERVIEW\s0 for more details. .SH "PUBLIC FIELDS" .IX Header "PUBLIC FIELDS" If field marked *RO* that mean field is read-only and shouldn't be changed. .PP Some field have default values (shown after equal sign). .PP Some field modified on events. .IP "cb" 4 .IX Item "cb" .PD 0 .IP "method ='\s-1IO\s0'" 4 .IX Item "method ='IO'" .PD User callback which will be called when some listed in {wait_for} events arise or error happens. .Sp Field {cb} should be either \s-1CODE\s0 ref or object or class name. In last two cases method named {method} will be called. Field {method} should be string. .IP "wait_for" 4 .IX Item "wait_for" Bitmask of events interesting for user. Can be changed at any time. For example: .Sp .Vb 1 \& $io\->{wait_for} = RESOLVED|CONNECTED|IN|EOF|OUT|SENT; .Ve .Sp When some data will be read from {fh}, {wait_for} must contain \s-1IN\s0 and/or \s-1EOF,\s0 or error \s-1EREQINEOF\s0 will be generated. So, it's better to always have \&\s-1IN\s0 and/or \s-1EOF\s0 in {wait_for}. .Sp If {wait_for} contain \s-1EOF\s0 and doesn't contain \s-1IN\s0 then {in_buf_limit} must be defined or error \s-1EREQINBUFLIMIT\s0 will be generated. .IP "fh *RO*" 4 .IX Item "fh *RO*" File handle for doing I/O. It's either provided by user to \fInew()\fR, or created by \fInew()\fR (when user provided {host}+{port} instead). .IP "host *RO*" 4 .IX Item "host *RO*" .PD 0 .IP "port *RO*" 4 .IX Item "port *RO*" .PD If user doesn't provide {fh} to \fInew()\fR, he should provide {host} and {port} instead. This way \fInew()\fR will create new \s-1TCP\s0 socket in {fh} and resolve {host} and connect this {fh} to resolved {ip} and {port}. Both resolving and connecting happens in non-blocking way, and will result in delivering \&\s-1RESOLVED\s0 and \s-1CONNECTED\s0 events into user callback (if user {wait_for} these events). .IP "in_buf_limit =undef" 4 .IX Item "in_buf_limit =undef" Used to avoid DoS attach when user doesn't handle \s-1IN\s0 events and want his callback called only on \s-1EOF\s0 event. Must be defined if user have \s-1EOF\s0 without \&\s-1IN\s0 in {wait_for}. .Sp Any value >0 will defined amount of bytes which can be read into {in_buf} before \s-1EOF\s0 happens. When size of {in_buf} become larger than {in_buf_limit}, error \s-1EINBUFLIMIT\s0 will be delivered to user callback. In this case user can either remove some data from {in_buf} to make it smaller than {in_buf_limit} or increase {in_buf_limit}, and continue reading data. .Sp \&\fB\s-1NOT RECOMMENDED\s0!\fR Value 0 will switch off DoS protection, so there will be no limit on amount of data to read into {in_buf} until \s-1EOF\s0 happens. .IP "out_buf =q{} # modified on: \s-1OUT\s0" 4 .IX Item "out_buf =q{} # modified on: OUT" .PD 0 .IP "out_pos =undef # modified on: \s-1OUT\s0" 4 .IX Item "out_pos =undef # modified on: OUT" .PD Data from {out_buf} will be written to {fh}. .Sp If {out_pos} not defined, then data will be written from beginning of {out_buf}, and after successful write written bytes will be removed from beginning of {out_buf}. .Sp If {out_pos} defined, it should be >= 0. In this case data will be written from {out_pos} position in {out_buf}, and after successful write {out_pos} will be incremented by amount of bytes written. {out_buf} will not be changed! .IP "out_bytes =0 # modified on: \s-1OUT\s0" 4 .IX Item "out_bytes =0 # modified on: OUT" Each successful write will increment {out_bytes} by amount of written bytes. You can change {out_bytes} in any way, but it should always be a number. .IP "in_buf =q{} # modified on: \s-1IN\s0" 4 .IX Item "in_buf =q{} # modified on: IN" Each successful read will concatenate read bytes to {in_buf}. You can change {in_buf} in any way, but it should always be a string. .IP "in_bytes =0 # modified on: \s-1IN\s0" 4 .IX Item "in_bytes =0 # modified on: IN" Each successful read will increment {in_bytes} by amount of read bytes. You can change {in_bytes} in any way, but it should always be a number. .IP "ip *RO* =undef # modified on: \s-1RESOLVED\s0" 4 .IX Item "ip *RO* =undef # modified on: RESOLVED" When you call \fInew()\fR with {host}+{port} instead of {fh} then \s-1IP\s0 address resolved from {host} will be stored in {ip}, and event \s-1RESOLVED\s0 will be generated. .IP "is_eof *RO* =undef # modified on: \s-1EOF\s0" 4 .IX Item "is_eof *RO* =undef # modified on: EOF" When \s-1EOF\s0 event happens {is_eof} will be set to true value. This allow you to detect is \s-1EOF\s0 already happens at any time, even if you doesn't have \s-1EOF\s0 in {wait_for}. .IP "plugin *RO* ={}" 4 .IX Item "plugin *RO* ={}" Allow you to set list of plugins when creating object with \fInew()\fR, and later access these plugins. .Sp This field is somewhat special, because when you call \fInew()\fR you should set plugin to \s-1ARRAY\s0 ref, but in IO::Stream object {plugin} is \s-1HASH\s0 ref: .Sp .Vb 10 \& my $io = IO::Stream\->new({ \& host => \*(Aqwww.google.com\*(Aq, \& port => 443, \& cb => \e&google, \& wait_for => EOF, \& in_buf_limit=> 102400, \& out_buf => "GET / HTTP/1.0\enHost: www.google.com\en\en", \& plugin => [ # <\-\-\-\-\-\- it\*(Aqs ARRAY, but looks like HASH \& ssl => IO::Stream::MatrixSSL::Client\->new(), \& proxy => IO::Stream::Proxy::HTTPS\->new({ \& host => \*(Aqmy.proxy.com\*(Aq, \& port => 3218, \& user => \*(Aqme\*(Aq, \& pass => \*(Aqmy pass\*(Aq, \& }), \& ], \& MyField1 => \*(Aqmy data1\*(Aq, \& MyField2 => \e%mydata2, \& }); \& \& # access the "proxy" plugin: \& $io\->{plugin}{proxy}; .Ve .Sp This is because when calling \fInew()\fR it's important to keep plugins in order, but later it's easier to access them using names. .SH "DIAGNOSTICS" .IX Header "DIAGNOSTICS" Exceptions may be thrown only in \fInew()\fR. All other errors will be delivered to user's callback in last parameter. .ie n .IP """usage: IO::Stream\->new({ cb=>, wait_for=>, [fh=>, | host=>, port=>,] ... })""" 4 .el .IP "\f(CWusage: IO::Stream\->new({ cb=>, wait_for=>, [fh=>, | host=>, port=>,] ... })\fR" 4 .IX Item "usage: IO::Stream->new({ cb=>, wait_for=>, [fh=>, | host=>, port=>,] ... })" You called \fInew()\fR with wrong parameters. .ie n .IP """socket: %s""" 4 .el .IP "\f(CWsocket: %s\fR" 4 .IX Item "socket: %s" .PD 0 .ie n .IP """fcntl: %s""" 4 .el .IP "\f(CWfcntl: %s\fR" 4 .IX Item "fcntl: %s" .PD Error happens while creating new socket. Usually this happens because you run out of file descriptors. .ie n .IP """can\*(Aqt get file descriptor""" 4 .el .IP "\f(CWcan\*(Aqt get file descriptor\fR" 4 .IX Item "cant get file descriptor" Failed to get \fIfileno()\fR for your fh. Either fh doesn't open, or this fh type is not supported (directory handle), or fh is not file handle at all. .ie n .IP """can\*(Aqt create second object for same fh""" 4 .el .IP "\f(CWcan\*(Aqt create second object for same fh\fR" 4 .IX Item "cant create second object for same fh" You can't have more than one IO::Stream object for same fh. .Sp IO::Stream keep all objects created by \fInew()\fR until \f(CW$io\fR\->\fIclose()\fR will be called. Probably you've closed fh in some way without calling \&\f(CW$io\fR\->\fIclose()\fR, then new fh was created with same file descriptor number, and you've tried to create IO::Stream object using new fh. .SH "SEE ALSO" .IX Header "SEE ALSO" AnyEvent::Handle .SH "SUPPORT" .IX Header "SUPPORT" .SS "Bugs / Feature Requests" .IX Subsection "Bugs / Feature Requests" Please report any bugs or feature requests through the issue tracker at . You will be notified automatically of any progress on your issue. .SS "Source Code" .IX Subsection "Source Code" This is open source software. The code repository is available for public review and contribution under the terms of the license. Feel free to fork the repository and submit pull requests. .PP .PP .Vb 1 \& git clone https://github.com/powerman/perl\-IO\-Stream.git .Ve .SS "Resources" .IX Subsection "Resources" .IP "\(bu" 4 MetaCPAN Search .Sp .IP "\(bu" 4 \&\s-1CPAN\s0 Ratings .Sp .IP "\(bu" 4 AnnoCPAN: Annotated \s-1CPAN\s0 documentation .Sp .IP "\(bu" 4 \&\s-1CPAN\s0 Testers Matrix .Sp .IP "\(bu" 4 \&\s-1CPANTS: A CPAN\s0 Testing Service (Kwalitee) .Sp .SH "AUTHOR" .IX Header "AUTHOR" Alex Efros .SH "COPYRIGHT AND LICENSE" .IX Header "COPYRIGHT AND LICENSE" This software is Copyright (c) 2008\- by Alex Efros . .PP This is free software, licensed under: .PP .Vb 1 \& The MIT (X11) License .Ve