Exemplo n.º 1
0
static int http_listen(URLContext *h, const char *uri, int flags,
                       AVDictionary **options) {
    HTTPContext *s = h->priv_data;
    int ret;
    static const char header[] = "HTTP/1.1 200 OK\r\nContent-Type: application/octet-stream\r\nTransfer-Encoding: chunked\r\n\r\n";
    char hostname[1024], proto[10];
    char lower_url[100];
    const char *lower_proto = "tcp";
    int port, new_location;
    av_url_split(proto, sizeof(proto), NULL, 0, hostname, sizeof(hostname), &port,
                 NULL, 0, uri);
    if (!strcmp(proto, "https"))
        lower_proto = "tls";
    ff_url_join(lower_url, sizeof(lower_url), lower_proto, NULL, hostname, port,
                NULL);
    av_dict_set(options, "listen", "1", 0);
    if ((ret = ffurl_open(&s->hd, lower_url, AVIO_FLAG_READ_WRITE,
                          &h->interrupt_callback, options)) < 0)
        goto fail;
    if ((ret = http_read_header(h, &new_location)) < 0)
         goto fail;
    if ((ret = ffurl_write(s->hd, header, strlen(header))) < 0)
         goto fail;
    return 0;

fail:
    handle_http_errors(h, ret);
    av_dict_free(&s->chained_options);
    return ret;
}
Exemplo n.º 2
0
static int http_read_stream(URLContext *h, uint8_t *buf, int size)
{
    HTTPContext *s = h->priv_data;
    int err, new_location, read_ret, seek_ret;

    if (!s->hd)
        return AVERROR_EOF;

    if (s->end_chunked_post && !s->end_header) {
        err = http_read_header(h, &new_location);
        if (err < 0)
            return err;
    }

    if (s->chunksize >= 0) {
        if (!s->chunksize) {
            char line[32];

                do {
                    if ((err = http_get_line(s, line, sizeof(line))) < 0)
                        return err;
                } while (!*line);    /* skip CR LF from last chunk */

                s->chunksize = strtoll(line, NULL, 16);

                av_log(NULL, AV_LOG_TRACE, "Chunked encoding data size: %"PRId64"'\n",
                        s->chunksize);

                if (!s->chunksize)
                    return 0;
        }
        size = FFMIN(size, s->chunksize);
    }
#if CONFIG_ZLIB
    if (s->compressed)
        return http_buf_read_compressed(h, buf, size);
#endif /* CONFIG_ZLIB */
    read_ret = http_buf_read(h, buf, size);
    if (read_ret < 0 && s->reconnect && !h->is_streamed && s->filesize > 0 && s->off < s->filesize) {
        av_log(h, AV_LOG_INFO, "Will reconnect at %"PRId64".\n", s->off);
        seek_ret = http_seek_internal(h, s->off, SEEK_SET, 1);
        if (seek_ret != s->off) {
            av_log(h, AV_LOG_ERROR, "Failed to reconnect at %"PRId64".\n", s->off);
            return read_ret;
        }

        read_ret = http_buf_read(h, buf, size);
    }

    return read_ret;
}
Exemplo n.º 3
0
/**
 *  @return
 *   -1 if a header was invalid (see http status for details).
 *    0 if the end-of-headers was reached.
 *    1 if a header was successfully parsed.
 */
int
http_parse_header(http_t *ctx, char *buf, size_t buf_size,
    char **name_ptr, char **value_ptr)
{
  char *value;
 
  RUNTIME_ASSERT(ctx);
  RUNTIME_ASSERT(HTTP_STATE_HEADERS == ctx->state);

  if (name_ptr)
    *name_ptr = NULL;
  if (value_ptr)
    *value_ptr = NULL;
  
  switch (http_read_header(ctx, buf, buf_size)) {
  case -1:
    DBUG("http_read_header() failed: %u \"%s\"",
    ctx->status_code, ctx->status_msg);
    return -1;
    
  case 0:
    ctx->state = HTTP_STATE_BODY;
    return 0;

  case 1:
    break;

  default:
    RUNTIME_ASSERT(0);
    http_set_status(ctx, 500, "Internal Server Error");
    return -1;
  }

  value = http_parse_header_name(buf);
  if (!value) {
    http_set_status(ctx, 400, "Bad Request (Bad Header)");
    return -1;
  }

  if (name_ptr)
    *name_ptr = buf;
  
  if (value_ptr)
    *value_ptr = skip_spaces(value);
 
  return 1;
}
Exemplo n.º 4
0
static int http_read_stream(URLContext *h, uint8_t *buf, int size)
{
    HTTPContext *s = h->priv_data;
    int err, new_location;

    if (!s->hd)
        return AVERROR_EOF;

    if (s->end_chunked_post && !s->end_header) {
        err = http_read_header(h, &new_location);
        if (err < 0)
            return err;
    }

    if (s->chunksize >= 0) {
        if (!s->chunksize) {
            char line[32];

            for (;;) {
                do {
                    if ((err = http_get_line(s, line, sizeof(line))) < 0)
                        return err;
                } while (!*line);    /* skip CR LF from last chunk */

                s->chunksize = strtoll(line, NULL, 16);

                av_log(NULL, AV_LOG_TRACE, "Chunked encoding data size: %"PRId64"'\n",
                        s->chunksize);

                if (!s->chunksize)
                    return 0;
                break;
            }
        }
        size = FFMIN(size, s->chunksize);
    }
#if CONFIG_ZLIB
    if (s->compressed)
        return http_buf_read_compressed(h, buf, size);
#endif /* CONFIG_ZLIB */
    return http_buf_read(h, buf, size);
}
Exemplo n.º 5
0
/* Return a usable socket descriptor after proxy negotiation, or -1 on any
   error. If any bytes are received through the proxy after negotiation, they
   are written to stdout. */
