void er_dtls_connection_start(ErDtlsConnection *self, gboolean is_client)
{
    g_return_if_fail(ER_IS_DTLS_CONNECTION(self));
    ErDtlsConnectionPrivate *priv = self->priv;
    g_return_if_fail(priv->send_closure);
    g_return_if_fail(priv->ssl);
    g_return_if_fail(priv->bio);

    LOG_TRACE(self, "locking @ start");
    g_mutex_lock(&priv->mutex);
    LOG_TRACE(self, "locked @ start");

    priv->is_alive = TRUE;
    priv->timeout_set = FALSE;
    priv->bio_buffer = NULL;
    priv->bio_buffer_len = 0;
    priv->bio_buffer_offset = 0;
    priv->keys_exported = FALSE;

    priv->is_client = is_client;
    if (priv->is_client) {
        SSL_set_connect_state(priv->ssl);
    } else {
        SSL_set_accept_state(priv->ssl);
    }
    log_state(self, "initial state set");

    openssl_poll(self);

    log_state(self, "first poll done");
    priv->thread = NULL;

    LOG_TRACE(self, "unlocking @ start");
    g_mutex_unlock(&priv->mutex);
}
static void
handle_timeout (gpointer data, gpointer user_data)
{
  GstDtlsConnection *self = user_data;
  GstDtlsConnectionPrivate *priv;
  gint ret;

  priv = self->priv;

  g_mutex_lock (&priv->mutex);
  priv->timeout_pending = FALSE;
  if (priv->is_alive) {
    ret = DTLSv1_handle_timeout (priv->ssl);

    GST_DEBUG_OBJECT (self, "handle timeout returned %d, is_alive: %d", ret,
        priv->is_alive);

    if (ret < 0) {
      GST_WARNING_OBJECT (self, "handling timeout failed");
    } else if (ret > 0) {
      log_state (self, "handling timeout before poll");
      openssl_poll (self);
      log_state (self, "handling timeout after poll");
    }
  }
  g_mutex_unlock (&priv->mutex);
}
static gpointer connection_timeout_thread_func(ErDtlsConnection *self)
{
    ErDtlsConnectionPrivate *priv = self->priv;
    struct timeval timeout;
    gint64 end_time, wait_time;
    gint ret;

    while (priv->is_alive) {
        LOG_TRACE(self, "locking @ timeout");
        g_mutex_lock(&priv->mutex);
        LOG_TRACE(self, "locked @ timeout");

        if (DTLSv1_get_timeout(priv->ssl, &timeout)) {
            wait_time = timeout.tv_sec * G_USEC_PER_SEC + timeout.tv_usec;

            if (wait_time) {
                LOG_DEBUG(self, "waiting for %" G_GINT64_FORMAT " usec", wait_time);

                end_time = g_get_monotonic_time() + wait_time;

                LOG_TRACE(self, "wait @ timeout");
                g_cond_wait_until(&priv->condition, &priv->mutex, end_time);
                LOG_TRACE(self, "continued @ timeout");
            }

            ret = DTLSv1_handle_timeout(priv->ssl);

            LOG_DEBUG(self, "handle timeout returned %d, is_alive: %d", ret, priv->is_alive);

            if (ret < 0) {
                LOG_TRACE(self, "unlocking @ timeout failed");
                g_mutex_unlock(&priv->mutex);
                break; /* self failed after DTLS1_TMO_ALERT_COUNT (12) attempts */
            }

            if (ret > 0) {
                log_state(self, "handling timeout before poll");
                openssl_poll(self);
                log_state(self, "handling timeout after poll");
            }
        } else {
            LOG_DEBUG(self, "waiting indefinitely");

            priv->timeout_set = FALSE;

            while (!priv->timeout_set && priv->is_alive) {
                LOG_TRACE(self, "wait @ timeout");
                g_cond_wait(&priv->condition, &priv->mutex);
            }
            LOG_TRACE(self, "continued @ timeout");
        }

        LOG_TRACE(self, "unlocking @ timeout");
        g_mutex_unlock(&priv->mutex);
    }

    log_state(self, "timeout thread exiting");

    return NULL;
}
Exemple #4
0
static snd_pcm_state_t try_recover(ALSA_CARD *card, int err,
						unsigned char *buffer) {
	// attempt card recovery if error encountered during capture
	snd_pcm_state_t state;
	log_state(card);
	int ret = snd_pcm_recover(card->handle, err, 1);
	log_msg("ALSA: snd_pcm_recover: %s [%d]\n", snd_strerror(ret), ret);
	snd_pcm_readi(card->handle, buffer, card->blocksize);
	state = log_state(card);
	log_msg("ALSA: continue capture...\n");
	return state;
	}
