/* Ċ Ġ* ĠCopyright Ġ 2 0 1 4 - 2 0 1 9 ĠJetBrains Ġs . r . o Ġand Ġcontributors . ĠUse Ġof Ġthis Ġsource Ġcode Ġis Ġgoverned Ġby Ġthe ĠApache Ġ 2 . 0 Ġlicense . Ċ Ġ*/ Ċ Ċ package Ġio . ktor . network . sockets Ċ Ċ import Ġio . ktor . network . selector .* Ċ import Ġio . ktor . util .* Ċ import Ġio . ktor . util . network . Network Address Ċ import Ġio . ktor . utils . io .* Ċ import Ġio . ktor . utils . io . errors .* Ċ import Ġkotlinx . c interop .* Ċ import Ġkotlinx . coroutines .* Ċ import Ġplatform . posix .* Ċ import Ġkotlin . coroutines .* Ċ import Ġkotlin . math .* Ċ Ċ internal Ġclass ĠTCP Socket Native ( ĊĠĠĠ Ġprivate Ġval Ġdescriptor : ĠInt , ĊĠĠĠ Ġprivate Ġval Ġselector : ĠSelector Manager , ĊĠĠĠ Ġoverride Ġval Ġremote Address : ĠNetwork Address , ĊĠĠĠ Ġoverride Ġval Ġlocal Address : ĠNetwork Address , ĊĠĠĠ Ġparent : ĠCor outine Context Ġ= ĠEmpty Coroutine Context Ċ ) Ġ: ĠSocket , ĠCor outine Scope Ġ{ ĊĠĠĠ Ġprivate Ġval Ġ_ context : ĠComp letable Job Ġ= ĠJob ( parent [ Job ]) ĊĠĠĠ Ġprivate Ġval Ġselect able : ĠSelect able Native Ġ= ĠSelect able Native ( descriptor ) ĊĊĠĠĠ Ġoverride Ġval Ġcoroutine Context : ĠCor outine Context Ġ= Ġparent Ġ+ ĠDispatch ers . Un conf ined Ġ+ Ġ_ context ĊĊĠĠĠ Ġoverride Ġval Ġsocket Context : ĠJob ĊĠĠĠĠĠĠĠ Ġget () Ġ= Ġ_ context ĊĊĠĠĠ Ġinit Ġ{ ĊĠĠĠĠĠĠĠ Ġmake Shared () ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġ@ K tor Experimental API ĊĠĠĠ Ġoverride Ġfun Ġattach For Reading ( user Channel : ĠByte Channel ): ĠWriter Job Ġ= Ġwriter ( Dispatch ers . Un conf ined , Ġuser Channel ) Ġ{ ĊĠĠĠĠĠĠĠ Ġwhile Ġ(! channel . is Closed For Write ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġcount Ġ= Ġchannel . write Ġ{ Ġmemory , ĠstartIndex , Ġend Index Ġ-> ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġbuffer Start Ġ= Ġmemory . pointer Ġ+ ĠstartIndex ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġsize Ġ= Ġend Index Ġ- ĠstartIndex ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġresult Ġ= Ġrecv ( descriptor , Ġbuffer Start , Ġsize . convert (), Ġ 0 ). toInt () ĊĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġif Ġ( result Ġ== Ġ 0 ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġchannel . close () ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġif Ġ( result Ġ== Ġ- 1 ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġif Ġ( errno Ġ== ĠE AG AIN ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġreturn @ write Ġ 0 ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġthrow ĠPos ix Exception . for Errno () ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġresult . convert () ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠĠĠĠĠ Ġif Ġ( count Ġ== Ġ 0 Ġ&& Ġ! channel . is Closed For Write ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġselector . select ( selectable , ĠSelect Interest . READ ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠĠĠĠĠ Ġchannel . flush () ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠ Ġ}. apply Ġ{ ĊĠĠĠĠĠĠĠ Ġinvoke On Completion Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġshutdown ( descriptor , ĠSH UT _ RD ) ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġ@ K tor Experimental API ĊĠĠĠ Ġoverride Ġfun Ġattach For Writing ( user Channel : ĠByte Channel ): ĠReader Job Ġ= Ġreader ( Dispatch ers . Un conf ined , Ġuser Channel ) Ġ{ ĊĠĠĠĠĠĠĠ Ġvar Ġsock ed Closed Ġ= Ġfalse ĊĠĠĠĠĠĠĠ Ġvar Ġneed Select Ġ= Ġfalse ĊĠĠĠĠĠĠĠ Ġvar Ġtotal Ġ= Ġ 0 ĊĠĠĠĠĠĠĠ Ġwhile Ġ(! sock ed Closed Ġ&& Ġ! channel . is Closed For Read ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġcount Ġ= Ġchannel . read Ġ{ Ġmemory , Ġstart , Ġstop Ġ-> ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġbuffer Start Ġ= Ġmemory . pointer Ġ+ Ġstart ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġremaining Ġ= Ġstop Ġ- Ġstart ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġresult Ġ= Ġif Ġ( remaining Ġ> Ġ 0 ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġsend ( descriptor , Ġbuffer Start , Ġremaining . convert (), Ġ 0 ). toInt () ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} Ġelse Ġ 0 ĊĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġwhen Ġ( result ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ 0 Ġ-> Ġsock ed Closed Ġ= Ġtrue ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ- 1 Ġ-> Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġif Ġ( errno Ġ== ĠE AG AIN ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġneed Select Ġ= Ġtrue ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} Ġelse Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġthrow ĠPos ix Exception . for Errno () ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġmax ( 0 , Ġresult ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠĠĠĠĠ Ġtotal Ġ+= Ġcount ĊĠĠĠĠĠĠĠĠĠĠĠ Ġif Ġ(! sock ed Closed Ġ&& Ġneed Select ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġselector . select ( selectable , ĠSelect Interest . WRITE ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġneed Select Ġ= Ġfalse ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠ Ġif Ġ(! channel . is Closed For Read ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġavailable For Read Ġ= Ġchannel . available For Read ĊĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġcause Ġ= ĠIOException (" Failed Ġwriting Ġto Ġclosed Ġsocket . ĠSome Ġbytes Ġremaining : Ġ$ available For Read ") ĊĠĠĠĠĠĠĠĠĠĠĠ Ġchannel . cancel ( cause ) ĊĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠ Ġ}. apply Ġ{ ĊĠĠĠĠĠĠĠ Ġinvoke On Completion Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġshutdown ( descriptor , ĠSH UT _ WR ) ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġoverride Ġfun Ġclose () Ġ{ ĊĠĠĠĠĠĠĠ Ġ_ context . complete () ĊĠĠĠĠĠĠĠ Ġ_ context . invoke On Completion Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġshutdown ( descriptor , ĠSH UT _ RD WR ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġclose ( descriptor ) ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠ Ġ} Ċ } ĊĊ