static int do_proxy_http(void)
{
    struct socket_buffer sockbuf;
    char *request;
    char *status_line, *header;
    char *remainder;
    size_t len;
    int sd, code;
    int n;

    sd = do_connect(SOCK_STREAM);
    if (sd == -1) {
        loguser("Proxy connection failed: %s.\n", socket_strerror(socket_errno()));
        return -1;
    }

    status_line = NULL;
    header = NULL;

    /* First try a request with no authentication. */
    request = http_connect_request(&httpconnect, &n);
    if (send(sd, request, n, 0) < 0) {
        loguser("Error sending proxy request: %s.\n", socket_strerror(socket_errno()));
        free(request);
        return -1;
    }
    free(request);

    socket_buffer_init(&sockbuf, sd);

    if (http_read_status_line(&sockbuf, &status_line) != 0) {
        loguser("Error reading proxy response Status-Line.\n");
        goto bail;
    }
    code = http_parse_status_line_code(status_line);
    logdebug("Proxy returned status code %d.\n", code);
    free(status_line);
    status_line = NULL;
    if (http_read_header(&sockbuf, &header) != 0) {
        loguser("Error reading proxy response header.\n");
        goto bail;
    }

    if (code == 407 && o.proxy_auth != NULL) {
        struct http_header *h;
        struct http_challenge challenge;

        close(sd);
        sd = -1;

        if (http_parse_header(&h, header) != 0) {
            loguser("Error parsing proxy response header.\n");
            goto bail;
        }
        free(header);
        header = NULL;

        if (http_header_get_proxy_challenge(h, &challenge) == NULL) {
            loguser("Error getting Proxy-Authenticate challenge.\n");
            http_header_free(h);
            goto bail;
        }
        http_header_free(h);

        sd = do_connect(SOCK_STREAM);
        if (sd == -1) {
            loguser("Proxy reconnection failed: %s.\n", socket_strerror(socket_errno()));
            goto bail;
        }

        request = http_connect_request_auth(&httpconnect, &n, &challenge);
        if (request == NULL) {
            loguser("Error building Proxy-Authorization header.\n");
            http_challenge_free(&challenge);
            goto bail;
        }
        logdebug("Reconnection header:\n%s", request);
        if (send(sd, request, n, 0) < 0) {
            loguser("Error sending proxy request: %s.\n", socket_strerror(socket_errno()));
            free(request);
            http_challenge_free(&challenge);
            goto bail;
        }
        free(request);
        http_challenge_free(&challenge);

        socket_buffer_init(&sockbuf, sd);

        if (http_read_status_line(&sockbuf, &status_line) != 0) {
            loguser("Error reading proxy response Status-Line.\n");
            goto bail;
        }
        code = http_parse_status_line_code(status_line);
        logdebug("Proxy returned status code %d.\n", code);
        free(status_line);
        status_line = NULL;
        if (http_read_header(&sockbuf, &header) != 0) {
            loguser("Error reading proxy response header.\n");
            goto bail;
        }
    }

    free(header);
    header = NULL;

    if (code != 200) {
        loguser("Proxy returned status code %d.\n", code);
        return -1;
    }

    remainder = socket_buffer_remainder(&sockbuf, &len);
    Write(STDOUT_FILENO, remainder, len);

    return sd;

bail:
    if (sd != -1)
        close(sd);
    if (status_line != NULL)
        free(status_line);
    if (header != NULL)
        free(header);

    return -1;
}
Exemplo n.º 6
0
SANE_Status bb_start_scan(struct ledm_session *ps)
{
  char buf[4096] = {0};
  char buf1[1024]={0};
  int len, bytes_read, paper_status;
  int i, timeout = 10 ;
  char szPage_ID[5] = {0};
  char szJob_ID[5] = {0};
  SANE_Status stat = SANE_STATUS_IO_ERROR;
  struct bb_ledm_session *pbb = ps->bb_session;
  
  ps->user_cancel = 0;
  _DBG("bb_start_scan() entering...job_id=%d\n", ps->job_id);
  if (ps->job_id == 0)
  {
    if(http_open(ps->dd, HPMUD_S_LEDM_SCAN, &pbb->http_handle) != HTTP_R_OK)
    {
        _BUG("unable to open channel HPMUD_S_LEDM_SCAN \n");
        goto bugout;
    }

    if (http_write(pbb->http_handle, GET_SCANNER_STATUS, sizeof(GET_SCANNER_STATUS)-1, timeout) != HTTP_R_OK)
    {
       _BUG("unable to GET_SCANNER_STATUS \n");
       goto bugout;
    }
 
    read_http_payload(ps, buf, sizeof(buf), timeout, &bytes_read);
     
    if(!strstr(buf, SCANNER_IDLE)) 
    {
        stat = SANE_STATUS_DEVICE_BUSY;
        goto bugout;
    }

    http_close(pbb->http_handle);
  	pbb->http_handle = 0;

    if(http_open(ps->dd, HPMUD_S_LEDM_SCAN, &pbb->http_handle) != HTTP_R_OK)
    {
        _BUG("unable to open channel HPMUD_S_LEDM_SCAN \n");
        goto bugout;
    }

    len = snprintf(buf, sizeof(buf), CREATE_SCAN_JOB_REQUEST,
        ps->currentResolution,//<XResolution>
        ps->currentResolution,//<YResolution>
        (int) (ps->currentTlx / 5548.7133),//<XStart>
        (int) ((ps->currentBrx / 5548.7133) - (ps->currentTlx / 5548.7133)),//<Width>
        (int) (ps->currentTly / 5548.7133),//<YStart>
        (int) ((ps->currentBry / 5548.7133) - (ps->currentTly / 5548.7133)),//<Height>
        "Jpeg",//<Format>
        (! strcmp(ce_element[ps->currentScanMode], "Color8")) ? "Color" : (! strcmp(ce_element[ps->currentScanMode], "Gray8")) ? "Gray" : "Gray",//<ColorSpace>
        ((! strcmp(ce_element[ps->currentScanMode], "Color8")) || (! strcmp(ce_element[ps->currentScanMode], "Gray8"))) ? 8: 8,//<BitDepth>
        ps->currentInputSource == IS_PLATEN ? is_element[1] : is_element[2],//<InputSource>
        ps->currentInputSource == IS_PLATEN ? is_element[1] : is_element[2],//<InputSourceType>
        ps->currentInputSource != IS_ADF_DUPLEX ? "" : "<AdfOptions><AdfOption>Duplex</AdfOption></AdfOptions>",
        (int)ps->currentBrightness,//<Brightness>
        (int)ps->currentContrast);//<Contrast>

    len = len + strlen(ZERO_FOOTER);

    len = snprintf(buf1, sizeof(buf1), POST_HEADER, len);
    if (http_write(pbb->http_handle, buf1, strlen(buf1), timeout) != HTTP_R_OK)
    {
        //goto bugout;
    }
    
    if (http_write(pbb->http_handle, buf, strlen(buf), 1) != HTTP_R_OK)
    {
        //goto bugout;
    }

    /* Write zero footer. */
    if (http_write(pbb->http_handle, ZERO_FOOTER, sizeof(ZERO_FOOTER)-1, 1) != HTTP_R_OK)
    {
        //goto bugout;
    }
    memset(buf, 0, sizeof(buf));
    /* Read response. */
    if (read_http_payload(ps, buf, sizeof(buf), timeout, &bytes_read))
       goto bugout;

    http_close(pbb->http_handle);
    pbb->http_handle = 0;

    char joblist[64];
    char* jl=strstr(buf, "Location:");
    if (!jl) goto bugout;
    jl=jl+10;
	
    int i=0;
    while(*jl != '\r')
    { 
      joblist[i]=*jl; 
      jl=jl+1; i++;
    } 
    joblist[i]='\0';

    strcpy(ps->url, joblist);
    char *c=ps->url;
    c=strstr(c, "JobList"); 
    if (c)
    {
      c=c+8;
      int job_id=strtol(c, NULL, 10);
      itoa(job_id, szJob_ID,10);
      itoa(1, szPage_ID,10);
      ps->page_id = 1;
      ps->job_id = job_id;
    }
  }
  else
  {
    if (ps->currentInputSource == IS_PLATEN)
    {
       stat = SANE_STATUS_INVAL;
       goto bugout;
    }

    ps->page_id++;
    itoa(ps->job_id,szJob_ID,10);
    itoa(ps->page_id, szPage_ID,10);
  }
  _DBG("bb_start_scan() url=%s page_id=%d\n", ps->url, ps->page_id);
  
  memset(buf, 0, sizeof(buf)-1);

  if(http_open(ps->dd, HPMUD_S_LEDM_SCAN, &pbb->http_handle) != HTTP_R_OK)
  {
      _BUG("unable to open channel HPMUD_S_LEDM_SCAN \n");
      goto bugout;
  }
  while(strstr(buf, READY_TO_UPLOAD) == NULL)
  {
     _DBG("bb_start_scan() ENTERING....buf=%s\n", buf);
     len = snprintf(buf, sizeof(buf), GET_SCAN_JOB_URL, ps->url);

     if (http_write(pbb->http_handle, buf, strlen(buf), 1) != HTTP_R_OK)
     {
        //goto bugout;
        break ;
     }
     if (read_http_payload (ps, buf, sizeof(buf), 5, &len) != HTTP_R_OK)
     {
        //goto bugout
        _DBG("bb_start_scan() read_http_payload FAILED len=%d buf=%s\n", len, buf);
        break;
     }
      //For a new scan, buf must contain <PreScanPage>. 
     if (NULL == strstr(buf,PRESCANPAGE)) 
     {         //i.e Paper is not present in Scanner
         stat = SANE_STATUS_NO_DOCS;
         goto bugout;
     }
     if (strstr(buf,JOBSTATE_CANCELED) || strstr(buf, CANCELED_BY_DEVICE) || strstr(buf, CANCELED_BY_CLIENT))
     {
        _DBG("bb_start_scan() SCAN CANCELLED\n");
        stat = SANE_STATUS_GOOD;
        ps->user_cancel = 1;
        goto bugout;
     }
     if (strstr(buf, JOBSTATE_COMPLETED))
     {
        stat = SANE_STATUS_GOOD;
        goto bugout;
     }
     usleep(500000);//0.5 sec delay
  }//end while()

  char *c = strstr(buf, "<BinaryURL>");
  _DBG("bb_start_scan() BinaryURL=%s \n", c);
  
  if (!c) goto bugout;
  c +=11;
  char BinaryURL[30];
  i = 0;
  while(*c != '<')
  {
     BinaryURL[i++] = *c ;
     c++;
  }
  BinaryURL[i] = '\0';
  //_DBG("bb_start_scan() BinaryURL=%s\n", BinaryURL);
  len = snprintf(buf, sizeof(buf), GET_SCAN_JOB_URL, BinaryURL);
 
  if (http_write(pbb->http_handle, buf, strlen(buf), timeout) != HTTP_R_OK)
  {
 	//goto bugout;
  }
 
  if (http_read_header(pbb->http_handle, buf, sizeof(buf), timeout, &len) != HTTP_R_OK)
  {
	 //goto bugout;
  }

  if(strstr(buf, "HTTP/1.1 400 Bad Request")) http_read_header(pbb->http_handle, buf, sizeof(buf), timeout, &len);
  
  stat = SANE_STATUS_GOOD;
bugout:
  if (stat && pbb->http_handle)
  {
    http_close(pbb->http_handle);   /* error, close http connection */
    pbb->http_handle = 0;
  }
  return stat;
} /* bb_start_scan */
Exemplo n.º 7
0
static int read_http_payload(struct ledm_session *ps, char *payload, int max_size, int sec_timeout, int *bytes_read)
{
  struct bb_ledm_session *pbb = ps->bb_session;
  int stat=1, total=0, len;
  int tmo=sec_timeout;
  enum HTTP_RESULT ret;
  int payload_length=-1;
  char *temp=NULL;

  *bytes_read = 0;

  if(http_read_header(pbb->http_handle, payload, max_size, tmo, &len) != HTTP_R_OK)
      goto bugout;

  _DBG("read_http_payload len=%d %s\n",len,payload);
  temp = strstr(payload, "HTTP/1.1 201 Created");
  if (temp)
  {
		*bytes_read = total = len;
		stat=0;
		return stat ;
  }
  
  temp=strstr(payload, "Content-Length:");
  if (temp)
  {
		temp=temp+16;
		temp=strtok(temp, "\r\n");
		payload_length=strtol(temp, NULL, 10);
		if (payload_length == 0)
	  	{
			*bytes_read = total = len;
			stat=0;
			return stat ;
		}
  }
  memset(payload, ' ', len);
  if(payload_length==-1)
  {
    int i=10;
    while(i)
    {
		len = 0;
		ret = http_read(pbb->http_handle, payload+total, max_size-total, tmo, &len);
		total+=len;
      	tmo=1;
    	i--;
		if (ret == HTTP_R_EOF)
        {
         _DBG("read_http_payload1 DONE......\n");
          break;    /* done */
        }

    	if (!(ret == HTTP_R_OK || ret == HTTP_R_EOF))
        {
        	_DBG("read_http_payload1 ERROR......\n");
        	goto bugout;
        }
    }//end while(i)
  }//end if(payload_length==-1)
  else
  {
	  len=payload_length;
	  while (total < payload_length) 
	  {
		  ret = http_read(pbb->http_handle, payload+total, max_size-total, tmo, &len);
		  total+=len;
		  tmo=1;
		  if (ret == HTTP_R_EOF)
		  {
		     _DBG("read_http_payload2 DONE......\n");
		     break;    /* done */
		  } 

		  if (!(ret == HTTP_R_OK || ret == HTTP_R_EOF))
		  {
        	  _DBG("read_http_payload2 ERROR......\n");
        	  goto bugout;
           }
        }//end while()
  }//end else

 *bytes_read = total;
  stat=0;

bugout:
   return stat;
} /* read_http_payload */
Exemplo n.º 8
0
/* Do a GET, HEAD, or POST transaction. */
static int do_transaction(struct http_request *request,
    struct socket_buffer *client_sock, struct socket_buffer *server_sock)
{
    char buf[BUFSIZ];
    struct http_response response;
    char *line;
    char *request_str, *response_str;
    size_t len;
    int code, n;

