Ejemplo n.º 1
0
int http_receive_request(int sockfd, struct HttpRequest **received_request) {
    debug("http_receive_request");
    *received_request = NULL;
    char *method = NULL;
    char *resource = NULL;
    struct dict *headers = dict_create();
    int content_length = -1;
    char *payload = NULL;

    int http_error = HTTP_SUCCESS;
    char *line = NULL;

    if ((http_error = http_read_line(sockfd, &line)) != HTTP_SUCCESS) {
        goto error;
    }
    if ((http_error = http_parse_request_line(line, &method, &resource)) != HTTP_SUCCESS) {
        goto error;
    }
    free(line);

    if ((http_error = http_receive_headers(sockfd, headers)) != HTTP_SUCCESS) {
        goto error;
    }

    const char *l = dict_get_case(headers, "Content-Length");
    if (l != 0) {
        content_length = atoi(l);
    }

    if (content_length == -1 || content_length == 0) {
        debug("No or 0 content-length.");
        content_length = 0;
    } else {
        if ((http_error = http_receive_payload(sockfd, &payload, content_length)) != HTTP_SUCCESS) {
            goto error;
        }
    }

    // create and fill return object
    struct HttpRequest *request = (struct HttpRequest *)malloc(sizeof(struct HttpRequest));
    check_mem(request);
    request->method = method;
    request->resource = resource;
    request->headers = headers;
    request->content_length = content_length;
    request->payload = payload;

    *received_request = request;
    return HTTP_SUCCESS;

error:
    dict_free(headers); //TODO free entries
    free(method);
    free(resource);
    free(payload);
    free(line);
    assert(http_error != HTTP_SUCCESS);
    return http_error;
}
Ejemplo n.º 2
0
const char *http_request_headers(int fd)
{
    static char buf[8192];      /* static variables are not on the stack */
    int i;
    char value[512];
    char envvar[512];

    /* For lab 2: don't remove this line. */
    touch("http_request_headers");

    /* Now parse HTTP headers */
    for (;;)
    {
        if (http_read_line(fd, buf, sizeof(buf)) < 0)
            return "Socket IO error";

        if (buf[0] == '\0')     /* end of headers */
            break;

        /* Parse things like "Cookie: foo bar" */
        char *sp = strchr(buf, ' ');
        if (!sp)
            return "Header parse error (1)";
        *sp = '\0';
        sp++;

        /* Strip off the colon, making sure it's there */
        if (strlen(buf) == 0)
            return "Header parse error (2)";

        char *colon = &buf[strlen(buf) - 1];
        if (*colon != ':')
            return "Header parse error (3)";
        *colon = '\0';

        /* Set the header name to uppercase and replace hyphens with underscores */
        for (i = 0; i < strlen(buf); i++) {
            buf[i] = toupper(buf[i]);
            if (buf[i] == '-')
                buf[i] = '_';
        }

        /* Decode URL escape sequences in the value */
        
        url_decode(value, sp);

        /* Store header in env. variable for application code */
        /* Some special headers don't use the HTTP_ prefix. */
        if (strcmp(buf, "CONTENT_TYPE") != 0 &&
            strcmp(buf, "CONTENT_LENGTH") != 0) {
            sprintf(envvar, "HTTP_%s", buf);
            setenv(envvar, value, 1);
        } else {
            setenv(buf, value, 1);
        }
    }

    return 0;
}
Ejemplo n.º 3
0
const char *http_request_line(int fd, char *reqpath, char *env, size_t *env_len)
{
    static char buf[8192];      /* static variables are not on the stack */
    char *sp1, *sp2, *qp, *envp = env;

    if (http_read_line(fd, buf, sizeof(buf)) < 0)
        return "Socket IO error";

    /* Parse request like "GET /foo.html HTTP/1.0" */
    sp1 = strchr(buf, ' ');
    if (!sp1)
        return "Cannot parse HTTP request (1)";
    *sp1 = '\0';
    sp1++;
    if (*sp1 != '/')
        return "Bad request path";

    sp2 = strchr(sp1, ' ');
    if (!sp2)
        return "Cannot parse HTTP request (2)";
    *sp2 = '\0';
    sp2++;

    /* We only support GET and POST requests */
    if (strcmp(buf, "GET") && strcmp(buf, "POST"))
        return "Unsupported request (not GET or POST)";

    envp += sprintf(envp, "REQUEST_METHOD=%s", buf) + 1;
    envp += sprintf(envp, "SERVER_PROTOCOL=%s", sp2) + 1;

    /* parse out query string, e.g. "foo.py?user=bob" */
    if ((qp = strchr(sp1, '?')))
    {
        *qp = '\0';
        envp += sprintf(envp, "QUERY_STRING=%s", qp + 1) + 1;
    }

    /* decode URL escape sequences in the requested path into reqpath */
    url_decode(reqpath, sp1);

    envp += sprintf(envp, "REQUEST_URI=%s", reqpath) + 1;

    envp += sprintf(envp, "SERVER_NAME=zoobar.org") + 1;

    *envp = 0;
    *env_len = envp - env + 1;

    printf("Buffer reqpath = ");
    int i = 0;
    for (; i < *env_len; i++) {
        printf("%c",env[i]);
    }
    printf("\n");
    return NULL;
}
Ejemplo n.º 4
0
int http_receive_response(int sockfd, struct HttpResponse **received_response) {
    debug("http_receive_response");
    *received_response = NULL;
    int status = 0;
    struct dict *headers = dict_create();
    int content_length = -1;
    char *payload = NULL;

    int http_error = HTTP_SUCCESS;
    char *line = NULL;

    if ((http_error = http_read_line(sockfd, &line)) != HTTP_SUCCESS) {
        goto error;
    }
    if ((http_error = http_parse_response_line(line, &status)) != HTTP_SUCCESS) {
        goto error;
    }
    free(line);

    if ((http_error = http_receive_headers(sockfd, headers)) != HTTP_SUCCESS) {
        goto error;
    }

    const char *l = dict_get_case(headers, "Content-Length");
    if (l != 0) {
        content_length = atoi(l);
    }

    if (content_length == -1 || content_length == 0) {
        debug("No or 0 content-length.");
        content_length = 0;
    } else {
        if ((http_error = http_receive_payload(sockfd, &payload, content_length)) != HTTP_SUCCESS) {
            goto error;
        }
    }

    // create and fill return object
    struct HttpResponse *response = (struct HttpResponse *)malloc(sizeof(struct HttpResponse));
    check_mem(response);
    response->status = status;
    response->headers = headers;
    response->content_length = content_length;
    response->payload = payload;

    *received_response = response;

    return HTTP_SUCCESS;

error:
    free(headers);
    free(payload);
    free(line);
    return http_error;
}
Ejemplo n.º 5
0
int update_radio_list(char* url)
{
    char *buf = NULL;
    int peer_handle = 0;
    int fd;
    int rc;

    peer_handle = radio_list_update_servicer_session_open(url);

    if(peer_handle < 0)
    {
        return -1;
    }

    fd = open(RADIO_FN, O_WRONLY | O_CREAT | O_TRUNC, 0);
    if(fd < 0)
    {
        return -1;
    }
    buf = rt_malloc (512);
    while ( 1 )
    {
        // read a line from the header information.
        rc = http_read_line(peer_handle, buf, 100);

        if ( rc < 0 ) break;

        // End of headers is a blank line.  exit.
        if (rc == 0) break;
        if ((rc == 2) && (buf[0] == '\r')) break;
        rt_kprintf(">>%s", buf);

        write(fd, buf, rc);
    }
    rt_free(buf);

    closesocket(peer_handle);

    if(close(fd) == 0)
    {
        rt_kprintf("Update radio list succeed \r\n");
    }

    return 0;
}
Ejemplo n.º 6
0
int http_receive_headers(int sockfd, struct dict *headers) {
    int http_error = HTTP_SUCCESS;
    char *line = NULL;

    while (TRUE) {
        char *field_name;
        char *field_value;
        if ((http_error = http_read_line(sockfd, &line)) != HTTP_SUCCESS) {
            break;
        }
        if (strcmp(line, "") == 0) {
            debug("End of Http header");
            break;
        }
        if ((http_error = http_parse_header_line(line, &field_name, &field_value)) != HTTP_SUCCESS) {
            break;
        }
        free(line);
        dict_set(headers, field_name, field_value);
    }
    free(line);
    return http_error;
}
Ejemplo n.º 7
0
void http_serve_executable(int fd, const char *pn)
{
    char buf[1024], headers[4096], *pheaders = headers;
    int pipefd[2], statusprinted = 0, ret, headerslen = 4096;

    pipe(pipefd);
    switch (fork()) {
    case -1:
        http_err(fd, 500, "fork: %s", strerror(errno));
        return;
    case 0:
        dup2(fd, 0);
        close(fd);
        dup2(pipefd[1], 1);
        close(pipefd[0]);
        close(pipefd[1]);
        execl(pn, pn, NULL);
        http_err(1, 500, "execl %s: %s", pn, strerror(errno));
        exit(1);
    default:
        close(pipefd[1]);
        while (1) {
            if (http_read_line(pipefd[0], buf, 1024) < 0) {
                http_err(fd, 500, "Premature end of script headers");
                close(pipefd[0]);
                return;
            }

            if (!*buf)
                break;

            if (!statusprinted && strncasecmp("Status: ", buf, 8) == 0) {
                fdprintf(fd, "HTTP/1.1 %s\r\n%s", buf + 8, headers);
                statusprinted = 1;
            } else if (statusprinted) {
                fdprintf(fd, "%s\r\n", buf);
            } else {
                ret = snprintf(pheaders, headerslen, "%s\r\n", buf);
                pheaders += ret;
                headerslen -= ret;
                if (headerslen == 0) {
                    http_err(fd, 500, "Too many script headers");
                    close(pipefd[0]);
                    return;
                }
            }
        }

        if (statusprinted)
            fdprintf(fd, "\r\n");
        else
            fdprintf(fd, "HTTP/1.0 200 OK\r\n%s\r\n", headers);

        while ((ret = read(pipefd[0], buf, 1024)) > 0) {
            write(fd, buf, ret);
        }

        close(fd);
        close(pipefd[0]);
    }
}
Ejemplo n.º 8
0
/*
 * http_handle_receive()
 *
 * Work out what the request we received was, and handle it.
 */
