コード例 #1
0
static int ioctl_delete(ITF *itf,uint32_t ip,int flags)
{
    ENTRY *entry,*walk,*next;

    if (!(entry = lookup_ip(itf,ip))) {
	diag(COMPONENT,DIAG_WARN,"ioctl_delete didn't find entry");
	return -ENOENT;
    }
    if ((flags ^ entry->flags) & ATF_ARPSRV) return -EINVAL;
    send_notifications(entry,0);
    if ((entry->flags & ATF_ARPSRV) && entry->itf)
	for (walk = entry->itf->table; walk; walk = next) {
	    next = walk->next;
	    if (walk != entry && walk->state == as_resolv) {
		send_notifications(walk,0);
		if (!walk->vccs && !(walk->flags & ATF_PERM))
		   /* PERM is rather unlikely here, since this would be a
		      second ARP server (only ARP servers can go as_resolv if
		      PERM), but we'll check for it anyway. */
		    discard_entry(walk);
		else {
		    STOP_TIMER(walk);
		    walk->state = as_invalid;
		}
	    }
	}
    discard_entry(entry);
    return 0;
}
コード例 #2
0
void
Event_Handler::run (void)
{
  send_notifications ();

  // Run for 30 seconds or until the test is done.
  for(int i = 0; i != 30 && !done(); ++i)
  {
    ACE_Time_Value tv (1,0);
    reactor ()->run_reactor_event_loop(tv);
  }

  if(!done())
  {
    ACE_ERROR ((LM_ERROR,
               ACE_TEXT ("Test %C failed due to timeout ")
               ACE_TEXT (" sent=%d,recv=%d\n"),
               test_name_,
               notifications_sent_,
               notifications_recv_));
  }
  else
  {
    ACE_DEBUG ((LM_INFO,
                ACE_TEXT ("Test %C passed sent=%d, recv=%d\n"),
                test_name_,
                notifications_sent_,
                notifications_recv_));
  }
}
コード例 #3
0
static void timeout(ENTRY *entry)
{
    VCC *vcc,*next;

    entry->timer = NULL;
    switch (entry->state) {
	case as_resolv:
	    send_notifications(entry,0);
	    if ((entry->flags & ATF_ARPSRV) && !entry->vccs) {
		if (entry->itf) want_arp_srv(entry->itf);
		break;
	    }
	    if (!entry->vccs && !(entry->flags & (ATF_PERM | ATF_ARPSRV)))
		discard_entry(entry);
	    else entry->state = as_invalid;
	    break;
	case as_valid:
	    if (!entry->vccs && !(entry->flags & (ATF_PERM | ATF_ARPSRV)) &&
	      entry->itf->arp_srv) {
		discard_entry(entry);
		break;
	    }
	    for (vcc = entry->vccs; vcc; vcc = next) {
		next = vcc->next;
		if (!vcc->connecting)
		    if (set_ip(vcc->fd,0) < 0) {
			diag(COMPONENT,DIAG_ERROR,"set_ip(0): %s",
			  strerror(errno));
			disconnect_vcc(vcc);
		    }
	    }
	    if (entry->svc && entry->itf->arp_srv &&
	      !(entry->flags & ATF_ARPSRV)) revalidate(entry);
	    else {
		inarp_request(entry);
		START_TIMER(entry,REPLY);
		entry->state = as_invalid;
	    }
	    break;
	case as_invalid:
	    if (!entry->svc) {
		inarp_request(entry);
		START_TIMER(entry,REPLY);
	    }
	    else if ((!entry->itf || !entry->itf->arp_srv) &&
		  !(entry->flags & ATF_PERM)) discard_entry(entry);
	    break;
	default:
	    diag(COMPONENT,DIAG_FATAL,"timed out in state %s",
	      entry_state_name[entry->state]);
    }
}
コード例 #4
0
static void learn_nak(uint32_t ip)
{
    ITF *itf;
    ENTRY *entry;

    if (!ip) return;
    itf = lookup_itf_by_ip(ip);
    if (!itf) return;
    entry = lookup_ip(itf,ip);
    if (!entry || entry->state != as_resolv) return;
    send_notifications(entry,0);
    if (entry->flags & ATF_PERM) return;
    if (entry->vccs) entry->state = as_invalid;
    else discard_entry(entry);
}
コード例 #5
0
int
Event_Handler::handle_exception (ACE_HANDLE)
{
  ++notifications_recv_;
  if(notifications_recv_ == notifications_sent_)
  {
    if(notifications_curr_ >= max_notifications_)
    {

      return 0;
    }
    send_notifications();
  }
  return 0;
}
コード例 #6
0
ファイル: w32notify.c プロジェクト: maxgfaraday/emacs
/* A completion routine (a.k.a. "APC function") for handling events
   read by ReadDirectoryChangesW.  Called by the OS when the thread
   which issued the asynchronous ReadDirectoryChangesW call is in the
   "alertable state", i.e. waiting inside SleepEx call.  */