    /* We don't handle the chunked transfer encoding, which in the absence of a
       Content-Length is the only way we know the end of a request body. RFC
       2616, section 4.4 says, "If a request contains a message-body and a
       Content-Length is not given, the server SHOULD respond with 400 (bad
       request) if it cannot determine the length of the message, or with 411
       (length required) if it wishes to insist on receiving a valid
       Content-Length." */
    if (strcmp(request->method, "POST") == 0 && request->content_length == 0) {
        if (o.debug)
            logdebug("POST request with no Content-Length.\n");
        return 400;
    }

    /* The version we use to talk to the server. */
    request->version = HTTP_10;

    /* Remove headers that only apply to our connection with the client. */
    code = http_header_remove_hop_by_hop(&request->header);
    if (code != 0) {
        if (o.verbose)
            logdebug("Error removing hop-by-hop headers.\n");
        return code;
    }

    /* Build the Host header. */
    if (request->uri.port == -1 || request->uri.port == 80)
        n = Snprintf(buf, sizeof(buf), "%s", request->uri.host);
    else
        n = Snprintf(buf, sizeof(buf), "%s:%hu", request->uri.host, request->uri.port);
    if (n < 0 || n >= sizeof(buf)) {
        /* Request Entity Too Large. */
        return 501;
    }
    request->header = http_header_set(request->header, "Host", buf);