static void openssl_poll(ErDtlsConnection *self)
{
    int ret;
    char buf[512];
    int error;

    log_state(self, "poll: before handshake");

    ret = SSL_do_handshake(self->priv->ssl);

    log_state(self, "poll: after handshake");

    if (ret == 1) {
        if (!self->priv->keys_exported) {
            LOG_INFO(self, "handshake just completed successfully, exporting keys");
            export_srtp_keys(self);
        } else {
            LOG_INFO(self, "handshake is completed");
        }
        return;
    } else {
        if (ret == 0) {
            LOG_DEBUG(self, "do_handshake encountered EOF");
        } else if (ret == -1) {
            LOG_WARNING(self, "do_handshake encountered BIO error");
        } else {
            LOG_DEBUG(self, "do_handshake returned %d", ret);
        }
    }

    error = SSL_get_error(self->priv->ssl, ret);

    switch (error) {
    case SSL_ERROR_NONE:
        LOG_WARNING(self, "no error, handshake should be done");
        break;
    case SSL_ERROR_SSL:
        LOG_LOG(self, "SSL error %d: %s", error, ERR_error_string(ERR_get_error(), buf));
        break;
    case SSL_ERROR_WANT_READ:
        LOG_LOG(self, "SSL wants read");
        break;
    case SSL_ERROR_WANT_WRITE:
        LOG_LOG(self, "SSL wants write");
        break;
    case SSL_ERROR_SYSCALL: {
        LOG_LOG(self, "SSL syscall (error) : %lu", ERR_get_error());
        break;
    }
    default:
        LOG_WARNING(self, "Unknown SSL error: %d, ret: %d", error, ret);
    }
}
static uint8_t NormalState_handleIR(  uint8_t cmdCode )
{

#if (MONO_COLOR_CLOCK != 1)
  if( UI_NORMAL_MODE == cmdCode){
    ++(g_params->curColorProfile);
    g_params->curColorProfile %=  UI_COLOR_PRESET_COUNT;
    NormalState_enter((void*)1);
  }else if( UI_CHANGE_R == cmdCode ){
    log_state("CR\n");
    mode_normalState.colorToSet = 0;
  }else if( UI_CHANGE_G == cmdCode ){
    log_state("CG\n");
    mode_normalState.colorToSet = 1;
  }else if( UI_CHANGE_B == cmdCode ){
    log_state("CB\n");
    mode_normalState.colorToSet = 2;
  }else if( UI_CHANGE_HUE == cmdCode ){
    log_state("CH\n");
    mode_normalState.colorToSet = 4;

  }else if(    UI_UP == cmdCode
            || UI_DOWN == cmdCode)
  {
    log_state("CC\n");
    int8_t dir = UI_UP == cmdCode?1:-1;
    if( mode_normalState.colorToSet < 4 ){  // handle RGB-Changes
      uint8_t* rgb = (uint8_t*)(&g_params->colorPresets[ g_params->curColorProfile ]);
      incDecRange(&rgb[ mode_normalState.colorToSet ], dir,0,  MAX_PWM_STEPS-1);
      pwm_set_color_step( rgb[0], rgb[1], rgb[2] );
    }else{     // handle HUE-Changes
      uint8_t r,g,b;
      if( dir<0 && mode_normalState.curHue < HUE_MANUAL_STEPS ){
        mode_normalState.curHue = HUE_MAX;
      }else if( dir>0 && mode_normalState.curHue >= HUE_MAX-HUE_MANUAL_STEPS){
        mode_normalState.curHue = 0;
      }else{
        mode_normalState.curHue += dir*HUE_MANUAL_STEPS;
      }
      hue2rgb(mode_normalState.curHue, &r, &g, &b);
      SetPWMs(r,g,b);
    }
  }else

#endif
  {
    return FALSE;
  }

  return TRUE;
}
static void SetSystemTimeState_enter( const void* param )
{
  log_state("SST\n");
  addSubState(MS_setSystemTime, MS_enterTime,  &g_dateTime );
  mode_setSystemTimeState.prohibitLeave = TRUE;

}
static void er_dtls_connection_set_property(GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec)
{
    ErDtlsConnection *self = ER_DTLS_CONNECTION(object);
    ErDtlsAgent *agent;
    ErDtlsConnectionPrivate *priv = self->priv;
    SSL_CTX *ssl_context;

    switch (prop_id) {
    case PROP_AGENT:
        g_return_if_fail(!priv->ssl);
        agent = ER_DTLS_AGENT(g_value_get_object(value));
        g_return_if_fail(ER_IS_DTLS_AGENT(agent));

        ssl_context = _er_dtls_agent_peek_context(agent);

        priv->ssl = SSL_new(ssl_context);
        g_return_if_fail(priv->ssl);

        priv->bio = BIO_new(BIO_s_er_dtls_connection());
        g_return_if_fail(priv->bio);

        priv->bio->ptr = self;
        SSL_set_bio(priv->ssl, priv->bio, priv->bio);

        SSL_set_verify(priv->ssl,
            SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT, openssl_verify_callback);
        SSL_set_ex_data(priv->ssl, connection_ex_index, self);

        log_state(self, "connection created");
        break;
    default:
        G_OBJECT_WARN_INVALID_PROPERTY_ID(self, prop_id, pspec);
    }
}
gint
gst_dtls_connection_process (GstDtlsConnection * self, gpointer data, gint len)
{
  GstDtlsConnectionPrivate *priv;
  gint result;

  g_return_val_if_fail (GST_IS_DTLS_CONNECTION (self), 0);
  g_return_val_if_fail (self->priv->ssl, 0);
  g_return_val_if_fail (self->priv->bio, 0);

  priv = self->priv;

  GST_TRACE_OBJECT (self, "locking @ process");
  g_mutex_lock (&priv->mutex);
  GST_TRACE_OBJECT (self, "locked @ process");

  g_warn_if_fail (!priv->bio_buffer);

  priv->bio_buffer = data;
  priv->bio_buffer_len = len;
  priv->bio_buffer_offset = 0;

  log_state (self, "process start");

  if (SSL_want_write (priv->ssl)) {
    openssl_poll (self);
    log_state (self, "process want write, after poll");
  }

  result = SSL_read (priv->ssl, data, len);

  log_state (self, "process after read");

  openssl_poll (self);

  log_state (self, "process after poll");

  GST_DEBUG_OBJECT (self, "read result: %d", result);

  GST_TRACE_OBJECT (self, "unlocking @ process");
  g_mutex_unlock (&priv->mutex);

  return result;
}
static void ShowNumberState_enter( const void* param )
{
  DisplayState dispData;
  uint8_t paramSN = (uint8_t)((uint16_t)param);  /* double cast to avoid warning */
  log_state( "enter showNumber\n");
  mode_showNumberState.delay100ms = USER_NORMAL_SHOW_NUMBER_DELAY_100ms;

  dispData = display_getNumberDisplayState(paramSN);
  display_setDisplayState(dispData, 0);
}
static uint8_t EnterTimeState_handleIr(  uint8_t cmdCode )
{
  uint8_t caller = g_stateStack[ g_currentIdxs[MS_enterTime] - 1];
  if(    (   (MS_setSystemTime == caller) 
          && (UI_SET_TIME      == cmdCode))
      || (   (MS_setOnOffTime    == caller) 
          && (UI_SET_ONOFF_TIMES == cmdCode)))
  {
    if( ETS_hour == mode_enterTimeState.curSubState ){
      log_time("TM\n");
      mode_enterTimeState.curSubState = ETS_minutes;
    }else if( ETS_minutes == mode_enterTimeState.curSubState){
      log_time("TS\n");
      mode_enterTimeState.time.ss = 0;
      mode_enterTimeState.prohibitLeave = FALSE;
      pwm_release_brightness();
      quitMyself(MS_enterTime, &(mode_enterTimeState.time));
      return TRUE;
    }
  }else if(    UI_UP   == cmdCode
            || UI_DOWN == cmdCode)
  {
    log_state("CHS\n");
    int8_t dir = UI_UP == cmdCode?1:-1;
    if( ETS_hour == mode_enterTimeState.curSubState )
    {
      incDecRangeOverflow(&(mode_enterTimeState.time.hh), dir, 23);
      if(   mode_enterTimeState.time.hh >=USER_ENTERTIME_DAY_NIGHT_CHANGE_HOUR 
         && mode_enterTimeState.time.hh < USER_ENTERTIME_DAY_NIGHT_CHANGE_HOUR+12 )
      {
        pwm_lock_brightness_val(USER_ENTERTIME_DAY_BRIGHTNESS);
      }else{
        pwm_lock_brightness_val(USER_ENTERTIME_NIGHT_BRIGHTNESS);
      }
    }else if( ETS_minutes == mode_enterTimeState.curSubState){
      if( MS_setOnOffTime == caller ){
        dir *= USER_ENTER_ONOFF_TIME_STEP;
      }
      incDecRangeOverflow(&(mode_enterTimeState.time.mm), dir, 59);
    }

  }else{
    //return FALSE;
  }
  dispInternalTime(&mode_enterTimeState.time, 
                   ((ETS_hour == mode_enterTimeState.curSubState)
                    ? display_getHoursMask()
                    : display_getMinuteMask()
                    ) | display_getTimeSetIndicatorMask()) ;

  return TRUE;
}
Exemple #12
0
/**
 * @brief Makes the given state to quit itself
 *
 * This will invoke leaveSubState() on the current index of the given mode
 * (g_currentIdxs). It will then reset the display state, and invoke
 * UserState_SubstateFinished() on the "parent" of the state just left.
 *
 * This is expected to be used on states that have fulfilled their actual task,
 * and want to hand over control to the "parent" again.
 *
 * @param state The state that should leave itself
 * @param result Result to be handed over to the "parent", might be NULL
 *
 * @see leaveSubState()
 * @see g_currentIdxs
 * @see UserState_SubstateFinished()
 */
