module OverSIP::SIP class TlsTunnelReactor < TcpReactor # Max size (bytes) of the buffered data when receiving message headers # (avoid DoS attacks). HEADERS_MAX_SIZE = 16384 def receive_data data @state == :ignore and return @buffer << data while (case @state when :init @parser.reset @parser_nbytes = 0 # If it's a TCP connection from the TLS tunnel then parse the HAProxy Protocol line # if it's not yet done. unless @haproxy_protocol_parsed @state = :haproxy_protocol else @state = :headers end when :haproxy_protocol parse_haproxy_protocol when :client_pems parse_client_pems when :headers parse_headers when :body get_body when :finished # Invoke the custom logic for requests. if @msg.request? process_request else process_response end # Set state to :init. @state = :init # Return true to continue processing possible remaining data. true when :ignore false end) end # while end def parse_haproxy_protocol if (haproxy_protocol_data = ::OverSIP::Utils.parse_haproxy_protocol(@buffer.to_str)) @haproxy_protocol_parsed = true # Update connection information. @remote_ip_type = haproxy_protocol_data[1] @remote_ip = haproxy_protocol_data[2] @remote_port = haproxy_protocol_data[3] # Add the connection with the client's source data. Note that we pass a TlsServer as class, but # the server instance is a TcpServer. @connection_id = case @remote_ip_type when :ipv4 ::OverSIP::SIP::TransportManager.add_connection self, ::OverSIP::SIP::IPv4TlsServer, :ipv4, @remote_ip, @remote_port when :ipv6 ::OverSIP::SIP::TransportManager.add_connection self, ::OverSIP::SIP::IPv6TlsServer, :ipv6, @remote_ip, @remote_port end # Update log information. remote_desc true # Remove the HAProxy Protocol line from the received data. @buffer.read haproxy_protocol_data[0] @state = :headers else log_system_error "HAProxy Protocol parsing error, closing connection" close_connection_after_writing @state = :ignore return false end end # TODO: Not terminated yet. def parse_client_pems # TODO: Wrong, it could occur that here the last PEMs byte arries. return false if @buffer.size < 3 # 3 bytes = 0\r\n (minimum data). @pems_str ||= "" @pems_str << @buffer.read(2) # No PEMS. if @pems_str == "\r\n" @state = :headers return true end #@pem_size_str = @state = :headers end end end