Beispiel #1
0
int nx_eventhandler(NXHANDLE handle)
{
  FAR struct nxfe_conn_s *conn = (FAR struct nxfe_conn_s *)handle;
  struct nxsvrmsg_s      *msg;
  struct nxbe_window_s   *wnd;
  uint8_t                 buffer[NX_MXCLIMSGLEN];
  int                     nbytes;

  /* Get the next message from our incoming message queue */

  do
    {
      nbytes = mq_receive(conn->crdmq, buffer, NX_MXCLIMSGLEN, 0);
      if (nbytes < 0)
        {
          /* EINTR is not an error.  The wait was interrupted by a signal and
           * we just need to try reading again.
           */

          if (errno != EINTR)
            {
              if (errno == EAGAIN)
                {
                  /* EAGAIN is not an error.  It occurs because the MQ is opened with
                   * O_NONBLOCK and there is no message available now.
                   */

                  return OK;
                }
              else
                {
                  gdbg("mq_receive failed: %d\n", errno);
                  return ERROR;
                }
            }
        }
    }
  while (nbytes < 0);

  DEBUGASSERT(nbytes >= sizeof(struct nxclimsg_s));

  /* Dispatch the message appropriately */

  msg = (struct nxsvrmsg_s *)buffer;
  gvdbg("Received msgid=%d\n", msg->msgid);
  switch (msg->msgid)
    {
    case NX_CLIMSG_CONNECTED:
      nx_connected(conn);
      break;

    case NX_CLIMSG_DISCONNECTED:
      nx_disconnected(conn);
      errno = EHOSTDOWN;
      return ERROR;

    case NX_CLIMSG_REDRAW:
      {
        FAR struct nxclimsg_redraw_s *redraw = (FAR struct nxclimsg_redraw_s *)buffer;
        wnd = redraw->wnd;
        DEBUGASSERT(wnd);
        if (wnd->cb->redraw)
          {
            wnd->cb->redraw((NXWINDOW)wnd, &redraw->rect, redraw->more, wnd->arg);
          }
      }
      break;

    case NX_CLIMSG_NEWPOSITION:
      {
        FAR struct nxclimsg_newposition_s *postn = (FAR struct nxclimsg_newposition_s *)buffer;
        wnd = postn->wnd;
        DEBUGASSERT(wnd);
        if (wnd->cb->position)
          {
            wnd->cb->position((NXWINDOW)wnd, &postn->size, &postn->pos, &postn->bounds, wnd->arg);
          }
      }
      break;

#ifdef CONFIG_NX_MOUSE
    case NX_CLIMSG_MOUSEIN:
      {
        FAR struct nxclimsg_mousein_s *mouse = (FAR struct nxclimsg_mousein_s *)buffer;
        wnd = mouse->wnd;
        DEBUGASSERT(wnd);
        if (wnd->cb->mousein)
          {
            wnd->cb->mousein((NXWINDOW)wnd, &mouse->pos, mouse->buttons, wnd->arg);
          }
        }
      break;
#endif

#ifdef CONFIG_NX_KBD
    case NX_CLIMSG_KBDIN:
      {
        FAR struct nxclimsg_kbdin_s *kbd = (FAR struct nxclimsg_kbdin_s *)buffer;
        wnd = kbd->wnd;
        DEBUGASSERT(wnd);
        if (wnd->cb->kbdin)
          {
            wnd->cb->kbdin((NXWINDOW)wnd, kbd->nch, kbd->ch, wnd->arg);
          }
        }
      break;
#endif

    case NX_CLIMSG_BLOCKED:
      {
        FAR struct nxclimsg_blocked_s *blocked = (FAR struct nxclimsg_blocked_s *)buffer;
        wnd = blocked->wnd;
        DEBUGASSERT(wnd);
        if (wnd->cb->blocked)
          {
            wnd->cb->blocked((NXWINDOW)wnd, wnd->arg, blocked->arg);
          }
        }
      break;

    default:
      gdbg("Unrecognized message opcode: %d\n", ((FAR struct nxsvrmsg_s *)buffer)->msgid);
      break;
    }

  return OK;
}
Beispiel #2
0
int modlib_depend(FAR struct module_s *importer, FAR struct module_s *exporter)
{
#if CONFIG_MODLIB_MAXDEPEND > 0
  int freendx;
  int i;

  DEBUGASSERT(importer != NULL && exporter != NULL);

  /* First checker if the exported is already in our list if dependencies.
   * This would happen if we are importing multiple symbols from the same
   * exporting module.  In that case, the module would already be in the
   * list of dependencies.
   *
   * The list dependency list is a a dumb, upacked array of pointers.  This
   * should not be too inefficient if the number of CONFIG_MODLIB_MAXDEPEND
   * is small.  Otherwise, a more dynamic data structure would be in order.
   */

  for (i = 0, freendx = -1; i < CONFIG_MODLIB_MAXDEPEND; i++)
    {
      FAR const struct module_s *modp;

      /* Check if this dependency slot is available. */

      modp = importer->dependencies[i];
      if (modp == NULL)
        {
          /* Remember this slot for use the module is NOT already in the
           * list of dependencies.
           */

          freendx = i;
        }
      else if (modp == exporter)
        {
          /* Yes, we are already importing symbols from this module.  Nothing
           * more needs to be done.
           */

          return OK;
        }
    }

  /* If we get here, then (1) this is a new exporting module that does not
   * already appear in the list of dependencies, and (2) freendx is the
   * index to the last free slot in the dependency list.  If freendx is
   * negative, then the dependency list is full.
   */

  if (freendx >= 0)
    {
      /* Increment the count of dependencies on the exporter module */

      DEBUGASSERT(exporter->dependents < UINT8_MAX);
      if (exporter->dependents >= UINT8_MAX)
        {
          return -ENOSPC;
        }

      exporter->dependents++;

      /* And remember the exporter so that we can decrement the count of
       * dependents if the importer is removed.
       */

       DEBUGASSERT(importer->dependencies[freendx] == NULL);
       importer->dependencies[freendx] = exporter;
       return OK;
    }

  /* If we get there then the list of dependencies is full. */

  DEBUGPANIC();
  return -ENFILE;

#else
  return OK;
#endif
}
Beispiel #3
0
int pthread_cond_timedwait(FAR pthread_cond_t *cond, FAR pthread_mutex_t *mutex,
                           FAR const struct timespec *abstime)
{
    FAR struct tcb_s *rtcb = (FAR struct tcb_s *)g_readytorun.head;
    int ticks;
    int mypid = (int)getpid();
    irqstate_t int_state;
    int ret = OK;
    int status;

    sdbg("cond=0x%p mutex=0x%p abstime=0x%p\n", cond, mutex, abstime);

    DEBUGASSERT(rtcb->waitdog == NULL);

    /* Make sure that non-NULL references were provided. */

    if (!cond || !mutex)
    {
        ret = EINVAL;
    }

    /* Make sure that the caller holds the mutex */

    else if (mutex->pid != mypid)
    {
        ret = EPERM;
    }

    /* If no wait time is provided, this function degenerates to
     * the same behavior as pthread_cond_wait().
     */

    else if (!abstime)
    {
        ret = pthread_cond_wait(cond, mutex);
    }

    else
    {
        /* Create a watchdog */

        rtcb->waitdog = wd_create();
        if (!rtcb->waitdog)
        {
            ret = EINVAL;
        }
        else
        {
            sdbg("Give up mutex...\n");

            /* We must disable pre-emption and interrupts here so that
             * the time stays valid until the wait begins.   This adds
             * complexity because we assure that interrupts and
             * pre-emption are re-enabled correctly.
             */

            sched_lock();
            int_state = irqsave();

            /* Convert the timespec to clock ticks.  We must disable pre-emption
             * here so that this time stays valid until the wait begins.
             */

            ret = clock_abstime2ticks(CLOCK_REALTIME, abstime, &ticks);
            if (ret)
            {
                /* Restore interrupts  (pre-emption will be enabled when
                 * we fall through the if/then/else
                 */

                irqrestore(int_state);
            }
            else
            {
                /* Check the absolute time to wait.  If it is now or in the past, then
                 * just return with the timedout condition.
                 */

                if (ticks <= 0)
                {
                    /* Restore interrupts and indicate that we have already timed out.
                     * (pre-emption will be enabled when we fall through the
                     * if/then/else
                     */

                    irqrestore(int_state);
                    ret = ETIMEDOUT;
                }
                else
                {
                    /* Give up the mutex */

                    mutex->pid = 0;
                    ret = pthread_givesemaphore((sem_t*)&mutex->sem);
                    if (ret)
                    {
                        /* Restore interrupts  (pre-emption will be enabled when
                         * we fall through the if/then/else)
                         */

                        irqrestore(int_state);
                    }
                    else
                    {
                        /* Start the watchdog */

                        wd_start(rtcb->waitdog, ticks, (wdentry_t)pthread_condtimedout,
                                 2, (uint32_t)mypid, (uint32_t)SIGCONDTIMEDOUT);

                        /* Take the condition semaphore.  Do not restore interrupts
                         * until we return from the wait.  This is necessary to
                         * make sure that the watchdog timer and the condition wait
                         * are started atomically.
                         */

                        status = sem_wait((sem_t*)&cond->sem);

                        /* Did we get the condition semaphore. */

                        if (status != OK)
                        {
                            /* NO.. Handle the special case where the semaphore wait was
                             * awakened by the receipt of a signal -- presumably the
                             * signal posted by pthread_condtimedout().
                             */

                            if (get_errno() == EINTR)
                            {
                                sdbg("Timedout!\n");
                                ret = ETIMEDOUT;
                            }
                            else
                            {
                                ret = EINVAL;
                            }
                        }

                        /* The interrupts stay disabled until after we sample the errno.
                         * This is because when debug is enabled and the console is used
                         * for debug output, then the errno can be altered by interrupt
                         * handling! (bad)
                         */

                        irqrestore(int_state);
                    }

                    /* Reacquire the mutex (retaining the ret). */

                    sdbg("Re-locking...\n");
                    status = pthread_takesemaphore((sem_t*)&mutex->sem);
                    if (!status)
                    {
                        mutex->pid = mypid;
                    }
                    else if (!ret)
                    {
                        ret = status;
                    }
                }

                /* Re-enable pre-emption (It is expected that interrupts
                 * have already been re-enabled in the above logic)
                 */

                sched_unlock();
            }

            /* We no longer need the watchdog */

            wd_delete(rtcb->waitdog);
            rtcb->waitdog = NULL;
        }
    }

    sdbg("Returning %d\n", ret);
    return ret;
}
Beispiel #4
0
int
lr_metalink_parse_file(lr_Metalink metalink, int fd, const char *filename)
{
    int ret = LRE_OK;
    XML_Parser parser;
    ParserData pd;
    lr_StatesSwitch *sw;

    assert(metalink);
    DEBUGASSERT(fd >= 0);

    /* Parser configuration */
    parser = XML_ParserCreate(NULL);
    XML_SetUserData(parser, (void *) &pd);
    XML_SetElementHandler(parser, lr_metalink_start_handler, lr_metalink_end_handler);
    XML_SetCharacterDataHandler(parser, lr_metalink_char_handler);

    /* Initialization of parser data */
    memset(&pd, 0, sizeof(pd));
    pd.ret = LRE_OK;
    pd.depth = 0;
    pd.state = STATE_START;
    pd.statedepth = 0;
    pd.docontent = 0;
    pd.content = lr_malloc(CONTENT_REALLOC_STEP);
    pd.lcontent = 0;
    pd.acontent = CONTENT_REALLOC_STEP;
    pd.parser = &parser;
    pd.metalink = metalink;
    pd.filename = (char *) filename;
    pd.ignore = 1;
    pd.found = 0;
    for (sw = stateswitches; sw->from != NUMSTATES; sw++) {
        if (!pd.swtab[sw->from])
            pd.swtab[sw->from] = sw;
        pd.sbtab[sw->to] = sw->from;
    }

    /* Parse */
    for (;;) {
        char *buf;
        int len;

        buf = XML_GetBuffer(parser, CHUNK_SIZE);
        if (!buf)
            lr_out_of_memory();

        len = read(fd, (void *) buf, CHUNK_SIZE);
        if (len < 0) {
            DPRINTF("%s: Cannot read for parsing : %s\n",
                    __func__, strerror(errno));
            ret = LRE_IO;
            break;
        }

        if (!XML_ParseBuffer(parser, len, len == 0)) {
            DPRINTF("%s: parsing error: %s\n",
                    __func__, XML_ErrorString(XML_GetErrorCode(parser)));
            ret = LRE_MLXML;
            break;
        }

        if (len == 0)
            break;

        if (pd.ret != LRE_OK) {
            ret = pd.ret;
            break;
        }
    }

    /* Parser data cleanup */
    lr_free(pd.content);
    XML_ParserFree(parser);

    if (!pd.found)
        return LRE_MLBAD; /* The wanted file was not found in metalink */

    return ret;
}
Beispiel #5
0
Datei: rtsp.c Projekt: 2px/curl
static CURLcode rtsp_do(struct connectdata *conn, bool *done)
{
  struct Curl_easy *data = conn->data;
  CURLcode result=CURLE_OK;
  Curl_RtspReq rtspreq = data->set.rtspreq;
  struct RTSP *rtsp = data->req.protop;
  struct HTTP *http;
  Curl_send_buffer *req_buffer;
  curl_off_t postsize = 0; /* for ANNOUNCE and SET_PARAMETER */
  curl_off_t putsize = 0; /* for ANNOUNCE and SET_PARAMETER */

  const char *p_request = NULL;
  const char *p_session_id = NULL;
  const char *p_accept = NULL;
  const char *p_accept_encoding = NULL;
  const char *p_range = NULL;
  const char *p_referrer = NULL;
  const char *p_stream_uri = NULL;
  const char *p_transport = NULL;
  const char *p_uagent = NULL;
  const char *p_proxyuserpwd = NULL;
  const char *p_userpwd = NULL;

  *done = TRUE;

  http = &(rtsp->http_wrapper);
  /* Assert that no one has changed the RTSP struct in an evil way */
  DEBUGASSERT((void *)http == (void *)rtsp);

  rtsp->CSeq_sent = data->state.rtsp_next_client_CSeq;
  rtsp->CSeq_recv = 0;

  /* Setup the 'p_request' pointer to the proper p_request string
   * Since all RTSP requests are included here, there is no need to
   * support custom requests like HTTP.
   **/
  data->set.opt_no_body = TRUE; /* most requests don't contain a body */
  switch(rtspreq) {
  default:
    failf(data, "Got invalid RTSP request");
    return CURLE_BAD_FUNCTION_ARGUMENT;
  case RTSPREQ_OPTIONS:
    p_request = "OPTIONS";
    break;
  case RTSPREQ_DESCRIBE:
    p_request = "DESCRIBE";
    data->set.opt_no_body = FALSE;
    break;
  case RTSPREQ_ANNOUNCE:
    p_request = "ANNOUNCE";
    break;
  case RTSPREQ_SETUP:
    p_request = "SETUP";
    break;
  case RTSPREQ_PLAY:
    p_request = "PLAY";
    break;
  case RTSPREQ_PAUSE:
    p_request = "PAUSE";
    break;
  case RTSPREQ_TEARDOWN:
    p_request = "TEARDOWN";
    break;
  case RTSPREQ_GET_PARAMETER:
    /* GET_PARAMETER's no_body status is determined later */
    p_request = "GET_PARAMETER";
    data->set.opt_no_body = FALSE;
    break;
  case RTSPREQ_SET_PARAMETER:
    p_request = "SET_PARAMETER";
    break;
  case RTSPREQ_RECORD:
    p_request = "RECORD";
    break;
  case RTSPREQ_RECEIVE:
    p_request = "";
    /* Treat interleaved RTP as body*/
    data->set.opt_no_body = FALSE;
    break;
  case RTSPREQ_LAST:
    failf(data, "Got invalid RTSP request: RTSPREQ_LAST");
    return CURLE_BAD_FUNCTION_ARGUMENT;
  }

  if(rtspreq == RTSPREQ_RECEIVE) {
    Curl_setup_transfer(conn, FIRSTSOCKET, -1, TRUE,
                        &http->readbytecount, -1, NULL);

    return result;
  }

  p_session_id = data->set.str[STRING_RTSP_SESSION_ID];
  if(!p_session_id &&
     (rtspreq & ~(RTSPREQ_OPTIONS | RTSPREQ_DESCRIBE | RTSPREQ_SETUP))) {
    failf(data, "Refusing to issue an RTSP request [%s] without a session ID.",
          p_request);
    return CURLE_BAD_FUNCTION_ARGUMENT;
  }

  /* TODO: proxy? */

  /* Stream URI. Default to server '*' if not specified */
  if(data->set.str[STRING_RTSP_STREAM_URI]) {
    p_stream_uri = data->set.str[STRING_RTSP_STREAM_URI];
  }
  else {
    p_stream_uri = "*";
  }

  /* Transport Header for SETUP requests */
  p_transport = Curl_checkheaders(conn, "Transport:");
  if(rtspreq == RTSPREQ_SETUP && !p_transport) {
    /* New Transport: setting? */
    if(data->set.str[STRING_RTSP_TRANSPORT]) {
      Curl_safefree(conn->allocptr.rtsp_transport);

      conn->allocptr.rtsp_transport =
        aprintf("Transport: %s\r\n",
                data->set.str[STRING_RTSP_TRANSPORT]);
      if(!conn->allocptr.rtsp_transport)
        return CURLE_OUT_OF_MEMORY;
    }
    else {
      failf(data,
            "Refusing to issue an RTSP SETUP without a Transport: header.");
      return CURLE_BAD_FUNCTION_ARGUMENT;
    }

    p_transport = conn->allocptr.rtsp_transport;
  }

  /* Accept Headers for DESCRIBE requests */
  if(rtspreq == RTSPREQ_DESCRIBE) {
    /* Accept Header */
    p_accept = Curl_checkheaders(conn, "Accept:")?
      NULL:"Accept: application/sdp\r\n";

    /* Accept-Encoding header */
    if(!Curl_checkheaders(conn, "Accept-Encoding:") &&
       data->set.str[STRING_ENCODING]) {
      Curl_safefree(conn->allocptr.accept_encoding);
      conn->allocptr.accept_encoding =
        aprintf("Accept-Encoding: %s\r\n", data->set.str[STRING_ENCODING]);

      if(!conn->allocptr.accept_encoding)
        return CURLE_OUT_OF_MEMORY;

      p_accept_encoding = conn->allocptr.accept_encoding;
    }
  }

  /* The User-Agent string might have been allocated in url.c already, because
     it might have been used in the proxy connect, but if we have got a header
     with the user-agent string specified, we erase the previously made string
     here. */
  if(Curl_checkheaders(conn, "User-Agent:") && conn->allocptr.uagent) {
    Curl_safefree(conn->allocptr.uagent);
    conn->allocptr.uagent = NULL;
  }
  else if(!Curl_checkheaders(conn, "User-Agent:") &&
          data->set.str[STRING_USERAGENT]) {
    p_uagent = conn->allocptr.uagent;
  }

  /* setup the authentication headers */
  result = Curl_http_output_auth(conn, p_request, p_stream_uri, FALSE);
  if(result)
    return result;

  p_proxyuserpwd = conn->allocptr.proxyuserpwd;
  p_userpwd = conn->allocptr.userpwd;

  /* Referrer */
  Curl_safefree(conn->allocptr.ref);
  if(data->change.referer && !Curl_checkheaders(conn, "Referer:"))
    conn->allocptr.ref = aprintf("Referer: %s\r\n", data->change.referer);
  else
    conn->allocptr.ref = NULL;

  p_referrer = conn->allocptr.ref;

  /*
   * Range Header
   * Only applies to PLAY, PAUSE, RECORD
   *
   * Go ahead and use the Range stuff supplied for HTTP
   */
  if(data->state.use_range &&
     (rtspreq  & (RTSPREQ_PLAY | RTSPREQ_PAUSE | RTSPREQ_RECORD))) {

    /* Check to see if there is a range set in the custom headers */
    if(!Curl_checkheaders(conn, "Range:") && data->state.range) {
      Curl_safefree(conn->allocptr.rangeline);
      conn->allocptr.rangeline = aprintf("Range: %s\r\n", data->state.range);
      p_range = conn->allocptr.rangeline;
    }
  }

  /*
   * Sanity check the custom headers
   */
  if(Curl_checkheaders(conn, "CSeq:")) {
    failf(data, "CSeq cannot be set as a custom header.");
    return CURLE_RTSP_CSEQ_ERROR;
  }
  if(Curl_checkheaders(conn, "Session:")) {
    failf(data, "Session ID cannot be set as a custom header.");
    return CURLE_BAD_FUNCTION_ARGUMENT;
  }

  /* Initialize a dynamic send buffer */
  req_buffer = Curl_add_buffer_init();

  if(!req_buffer)
    return CURLE_OUT_OF_MEMORY;

  result =
    Curl_add_bufferf(req_buffer,
                     "%s %s RTSP/1.0\r\n" /* Request Stream-URI RTSP/1.0 */
                     "CSeq: %ld\r\n", /* CSeq */
                     p_request, p_stream_uri, rtsp->CSeq_sent);
  if(result)
    return result;

  /*
   * Rather than do a normal alloc line, keep the session_id unformatted
   * to make comparison easier
   */
  if(p_session_id) {
    result = Curl_add_bufferf(req_buffer, "Session: %s\r\n", p_session_id);
    if(result)
      return result;
  }

  /*
   * Shared HTTP-like options
   */
  result = Curl_add_bufferf(req_buffer,
                            "%s" /* transport */
                            "%s" /* accept */
                            "%s" /* accept-encoding */
                            "%s" /* range */
                            "%s" /* referrer */
                            "%s" /* user-agent */
                            "%s" /* proxyuserpwd */
                            "%s" /* userpwd */
                            ,
                            p_transport ? p_transport : "",
                            p_accept ? p_accept : "",
                            p_accept_encoding ? p_accept_encoding : "",
                            p_range ? p_range : "",
                            p_referrer ? p_referrer : "",
                            p_uagent ? p_uagent : "",
                            p_proxyuserpwd ? p_proxyuserpwd : "",
                            p_userpwd ? p_userpwd : "");

  /*
   * Free userpwd now --- cannot reuse this for Negotiate and possibly NTLM
   * with basic and digest, it will be freed anyway by the next request
   */
  Curl_safefree (conn->allocptr.userpwd);
  conn->allocptr.userpwd = NULL;

  if(result)
    return result;

  if((rtspreq == RTSPREQ_SETUP) || (rtspreq == RTSPREQ_DESCRIBE)) {
    result = Curl_add_timecondition(data, req_buffer);
    if(result)
      return result;
  }

  result = Curl_add_custom_headers(conn, FALSE, req_buffer);
  if(result)
    return result;

  if(rtspreq == RTSPREQ_ANNOUNCE ||
     rtspreq == RTSPREQ_SET_PARAMETER ||
     rtspreq == RTSPREQ_GET_PARAMETER) {

    if(data->set.upload) {
      putsize = data->state.infilesize;
      data->set.httpreq = HTTPREQ_PUT;

    }
    else {
      postsize = (data->state.infilesize != -1)?
        data->state.infilesize:
        (data->set.postfields? (curl_off_t)strlen(data->set.postfields):0);
      data->set.httpreq = HTTPREQ_POST;
    }

    if(putsize > 0 || postsize > 0) {
      /* As stated in the http comments, it is probably not wise to
       * actually set a custom Content-Length in the headers */
      if(!Curl_checkheaders(conn, "Content-Length:")) {
        result = Curl_add_bufferf(req_buffer,
            "Content-Length: %" CURL_FORMAT_CURL_OFF_T"\r\n",
            (data->set.upload ? putsize : postsize));
        if(result)
          return result;
      }

      if(rtspreq == RTSPREQ_SET_PARAMETER ||
         rtspreq == RTSPREQ_GET_PARAMETER) {
        if(!Curl_checkheaders(conn, "Content-Type:")) {
          result = Curl_add_bufferf(req_buffer,
              "Content-Type: text/parameters\r\n");
          if(result)
            return result;
        }
      }

      if(rtspreq == RTSPREQ_ANNOUNCE) {
        if(!Curl_checkheaders(conn, "Content-Type:")) {
          result = Curl_add_bufferf(req_buffer,
              "Content-Type: application/sdp\r\n");
          if(result)
            return result;
        }
      }

      data->state.expect100header = FALSE; /* RTSP posts are simple/small */
    }
    else if(rtspreq == RTSPREQ_GET_PARAMETER) {
      /* Check for an empty GET_PARAMETER (heartbeat) request */
      data->set.httpreq = HTTPREQ_HEAD;
      data->set.opt_no_body = TRUE;
    }
  }

  /* RTSP never allows chunked transfer */
  data->req.forbidchunk = TRUE;
  /* Finish the request buffer */
  result = Curl_add_buffer(req_buffer, "\r\n", 2);
  if(result)
    return result;

  if(postsize > 0) {
    result = Curl_add_buffer(req_buffer, data->set.postfields,
                             (size_t)postsize);
    if(result)
      return result;
  }

  /* issue the request */
  result = Curl_add_buffer_send(req_buffer, conn,
                                &data->info.request_size, 0, FIRSTSOCKET);
  if(result) {
    failf(data, "Failed sending RTSP request");
    return result;
  }

  Curl_setup_transfer(conn, FIRSTSOCKET, -1, TRUE, &http->readbytecount,
                      putsize?FIRSTSOCKET:-1,
                      putsize?&http->writebytecount:NULL);

  /* Increment the CSeq on success */
  data->state.rtsp_next_client_CSeq++;

  if(http->writebytecount) {
    /* if a request-body has been sent off, we make sure this progress is
       noted properly */
    Curl_pgrsSetUploadCounter(data, http->writebytecount);
    if(Curl_pgrsUpdate(conn))
      result = CURLE_ABORTED_BY_CALLBACK;
  }

  return result;
}
/*
 * Curl_pp_readresp()
 *
 * Reads a piece of a server response.
 */
