/* Remote notification in GDB protocol

   Copyright (C) 1988-2021 Free Software Foundation, Inc.

   This file is part of GDB.

   This program is free software; you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
   the Free Software Foundation; either version 3 of the License, or
   (at your option) any later version.

   This program is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   GNU General Public License for more details.

   You should have received a copy of the GNU General Public License
   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */

/* Remote async notification is sent from remote target over RSP.
   Each type of notification is represented by an object of
   'struct notif', which has a field 'pending_reply'.  It is not
   NULL when GDB receives a notification from GDBserver, but hasn't
   acknowledge yet.  Before GDB acknowledges the notification,
   GDBserver shouldn't send notification again (see the header comments
   in gdbserver/notif.c).

   Notifications are processed in an almost-unified approach for both
   all-stop mode and non-stop mode, except the timing to process them.
   In non-stop mode, notifications are processed in
   remote_async_get_pending_events_handler, while in all-stop mode,
   they are processed in remote_resume.  */

#include "defs.h"
#include "remote.h"
#include "remote-notif.h"
#include "observable.h"
#include "gdbsupport/event-loop.h"
#include "target.h"
#include "inferior.h"
#include "infrun.h"
#include "gdbcmd.h"
#include "async-event.h"

bool notif_debug = false;

/* Supported clients of notifications.  */

static struct notif_client *notifs[] =
{
  &notif_client_stop,
};

gdb_static_assert (ARRAY_SIZE (notifs) == REMOTE_NOTIF_LAST);

/* Parse the BUF for the expected notification NC, and send packet to
   acknowledge.  */

void
remote_notif_ack (remote_target *remote,
		  struct notif_client *nc, const char *buf)
{
  notif_event_up event = nc->alloc_event ();

  if (notif_debug)
    fprintf_unfiltered (gdb_stdlog, "notif: ack '%s'\n",
			nc->ack_command);

  nc->parse (remote, nc, buf, event.get ());
  nc->ack (remote, nc, buf, event.release ());
}

/* Parse the BUF for the expected notification NC.  */

struct notif_event *
remote_notif_parse (remote_target *remote,
		    struct notif_client *nc, const char *buf)
{
  notif_event_up event = nc->alloc_event ();

  if (notif_debug)
    fprintf_unfiltered (gdb_stdlog, "notif: parse '%s'\n", nc->name);

  nc->parse (remote, nc, buf, event.get ());

  return event.release ();
}

/* Process notifications in STATE's notification queue one by one.
   EXCEPT is not expected in the queue.  */

void
remote_notif_process (struct remote_notif_state *state,
		      struct notif_client *except)
{
  while (!state->notif_queue.empty ())
    {
      struct notif_client *nc = state->notif_queue.front ();
      state->notif_queue.pop_front ();

      gdb_assert (nc != except);

      if (nc->can_get_pending_events (state->remote, nc))
	remote_notif_get_pending_events (state->remote, nc);
    }
}

static void
remote_async_get_pending_events_handler (gdb_client_data data)
{
  remote_notif_state *notif_state = (remote_notif_state *) data;
  clear_async_event_handler (notif_state->get_pending_events_token);
  gdb_assert (remote_target_is_non_stop_p (notif_state->remote));
  remote_notif_process (notif_state, NULL);
}

/* Remote notification handler.  Parse BUF, queue notification and
   update STATE.  */

void
handle_notification (struct remote_notif_state *state, const char *buf)
{
  struct notif_client *nc;
  size_t i;

  for (i = 0; i < ARRAY_SIZE (notifs); i++)
    {
      const char *name = notifs[i]->name;

      if (startswith (buf, name)
	  && buf[strlen (name)] == ':')
	break;
    }

  /* We ignore notifications we don't recognize, for compatibility
     with newer stubs.  */
  if (i == ARRAY_SIZE (notifs))
    return;

  nc =  notifs[i];

  if (state->pending_event[nc->id] != NULL)
    {
      /* We've already parsed the in-flight reply, but the stub for some
	 reason thought we didn't, possibly due to timeout on its side.
	 Just ignore it.  */
      if (notif_debug)
	fprintf_unfiltered (gdb_stdlog,
			    "notif: ignoring resent notification\n");
    }
  else
    {
      struct notif_event *event
	= remote_notif_parse (state->remote, nc, buf + strlen (nc->name) + 1);

      /* Be careful to only set it after parsing, since an error
	 may be thrown then.  */
      state->pending_event[nc->id] = event;

      /* Notify the event loop there's a stop reply to acknowledge
	 and that there may be more events to fetch.  */
      state->notif_queue.push_back (nc);
      if (target_is_non_stop_p ())
	{
	  /* In non-stop, We mark REMOTE_ASYNC_GET_PENDING_EVENTS_TOKEN
	     in order to go on what we were doing and postpone
	     querying notification events to some point safe to do so.
	     See details in the function comment of
	     remote.c:remote_notif_get_pending_events.

	     In all-stop, GDB may be blocked to wait for the reply, we
	     shouldn't return to event loop until the expected reply
	     arrives.  For example:

	     1.1) --> vCont;c
	       GDB expects getting stop reply 'T05 thread:2'.
	     1.2) <-- %Notif
	       <GDB marks the REMOTE_ASYNC_GET_PENDING_EVENTS_TOKEN>

	     After step #1.2, we return to the event loop, which
	     notices there is a new event on the
	     REMOTE_ASYNC_GET_PENDING_EVENTS_TOKEN and calls the
	     handler, which will send 'vNotif' packet.
	     1.3) --> vNotif
	     It is not safe to start a new sequence, because target
	     is still running and GDB is expecting the stop reply
	     from stub.

	     To solve this, whenever we parse a notification
	     successfully, we don't mark the
	     REMOTE_ASYNC_GET_PENDING_EVENTS_TOKEN and let GDB blocked
	     there as before to get the sequence done.

	     2.1) --> vCont;c
	       GDB expects getting stop reply 'T05 thread:2'
	     2.2) <-- %Notif
	       <Don't mark the REMOTE_ASYNC_GET_PENDING_EVENTS_TOKEN>
	     2.3) <-- T05 thread:2

	     These pending notifications can be processed later.  */
	  mark_async_event_handler (state->get_pending_events_token);
	}

      if (notif_debug)
	fprintf_unfiltered (gdb_stdlog,
			    "notif: Notification '%s' captured\n",
			    nc->name);
    }
}

/* Return an allocated remote_notif_state.  */

struct remote_notif_state *
remote_notif_state_allocate (remote_target *remote)
{
  struct remote_notif_state *notif_state = new struct remote_notif_state;

  notif_state->remote = remote;

  /* Register async_event_handler for notification.  */

  notif_state->get_pending_events_token
    = create_async_event_handler (remote_async_get_pending_events_handler,
				  notif_state, "remote-notif");

  return notif_state;
}

/* Free STATE and its fields.  */

remote_notif_state::~remote_notif_state ()
{
  int i;

  /* Unregister async_event_handler for notification.  */
  if (get_pending_events_token != NULL)
    delete_async_event_handler (&get_pending_events_token);

  for (i = 0; i < REMOTE_NOTIF_LAST; i++)
    delete pending_event[i];
}

void _initialize_notif ();
void
_initialize_notif ()
{
  add_setshow_boolean_cmd ("notification", no_class, &notif_debug,
			   _("\
Set debugging of async remote notification."), _("\
Show debugging of async remote notification."), _("\
When non-zero, debugging output about async remote notifications"
" is enabled."),
			   NULL,
			   NULL,
			   &setdebuglist, &showdebuglist);
}
