Esempio n. 1
0
/* Returns True is the pinentry is currently active. If WAITSECONDS is
   greater than zero the function will wait for this many seconds
   before returning.  */
int
pinentry_active_p (ctrl_t ctrl, int waitseconds)
{
  (void)ctrl;

  if (waitseconds > 0)
    {
      pth_event_t evt;
      int rc;

      evt = pth_event (PTH_EVENT_TIME, pth_timeout (waitseconds, 0));
      if (!pth_mutex_acquire (&entry_lock, 0, evt))
        {
          if (pth_event_occurred (evt))
            rc = gpg_error (GPG_ERR_TIMEOUT);
          else
            rc = gpg_error (GPG_ERR_INTERNAL);
          pth_event_free (evt, PTH_FREE_THIS);
          return rc;
        }
      pth_event_free (evt, PTH_FREE_THIS);
    }
  else
    {
      if (!pth_mutex_acquire (&entry_lock, 1, NULL))
        return gpg_error (GPG_ERR_LOCKED);
    }

  if (!pth_mutex_release (&entry_lock))
    log_error ("failed to release the entry lock at %d\n", __LINE__);
  return 0;
}
Esempio n. 2
0
APDU *
Layer7_Individual::Request_Response (APDU * r)
{
  APDU *a;
  CArray *c;
  l4->Send (r->ToPacket ());
  pth_event_t t = pth_event (PTH_EVENT_RTIME, pth_time (6, 100));
  while (pth_event_status (t) != PTH_STATUS_OCCURRED)
    {
      c = l4->Get (t);
      if (c)
	{
	  if (c->len () == 0)
	    {
	      delete c;
	      pth_event_free (t, PTH_FREE_THIS);
	      return 0;
	    }
	  a = APDU::fromPacket (*c, this->t);
	  delete c;
	  if (a->isResponse (r))
	    {
	      pth_event_free (t, PTH_FREE_THIS);
	      return a;
	    }
	  delete a;
	  pth_event_free (t, PTH_FREE_THIS);
	  return 0;
	}
    }
  pth_event_free (t, PTH_FREE_THIS);
  return 0;
}
Esempio n. 3
0
/* Wait on the condition variable for at most 'ms' milliseconds.
   The mutex must be locked before entering this function!
   The mutex is unlocked during the wait, and locked again after the wait.

Typical use:

Thread A:
 SDL_LockMutex(lock);
 while ( ! condition ) {
   SDL_CondWait(cond);
 }
 SDL_UnlockMutex(lock);

Thread B:
 SDL_LockMutex(lock);
 ...
 condition = true;
 ...
 SDL_UnlockMutex(lock);
 */
int SDL_CondWaitTimeout(SDL_cond *cond, SDL_mutex *mutex, Uint32 ms)
{
 int retval;
 pth_event_t ev;
 int sec;

 if ( ! cond ) {
   SDL_SetError("Passed a NULL condition variable");
   return -1;
 }

 retval = 0;

 sec = ms/1000;
 ev = pth_event(PTH_EVENT_TIME, pth_timeout(sec,(ms-sec*1000)*1000));

 if ( pth_cond_await(&(cond->condpth_p), &(mutex->mutexpth_p), ev) != 0 ) {
   SDL_SetError("pth_cond_await() failed");
   retval = -1;
 }

    pth_event_free(ev, PTH_FREE_ALL);

 return retval;
}
Esempio n. 4
0
Array < eibaddr_t >
  Layer7_Broadcast::A_IndividualAddress_Read (unsigned timeout)
{
  Array < eibaddr_t > addrs;
  A_IndividualAddress_Read_PDU r;
  APDU *a;
  l4->Send (r.ToPacket ());
  pth_event_t t = pth_event (PTH_EVENT_RTIME, pth_time (timeout, 0));
  while (pth_event_status (t) != PTH_STATUS_OCCURRED)
    {
      BroadcastComm *c = l4->Get (t);
      if (c)
	{
	  a = APDU::fromPacket (c->data);
	  if (a->isResponse (&r))
	    {
	      addrs.resize (addrs () + 1);
	      addrs[addrs () - 1] = c->src;
	    }
	  delete a;
	  delete c;
	}
    }
  pth_event_free (t, PTH_FREE_THIS);
  return addrs;
}
Esempio n. 5
0
static void worker_cleanup(void *arg)
{
    worker_cleanup_t *wc = (worker_cleanup_t *)arg;
    pth_event_free(wc->ev, PTH_FREE_THIS);
    pth_msgport_destroy(wc->mp);
    return;
}
Esempio n. 6
0
Array < eibaddr_t > GroupCache::LastUpdates (uint16_t start, uint8_t Timeout,
					     uint16_t & end, pth_event_t stop)
{
  Array < eibaddr_t > a;
  pth_event_t timeout = pth_event (PTH_EVENT_RTIME, pth_time (Timeout, 0));

  do
    {
      if (pos < 0x100)
	{
	  if (pos < start && start < ((pos - 0x100) & 0xffff))
	    start = (pos - 0x100) & 0xffff;
	}
      else
	{
	  if (start < ((pos - 0x100) & 0xffff) || start > pos)
	    start = (pos - 0x100) & 0xffff;
	}
      TRACEPRINTF (t, 8, this, "LastUpdates start: %d pos: %d", start, pos);
      while (start != pos && !updates[start & 0xff])
	start++;
      if (start != pos)
	{
	  while (start != pos)
	    {
	      if (updates[start & 0xff])
		a.add (updates[start & 0xff]);
	      start++;
	    }
	  end = pos;
	  pth_event_free (timeout, PTH_FREE_THIS);
	  return a;
	}
      if (pth_event_status (timeout) == PTH_STATUS_OCCURRED)
	{
	  end = pos;
	  pth_event_free (timeout, PTH_FREE_THIS);
	  return a;
	}
      pth_event_concat (timeout, stop, NULL);
      pth_mutex_acquire (&mutex, 0, 0);
      pth_cond_await (&cond, &mutex, timeout);
      pth_mutex_release (&mutex);
      pth_event_isolate (timeout);
    }
  while (1);
}
Esempio n. 7
0
void KnxConnection::Run (pth_sem_t * stop1)
{
    if (url_m == "")
        return;
    stop_m = pth_event (PTH_EVENT_SEM, stop1);
    bool retry = true;
    while (retry)
    {
        con_m = EIBSocketURL(url_m.c_str());
        if (con_m)
        {
            EIBSetEvent (con_m, stop_m);
            if (EIBOpen_GroupSocket (con_m, 0) != -1)
            {
                logger_m.infoStream() << "KnxConnection: Group socket opened. Waiting for messages." << endlog;

                // If scope reached this point, there is no doubt that the
                // connection with the bus is up and ready.
                isReady_m = true;

                int retval;
                while ((retval = checkInput()) > 0)
                {
                    /*        TODO: find another way to check if event occured
                              struct timeval tv;
                              tv.tv_sec = 1;
                              tv.tv_usec = 0;
                              pth_select_ev(0,0,0,0,&tv,stop);
                    */
                }
                if (retval == -1)
                    retry = false;
            }
            else
                logger_m.errorStream() << "Failed to open group socket." << endlog;

            if (con_m)
                EIBClose(con_m);
            con_m = 0;
        }
        else
            logger_m.errorStream() << "Failed to open knxConnection url." << endlog;
        if (retry)
        {
            struct timeval tv;
            tv.tv_sec = 60;
            tv.tv_usec = 0;
            pth_select_ev(0,0,0,0,&tv,stop_m);
            if (pth_event_status (stop_m) == PTH_STATUS_OCCURRED)
                retry = false;
        }
    }
    logger_m.infoStream() << "Out of KnxConnection loop." << endlog;
    pth_event_free (stop_m, PTH_FREE_THIS);
    stop_m = 0;
}
Esempio n. 8
0
EIBNetIPTunnel::~EIBNetIPTunnel ()
{
  TRACEPRINTF (t, 2, this, "Close");
  Stop ();
  while (!outqueue.isempty ())
    delete outqueue.get ();
  pth_event_free (getwait, PTH_FREE_THIS);
  if (sock)
    delete sock;
}
Esempio n. 9
0
void
EIBNetIPRouter::Run (pth_sem_t * stop1)
{
  pth_event_t stop = pth_event (PTH_EVENT_SEM, stop1);
  while (pth_event_status (stop) != PTH_STATUS_OCCURRED)
    {
      EIBNetIPPacket *p = sock->Get (stop);
      if (p)
	{
	  if (p->service != ROUTING_INDICATION)
	    {
	      delete p;
	      continue;
	    }
	  if (p->data () < 2 || p->data[0] != 0x29)
	    {
              if (p->data () < 2)
                {
	          TRACEPRINTF (t, 2, this, "No payload (%d)", p->data ());
                }
              else
                {
	          TRACEPRINTF (t, 2, this, "Payload not L_Data.ind (%02x)", p->data[0]);
                }
	      delete p;
	      continue;
	    }
	  const CArray data = p->data;
	  delete p;
	  L_Data_PDU *c = CEMI_to_L_Data (data, this);
	  if (c)
	    {
	      TRACEPRINTF (t, 2, this, "Recv %s", c->Decode ()());
	      if (mode & BUSMODE_UP)
		{
		  if (mode == BUSMODE_VMONITOR)
		    {
		      L_Busmonitor_PDU *l2 = new L_Busmonitor_PDU (this);
		      l2->pdu.set (c->ToPacket ());
		      l3->recv_L_Data (l2);
		    }
		  l3->recv_L_Data (c);
		  continue;
		}
	      L_Busmonitor_PDU *p1 = new L_Busmonitor_PDU (this);
	      p1->pdu = c->ToPacket ();
	      delete c;
	      l3->recv_L_Data (p1);
	      continue;
	    }
	}
    }
  pth_event_free (stop, PTH_FREE_THIS);
}
Esempio n. 10
0
BCU1SerialLowLevelDriver::~BCU1SerialLowLevelDriver ()
{
  TRACEPRINTF (t, 1, this, "Close");
  Stop ();
  pth_event_free (getwait, PTH_FREE_THIS);

  if (fd != -1)
    {
      restore_low_latency (fd, &sold);
      tcsetattr (fd, TCSAFLUSH, &told);
      close (fd);
    }
}
Esempio n. 11
0
FT12LowLevelDriver::~FT12LowLevelDriver ()
{
  Stop ();
  pth_event_free (getwait, PTH_FREE_THIS);

  while (!outqueue.isempty ())
    delete outqueue.get ();

  TRACEPRINTF (t, 1, this, "Close");
  if (fd != -1)
    {
      tcsetattr (fd, TCSAFLUSH, &old);
      restore_low_latency (fd, &sold);
      close (fd);
    }
}
Esempio n. 12
0
TPUARTLayer2Driver::~TPUARTLayer2Driver ()
{
  TRACEPRINTF (t, 2, this, "Close");
  Stop ();
  pth_event_free (getwait, PTH_FREE_THIS);
  while (!inqueue.isempty ())
    delete inqueue.get ();
  while (!outqueue.isempty ())
    delete outqueue.get ();

  if (fd != -1)
    {
      removeAddress (addr);
      close (fd);
    }
}
Esempio n. 13
0
void *
task_pth_run(void *data)
{
   Task *task;

   task = (Task *) data;
   char msgPortName[10];

   pth_msgport_t mp;

   pth_event_t ev;

#ifdef _LDEBUG
   printf("F=%s,L=%d,data_pth_run=%p,%p,name=%s,%p\n", __FILE__, __LINE__, data, task, task->name, task->name);
#endif
   if (task == NULL)
      return NULL;
   append_List(&Tasks, (void *) task);
   local_print_List(&Tasks);

   snprintf(msgPortName, 10, "%ld", task->id);
#ifdef _MDEBUG
   printf("F=%s,L=%d,task->id=%ld,msgPortName=%s\n", __FILE__, __LINE__, task->id, msgPortName);
#endif
   mp = pth_msgport_create(msgPortName);
   ev = pth_event(PTH_EVENT_MSG, mp);

   if (task->run)
      task->run(task->data);

   pth_event_free(ev, PTH_FREE_THIS);
   pth_msgport_destroy(mp);

   if (task->destroy)
      task->destroy(task->data);
   stopcount = 0;
   Task_START();
   removeIt_List(&Tasks, task);
//      local_print_List(&Tasks);
   free(task->name);
   free(task);
#ifdef _LDEBUG
   printf("	task end run=%p\n", task);
   printf("F=%s,L=%d\n", __FILE__, __LINE__);
#endif
   return NULL;
}
Esempio n. 14
0
/*!
 * \brief close connection with eibnetmux socket server
 * 
 * \param   conn            connection handle as returned by enmx_open()
 */