CURLcode Curl_pp_readresp(curl_socket_t sockfd,
                          struct pingpong *pp,
                          int *code, /* return the server code if done */
                          size_t *size) /* size of the response */
{
  ssize_t perline; /* count bytes per line */
  bool keepon=TRUE;
  ssize_t gotbytes;
  char *ptr;
  struct connectdata *conn = pp->conn;
  struct SessionHandle *data = conn->data;
  char * const buf = data->state.buffer;
  CURLcode result = CURLE_OK;

  *code = 0; /* 0 for errors or not done */
  *size = 0;

  ptr=buf + pp->nread_resp;

  /* number of bytes in the current line, so far */
  perline = (ssize_t)(ptr-pp->linestart_resp);

  keepon=TRUE;

  while((pp->nread_resp<BUFSIZE) && (keepon && !result)) {

    if(pp->cache) {
      /* we had data in the "cache", copy that instead of doing an actual
       * read
       *
       * pp->cache_size is cast to ssize_t here.  This should be safe, because
       * it would have been populated with something of size int to begin
       * with, even though its datatype may be larger than an int.
       */
      DEBUGASSERT((ptr+pp->cache_size) <= (buf+BUFSIZE+1));
      memcpy(ptr, pp->cache, pp->cache_size);
      gotbytes = (ssize_t)pp->cache_size;
      free(pp->cache);    /* free the cache */
      pp->cache = NULL;   /* clear the pointer */
      pp->cache_size = 0; /* zero the size just in case */
    }
    else {
      int res;
#if defined(HAVE_KRB4) || defined(HAVE_GSSAPI)
      enum protection_level prot = conn->data_prot;
      conn->data_prot = PROT_CLEAR;
#endif
      DEBUGASSERT((ptr+BUFSIZE-pp->nread_resp) <= (buf+BUFSIZE+1));
      res = Curl_read(conn, sockfd, ptr, BUFSIZE-pp->nread_resp,
                      &gotbytes);
#if defined(HAVE_KRB4) || defined(HAVE_GSSAPI)
      DEBUGASSERT(prot  > PROT_NONE && prot < PROT_LAST);
      conn->data_prot = prot;
#endif
      if(res == CURLE_AGAIN)
        return CURLE_OK; /* return */

      if((res == CURLE_OK) && (gotbytes > 0))
        /* convert from the network encoding */
        res = Curl_convert_from_network(data, ptr, gotbytes);
      /* Curl_convert_from_network calls failf if unsuccessful */

      if(CURLE_OK != res) {
        result = (CURLcode)res; /* Set outer result variable to this error. */
        keepon = FALSE;
      }
    }

    if(!keepon)
      ;
    else if(gotbytes <= 0) {
      keepon = FALSE;
      result = CURLE_RECV_ERROR;
      failf(data, "response reading failed");
    }
    else {
      /* we got a whole chunk of data, which can be anything from one
       * byte to a set of lines and possible just a piece of the last
       * line */
      ssize_t i;
      ssize_t clipamount = 0;
      bool restart = FALSE;

      data->req.headerbytecount += (long)gotbytes;

      pp->nread_resp += gotbytes;
      for(i = 0; i < gotbytes; ptr++, i++) {
        perline++;
        if(*ptr=='\n') {
          /* a newline is CRLF in pp-talk, so the CR is ignored as
             the line isn't really terminated until the LF comes */

          /* output debug output if that is requested */
#if defined(HAVE_KRB4) || defined(HAVE_GSSAPI)
          if(!conn->sec_complete)
#endif
            if(data->set.verbose)
              Curl_debug(data, CURLINFO_HEADER_IN,
                         pp->linestart_resp, (size_t)perline, conn);

          /*
           * We pass all response-lines to the callback function registered
           * for "headers". The response lines can be seen as a kind of
           * headers.
           */
          result = Curl_client_write(conn, CLIENTWRITE_HEADER,
                                     pp->linestart_resp, perline);
          if(result)
            return result;

          if(pp->endofresp(pp, code)) {
            /* This is the end of the last line, copy the last line to the
               start of the buffer and zero terminate, for old times sake (and
               krb4)! */
            char *meow;
            int n;
            for(meow=pp->linestart_resp, n=0; meow<ptr; meow++, n++)
              buf[n] = *meow;
            *meow=0; /* zero terminate */
            keepon=FALSE;
            pp->linestart_resp = ptr+1; /* advance pointer */
            i++; /* skip this before getting out */

            *size = pp->nread_resp; /* size of the response */
            pp->nread_resp = 0; /* restart */
            break;
          }
          perline=0; /* line starts over here */
          pp->linestart_resp = ptr+1;
        }
      }

      if(!keepon && (i != gotbytes)) {
        /* We found the end of the response lines, but we didn't parse the
           full chunk of data we have read from the server. We therefore need
           to store the rest of the data to be checked on the next invoke as
           it may actually contain another end of response already! */
        clipamount = gotbytes - i;
        restart = TRUE;
      }
      else if(keepon) {

        if((perline == gotbytes) && (gotbytes > BUFSIZE/2)) {
          /* We got an excessive line without newlines and we need to deal
             with it. We keep the first bytes of the line then we throw
             away the rest. */
          infof(data, "Excessive server response line length received, "
                "%zd bytes. Stripping\n", gotbytes);
          restart = TRUE;

          /* we keep 40 bytes since all our pingpong protocols are only
             interested in the first piece */
          clipamount = 40;
        }
        else if(pp->nread_resp > BUFSIZE/2) {
          /* We got a large chunk of data and there's potentially still
             trailing data to take care of, so we put any such part in the
             "cache", clear the buffer to make space and restart. */
          clipamount = perline;
          restart = TRUE;
        }
      }
      else if(i == gotbytes)
        restart = TRUE;

      if(clipamount) {
        pp->cache_size = clipamount;
        pp->cache = malloc(pp->cache_size);
        if(pp->cache)
          memcpy(pp->cache, pp->linestart_resp, pp->cache_size);
        else
          return CURLE_OUT_OF_MEMORY;
      }
      if(restart) {
        /* now reset a few variables to start over nicely from the start of
           the big buffer */
        pp->nread_resp = 0; /* start over from scratch in the buffer */
        ptr = pp->linestart_resp = buf;
        perline = 0;
      }

    } /* there was data */

  } /* while there's buffer left and loop is requested */

  pp->pending_resp = FALSE;

  return result;
}
Beispiel #7
0
FAR const char *inet_ntop(int af, FAR const void *src, FAR char *dst, socklen_t size)
{
  int errval;
#ifndef CONFIG_NET_IPv6
  FAR char *ptr;

  DEBUGASSERT(src && dst);

  if (af != AF_INET)
    {
      errval = EAFNOSUPPORT;
      goto errout;
    }

  if (size < INET_ADDRSTRLEN)
    {
      errval = ENOSPC;
      goto errout;
    }

  ptr = (FAR char*)src;
  sprintf(dst, "%d.%d.%d.%d", ptr[0], ptr[1], ptr[2], ptr[3]);
  return dst;
#else
  FAR const struct in6_addr *in6_addr;
  uint16_t warray[8];
  int offset;
  int entry;
  int count;
  int maxentry;
  int maxcount;
 
  DEBUGASSERT(src && dst);

  if (af != AF_INET6)
    {
      errval = EAFNOSUPPORT;
      goto errout;
    }

  if (size < INET6_ADDRSTRLEN)
    {
      errval = ENOSPC;
      goto errout;
    }

  in6_addr = (FAR const struct in6_addr *)src;
  entry    = -1;
  maxentry = -1;
  maxcount = 0;
  offset   = 0;

  while (offset < 8)
    {
      warray[offset] = ntohs(in6_addr->s6_addr16[offset]);
      if (warray[offset] == 0)
        {
          entry = offset;
          count = 1;
          offset++;

          while (offset < 8)
            {
              warray[offset] = ntohs(in6_addr->s6_addr16[offset]);
              if (warray[offset] != 0)
                {
                  break;
                }
              offset++;
              count++;
            }

          if (count > maxcount)
            {
              maxentry = entry;
              maxcount = count;
            }
        }
      offset++;
    }

  offset = 0;
  dst[0] = '\0';

  while (offset < 8)
    {
      if (offset == maxentry)
        {
          size   -= snprintf(&dst[strlen(dst)], size, ":");
          offset += maxcount;
          if (offset >= 8)
            {
              size -= snprintf(&dst[strlen(dst)], size, ":");
            }
        }
      else
        {
          if (offset > 0)
            {
              size -= snprintf(&dst[strlen(dst)], size, ":");
            }

          size -= snprintf(&dst[strlen(dst)], size, "%x", warray[offset]);
          offset++;
        }
    }

    return dst;
#endif

errout:
    set_errno(errval);
    memset(dst, 0, size);
    return NULL;
}
Beispiel #8
0
/*
 * Our thread-safe and smart strerror() replacement.
 *
 * The 'err' argument passed in to this function MUST be a true errno number
 * as reported on this system. We do no range checking on the number before
 * we pass it to the "number-to-message" conversion function and there might
 * be systems that don't do proper range checking in there themselves.
 *
 * We don't do range checking (on systems other than Windows) since there is
 * no good reliable and portable way to do it.
 */