    request->header = http_header_set(request->header, "Connection", "close");

    /* Send the request to the server. */
    request_str = http_request_to_string(request, &len);
    n = send(server_sock->fdn.fd, request_str, len, 0);
    free(request_str);
    if (n < 0)
        return 504;
    /* Send the request body, if any. Count up to Content-Length. */
    while (request->bytes_transferred < request->content_length) {
        n = socket_buffer_read(client_sock, buf, MIN(sizeof(buf), request->content_length - request->bytes_transferred));
        if (n < 0)
            return 504;
        if (n == 0)
            break;
        request->bytes_transferred += n;
        n = send(server_sock->fdn.fd, buf, n, 0);
        if (n < 0)
            return 504;
    }
    if (o.debug && request->bytes_transferred < request->content_length)
        logdebug("Received only %lu request body bytes (Content-Length was %lu).\n", request->bytes_transferred, request->content_length);


    /* Read the response. */
    code = http_read_status_line(server_sock, &line);
    if (o.debug > 1)
        logdebug("Status-Line: %s", line);
    if (code != 0) {
        if (o.verbose)
            logdebug("Error reading Status-Line.\n");
        return 0;
    }
    code = http_parse_status_line(line, &response);
    free(line);
    if (code != 0) {
        if (o.verbose)
            logdebug("Error parsing Status-Line.\n");
        return 0;
    }