void enmx_close( ENMX_HANDLE conn )
{
    sConnectionInfo         **connInfo, *temp;
    SOCKET_CMD_HEAD         cmd_head;
    pth_event_t             ev_wakeup;
    time_t                  secs;
    
    temp = NULL;
    for( connInfo = &enmx_connections; *connInfo != NULL; connInfo = &(*connInfo)->next ) {
        if( (*connInfo)->socket == conn ) {
            temp = *connInfo;
            *connInfo = (*connInfo)->next;
            break;
        }
    }
    
    if( temp != NULL ) {
        cmd_head.cmd = SOCKET_CMD_EXIT;
        cmd_head.address = 0xffff;
        secs = time( NULL ) + TIMEOUT;
        switch( temp->mode ) {
            case ENMX_MODE_STANDARD:
                while( write( conn, &cmd_head, sizeof( cmd_head )) == -1 ) {
                    if( errno == EAGAIN ) {
                        if( secs <= time( NULL )) {
                            break;
                        }
                        usleep( 10 * 1000 );
                        continue;
                    }
                }
                break;
            case ENMX_MODE_PTH:
                ev_wakeup = pth_event( PTH_EVENT_TIME, pth_time( secs, 0 ));
                pth_write_ev( conn, &cmd_head, sizeof( cmd_head ), ev_wakeup );
                // either the request has been sent or timeout reached
                // in any case, we've finished
                pth_event_free( ev_wakeup, PTH_FREE_ALL );
                break;
        }
        if( temp->hostname ) free( temp->hostname );
        if( temp->name ) free( temp->name );
        free( temp );
    }

    close( conn );
}
Esempio n. 15
0
bool
EMI1Layer2::Close ()
{
  if (!Layer2::Close ())
    return false;
  TRACEPRINTF (t, 2, this, "CloseL2");
  uchar t[] = { 0x46, 0x01, 0x00, 0x60, 0xc0 };
  iface->Send_Packet (CArray (t, sizeof (t)));
  if (!iface->Send_Queue_Empty ())
    {
      pth_event_t
	e = pth_event (PTH_EVENT_SEM, iface->Send_Queue_Empty_Cond ());
      pth_wait (e);
      pth_event_free (e, PTH_FREE_THIS);
    }
  return true;
}
Esempio n. 16
0
bool
EMI2Layer2::leaveBusmonitor ()
{
  if (!Layer2::leaveBusmonitor ())
    return false;
  TRACEPRINTF (t, 2, this, "CloseBusmon");
  uchar t[] = { 0xa9, 0x1E, 0x12, 0x34, 0x56, 0x78, 0x9a };
  iface->Send_Packet (CArray (t, sizeof (t)));
  while (!iface->Send_Queue_Empty ())
    {
      pth_event_t
	e = pth_event (PTH_EVENT_SEM, iface->Send_Queue_Empty_Cond ());
      pth_wait (e);
      pth_event_free (e, PTH_FREE_THIS);
    }
  return true;
}
Esempio n. 17
0
void RxThread::Run (pth_sem_t * stop1)
{
    stop_m = pth_event (PTH_EVENT_SEM, stop1);
    uint8_t buf[1024];
    int retval;
    logger_m.debugStream() << "Start IO Port loop." << endlog;
    while ((retval = port_m->get(buf, sizeof(buf), stop_m)) > 0)
    {
        ListenerList_t::iterator it;
        for (it = listenerList_m.begin(); it != listenerList_m.end(); it++)
        {
//            logger_m.debugStream() << "Calling onDataReceived on listener for " << port_m->getID() << endlog;
            (*it)->onDataReceived(buf, retval);
        }
    }
    logger_m.debugStream() << "Out of IO Port loop." << endlog;
    pth_event_free (stop_m, PTH_FREE_THIS);
    stop_m = 0;
}
Esempio n. 18
0
bool
EMI1Layer2::Open ()
{
  if (!Layer2::Open ())
    return false;
  const uchar t1[] = { 0x46, 0x01, 0x00, 0x60, 0x12 };
  TRACEPRINTF (t, 2, this, "OpenL2");
  iface->SendReset ();
  iface->Send_Packet (CArray (t1, sizeof (t1)));

  while (!iface->Send_Queue_Empty ())
    {
      pth_event_t
	e = pth_event (PTH_EVENT_SEM, iface->Send_Queue_Empty_Cond ());
      pth_wait (e);
      pth_event_free (e, PTH_FREE_THIS);
    }
  return true;
}
Esempio n. 19
0
int
glthread_cond_timedwait_multithreaded (gl_cond_t *cond,
                                       gl_lock_t *lock,
                                       struct timespec *abstime)
{
  int ret, status;
  pth_event_t ev;