void http_handle_receive(http_conn* conn, int http_instance)
{
  int data_used, rx_code;
  
  if (conn->state == READY)
  {
    rx_code = recv(conn->fd, conn->rx_wr_pos, 
              (HTTP_RX_BUF_SIZE - (conn->rx_wr_pos - conn->rx_buffer) -1), 
              0);
        
    /* 
     * If a valid data received, take care of buffer pointer & string 
     * termination and move on. Otherwise, we need to return and wait for more
     * data to arrive (until we time out).
     */
    if(rx_code > 0)
    {
      /* Increment rx_wr_pos by the amount of data received. */
      conn->rx_wr_pos += rx_code;
      /* Place a zero just after the data received to serve as a terminator. */
      *(conn->rx_wr_pos+1) = 0;
      
      if(strstr(conn->rx_buffer, HTTP_END_OF_HEADERS))
      {
        conn->state = PROCESS;
      }
      /* If the connection is a file upload, skip right to DATA.*/
      if(conn->file_upload == 1)
      {
        conn->state = DATA;
      }
    }
  }
  
  if(conn->state == PROCESS)
  {
    /* 
     * If we (think) we have valid headers, keep the connection alive a bit
     * longer.
     */
    conn->activity_time = alt_nticks();
    
    /* 
     * Attempt to process the fundamentals of the HTTP request. We may 
     * error out and reset if the request wasn't complete, or something
     * was asked from us that we can't handle.
     */
    if (http_process_request(conn))
    {
      fprintf(stderr, "[http_handle_receive] http_process_request failed\n");
      conn->state = RESET;
      http_manage_connection(conn, http_instance);
    }
    
    /* 
     * Step through the headers to see if there is any other useful 
     * information about our pending transaction to extract. After that's 
     * done, send some headers of our own back to let the client know 
     * what's happening. Also, once all in-coming headers have been parsed
     * we can manage our RX buffer to prepare for the next in-coming 
     * connection.
     */
    while(conn->state == PROCESS)
    {
      if(http_read_line(conn))
      {
        fprintf(stderr, "[http_handle_receive] error reading headers\n");
        conn->state = RESET;
        http_manage_connection(conn, http_instance);
        break;
      }
      if(http_process_headers(conn))
      {
        if( (conn->rx_rd_pos = strstr(conn->rx_rd_pos, HTTP_CR_LF)) )
        {
          conn->rx_rd_pos += 2;
          conn->state = DATA;
          conn->activity_time = alt_nticks();
        }
        else
        {
          fprintf(stderr, "[http_handle_receive] Can't find end of headers!\n");
          conn->state = RESET;
          http_manage_connection(conn, http_instance);
          break;
        }
      } 
    } /* while(conn->state == PROCESS) */
    
    if( http_prepare_response(conn) )
    {
      conn->state = RESET;
      fprintf(stderr, "[http_handle_receive] Error preparing response\n");
      http_manage_connection(conn, http_instance);
    }
              
    /* 
     * Manage RX Buffer: Slide any un-read data in our input buffer 
     * down over previously-read data that can now be overwritten, and 
     * zero-out any bytes in question at the top of our new un-read space. 
     */
    if(conn->rx_rd_pos > (conn->rx_buffer + HTTP_RX_BUF_SIZE))
    {
      conn->rx_rd_pos = conn->rx_buffer + HTTP_RX_BUF_SIZE;
    }
        
    data_used = conn->rx_rd_pos - conn->rx_buffer;
    memmove(conn->rx_buffer,conn->rx_rd_pos,conn->rx_wr_pos-conn->rx_rd_pos);
    conn->rx_rd_pos = conn->rx_buffer;
    conn->rx_wr_pos -= data_used;
    memset(conn->rx_wr_pos, 0, data_used);
   }
   
  if (conn->state == DATA && conn->file_upload == 1 )
  {
    /* Jump to the file_upload() function....process more received data. */
    upload_field.func(conn);
  }
}
Ejemplo n.º 9
0
//
// This is the main HTTP client connect work.  Makes the connection
// and handles the protocol and reads the return headers.  Needs
// to leave the stream at the start of the real data.
//
static int shoutcast_connect(struct shoutcast_session* session,
    struct sockaddr_in* server, char* host_addr, const char* url)
{
	int socket_handle;
	int peer_handle;
	int rc;
	char mimeBuffer[256];
	int timeout = HTTP_RCV_TIMEO;