const char *Curl_strerror(struct connectdata *conn, int err)
{
  char *buf, *p;
  size_t max;
  int old_errno = ERRNO;

  DEBUGASSERT(conn);
  DEBUGASSERT(err >= 0);

  buf = conn->syserr_buf;
  max = sizeof(conn->syserr_buf)-1;
  *buf = '\0';

#ifdef USE_WINSOCK

#ifdef _WIN32_WCE
  {
    wchar_t wbuf[256];
    wbuf[0] = L'\0';

    FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM, NULL, err,
                  LANG_NEUTRAL, wbuf, sizeof(wbuf)/sizeof(wchar_t), NULL);
    wcstombs(buf,wbuf,max);
  }
#else
  /* 'sys_nerr' is the maximum errno number, it is not widely portable */
  if(err >= 0 && err < sys_nerr)
    strncpy(buf, strerror(err), max);
  else {
    if(!get_winsock_error(err, buf, max) &&
       !FormatMessageA(FORMAT_MESSAGE_FROM_SYSTEM, NULL, err,
                       LANG_NEUTRAL, buf, (DWORD)max, NULL))
      snprintf(buf, max, "Unknown error %d (%#x)", err, err);
  }
#endif

#else /* not USE_WINSOCK coming up */

#if defined(HAVE_STRERROR_R) && defined(HAVE_POSIX_STRERROR_R)
 /*
  * The POSIX-style strerror_r() may set errno to ERANGE if insufficient
  * storage is supplied via 'strerrbuf' and 'buflen' to hold the generated
  * message string, or EINVAL if 'errnum' is not a valid error number.
  */
  if(0 != strerror_r(err, buf, max)) {
    if('\0' == buf[0])
      snprintf(buf, max, "Unknown error %d", err);
  }
#elif defined(HAVE_STRERROR_R) && defined(HAVE_GLIBC_STRERROR_R)
 /*
  * The glibc-style strerror_r() only *might* use the buffer we pass to
  * the function, but it always returns the error message as a pointer,
  * so we must copy that string unconditionally (if non-NULL).
  */
  {
    char buffer[256];
    char *msg = strerror_r(err, buffer, sizeof(buffer));
    if(msg)
      strncpy(buf, msg, max);
    else
      snprintf(buf, max, "Unknown error %d", err);
  }
#elif defined(HAVE_STRERROR_R) && defined(HAVE_VXWORKS_STRERROR_R)
 /*
  * The vxworks-style strerror_r() does use the buffer we pass to the function.
  * The buffer size should be at least NAME_MAX (256)
  */
  {
    char buffer[256];
    if(OK == strerror_r(err, buffer))
      strncpy(buf, buffer, max);
    else
      snprintf(buf, max, "Unknown error %d", err);
  }
#else
  {
    char *msg = strerror(err);
    if(msg)
      strncpy(buf, msg, max);
    else
      snprintf(buf, max, "Unknown error %d", err);
  }
#endif

#endif /* end of ! USE_WINSOCK */

  buf[max] = '\0'; /* make sure the string is zero terminated */

  /* strip trailing '\r\n' or '\n'. */
  if((p = strrchr(buf,'\n')) != NULL && (p - buf) >= 2)
     *p = '\0';
  if((p = strrchr(buf,'\r')) != NULL && (p - buf) >= 1)
     *p = '\0';

  if(old_errno != ERRNO)
    SET_ERRNO(old_errno);

  return buf;
}
Beispiel #9
0
/*
 * Return error-string for libidn status as returned from idna_to_ascii_lz().
 */