    code = http_read_header(server_sock, &line);
    if (code != 0) {
        if (o.verbose)
            logdebug("Error reading header.\n");
        return 0;
    }
    if (o.debug > 1)
        logdebug("Response header:\n%s", line);

    code = http_response_parse_header(&response, line);
    free(line);
    if (code != 0) {
        if (o.verbose)
            logdebug("Error parsing response header.\n");
        return 0;
    }


    /* The version we use to talk to the client. */
    response.version = HTTP_10;

    /* Remove headers that only apply to our connection with the server. */
    code = http_header_remove_hop_by_hop(&response.header);
    if (code != 0) {
        if (o.verbose)
            logdebug("Error removing hop-by-hop headers.\n");
        return code;
    }

    response.header = http_header_set(response.header, "Connection", "close");

    /* Send the response to the client. */
    response_str = http_response_to_string(&response, &len);
    n = fdinfo_send(&client_sock->fdn, response_str, len);
    free(response_str);
    if (n < 0) {
        http_response_free(&response);
        return 504;
    }
    /* If the Content-Length is 0, read until the connection is closed.
       Otherwise read until the Content-Length. At this point it's too late to
       return our own error code so return 0 in case of any error. */
    while (response.content_length == 0
        || response.bytes_transferred < response.content_length) {
        size_t remaining = response.content_length - response.bytes_transferred;
        size_t count;

        count = sizeof(buf);
        if (response.content_length > 0 && remaining < count)
            count = remaining;
        n = socket_buffer_read(server_sock, buf, count);
        if (n <= 0)
            break;
        response.bytes_transferred += n;
        n = fdinfo_send(&client_sock->fdn, buf, n);
        if (n < 0)
            break;
    }

    http_response_free(&response);