	if((socket_handle = socket( PF_INET, SOCK_STREAM, IPPROTO_TCP )) < 0)
	{
		rt_kprintf( "ICY: SOCKET FAILED\n" );
		return -1;
	}

	/* set recv timeout option */
	setsockopt(socket_handle, SOL_SOCKET, SO_RCVTIMEO, (void*)&timeout, sizeof(timeout));

	peer_handle = connect( socket_handle, (struct sockaddr *) server, sizeof(*server));
	if ( peer_handle < 0 )
	{
		rt_kprintf( "ICY: CONNECT FAILED %i\n", peer_handle );
		lwip_close(socket_handle);

		return -1;
	}

	{
		char *buf;
		rt_uint32_t length;

		buf = rt_malloc (512);
		if (*url)
			length = rt_snprintf(buf, 512, _shoutcast_get, url, host_addr);
		else
			length = rt_snprintf(buf, 512, _shoutcast_get, "/", host_addr);

		rc = send(peer_handle, buf, length, 0);
		rt_kprintf("SHOUTCAST request:\n%s", buf);

		/* release buffer */
		rt_free(buf);
	}

	/* read the header information */
	while ( 1 )
	{
		// read a line from the header information.
		rc = http_read_line(peer_handle, mimeBuffer, 100);
		rt_kprintf(">>%s", mimeBuffer);

		if ( rc < 0 )
		{
			lwip_close(socket_handle);
			return rc;
		}

		// End of headers is a blank line.  exit.
		if (rc == 0) break;
		if ((rc == 2) && (mimeBuffer[0] == '\r')) break;

		if(strstr(mimeBuffer, "ICY")) // First line of header, contains status code. Check for an error code
		{
			rc = shoutcast_is_error_header(mimeBuffer);
			if(rc)
			{
				rt_kprintf("ICY: status code = %d!\n", rc);
				lwip_close(socket_handle);
				return -rc;
			}
		}

		if (strstr(mimeBuffer, "HTTP/1."))
		{
			rc = http_is_error_header(mimeBuffer);
			if(rc)
			{
				rt_kprintf("HTTP: status code = %d!\n", rc);
				lwip_close(socket_handle);
				return -rc;
			}
		}

		if (strstr(mimeBuffer, "icy-name:"))
		{
			/* get name */
			char* name;

			name = mimeBuffer + strlen("icy-name:");
			session->station_name = rt_strdup(name);
			rt_kprintf("station name: %s\n", session->station_name);
		}

		if (strstr(mimeBuffer, "icy-br:"))
		{
			/* get bitrate */
			session->bitrate = strtol(mimeBuffer + strlen("icy-br:"), RT_NULL, 10);
			rt_kprintf("bitrate: %d\n", session->bitrate);
		}

		if (strstr(mimeBuffer, "icy-metaint:"))
		{
			/* get metaint */
			session->metaint = strtol(mimeBuffer + strlen("icy-metaint:"), RT_NULL, 10);
			rt_kprintf("metaint: %d\n", session->metaint);
		}

		if (strstr(mimeBuffer, "content-type:"))
		{
			/* check content-type */
			if (strstr(mimeBuffer, "audio/mpeg") == RT_NULL)
			{
				rt_kprintf("ICY content is not audio/mpeg.\n");
				lwip_close(socket_handle);
				return -1;
			}
		}

		if (strstr(mimeBuffer, "Content-Type:"))
		{
			/* check content-type */
			if (strstr(mimeBuffer, "audio/mpeg") == RT_NULL)
			{
				rt_kprintf("ICY content is not audio/mpeg.\n");
				lwip_close(socket_handle);
				return -1;
			}
		}
	}