  ev = pth_event (PTH_EVENT_TIME, pth_time (abstime->tv_sec, abstime->tv_nsec / 1000));
  ret = pth_cond_await (cond, lock, ev);

  status = pth_event_status (ev);
  pth_event_free (ev, PTH_FREE_THIS);

  if (status == PTH_STATUS_OCCURRED)
    return ETIMEDOUT;

  return ret;
}
Esempio n. 20
0
bool
EMI2Layer2::enterBusmonitor ()
{
  if (!Layer2::enterBusmonitor ())
    return false;
  const uchar t1[] = { 0xa9, 0x1E, 0x12, 0x34, 0x56, 0x78, 0x9a };
  const uchar t2[] = { 0xa9, 0x90, 0x18, 0x34, 0x45, 0x67, 0x8a };
  TRACEPRINTF (t, 2, this, "OpenBusmon");
  iface->SendReset ();
  iface->Send_Packet (CArray (t1, sizeof (t1)));
  iface->Send_Packet (CArray (t2, sizeof (t2)));

  if (!iface->Send_Queue_Empty ())
    {
      pth_event_t
	e = pth_event (PTH_EVENT_SEM, iface->Send_Queue_Empty_Cond ());
      pth_wait (e);
      pth_event_free (e, PTH_FREE_THIS);
    }
  return true;
}
Esempio n. 21
0
void
USBLoop::Run (pth_sem_t * stop1)
{
  fd_set r, w, e;
  int rc, fds, i;
  struct timeval tv, tv1;
  const struct libusb_pollfd **usbfd, **usbfd_orig;
  pth_event_t stop = pth_event (PTH_EVENT_SEM, stop1);
  // The next two are dummy allocations which will be replaced later
  pth_event_t event = pth_event (PTH_EVENT_SEM, stop1);
  pth_event_t timeout = pth_event (PTH_EVENT_SEM, stop1);

  tv1.tv_sec = tv1.tv_usec = 0;
  TRACEPRINTF (t, 10, this, "LoopStart");
  while (pth_event_status (stop) != PTH_STATUS_OCCURRED)
    {
      TRACEPRINTF (t, 10, this, "LoopBegin");
      FD_ZERO (&r);
      FD_ZERO (&w);
      FD_ZERO (&e);
      fds = 0;
      rc = 0;

      usbfd = libusb_get_pollfds (context);
      usbfd_orig = usbfd;
      if (usbfd)
	while (*usbfd)
	  {
	    if ((*usbfd)->fd > fds)
	      fds = (*usbfd)->fd;
	    if ((*usbfd)->events & POLLIN)
	      FD_SET ((*usbfd)->fd, &r);
	    if ((*usbfd)->events & POLLOUT)
	      FD_SET ((*usbfd)->fd, &w);
	    usbfd++;
	  }
      free (usbfd_orig);

      i = libusb_get_next_timeout (context, &tv);
      if (i < 0)
	break;
      if (i > 0)
	{
	  pth_event (PTH_EVENT_RTIME | PTH_MODE_REUSE,
		     timeout, pth_time (tv.tv_sec, tv.tv_usec));
	  pth_event_concat (stop, timeout, NULL);
	}
      pth_event (PTH_EVENT_SELECT | PTH_MODE_REUSE, event, &rc, fds + 1, &r,
		 &w, &e);
      pth_event_concat (stop, event, NULL);
      TRACEPRINTF (t, 10, this, "LoopWait");
      pth_wait (stop);
      TRACEPRINTF (t, 10, this, "LoopProcess");

      pth_event_isolate (event);
      pth_event_isolate (timeout);

      if (libusb_handle_events_timeout (context, &tv1))
	break;
      TRACEPRINTF (t, 10, this, "LoopEnd");
    }
  TRACEPRINTF (t, 10, this, "LoopStop");

  pth_event_free (timeout, PTH_FREE_THIS);
  pth_event_free (event, PTH_FREE_THIS);
  pth_event_free (stop, PTH_FREE_THIS);
}
Esempio n. 22
0
void
EMI1Layer2::Run (pth_sem_t * stop1)
{
  pth_event_t stop = pth_event (PTH_EVENT_SEM, stop1);
  pth_event_t input = pth_event (PTH_EVENT_SEM, &in_signal);
  pth_event_t timeout = pth_event (PTH_EVENT_RTIME, pth_time (0, 0));
  bool wait_confirm = false;
  while (pth_event_status (stop) != PTH_STATUS_OCCURRED)
    {
      if (!wait_confirm)
	pth_event_concat (stop, input, NULL);
      if (wait_confirm)
	pth_event_concat (stop, timeout, NULL);
      CArray *c = iface->Get_Packet (stop);
      pth_event_isolate(input);
      pth_event_isolate(timeout);
      if (!wait_confirm && !inqueue.isempty())
	{
	  pth_sem_dec (&in_signal);	
	  Send(inqueue.get());
	  if (noqueue)
	    {
	      pth_event (PTH_EVENT_RTIME | PTH_MODE_REUSE, timeout,
			 pth_time (1, 0));
	      wait_confirm = true;
	    }
	}
      if (wait_confirm && pth_event_status(timeout) == PTH_STATUS_OCCURRED)
	wait_confirm = false;
      if (!c)
	continue;
      if (c->len () == 1 && (*c)[0] == 0xA0 && (mode & BUSMODE_UP))
	{
	  TRACEPRINTF (t, 2, this, "Reopen");
          busmode_t old_mode = mode;
	  mode = BUSMODE_DOWN;
	  if (Open ())
            mode = old_mode; // restore VMONITOR
	}
      if (c->len () == 1 && (*c)[0] == 0xA0 && mode == BUSMODE_MONITOR)
	{
	  TRACEPRINTF (t, 2, this, "Reopen Busmonitor");
	  mode = BUSMODE_DOWN;
	  enterBusmonitor ();
	}
      if (c->len () && (*c)[0] == 0x4E)
	wait_confirm = false;
      if (c->len () && (*c)[0] == 0x49 && (mode & BUSMODE_UP))
	{
	  L_Data_PDU *p = EMI_to_L_Data (*c, this);
	  if (p)
	    {
	      delete c;
	      if (p->AddrType == IndividualAddress)
		p->dest = 0;
	      TRACEPRINTF (t, 2, this, "Recv %s", p->Decode ()());
	      if (mode == BUSMODE_VMONITOR)
		{
		  L_Busmonitor_PDU *l2 = new L_Busmonitor_PDU (this);
		  l2->pdu.set (p->ToPacket ());
		  l3->recv_L_Data (l2);
		}
	      l3->recv_L_Data (p);
	      continue;
	    }
	}
      if (c->len () > 4 && (*c)[0] == 0x49 && mode == BUSMODE_MONITOR)
	{
	  L_Busmonitor_PDU *p = new L_Busmonitor_PDU (this);
	  p->status = (*c)[1];
	  p->timestamp = ((*c)[2] << 24) | ((*c)[3] << 16);
	  p->pdu.set (c->array () + 4, c->len () - 4);
	  delete c;
	  TRACEPRINTF (t, 2, this, "Recv %s", p->Decode ()());
	  l3->recv_L_Data (p);
	  continue;
	}
      delete c;
    }
  pth_event_free (stop, PTH_FREE_THIS);
  pth_event_free (input, PTH_FREE_THIS);
  pth_event_free (timeout, PTH_FREE_THIS);
}
Esempio n. 23
0
GroupCacheEntry
  GroupCache::Read (eibaddr_t addr, unsigned Timeout, uint16_t age)
{
  TRACEPRINTF (t, 4, this, "GroupCacheRead %s %d %d",
	       FormatGroupAddr (addr)(), Timeout, age);
  bool rm = false;
  GroupCacheEntry *c;
  if (!enable)
    {
      GroupCacheEntry f;
      f.src = 0;
      f.dst = 0;
      TRACEPRINTF (t, 4, this, "GroupCache not enabled");
      return f;
    }

  c = find (addr);
  if (c && age && c->recvtime + age < time (0))
    rm = true;

  if (c && !rm)
    {
      TRACEPRINTF (t, 4, this, "GroupCache found: %s",
		   FormatEIBAddr (c->src)());
      return *c;
    }

  if (!Timeout)
    {
      GroupCacheEntry f;
      f.src = 0;
      f.dst = addr;
      TRACEPRINTF (t, 4, this, "GroupCache no entry");
      return f;
    }

  A_GroupValue_Read_PDU apdu;
  T_DATA_XXX_REQ_PDU tpdu;
  L_Data_PDU *l;
  pth_event_t timeout = pth_event (PTH_EVENT_RTIME, pth_time (Timeout, 0));

  tpdu.data = apdu.ToPacket ();
  l = new L_Data_PDU (FakeL2);
  l->data = tpdu.ToPacket ();
  l->source = 0;
  l->dest = addr;
  l->AddrType = GroupAddress;
  layer3->send_L_Data (l);

  do
    {
      c = find (addr);
      rm = false;
      if (c && age && c->recvtime + age < time (0))
	rm = true;

      if (c && !rm)
	{
	  TRACEPRINTF (t, 4, this, "GroupCache found: %s",
		       FormatEIBAddr (c->src)());
	  pth_event_free (timeout, PTH_FREE_THIS);
	  return *c;
	}

      if (pth_event_status (timeout) == PTH_STATUS_OCCURRED && c)
	{
	  GroupCacheEntry gc;
	  gc.src = 0;
	  gc.dst = addr;
	  TRACEPRINTF (t, 4, this, "GroupCache reread timeout");
	  pth_event_free (timeout, PTH_FREE_THIS);
	  return gc;
	}

      if (pth_event_status (timeout) == PTH_STATUS_OCCURRED)
	{
	  c = new GroupCacheEntry;
	  c->src = 0;
	  c->dst = addr;
	  c->recvtime = time (0);
	  add (c);
	  TRACEPRINTF (t, 4, this, "GroupCache timeout");
	  pth_event_free (timeout, PTH_FREE_THIS);
	  return *c;
	}

      pth_mutex_acquire (&mutex, 0, 0);
      pth_cond_await (&cond, &mutex, timeout);
      pth_mutex_release (&mutex);
    }
  while (1);
}
Esempio n. 24
0
void
BCU1SerialLowLevelDriver::Run (pth_sem_t * stop1)
{
  pth_event_t stop = pth_event (PTH_EVENT_SEM, stop1);
  pth_event_t input = pth_event (PTH_EVENT_SEM, &in_signal);
  pth_event_t timeout = pth_event (PTH_EVENT_RTIME, pth_time (0, 10));
  while (pth_event_status (stop) != PTH_STATUS_OCCURRED)
    {
      int error;
      timeout =
	pth_event (PTH_EVENT_RTIME | PTH_MODE_REUSE, timeout,
		   pth_time (0, 150));
      pth_event_concat (stop, input, timeout, NULL);
      pth_wait (stop);
      pth_event_isolate (stop);
      pth_event_isolate (input);
      timeout =
	pth_event (PTH_EVENT_RTIME | PTH_MODE_REUSE, timeout,
		   pth_time (0, 200));
      pth_event_concat (stop, timeout, NULL);

      struct timeval v1, v2;
      gettimeofday (&v1, 0);

      CArray e;
      CArray r;
      uchar s;
      if (!inqueue.isempty ())
	{
	  const CArray & c = inqueue.top ();
	  e.resize (c () + 1);
	  s = c () & 0x1f;
	  s |= 0x20;
	  s |= 0x80 * bitcount (s);
	  e[0] = s;
	  e.setpart (c, 1);
	}
      else
	{
	  e.resize (1);
	  e[0] = 0xff;
	}
      if (!startsync ())
	{
	  error = 1;
	  goto err;
	}
      if (!exchange (e[0], s, stop))
	{
	  error = 3;
	  goto err;
	}
      if (!endsync ())
	{
	  error = 2;
	  goto err;
	}
      if (s == 0xff && e[0] != 0xff)
	{
	  for (unsigned i = 1; i < e (); i++)
	    {
	      if (!startsync ())
		{
		  error = 1;
		  goto err;
		}
	      if (!exchange (e[i], s, stop))
		{
		  error = 3;
		  goto err;
		}
	      if (endsync ())
		{
		  error = 2;
		  goto err;
		}
	    }
	  if (s != 0x00)
	    {
	      error = 10;
	      goto err;
	    }
	  inqueue.get ();
	  TRACEPRINTF (t, 0, this, "Sent");
	  pth_sem_dec (&in_signal);
	  if (inqueue.isempty ())
	    pth_sem_set_value (&send_empty, 1);
	}
      else if (s != 0xff)
	{
	  r.resize ((s & 0x1f));
	  for (unsigned i = 0; i < (s & 0x1f); i++)
	    {
	      if (!startsync ())
		{
		  error = 1;
		  goto err;
		}
	      if (!exchange (0, r[i], stop))
		{
		  error = 3;
		  goto err;
		}
	      if (!endsync ())
		{
		  error = 2;
		  goto err;
		}
	    }
	  TRACEPRINTF (t, 0, this, "Recv");
	  outqueue.put (new CArray (r));
	  pth_sem_inc (&out_signal, 1);
	}
      gettimeofday (&v2, 0);
      TRACEPRINTF (t, 1, this, "Recvtime: %d",
		   v2.tv_sec * 1000000L + v2.tv_usec -
		   (v1.tv_sec * 1000000L + v1.tv_usec));

      if (0)
	{
	err:
	  gettimeofday (&v2, 0);
	  TRACEPRINTF (t, 1, this, "ERecvtime: %d",
		       v2.tv_sec * 1000000L + v2.tv_usec -
		       (v1.tv_sec * 1000000L + v1.tv_usec));
	  setstat (getstat () & ~(TIOCM_RTS | TIOCM_CTS));
	  pth_usleep (2000);
	  while ((getstat () & TIOCM_CTS));
	  TRACEPRINTF (t, 0, this, "Restart %d", error);
	}

      pth_event_isolate (timeout);
    }
  pth_event_free (timeout, PTH_FREE_THIS);
  pth_event_free (stop, PTH_FREE_THIS);
  pth_event_free (input, PTH_FREE_THIS);
}
Esempio n. 25
0
void
Layer3::Run (pth_sem_t * stop1)
{
  pth_event_t stop = pth_event (PTH_EVENT_SEM, stop1);
  unsigned i;

  while (pth_event_status (stop) != PTH_STATUS_OCCURRED)
    {
      LPDU *l = layer2->Get_L_Data (stop);
      if (!l)
	continue;
      if (l->getType () == L_Busmonitor)
	{
	  L_Busmonitor_PDU *l1, *l2;
	  l1 = (L_Busmonitor_PDU *) l;

	  TRACEPRINTF (t, 3, this, "Recv %s", l1->Decode ()());
	  for (i = 0; i < busmonitor (); i++)
	    {
	      l2 = new L_Busmonitor_PDU (*l1);
	      busmonitor[i].cb->Get_L_Busmonitor (l2);
	    }
	  for (i = 0; i < vbusmonitor (); i++)
	    {
	      l2 = new L_Busmonitor_PDU (*l1);
	      vbusmonitor[i].cb->Get_L_Busmonitor (l2);
	    }
	}
      if (l->getType () == L_Data)
	{
	  L_Data_PDU *l1;
	  l1 = (L_Data_PDU *) l;
	  if (l1->repeated)
	    {
	      CArray d1 = l1->ToPacket ();
	      for (i = 0; i < ignore (); i++)
		if (d1 == ignore[i].data)
		  {
		    TRACEPRINTF (t, 3, this, "Repeated discareded");
		    goto wt;
		  }
	    }
	  l1->repeated = 1;
	  ignore.resize (ignore () + 1);
	  ignore[ignore () - 1].data = l1->ToPacket ();
	  ignore[ignore () - 1].end = getTime () + 1000000;
	  l1->repeated = 0;

	  if (l1->AddrType == IndividualAddress
	      && l1->dest == layer2->getDefaultAddr ())
	    l1->dest = 0;
	  TRACEPRINTF (t, 3, this, "Recv %s", l1->Decode ()());

	  if (l1->AddrType == GroupAddress && l1->dest == 0)
	    {
	      for (i = 0; i < broadcast (); i++)
		broadcast[i].cb->Get_L_Data (new L_Data_PDU (*l1));
	    }
	  if (l1->AddrType == GroupAddress && l1->dest != 0)
	    {
	      for (i = 0; i < group (); i++)
		if (group[i].dest == l1->dest || group[i].dest == 0)
		  group[i].cb->Get_L_Data (new L_Data_PDU (*l1));
	    }
	  if (l1->AddrType == IndividualAddress)
	    {
	      for (i = 0; i < individual (); i++)
		if (individual[i].dest == l1->dest
		    || individual[i].dest == 0)
		  if (individual[i].src == l1->source
		      || individual[i].src == 0)
		    individual[i].cb->Get_L_Data (new L_Data_PDU (*l1));
	    }
	}
    redel:
      for (i = 0; i < ignore (); i++)
	if (ignore[i].end < getTime ())
	  {
	    ignore.deletepart (i, 1);
	    goto redel;
	  }
    wt:
      delete l;

    }
  pth_event_free (stop, PTH_FREE_THIS);
}
Esempio n. 26
0
void
EIBNetIPTunnel::Run (pth_sem_t * stop1)
{
  int channel = -1;
  int mod = 0;
  int rno = 0;
  int sno = 0;
  int retry = 0;
  int heartbeat = 0;
  int drop = 0;
  eibaddr_t myaddr;
  pth_event_t stop = pth_event (PTH_EVENT_SEM, stop1);
  pth_event_t input = pth_event (PTH_EVENT_SEM, &insignal);
  pth_event_t timeout = pth_event (PTH_EVENT_RTIME, pth_time (0, 0));
  pth_event_t timeout1 = pth_event (PTH_EVENT_RTIME, pth_time (10, 0));
  L_Data_PDU *c;

  EIBNetIPPacket p;
  EIBNetIPPacket *p1;
  EIBnet_ConnectRequest creq;
  creq.nat = saddr.sin_addr.s_addr == 0;
  EIBnet_ConnectResponse cresp;
  EIBnet_ConnectionStateRequest csreq;
  csreq.nat = saddr.sin_addr.s_addr == 0;
  EIBnet_ConnectionStateResponse csresp;
  EIBnet_TunnelRequest treq;
  EIBnet_TunnelACK tresp;
  EIBnet_DisconnectRequest dreq;
  dreq.nat = saddr.sin_addr.s_addr == 0;
  EIBnet_DisconnectResponse dresp;
  creq.caddr = saddr;
  creq.daddr = saddr;
  creq.CRI.resize (3);
  creq.CRI[0] = 0x04;
  creq.CRI[1] = 0x02;
  creq.CRI[2] = 0x00;
  p = creq.ToPacket ();
  sock->sendaddr = caddr;
  sock->Send (p);

  while (pth_event_status (stop) != PTH_STATUS_OCCURRED)
    {
      if (mod == 1)
	pth_event_concat (stop, input, NULL);
      if (mod == 2 || mod == 3)
	pth_event_concat (stop, timeout, NULL);

      pth_event_concat (stop, timeout1, NULL);

      p1 = sock->Get (stop);
      pth_event_isolate (stop);
      pth_event_isolate (timeout);
      pth_event_isolate (timeout1);
      if (p1)
	{
	  switch (p1->service)
	    {
	    case CONNECTION_RESPONSE:
	      if (mod)
		goto err;
	      if (parseEIBnet_ConnectResponse (*p1, cresp))
		{
		  TRACEPRINTF (t, 1, this, "Recv wrong connection response");
		  break;
		}
	      if (cresp.status != 0)
		{
		  TRACEPRINTF (t, 1, this, "Connect failed with error %02X",
			       cresp.status);
		  if (cresp.status == 0x23 && support_busmonitor == 1
		      && connect_busmonitor == 1)
		    {
		      TRACEPRINTF (t, 1, this, "Disable busmonitor support");
		      support_busmonitor = 0;
		      connect_busmonitor = 0;
		      creq.CRI[1] = 0x02;
		      pth_event (PTH_EVENT_RTIME | PTH_MODE_REUSE, timeout1,
				 pth_time (10, 0));
		      p = creq.ToPacket ();
		      TRACEPRINTF (t, 1, this, "Connectretry");
		      sock->sendaddr = caddr;
		      sock->Send (p);
		    }
		  break;
		}
	      if (cresp.CRD () != 3)
		{
		  TRACEPRINTF (t, 1, this, "Recv wrong connection response");
		  break;
		}
	      myaddr = (cresp.CRD[1] << 8) | cresp.CRD[2];
	      daddr = cresp.daddr;
	      if (!cresp.nat)
		{
		  if (NAT)
		    daddr.sin_addr = caddr.sin_addr;
		  if (dataport != -1)
		    daddr.sin_port = htons (dataport);
		}
	      channel = cresp.channel;
	      mod = 1;
	      sno = 0;
	      rno = 0;
	      sock->recvaddr2 = daddr;
	      sock->recvall = 3;
	      pth_event (PTH_EVENT_RTIME | PTH_MODE_REUSE, timeout1,
			 pth_time (30, 0));
	      heartbeat = 0;
	      break;

	    case TUNNEL_REQUEST:
	      if (mod == 0)
		{
		  TRACEPRINTF (t, 1, this, "Not connected");
		  goto err;
		}
	      if (parseEIBnet_TunnelRequest (*p1, treq))
		{
		  TRACEPRINTF (t, 1, this, "Invalid request");
		  break;
		}
	      if (treq.channel != channel)
		{
		  TRACEPRINTF (t, 1, this, "Not for us");
		  break;
		}
	      if (((treq.seqno + 1) & 0xff) == rno)
		{
		  tresp.status = 0;
		  tresp.channel = channel;
		  tresp.seqno = treq.seqno;
		  p = tresp.ToPacket ();
		  sock->sendaddr = daddr;
		  sock->Send (p);
		  sock->recvall = 0;
		  break;
		}
	      if (treq.seqno != rno)
		{
		  TRACEPRINTF (t, 1, this, "Wrong sequence %d<->%d",
			       treq.seqno, rno);
		  if (treq.seqno < rno)
		    treq.seqno += 0x100;
		  if (treq.seqno >= rno + 5)
		    {
		      dreq.caddr = saddr;
		      dreq.channel = channel;
		      p = dreq.ToPacket ();
		      sock->sendaddr = caddr;
		      sock->Send (p);
		      sock->recvall = 0;
		      mod = 0;
		    }
		  break;
		}
	      rno++;
	      if (rno > 0xff)
		rno = 0;
	      tresp.status = 0;
	      tresp.channel = channel;
	      tresp.seqno = treq.seqno;
	      p = tresp.ToPacket ();
	      sock->sendaddr = daddr;
	      sock->Send (p);
	      //Confirmation
	      if (treq.CEMI[0] == 0x2E)
		{
		  if (mod == 3)
		    mod = 1;
		  break;
		}
	      if (treq.CEMI[0] == 0x2B)
		{
		  L_Busmonitor_PDU *l2 = CEMI_to_Busmonitor (treq.CEMI);
		  outqueue.put (l2);
		  pth_sem_inc (&outsignal, 1);
		  break;
		}
	      if (treq.CEMI[0] != 0x29)
		{
		  TRACEPRINTF (t, 1, this, "Unexpected CEMI Type %02X",
			       treq.CEMI[0]);
		  break;
		}
	      c = CEMI_to_L_Data (treq.CEMI);
	      if (c)
		{

		  TRACEPRINTF (t, 1, this, "Recv %s", c->Decode ()());
		  if (mode == 0)
		    {
		      if (vmode)
			{
			  L_Busmonitor_PDU *l2 = new L_Busmonitor_PDU;
			  l2->pdu.set (c->ToPacket ());
			  outqueue.put (l2);
			  pth_sem_inc (&outsignal, 1);
			}
		      if (c->AddrType == IndividualAddress
			  && c->dest == myaddr)
			c->dest = 0;
		      outqueue.put (c);
		      pth_sem_inc (&outsignal, 1);
		      break;
		    }
		  L_Busmonitor_PDU *p1 = new L_Busmonitor_PDU;
		  p1->pdu = c->ToPacket ();
		  delete c;
		  outqueue.put (p1);
		  pth_sem_inc (&outsignal, 1);
		  break;
		}
	      TRACEPRINTF (t, 1, this, "Unknown CEMI");
	      break;
	    case TUNNEL_RESPONSE:
	      if (mod == 0)
		{
		  TRACEPRINTF (t, 1, this, "Not connected");
		  goto err;
		}
	      if (parseEIBnet_TunnelACK (*p1, tresp))
		{
		  TRACEPRINTF (t, 1, this, "Invalid response");
		  break;
		}
	      if (tresp.channel != channel)
		{
		  TRACEPRINTF (t, 1, this, "Not for us");
		  break;
		}
	      if (tresp.seqno != sno)
		{
		  TRACEPRINTF (t, 1, this, "Wrong sequence %d<->%d",
			       tresp.seqno, sno);
		  break;
		}
	      if (tresp.status)
		{
		  TRACEPRINTF (t, 1, this, "Error in ACK %d", tresp.status);
		  break;
		}
	      if (mod == 2)
		{
		  sno++;
		  if (sno > 0xff)
		    sno = 0;
		  pth_sem_dec (&insignal);
		  inqueue.get ();
		  if (noqueue)
		    {
		      mod = 3;
		      pth_event (PTH_EVENT_RTIME | PTH_MODE_REUSE, timeout,
				 pth_time (1, 0));
		    }
		  else
		    mod = 1;
		  retry = 0;
		  drop = 0;
		}
	      else
		TRACEPRINTF (t, 1, this, "Unexpected ACK");
	      break;
	    case CONNECTIONSTATE_RESPONSE:
	      if (parseEIBnet_ConnectionStateResponse (*p1, csresp))
		{
		  TRACEPRINTF (t, 1, this, "Invalid response");
		  break;
		}
	      if (csresp.channel != channel)
		{
		  TRACEPRINTF (t, 1, this, "Not for us");
		  break;
		}
	      if (csresp.status == 0)
		{
		  if (heartbeat > 0)
		    heartbeat--;
		  else
		    TRACEPRINTF (t, 1, this,
				 "Duplicate Connection State Response");
		}
	      else if (csresp.status == 0x21)
		{
		  TRACEPRINTF (t, 1, this,
			       "Connection State Response not connected");
		  dreq.caddr = saddr;
		  dreq.channel = channel;
		  p = dreq.ToPacket ();
		  sock->sendaddr = caddr;
		  sock->Send (p);
		  sock->recvall = 0;
		  mod = 0;
		}
	      else
		TRACEPRINTF (t, 1, this,
			     "Connection State Response Error %02x",
			     csresp.status);
	      break;
	    case DISCONNECT_REQUEST:
	      if (mod == 0)
		{
		  TRACEPRINTF (t, 1, this, "Not connected");
		  goto err;
		}
	      if (parseEIBnet_DisconnectRequest (*p1, dreq))
		{
		  TRACEPRINTF (t, 1, this, "Invalid request");
		  break;
		}
	      if (dreq.channel != channel)
		{
		  TRACEPRINTF (t, 1, this, "Not for us");
		  break;
		}
	      dresp.channel = channel;
	      dresp.status = 0;
	      p = dresp.ToPacket ();
	      t->TracePacket (1, this, "SendDis", p.data);
	      sock->sendaddr = caddr;
	      sock->Send (p);
	      sock->recvall = 0;
	      mod = 0;
	      break;
	    case DISCONNECT_RESPONSE:
	      if (mod == 0)
		{
		  TRACEPRINTF (t, 1, this, "Not connected");
		  break;
		}
	      if (parseEIBnet_DisconnectResponse (*p1, dresp))
		{
		  TRACEPRINTF (t, 1, this, "Invalid request");
		  break;
		}
	      if (dresp.channel != channel)
		{
		  TRACEPRINTF (t, 1, this, "Not for us");
		  break;
		}
	      mod = 0;
	      sock->recvall = 0;
	      TRACEPRINTF (t, 1, this, "Disconnected");
	      pth_event (PTH_EVENT_RTIME | PTH_MODE_REUSE, timeout1,
			 pth_time (0, 100));
	      break;
	    default:
	    err:
	      TRACEPRINTF (t, 1, this, "Recv unexpected service %04X",
			   p1->service);
	    }
	  delete p1;
	}
      if (mod == 2 && pth_event_status (timeout) == PTH_STATUS_OCCURRED)
	{
	  mod = 1;
	  retry++;
	  if (retry > 3)
	    {
	      TRACEPRINTF (t, 1, this, "Drop");
	      pth_sem_dec (&insignal);
	      inqueue.get ();
	      retry = 0;
	      drop++;
	      if (drop >= 3)
		{
		  dreq.caddr = saddr;
		  dreq.channel = channel;
		  p = dreq.ToPacket ();
		  sock->sendaddr = caddr;
		  sock->Send (p);
		  sock->recvall = 0;
		  mod = 0;
		}
	    }
	}
      if (mod == 3 && pth_event_status (timeout) == PTH_STATUS_OCCURRED)
	mod = 1;
      if (mod != 0 && pth_event_status (timeout1) == PTH_STATUS_OCCURRED)
	{
	  pth_event (PTH_EVENT_RTIME | PTH_MODE_REUSE, timeout1,
		     pth_time (30, 0));
	  if (heartbeat < 5)
	    {
	      csreq.caddr = saddr;
	      csreq.channel = channel;
	      p = csreq.ToPacket ();
	      TRACEPRINTF (t, 1, this, "Heartbeat");
	      sock->sendaddr = caddr;
	      sock->Send (p);
	      heartbeat++;
	    }
	  else
	    {
	      TRACEPRINTF (t, 1, this, "Disconnection because of errors");
	      dreq.caddr = saddr;
	      dreq.channel = channel;
	      p = dreq.ToPacket ();
	      sock->sendaddr = caddr;
	      if (channel != -1)
		sock->Send (p);
	      sock->recvall = 0;
	      mod = 0;
	    }
	}
      if (mod == 0 && pth_event_status (timeout1) == PTH_STATUS_OCCURRED)
	{
	  pth_event (PTH_EVENT_RTIME | PTH_MODE_REUSE, timeout1,
		     pth_time (10, 0));
	  creq.CRI[1] =
	    ((connect_busmonitor && support_busmonitor) ? 0x80 : 0x02);
	  p = creq.ToPacket ();
	  TRACEPRINTF (t, 1, this, "Connectretry");
	  sock->sendaddr = caddr;
	  sock->Send (p);
	}

      if (!inqueue.isempty () && inqueue.top ()() == 0)
	{
	  pth_sem_dec (&insignal);
	  inqueue.get ();
	  if (support_busmonitor)
	    {
	      dreq.caddr = saddr;
	      dreq.channel = channel;
	      p = dreq.ToPacket ();
	      sock->sendaddr = caddr;
	      sock->Send (p);
	    }
	}

      if (!inqueue.isempty () && mod == 1)
	{
	  treq.channel = channel;
	  treq.seqno = sno;
	  treq.CEMI = inqueue.top ();
	  p = treq.ToPacket ();
	  t->TracePacket (1, this, "SendTunnel", p.data);
	  sock->sendaddr = daddr;
	  sock->Send (p);
	  mod = 2;
	  pth_event (PTH_EVENT_RTIME | PTH_MODE_REUSE, timeout,
		     pth_time (1, 0));
	}
    }
out:
  dreq.caddr = saddr;
  dreq.channel = channel;
  p = dreq.ToPacket ();
  sock->sendaddr = caddr;
  if (channel != -1)
    sock->Send (p);

  pth_event_free (stop, PTH_FREE_THIS);
  pth_event_free (input, PTH_FREE_THIS);
  pth_event_free (timeout, PTH_FREE_THIS);
  pth_event_free (timeout1, PTH_FREE_THIS);
}
Esempio n. 27
0
void
TPUARTLayer2Driver::Run (pth_sem_t * stop1)
{
  struct message m;
  int l;
  pth_event_t stop = pth_event (PTH_EVENT_SEM, stop1);
  pth_event_t input = pth_event (PTH_EVENT_SEM, &in_signal);
  while (pth_event_status (stop) != PTH_STATUS_OCCURRED)
    {
      pth_event_concat (stop, input, NULL);
      l = pth_read_ev (fd, &m, sizeof (m), stop);
      if (l >= 0)
	{
	  LPDU *l1;
	  if (m.length > sizeof (m.data))
	    m.length = sizeof (m.data);
	  t->TracePacket (0, this, "Recv", m.length, m.data);
	  if (vmode && mode == 0)
	    {
	      L_Busmonitor_PDU *l2 = new L_Busmonitor_PDU;
	      l2->pdu.set (m.data, m.length);
	      outqueue.put (l2);
	      pth_sem_inc (&out_signal, 1);
	    }
	  if (mode == 0)
	    l1 = LPDU::fromPacket (CArray (m.data, m.length));
	  else
	    {
	      l1 = new L_Busmonitor_PDU;
	      ((L_Busmonitor_PDU *) l1)->pdu.set (m.data, m.length);
	    }
	  outqueue.put (l1);
	  pth_sem_inc (&out_signal, 1);
	}
      pth_event_isolate (stop);
      if (!inqueue.isempty ())
	{
	  LPDU *l1 = inqueue.top ();
	  CArray c = l1->ToPacket ();
	  unsigned len = c ();
	  if (len > sizeof (m.data))
	    len = sizeof (m.data);
	  memcpy (m.data, c.array (), len);
	  m.length = len;
	  if (ver)
	    m.length--;
	  t->TracePacket (0, this, "Send", m.length, m.data);
	  l = pth_write_ev (fd, &m, sizeof (m), stop);
	  if (l >= 0)
	    {
	      if (vmode)
		{
		  L_Busmonitor_PDU *l2 = new L_Busmonitor_PDU;
		  l2->pdu.set (c);
		  outqueue.put (l2);
		  pth_sem_inc (&out_signal, 1);
		}
	      pth_sem_dec (&in_signal);
	      delete inqueue.get ();
	    }
	}
    }
  pth_event_free (stop, PTH_FREE_THIS);
  pth_event_free (input, PTH_FREE_THIS);
}
Esempio n. 28
0
int main(int argc, char *argv[])
{
    int i;
    sigset_t ss;
    int sig;
    pth_event_t ev;

    /* initialize Pth library */
    pth_init();

    /* display test program header */
    printf("This is TEST_PHILO, a Pth test showing the Five Dining Philosophers\n");
    printf("\n");
    printf("This is a demonstration showing the famous concurrency problem of the\n");
    printf("Five Dining Philosophers as analysed 1965 by E.W.Dijkstra:\n");
    printf("\n");
    printf("Five philosophers are sitting around a round table, each with a bowl of\n");
    printf("Chinese food in front of him. Between periods of talking they may start\n");
    printf("eating whenever they want to, with their bowls being filled frequently.\n");
    printf("But there are only five chopsticks available, one each to the left of\n");
    printf("each bowl - and for eating Chinese food one needs two chopsticks. When\n");
    printf("a philosopher wants to start eating, he must pick up the chopstick to\n");
    printf("the left of his bowl and the chopstick to the right of his bowl. He\n");
    printf("may find, however, that either one (or even both) of the chopsticks is\n");
    printf("unavailable as it is being used by another philosopher sitting on his\n");
    printf("right or left, so he has to wait.\n");
    printf("\n");
    printf("This situation shows classical contention under concurrency (the\n");
    printf("philosophers want to grab the chopsticks) and the possibility of a\n");
    printf("deadlock (all philosophers wait that the chopstick to their left becomes\n");
    printf("available).\n");
    printf("\n");
    printf("The demonstration runs max. 60 seconds. To stop before, press CTRL-C.\n");
    printf("\n");
    printf("+----P1----+----P2----+----P3----+----P4----+----P5----+\n");

    /* initialize the control table */
    tab = (table *)malloc(sizeof(table));
    if (!pth_mutex_init(&(tab->mutex))) {
        perror("pth_mutex_init");
        exit(1);
    }
    for (i = 0; i < PHILNUM; i++) {
        (tab->self)[i] = i;
        (tab->status)[i] = thinking;
        if (!pth_cond_init(&((tab->condition)[i]))) {
            perror("pth_cond_init");
            exit(1);
        }
    }

    /* spawn the philosopher threads */
    for (i = 0; i < PHILNUM; i++) {
        if (((tab->tid)[i] =
              pth_spawn(PTH_ATTR_DEFAULT, philosopher,
                        &((tab->self)[i]))) == NULL) {
            perror("pth_spawn");
            exit(1);
        }
    }

    /* wait until 60 seconds have elapsed or CTRL-C was pressed */
    sigemptyset(&ss);
    sigaddset(&ss, SIGINT);
    ev = pth_event(PTH_EVENT_TIME, pth_timeout(60,0));
    pth_sigwait_ev(&ss, &sig, ev);
    pth_event_free(ev, PTH_FREE_ALL);

    /* cancel and join the philosopher threads */
    for (i = 0; i < PHILNUM; i++)
        pth_cancel((tab->tid)[i]);
    while (pth_join(NULL, NULL));

    /* finish display */
    printf("+----------+----------+----------+----------+----------+\n");

    /* free the control table */
    free(tab);

    /* shutdown Pth library */
    pth_kill();

    return 0;
}
Esempio n. 29
0
/* Fork off the pin entry if this has not already been done.  Note,
   that this function must always be used to aquire the lock for the
   pinentry - we will serialize _all_ pinentry calls.
 */
