1717 * along with Aero. If not, see <https://www.gnu.org/licenses/>.
1818 */
1919
20- use aero_syscall:: { IpProtocol , SocketAddrInet , SocketType , SyscallError } ;
20+ use aero_syscall:: socket:: MessageHeader ;
21+ use aero_syscall:: { IpProtocol , OpenFlags , SocketAddrInet , SocketType , SyscallError } ;
2122use alloc:: sync:: { Arc , Weak } ;
2223use alloc:: vec:: Vec ;
24+ use spin:: Once ;
2325
24- use crate :: fs:: inode:: { FileType , INodeInterface , Metadata } ;
26+ use crate :: fs:: cache:: DirCacheItem ;
27+ use crate :: fs:: file_table:: FileHandle ;
28+ use crate :: fs:: inode:: { FileType , INodeInterface , Metadata , PollFlags } ;
2529use crate :: fs:: { self , FileSystemError } ;
2630use crate :: net:: ip:: Ipv4Addr ;
2731use crate :: net:: udp:: { self , Udp , UdpHandler } ;
2832use crate :: net:: { Packet , PacketHeader , PacketTrait } ;
29- use crate :: utils:: sync:: Mutex ;
33+ use crate :: utils:: sync:: { BlockQueue , Mutex } ;
3034
3135#[ derive( Default ) ]
3236enum SocketState {
@@ -41,22 +45,32 @@ struct InetSocketInner {
4145 /// The address that the socket has been bound to.
4246 address : Option < SocketAddrInet > ,
4347 state : SocketState ,
48+ incoming : Vec < Packet < Udp > > ,
4449}
4550
4651pub struct InetSocket {
4752 typ : SocketType ,
4853 protocol : IpProtocol ,
4954 inner : Mutex < InetSocketInner > ,
55+ wq : BlockQueue ,
56+ handle : Once < Arc < FileHandle > > ,
5057
5158 sref : Weak < Self > ,
5259}
5360
5461impl InetSocket {
5562 pub fn new ( typ : SocketType , protocol : IpProtocol ) -> Result < Arc < Self > , SyscallError > {
63+ if typ != SocketType :: Dgram && protocol != IpProtocol :: Udp {
64+ return Err ( SyscallError :: EINVAL ) ;
65+ }
66+
5667 Ok ( Arc :: new_cyclic ( |sref| Self {
5768 typ,
5869 protocol,
5970
71+ wq : BlockQueue :: new ( ) ,
72+ handle : Once :: new ( ) ,
73+
6074 inner : Mutex :: new ( Default :: default ( ) ) ,
6175 sref : sref. clone ( ) ,
6276 } ) )
@@ -88,9 +102,27 @@ impl InetSocket {
88102 _ => unreachable ! ( ) ,
89103 }
90104 }
105+
106+ pub fn is_non_block ( & self ) -> bool {
107+ self . handle
108+ . get ( )
109+ . expect ( "inet: not bound to an fd" )
110+ . flags
111+ . read ( )
112+ . contains ( OpenFlags :: O_NONBLOCK )
113+ }
91114}
92115
93116impl INodeInterface for InetSocket {
117+ fn open (
118+ & self ,
119+ _flags : aero_syscall:: OpenFlags ,
120+ handle : Arc < FileHandle > ,
121+ ) -> fs:: Result < Option < DirCacheItem > > {
122+ self . handle . call_once ( || handle) ;
123+ Ok ( None )
124+ }
125+
94126 fn metadata ( & self ) -> fs:: Result < fs:: inode:: Metadata > {
95127 Ok ( Metadata {
96128 id : 0 ,
@@ -130,7 +162,7 @@ impl INodeInterface for InetSocket {
130162 }
131163 }
132164
133- fn send ( & self , message_hdr : & mut aero_syscall :: socket :: MessageHeader ) -> fs:: Result < usize > {
165+ fn send ( & self , message_hdr : & mut MessageHeader ) -> fs:: Result < usize > {
134166 let name = message_hdr
135167 . name_mut :: < SocketAddrInet > ( )
136168 . cloned ( )
@@ -139,9 +171,17 @@ impl INodeInterface for InetSocket {
139171 let dest_port = name. port . to_native ( ) ;
140172 let dest_ip = Ipv4Addr :: new ( name. addr ( ) ) ;
141173
142- let src_port = self . src_port ( ) . unwrap_or_else ( || {
143- udp:: alloc_ephemeral_port ( self . sref ( ) ) . expect ( "inet: out of ephemeral ports" )
144- } ) ;
174+ let src_port;
175+
176+ if let Some ( port) = self . src_port ( ) {
177+ src_port = port;
178+ } else {
179+ src_port = udp:: alloc_ephemeral_port ( self . sref ( ) ) . ok_or ( FileSystemError :: WouldBlock ) ?;
180+ log:: debug!( "Inet::send(): allocated ephemeral port {}" , src_port) ;
181+
182+ // FIXME: handle ephemeral port INET socket
183+ return Err ( FileSystemError :: NotSupported ) ;
184+ }
145185
146186 let data = message_hdr
147187 . iovecs ( )
@@ -159,6 +199,41 @@ impl INodeInterface for InetSocket {
159199 packet. send ( ) ;
160200 Ok ( data. len ( ) )
161201 }
202+
203+ fn recv ( & self , message_hdr : & mut MessageHeader ) -> fs:: Result < usize > {
204+ if self . inner . lock_irq ( ) . incoming . is_empty ( ) && self . is_non_block ( ) {
205+ return Err ( FileSystemError :: WouldBlock ) ;
206+ }
207+
208+ let mut this = self . wq . block_on ( & self . inner , |e| !e. incoming . is_empty ( ) ) ?;
209+ let packet = this. incoming . pop ( ) . expect ( "recv: someone was greedy" ) ;
210+
211+ let mut data = packet. as_slice ( ) . to_vec ( ) ;
212+
213+ Ok ( message_hdr
214+ . iovecs_mut ( )
215+ . iter_mut ( )
216+ . map ( |iovec| {
217+ let iovec = iovec. as_slice_mut ( ) ;
218+ let size = core:: cmp:: min ( iovec. len ( ) , data. len ( ) ) ;
219+ iovec. copy_from_slice ( & data. drain ( ..size) . collect :: < Vec < _ > > ( ) ) ;
220+ size
221+ } )
222+ . sum :: < usize > ( ) )
223+ }
224+
225+ fn poll ( & self , table : Option < & mut fs:: inode:: PollTable > ) -> fs:: Result < PollFlags > {
226+ if let Some ( table) = table {
227+ table. insert ( & self . wq ) ;
228+ }
229+
230+ Ok ( PollFlags :: OUT )
231+ }
162232}
163233
164- impl UdpHandler for InetSocket { }
234+ impl UdpHandler for InetSocket {
235+ fn recv ( & self , packet : Packet < Udp > ) {
236+ self . inner . lock_irq ( ) . incoming . push ( packet) ;
237+ self . wq . notify_complete ( ) ;
238+ }
239+ }
0 commit comments