void quitMyself(menu_state_t state, const void* result)
{

    bool success;
    int8_t currentIdx = g_currentIdxs[state];

    log_state("quit self\n");

    success = leaveSubState(currentIdx);

    if (!success) {

        log_state("ERROR: leaving substates failed\n");

    }

    dispInternalTime(datetime_get(), 0);
    UserState_SubstateFinished(g_stateStack[currentIdx - 1], state, result);

    log_state("quit self finished\n");

}
Exemple #13
0
rust_port::~rust_port() {
    task->log(rust_log::COMM | rust_log::MEM,
              "~rust_port 0x%" PRIxPTR, (uintptr_t) this);

    log_state();

    // Disassociate channels from this port.
    while (chans.is_empty() == false) {
        rust_chan *chan = chans.peek();
        chan->disassociate();
    }

    delete remote_channel;
}
Exemple #14
0
/**
 * @brief Adds a substate to a specific state
 *
 * A substate can be understood as a state, which in a way is related to its
 * "parent", e.g. MS_enterTime can be a substate of MS_setSystemTime.
 *
 * Only a single substate for each parent can be entered at any given point in
 * time. Therefore this function will try to leave any previously entered
 * substates, before actually entering the given substate itself. The added
 * substate will take up place on the actual stack itself - as it is handled
 * quite similar to a normal state.
 *
 * Passing "-1" as value for the first parameter (curState) this function can
 * be used to replace the "base" state itself (the state at the very bottom).
 * Every state on top of it will then be left - if possible.
 *
 * @param curState The parent of the substate that should be added, -1 for base
 * @param mode The substate that should be added
 * @param param Any parameter for the given state, might be NULL
 *
 * @see g_currentIdxs
 * @see leaveSubState()
 * @see addState()
 */
void addSubState(int8_t curState, menu_state_t mode, const void* param)
{

    bool success = true;
    int8_t nextIdx;

    if (curState == -1) {

        nextIdx = 0;
        log_state("replace Base state\n");

    } else {

        nextIdx = g_currentIdxs[curState] + 1;

    }

    log_state("addSubstate\n");

    if (nextIdx != g_topOfStack) {

        success = leaveSubState(nextIdx);

    }

    if (success) {

        addState(mode, param);

    } else {

        log_state("ERROR: leaving substates failed\n");

    }

}
static void SetOnOffTimeState_enter( const void* param )
{
  DATETIME dt = {0,0,0,0,0,0,0};
  dt.hh = g_params->autoOffTimes[0].h;
  dt.mm = g_params->autoOffTimes[0].m;

  log_state("SOOT\n");
  mode_setOnOffTimeState.currentTimeToSet = 0;
  
  addSubState(MS_setOnOffTime
             , MS_enterTime
             , &dt);
  mode_setOnOffTimeState.prohibitLeave = TRUE;

}
void
gst_dtls_connection_start (GstDtlsConnection * self, gboolean is_client)
{
  GstDtlsConnectionPrivate *priv;

  priv = self->priv;

  g_return_if_fail (priv->send_closure);
  g_return_if_fail (priv->ssl);
  g_return_if_fail (priv->bio);

  GST_TRACE_OBJECT (self, "locking @ start");
  g_mutex_lock (&priv->mutex);
  GST_TRACE_OBJECT (self, "locked @ start");

  priv->is_alive = TRUE;
  priv->bio_buffer = NULL;
  priv->bio_buffer_len = 0;
  priv->bio_buffer_offset = 0;
  priv->keys_exported = FALSE;

  priv->is_client = is_client;
  if (priv->is_client) {
    SSL_set_connect_state (priv->ssl);
  } else {
    SSL_set_accept_state (priv->ssl);
  }
  log_state (self, "initial state set");

  openssl_poll (self);

  log_state (self, "first poll done");

  GST_TRACE_OBJECT (self, "unlocking @ start");
  g_mutex_unlock (&priv->mutex);
}
static void NormalState_enter( const void* param )
{
  log_state("nm\n");

#if (MONO_COLOR_CLOCK != 1)
  pwm_set_color_step( g_params->colorPresets[g_params->curColorProfile].r,
                      g_params->colorPresets[g_params->curColorProfile].g,
                      g_params->colorPresets[g_params->curColorProfile].b);
  if( ((uint16_t)param) != 0 ){
    addSubState(MS_normalMode, MS_showNumber, (void*)(((uint16_t)g_params->curColorProfile+1)) ); /* doulbe cast to avoid warning */
  }
#else
  dispInternalTime( &g_dateTime,  0);  // force update of display (in multicolor this is done on substate exit)
#endif
}
Exemple #18
0
/**
 * @brief Leaves the state at the given stack position
 *
 * First of all this function will check whether the given state and all states
 * on top of it can actually be left or whether leaving one of them is
 * currently prohibited (UserState_prohibitLeave()). If it is possible to leave
 * all of these states, it will invoke UserState_LeaveState() on each of them
 * and the function will return true. If at least one state can't be left,
 * nothing happens at all and the function simply returns false.
 *
 * @param indexOfStateToLeave Stack position of state to leave
 *
 * @return Indicates whether or not the given state was left
 *
 * @see UserState_prohibitLeave()
 * @see UserState_LeaveState()
 */