const char *Curl_idn_strerror (struct connectdata *conn, int err)
{
#ifdef HAVE_IDNA_STRERROR
  (void)conn;
  return idna_strerror((Idna_rc) err);
#else
  const char *str;
  char *buf;
  size_t max;

  DEBUGASSERT(conn);

  buf = conn->syserr_buf;
  max = sizeof(conn->syserr_buf)-1;
  *buf = '\0';

#ifndef CURL_DISABLE_VERBOSE_STRINGS
  switch ((Idna_rc)err) {
    case IDNA_SUCCESS:
      str = "No error";
      break;
    case IDNA_STRINGPREP_ERROR:
      str = "Error in string preparation";
      break;
    case IDNA_PUNYCODE_ERROR:
      str = "Error in Punycode operation";
      break;
    case IDNA_CONTAINS_NON_LDH:
      str = "Illegal ASCII characters";
      break;
    case IDNA_CONTAINS_MINUS:
      str = "Contains minus";
      break;
    case IDNA_INVALID_LENGTH:
      str = "Invalid output length";
      break;
    case IDNA_NO_ACE_PREFIX:
      str = "No ACE prefix (\"xn--\")";
      break;
    case IDNA_ROUNDTRIP_VERIFY_ERROR:
      str = "Round trip verify error";
      break;
    case IDNA_CONTAINS_ACE_PREFIX:
      str = "Already have ACE prefix (\"xn--\")";
      break;
    case IDNA_ICONV_ERROR:
      str = "Locale conversion failed";
      break;
    case IDNA_MALLOC_ERROR:
      str = "Allocation failed";
      break;
    case IDNA_DLOPEN_ERROR:
      str = "dlopen() error";
      break;
    default:
      snprintf(buf, max, "error %d", err);
      str = NULL;
      break;
  }
#else
  if((Idna_rc)err == IDNA_SUCCESS)
    str = "No error";
  else
    str = "Error";
#endif
  if(str)
    strncpy(buf, str, max);
  buf[max] = '\0';
  return (buf);
#endif
}
Beispiel #10
0
FAR struct iob_s *iob_tryalloc(bool throttled)
{
  FAR struct iob_s *iob;
  irqstate_t flags;
#if CONFIG_IOB_THROTTLE > 0
  FAR sem_t *sem;
#endif

#if CONFIG_IOB_THROTTLE > 0
  /* Select the semaphore count to check. */

  sem = (throttled ? &g_throttle_sem : &g_iob_sem);
#endif

  /* We don't know what context we are called from so we use extreme measures
   * to protect the free list:  We disable interrupts very briefly.
   */

  flags = irqsave();

#if CONFIG_IOB_THROTTLE > 0
  /* If there are free I/O buffers for this allocation */

  if (sem->semcount > 0)
#endif
    {
      /* Take the I/O buffer from the head of the free list */

      iob = g_iob_freelist;
      if (iob)
        {
          /* Remove the I/O buffer from the free list and decrement the
           * counting semaphore(s) that tracks the number of available
           * IOBs.
           */

          g_iob_freelist = iob->io_flink;

          /* Take a semaphore count.  Note that we cannot do this in
           * in the orthodox way by calling sem_wait() or sem_trywait()
           * because this function may be called from an interrupt
           * handler. Fortunately we know at at least one free buffer
           * so a simple decrement is all that is needed.
           */

          g_iob_sem.semcount--;
          DEBUGASSERT(g_iob_sem.semcount >= 0);

#if CONFIG_IOB_THROTTLE > 0
          /* The throttle semaphore is a little more complicated because
           * it can be negative!  Decrementing is still safe, however.
           */

          g_throttle_sem.semcount--;
          DEBUGASSERT(g_throttle_sem.semcount >= -CONFIG_IOB_THROTTLE);
#endif
          irqrestore(flags);

          /* Put the I/O buffer in a known state */

          iob->io_flink  = NULL; /* Not in a chain */
          iob->io_len    = 0;    /* Length of the data in the entry */
          iob->io_offset = 0;    /* Offset to the beginning of data */
          iob->io_pktlen = 0;    /* Total length of the packet */
          return iob;
        }
    }

  irqrestore(flags);
  return NULL;
}
Beispiel #11
0
static FAR struct iob_s *iob_allocwait(bool throttled)
{
  FAR struct iob_s *iob;
  irqstate_t flags;
  FAR sem_t *sem;
  int ret = OK;

#if CONFIG_IOB_THROTTLE > 0
  /* Select the semaphore count to check. */

  sem = (throttled ? &g_throttle_sem : &g_iob_sem);
#else
  sem = &g_iob_sem;
#endif

  /* The following must be atomic; interrupt must be disabled so that there
   * is no conflict with interrupt level I/O buffer allocations.  This is
   * not as bad as it sounds because interrupts will be re-enabled while
   * we are waiting for I/O buffers to become free.
   */

  flags = irqsave();
  do
    {
      /* Try to get an I/O buffer.  If successful, the semaphore count
       * will be decremented atomically.
       */

      iob = iob_tryalloc(throttled);
      if (!iob)
        {
          /* If not successful, then the semaphore count was less than or
           * equal to zero (meaning that there are no free buffers).  We
           * need to wait for an I/O buffer to be released when the semaphore
           * count will be incremented.
           */

          ret = sem_wait(sem);
          if (ret < 0)
            {
              int errcode = get_errno();

              /* EINTR is not an error!  EINTR simply means that we were
               * awakened by a signal and we should try again.
               *
               * REVISIT:  Many end-user interfaces are required to return
               * with an error if EINTR is set.  Most uses of this function
               * is in internal, non-user logic.  But are there cases where
               * the error should be returned.
               */

              if (errcode == EINTR)
                {
                  /* Force a success indication so that we will continue
                   * looping.
                   */

                  ret = 0;
                }
              else
                {
                  /* Stop the loop and return a error */

                  DEBUGASSERT(errcode > 0);
                  ret = -errcode;
                }
            }
          else
            {
              /* When we wake up from wait successfully, an I/O buffer was
               * returned to the free list.  However, if there are concurrent
               * allocations from interrupt handling, then I suspect that
               * there is a race condition.  But no harm, we will just wait
               * again in that case.
               *
               * We need release our count so that it is available to
               * iob_tryalloc(), perhaps allowing another thread to take our
               * count.  In that event, iob_tryalloc() will fail above and
               * we will have to wait again.
               *
               * TODO: Consider a design modification to permit us to
               * complete the allocation without losing our count.
               */

              sem_post(sem);
            }
        }
    }
  while (ret == OK && iob == NULL);

  irqrestore(flags);
  return iob;
}
int nanosleep(FAR const struct timespec *rqtp, FAR struct timespec *rmtp)
{
  irqstate_t flags;
  systime_t starttick;
  sigset_t set;
  struct siginfo value;
  int errval;
#ifdef CONFIG_DEBUG /* Warning avoidance */
  int ret;
#endif

  if (!rqtp || rqtp->tv_nsec < 0 || rqtp->tv_nsec >= 1000000000)
    {
      errval = EINVAL;
      goto errout;
    }

  /* Get the start time of the wait.  Interrupts are disabled to prevent
   * timer interrupts while we do tick-related calculations before and
   * after the wait.
   */

  flags     = irqsave();
  starttick = clock_systimer();

  /* Set up for the sleep.  Using the empty set means that we are not
   * waiting for any particular signal.  However, any unmasked signal can
   * still awaken sigtimedwait().
   */

  (void)sigemptyset(&set);

  /* nanosleep is a simple application of sigtimedwait. */

#ifdef CONFIG_DEBUG /* Warning avoidance */
  ret = sigtimedwait(&set, &value, rqtp);
#else
  (void)sigtimedwait(&set, &value, rqtp);
#endif

  /* sigtimedwait() cannot succeed.  It should always return error with
   * either (1) EAGAIN meaning that the timeout occurred, or (2) EINTR
   * meaning that some other unblocked signal was caught.
   */

  errval = get_errno();
  DEBUGASSERT(ret < 0 && (errval == EAGAIN || errval == EINTR));

  if (errval == EAGAIN)
    {
      /* The timeout "error" is the normal, successful result */

      irqrestore(flags);
      return OK;
    }

  /* If we get there, the wait has failed because we were awakened by a
   * signal.  Return the amount of "unwaited" time if rmtp is non-NULL.
   */

  if (rmtp)
    {
      systime_t elapsed;
      systime_t remaining;
      int ticks;

      /* First get the number of clock ticks that we were requested to
       * wait.
       */

      (void)clock_time2ticks(rqtp, &ticks);

      /* Get the number of ticks that we actually waited */

      elapsed = clock_systimer() - starttick;

      /* The difference between the number of ticks that we were requested
       * to wait and the number of ticks that we actualy waited is that
       * amount of time that we failed to wait.
       */

      if (elapsed >= (uint32_t)ticks)
        {
          remaining = 0;
        }
      else
        {
          remaining = (uint32_t)ticks - elapsed;
        }

      (void)clock_ticks2time((int)remaining, rmtp);
    }

  irqrestore(flags);

errout:
  set_errno(errval);
  return ERROR;
}
Beispiel #13
0
static void board_mscuninitialize(FAR struct usbdevclass_driver_s *classdev)
{
  DEBUGASSERT(g_mschandle != NULL);
  usbmsc_uninitialize(g_mschandle);
  g_mschandle = NULL;
}
Beispiel #14
0
static inline void nx_connected(FAR struct nxfe_conn_s *conn)
{
  DEBUGASSERT(conn->state == NX_CLISTATE_NOTCONNECTED);
  conn->state = NX_CLISTATE_CONNECTED;
}
static uint16_t send_interrupt(FAR struct uip_driver_s *dev, FAR void *pvconn,
                               FAR void *pvpriv, uint16_t flags)
{
  FAR struct uip_conn *conn = (FAR struct uip_conn*)pvconn;
  FAR struct socket *psock = (FAR struct socket *)pvpriv;

  nllvdbg("flags: %04x\n", flags);

  /* If this packet contains an acknowledgement, then update the count of
   * acknowledged bytes.
   */

  if ((flags & UIP_ACKDATA) != 0)
    {
      FAR sq_entry_t *entry, *next;
      FAR struct uip_wrbuffer_s *segment;
      uint32_t ackno;

      ackno = uip_tcpgetsequence(TCPBUF->ackno);
      for (entry = sq_peek(&conn->unacked_q); entry; entry = next)
        {
          next    = sq_next(entry);
          segment = (FAR struct uip_wrbuffer_s*)entry;

          if (segment->wb_seqno < ackno)
            {
              nllvdbg("ACK: acked=%d buflen=%d ackno=%d\n",
                      segment->wb_seqno, segment->wb_nbytes, ackno);

              /* Segment was ACKed. Remove from ACK waiting queue */

              sq_rem(entry, &conn->unacked_q);

              /* Return the write buffer to the pool of free buffers */

              uip_tcpwrbuffer_release(segment);
            }
        }
    }

  /* Check for a loss of connection */

  else if ((flags & (UIP_CLOSE | UIP_ABORT | UIP_TIMEDOUT)) != 0)
    {
      /* Report not connected */

       nllvdbg("Lost connection\n");
       net_lostconnection(psock, flags);
       goto end_wait;
     }

   /* Check if we are being asked to retransmit data */

   else if ((flags & UIP_REXMIT) != 0)
    {
      sq_entry_t *entry;

      /* Put all segments that have been sent but not ACKed to write queue
       * again note, the un-ACKed segment is put at the first of the write_q,
       * so it can be sent as soon as possible.
       */

      while ((entry = sq_remlast(&conn->unacked_q)))
        {
          struct uip_wrbuffer_s *segment = (struct uip_wrbuffer_s*)entry;

          if (segment->wb_nrtx >= UIP_MAXRTX)
            {
              //conn->unacked -= segment->wb_nbytes;

              /* Return the write buffer */

              uip_tcpwrbuffer_release(segment);

              /* NOTE expired is different from un-ACKed, it is designed to
               * represent the number of segments that have been sent,
               * retransmitted, and un-ACKed, if expired is not zero, the
               * connection will be closed.
               *
               * field expired can only be updated at UIP_ESTABLISHED state
               */

              conn->expired++;
              continue;
            }

          send_insert_seqment(segment, &conn->write_q);
        }
    }

  /* Check if the outgoing packet is available (it may have been claimed
   * by a sendto interrupt serving a different thread).
   */

  if (dev->d_sndlen > 0)
    {
      /* Another thread has beat us sending data, wait for the next poll */

      return flags;
    }

  /* We get here if (1) not all of the data has been ACKed, (2) we have been
   * asked to retransmit data, (3) the connection is still healthy, and (4)
   * the outgoing packet is available for our use.  In this case, we are
   * now free to send more data to receiver -- UNLESS the buffer contains
   * unprocesed incoming data.  In that event, we will have to wait for the
   * next polling cycle.
   */

  if ((conn->tcpstateflags & UIP_ESTABLISHED) &&
      (flags & (UIP_POLL | UIP_REXMIT)) &&
      !(sq_empty(&conn->write_q)))
    {
      /* Check if the destination IP address is in the ARP table.  If not,
       * then the send won't actually make it out... it will be replaced with
       * an ARP request.
       *
       * NOTE 1: This could be an expensive check if there are a lot of
       * entries in the ARP table.
       *
       * NOTE 2: If we are actually harvesting IP addresses on incoming IP
       * packets, then this check should not be necessary; the MAC mapping
       * should already be in the ARP table.
       */

#if defined(CONFIG_NET_ETHERNET) && !defined(CONFIG_NET_ARP_IPIN)
      if (arp_find(conn->ripaddr) != NULL)
#endif
        {
          FAR struct uip_wrbuffer_s *segment;
          FAR void *sndbuf;
          size_t sndlen;

          /* Get the amount of data that we can send in the next packet */

          segment = (FAR struct uip_wrbuffer_s *)sq_remfirst(&conn->write_q);
          if (segment)
            {
              sndbuf = segment->wb_buffer;
              sndlen = segment->wb_nbytes;

              DEBUGASSERT(sndlen <= uip_mss(conn));

              /* REVISIT:  There should be a check here to assure that we do
               * not excced the window (conn->winsize).
               */

              /* Set the sequence number for this segment.  NOTE: uIP
               * updates sndseq on receipt of ACK *before* this function
               * is called. In that case sndseq will point to the next
               * unacknowledged byte (which might have already been
               * sent). We will overwrite the value of sndseq here
               * before the packet is sent.
               */

              if (segment->wb_nrtx == 0 && segment->wb_seqno == (unsigned)-1)
                {
                  segment->wb_seqno = conn->isn + conn->sent;
                }

              uip_tcpsetsequence(conn->sndseq, segment->wb_seqno);

              /* Then set-up to send that amount of data. (this won't
               * actually happen until the polling cycle completes).
               */

              uip_send(dev, sndbuf, sndlen);

              /* Remember how much data we send out now so that we know
               * when everything has been acknowledged.  Just increment
               * the amount of data sent. This will be needed in
               * sequence* number calculations and we know that this is
               * not a re-transmission. Re-transmissions do not go through
               * this path.
               */

              if (segment->wb_nrtx == 0)
                {
                  conn->unacked += sndlen;
                  conn->sent    += sndlen;
                }

              /* Increment the retransmission counter before expiration.
               * NOTE we will not calculate the retransmission timer
               * (RTT) to save cpu cycles, each send_insert_seqment
               * segment will be retransmitted UIP_MAXRTX times in halt-
               * second interval before expiration.
               */

              segment->wb_nrtx++;

              /* The segment is waiting for ACK again */

              send_insert_seqment(segment, &conn->unacked_q);

              /* Only one data can be sent by low level driver at once,
               * tell the caller stop polling the other connection.
               */

              flags &= ~UIP_POLL;
            }
        }
    }

  /* Continue waiting */

  return flags;

end_wait:

  /* Do not allow any further callbacks */

  psock->s_sndcb->flags = 0;
  psock->s_sndcb->event = NULL;

  return flags;
}
Beispiel #16
0
const char *Curl_sspi_strerror (struct connectdata *conn, int err)
{
#ifndef CURL_DISABLE_VERBOSE_STRINGS
  char txtbuf[80];
  char msgbuf[sizeof(conn->syserr_buf)];
  char *p, *str, *msg = NULL;
  bool msg_formatted = FALSE;
  int old_errno;
#endif
  const char *txt;
  char *outbuf;
  size_t outmax;

  DEBUGASSERT(conn);

  outbuf = conn->syserr_buf;
  outmax = sizeof(conn->syserr_buf)-1;
  *outbuf = '\0';

#ifndef CURL_DISABLE_VERBOSE_STRINGS

  old_errno = ERRNO;

  switch (err) {
    case SEC_E_OK:
      txt = "No error";
      break;
    case SEC_E_ALGORITHM_MISMATCH:
      txt = "SEC_E_ALGORITHM_MISMATCH";
      break;
    case SEC_E_BAD_BINDINGS:
      txt = "SEC_E_BAD_BINDINGS";
      break;
    case SEC_E_BAD_PKGID:
      txt = "SEC_E_BAD_PKGID";
      break;
    case SEC_E_BUFFER_TOO_SMALL:
      txt = "SEC_E_BUFFER_TOO_SMALL";
      break;
    case SEC_E_CANNOT_INSTALL:
      txt = "SEC_E_CANNOT_INSTALL";
      break;
    case SEC_E_CANNOT_PACK:
      txt = "SEC_E_CANNOT_PACK";
      break;
    case SEC_E_CERT_EXPIRED:
      txt = "SEC_E_CERT_EXPIRED";
      break;
    case SEC_E_CERT_UNKNOWN:
      txt = "SEC_E_CERT_UNKNOWN";
      break;
    case SEC_E_CERT_WRONG_USAGE:
      txt = "SEC_E_CERT_WRONG_USAGE";
      break;
    case SEC_E_CONTEXT_EXPIRED:
      txt = "SEC_E_CONTEXT_EXPIRED";
      break;
    case SEC_E_CROSSREALM_DELEGATION_FAILURE:
      txt = "SEC_E_CROSSREALM_DELEGATION_FAILURE";
      break;
    case SEC_E_CRYPTO_SYSTEM_INVALID:
      txt = "SEC_E_CRYPTO_SYSTEM_INVALID";
      break;
    case SEC_E_DECRYPT_FAILURE:
      txt = "SEC_E_DECRYPT_FAILURE";
      break;
    case SEC_E_DELEGATION_POLICY:
      txt = "SEC_E_DELEGATION_POLICY";
      break;
    case SEC_E_DELEGATION_REQUIRED:
      txt = "SEC_E_DELEGATION_REQUIRED";
      break;
    case SEC_E_DOWNGRADE_DETECTED:
      txt = "SEC_E_DOWNGRADE_DETECTED";
      break;
    case SEC_E_ENCRYPT_FAILURE:
      txt = "SEC_E_ENCRYPT_FAILURE";
      break;
    case SEC_E_ILLEGAL_MESSAGE:
      txt = "SEC_E_ILLEGAL_MESSAGE";
      break;
    case SEC_E_INCOMPLETE_CREDENTIALS:
      txt = "SEC_E_INCOMPLETE_CREDENTIALS";
      break;
    case SEC_E_INCOMPLETE_MESSAGE:
      txt = "SEC_E_INCOMPLETE_MESSAGE";
      break;
    case SEC_E_INSUFFICIENT_MEMORY:
      txt = "SEC_E_INSUFFICIENT_MEMORY";
      break;
    case SEC_E_INTERNAL_ERROR:
      txt = "SEC_E_INTERNAL_ERROR";
      break;
    case SEC_E_INVALID_HANDLE:
      txt = "SEC_E_INVALID_HANDLE";
      break;
    case SEC_E_INVALID_PARAMETER:
      txt = "SEC_E_INVALID_PARAMETER";
      break;
    case SEC_E_INVALID_TOKEN:
      txt = "SEC_E_INVALID_TOKEN";
      break;
    case SEC_E_ISSUING_CA_UNTRUSTED:
      txt = "SEC_E_ISSUING_CA_UNTRUSTED";
      break;
    case SEC_E_ISSUING_CA_UNTRUSTED_KDC:
      txt = "SEC_E_ISSUING_CA_UNTRUSTED_KDC";
      break;
    case SEC_E_KDC_CERT_EXPIRED:
      txt = "SEC_E_KDC_CERT_EXPIRED";
      break;
    case SEC_E_KDC_CERT_REVOKED:
      txt = "SEC_E_KDC_CERT_REVOKED";
      break;
    case SEC_E_KDC_INVALID_REQUEST:
      txt = "SEC_E_KDC_INVALID_REQUEST";
      break;
    case SEC_E_KDC_UNABLE_TO_REFER:
      txt = "SEC_E_KDC_UNABLE_TO_REFER";
      break;
    case SEC_E_KDC_UNKNOWN_ETYPE:
      txt = "SEC_E_KDC_UNKNOWN_ETYPE";
      break;
    case SEC_E_LOGON_DENIED:
      txt = "SEC_E_LOGON_DENIED";
      break;
    case SEC_E_MAX_REFERRALS_EXCEEDED:
      txt = "SEC_E_MAX_REFERRALS_EXCEEDED";
      break;
    case SEC_E_MESSAGE_ALTERED:
      txt = "SEC_E_MESSAGE_ALTERED";
      break;
    case SEC_E_MULTIPLE_ACCOUNTS:
      txt = "SEC_E_MULTIPLE_ACCOUNTS";
      break;
    case SEC_E_MUST_BE_KDC:
      txt = "SEC_E_MUST_BE_KDC";
      break;
    case SEC_E_NOT_OWNER:
      txt = "SEC_E_NOT_OWNER";
      break;
    case SEC_E_NO_AUTHENTICATING_AUTHORITY:
      txt = "SEC_E_NO_AUTHENTICATING_AUTHORITY";
      break;
    case SEC_E_NO_CREDENTIALS:
      txt = "SEC_E_NO_CREDENTIALS";
      break;
    case SEC_E_NO_IMPERSONATION:
      txt = "SEC_E_NO_IMPERSONATION";
      break;
    case SEC_E_NO_IP_ADDRESSES:
      txt = "SEC_E_NO_IP_ADDRESSES";
      break;
    case SEC_E_NO_KERB_KEY:
      txt = "SEC_E_NO_KERB_KEY";
      break;
    case SEC_E_NO_PA_DATA:
      txt = "SEC_E_NO_PA_DATA";
      break;
    case SEC_E_NO_S4U_PROT_SUPPORT:
      txt = "SEC_E_NO_S4U_PROT_SUPPORT";
      break;
    case SEC_E_NO_TGT_REPLY:
      txt = "SEC_E_NO_TGT_REPLY";
      break;
    case SEC_E_OUT_OF_SEQUENCE:
      txt = "SEC_E_OUT_OF_SEQUENCE";
      break;
    case SEC_E_PKINIT_CLIENT_FAILURE:
      txt = "SEC_E_PKINIT_CLIENT_FAILURE";
      break;
    case SEC_E_PKINIT_NAME_MISMATCH:
      txt = "SEC_E_PKINIT_NAME_MISMATCH";
      break;
    case SEC_E_POLICY_NLTM_ONLY:
      txt = "SEC_E_POLICY_NLTM_ONLY";
      break;
    case SEC_E_QOP_NOT_SUPPORTED:
      txt = "SEC_E_QOP_NOT_SUPPORTED";
      break;
    case SEC_E_REVOCATION_OFFLINE_C:
      txt = "SEC_E_REVOCATION_OFFLINE_C";
      break;
    case SEC_E_REVOCATION_OFFLINE_KDC:
      txt = "SEC_E_REVOCATION_OFFLINE_KDC";
      break;
    case SEC_E_SECPKG_NOT_FOUND:
      txt = "SEC_E_SECPKG_NOT_FOUND";
      break;
    case SEC_E_SECURITY_QOS_FAILED:
      txt = "SEC_E_SECURITY_QOS_FAILED";
      break;
    case SEC_E_SHUTDOWN_IN_PROGRESS:
      txt = "SEC_E_SHUTDOWN_IN_PROGRESS";
      break;
    case SEC_E_SMARTCARD_CERT_EXPIRED:
      txt = "SEC_E_SMARTCARD_CERT_EXPIRED";
      break;
    case SEC_E_SMARTCARD_CERT_REVOKED:
      txt = "SEC_E_SMARTCARD_CERT_REVOKED";
      break;
    case SEC_E_SMARTCARD_LOGON_REQUIRED:
      txt = "SEC_E_SMARTCARD_LOGON_REQUIRED";
      break;
    case SEC_E_STRONG_CRYPTO_NOT_SUPPORTED:
      txt = "SEC_E_STRONG_CRYPTO_NOT_SUPPORTED";
      break;
    case SEC_E_TARGET_UNKNOWN:
      txt = "SEC_E_TARGET_UNKNOWN";
      break;
    case SEC_E_TIME_SKEW:
      txt = "SEC_E_TIME_SKEW";
      break;
    case SEC_E_TOO_MANY_PRINCIPALS:
      txt = "SEC_E_TOO_MANY_PRINCIPALS";
      break;
    case SEC_E_UNFINISHED_CONTEXT_DELETED:
      txt = "SEC_E_UNFINISHED_CONTEXT_DELETED";
      break;
    case SEC_E_UNKNOWN_CREDENTIALS:
      txt = "SEC_E_UNKNOWN_CREDENTIALS";
      break;
    case SEC_E_UNSUPPORTED_FUNCTION:
      txt = "SEC_E_UNSUPPORTED_FUNCTION";
      break;
    case SEC_E_UNSUPPORTED_PREAUTH:
      txt = "SEC_E_UNSUPPORTED_PREAUTH";
      break;
    case SEC_E_UNTRUSTED_ROOT:
      txt = "SEC_E_UNTRUSTED_ROOT";
      break;
    case SEC_E_WRONG_CREDENTIAL_HANDLE:
      txt = "SEC_E_WRONG_CREDENTIAL_HANDLE";
      break;
    case SEC_E_WRONG_PRINCIPAL:
      txt = "SEC_E_WRONG_PRINCIPAL";
      break;
    case SEC_I_COMPLETE_AND_CONTINUE:
      txt = "SEC_I_COMPLETE_AND_CONTINUE";
      break;
    case SEC_I_COMPLETE_NEEDED:
      txt = "SEC_I_COMPLETE_NEEDED";
      break;
    case SEC_I_CONTEXT_EXPIRED:
      txt = "SEC_I_CONTEXT_EXPIRED";
      break;
    case SEC_I_CONTINUE_NEEDED:
      txt = "SEC_I_CONTINUE_NEEDED";
      break;
    case SEC_I_INCOMPLETE_CREDENTIALS:
      txt = "SEC_I_INCOMPLETE_CREDENTIALS";
      break;
    case SEC_I_LOCAL_LOGON:
      txt = "SEC_I_LOCAL_LOGON";
      break;
    case SEC_I_NO_LSA_CONTEXT:
      txt = "SEC_I_NO_LSA_CONTEXT";
      break;
    case SEC_I_RENEGOTIATE:
      txt = "SEC_I_RENEGOTIATE";
      break;
    case SEC_I_SIGNATURE_NEEDED:
      txt = "SEC_I_SIGNATURE_NEEDED";
      break;
    default:
      txt = "Unknown error";
  }

  if(err == SEC_E_OK)
    strncpy(outbuf, txt, outmax);
  else {
    str = txtbuf;
    snprintf(txtbuf, sizeof(txtbuf), "%s (0x%04X%04X)",
             txt, (err >> 16) & 0xffff, err & 0xffff);
    txtbuf[sizeof(txtbuf)-1] = '\0';

#ifdef _WIN32_WCE
    {
      wchar_t wbuf[256];
      wbuf[0] = L'\0';

      if(FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM |
                       FORMAT_MESSAGE_IGNORE_INSERTS,
                       NULL, err, LANG_NEUTRAL,
                       wbuf, sizeof(wbuf)/sizeof(wchar_t), NULL)) {
        wcstombs(msgbuf,wbuf,sizeof(msgbuf)-1);
        msg_formatted = TRUE;
      }
    }
#else
    if(FormatMessageA(FORMAT_MESSAGE_FROM_SYSTEM |
                      FORMAT_MESSAGE_IGNORE_INSERTS,
                      NULL, err, LANG_NEUTRAL,
                      msgbuf, sizeof(msgbuf)-1, NULL)) {
      msg_formatted = TRUE;
    }
#endif
    if(msg_formatted) {
      msgbuf[sizeof(msgbuf)-1] = '\0';
      /* strip trailing '\r\n' or '\n' */
      if((p = strrchr(msgbuf,'\n')) != NULL && (p - msgbuf) >= 2)
         *p = '\0';
      if((p = strrchr(msgbuf,'\r')) != NULL && (p - msgbuf) >= 1)
         *p = '\0';
      msg = msgbuf;
    }
    if(msg)
      snprintf(outbuf, outmax, "%s - %s", str, msg);
    else
      strncpy(outbuf, str, outmax);
  }

  if(old_errno != ERRNO)
    SET_ERRNO(old_errno);

