Esempio n. 1
0
tsb_t *
get_tsb_ptr_by_name(char *name) {
  tsb_vector_el_t *tsb_ptr =
    search_vector(&Tsb_vector,
		(vector_search_func_t)tsb_name_compare, name);
  if(!tsb_ptr) {
    return NULL;
  }
  return *tsb_ptr;
}
/**
 * @fn            HRESULT receive_execute(struct CONN_BCAP_SERVER *bcap_param)
 * @brief         Receives the b-CAP packet and executes callback functions.
 * @param[in,out] bcap_param b-CAP communication object.
 */
static HRESULT
receive_execute(struct CONN_BCAP_SERVER *bcap_param)
{
  int index;
  int32_t relation_id;
  uint16_t i, clear_flag = 1;
  uint32_t cur, start, diff;
  HRESULT hr;
  struct CONN_BCAP_SERVER *tmp_param = bcap_param;
  struct CONN_PARAM_COMMON *device = &bcap_param->device;
  struct BCAP_PACKET tmp_send_packet, tmp_recv_packet, *send_packet =
      &bcap_param->last_send, *recv_packet = &bcap_param->last_recv;
  struct VEC_OBJECT *pObj = NULL;
  BSTR bstrOpt = NULL;
  VARIANT vntTmp, vntOpt;

  VariantInit(&vntTmp);
  VariantInit(&vntOpt);

  /* Initializes temporary packet */
  tmp_recv_packet.argc = (uint16_t) -1;
  tmp_recv_packet.args = NULL;

  /* Receives b-CAP packet */
  hr = bcap_recv(device, &tmp_recv_packet, 0);

  if(SUCCEEDED(hr)) {
    /* Sets S_EXECUTING packet */
    memset(&tmp_send_packet, 0, sizeof(struct BCAP_PACKET));
    tmp_send_packet.serial = tmp_recv_packet.serial;
    tmp_send_packet.id = S_EXECUTING;

    /* Checks retry packet */
    switch(device->type) {
      case CONN_UDP:
        tmp_param = search_node(bcap_param, device->arg,
            sizeof(struct sockaddr_in));
        if(tmp_param == NULL) {
          /* Checks life limit */
          if((bcap_param->num_child >= BCAP_CLIENT_MAX)
              && (check_lifelimit(bcap_param) >= BCAP_CLIENT_MAX))
          {
            tmp_send_packet.id = E_MAX_CONNECT;
            bcap_send(device, &tmp_send_packet);
            hr = S_FALSE;
            goto exit_proc;
          }

          /* Adds child */
          change_relation(bcap_param, ADD_CHILD, &device->sock);
          tmp_param = bcap_param->node1;
        }

        send_packet = &tmp_param->last_send;

        //break;

      case CONN_COM:
        /* Sets retry count */
        tmp_recv_packet.reserv =
            (tmp_recv_packet.reserv == 0) ?
                tmp_recv_packet.serial : tmp_recv_packet.reserv;

        /* If already responded, then does not execute */
        if(send_packet->serial == tmp_recv_packet.reserv) {
          /* Copies last send packet */
          tmp_send_packet = *send_packet;

          /* Sets new serial number */
          tmp_send_packet.serial = tmp_recv_packet.serial;

          /* Sends temporary send packet */
          bcap_send(device, &tmp_send_packet);
          hr = S_FALSE;
          goto exit_proc;
        }  

        break;

      default:
        break;
    }

    /* Checks execute thread */
    hr = wait_event(&bcap_param->comp_evt, 0);
    if(hr == E_TIMEOUT) {
      /* Sends result busy process */
      tmp_send_packet.id = E_BUSY_PROC;
      bcap_send(device, &tmp_send_packet);
      goto exit_proc;
    }

    switch(tmp_recv_packet.id) {
      case ID_SERVICE_START:
      case ID_CONTROLLER_CONNECT:
      case ID_CONTROLLER_GETEXTENSION:
      case ID_CONTROLLER_GETFILE:
      case ID_FILE_GETFILE:
      case ID_CONTROLLER_GETROBOT:
      case ID_CONTROLLER_GETTASK:
      case ID_CONTROLLER_GETVARIABLE:
      case ID_EXTENSION_GETVARIABLE:
      case ID_FILE_GETVARIABLE:
      case ID_ROBOT_GETVARIABLE:
      case ID_TASK_GETVARIABLE:
      case ID_CONTROLLER_GETCOMMAND:
      case ID_CONTROLLER_GETMESSAGE:
        if(bcap_param->num_object >= BCAP_OBJECT_MAX) {
          tmp_send_packet.id = E_MAX_OBJECT;
          bcap_send(device, &tmp_send_packet);
          hr = S_FALSE;
          goto exit_proc;
        }

        if(tmp_recv_packet.id == ID_SERVICE_START) {
          if((tmp_recv_packet.argc >= 1) && (tmp_recv_packet.args != NULL)) {
            VariantCopy(&vntTmp, &tmp_recv_packet.args[0]);
            hr = VariantChangeType(&vntTmp, &vntTmp, 0, VT_BSTR);
            if(FAILED(hr)) {
              tmp_send_packet.id = hr;
              bcap_send(device, &tmp_send_packet);
              hr = S_FALSE;
              goto exit_proc;
            }
          } else {
            vntTmp.vt = VT_BSTR;
            vntTmp.bstrVal = SysAllocString(L"");
          }

          bstrOpt = SysAllocString(L"WDT");
          hr = GetOptionValue(vntTmp.bstrVal, bstrOpt, VT_UI4, &vntOpt);
          vntOpt.ulVal =
              (vntOpt.vt == VT_UI4) ? vntOpt.ulVal : INIT_WDT_INTERVAL;
          if(vntOpt.ulVal < MIN_WDT_INTERVAL) {
            tmp_send_packet.id = E_INVALIDARG;
            bcap_send(device, &tmp_send_packet);
            hr = S_FALSE;
            goto exit_proc;
          } else {
            tmp_param->wdt_interval = vntOpt.ulVal;
          }
          SysFreeString(bstrOpt);
          VariantClear(&vntOpt);

          bstrOpt = SysAllocString(L"InvokeTimeout");
          hr = GetOptionValue(vntTmp.bstrVal, bstrOpt, VT_UI4, &vntOpt);
          vntOpt.ulVal =
              (vntOpt.vt == VT_UI4) ? vntOpt.ulVal : INIT_EXEC_TIMEOUT;
          if(vntOpt.ulVal < MIN_WDT_INTERVAL) {
            tmp_send_packet.id = E_INVALIDARG;
            bcap_send(device, &tmp_send_packet);
            hr = S_FALSE;
            goto exit_proc;
          } else {
            tmp_param->exec_timeout = vntOpt.ulVal;
          }
          SysFreeString(bstrOpt);
          VariantClear(&vntOpt);

          VariantClear(&vntTmp);
          bstrOpt = NULL;
        }

        break;

      default:
        break;
    }

    /* Resets last received packet */
    if(recv_packet->args != NULL) {
      for(i = 0; i < recv_packet->argc; i++) {
        VariantClear(&recv_packet->args[i]);
      }
      free(recv_packet->args);
    }

    /* Copies to last receive packet */
    clear_flag = 0;
    *recv_packet = tmp_recv_packet;

    /* Runs execute thread */
    reset_event(&bcap_param->comp_evt);
    set_event(&bcap_param->exec_evt);

    if(SUCCEEDED(hr)) {
      start = gettimeofday_msec();
      while(1) {
        hr = wait_event(&bcap_param->comp_evt, tmp_param->wdt_interval);
        if(SUCCEEDED(hr)) {
          break;
        } else {
          /* Sends S_EXECUTING packet */
          hr = bcap_send(device, &tmp_send_packet);
          if(FAILED(hr)) {
            break;
          }
        }

        /* Checks executing timeout */
        cur = gettimeofday_msec();
        diff = calc_time_diff(start, cur);
        if(diff > tmp_param->exec_timeout) {
          hr = E_TIMEOUT;
          break;
        }
      }
    }
  }

exit_proc:
  if(hr == S_OK) {
    if(bcap_param->last_send.id == S_OK) {
      /* Changes the vector of created objects */
      relation_id = m_map_id[recv_packet->id].relation_id;
      if(relation_id > 0) { // Push
        pObj = (struct VEC_OBJECT *) malloc(sizeof(struct VEC_OBJECT));
        if(pObj != NULL) {
          memset(pObj, 0, sizeof(struct VEC_OBJECT));
          pObj->id = relation_id;
          pObj->hObj =
              (recv_packet->id == ID_SERVICE_START) ?
                  0 : bcap_param->last_send.args[0].lVal;
          push_vector(bcap_param, pObj);
        }
      }
      else if(relation_id < 0) { // Pop
        index = search_vector(bcap_param, recv_packet->id,
          (recv_packet->id == ID_SERVICE_STOP) ?
              0 : recv_packet->args[0].lVal);
        if(index >= 0) {
          pop_vector(bcap_param, &pObj, index);
          free(pObj);
        }
        if((device->type == CONN_UDP)
          && (recv_packet->id == ID_SERVICE_STOP))
        {
          change_relation(tmp_param, DESTROY_SELF, NULL);
          change_relation(bcap_param, DELETE_CHILD, NULL);
          tmp_param = NULL;
        }
      }
    }

    /* Responds the result message */
    hr = bcap_send(device, &bcap_param->last_send);
    if(SUCCEEDED(hr) && (tmp_param != NULL)) {
        tmp_param->last_send.serial = bcap_param->last_send.serial;
        tmp_param->last_send.reserv = bcap_param->last_send.reserv;
        tmp_param->last_send.id     = bcap_param->last_send.id;
        tmp_param->last_send.argc   = bcap_param->last_send.argc;
        VariantCopy(tmp_param->last_send.args, bcap_param->last_send.args);

        tmp_param->last_modified = gettimeofday_msec();
    }
  }

  /* Clears temporary packet */
  if(clear_flag) {
    if(tmp_recv_packet.args != NULL) {
      for(i = 0; i < tmp_recv_packet.argc; i++) {
        VariantClear(&tmp_recv_packet.args[i]);
      }
      free(tmp_recv_packet.args);
    }
  }

  VariantClear(&vntTmp);
  VariantClear(&vntOpt);
  if(bstrOpt) {
    SysFreeString(bstrOpt);
  }

  return hr;
}