bool leaveSubState(int8_t indexOfStateToLeave)
{

    int8_t i;
    bool success = true;

    log_state("leaving substates: ");

    for (i = g_topOfStack - 1; i >= indexOfStateToLeave; --i) {

        bool canLeave = !UserState_prohibitLeave(g_stateStack[i]);
        success &= canLeave;

        #if (LOG_USER_STATE == 1)

        {

            char buff[5];

            sprintf_P(buff, fmt_output_unsigned_decimal, g_stateStack[i]);
            uart_puts(buff);
            uart_putc(':');
            uart_putc(canLeave ? 'y' : 'n');
            uart_puts_P(", ");

        }

        #endif

    }

    if (success) {

        for (i = g_topOfStack - 1; i >= indexOfStateToLeave; --i) {

            UserState_LeaveState(g_stateStack[i]);
            --g_topOfStack;

            PRINT_STATE_STACK();

        }

    }

    return success;

}
Exemple #19
0
/**
 * @brief Adds a state on top of the stack
 *
 * This adds the given state (mode) to the stack, when the state was not
 * already put there before. It will update all variables dealing with the
 * state of the stack itself.
 *
 * Regardless of whether or not the given state was already put on the stack
 * beforehand, it will execute UserState_enter() with the given parameter.
 *
 * @param mode The state to add
 * @param param Any parameter for the given state, might also be NULL
 *
 * @see g_stateStack
 * @see g_topOfStack
 * @see g_currentIdxs
 * @see UserState_enter()
 */
void addState(menu_state_t mode, const void* param)
{

    log_state("addstate\n");

    if ((g_topOfStack == 0) || (user_get_current_menu_state() != mode)) {

        g_stateStack[g_topOfStack] = mode;
        g_currentIdxs[mode] = g_topOfStack;
        ++g_topOfStack;

    }

    UserState_enter(mode, param);

    PRINT_STATE_STACK();

}
Exemple #20
0
/**
 * Checks for simple deadlocks.
 */
bool
rust_dom::is_deadlocked() {
    if (_live_domains.size() != 1) {
        // We cannot tell if we are deadlocked if other domains exists.
        return false;
    }

    if (running_tasks.length() != 0) {
        // We are making progress and therefore we are not deadlocked.
        return false;
    }

    if (_incoming_message_queue.is_empty() && blocked_tasks.length() > 0) {
        // We have no messages to process, no running tasks to schedule
        // and some blocked tasks therefore we are likely in a deadlock.
        log_state();
        return true;
    }

    return false;
}
static uint8_t PulseState_handleIR(  uint8_t cmdCode )
{
  if(    UI_UP == cmdCode
      || UI_DOWN == cmdCode)
  {
    log_state("CPS \n");
    int8_t dir = UI_UP == cmdCode?-1:1;
    incDecRange(    &g_params->pulseUpdateInterval
                  , dir
                  , USER_PULSE_CHANGE_INT_10ms_MIN
                  , USER_PULSE_CHANGE_INT_10ms_MAX);
#if (USER_LOG_STATE == 1)
    uart_putc('0' + g_params->pulseUpdateInterval);
#endif
  }else{
    return FALSE;
  }
   
  return TRUE;

}
Exemple #22
0
/**
 * Starts the main scheduler loop which performs task scheduling for this
 * domain.
 *
 * Returns once no more tasks can be scheduled and all task ref_counts
 * drop to zero.
 */
int
rust_scheduler::start_main_loop(int id) {
    kernel->scheduler_lock.lock();

    // Make sure someone is watching, to pull us out of infinite loops.
    //
    // FIXME: time-based interruption is not presently working; worked
    // in rustboot and has been completely broken in rustc.
    //
    // rust_timer timer(this);

    DLOG(this, dom, "started domain loop %d", id);

    while (number_of_live_tasks() > 0) {
        A(this, kernel->is_deadlocked() == false, "deadlock");

        DLOG(this, dom, "worker %d, number_of_live_tasks = %d",
             id, number_of_live_tasks());

        drain_incoming_message_queue(true);

        rust_task *scheduled_task = schedule_task(id);

        // The scheduler busy waits until a task is available for scheduling.
        // Eventually we'll want a smarter way to do this, perhaps sleep
        // for a minimum amount of time.

        if (scheduled_task == NULL) {
            log_state();
            DLOG(this, task,
                 "all tasks are blocked, scheduler id %d yielding ...",
                 id);
            kernel->scheduler_lock.unlock();
            sync::sleep(100);
            kernel->scheduler_lock.lock();
            DLOG(this, task,
                "scheduler resuming ...");
            continue;
        }

        I(this, scheduled_task->running());

        DLOG(this, task,
            "activating task %s 0x%" PRIxPTR
            ", sp=0x%" PRIxPTR
            ", ref_count=%d"
            ", state: %s",
            scheduled_task->name,
            (uintptr_t)scheduled_task,
            scheduled_task->rust_sp,
            scheduled_task->ref_count,
            scheduled_task->state->name);

        interrupt_flag = 0;

        DLOG(this, task,
             "Running task %p on worker %d",
             scheduled_task, id);
        scheduled_task->running_on = id;
        activate(scheduled_task);
        scheduled_task->running_on = -1;

        DLOG(this, task,
             "returned from task %s @0x%" PRIxPTR
             " in state '%s', sp=0x%x, worker id=%d" PRIxPTR,
             scheduled_task->name,
             (uintptr_t)scheduled_task,
             scheduled_task->state->name,
             scheduled_task->rust_sp,
             id);

        reap_dead_tasks(id);
    }

    DLOG(this, dom,
         "terminated scheduler loop, reaping dead tasks ...");

    while (dead_tasks.length() > 0) {
        if (message_queue->is_empty()) {
            DLOG(this, dom,
                "waiting for %d dead tasks to become dereferenced, "
                "scheduler yielding ...",
                dead_tasks.length());
            log_state();
            kernel->scheduler_lock.unlock();
            sync::yield();
            kernel->scheduler_lock.lock();
        } else {
            drain_incoming_message_queue(true);
        }
        reap_dead_tasks(id);
    }

    DLOG(this, dom, "finished main-loop %d (dom.rval = %d)", id, rval);

    kernel->scheduler_lock.unlock();
    return rval;
}
Exemple #23
0
/**
 * Starts the main scheduler loop which performs task scheduling for this
 * domain.
 *
 * Returns once no more tasks can be scheduled and all task ref_counts
 * drop to zero.
 */