	// We've sent the request, and read the headers.  SockHandle is
	// now at the start of the main data read for a file io read.
	return peer_handle;
}
Ejemplo n.º 10
0
//
// This is the main HTTP client connect work.  Makes the connection
// and handles the protocol and reads the return headers.  Needs
// to leave the stream at the start of the real data.
//
static int http_connect(struct http_session* session,
    struct sockaddr_in * server, char *host_addr, const char *url)
{
	int socket_handle;
	int peer_handle;
	int rc;
	char mimeBuffer[100];
	int timeout = HTTP_RCV_TIMEO;

	if((socket_handle = socket( PF_INET, SOCK_STREAM, IPPROTO_TCP )) < 0)
	{
		rt_kprintf( "HTTP: SOCKET FAILED\n" );
		return -1;
	}

	/* set recv timeout option */
	setsockopt(socket_handle, SOL_SOCKET, SO_RCVTIMEO, (void*)&timeout, sizeof(timeout));

	peer_handle = connect( socket_handle, (struct sockaddr *) server, sizeof(*server));
	if ( peer_handle < 0 )
	{
		rt_kprintf( "HTTP: CONNECT FAILED %i\n", peer_handle );
		return -1;
	}

	{
		char *buf;
		rt_uint32_t length;

		buf = rt_malloc (512);
		if (*url)
			length = rt_snprintf(buf, 512, _http_get, url, host_addr);
		else
			length = rt_snprintf(buf, 512, _http_get, "/", host_addr);

		rc = send(peer_handle, buf, length, 0);
		// rt_kprintf("HTTP request:\n%s", buf);

		/* release buffer */
		rt_free(buf);
	}

