note description: "Summary description for {HTTP_STREAM_SOCKET}." date: "$Date$" revision: "$Revision$" class HTTP_STREAM_SOCKET inherit NETWORK_STREAM_SOCKET create make, make_empty, make_client_by_port, make_client_by_address_and_port, make_server_by_port, make_server_by_address_and_port, make_loopback_server_by_port create {NETWORK_STREAM_SOCKET} make_from_descriptor_and_address feature -- Status report is_secure_connection_supported: BOOLEAN -- SSL/TLS supported? once Result := False ensure Result = {HTTP_SECURE_HELPER}.is_secure_connection_supported end feature -- Input read_character_noexception -- Read a new character. -- Make result available in `last_character'. -- No exception raised! do read_to_managed_pointer_noexception (read_socket_buffer, 0, character_8_bytes) if was_error then -- Socket error already set. elseif bytes_read /= character_8_bytes then socket_error := "Peer closed connection" else last_character := read_socket_buffer.read_character (0) socket_error := Void end end read_stream_noexception (nb_char: INTEGER) -- Read a string of at most `nb_char' characters. -- Make result available in `last_string'. local ext: C_STRING return_val: INTEGER do create ext.make_empty (nb_char + 1) return_val := c_read_stream_noexception (descriptor, nb_char, ext.item) bytes_read := return_val if return_val >= 0 then ext.set_count (return_val) last_string := ext.substring (1, return_val) else socket_error := "Peer error [0x" + return_val.to_hex_string + "]" last_string.wipe_out end end read_to_managed_pointer_noexception (p: MANAGED_POINTER; start_pos, nb_bytes: INTEGER) -- Read at most `nb_bytes' bound bytes and make result -- available in `p' at position `start_pos'. -- No exception raised! do read_into_pointer_noexception (p.item, start_pos, nb_bytes) end read_line_noexception -- Read a line of characters (ended by a new_line). -- No exception raised! local l_last_string: like last_string do create l_last_string.make (512) read_character_noexception from until last_character = '%N' or else was_error loop l_last_string.extend (last_character) read_character_noexception end last_string := l_last_string end peek_stream_noexception (nb_char: INTEGER) -- Read a string of at most `nb_char' characters without removing the data from the queue. -- Make result available in last_string. -- No exception raised! require readable: readable socket_exists: exists local ext: C_STRING retval: INTEGER l: like last_string do create ext.make_empty (nb_char + 1) retval := c_recv_noexception (descriptor, ext.item, nb_char, c_peekmsg) if retval = 0 then last_string.wipe_out socket_error := Void elseif retval > 0 then ext.set_count (retval) l := last_string l.wipe_out l.grow (retval) l.set_count (retval) ext.read_substring_into (l, 1, retval) socket_error := Void else last_string.wipe_out socket_error := "Socket error (MSG_PEEK)" end ensure last_string_not_void: last_string /= Void end feature {NONE} -- Input read_into_pointer_noexception (p: POINTER; start_pos, nb_bytes: INTEGER_32) -- Read at most `nb_bytes' bound bytes and make result -- available in `p' at position `start_pos'. -- No exception raised! require p_not_void: p /= default_pointer nb_bytes_non_negative: nb_bytes >= 0 is_readable: readable local l_read: INTEGER_32 l_last_read: INTEGER_32 do from l_last_read := 1 until l_read = nb_bytes or l_last_read <= 0 loop l_last_read := c_read_stream_noexception (descriptor, nb_bytes - l_read, p + start_pos + l_read) if l_last_read >= 0 then l_read := l_read + l_last_read else socket_error := "Network error!" end end bytes_read := l_read ensure bytes_read_updated: 0 <= bytes_read and bytes_read <= nb_bytes end feature -- Output bytes_sent: INTEGER -- Last number of bytes sent by `put_managed_pointer_noexception' (i.e `put_pointer_content_noexception'). put_managed_pointer_noexception (p: MANAGED_POINTER; start_pos, nb_bytes: INTEGER_32) -- Put data of length `nb_bytes' pointed by `start_pos' index in `p' at -- current position. -- Update `bytes_sent'. -- No exception raised! require p_not_void: p /= Void p_large_enough: p.count >= nb_bytes + start_pos nb_bytes_non_negative: nb_bytes >= 0 extendible: extendible do put_pointer_content_noexception (p.item, start_pos, nb_bytes) end put_pointer_content_noexception (a_pointer: POINTER; a_offset, a_byte_count: INTEGER) -- Write `a_byte_count' bytes to the socket. -- The data is taken from the memory area pointed to by `a_pointer', at offset `a_offset'. -- Update `bytes_sent'. -- No exception raised! require pointer_not_void: a_pointer /= default_pointer byte_count_non_negative: a_byte_count >= 0 extendible: extendible local l_sent: INTEGER_32 l_last_sent: INTEGER_32 do from l_last_sent := 1 until l_sent = a_byte_count or l_last_sent <= 0 loop l_last_sent := c_put_stream_noexception (descriptor, a_pointer + a_offset + l_sent, a_byte_count - l_sent) if l_last_sent >= 0 then l_sent := l_sent + l_last_sent elseif l_sent < a_byte_count then socket_error := "No all bytes sent!" end end bytes_sent := l_sent ensure bytes_sent_updated: not was_error implies (0 <= bytes_sent and bytes_sent <= a_byte_count) end put_character_noexception (c: CHARACTER) -- Write character `c' to socket. do put_socket_buffer.put_character (c, 0) put_managed_pointer_noexception (put_socket_buffer, 0, character_8_bytes) end put_string_8_noexception (s: READABLE_STRING_8) -- Write readable string `s' to socket. -- No exception raised! local ext: C_STRING do create ext.make (s) put_managed_pointer_noexception (ext.managed_data, 0, s.count) end put_readable_string_8 (s: READABLE_STRING_8) -- Write readable string `s' to socket. local ext: C_STRING do create ext.make (s) put_managed_pointer (ext.managed_data, 0, s.count) end feature -- Status report has_incoming_data: BOOLEAN -- Check if Current has available data to be read. -- note: no data will not be removed from the queue. require socket_exists: exists do peek_stream_noexception (1) Result := last_string.count = 1 end note copyright: "2011-2017, Jocelyn Fiat, Javier Velilla, Olivier Ligot, Colin Adams, Eiffel Software and others" license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)" source: "[ Eiffel Software 5949 Hollister Ave., Goleta, CA 93117 USA Telephone 805-685-1006, Fax 805-685-6869 Website http://www.eiffel.com Customer support http://support.eiffel.com ]" end