    return 0;
}
Exemplo n.º 9
0
static void http_server_handler(int c)
{
    int code;
    struct socket_buffer sock;
    struct http_request request;
    char *buf;

    socket_buffer_init(&sock, c);
#if HAVE_OPENSSL
    if (o.ssl) {
        sock.fdn.ssl = new_ssl(sock.fdn.fd);
        if (SSL_accept(sock.fdn.ssl) != 1) {
            loguser("Failed SSL connection: %s\n",
                ERR_error_string(ERR_get_error(), NULL));
            fdinfo_close(&sock.fdn);
            return;
        }
    }
#endif

    code = http_read_request_line(&sock, &buf);
    if (code != 0) {
        if (o.verbose)
            logdebug("Error reading Request-Line.\n");
        send_string(&sock.fdn, http_code2str(code));
        fdinfo_close(&sock.fdn);
        return;
    }
    if (o.debug > 1)
        logdebug("Request-Line: %s", buf);
    code = http_parse_request_line(buf, &request);
    free(buf);
    if (code != 0) {
        if (o.verbose)
            logdebug("Error parsing Request-Line.\n");
        send_string(&sock.fdn, http_code2str(code));
        fdinfo_close(&sock.fdn);
        return;
    }

    if (!method_is_known(request.method)) {
        if (o.debug > 1)
            logdebug("Bad method: %s.\n", request.method);
        http_request_free(&request);
        send_string(&sock.fdn, http_code2str(405));
        fdinfo_close(&sock.fdn);
        return;
    }

    code = http_read_header(&sock, &buf);
    if (code != 0) {
        if (o.verbose)
            logdebug("Error reading header.\n");
        http_request_free(&request);
        send_string(&sock.fdn, http_code2str(code));
        fdinfo_close(&sock.fdn);
        return;
    }
    if (o.debug > 1)
        logdebug("Header:\n%s", buf);
    code = http_request_parse_header(&request, buf);
    free(buf);
    if (code != 0) {
        if (o.verbose)
            logdebug("Error parsing header.\n");
        http_request_free(&request);
        send_string(&sock.fdn, http_code2str(code));
        fdinfo_close(&sock.fdn);
        return;
    }

    /* Check authentication. */
    if (o.proxy_auth) {
        struct http_credentials credentials;
        int ret, stale;

        if (http_header_get_proxy_credentials(request.header, &credentials) == NULL) {
            /* No credentials or a parsing error. */
            send_proxy_authenticate(&sock.fdn, 0);
            http_request_free(&request);
            fdinfo_close(&sock.fdn);
            return;
        }

        ret = check_auth(&request, &credentials, &stale);
        http_credentials_free(&credentials);
        if (!ret) {
            /* Password doesn't match. */
            /* RFC 2617, section 1.2: "If a proxy does not accept the
               credentials sent with a request, it SHOULD return a 407 (Proxy
               Authentication Required). */
            send_proxy_authenticate(&sock.fdn, stale);
            http_request_free(&request);
            fdinfo_close(&sock.fdn);
            return;
        }
    }

    if (strcmp(request.method, "CONNECT") == 0) {
        code = handle_connect(&sock, &request);
    } else if (strcmp(request.method, "GET") == 0
        || strcmp(request.method, "HEAD") == 0
        || strcmp(request.method, "POST") == 0) {
        code = handle_method(&sock, &request);
    } else {
        code = 500;
    }
    http_request_free(&request);

    if (code != 0) {
        send_string(&sock.fdn, http_code2str(code));
        fdinfo_close(&sock.fdn);
        return;
    }

    fdinfo_close(&sock.fdn);
}
Exemplo n.º 10
0
static int http_connect(URLContext *h, const char *path, const char *local_path,
                        const char *hoststr, const char *auth,
                        const char *proxyauth, int *new_location)
{
    HTTPContext *s = h->priv_data;
    int post, err;
    char headers[HTTP_HEADERS_SIZE] = "";
    char *authstr = NULL, *proxyauthstr = NULL;
    int64_t off = s->off;
    int len = 0;
    const char *method;
    int send_expect_100 = 0;

    /* send http header */
    post = h->flags & AVIO_FLAG_WRITE;

    if (s->post_data) {
        /* force POST method and disable chunked encoding when
         * custom HTTP post data is set */
        post            = 1;
        s->chunked_post = 0;
    }

    if (s->method)
        method = s->method;
    else
        method = post ? "POST" : "GET";

    authstr      = ff_http_auth_create_response(&s->auth_state, auth,
                                                local_path, method);
    proxyauthstr = ff_http_auth_create_response(&s->proxy_auth_state, proxyauth,
                                                local_path, method);
    if (post && !s->post_data) {
        send_expect_100 = s->send_expect_100;
        /* The user has supplied authentication but we don't know the auth type,
         * send Expect: 100-continue to get the 401 response including the
         * WWW-Authenticate header, or an 100 continue if no auth actually
         * is needed. */
        if (auth && *auth &&
            s->auth_state.auth_type == HTTP_AUTH_NONE &&
            s->http_code != 401)
            send_expect_100 = 1;
    }

    /* set default headers if needed */
    if (!has_header(s->headers, "\r\nUser-Agent: "))
        len += av_strlcatf(headers + len, sizeof(headers) - len,
                           "User-Agent: %s\r\n", s->user_agent);
    if (!has_header(s->headers, "\r\nAccept: "))
        len += av_strlcpy(headers + len, "Accept: */*\r\n",
                          sizeof(headers) - len);
    // Note: we send this on purpose even when s->off is 0 when we're probing,
    // since it allows us to detect more reliably if a (non-conforming)
    // server supports seeking by analysing the reply headers.
    if (!has_header(s->headers, "\r\nRange: ") && !post && (s->off > 0 || s->end_off || s->seekable == -1)) {
        len += av_strlcatf(headers + len, sizeof(headers) - len,
                           "Range: bytes=%"PRId64"-", s->off);
        if (s->end_off)
            len += av_strlcatf(headers + len, sizeof(headers) - len,
                               "%"PRId64, s->end_off - 1);
        len += av_strlcpy(headers + len, "\r\n",
                          sizeof(headers) - len);
    }
    if (send_expect_100 && !has_header(s->headers, "\r\nExpect: "))
        len += av_strlcatf(headers + len, sizeof(headers) - len,
                           "Expect: 100-continue\r\n");

    if (!has_header(s->headers, "\r\nConnection: ")) {
        if (s->multiple_requests)
            len += av_strlcpy(headers + len, "Connection: keep-alive\r\n",
                              sizeof(headers) - len);
        else
            len += av_strlcpy(headers + len, "Connection: close\r\n",
                              sizeof(headers) - len);
    }

    if (!has_header(s->headers, "\r\nHost: "))
        len += av_strlcatf(headers + len, sizeof(headers) - len,
                           "Host: %s\r\n", hoststr);
    if (!has_header(s->headers, "\r\nContent-Length: ") && s->post_data)
        len += av_strlcatf(headers + len, sizeof(headers) - len,
                           "Content-Length: %d\r\n", s->post_datalen);

    if (!has_header(s->headers, "\r\nContent-Type: ") && s->content_type)
        len += av_strlcatf(headers + len, sizeof(headers) - len,
                           "Content-Type: %s\r\n", s->content_type);
    if (!has_header(s->headers, "\r\nCookie: ") && s->cookies) {
        char *cookies = NULL;
        if (!get_cookies(s, &cookies, path, hoststr) && cookies) {
            len += av_strlcatf(headers + len, sizeof(headers) - len,
                               "Cookie: %s\r\n", cookies);
            av_free(cookies);
        }
    }
    if (!has_header(s->headers, "\r\nIcy-MetaData: ") && s->icy)
        len += av_strlcatf(headers + len, sizeof(headers) - len,
                           "Icy-MetaData: %d\r\n", 1);

    /* now add in custom headers */
    if (s->headers)
        av_strlcpy(headers + len, s->headers, sizeof(headers) - len);

    snprintf(s->buffer, sizeof(s->buffer),
             "%s %s HTTP/1.1\r\n"
             "%s"
             "%s"
             "%s"
             "%s%s"
             "\r\n",
             method,
             path,
             post && s->chunked_post ? "Transfer-Encoding: chunked\r\n" : "",
             headers,
             authstr ? authstr : "",
             proxyauthstr ? "Proxy-" : "", proxyauthstr ? proxyauthstr : "");

    av_log(h, AV_LOG_DEBUG, "request: %s\n", s->buffer);

    if ((err = ffurl_write(s->hd, s->buffer, strlen(s->buffer))) < 0)
        goto done;

    if (s->post_data)
        if ((err = ffurl_write(s->hd, s->post_data, s->post_datalen)) < 0)
            goto done;

    /* init input buffer */
    s->buf_ptr          = s->buffer;
    s->buf_end          = s->buffer;
    s->line_count       = 0;
    s->off              = 0;
    s->icy_data_read    = 0;
    s->filesize         = -1;
    s->willclose        = 0;
    s->end_chunked_post = 0;
    s->end_header       = 0;
    if (post && !s->post_data && !send_expect_100) {
        /* Pretend that it did work. We didn't read any header yet, since
         * we've still to send the POST data, but the code calling this
         * function will check http_code after we return. */
        s->http_code = 200;
        err = 0;
        goto done;
    }

    /* wait for header */
    err = http_read_header(h, new_location);
    if (err < 0)
        goto done;

    if (*new_location)
        s->off = off;

    err = (off == s->off) ? 0 : -1;
done:
    av_freep(&authstr);
    av_freep(&proxyauthstr);
    return err;
}
Exemplo n.º 11
0
static int http_proxy_open(URLContext *h, const char *uri, int flags)
{
    HTTPContext *s = h->priv_data;
    char hostname[1024], hoststr[1024];
    char auth[1024], pathbuf[1024], *path;
    char lower_url[100];
    int port, ret = 0, attempts = 0;
    HTTPAuthType cur_auth_type;
    char *authstr;
    int new_loc;

    if( s->seekable == 1 )
        h->is_streamed = 0;
    else
        h->is_streamed = 1;

    av_url_split(NULL, 0, auth, sizeof(auth), hostname, sizeof(hostname), &port,
                 pathbuf, sizeof(pathbuf), uri);
    ff_url_join(hoststr, sizeof(hoststr), NULL, NULL, hostname, port, NULL);
    path = pathbuf;
    if (*path == '/')
        path++;

    ff_url_join(lower_url, sizeof(lower_url), "tcp", NULL, hostname, port,
                NULL);
redo:
    ret = ffurl_open(&s->hd, lower_url, AVIO_FLAG_READ_WRITE,
                     &h->interrupt_callback, NULL);
    if (ret < 0)
        return ret;

    authstr = ff_http_auth_create_response(&s->proxy_auth_state, auth,
                                           path, "CONNECT");
    snprintf(s->buffer, sizeof(s->buffer),
             "CONNECT %s HTTP/1.1\r\n"
             "Host: %s\r\n"
             "Connection: close\r\n"
             "%s%s"
             "\r\n",
             path,
             hoststr,
             authstr ? "Proxy-" : "", authstr ? authstr : "");
    av_freep(&authstr);

    if ((ret = ffurl_write(s->hd, s->buffer, strlen(s->buffer))) < 0)
        goto fail;

    s->buf_ptr    = s->buffer;
    s->buf_end    = s->buffer;
    s->line_count = 0;
    s->filesize   = -1;
    cur_auth_type = s->proxy_auth_state.auth_type;

    /* Note: This uses buffering, potentially reading more than the
     * HTTP header. If tunneling a protocol where the server starts
     * the conversation, we might buffer part of that here, too.
     * Reading that requires using the proper ffurl_read() function
     * on this URLContext, not using the fd directly (as the tls
     * protocol does). This shouldn't be an issue for tls though,
     * since the client starts the conversation there, so there
     * is no extra data that we might buffer up here.
     */
    ret = http_read_header(h, &new_loc);
    if (ret < 0)
        goto fail;

    attempts++;
    if (s->http_code == 407 &&
        (cur_auth_type == HTTP_AUTH_NONE || s->proxy_auth_state.stale) &&
        s->proxy_auth_state.auth_type != HTTP_AUTH_NONE && attempts < 2) {
        ffurl_closep(&s->hd);
        goto redo;
    }

    if (s->http_code < 400)
        return 0;
    ret = ff_http_averror(s->http_code, AVERROR(EIO));

fail:
    http_proxy_close(h);
    return ret;
}
Exemplo n.º 12
0
// parses a http request
//
// can be called multiple times on the same buffer (with increasing lenghth)
// for incremental parsing... (it remembers the last_pos in req->last_pos)
//
// returns 0 if the request was parsed without errors so far, but is not yet
// finished and returns -1 if an error occured. if the request was successfully
// and completely parsed it will return the (positive non-zero) position of the
// first byte of the http request body
int http_read(http_req_t* req, char* buf, size_t len) {
  int n, nxt = len - req->last_pos - 1;
  char* pos  = buf + req->last_pos;

  for (n = 0; n <= nxt; n++) {
    switch (*pos) {

      case '\r':
        *pos = 0;
        break;

      case ' ':
        switch (req->state) {

          case HTTP_STATE_METHOD:
            if (http_read_method(req, buf, pos - buf) == -1)
              return -1;

            req->cur_token = pos + 1;
            break;

          case HTTP_STATE_URI:
            if (http_read_uri(req, HTTP_CUR_TOKEN) == -1)
              return -1;

            req->cur_token = pos + 1;
            break;

        }; break;

      case '\n':
        switch (req->state) {

          case HTTP_STATE_METHOD:
            return -1;

          case HTTP_STATE_URI:
            return -1;

          case HTTP_STATE_VERSION:
            if (http_read_version(req, HTTP_CUR_TOKEN) == -1)
              return -1;

            req->cur_token = pos + 1;
            break;

          case HTTP_STATE_HVAL:
            while (*(req->cur_token) == ' ' && req->cur_token < pos)
              req->cur_token++;

            http_read_header(req,
              req->cur_hkey, req->cur_hkey_len,
              req->cur_token, pos - req->cur_token);

            req->state = HTTP_STATE_HKEY;
            req->cur_token = pos + 1;
            break;

          case HTTP_STATE_HKEY:
            return pos - buf;
            break;

      }; break;

      case ':':
        switch (req->state) {

          case HTTP_STATE_HKEY:
            req->cur_hkey_len = pos - req->cur_token;
            req->cur_hkey = req->cur_token;
            req->cur_token = pos + 1;
            req->state = HTTP_STATE_HVAL;
            break;

      }; break;

    }

    pos++;
  }

  req->last_pos += nxt;
  return 0;
}