	// We now need to read the header information
	while ( 1 )
	{
		int i;

		// read a line from the header information.
		rc = http_read_line( peer_handle, mimeBuffer, 100 );
		// rt_kprintf(">> %s\n", mimeBuffer);

		if ( rc < 0 ) return rc;

		// End of headers is a blank line.  exit.
		if (rc == 0) break;
		if ((rc == 2) && (mimeBuffer[0] == '\r')) break;

		// Convert mimeBuffer to upper case, so we can do string comps
		for(i = 0; i < strlen(mimeBuffer); i++)
			mimeBuffer[i] = toupper(mimeBuffer[i]);

		if(strstr(mimeBuffer, "HTTP/1.")) // First line of header, contains status code. Check for an error code
		{
			rc = http_is_error_header(mimeBuffer);
			if(rc)
			{
				rt_kprintf("HTTP: status code = %d!\n", rc);
				return -rc;
			}
		}

		if(strstr(mimeBuffer, "CONTENT-LENGTH:"))
		{
			session->size = http_parse_content_length(mimeBuffer);
			rt_kprintf("size = %d\n", session->size);
		}
	}

	// We've sent the request, and read the headers.  SockHandle is
	// now at the start of the main data read for a file io read.
	return peer_handle;
}
Ejemplo n.º 11
0
const char *http_request_line(int fd, char *reqpath, char *env, size_t *env_len, int env_buf_size, int reqpath_buf_size)
{
    static char buf[8192];      /* static variables are not on the stack */
    char *sp1, *sp2, *qp, *envp = env;

    /* For lab 2: don't remove this line. */
    touch("http_request_line");

    if (http_read_line(fd, buf, sizeof(buf)) < 0)
        return "Socket IO error";

    /* Parse request like "GET /foo.html HTTP/1.0" */
    sp1 = strchr(buf, ' ');
    if (!sp1)
        return "Cannot parse HTTP request (1)";
    *sp1 = '\0';
    sp1++;
    if (*sp1 != '/')
        return "Bad request path";

    sp2 = strchr(sp1, ' ');
    if (!sp2)
        return "Cannot parse HTTP request (2)";
    *sp2 = '\0';
    sp2++;

    /* We only support GET and POST requests */
    if (strcmp(buf, "GET") && strcmp(buf, "POST"))
        return "Unsupported request (not GET or POST)";

    /* We start building the env, without exceeding env_buf_size
       Checks for REQUEST_METHOD and SERVER_NAME are optional, but I add them
       for consistency in case we would like to extend the code in the future.
    */
    int copied = 0;

    int request_method_size = snprintf(envp, env_buf_size-copied, "REQUEST_METHOD=%s", buf);
    if (request_method_size >= env_buf_size-copied)
        return "Unsupported request method";

    envp += request_method_size+1;
    copied += request_method_size+1;

    int protocol_size = snprintf(envp, env_buf_size-copied, "SERVER_PROTOCOL=%s", sp2);
    if (protocol_size >= env_buf_size-copied)
        return "Unsupported server protocol";

    envp += protocol_size+1;
    copied += protocol_size+1;

    /* parse out query string, e.g. "foo.py?user=bob" */
    if ((qp = strchr(sp1, '?')))
    {
        *qp = '\0';
        int query_string_size = snprintf(envp, env_buf_size-copied, "QUERY_STRING=%s", qp + 1);
        if (query_string_size >= env_buf_size-copied)
            return "Query string too long";

        envp += query_string_size+1;
        copied += query_string_size+1;
    }

    /* decode URL escape sequences in the requested path into reqpath */
    url_decode(reqpath, sp1, reqpath_buf_size);

    int request_uri_size = snprintf(envp, env_buf_size-copied, "REQUEST_URI=%s", reqpath);
    if (request_uri_size >= env_buf_size-copied)
        return "Request URI too long";

    envp += request_uri_size+1;
    copied += request_uri_size+1;

    int server_name_size = snprintf(envp, env_buf_size-copied, "SERVER_NAME=zoobar.org");
    if (server_name_size >= env_buf_size-copied)
        return "Request line too long";

    copied += request_uri_size+1;
    *env_len = copied;
    return NULL;
}
Ejemplo n.º 12
0
int  radio_list_update_servicer_connect(struct sockaddr_in* server, char* host_addr, const char* url)
{
    int socket_handle;
    int peer_handle;
    int rc;
    char mimeBuffer[256];

    if((socket_handle = socket( PF_INET, SOCK_STREAM, IPPROTO_TCP )) < 0)
    {
        rt_kprintf( "RLUS: SOCKET FAILED\n" );
        return -1;
    }

    peer_handle = connect( socket_handle, (struct sockaddr *) server, sizeof(*server));
    if ( peer_handle < 0 )
    {
        closesocket(socket_handle);
        rt_kprintf( "RLUS: CONNECT FAILED %i\n", peer_handle );
        return -1;
    }

    {
        char *buf;
        rt_uint32_t length;

        buf = rt_malloc (512);
        if (*url)
            length = rt_snprintf(buf, 512, _radio_list_update_get, url, host_addr, ntohs(server->sin_port));
        else
            length = rt_snprintf(buf, 512, _radio_list_update_get, "/", host_addr, ntohs(server->sin_port));

        rc = send(peer_handle, buf, length, 0);
        rt_kprintf("radio list update request:\n%s", buf);

        /* release buffer */
        rt_free(buf);
    }
    /* read the header information */
    while ( 1 )
    {
        // read a line from the header information.
        rc = http_read_line(peer_handle, mimeBuffer, 100);
        rt_kprintf(">>%s", mimeBuffer);

        if ( rc < 0 )
        {
            closesocket(peer_handle);
            return rc;
        }
        // End of headers is a blank line.  exit.
        if (rc == 0) break;
        if ((rc == 2) && (mimeBuffer[0] == '\r')) break;

        if (strstr(mimeBuffer, "HTTP/1."))
        {
            rc = http_is_error_header(mimeBuffer);
            if(rc)
            {
                rt_kprintf("HTTP: status code = %d!\n", rc);
                closesocket(peer_handle);
                return -rc;
            }
        }

        if (strstr(mimeBuffer, "content-type:"))
        {
            /* check content-type */
            if (strstr(mimeBuffer, "text/plain") == RT_NULL)
            {
                rt_kprintf("radio list update content is not text/plain.\n");
                closesocket(peer_handle);
                return -1;
            }
        }

        if (strstr(mimeBuffer, "Content-Type:"))
        {
#if 0       // not check content-type anymore
            /* check content-type */
            if (strstr(mimeBuffer, "text/plain") == RT_NULL)
            {
                rt_kprintf("radio list update content is not text/plain.\n");
                closesocket(peer_handle);
                return -1;
            }
#endif
        }
    }

    return peer_handle;
}