int
rust_dom::start_main_loop()
{
    // Make sure someone is watching, to pull us out of infinite loops.
    rust_timer timer(this);

    log(rust_log::DOM, "running main-loop on domain %s @0x%" PRIxPTR,
        name, this);
    logptr("exit-task glue", root_crate->get_exit_task_glue());

    while (n_live_tasks() > 0) {
        A(this, is_deadlocked() == false, "deadlock");

        drain_incoming_message_queue(true);

        rust_task *scheduled_task = schedule_task();

        // The scheduler busy waits until a task is available for scheduling.
        // Eventually we'll want a smarter way to do this, perhaps sleep
        // for a minimum amount of time.

        if (scheduled_task == NULL) {
            if (_log.is_tracing(rust_log::TASK)) {
                log_state();
            }
            log(rust_log::TASK,
                "all tasks are blocked, scheduler yielding ...");
            sync::yield();
            log(rust_log::TASK,
                "scheduler resuming ...");
            continue;
        }

        I(this, scheduled_task->running());

        log(rust_log::TASK,
            "activating task %s 0x%" PRIxPTR
            ", sp=0x%" PRIxPTR
            ", ref_count=%d"
            ", state: %s",
            scheduled_task->name,
            (uintptr_t)scheduled_task,
            scheduled_task->rust_sp,
            scheduled_task->ref_count,
            scheduled_task->state_str());

        interrupt_flag = 0;

        activate(scheduled_task);

        log(rust_log::TASK,
                 "returned from task %s @0x%" PRIxPTR
                 " in state '%s', sp=0x%" PRIxPTR,
                 scheduled_task->name,
                 (uintptr_t)scheduled_task,
                 state_vec_name(scheduled_task->state),
                 scheduled_task->rust_sp);

        I(this, scheduled_task->rust_sp >=
          (uintptr_t) &scheduled_task->stk->data[0]);
        I(this, scheduled_task->rust_sp < scheduled_task->stk->limit);

        reap_dead_tasks();
    }

    log(rust_log::DOM, "terminated scheduler loop, reaping dead tasks ...");

    while (dead_tasks.length() > 0) {
        if (_incoming_message_queue.is_empty()) {
            log(rust_log::DOM,
                "waiting for %d dead tasks to become dereferenced, "
                "scheduler yielding ...",
                dead_tasks.length());
            if (_log.is_tracing(rust_log::TASK)) {
                log_state();
            }
            sync::yield();
        } else {
            drain_incoming_message_queue(true);
        }
        reap_dead_tasks();
    }

    log(rust_log::DOM, "finished main-loop (dom.rval = %d)", rval);
    return rval;
}
Exemple #24
0
/**
 * @name expand_node
 *
 * Create the states that are attached to this one.  Check to see that
 * each one has not already been visited.  If not add it to the priority
 * queue.
 */
void Wordrec::expand_node(FLOAT32 worst_priority,
                          CHUNKS_RECORD *chunks_record,
                          SEARCH_RECORD *the_search) {
  STATE old_state;
  int x;
  uinT32 mask = 1 << (the_search->num_joints - 1 - 32);

  old_state.part1 = the_search->this_state->part1;
  old_state.part2 = the_search->this_state->part2;

  // We need to expand the search more intelligently, or we get stuck
  // with a bad starting segmentation in a long word sequence as in CJK.
  // Expand a child node only if it is within the global bound, and no
  // worse than 2x of its parent.
  // TODO(dsl): There is some redudency here in recomputing the priority,
  // and in filtering of old_merit and worst_priority.
  the_search->this_state->part2 = old_state.part2;
  for (x = the_search->num_joints; x > 32; x--) {
    the_search->this_state->part1 = mask ^ old_state.part1;
    if (!hash_lookup (the_search->closed_states, the_search->this_state)) {
      FLOAT32 new_merit = prioritize_state(chunks_record, the_search);
      if (new_merit < worst_priority) {
        if (wordrec_debug_level > 1)
          log_state("Pushing segstate", the_search->num_joints,
                    the_search->this_state, new_merit);
        push_queue(the_search->open_states, the_search->this_state,
                   worst_priority, new_merit, wordrec_debug_level > 1);
      } else {
        if (wordrec_debug_level > 1)
          log_state("Ignore weak segstate", the_search->num_joints,
                    the_search->this_state, new_merit);
      }
    }
    mask >>= 1;
  }

  if (the_search->num_joints > 32) {
    mask = 1 << 31;
  }
  else {
    mask = 1 << (the_search->num_joints - 1);
  }

  the_search->this_state->part1 = old_state.part1;
  while (x--) {
    the_search->this_state->part2 = mask ^ old_state.part2;
    if (!hash_lookup (the_search->closed_states, the_search->this_state)) {
      FLOAT32 new_merit = prioritize_state(chunks_record, the_search);
      if (new_merit < worst_priority) {
        if (wordrec_debug_level > 1)
          log_state("Pushing segstate", the_search->num_joints,
                    the_search->this_state, new_merit);
        push_queue(the_search->open_states, the_search->this_state,
                   worst_priority, new_merit, wordrec_debug_level > 1);
      } else {
        if (wordrec_debug_level > 1)
          log_state("Ignoring weak segstate", the_search->num_joints,
                    the_search->this_state, new_merit);
      }
    }
    mask >>= 1;
  }
}
Exemple #25
0
rust_sched_loop_state
rust_sched_loop::run_single_turn() {
    DLOG(this, task,
         "scheduler %d resuming ...", id);

    lock.lock();

    if (!should_exit) {
        assert(dead_task == NULL && "Tasks should only die after running");

        DLOG(this, dom, "worker %d, number_of_live_tasks = %d",
             id, number_of_live_tasks());

        rust_task *scheduled_task = schedule_task();

        if (scheduled_task == NULL) {
            log_state();
            DLOG(this, task,
                 "all tasks are blocked, scheduler id %d yielding ...",
                 id);

            lock.unlock();
            return sched_loop_state_block;
        }

        scheduled_task->assert_is_running();

        DLOG(this, task,
             "activating task %s 0x%" PRIxPTR
             ", state: %s",
             scheduled_task->name,
             (uintptr_t)scheduled_task,
             state_name(scheduled_task->get_state()));

        place_task_in_tls(scheduled_task);

        DLOG(this, task,
             "Running task %p on worker %d",
             scheduled_task, id);
        activate(scheduled_task);

        DLOG(this, task,
             "returned from task %s @0x%" PRIxPTR
             " in state '%s', worker id=%d" PRIxPTR,
             scheduled_task->name,
             (uintptr_t)scheduled_task,
             state_name(scheduled_task->get_state()),
             id);

        reap_dead_tasks();

        lock.unlock();
        return sched_loop_state_keep_going;
    } else {
        assert(running_tasks.is_empty() && "Should have no running tasks");
        assert(blocked_tasks.is_empty() && "Should have no blocked tasks");
        assert(dead_task == NULL && "Should have no dead tasks");

        DLOG(this, dom, "finished main-loop %d", id);

        lock.unlock();

        assert(!extra_c_stack);
        if (cached_c_stack) {
            destroy_exchange_stack(kernel->region(), cached_c_stack);
            cached_c_stack = NULL;
        }
        assert(!extra_big_stack);
        if (cached_big_stack) {
            destroy_exchange_stack(kernel->region(), cached_big_stack);
            cached_big_stack = NULL;
        }

        sched->release_task_thread();
        return sched_loop_state_exit;
    }
}
Exemple #26
0
/**
 * @name evaluate_state
 *
 * Evaluate the segmentation that is represented by this state in the
 * best first search.  Add this state to the "states_seen" list.
 */