VOID CALLBACK
watch_completion (DWORD status, DWORD bytes_ret, OVERLAPPED *io_info)
{
  struct notification *dirwatch;

  /* Who knows what happened?  Perhaps the OVERLAPPED structure was
     freed by someone already?  In any case, we cannot do anything
     with this request, so just punt and skip it.  FIXME: should we
     raise the 'terminate' flag in this case?  */
  if (!io_info)
    return;

  /* We have a pointer to our dirwatch structure conveniently stashed
     away in the hEvent member of the OVERLAPPED struct.  According to
     MSDN documentation of ReadDirectoryChangesW: "The hEvent member
     of the OVERLAPPED structure is not used by the system, so you can
     use it yourself."  */
  dirwatch = (struct notification *)io_info->hEvent;
  if (status == ERROR_OPERATION_ABORTED)
    {
      /* We've been called because the main thread told us to issue
	 CancelIo on the directory we watch, and watch_end did so.
	 The directory handle is already closed.  We should clean up
	 and exit, signaling to the thread worker routine not to
	 issue another call to ReadDirectoryChangesW.  Note that we
	 don't free the dirwatch object itself nor the memory consumed
	 by its buffers; this is done by the main thread in
	 remove_watch.  Calling malloc/free from a thread other than
	 the main thread is a no-no.  */
      dirwatch->dir = NULL;
      dirwatch->terminate = 1;
    }
  else
    {
      /* Tell the main thread we have notifications for it.  */
      send_notifications (dirwatch->buf, bytes_ret, dirwatch,
			  &dirwatch->terminate);
    }
}
コード例 #7
0
int
Driver::run_one_iteration (void)
{
  ACE_DEBUG ((LM_INFO,
              ACE_TEXT ("Running iteration with %d events for %C test\n"),
              notifications_curr_,
              test_name_));

  send_notifications ();

  // Run for 30 seconds or until the test is done.

  ACE_Time_Value const timeout(30,0);

  while (!current_iteration_done())
  {
    ACE_Time_Value start = ACE_OS::gettimeofday();
    ACE_Time_Value interval(1,0);
    reactor()->run_reactor_event_loop(interval);
    ACE_Time_Value end = ACE_OS::gettimeofday();

    if (end - start >= timeout)
      {
        ACE_ERROR ((LM_ERROR,
                    ACE_TEXT ("Test %C failed due to timeout ")
                    ACE_TEXT (" sent=%d,recv=%d,skip=%d\n"),
                    test_name_,
                    notifications_sent_,
                    notifications_recv_,
                    notifications_skipped_));
        return -1;
      }
  }

  return 0;
}
コード例 #8
0
ファイル: w32notify.c プロジェクト: Ferryworld/emacs
VOID CALLBACK
watch_completion (DWORD status, DWORD bytes_ret, OVERLAPPED *io_info)
{
  struct notification *dirwatch;
  DWORD _bytes;
  struct notifications_set *ns = NULL;
  BOOL terminate = FALSE;

  /* Who knows what happened?  Perhaps the OVERLAPPED structure was
     freed by someone already?  In any case, we cannot do anything
     with this request, so just punt and skip it.  FIXME: should we
     raise the 'terminate' flag in this case?  */
  if (!io_info)
    {
      DebPrint(("watch_completion: io_info is null.\n"));
      return;
    }

  /* We have a pointer to our dirwatch structure conveniently stashed
     away in the hEvent member of the OVERLAPPED struct.  According to
     MSDN documentation of ReadDirectoryChangesW: "The hEvent member
     of the OVERLAPPED structure is not used by the system, so you can
     use it yourself."  */
  dirwatch = (struct notification *)io_info->hEvent;

  if (status == ERROR_OPERATION_ABORTED)
    {
      /* We've been called because the main thread told us to issue
	 CancelIo on the directory we watch, and watch_end did so.
         We must exit, without issuing another call to
         ReadDirectoryChangesW. */
      return;
    }

  /* We allocate a new set of notifications to be linked to the linked
     list of notifications set.  This will be processed by Emacs event
     loop in the main thread.  We need to duplicate the notifications
     buffer, but not the dirwatch structure.  */

  /* Implementation note: In general, allocating memory in non-main
     threads is a no-no in Emacs.  We certainly cannot call xmalloc
     and friends, because it can longjmp when allocation fails, which
     will crash Emacs because the jmp_buf is set up to a location on
     the main thread's stack.  However, we can call 'malloc' directly,
     since that is redirected to HeapAlloc that uses our private heap,
     see w32heap.c, and that is thread-safe.  */
  ns = malloc (sizeof(struct notifications_set));
  if (ns)
    {
      memset (ns, 0, sizeof(struct notifications_set));
      ns->notifications = malloc (bytes_ret);
      if (ns->notifications)
	{
	  memcpy (ns->notifications, dirwatch->buf, bytes_ret);
	  ns->size = bytes_ret;
	  ns->desc = dirwatch;
	}
      else
	{
	  free (ns);
	  ns = NULL;
	}
    }
  if (ns == NULL)
    DebPrint(("Out of memory.  Notifications lost."));

  /* Calling ReadDirectoryChangesW quickly to watch again for new
     notifications.  */
  if (!ReadDirectoryChangesW (dirwatch->dir, dirwatch->buf,
			      DIRWATCH_BUFFER_SIZE, dirwatch->subtree,
			      dirwatch->filter, &_bytes, dirwatch->io_info,
			      watch_completion))
    {
      DebPrint (("ReadDirectoryChangesW error: %lu\n", GetLastError ()));
      /* If this call fails, it means that the directory is not
         watchable any more.  We need to terminate the worker thread.
         Still, we will wait until the current notifications have been
         sent to the main thread.  */
      terminate = TRUE;
    }

  if (ns)
    send_notifications(ns);

  /* If we were asked to terminate the thread, then fire the event. */
  if (terminate)
    SetEvent(dirwatch->terminate);
}
コード例 #9
0
static int learn(VCC *vcc,uint32_t ip,struct sockaddr_atmsvc *addr)
{
    ENTRY *entry;
    ITF *itf;
    VCC *walk,*next;
    unsigned char *ipp;
    int result = 0;

    if (!ip) return 0;
    ipp = (unsigned char *) &ip;
    itf = lookup_itf_by_ip(ip);
    if (!itf) {
	diag(COMPONENT,DIAG_ERROR,"got unroutable IP address %d.%d.%d.%d",
	  ipp[0],ipp[1],ipp[2],ipp[3]);
	return 0;
    }
    entry = lookup_ip(itf,ip);
    assert(!vcc || vcc->entry);
    /*
     * If the entry on which we received the update isn't dangling but it
     * doesn't correspond to the one with the address, ...
     */
    if (entry && vcc && vcc->entry->itf && entry != vcc->entry) {
	diag(COMPONENT,DIAG_DEBUG,"collision on %d.%d.%d.%d",ipp[0],ipp[1],
	  ipp[2],ipp[3]);
	return 0;
    }
    /*
     * If the entry on which we received the update is dangling and we found
     * an entry that already describes that IP address, ...
     */
    if (entry && vcc && !vcc->entry->itf) {
	if (!entry->svc) {
	    diag(COMPONENT,DIAG_ERROR,"attempt to overwrite PVC for IP "
	      "%d.%d.%d.%d",ipp[0],ipp[1],ipp[2],ipp[3]);
	    return 0;
	}
	STOP_TIMER(vcc->entry);
	Q_REMOVE(unknown_incoming,vcc->entry);
	free(vcc->entry);
	vcc->entry = entry;
	Q_INSERT_HEAD(entry->vccs,vcc);
	set_sndbuf(vcc);
	entry->flags &= ~ATF_NOVC;
	assert(!vcc->connecting);
	if (set_ip(vcc->fd,ip) < 0) {
	    diag(COMPONENT,DIAG_ERROR,"set_ip: %s",strerror(errno));
	    disconnect_vcc(vcc);
	    vcc = NULL;
	    result = -1;
	}
    }
    /*
     * If we still don't have an entry, we try to use the entry that already
     * belongs to the VCC (InARP), or we create a new one (ARP).
     */
    if (!entry) {
	if (vcc) {
	    entry = vcc->entry;
	    if (!entry->itf) {
		Q_REMOVE(unknown_incoming,entry);
		entry->sndbuf = itf->sndbuf;
		set_sndbuf(vcc);
	    }
	    else if (entry->ip && entry->ip != ip && (entry->flags & ATF_PERM)
		  && !(entry->flags & ATF_ARPSRV)) {
		    diag(COMPONENT,DIAG_ERROR,"ignoring attempt to change IP "
		      "address of permanent entry (to %d.%d.%d.%d)",ipp[0],
		      ipp[1],ipp[2],ipp[3]);
		    return result;
		}
	}
	else {
	    entry = alloc_entry(1);
	    entry->flags = ATF_PUBL;
	}
    }
    if (!atmsvc_addr_in_use(*addr)) addr = NULL;
    if (entry->addr && addr && (entry->flags & ATF_PERM) &&
      !atm_equal((struct sockaddr *) entry->addr,(struct sockaddr *) addr,0,0))
      {
	diag(COMPONENT,DIAG_ERROR,"ignoring attempt to change ATM address of "
	  "permanent entry");
	return result;
    }
    if (entry->state == as_valid && entry->ip == ip && (!addr || (entry->addr
      && atm_equal((struct sockaddr *) entry->addr,(struct sockaddr *) addr,0,
      0)))) return result; /* no news */
    STOP_TIMER(entry);
    if (entry->ip != ip) send_notifications(entry,0);
    entry->ip = ip;
    if (!entry->itf) {
	entry->itf = itf;
	/* @@@
	 * Need to fix this is in case we allow entries without a valid IP
	 * address but with a pre-set QOS, e.g. a VC on a given PVC with an
	 * unknown remote end.
	 */
	entry->qos = entry->itf->qos;
	adjust_qos(entry->itf,&entry->qos,0);
	Q_INSERT_HEAD(itf->table,entry);
    }
    if (entry->itf != itf)
	diag(COMPONENT,DIAG_ERROR,"interesting, interface has changed ... "
	  "(%d -> %d)",entry->itf->number,itf->number);
    if (addr) {
	if (!entry->addr) entry->addr = alloc(sizeof(*addr));
	*entry->addr = *addr;
	if (merge) {
	    ENTRY *incoming;

	    while ((incoming = lookup_incoming(addr))) {
		STOP_TIMER(incoming);
		Q_REMOVE(unknown_incoming,incoming);
		incoming->vccs->entry = entry;
		Q_INSERT_HEAD(entry->vccs,incoming->vccs);
		set_sndbuf(incoming->vccs);
		free(incoming);
	    }
	}
    }
    for (walk = entry->vccs; walk; walk = next) {
	next = walk->next;
	if (!walk->connecting)
	    if (set_ip(walk->fd,ip) < 0) {
		diag(COMPONENT,DIAG_ERROR,"set_ip: %s",strerror(errno));
		disconnect_vcc(walk);
		if (walk == vcc) result = -1;
	    }
    }
    if (entry->state != as_valid) {
	if (!entry->vccs && itf->arp_srv && !(entry->flags & ATF_NOVC))
	    connect_me(entry);
	send_notifications(entry,1);
    }
    if ((entry->flags & ATF_ARPSRV) || !(entry->flags & ATF_PERM)) {
	if (entry->itf->arp_srv) START_TIMER(entry,CREVAL);
	else START_TIMER(entry,SREVAL);
    }
    entry->state = as_valid;
    return result;
}