static int
start_pinentry (ctrl_t ctrl)
{
  int rc;
  const char *pgmname;
  assuan_context_t ctx;
  const char *argv[5];
  int no_close_list[3];
  int i;
  pth_event_t evt;
  const char *tmpstr;
  unsigned long pinentry_pid;
  const char *value;

  evt = pth_event (PTH_EVENT_TIME, pth_timeout (LOCK_TIMEOUT, 0));
  if (!pth_mutex_acquire (&entry_lock, 0, evt))
    {
      if (pth_event_occurred (evt))
        rc = gpg_error (GPG_ERR_TIMEOUT);
      else
        rc = gpg_error (GPG_ERR_INTERNAL);
      pth_event_free (evt, PTH_FREE_THIS);
      log_error (_("failed to acquire the pinentry lock: %s\n"),
                 gpg_strerror (rc));
      return rc;
    }
  pth_event_free (evt, PTH_FREE_THIS);

  entry_owner = ctrl;

  if (entry_ctx)
    return 0; 

  if (opt.verbose)
    log_info ("starting a new PIN Entry\n");

#ifdef HAVE_W32_SYSTEM      
  fflush (stdout);
  fflush (stderr);
#endif
  if (fflush (NULL))
    {
#ifndef HAVE_W32_SYSTEM
      gpg_error_t tmperr = gpg_error (gpg_err_code_from_errno (errno));
#endif
      log_error ("error flushing pending output: %s\n", strerror (errno));
      /* At least Windows XP fails here with EBADF.  According to docs
         and Wine an fflush(NULL) is the same as _flushall.  However
         the Wime implementaion does not flush stdin,stdout and stderr
         - see above.  Lets try to ignore the error. */
#ifndef HAVE_W32_SYSTEM
      return unlock_pinentry (tmperr);
#endif
    }

  if (!opt.pinentry_program || !*opt.pinentry_program)
    opt.pinentry_program = gnupg_module_name (GNUPG_MODULE_NAME_PINENTRY);
    pgmname = opt.pinentry_program;
  if ( !(pgmname = strrchr (opt.pinentry_program, '/')))
    pgmname = opt.pinentry_program;
  else
    pgmname++;

  /* OS X needs the entire file name in argv[0], so that it can locate
     the resource bundle.  For other systems we stick to the usual
     convention of supplying only the name of the program.  */
#ifdef __APPLE__
  argv[0] = opt.pinentry_program;
#else /*!__APPLE__*/
  argv[0] = pgmname;
#endif /*__APPLE__*/

  if (!opt.keep_display
      && (value = session_env_getenv (ctrl->session_env, "DISPLAY")))
    {
      argv[1] = "--display";
      argv[2] = value;
      argv[3] = NULL;
    }
  else
    argv[1] = NULL;
  
  i=0;
  if (!opt.running_detached)
    {
      if (log_get_fd () != -1)
        no_close_list[i++] = assuan_fd_from_posix_fd (log_get_fd ());
      no_close_list[i++] = assuan_fd_from_posix_fd (fileno (stderr));
    }
  no_close_list[i] = -1;

  rc = assuan_new (&ctx);
  if (rc)
    {
      log_error ("can't allocate assuan context: %s\n", gpg_strerror (rc));
      return rc;
    }

  /* Connect to the pinentry and perform initial handshaking.  Note
     that atfork is used to change the environment for pinentry.  We
     start the server in detached mode to suppress the console window
     under Windows.  */
  rc = assuan_pipe_connect (ctx, opt.pinentry_program, argv,
			    no_close_list, atfork_cb, ctrl,
			    ASSUAN_PIPE_CONNECT_DETACHED);
  if (rc)
    {
      log_error ("can't connect to the PIN entry module: %s\n",
                 gpg_strerror (rc));
      assuan_release (ctx);
      return unlock_pinentry (gpg_error (GPG_ERR_NO_PIN_ENTRY));
    }
  entry_ctx = ctx;

  if (DBG_ASSUAN)
    log_debug ("connection to PIN entry established\n");

  rc = assuan_transact (entry_ctx, 
                        opt.no_grab? "OPTION no-grab":"OPTION grab",
                        NULL, NULL, NULL, NULL, NULL, NULL);
  if (rc)
    return unlock_pinentry (rc);

  value = session_env_getenv (ctrl->session_env, "GPG_TTY");
  if (value)
    {
      char *optstr;
      if (asprintf (&optstr, "OPTION ttyname=%s", value) < 0 )
	return unlock_pinentry (out_of_core ());
      rc = assuan_transact (entry_ctx, optstr, NULL, NULL, NULL, NULL, NULL,
			    NULL);
      xfree (optstr);
      if (rc)
	return unlock_pinentry (rc);
    }
  value = session_env_getenv (ctrl->session_env, "TERM");
  if (value)
    {
      char *optstr;
      if (asprintf (&optstr, "OPTION ttytype=%s", value) < 0 )
	return unlock_pinentry (out_of_core ());
      rc = assuan_transact (entry_ctx, optstr, NULL, NULL, NULL, NULL, NULL,
			    NULL);
      xfree (optstr);
      if (rc)
	return unlock_pinentry (rc);
    }
  if (ctrl->lc_ctype)
    {
      char *optstr;
      if (asprintf (&optstr, "OPTION lc-ctype=%s", ctrl->lc_ctype) < 0 )
	return unlock_pinentry (out_of_core ());
      rc = assuan_transact (entry_ctx, optstr, NULL, NULL, NULL, NULL, NULL,
			    NULL);
      xfree (optstr);
      if (rc)
	return unlock_pinentry (rc);
    }
  if (ctrl->lc_messages)
    {
      char *optstr;
      if (asprintf (&optstr, "OPTION lc-messages=%s", ctrl->lc_messages) < 0 )
	return unlock_pinentry (out_of_core ());
      rc = assuan_transact (entry_ctx, optstr, NULL, NULL, NULL, NULL, NULL,
			    NULL);
      xfree (optstr);
      if (rc)
	return unlock_pinentry (rc);
    }

  {
    /* Provide a few default strings for use by the pinentries.  This
       may help a pinentry to avoid implementing localization code.  */
    static struct { const char *key, *value; } tbl[] = {
      /* TRANSLATORS: These are labels for buttons etc used in
         Pinentries.  An underscore indicates that the next letter
         should be used as an accelerator.  Double the underscore for
         a literal one.  The actual to be translated text starts after
         the second vertical bar.  */
      { "ok",     N_("|pinentry-label|_OK") },
      { "cancel", N_("|pinentry-label|_Cancel") },
      { "prompt", N_("|pinentry-label|PIN:") },
      { NULL, NULL}
    };
    char *optstr;
    int idx;
    const char *s, *s2;

    for (idx=0; tbl[idx].key; idx++)
      {
        s = _(tbl[idx].value);
        if (*s == '|' && (s2=strchr (s+1,'|')))
          s = s2+1;
        if (asprintf (&optstr, "OPTION default-%s=%s", tbl[idx].key, s) < 0 )
          return unlock_pinentry (out_of_core ());
        assuan_transact (entry_ctx, optstr, NULL, NULL, NULL, NULL, NULL,
                         NULL);
        xfree (optstr);
      }
  }

  
  /* Tell the pinentry the name of a file it shall touch after having
     messed with the tty.  This is optional and only supported by
     newer pinentries and thus we do no error checking. */
  tmpstr = opt.pinentry_touch_file;
  if (tmpstr && !strcmp (tmpstr, "/dev/null"))
    tmpstr = NULL;
  else if (!tmpstr)
    tmpstr = get_agent_socket_name ();
  if (tmpstr)
    {
      char *optstr;
      
      if (asprintf (&optstr, "OPTION touch-file=%s", tmpstr ) < 0 )
        ;
      else
        {
          assuan_transact (entry_ctx, optstr, NULL, NULL, NULL, NULL, NULL,
                           NULL);
          xfree (optstr);
        }
    }


  /* Now ask the Pinentry for its PID.  If the Pinentry is new enough
     it will send the pid back and we will use an inquire to notify
     our client.  The client may answer the inquiry either with END or
     with CAN to cancel the pinentry. */
  rc = assuan_transact (entry_ctx, "GETINFO pid", 
                        getinfo_pid_cb, &pinentry_pid,
                        NULL, NULL, NULL, NULL);
  if (rc)
    {
      log_info ("You may want to update to a newer pinentry\n");
      rc = 0;
    }
  else if (!rc && (pid_t)pinentry_pid == (pid_t)(-1))
    log_error ("pinentry did not return a PID\n");
  else
    {
      rc = agent_inq_pinentry_launched (ctrl, pinentry_pid);
      if (gpg_err_code (rc) == GPG_ERR_CANCELED)
        return unlock_pinentry (gpg_error (GPG_ERR_CANCELED));
      rc = 0;
    }

  return 0;
}
Esempio n. 30
0
void
FT12LowLevelDriver::Run (pth_sem_t * stop1)
{
  CArray last;
  int i;
  uchar buf[255];

  pth_event_t stop = pth_event (PTH_EVENT_SEM, stop1);
  pth_event_t input = pth_event (PTH_EVENT_SEM, &in_signal);
  pth_event_t timeout = pth_event (PTH_EVENT_RTIME, pth_time (0, 100000));
  while (pth_event_status (stop) != PTH_STATUS_OCCURRED)
    {
      pth_event_isolate (input);
      pth_event_isolate (timeout);
      if (mode == 0)
	pth_event_concat (stop, input, NULL);
      if (mode == 1)
	pth_event_concat (stop, timeout, NULL);

      i = pth_read_ev (fd, buf, sizeof (buf), stop);
      if (i > 0)
	{
	  t->TracePacket (0, this, "Recv", i, buf);
	  akt.setpart (buf, akt (), i);
	}

      while (akt.len () > 0)
	{
	  if (akt[0] == 0xE5 && mode == 1)
	    {
	      pth_sem_dec (&in_signal);
	      inqueue.get ();
	      if (inqueue.isempty ())
		pth_sem_set_value (&send_empty, 1);
	      akt.deletepart (0, 1);
	      mode = 0;
	      repeatcount = 0;
	    }
	  else if (akt[0] == 0x10)
	    {
	      if (akt () < 4)
		break;
	      if (akt[1] == akt[2] && akt[3] == 0x16)
		{
		  uchar c1 = 0xE5;
		  t->TracePacket (0, this, "Send Ack", 1, &c1);
		  write (fd, &c1, 1);
		  if ((akt[1] == 0xF3 && !recvflag) ||
		      (akt[1] == 0xD3 && recvflag))
		    {
		      //right sequence number
		      recvflag = !recvflag;
		    }
		  if ((akt[1] & 0x0f) == 0)
		    {
		      const uchar reset[1] = { 0xA0 };
		      CArray *c = new CArray (reset, sizeof (reset));
		      t->TracePacket (0, this, "RecvReset", *c);
		      outqueue.put (c);
		      pth_sem_inc (&out_signal, TRUE);
		    }
		}
	      akt.deletepart (0, 4);
	    }
	  else if (akt[0] == 0x68)
	    {
	      int len;
	      uchar c1;
	      if (akt () < 7)
		break;
	      if (akt[1] != akt[2] || akt[3] != 0x68)
		{
		  //receive error, try to resume
		  akt.deletepart (0, 1);
		  continue;
		}
	      if (akt () < akt[1] + 6)
		break;

	      c1 = 0;
	      for (i = 4; i < akt[1] + 4; i++)
		c1 += akt[i];
	      if (akt[akt[1] + 4] != c1 || akt[akt[1] + 5] != 0x16)
		{
		  len = akt[1] + 6;
		  //Forget wrong short frame
		  akt.deletepart (0, len);
		  continue;
		}

	      c1 = 0xE5;
	      t->TracePacket (0, this, "Send Ack", 1, &c1);
	      i = write (fd, &c1, 1);

	      if ((akt[4] == 0xF3 && recvflag) ||
		  (akt[4] == 0xD3 && !recvflag))
		{
		  if (CArray (akt.array () + 5, akt[1] - 1) != last)
		    {
		      TRACEPRINTF (t, 0, this, "Sequence jump");
		      recvflag = !recvflag;
		    }
		  else
		    TRACEPRINTF (t, 0, this, "Wrong Sequence");
		}

	      if ((akt[4] == 0xF3 && !recvflag) ||
		  (akt[4] == 0xD3 && recvflag))
		{
		  recvflag = !recvflag;
		  CArray *c = new CArray;
		  len = akt[1] + 6;
		  c->setpart (akt.array () + 5, 0, len - 7);
		  last = *c;
		  outqueue.put (c);
		  pth_sem_inc (&out_signal, TRUE);
		}
	      akt.deletepart (0, len);
	    }
	  else
	    //Forget unknown byte
	    akt.deletepart (0, 1);
	}

      if (mode == 1 && pth_event_status (timeout) == PTH_STATUS_OCCURRED)
	mode = 0;

      if (mode == 0 && !inqueue.isempty ())
	{
	  const CArray & c = inqueue.top ();
	  t->TracePacket (0, this, "Send", c);
	  repeatcount++;
	  i = pth_write_ev (fd, c.array (), c (), stop);
	  if (i == c ())
	    {
	      mode = 1;
	      timeout =
		pth_event (PTH_EVENT_RTIME | PTH_MODE_REUSE, timeout,
			   pth_time (0, 100000));
	    }
	}
    }
  pth_event_free (stop, PTH_FREE_THIS);
  pth_event_free (timeout, PTH_FREE_THIS);
  pth_event_free (input, PTH_FREE_THIS);
}