inT16 Wordrec::evaluate_state(CHUNKS_RECORD *chunks_record,
                              SEARCH_RECORD *the_search,
                              DANGERR *fixpt,
                              BlamerBundle *blamer_bundle) {
  BLOB_CHOICE_LIST_VECTOR *char_choices;
  SEARCH_STATE chunk_groups;
  float rating_limit = the_search->best_choice->rating();
  bool keep_going = true;
  PIECES_STATE widths;

  the_search->num_states++;
  chunk_groups = bin_to_chunks(the_search->this_state,
                               the_search->num_joints);
  bin_to_pieces (the_search->this_state, the_search->num_joints, widths);
  if (wordrec_debug_level > 1) {
    log_state("Evaluating state", the_search->num_joints,
              the_search->this_state);
  }
  getDict().LogNewSegmentation(widths);

  char_choices = evaluate_chunks(chunks_record, chunk_groups, blamer_bundle);
  getDict().SetWordsegRatingAdjustFactor(-1.0f);
  bool updated_best_choice = false;
  if (char_choices != NULL && char_choices->length() > 0) {
    // Compute the segmentation cost and include the cost in word rating.
    // TODO(dsl): We should change the SEARCH_RECORD to store this cost
    // from state evaluation and avoid recomputing it here.
    prioritize_state(chunks_record, the_search);
    getDict().SetWordsegRatingAdjustFactor(the_search->segcost_bias);
    updated_best_choice =
      getDict().permute_characters(*char_choices,
                                   the_search->best_choice,
                                   the_search->raw_choice);
    bool replaced = false;
    if (updated_best_choice) {
      if (getDict().AcceptableChoice(char_choices, the_search->best_choice,
                                     NULL, ASSOCIATOR_CALLER, &replaced)) {
        keep_going = false;
      }
      CopyCharChoices(*char_choices, the_search->best_char_choices);
    }
  }
  getDict().SetWordsegRatingAdjustFactor(-1.0f);

#ifndef GRAPHICS_DISABLED
  if (wordrec_display_segmentations) {
    display_segmentation (chunks_record->chunks, chunk_groups);
    if (wordrec_display_segmentations > 1)
      window_wait(segm_window);
  }
#endif

  if (rating_limit != the_search->best_choice->rating()) {
    ASSERT_HOST(updated_best_choice);
    the_search->before_best = the_search->num_states;
    the_search->best_state->part1 = the_search->this_state->part1;
    the_search->best_state->part2 = the_search->this_state->part2;
    replace_char_widths(chunks_record, chunk_groups);
  } else {
    ASSERT_HOST(!updated_best_choice);
    if (char_choices != NULL) fixpt->clear();
  }

  if (char_choices != NULL) delete char_choices;
  memfree(chunk_groups);

  return (keep_going);
}
static void
openssl_poll (GstDtlsConnection * self)
{
  int ret;
  int error;

  log_state (self, "poll: before handshake");

  ERR_clear_error ();
  ret = SSL_do_handshake (self->priv->ssl);

  log_state (self, "poll: after handshake");

  switch (ret) {
    case 1:
      if (!self->priv->keys_exported) {
        GST_INFO_OBJECT (self,
            "handshake just completed successfully, exporting keys");
        export_srtp_keys (self);
      } else {
        GST_INFO_OBJECT (self, "handshake is completed");
      }
      return;
    case 0:
      GST_DEBUG_OBJECT (self, "do_handshake encountered EOF");
      break;
    case -1:
      GST_DEBUG_OBJECT (self, "do_handshake encountered BIO error");
      break;
    default:
      GST_DEBUG_OBJECT (self, "do_handshake returned %d", ret);
  }

  error = SSL_get_error (self->priv->ssl, ret);

  switch (error) {
    case SSL_ERROR_NONE:
      GST_WARNING_OBJECT (self, "no error, handshake should be done");
      break;
    case SSL_ERROR_SSL:
      GST_ERROR_OBJECT (self, "SSL error");
      ERR_print_errors_cb (ssl_err_cb, self);
      return;
    case SSL_ERROR_WANT_READ:
      GST_LOG_OBJECT (self, "SSL wants read");
      break;
    case SSL_ERROR_WANT_WRITE:
      GST_LOG_OBJECT (self, "SSL wants write");
      break;
    case SSL_ERROR_SYSCALL:{
      gchar message[1024] = "<unknown>";
      gint syserror;
#ifdef G_OS_WIN32
      syserror = WSAGetLastError ();
      FormatMessage (FORMAT_MESSAGE_FROM_SYSTEM, NULL, syserror, 0, message,
          sizeof message, NULL);
#else
      syserror = errno;
      strerror_r (syserror, message, sizeof message);
#endif
      GST_CAT_LEVEL_LOG (GST_CAT_DEFAULT,
          syserror != 0 ? GST_LEVEL_WARNING : GST_LEVEL_LOG,
          self, "SSL syscall error: errno %d: %s", syserror, message);
      break;
    }
    default:
      GST_WARNING_OBJECT (self, "Unknown SSL error: %d, ret: %d", error, ret);
  }

  ERR_print_errors_cb (ssl_warn_cb, self);
}
static void TrainIrState_enter( const void* param )
{
  log_state( "enter train\n");
  display_setDisplayState( display_getIndicatorMask(), display_getIndicatorMask() );
}
void main()
{
	system_init(buffer, sizeof(buffer), buffer, sizeof(buffer));
#if RF == CC1101 || RF == CC1120
	spi_init();
#endif

	ResetRadioCore();
	int p = ReadSingleReg(PARTNUM);
	log_print_string("PARTNUM 0x%x", p);
	p = ReadSingleReg(VERSION);
	log_print_string("VERSION 0x%x", p);
	log_print_string("started");

	WriteRfSettings(&rfSettings);
//	WriteSingleReg(IOCFG2,0x0B);    //GDO2 Output Pin Configuration
//	WriteSingleReg(IOCFG0,0x0C);    //GDO0 Output Pin Configuration
//	WriteSingleReg(FIFOTHR,0x47);   //RX FIFO and TX FIFO Thresholds
//	WriteSingleReg(PKTCTRL0,0x22);  //Packet Automation Control
//	WriteSingleReg(FSCTRL1,0x08);   //Frequency Synthesizer Control
//	WriteSingleReg(FREQ2,0x10);     //Frequency Control Word, High Byte
//	WriteSingleReg(FREQ1,0xB1);     //Frequency Control Word, Middle Byte
//	WriteSingleReg(FREQ0,0x3A);     //Frequency Control Word, Low Byte
//	WriteSingleReg(MDMCFG4,0xCA);   //Modem Configuration
//	WriteSingleReg(MDMCFG3,0x83);   //Modem Configuration
//	WriteSingleReg(MDMCFG2,0xB0);   //Modem Configuration
//	WriteSingleReg(DEVIATN,0x35);   //Modem Deviation Setting
//	WriteSingleReg(MCSM0,0x18);     //Main Radio Control State Machine Configuration
//	WriteSingleReg(FOCCFG,0x16);    //Frequency Offset Compensation Configuration
//	WriteSingleReg(AGCCTRL2,0x43);  //AGC Control
//	WriteSingleReg(WORCTRL,0xFB);   //Wake On Radio Control
//	WriteSingleReg(FREND0,0x11);    //Front End TX Configuration
//	WriteSingleReg(FSCAL3,0xE9);    //Frequency Synthesizer Calibration
//	WriteSingleReg(FSCAL2,0x2A);    //Frequency Synthesizer Calibration
//	WriteSingleReg(FSCAL1,0x00);    //Frequency Synthesizer Calibration
//	WriteSingleReg(FSCAL0,0x1F);    //Frequency Synthesizer Calibration
//	WriteSingleReg(TEST2,0x81);     //Various Test Settings
//	WriteSingleReg(TEST1,0x35);     //Various Test Settings
//	WriteSingleReg(TEST0,0x09);     //Various Test Settings
//	WriteSingleReg(RSSI,0x80);      //Received Signal Strength Indication
//	WriteSingleReg(MARCSTATE,0x01); //Main Radio Control State Machine State
//	WriteSingleReg(VCO_VC_DAC,0x94);//Current Setting from PLL Calibration Module

	//phy_keep_radio_on(true);

	Strobe(RF_SIDLE);
	Strobe(RF_SFTX);

	//uint8_t spectrum_id[2] = { 4, 0 };
	//phy_translate_and_set_settings(spectrum_id, 0);

	//set_length_infinite(false);
	//WriteSingleReg(PKTLEN, 7);

	Strobe(RF_STX);

	//WriteSingleReg(PKTCTRL0, 0x22);

	//WriteSingleReg(FIFOTHR, RADIO_FIFOTHR_FIFO_THR_17_48);

	//WriteBurstReg(RF_TXFIFOWR, packet, 7);




	/*
	ResetRadioCore();
	log_state();
	Strobe(RF_SIDLE);
	WriteRfSettings(&rfSettings);
	log_print_string("wrote settings");
	log_state();
	Strobe(RF_STX);
	log_print_string("strobed TX");
	*/

	int i;
	for(i = 0; i < 50;i++)
	{
		log_state();
	}



	while(1);
}
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nShowCmd) {
    HANDLE cld_r, cld_w2, cld_w;
    STARTUPINFO sinfo;
    enum fresh_states fstate = FRESH_PRE;
    AV_UPD_STATUS st = {UPD_CHECK, 0, 0, 0, L"", 0};
    DWORD dw;
    struct my_f spam;
    char command[8192], *ptr;
    int updated_files = 0, customok = 0, mindefs = 0, customonly = 0;
    char *cmdl = GetCommandLineA();

    //DebugBreak();
    mindefs = (cmdl && strstr(cmdl, " --mindefs=1"));
	customonly = (cmdl && strstr(cmdl, " --customsigonly"));

    /* Locate myself */
    dw = GetModuleFileName(NULL, datadir, sizeof(datadir));
    if(!dw || dw >= sizeof(datadir)-2)
	return 10;
    ptr = strrchr(datadir, '\\');
    if(!ptr)
	return 10;
    *ptr = '\0';

    /* Log file */
    flog_open(datadir);

    /* Connect to master */
    updpipe = CreateFile("\\\\.\\pipe\\IMMUNET_AVUPDATE", GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_FLAG_OVERLAPPED, NULL);
    if(updpipe == INVALID_HANDLE_VALUE) {
	flog("ERROR: failed to connect pipe");
	flog_close();
	return 10;
    }
    dw = PIPE_READMODE_MESSAGE;
    if(!SetNamedPipeHandleState(updpipe, &dw, NULL, NULL)) {
	CloseHandle(updpipe);
	flog("ERROR: failed to set pipe to message mode");
    	flog_close();
	return 10;
    }
    if(!(write_event = CreateEvent(NULL, TRUE, FALSE, NULL))) {
	CloseHandle(updpipe);
	flog("ERROR: failed to create write event");
	flog_close();
	return 10;
    }

    /* Run local-only-hack freshclam */
    _snprintf(command, sizeof(command)-1, "freshclam.exe --update-db=custom --quiet --config-file=\"%s\\freshclam.conf\" --datadir=\"%s\"", datadir, datadir);
    command[sizeof(command)-1] = '\0';
    memset(&sinfo, 0, sizeof(sinfo));
    sinfo.cb = sizeof(sinfo);
    sinfo.dwFlags = STARTF_FORCEOFFFEEDBACK;
    if(!CreateProcess(NULL, command, NULL, NULL, TRUE, DETACHED_PROCESS, NULL, datadir, &sinfo, &pinfo)) {
	flog("ERROR: failed to execute '%s'", command);
	SENDFAIL_AND_QUIT(UPD_CHECK);
    }
    CloseHandle(pinfo.hThread);
    if(WaitForSingleObject(pinfo.hProcess, 60*1000) == WAIT_TIMEOUT) {
	TerminateProcess(pinfo.hProcess, 1338);
	flog("ERROR: timeout waiting for custom freshclam");
	SENDFAIL_AND_QUIT(UPD_CHECK);
    }
    if(!GetExitCodeProcess(pinfo.hProcess, &dw)) {
	CloseHandle(pinfo.hProcess);
	flog("ERROR: failed to retrieve custom freshclam return code");
	SENDFAIL_AND_QUIT(UPD_CHECK);
    }
    CloseHandle(pinfo.hProcess);
    if(dw == 0)
	customok = 1;
    else
	flog("INFO: custom freshclam return code: %u", dw);

    /* Early exit for custom only */
    if(customonly) {
        if(dw == 0) 
            SENDMSG_AND_RETURN(UPD_DONE, dw);
        else
            SENDMSG_AND_RETURN(UPD_ABORT, dw);
    }

    /* Make pipe for freshclam stdio */
    if(!CreatePipe(&cld_r, &cld_w, NULL, 0)) {
	flog("ERROR: failed to create pipe");
	SENDFAIL_AND_QUIT(UPD_CHECK);
    }

    if(!DuplicateHandle(GetCurrentProcess(), cld_w, GetCurrentProcess(), &cld_w2, 0, TRUE, DUPLICATE_SAME_ACCESS)) {
	CloseHandle(cld_r);
	CloseHandle(cld_w);
	flog("ERROR: failed to duplicate pipe");
	SENDFAIL_AND_QUIT(UPD_CHECK);
    }
    CloseHandle(cld_w);

    /* init my_fgets */
    init_myf(&spam, cld_r);

    /* Redir freshclam stdio */
    memset(&sinfo, 0, sizeof(sinfo));
    sinfo.cb = sizeof(sinfo);
    sinfo.hStdInput = GetStdHandle(STD_INPUT_HANDLE);
    sinfo.hStdOutput = cld_w2;
    sinfo.hStdError = cld_w2;
    sinfo.dwFlags = STARTF_FORCEOFFFEEDBACK|STARTF_USESTDHANDLES;

    /* Run main freshclam */
    _snprintf(command, sizeof(command)-1, "freshclam.exe --stdout --config-file=\"%s\\freshclam.conf\" --datadir=\"%s\"%s", datadir, datadir, mindefs ? " --update-db=daily" : "");
    command[sizeof(command)-1] = '\0';
    if(!CreateProcess(NULL, command, NULL, NULL, TRUE, DETACHED_PROCESS, NULL, datadir, &sinfo, &pinfo)) {
	CloseHandle(cld_w2);
	CloseHandle(cld_r);
	flog("ERROR: failed to execute '%s'", command);
	SENDFAIL_AND_QUIT(UPD_CHECK);
    }
	st.pid = pinfo.dwProcessId;
    CloseHandle(pinfo.hThread);
    CloseHandle(cld_w2);

    flog_dbg("Executing '%s'", command);

    /* Create STOP watcher */
    if(!CreateThread(NULL, 0, watch_stop, NULL, 0, &dw)) {
	flog("ERROR: failed to create watch_stop thread");
	CloseHandle(cld_r);
	CloseHandle(pinfo.hProcess);
	SENDFAIL_AND_QUIT(UPD_CHECK);
    }

    log_state(fstate);
    /* Spam parsing */
    while(1) {
	char *buf;
	buf = my_fgets(&spam);
	flog_dbg("GOT: %s", buf);
	if(!buf)
	    break;

	if(fstate == FRESH_PRE && !strncmp(buf, FRESH_PRE_START_S, sizeof(FRESH_PRE_START_S)-1)) {
	    SENDOK(UPD_CHECK);
	    fstate = FRESH_IDLE;
	    log_state(fstate);
	    continue;
	}

	if((fstate == FRESH_IDLE || fstate == FRESH_DOWN) && !strncmp(buf, FRESH_DOWN_S, sizeof(FRESH_DOWN_S)-1)) {
	    unsigned int pct, fnamelen;
	    char *partname = buf + 12, *partend, *pctend;

	    wchar_t nuname[AV_UPD_FILE_NAME_MAX];

	    if(!updated_files) {
		SENDOK(UPD_NEWER_FOUND);
		SENDOK(UPD_DOWNLOAD_BEGIN);
	    }
	    updated_files++;
	    partend = strchr(partname, ' ');
	    if(!partend)
		break;
	    *partend = '\0';
	    fnamelen = partend - partname;
	    partend = strchr(partend + 1, '[');
	    if(!partend)
		break;
	    partend++;
	    pct = strtol(partend, &pctend, 10);
	    if(pctend == partend || *pctend != '%')
		break;
	    fnamelen = MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, partname, (fnamelen < AV_UPD_FILE_NAME_MAX-1) ? fnamelen : AV_UPD_FILE_NAME_MAX-1, nuname, sizeof(nuname));
	    if(!fnamelen)
		break;
	    nuname[fnamelen] = L'\0';
	    if(fstate == FRESH_DOWN && wcscmp(nuname, st.fileName)) {
		st.percentDownloaded = 100;
		SENDOK(UPD_FILE_COMPLETE);
		fstate = FRESH_IDLE;
		log_state(fstate);
	    }
	    if(fstate == FRESH_IDLE) {
		wcscpy(st.fileName, nuname);
		st.percentDownloaded = 0;
		SENDOK(UPD_FILE_BEGIN);
		fstate = FRESH_DOWN;
		log_state(fstate);
	    }
	    st.percentDownloaded = pct;
	    SENDOK(UPD_FILE_PROGRESS);
	    continue;
	}

	if(fstate == FRESH_IDLE) {
	    if(strstr(buf, FRESH_UPTODATE_S))
		continue;
	    if(!strncmp(buf, FRESH_DONE_S, sizeof(FRESH_DONE_S) - 1)) {
		fstate = FRESH_RELOAD;
		log_state(fstate);
		continue;
	    }
	}
	if(fstate == FRESH_DOWN) {
	    if(!strcmp(buf, FRESH_DOWN_FAIL_S)) {
		flog("ERROR: sigcheck verification failed");
#if 0
		// FIXME: ask prashant
		send_pipe(&st, UPD_FILE_COMPLETE, 1);
#else
		SENDOK(UPD_FILE_COMPLETE);
#endif
		fstate = FRESH_IDLE;
		log_state(fstate);
		continue;
	    }
	    if(strstr(buf, FRESH_UPDATED_S)) {
		SENDOK(UPD_FILE_COMPLETE);
		fstate = FRESH_IDLE;
		log_state(fstate);
		continue;
	    }
	    if(strlen(buf) > sizeof(FRESH_DOWN_S)-1 && strstr(buf, FRESH_DOWN_S)) 
		continue;
	}
    }
    CloseHandle(cld_r);
    WaitForSingleObject(pinfo.hProcess, 30*1000);
    if(!GetExitCodeProcess(pinfo.hProcess, &dw)) {
	CloseHandle(pinfo.hProcess);
	flog("ERROR: failed to retrieve freshclam return code");
	SENDFAIL_AND_QUIT(UPD_ABORT);
    }
    CloseHandle(pinfo.hProcess);
    if(dw) {
	if(dw == STILL_ACTIVE) {
	    flog("WARNING: freshclam didn't exit, killing it...");
	    kill_freshclam();
	} else
	    flog("ERROR: freshclam exit code %u", dw);
	if(st.state == UPD_CHECK)
	    st.state = UPD_ABORT;
	SENDMSG_AND_RETURN(st.state, dw);
    }
    if((updated_files && fstate != FRESH_RELOAD) || (!updated_files && fstate != FRESH_IDLE)) {
	flog("ERROR: log parse failure. Freshclam exit value: %u", dw);
	SENDFAIL_AND_QUIT(st.state);
    }

    /* Send complete fin seq */
    if(updated_files) {
	SENDOK(UPD_DOWNLOAD_COMPLETE);
	SENDOK(UPD_INSTALL_BEGIN);
	SENDOK(UPD_INSTALL_COMPLETE);
	SENDOK(UPD_DONE);
    } else
	SENDOK(UPD_NONE);

    CloseHandle(updpipe);
    CloseHandle(write_event);
    flog_close();
    return 0;
}