mirror of
				https://github.com/RGBCube/serenity
				synced 2025-10-31 17:52:45 +00:00 
			
		
		
		
	LocalSocket: Teach recvfrom() how to block if needed, and simplify it
If we can't already read when we enter recvfrom() on a LocalSocket, we'll now block the current thread until we can. Also added a buffer_for(FileDescription&) helper so that the client and server can share some of the code. :^)
This commit is contained in:
		
							parent
							
								
									34d0e96aec
								
							
						
					
					
						commit
						65409e8f04
					
				
					 2 changed files with 26 additions and 23 deletions
				
			
		|  | @ -229,34 +229,36 @@ ssize_t LocalSocket::sendto(FileDescription& description, const void* data, size | |||
|     ASSERT_NOT_REACHED(); | ||||
| } | ||||
| 
 | ||||
| ssize_t LocalSocket::recvfrom(FileDescription& description, void* buffer, size_t buffer_size, int, sockaddr*, socklen_t*) | ||||
| DoubleBuffer& LocalSocket::buffer_for(FileDescription& description) | ||||
| { | ||||
|     auto role = this->role(description); | ||||
|     if (role == Role::Accepted) { | ||||
|         if (!description.is_blocking()) { | ||||
|             if (m_for_server.is_empty()) { | ||||
|                 if (!has_attached_peer(description)) | ||||
|                     return 0; | ||||
|                 return -EAGAIN; | ||||
|             } | ||||
|         } | ||||
|         ASSERT(!m_for_server.is_empty()); | ||||
|         return m_for_server.read((u8*)buffer, buffer_size); | ||||
|     } | ||||
|     if (role == Role::Connected) { | ||||
|         if (!description.is_blocking()) { | ||||
|             if (m_for_client.is_empty()) { | ||||
|                 if (!has_attached_peer(description)) | ||||
|                     return 0; | ||||
|                 return -EAGAIN; | ||||
|             } | ||||
|         } | ||||
|         ASSERT(!m_for_client.is_empty()); | ||||
|         return m_for_client.read((u8*)buffer, buffer_size); | ||||
|     } | ||||
|     if (role == Role::Accepted) | ||||
|         return m_for_server; | ||||
|     if (role == Role::Connected) | ||||
|         return m_for_client; | ||||
|     ASSERT_NOT_REACHED(); | ||||
| } | ||||
| 
 | ||||
| ssize_t LocalSocket::recvfrom(FileDescription& description, void* buffer, size_t buffer_size, int, sockaddr*, socklen_t*) | ||||
| { | ||||
|     auto& buffer_for_me = buffer_for(description); | ||||
|     if (!description.is_blocking()) { | ||||
|         if (buffer_for_me.is_empty()) { | ||||
|             if (!has_attached_peer(description)) | ||||
|                 return 0; | ||||
|             return -EAGAIN; | ||||
|         } | ||||
|     } else if (!can_read(description)) { | ||||
|         auto result = current->block<Thread::ReceiveBlocker>(description); | ||||
|         if (result == Thread::BlockResult::InterruptedBySignal) | ||||
|             return -EINTR; | ||||
|     } | ||||
|     if (!has_attached_peer(description) && buffer_for_me.is_empty()) | ||||
|         return 0; | ||||
|     ASSERT(!buffer_for_me.is_empty()); | ||||
|     return buffer_for_me.read((u8*)buffer, buffer_size); | ||||
| } | ||||
| 
 | ||||
| StringView LocalSocket::socket_path() const | ||||
| { | ||||
|     int len = strnlen(m_address.sun_path, sizeof(m_address.sun_path)); | ||||
|  |  | |||
|  | @ -36,6 +36,7 @@ private: | |||
|     virtual bool is_local() const override { return true; } | ||||
|     bool has_attached_peer(const FileDescription&) const; | ||||
|     static Lockable<InlineLinkedList<LocalSocket>>& all_sockets(); | ||||
|     DoubleBuffer& buffer_for(FileDescription&); | ||||
| 
 | ||||
|     // An open socket file on the filesystem.
 | ||||
|     RefPtr<FileDescription> m_file; | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 Andreas Kling
						Andreas Kling