#else

  if(err == SEC_E_OK)
    txt = "No error";
  else
    txt = "Error";

  strncpy(outbuf, txt, outmax);

#endif

  outbuf[outmax] = '\0';

  return outbuf;
}
/***********************************************************************
 *
 * Curl_pp_vsendf()
 *
 * Send the formated string as a command to a pingpong server. Note that
 * the string should not have any CRLF appended, as this function will
 * append the necessary things itself.
 *
 * made to never block
 */
CURLcode Curl_pp_vsendf(struct pingpong *pp,
                        const char *fmt,
                        va_list args)
{
  ssize_t bytes_written;
  size_t write_len;
  char *fmt_crlf;
  char *s;
  CURLcode error;
  struct connectdata *conn = pp->conn;
  struct SessionHandle *data = conn->data;

#if defined(HAVE_KRB4) || defined(HAVE_GSSAPI)
  enum protection_level data_sec = conn->data_prot;
#endif

  DEBUGASSERT(pp->sendleft == 0);
  DEBUGASSERT(pp->sendsize == 0);
  DEBUGASSERT(pp->sendthis == NULL);

  fmt_crlf = aprintf("%s\r\n", fmt); /* append a trailing CRLF */
  if(!fmt_crlf)
    return CURLE_OUT_OF_MEMORY;

  s = vaprintf(fmt_crlf, args); /* trailing CRLF appended */
  free(fmt_crlf);
  if(!s)
    return CURLE_OUT_OF_MEMORY;

  bytes_written = 0;
  write_len = strlen(s);

  Curl_pp_init(pp);

  error = Curl_convert_to_network(data, s, write_len);
  /* Curl_convert_to_network calls failf if unsuccessful */
  if(error) {
    free(s);
    return error;
  }

#if defined(HAVE_KRB4) || defined(HAVE_GSSAPI)
  conn->data_prot = PROT_CMD;
#endif
  error = Curl_write(conn, conn->sock[FIRSTSOCKET], s, write_len,
                     &bytes_written);
#if defined(HAVE_KRB4) || defined(HAVE_GSSAPI)
  DEBUGASSERT(data_sec > PROT_NONE && data_sec < PROT_LAST);
  conn->data_prot = data_sec;
#endif

  if(error) {
    free(s);
    return error;
  }

  if(conn->data->set.verbose)
    Curl_debug(conn->data, CURLINFO_HEADER_OUT,
               s, (size_t)bytes_written, conn);

  if(bytes_written != (ssize_t)write_len) {
    /* the whole chunk was not sent, keep it around and adjust sizes */
    pp->sendthis = s;
    pp->sendsize = write_len;
    pp->sendleft = write_len - bytes_written;
  }
  else {
    free(s);
    pp->sendthis = NULL;
    pp->sendleft = pp->sendsize = 0;
    pp->response = Curl_tvnow();
  }

  return CURLE_OK;
}
Beispiel #18
0
uint8_t board_get_product_name(uint8_t *product_name, size_t maxlen)
{
	DEBUGASSERT(maxlen > UAVCAN_STRLEN(HW_UAVCAN_NAME));
	memcpy(product_name, HW_UAVCAN_NAME, UAVCAN_STRLEN(HW_UAVCAN_NAME));
	return UAVCAN_STRLEN(HW_UAVCAN_NAME);
}
Beispiel #19
0
int group_allocate(FAR struct task_tcb_s *tcb, uint8_t ttype)
{
  FAR struct task_group_s *group;
  int ret;

  DEBUGASSERT(tcb && !tcb->cmn.group);

  /* Allocate the group structure and assign it to the TCB */

  group = (FAR struct task_group_s *)kmm_zalloc(sizeof(struct task_group_s));
  if (!group)
    {
      return -ENOMEM;
    }

#if CONFIG_NFILE_STREAMS > 0 && (defined(CONFIG_BUILD_PROTECTED) || \
    defined(CONFIG_BUILD_KERNEL)) && defined(CONFIG_MM_KERNEL_HEAP)
  /* If this group is being created for a privileged thread, then all elements
   * of the group must be created for privileged access.
   */

  if ((ttype & TCB_FLAG_TTYPE_MASK) == TCB_FLAG_TTYPE_KERNEL)
    {
      group->tg_flags |= GROUP_FLAG_PRIVILEGED;
    }

  /* In a flat, single-heap build.  The stream list is allocated with the
   * group structure.  But in a kernel build with a kernel allocator, it
   * must be separately allocated using a user-space allocator.
   */

  group->tg_streamlist = (FAR struct streamlist *)
    group_zalloc(group, sizeof(struct streamlist));

  if (!group->tg_streamlist)
    {
      kmm_free(group);
      return -ENOMEM;
    }

#endif

  /* Attach the group to the TCB */

  tcb->cmn.group = group;

#if defined(HAVE_GROUP_MEMBERS) || defined(CONFIG_ARCH_ADDRENV)
  /* Assign the group a unique ID.  If g_gidcounter were to wrap before we
   * finish with task creation, that would be a problem.
   */

  group_assigngid(group);
#endif

  /* Duplicate the parent tasks environment */

  ret = env_dup(group);
  if (ret < 0)
    {
#if CONFIG_NFILE_STREAMS > 0 && (defined(CONFIG_BUILD_PROTECTED) || \
    defined(CONFIG_BUILD_KERNEL)) && defined(CONFIG_MM_KERNEL_HEAP)
      group_free(group, group->tg_streamlist);
#endif
      kmm_free(group);
      tcb->cmn.group = NULL;
      return ret;
    }

#ifndef CONFIG_DISABLE_PTHREAD
  /* Initialize the pthread join semaphore */

  (void)sem_init(&group->tg_joinsem, 0, 1);
#endif

#if defined(CONFIG_SCHED_WAITPID) && !defined(CONFIG_SCHED_HAVE_PARENT)
  /* Initialize the exit/wait semaphores
   *
   * This semaphore is used for signaling and, hence, should not have
   * priority inheritance enabled.
   */

  (void)sem_init(&group->tg_exitsem, 0, 0);
  (void)sem_setprotocol(&group->tg_exitsem, SEM_PRIO_NONE);
#endif

  return OK;
}
Beispiel #20
0
int nxflat_addrenv_alloc(FAR struct nxflat_loadinfo_s *loadinfo, size_t envsize)
{
    FAR struct dspace_s *dspace;
#ifdef CONFIG_ARCH_ADDRENV
    FAR void *vdata;
    save_addrenv_t oldenv;
    size_t heapsize;
    int ret;
#endif

    DEBUGASSERT(!loadinfo->dspace);

    /* Allocate the struct dspace_s container for the D-Space allocation */

    dspace = (FAR struct dspace_s *)kmm_malloc(sizeof(struct dspace_s));
    if (dspace == 0)
    {
        bdbg("ERROR: Failed to allocate DSpace\n");
        return -ENOMEM;
    }

#ifdef CONFIG_ARCH_ADDRENV
    /* Determine the heapsize to allocate */

#ifdef CONFIG_ARCH_STACK_DYNAMIC
    heapsize = ARCH_HEAP_SIZE;
#else
    heapsize = MIN(loadinfo->stacksize, ARCH_HEAP_SIZE);
#endif

    /* Create a D-Space address environment for the new NXFLAT task */

    ret = up_addrenv_create(0, envsize, heapsize, &loadinfo->addrenv);
    if (ret < 0)
    {
        bdbg("ERROR: up_addrenv_create failed: %d\n", ret);
        goto errout_with_dspace;
    }

    /* Get the virtual address associated with the start of the address
     * environment.  This is the base address that we will need to use to
     * access the D-Space region (but only if the address environment has been
     * selected.
     */

    ret = up_addrenv_vdata(&loadinfo->addrenv, 0, &vdata);
    if (ret < 0)
    {
        bdbg("ERROR: up_addrenv_vdata failed: %d\n", ret);
        goto errout_with_addrenv;
    }

    /* Clear all of the allocated D-Space memory.  We have to temporarily
     * selected the D-Space address environment to do this.
     */

    ret = up_addrenv_select(loadinfo->addrenv, &oldenv);
    if (ret < 0)
    {
        bdbg("ERROR: up_addrenv_select failed: %d\n", ret);
        goto errout_with_addrenv;
    }

    memset(vdata, 0, envsize);

    ret = up_addrenv_restore(oldenv);
    if (ret < 0)
    {
        bdbg("ERROR: up_addrenv_restore failed: %d\n", ret);
        goto errout_with_addrenv;
    }

    /* Success... save the fruits of our labor */

    loadinfo->dspace = dspace;
    dspace->crefs    = 1;
    dspace->region   = (FAR uint8_t *)vdata;
    return OK;

errout_with_addrenv:
    (void)up_addrenv_destroy(&loadinfo->addrenv);
    loadinfo->addrenv = 0;

errout_with_dspace:
    kmm_free(dspace);
    return ret;
#else
    /* Allocate (and zero) memory to hold the ELF image */

    dspace->region = (FAR uint8_t *)kumm_zalloc(envsize);
    if (!dspace->region)
    {
        kmm_free(dspace);
        return -ENOMEM;
    }

    loadinfo->dspace = dspace;
    dspace->crefs    = 1;
    return OK;
#endif
}
Beispiel #21
0
static int ssd1289_getrun(fb_coord_t row, fb_coord_t col, FAR uint8_t *buffer,
                          size_t npixels)
{
#ifndef CONFIG_LCD_NOGETRUN
  FAR struct ssd1289_dev_s *priv = &g_lcddev;
  FAR struct ssd1289_lcd_s *lcd = priv->lcd;
  FAR uint16_t *dest = (FAR uint16_t*)buffer;
  uint16_t accum;
  int i;
 
  /* Buffer must be provided and aligned to a 16-bit address boundary */

  ssd1289_showrun(priv, row, col, npixels, false);
  DEBUGASSERT(buffer && ((uintptr_t)buffer & 1) == 0);

  /* Select the LCD */

  lcd->select(lcd);

  /* Read the run from GRAM. */

#ifdef CONFIG_LCD_LANDSCAPE
  /* Convert coordinates -- Here the edge away from the row of buttons on
   * the STM3240G-EVAL is used as the top.
   */

  for (i = 0; i < npixels; i++)
    {
      /* Read the next pixel from this position */

      ssd1289_setcursor(lcd, row, col);
      ssd1289_gramselect(lcd);
      ssd1289_readsetup(lcd, &accum);
      *dest++ = ssd1289_gramread(lcd, &accum);

      /* Increment to the next column */

      col++;
    }
#elif defined(CONFIG_LCD_RLANDSCAPE)
  /* Convert coordinates -- Here the edge next to the row of buttons on
   * the STM3240G-EVAL is used as the top.
   */

  col = (SSD1289_XRES-1) - col;
  row = (SSD1289_YRES-1) - row;

  /* Set the cursor position */

  ssd1289_setcursor(lcd, col, row);

  /* Then read the GRAM data, auto-decrementing Y */

  ssd1289_gramselect(lcd);

  /* Prime the pump for unaligned read data */

  ssd1289_readsetup(lcd, &accum);

  for (i = 0; i < npixels; i++)
    {
      /* Read the next pixel from this position (autoincrements to the next row) */

      *dest++ = ssd1289_gramread(lcd, &accum);
    }
#elif defined(CONFIG_LCD_PORTRAIT)
  /* Convert coordinates.  In this configuration, the top of the display is to the left
   * of the buttons (if the board is held so that the buttons are at the botton of the
   * board).
   */

  col = (SSD1289_XRES-1) - col;

  /* Then read the GRAM data, manually incrementing Y (which is col) */

  for (i = 0; i < npixels; i++)
    {
      /* Read the next pixel from this position */

      ssd1289_setcursor(lcd, row, col);
      ssd1289_gramselect(lcd);
      ssd1289_readsetup(lcd, &accum);
      *dest++ = ssd1289_gramread(lcd, &accum);

      /* Increment to the next column */

      col--;
    }
#else /* CONFIG_LCD_RPORTRAIT */
  /* Convert coordinates.  In this configuration, the top of the display is to the right
   * of the buttons (if the board is held so that the buttons are at the botton of the
   * board).
   */

  row = (SSD1289_YRES-1) - row;
  
  /* Then write the GRAM data, manually incrementing Y (which is col) */

  for (i = 0; i < npixels; i++)
    {
      /* Write the next pixel to this position */

      ssd1289_setcursor(lcd, row, col);
      ssd1289_gramselect(lcd);
      ssd1289_readsetup(lcd, &accum);
      *dest++ = ssd1289_gramread(lcd, &accum);

      /* Decrement to the next column */

      col++;
    }
#endif

  /* De-select the LCD */

  lcd->deselect(lcd);
  return OK;
#else
  return -ENOSYS;
#endif
}
Beispiel #22
0
static int kinetis_irqinfo(int irq, uintptr_t *regaddr, uint32_t *bit,
                           uintptr_t offset)
{
  DEBUGASSERT(irq >= KINETIS_IRQ_NMI && irq < NR_IRQS);

  /* Check for external interrupt */

  if (irq >= KINETIS_IRQ_FIRST)
    {
      if (irq < (KINETIS_IRQ_FIRST+32))
        {
           *regaddr = (NVIC_IRQ0_31_ENABLE + offset);
           *bit     = 1 << (irq - KINETIS_IRQ_FIRST);
        }
      else if (irq < (KINETIS_IRQ_FIRST+64))
        {
           *regaddr = (NVIC_IRQ32_63_ENABLE + offset);
           *bit     = 1 << (irq - KINETIS_IRQ_FIRST - 32);
        }
      else if (irq < (KINETIS_IRQ_FIRST+96))
        {
           *regaddr = (NVIC_IRQ64_95_ENABLE + offset);
           *bit     = 1 << (irq - KINETIS_IRQ_FIRST - 64);
        }
      else if (irq < NR_IRQS)
        {
           *regaddr = (NVIC_IRQ96_127_ENABLE + offset);
           *bit     = 1 << (irq - KINETIS_IRQ_FIRST - 96);
        }
      else
        {
          return ERROR; /* Invalid irq */
        }
    }

  /* Handle processor exceptions.  Only a few can be disabled */

  else
    {
      *regaddr = NVIC_SYSHCON;
      if (irq == KINETIS_IRQ_MEMFAULT)
        {
          *bit = NVIC_SYSHCON_MEMFAULTENA;
        }
      else if (irq == KINETIS_IRQ_BUSFAULT)
        {
          *bit = NVIC_SYSHCON_BUSFAULTENA;
        }
      else if (irq == KINETIS_IRQ_USAGEFAULT)
        {
          *bit = NVIC_SYSHCON_USGFAULTENA;
        }
      else if (irq == KINETIS_IRQ_SYSTICK)
        {
          *regaddr = NVIC_SYSTICK_CTRL;
          *bit = NVIC_SYSTICK_CTRL_ENABLE;
        }
      else
        {
          return ERROR; /* Invalid or unsupported exception */
        }
    }

  return OK;
}
Beispiel #23
0
CURLcode Curl_is_connected(struct connectdata *conn,
                           int sockindex,
                           bool *connected)
{
  int rc;
  struct SessionHandle *data = conn->data;
  CURLcode code = CURLE_OK;
  curl_socket_t sockfd = conn->sock[sockindex];
  long allow = DEFAULT_CONNECT_TIMEOUT;
  long allow_total = 0;
  long has_passed;

  DEBUGASSERT(sockindex >= FIRSTSOCKET && sockindex <= SECONDARYSOCKET);

  *connected = FALSE; /* a very negative world view is best */

  /* Evaluate in milliseconds how much time that has passed */
  has_passed = Curl_tvdiff(Curl_tvnow(), data->progress.t_startsingle);

  /* subtract the most strict timeout of the ones */
  if(data->set.timeout && data->set.connecttimeout) {
    if (data->set.timeout < data->set.connecttimeout)
      allow_total = allow = data->set.timeout;
    else
      allow = data->set.connecttimeout;
  }
  else if(data->set.timeout) {
    allow_total = allow = data->set.timeout;
  }
  else if(data->set.connecttimeout) {
    allow = data->set.connecttimeout;
  }

  if(has_passed > allow ) {
    /* time-out, bail out, go home */
    failf(data, "Connection time-out after %ld ms", has_passed);
    return CURLE_OPERATION_TIMEOUTED;
  }
  if(conn->bits.tcpconnect) {
    /* we are connected already! */
    Curl_expire(data, allow_total);
    *connected = TRUE;
    return CURLE_OK;
  }

  Curl_expire(data, allow);

  /* check for connect without timeout as we want to return immediately */
  rc = waitconnect(sockfd, 0);

  if(WAITCONN_CONNECTED == rc) {
    int error;
    if (verifyconnect(sockfd, &error)) {
      /* we are connected, awesome! */
      *connected = TRUE;
      return CURLE_OK;
    }
    /* nope, not connected for real */
    data->state.os_errno = error;
    infof(data, "Connection failed\n");
    if(trynextip(conn, sockindex, connected)) {
      code = CURLE_COULDNT_CONNECT;
    }
  }
  else if(WAITCONN_TIMEOUT != rc) {
    int error = 0;

    /* nope, not connected  */
    if (WAITCONN_FDSET_ERROR == rc) {
      (void)verifyconnect(sockfd, &error);
      data->state.os_errno = error;
      infof(data, "%s\n",Curl_strerror(conn,error));
    }
    else
      infof(data, "Connection failed\n");

    if(trynextip(conn, sockindex, connected)) {
      error = SOCKERRNO;
      data->state.os_errno = error;
      failf(data, "Failed connect to %s:%d; %s",
            conn->host.name, conn->port, Curl_strerror(conn,error));
      code = CURLE_COULDNT_CONNECT;
    }
  }
  /*
   * If the connection failed here, we should attempt to connect to the "next
   * address" for the given host.
   */

  return code;
}
Beispiel #24
0
static int on_frame_recv(nghttp2_session *session, const nghttp2_frame *frame,
                         void *userp)
{
  struct connectdata *conn = NULL;
  struct http_conn *httpc = NULL;
  struct SessionHandle *data_s = NULL;
  struct HTTP *stream = NULL;
  static int lastStream = -1;
  int rv;
  size_t left, ncopy;
  int32_t stream_id = frame->hd.stream_id;

  (void)userp;

  if(!stream_id) {
    /* stream ID zero is for connection-oriented stuff */
    return 0;
  }
  data_s = nghttp2_session_get_stream_user_data(session,
                                                frame->hd.stream_id);
  if(lastStream != frame->hd.stream_id) {
    lastStream = frame->hd.stream_id;
  }
  if(!data_s) {
    DEBUGF(infof(conn->data,
                 "No SessionHandle associated with stream: %x\n",
                 stream_id));
    return 0;
  }

  stream = data_s->req.protop;
  if(!stream)
    return NGHTTP2_ERR_CALLBACK_FAILURE;

  DEBUGF(infof(data_s, "on_frame_recv() header %x stream %x\n",
               frame->hd.type, stream_id));

  conn = data_s->easy_conn;
  assert(conn);
  assert(conn->data == data_s);
  httpc = &conn->proto.httpc;
  switch(frame->hd.type) {
  case NGHTTP2_DATA:
    /* If body started on this stream, then receiving DATA is illegal. */
    if(!stream->bodystarted) {
      rv = nghttp2_submit_rst_stream(session, NGHTTP2_FLAG_NONE,
                                     stream_id, NGHTTP2_PROTOCOL_ERROR);

      if(nghttp2_is_fatal(rv)) {
        return NGHTTP2_ERR_CALLBACK_FAILURE;
      }
    }
    break;
  case NGHTTP2_HEADERS:
    if(frame->headers.cat == NGHTTP2_HCAT_REQUEST)
      break;

    if(stream->bodystarted) {
      /* Only valid HEADERS after body started is trailer HEADERS.  We
         ignores trailer HEADERS for now.  nghttp2 guarantees that it
         has END_STREAM flag set. */
      break;
    }

    /* nghttp2 guarantees that :status is received, and we store it to
       stream->status_code */
    DEBUGASSERT(stream->status_code != -1);

    /* Only final status code signals the end of header */
    if(stream->status_code / 100 != 1) {
      stream->bodystarted = TRUE;
      stream->status_code = -1;
    }

    Curl_add_buffer(stream->header_recvbuf, "\r\n", 2);

    left = stream->header_recvbuf->size_used - stream->nread_header_recvbuf;
    ncopy = MIN(stream->len, left);

    memcpy(&stream->mem[stream->memlen],
           stream->header_recvbuf->buffer + stream->nread_header_recvbuf,
           ncopy);
    stream->nread_header_recvbuf += ncopy;

    DEBUGF(infof(data_s, "Store %zu bytes headers from stream %u at %p\n",
                 ncopy, stream_id, stream->mem));

    stream->len -= ncopy;
    stream->memlen += ncopy;

    data_s->state.drain++;
    Curl_expire(data_s, 1);
    break;
  case NGHTTP2_PUSH_PROMISE:
    rv = push_promise(data_s, conn, &frame->push_promise);
    if(rv) { /* deny! */
      rv = nghttp2_submit_rst_stream(session, NGHTTP2_FLAG_NONE,
                                     frame->push_promise.promised_stream_id,
                                     NGHTTP2_CANCEL);
      if(nghttp2_is_fatal(rv)) {
        return rv;
      }
    }
    break;
  case NGHTTP2_SETTINGS:
  {
    uint32_t max_conn = httpc->settings.max_concurrent_streams;
    DEBUGF(infof(conn->data, "Got SETTINGS for stream %u!\n", stream_id));
    httpc->settings.max_concurrent_streams =
      nghttp2_session_get_remote_settings(
        session, NGHTTP2_SETTINGS_MAX_CONCURRENT_STREAMS);
    httpc->settings.enable_push =
      nghttp2_session_get_remote_settings(
        session, NGHTTP2_SETTINGS_ENABLE_PUSH);
    DEBUGF(infof(conn->data, "MAX_CONCURRENT_STREAMS == %d\n",
                 httpc->settings.max_concurrent_streams));
    DEBUGF(infof(conn->data, "ENABLE_PUSH == %s\n",
                 httpc->settings.enable_push?"TRUE":"false"));
    if(max_conn != httpc->settings.max_concurrent_streams) {
      /* only signal change if the value actually changed */
      infof(conn->data,
            "Connection state changed (MAX_CONCURRENT_STREAMS updated)!\n");
      Curl_multi_connchanged(conn->data->multi);
    }
  }
  break;
  default:
    DEBUGF(infof(conn->data, "Got frame type %x for stream %u!\n",
                 frame->hd.type, stream_id));
    break;
  }
  return 0;
}
Beispiel #25
0
Datei: rtsp.c Projekt: 2px/curl
static CURLcode rtsp_rtp_readwrite(struct Curl_easy *data,
                                   struct connectdata *conn,
                                   ssize_t *nread,
                                   bool *readmore) {
  struct SingleRequest *k = &data->req;
  struct rtsp_conn *rtspc = &(conn->proto.rtspc);

  char *rtp; /* moving pointer to rtp data */
  ssize_t rtp_dataleft; /* how much data left to parse in this round */
  char *scratch;
  CURLcode result;

  if(rtspc->rtp_buf) {
    /* There was some leftover data the last time. Merge buffers */
    char *newptr = realloc(rtspc->rtp_buf, rtspc->rtp_bufsize + *nread);
    if(!newptr) {
      Curl_safefree(rtspc->rtp_buf);
      rtspc->rtp_buf = NULL;
      rtspc->rtp_bufsize = 0;
      return CURLE_OUT_OF_MEMORY;
    }
    rtspc->rtp_buf = newptr;
    memcpy(rtspc->rtp_buf + rtspc->rtp_bufsize, k->str, *nread);
    rtspc->rtp_bufsize += *nread;
    rtp = rtspc->rtp_buf;
    rtp_dataleft = rtspc->rtp_bufsize;
  }
  else {
    /* Just parse the request buffer directly */
    rtp = k->str;
    rtp_dataleft = *nread;
  }

  while((rtp_dataleft > 0) &&
        (rtp[0] == '$')) {
    if(rtp_dataleft > 4) {
      int rtp_length;

      /* Parse the header */
      /* The channel identifier immediately follows and is 1 byte */
      rtspc->rtp_channel = RTP_PKT_CHANNEL(rtp);

      /* The length is two bytes */
      rtp_length = RTP_PKT_LENGTH(rtp);

      if(rtp_dataleft < rtp_length + 4) {
        /* Need more - incomplete payload*/
        *readmore = TRUE;
        break;
      }
      else {
        /* We have the full RTP interleaved packet
         * Write out the header including the leading '$' */
        DEBUGF(infof(data, "RTP write channel %d rtp_length %d\n",
              rtspc->rtp_channel, rtp_length));
        result = rtp_client_write(conn, &rtp[0], rtp_length + 4);
        if(result) {
          failf(data, "Got an error writing an RTP packet");
          *readmore = FALSE;
          Curl_safefree(rtspc->rtp_buf);
          rtspc->rtp_buf = NULL;
          rtspc->rtp_bufsize = 0;
          return result;
        }

        /* Move forward in the buffer */
        rtp_dataleft -= rtp_length + 4;
        rtp += rtp_length + 4;

        if(data->set.rtspreq == RTSPREQ_RECEIVE) {
          /* If we are in a passive receive, give control back
           * to the app as often as we can.
           */
          k->keepon &= ~KEEP_RECV;
        }
      }
    }
    else {
      /* Need more - incomplete header */
      *readmore = TRUE;
      break;
    }
  }

  if(rtp_dataleft != 0 && rtp[0] == '$') {
    DEBUGF(infof(data, "RTP Rewinding %zd %s\n", rtp_dataleft,
          *readmore ? "(READMORE)" : ""));

    /* Store the incomplete RTP packet for a "rewind" */
    scratch = malloc(rtp_dataleft);
    if(!scratch) {
      Curl_safefree(rtspc->rtp_buf);
      rtspc->rtp_buf = NULL;
      rtspc->rtp_bufsize = 0;
      return CURLE_OUT_OF_MEMORY;
    }
    memcpy(scratch, rtp, rtp_dataleft);
    Curl_safefree(rtspc->rtp_buf);
    rtspc->rtp_buf = scratch;
    rtspc->rtp_bufsize = rtp_dataleft;

    /* As far as the transfer is concerned, this data is consumed */
    *nread = 0;
    return CURLE_OK;
  }
  else {
    /* Fix up k->str to point just after the last RTP packet */
    k->str += *nread - rtp_dataleft;

    /* either all of the data has been read or...
     * rtp now points at the next byte to parse
     */
    if(rtp_dataleft > 0)
      DEBUGASSERT(k->str[0] == rtp[0]);

    DEBUGASSERT(rtp_dataleft <= *nread); /* sanity check */

    *nread = rtp_dataleft;
  }

  /* If we get here, we have finished with the leftover/merge buffer */
  Curl_safefree(rtspc->rtp_buf);
  rtspc->rtp_buf = NULL;
  rtspc->rtp_bufsize = 0;

  return CURLE_OK;
}
Beispiel #26
0
/* frame->hd.type is either NGHTTP2_HEADERS or NGHTTP2_PUSH_PROMISE */
static int on_header(nghttp2_session *session, const nghttp2_frame *frame,
                     const uint8_t *name, size_t namelen,
                     const uint8_t *value, size_t valuelen,
                     uint8_t flags,
                     void *userp)
{
  struct HTTP *stream;
  struct SessionHandle *data_s;
  int32_t stream_id = frame->hd.stream_id;

  (void)flags;
  (void)userp;

  DEBUGASSERT(stream_id); /* should never be a zero stream ID here */

  /* get the stream from the hash based on Stream ID */
  data_s = nghttp2_session_get_stream_user_data(session, stream_id);
  if(!data_s)
    /* Receiving a Stream ID not in the hash should not happen, this is an
       internal error more than anything else! */
    return NGHTTP2_ERR_CALLBACK_FAILURE;

  stream = data_s->req.protop;
  if(!stream) {
    failf(data_s, "Internal NULL stream! 5\n");
    return NGHTTP2_ERR_CALLBACK_FAILURE;
  }

  if(stream->bodystarted)
    /* Ignore trailer or HEADERS not mapped to HTTP semantics.  The
       consequence is handled in on_frame_recv(). */
    return 0;

  /* Store received PUSH_PROMISE headers to be used when the subsequent
     PUSH_PROMISE callback comes */
  if(frame->hd.type == NGHTTP2_PUSH_PROMISE) {
    char *h;

    if(!stream->push_headers) {
      stream->push_headers_alloc = 10;
      stream->push_headers = malloc(stream->push_headers_alloc *
                                    sizeof(char *));
      stream->push_headers_used = 0;
    }
    else if(stream->push_headers_used ==
            stream->push_headers_alloc) {
      char **headp;
      stream->push_headers_alloc *= 2;
      headp = realloc(stream->push_headers,
                      stream->push_headers_alloc * sizeof(char *));
      if(!headp) {
        free(stream->push_headers);
        stream->push_headers = NULL;
        return NGHTTP2_ERR_TEMPORAL_CALLBACK_FAILURE;
      }
      stream->push_headers = headp;
    }
    h = aprintf("%s:%s", name, value);
    if(h)
      stream->push_headers[stream->push_headers_used++] = h;
    return 0;
  }

  if(namelen == sizeof(":status") - 1 &&
     memcmp(":status", name, namelen) == 0) {
    /* nghttp2 guarantees :status is received first and only once, and
       value is 3 digits status code, and decode_status_code always
       succeeds. */
    stream->status_code = decode_status_code(value, valuelen);
    DEBUGASSERT(stream->status_code != -1);

    Curl_add_buffer(stream->header_recvbuf, "HTTP/2.0 ", 9);
    Curl_add_buffer(stream->header_recvbuf, value, valuelen);
    Curl_add_buffer(stream->header_recvbuf, "\r\n", 2);
    data_s->state.drain++;
    Curl_expire(data_s, 1);

    DEBUGF(infof(data_s, "h2 status: HTTP/2 %03d\n",
                 stream->status_code));
    return 0;
  }

  /* nghttp2 guarantees that namelen > 0, and :status was already
     received, and this is not pseudo-header field . */
  /* convert to a HTTP1-style header */
  Curl_add_buffer(stream->header_recvbuf, name, namelen);
  Curl_add_buffer(stream->header_recvbuf, ":", 1);
  Curl_add_buffer(stream->header_recvbuf, value, valuelen);
  Curl_add_buffer(stream->header_recvbuf, "\r\n", 2);
  data_s->state.drain++;
  Curl_expire(data_s, 1);

  DEBUGF(infof(data_s, "h2 header: %.*s: %.*s\n", namelen, name, valuelen,
               value));

  return 0; /* 0 is successful */
}
Beispiel #27
0
int lib_mode2oflags(FAR const char *mode)
{
  unsigned int state;
  int oflags;

  /* Verify that a mode string was provided.  */

  DEBUGASSERT(mode);

  /* Parse the mode string to determine the corresponding open flags */

  state  = MODE_NONE;
  oflags = 0;

  for (; *mode; mode++)
    {
      switch (*mode)
        {
          /* Open for read access ("r{b|x|+}") */

          case 'r' :
            if (state == MODE_NONE)
              {
                /* Open for read access */

                oflags = O_RDOK;
                state  = MODE_R;
              }
            else
              {
                goto errout;
              }
            break;

          /* Open for write access ("w{b|x|+}") */

          case 'w' :
            if (state == MODE_NONE)
              {
                /* Open for write access, truncating any existing file */

                oflags = (O_WROK | O_CREAT | O_TRUNC);
                state  = MODE_W;
              }
            else
              {
                goto errout;
              }
            break;

          /* Open for write/append access ("a{b|x|+}") */

          case 'a' :
            if (state == MODE_NONE)
              {
                /* Write to the end of the file */

                oflags = O_WROK | O_CREAT | O_APPEND;
                state  = MODE_A;
              }
            else
              {
                goto errout;
              }
            break;

          /* Open for update access ("{r|w|a|b|x}+") */

          case '+' :
            switch (state & MODE_MASK)
              {
                case MODE_R:
                  {
                    /* Retain any binary and exclusive mode selections */

                    oflags &= (O_BINARY | O_EXCL);

                    /* Open for read/write access */

                    oflags |= O_RDWR;
                    state  |= MODE_PLUS;
                 }
                 break;

                case MODE_W:
                  {
                    /* Retain any binary and exclusive mode selections */

                    oflags &= (O_BINARY | O_EXCL);

                    /* Open for write read/access, truncating any existing file */

                    oflags |= (O_RDWR | O_CREAT | O_TRUNC);
                    state  |= MODE_PLUS;
                  }
                  break;

                case MODE_A:
                  {
                    /* Retain any binary and exclusive mode selections */

                    oflags &= (O_BINARY | O_EXCL);

                    /* Read from the beginning of the file; write to the end */

                    oflags |= (O_RDWR | O_CREAT | O_APPEND);
                    state  |= MODE_PLUS;
                  }
                  break;

                default:
                  goto errout;
                  break;
              }
            break;

          /* Open for binary access ("{r|w|a|x|+}b") */

          case 'b' :
            if ((state & MODE_MASK) != MODE_NONE)
              {
                /* The file is opened in binary mode */

                oflags |= O_BINARY;
                state  |= MODE_B;
              }
            else
              {
                goto errout;
              }
            break;

          /* Open for exclusive access ("{r|w|a|b|+}x") */

          case 'X' :
            if ((state & MODE_MASK) != MODE_NONE)
              {
                /* The file is opened in exclusive mode */

                oflags |= O_EXCL;
                state  |= MODE_X;
              }
            else
              {
                goto errout;
              }
            break;

          /* Unrecognized or unsupported mode */

          default:
            goto errout;
            break;
        }
    }

  return oflags;

/* Both fopen and fdopen should fail with errno == EINVAL if the mode
 * string is invalid.
 */

errout:
  set_errno(EINVAL);
  return ERROR;
}
Beispiel #28
0
CURLcode Curl_is_connected(struct connectdata *conn,
                           int sockindex,
                           bool *connected)
{
  struct SessionHandle *data = conn->data;
  CURLcode result = CURLE_OK;
  long allow;
  int error = 0;
  struct timeval now;
  int rc;
  int i;

  DEBUGASSERT(sockindex >= FIRSTSOCKET && sockindex <= SECONDARYSOCKET);

  *connected = FALSE; /* a very negative world view is best */

  if(conn->bits.tcpconnect[sockindex]) {
    /* we are connected already! */
    *connected = TRUE;
    return CURLE_OK;
  }

  now = Curl_tvnow();

  /* figure out how long time we have left to connect */
  allow = Curl_timeleft(data, &now, TRUE);

  if(allow < 0) {
    /* time-out, bail out, go home */
    failf(data, "Connection time-out");
    return CURLE_OPERATION_TIMEDOUT;
  }

  for(i=0; i<2; i++) {
    if(conn->tempsock[i] == CURL_SOCKET_BAD)
      continue;

#ifdef mpeix
    /* Call this function once now, and ignore the results. We do this to
       "clear" the error state on the socket so that we can later read it
       reliably. This is reported necessary on the MPE/iX operating system. */
    (void)verifyconnect(conn->tempsock[i], NULL);
#endif

    /* check socket for connect */
    rc = Curl_socket_ready(CURL_SOCKET_BAD, conn->tempsock[i], 0);

    if(rc == 0) { /* no connection yet */
      if(curlx_tvdiff(now, conn->connecttime) >= conn->timeoutms_per_addr) {
        infof(data, "After %ldms connect time, move on!\n",
              conn->timeoutms_per_addr);
        error = ETIMEDOUT;
      }

      /* should we try another protocol family? */
      if(i == 0 && conn->tempaddr[1] == NULL &&
         curlx_tvdiff(now, conn->connecttime) >= HAPPY_EYEBALLS_TIMEOUT) {
        trynextip(conn, sockindex, 1);
      }
    }
    else if(rc == CURL_CSELECT_OUT) {
      if(verifyconnect(conn->tempsock[i], &error)) {
        /* we are connected with TCP, awesome! */
        int other = i ^ 1;

        /* use this socket from now on */
        conn->sock[sockindex] = conn->tempsock[i];
        conn->ip_addr = conn->tempaddr[i];
        conn->tempsock[i] = CURL_SOCKET_BAD;

        /* close the other socket, if open */
        if(conn->tempsock[other] != CURL_SOCKET_BAD) {
          Curl_closesocket(conn, conn->tempsock[other]);
          conn->tempsock[other] = CURL_SOCKET_BAD;
        }

        /* see if we need to do any proxy magic first once we connected */
        result = Curl_connected_proxy(conn, sockindex);
        if(result)
          return result;

        conn->bits.tcpconnect[sockindex] = TRUE;

        *connected = TRUE;
        if(sockindex == FIRSTSOCKET)
          Curl_pgrsTime(data, TIMER_CONNECT); /* connect done */
        Curl_updateconninfo(conn, conn->sock[sockindex]);
        Curl_verboseconnect(conn);

        return CURLE_OK;
      }
      else
        infof(data, "Connection failed\n");
    }
    else if(rc & CURL_CSELECT_ERR)
      (void)verifyconnect(conn->tempsock[i], &error);

    /*
     * The connection failed here, we should attempt to connect to the "next
     * address" for the given host. But first remember the latest error.
     */
    if(error) {
      data->state.os_errno = error;
      SET_SOCKERRNO(error);
      if(conn->tempaddr[i]) {
        char ipaddress[MAX_IPADR_LEN];
        Curl_printable_address(conn->tempaddr[i], ipaddress, MAX_IPADR_LEN);
        infof(data, "connect to %s port %ld failed: %s\n",
              ipaddress, conn->port, Curl_strerror(conn, error));

        conn->timeoutms_per_addr = conn->tempaddr[i]->ai_next == NULL ?
                                   allow : allow / 2;

        result = trynextip(conn, sockindex, i);
      }
    }
  }

  if(result) {
    /* no more addresses to try */

    /* if the first address family runs out of addresses to try before
       the happy eyeball timeout, go ahead and try the next family now */
    if(conn->tempaddr[1] == NULL) {
      result = trynextip(conn, sockindex, 1);
      if(!result)
        return result;
    }

    failf(data, "Failed to connect to %s port %ld: %s",
          conn->bits.proxy?conn->proxy.name:conn->host.name,
          conn->port, Curl_strerror(conn, error));
  }

  return result;
}
Beispiel #29
0
static int procfs_opendir(FAR struct inode *mountpt, FAR const char *relpath,
                          FAR struct fs_dirent_s *dir)
{
    FAR struct procfs_level0_s *level0;
    FAR struct procfs_dir_priv_s *dirpriv;
    FAR void *priv = NULL;
    irqstate_t flags;

    fvdbg("relpath: \"%s\"\n", relpath ? relpath : "NULL");
    DEBUGASSERT(mountpt && relpath && dir && !dir->u.procfs);

    /* The relative must be either:
     *
     * ""      - The top level directory of task/thread IDs
     * "<pid>" - The sub-directory of task/thread attributes
     */

    if (!relpath || relpath[0] == '\0')
    {
        /* The path refers to the top level directory.  Allocate the level0
         * dirent structure.
         */

        level0 = (FAR struct procfs_level0_s *)
                 kmm_zalloc(sizeof(struct procfs_level0_s));

        if (!level0)
        {
            fdbg("ERROR: Failed to allocate the level0 directory structure\n");
            return -ENOMEM;
        }

        /* Take a snapshot of all currently active tasks.  Any new tasks
         * added between the opendir() and closedir() call will not be
         * visible.
         *
         * NOTE that interrupts must be disabled throughout the traversal.
         */

#ifndef CONFIG_FS_PROCFS_EXCLUDE_PROCESS
        flags = irqsave();
        sched_foreach(procfs_enum, level0);
        irqrestore(flags);
#else
        level0->base.index = 0;
        level0->base.nentries = 0;
#endif

        /* Initialze lastread entries */

        level0->lastread = "";
        level0->lastlen = 0;
        level0->base.procfsentry = NULL;

        priv = (FAR void *)level0;
    }
    else
    {
        int x, ret;
        int len = strlen(relpath);

        /* Search the static array of procfs_entries */

        for (x = 0; x < g_procfsentrycount; x++)
        {
            /* Test if the path matches this entry's specification */

            if (match(g_procfsentries[x].pathpattern, relpath))
            {
                /* Match found!  Call the handler's opendir routine.  If successful,
                 * this opendir routine will create an entry derived from struct
                 * procfs_dir_priv_s as dir->u.procfs.
                 */

                DEBUGASSERT(g_procfsentries[x].ops && g_procfsentries[x].ops->opendir);
                ret = g_procfsentries[x].ops->opendir(relpath, dir);

                if (ret == OK)
                {
                    DEBUGASSERT(dir->u.procfs);

                    /* Set the procfs_entry handler */

                    dirpriv = (FAR struct procfs_dir_priv_s *)dir->u.procfs;
                    dirpriv->procfsentry = &g_procfsentries[x];
                }

                return ret;
            }

            /* Test for a sub-string match (e.g. "ls /proc/fs") */

            else if (strncmp(g_procfsentries[x].pathpattern, relpath, len) == 0)
            {
                FAR struct procfs_level1_s *level1;

                /* Doing an intermediate directory search */

                /* The path refers to the top level directory.  Allocate the level0
                 * dirent structure.
                 */

                level1 = (FAR struct procfs_level1_s *)
                         kmm_zalloc(sizeof(struct procfs_level1_s));

                if (!level1)
                {
                    fdbg("ERROR: Failed to allocate the level0 directory structure\n");
                    return -ENOMEM;
                }

                level1->base.level = 1;
                level1->base.index = x;
                level1->firstindex = x;
                level1->subdirlen = len;
                level1->lastread = "";
                level1->lastlen = 0;
                level1->base.procfsentry = NULL;

                priv = (FAR void *)level1;
                break;
            }
        }
    }

    dir->u.procfs = priv;
    return OK;
}
Beispiel #30
0
pid_t waitpid(pid_t pid, int *stat_loc, int options)
{
  FAR struct tcb_s *rtcb = this_task();
  FAR struct tcb_s *ctcb;
#ifdef CONFIG_SCHED_CHILD_STATUS
  FAR struct child_status_s *child;
  bool retains;
#endif
  FAR struct siginfo info;
  sigset_t set;
  int errcode;
  int ret;

  DEBUGASSERT(stat_loc);

  /* waitpid() is a cancellation point */

  (void)enter_cancellation_point();

  /* None of the options are supported */

#ifdef CONFIG_DEBUG_FEATURES
  if (options != 0)
    {
      set_errno(ENOSYS);
      leave_cancellation_point();
      return ERROR;
    }
#endif

  /* Create a signal set that contains only SIGCHLD */

  (void)sigemptyset(&set);
  (void)sigaddset(&set, SIGCHLD);

  /* Disable pre-emption so that nothing changes while the loop executes */

  sched_lock();

  /* Verify that this task actually has children and that the requested PID
   * is actually a child of this task.
   */

#ifdef CONFIG_SCHED_CHILD_STATUS
  /* Does this task retain child status? */

  retains = ((rtcb->group->tg_flags && GROUP_FLAG_NOCLDWAIT) == 0);

  if (rtcb->group->tg_children == NULL && retains)
    {
      errcode = ECHILD;
      goto errout_with_errno;
    }
  else if (pid != (pid_t)-1)
    {
      /* Get the TCB corresponding to this PID and make sure that the
       * thread it is our child.
       */

      ctcb = sched_gettcb(pid);

#ifdef HAVE_GROUP_MEMBERS
      if (ctcb == NULL || ctcb->group->tg_pgid != rtcb->group->tg_gid)
#else
      if (ctcb == NULL || ctcb->group->tg_ppid != rtcb->pid)
#endif
        {
          errcode = ECHILD;
          goto errout_with_errno;
        }

      /* Does this task retain child status? */

      if (retains)
        {
          /* Check if this specific pid has allocated child status? */

          if (group_findchild(rtcb->group, pid) == NULL)
            {
              errcode = ECHILD;
              goto errout_with_errno;
            }
        }
    }

#else /* CONFIG_SCHED_CHILD_STATUS */

  if (rtcb->group->tg_nchildren == 0)
    {
      /* There are no children */

      errcode = ECHILD;
      goto errout_with_errno;
    }
  else if (pid != (pid_t)-1)
    {
      /* Get the TCB corresponding to this PID and make sure that the
       * thread it is our child.
       */

      ctcb = sched_gettcb(pid);

#ifdef HAVE_GROUP_MEMBERS
      if (ctcb == NULL || ctcb->group->tg_pgid != rtcb->group->tg_gid)
#else
      if (ctcb == NULL || ctcb->group->tg_ppid != rtcb->pid)
#endif
        {
          errcode = ECHILD;
          goto errout_with_errno;
        }
    }

#endif /* CONFIG_SCHED_CHILD_STATUS */

  /* Loop until the child that we are waiting for dies */

  for (; ; )
    {
#ifdef CONFIG_SCHED_CHILD_STATUS
      /* Check if the task has already died. Signals are not queued in
       * NuttX.  So a possibility is that the child has died and we
       * missed the death of child signal (we got some other signal
       * instead).
       */

      if (pid == (pid_t)-1)
        {
          /* We are waiting for any child, check if there are still
           * chilren.
           */

          DEBUGASSERT(!retains || rtcb->group->tg_children);
          if (retains && (child = group_exitchild(rtcb->group)) != NULL)
            {
              /* A child has exited.  Apparently we missed the signal.
               * Return the saved exit status.
               */

              /* The child has exited. Return the saved exit status */

              *stat_loc = child->ch_status << 8;

              /* Discard the child entry and break out of the loop */

              (void)group_removechild(rtcb->group, child->ch_pid);
              group_freechild(child);
              break;
            }
        }

      /* We are waiting for a specific PID. Does this task retain child status? */

      else if (retains)
        {
          /* Get the current status of the child task. */

          child = group_findchild(rtcb->group, pid);
          DEBUGASSERT(child);

          /* Did the child exit? */

          if ((child->ch_flags & CHILD_FLAG_EXITED) != 0)
            {
              /* The child has exited. Return the saved exit status */

              *stat_loc = child->ch_status << 8;

              /* Discard the child entry and break out of the loop */

              (void)group_removechild(rtcb->group, pid);
              group_freechild(child);
              break;
            }
        }
      else
        {
          /* We can use kill() with signal number 0 to determine if that
           * task is still alive.
           */

          ret = kill(pid, 0);
          if (ret < 0)
            {
              /* It is no longer running.  We know that the child task
               * was running okay when we started, so we must have lost
               * the signal.  In this case, we know that the task exit'ed,
               * but we do not know its exit status.  It would be better
               * to reported ECHILD than bogus status.
               */

              errcode = ECHILD;
              goto errout_with_errno;
            }
        }

#else  /* CONFIG_SCHED_CHILD_STATUS */

      /* Check if the task has already died. Signals are not queued in
       * NuttX.  So a possibility is that the child has died and we
       * missed the death of child signal (we got some other signal
       * instead).
       */

      if (rtcb->group->tg_nchildren == 0 ||
          (pid != (pid_t)-1 && (ret = kill(pid, 0)) < 0))
        {
          /* We know that the child task was running okay we stared,
           * so we must have lost the signal.  What can we do?
           * Let's return ECHILD.. that is at least informative.
           */

          errcode = ECHILD;
          goto errout_with_errno;
        }

#endif /* CONFIG_SCHED_CHILD_STATUS */

      /* Wait for any death-of-child signal */

      ret = sigwaitinfo(&set, &info);
      if (ret < 0)
        {
          goto errout_with_lock;
        }

      /* Was this the death of the thread we were waiting for? In the of
       * pid == (pid_t)-1, we are waiting for any child thread.
       */

      if (info.si_signo == SIGCHLD &&
         (pid == (pid_t)-1 || info.si_pid == pid))
        {
          /* Yes... return the status and PID (in the event it was -1) */

          *stat_loc = info.si_status << 8;
          pid = info.si_pid;
          break;
        }
    }

  leave_cancellation_point();
  sched_unlock();
  return (int)pid;

errout_with_errno:
  set_errno(errcode);

errout_with_lock:
  leave_cancellation_point();
  sched_unlock();
  return ERROR;
}