int http_connect(http_client_t *http_client, char *hostname, int port)
{
    http_request_init(&http_client->request);
    http_response_init(&http_client->response);
    sprintf(http_client->request.req_header.host, "%s", hostname);

    return open_tcp(&http_client->connection, hostname, port);
}
int test_parse_invalid_http_version()
{
  printf("test_parse_invalid_http_version - running\n");
  http_request* req;
  http_request_init(&req);
  char* data = "GET http://www.redd.it/hej/ HTTP/2.0\r\n";
  http_parse_method(req, data);
  assert(req->version == HTTP_VERSION_INVALID);
  printf("test_parse_invalid_http_version - ok\n");
  return 0;
}
int test_parse_invalid_method()
{
  printf("test_parse_invalid_method - running\n");
  http_request* req;
  http_request_init(&req);
  char* data = "FAKE http://www.redd.it/hej/ HTTP/1.1\r\n";
  http_parse_method(req, data);
  assert(strcmp(http_methods[req->method], "INVALID") == 0);
  printf("test_parse_invalid_method - ok\n");
  return 0;
}
Exemple #4
0
void http_request_free(HttpRequest* request) {
  if(request->headers) {
    for(size_t i=0; i<request->num_headers; ++i) {
      http_header_free(&request->headers[i]);
    }
    free(request->headers);
  }
  if(request->uri) free(request->uri);
  if(request->body) free(request->body);
  if(request->error) free(request->error);
  http_request_init(request);
}
int test_parse_valid_method()
{
  printf("test_parse_valid_method - running\n");
  http_request* req;
  http_request_init(&req);
  char* data = "GET http://www.redd.it/hej/ HTTP/1.1\r\n";
  http_parse_method(req, data);
  assert(strcmp(http_methods[req->method], "GET") == 0);
  assert(req->version == HTTP_VERSION_1_1);
  assert(strcmp(req->search_path, "http://www.redd.it/hej/") == 0);
  http_request_destroy(req);
  printf("test_parse_valid_method - ok\n");
  return 0;
}
Exemple #6
0
http_request_t * http_request_new(const char * url) {
	http_request_t * ret = m_new0(http_request_t, 1);
	assert(ret != NULL);
	ret->url = strdup(url);

	ret->ver = NULL;
	ret->uri = NULL;

	ret->handlers.on_load = NULL;
	ret->handlers.on_error = NULL;
	ret->handlers.on_progress = NULL;
	ret->handlers.on_state_change = NULL;
	ret->handlers.on_timeout = NULL;
	ret->handlers.on_loadstart = NULL;
	ret->state = STATE_UNSENT;


	http_request_init(ret);

	return ret;
}
Exemple #7
0
int http_parse_request_line(const char *line, struct http_request *request)
{
    const char *p, *q;
    struct uri *uri;
    char *uri_s;

    http_request_init(request);

    p = line;
    while (*p == ' ')
        p++;

    /* Method (CONNECT, GET, etc.). */
    q = p;
    while (is_token_char(*q))
        q++;
    if (p == q)
        goto badreq;
    request->method = mkstr(p, q);

    /* URI. */
    p = q;
    while (*p == ' ')
        p++;
    q = p;
    while (*q != '\0' && *q != ' ')
        q++;
    if (p == q)
        goto badreq;
    uri_s = mkstr(p, q);

    /* RFC 2616, section 5.1.1: The method is case-sensitive.
       RFC 2616, section 5.1.2:
         Request-URI    = "*" | absoluteURI | abs_path | authority
       The absoluteURI form is REQUIRED when the request is being made to a
       proxy... The authority form is only used by the CONNECT method. */
    if (strcmp(request->method, "CONNECT") == 0) {
        uri = uri_parse_authority(&request->uri, uri_s);
    } else {
        uri = uri_parse(&request->uri, uri_s);
    }
    free(uri_s);
    if (uri == NULL)
        /* The URI parsing failed. */
        goto badreq;

    /* Version number. */
    p = q;
    while (*p == ' ')
        p++;
    if (*p == '\0') {
        /* No HTTP/X.X version number indicates version 0.9. */
        request->version = HTTP_09;
    } else {
        q = parse_http_version(p, &request->version);
        if (p == q)
            goto badreq;
    }

    return 0;

badreq:
    http_request_free(request);
    return 400;
}
Exemple #8
0
void *thread_worker(void *arg)
{
  struct thread_info *tinfo = arg;
  static char buffer[4096];
  int pipe_socket = tinfo->pipe_socket;
  // printf("thread %d pipe %d\n", tinfo->thread_num, pipe_socket);

  int epoll = epoll_create1(0);

  struct epoll_event pipe_event;
  pipe_event.data.fd = pipe_socket;
  pipe_event.events = EPOLLIN;
  if(epoll_ctl(epoll, EPOLL_CTL_ADD, pipe_socket, &pipe_event) == -1) {
    perror("Error epoll_ctl connection sock\n");
    exit(1);
  }

  while (1) {
    struct epoll_event events[MAX_EVENTS];
    int n_events = epoll_wait(epoll, events, MAX_EVENTS, -1);
    if(n_events == -1) {
      perror("Error epoll_wait\n");
      exit(1);
    }

    for (int i = 0; i < n_events; ++i)
    {
      if(events[i].data.fd == pipe_socket) {
        int accept_socket;
        recv_socket_from_pipeline(pipe_socket, &accept_socket);

        struct epoll_event new_event;
        new_event.data.fd = accept_socket;
        new_event.events = EPOLLIN | EPOLLET;
        if(epoll_ctl(epoll, EPOLL_CTL_ADD, accept_socket, &new_event) == -1) {
          perror("Error epoll_ctl connection sock\n");
          exit(1);
        }
      } else {
        int cur_socket = events[i].data.fd;
        // printf("socket = %d\n", cur_socket);
        ssize_t size = recv(cur_socket, buffer, sizeof(buffer), MSG_NOSIGNAL);
        // printf("size = %lu\n", size);
        if (size > 0) {
          buffer[size] = 0;
          // printf("%s", buffer);
          struct http_request req;
          http_request_init(&req);
          struct http_response res;
          http_response_init(&res);
          int fd;
            // struct http_io *w_read = (struct http_io *)watcher;
          if(http_request_parse(&req, buffer, size) == -1) {
            res.code = _501;
          } else if(req.method != GET) {
            res.code = _501;
          } else {
            fd = open(req.path, O_RDONLY);
            if(fd == -1) {
              res.code = _404;
            } else {
              res.code = _200;
                /* get the size of the file to be sent */
              struct stat stat_buf;
              fstat(fd, &stat_buf);
              res.content_length = stat_buf.st_size;
              res.content_type = html;
            }
            render_header(&res);
            send(cur_socket, res.header, strlen(res.header), MSG_NOSIGNAL);
            if(res.code == _200) {
              ssize_t l;
              while((l = read(fd, buffer, sizeof(buffer))) > 0) {
                send(cur_socket, buffer, l, MSG_NOSIGNAL);
              }
              close(fd);
            }
          }
        }
        shutdown(cur_socket, SHUT_RDWR);
        close(cur_socket);
      }
    }
  }

  // sem_post(&semaphore);
  return NULL;
}
Exemple #9
0
int main(int argc, char *argv[])
{
    int sockfd, portno, n;
    struct sockaddr_in serv_addr;
    struct hostent *server;

    log_init("client.log", 1);

    char buffer[2049];
    int buflen;
    char url[256], host[256], res[256];
    printf("URL to access: ");
    gets(url);
    if(strncmp(url, "http://", 7)) {
        printf("error: url should started with http://\n");
        return -1;
    }

    int i, len = strlen(url), hostlen = 0;
    for(i = 7; i < len; i++, hostlen++) {
        if(url[i] == ':') {
            strncpy(host, url + 7, hostlen);
            portno = atoi(url + i + 1);
            while(i < len && url[i] != '/') i++;
            if(i >= len) strcpy(res, "/");
            else strcpy(res, url + i);
            break;
        } else if(url[i] == '/') {
            strncpy(host, url + 7, hostlen);
            portno = 80;
            strcpy(res, url + i);
            break;
        }
    }
    if(i >= len) {
        printf("error: malformed url");
        return 0;
    }

    printf("connecting to host %s at port %d with url %s\n", host, portno, res);
    sockfd = socket(AF_INET, SOCK_STREAM, 0);
    if (sockfd < 0)
        perror("error while opening socket: ");
    server = gethostbyname(host);
    if (server == NULL) {
        perror("host not found: ");
        return 0;
    }
    bzero((char *) &serv_addr, sizeof(serv_addr));
    serv_addr.sin_family = AF_INET;
    bcopy((char *)server->h_addr,
         (char *)&serv_addr.sin_addr.s_addr,
         server->h_length);
    serv_addr.sin_port = htons(portno);
    if (connect(sockfd,(struct sockaddr *) &serv_addr,sizeof(serv_addr)) < 0) {
        perror("error while connecting: ");
        return 0;
    }

    http_request_t req;
    http_response_t resp;
    http_request_init(&req);
    http_response_init(&resp);
    req.type = HTTP_GET;
    strcpy(req.url, res);
    req.version = HTTP_VERSION_1_1;
    sprintf(host, "%s:%d", host, portno);
    dict_put(req.fields, "Host", host);
    if(0 > http_assemble_request(&req, sockfd)) {
        perror("error while writing: ");
        return 0;
    }

    buflen = 0;
    do {
        n = read(sockfd, buffer + buflen, 2048 - buflen);
        if(n > 0)
            buflen += n;
    } while(n > 0 && buflen < 2048);

    puts("===raw resp===");
    for(i = 0; i < buflen; i++) {
        putchar(buffer[i]);
    }
    puts("\n===end===\n");

    if(http_parse_response(&resp, buffer, buflen)) {
        printf("error while parsing response\n");
        return 0;
    }
    printf("%s\n", resp.document);
    http_request_free(&req);
    http_response_free(&resp);
    close(sockfd);
    log_close();
    return 0;
}
Exemple #10
0
static THREAD_RETVAL
httpd_thread(void *arg)
{
	httpd_t *httpd = arg;
	char buffer[1024];
	int i;

	assert(httpd);

	while (1) {
		fd_set rfds;
		struct timeval tv;
		int nfds=0;
		int ret;

		MUTEX_LOCK(httpd->run_mutex);
		if (!httpd->running) {
			MUTEX_UNLOCK(httpd->run_mutex);
			break;
		}
		MUTEX_UNLOCK(httpd->run_mutex);

		/* Set timeout value to 5ms */
		tv.tv_sec = 1;
		tv.tv_usec = 5000;

		/* Get the correct nfds value and set rfds */
		FD_ZERO(&rfds);
		if (httpd->open_connections < httpd->max_connections) {
			FD_SET(httpd->server_fd4, &rfds);
			nfds = httpd->server_fd4+1;
			if (httpd->server_fd6 != -1) {
				FD_SET(httpd->server_fd6, &rfds);
				if (nfds <= httpd->server_fd6) {
					nfds = httpd->server_fd6+1;
				}
			}
		}
		for (i=0; i<httpd->max_connections; i++) {
			int socket_fd;
			if (!httpd->connections[i].connected) {
				continue;
			}
			socket_fd = httpd->connections[i].socket_fd;
			FD_SET(socket_fd, &rfds);
			if (nfds <= socket_fd) {
				nfds = socket_fd+1;
			}
		}

		ret = select(nfds, &rfds, NULL, NULL, &tv);
		if (ret == 0) {
			/* Timeout happened */
			continue;
		} else if (ret == -1) {
			/* FIXME: Error happened */
			logger_log(httpd->logger, LOGGER_INFO, "Error in select");
			break;
		}

		if (FD_ISSET(httpd->server_fd4, &rfds)) {
			ret = httpd_accept_connection(httpd, httpd->server_fd4, 0);
			if (ret == -1) {
				break;
			} else if (ret == 0) {
				continue;
			}
		}
		if (httpd->server_fd6 != -1 && FD_ISSET(httpd->server_fd6, &rfds)) {
			ret = httpd_accept_connection(httpd, httpd->server_fd6, 1);
			if (ret == -1) {
				break;
			} else if (ret == 0) {
				continue;
			}
		}
		for (i=0; i<httpd->max_connections; i++) {
			http_connection_t *connection = &httpd->connections[i];

			if (!connection->connected) {
				continue;
			}
			if (!FD_ISSET(connection->socket_fd, &rfds)) {
				continue;
			}

			/* If not in the middle of request, allocate one */
			if (!connection->request) {
				connection->request = http_request_init(httpd->use_rtsp);
				assert(connection->request);
			}

			logger_log(httpd->logger, LOGGER_DEBUG, "Receiving on socket %d", connection->socket_fd);
			ret = recv(connection->socket_fd, buffer, sizeof(buffer), 0);
			if (ret == 0) {
				logger_log(httpd->logger, LOGGER_INFO, "Connection closed for socket %d", connection->socket_fd);
				httpd_remove_connection(httpd, connection);
				continue;
			}

			/* Parse HTTP request from data read from connection */
			http_request_add_data(connection->request, buffer, ret);
			if (http_request_has_error(connection->request)) {
				logger_log(httpd->logger, LOGGER_INFO, "Error in parsing: %s", http_request_get_error_name(connection->request));
				httpd_remove_connection(httpd, connection);
				continue;
			}

			/* If request is finished, process and deallocate */
			if (http_request_is_complete(connection->request)) {
				http_response_t *response = NULL;

				httpd->callbacks.conn_request(connection->user_data, connection->request, &response);
				http_request_destroy(connection->request);
				connection->request = NULL;

				if (response) {
					const char *data;
					int datalen;
					int written;
					int ret;

					/* Get response data and datalen */
					data = http_response_get_data(response, &datalen);

					written = 0;
					while (written < datalen) {
						ret = send(connection->socket_fd, data+written, datalen-written, 0);
						if (ret == -1) {
							/* FIXME: Error happened */
							logger_log(httpd->logger, LOGGER_INFO, "Error in sending data");
							break;
						}
						written += ret;
					}
				} else {
					logger_log(httpd->logger, LOGGER_INFO, "Didn't get response");
				}
				http_response_destroy(response);
			}
		}
	}

	/* Remove all connections that are still connected */
	for (i=0; i<httpd->max_connections; i++) {
		http_connection_t *connection = &httpd->connections[i];

		if (!connection->connected) {
			continue;
		}
		logger_log(httpd->logger, LOGGER_INFO, "Removing connection for socket %d", connection->socket_fd);
		httpd_remove_connection(httpd, connection);
	}

	logger_log(httpd->logger, LOGGER_INFO, "Exiting HTTP thread");

	return 0;
}
Exemple #11
0
int main(int argc, char *argv[]) {
    printf("%s", "start\n");
    int listen_fd;
    int rcode;
    struct epoll_event *events;
    
    if (argc != 2) {
        fprintf(stderr, "usage: %s [port]\n", argv[0]);
        exit(EXIT_FAILURE);
    }
    
    struct sigaction sa;
    memset(&sa, 0, sizeof(sa));
    sa.sa_handler = SIG_IGN;
    sa.sa_flags = 0;
    if (sigaction(SIGPIPE, &sa, NULL)) {
        printf("ignore SIGPIPE\n");
    }
    
    struct sockaddr_in client_addr;
    socklen_t client_len = 1;
    memset(&client_addr, 0, sizeof(struct sockaddr_in));
    
    /* create and bind the port, and then set the socket to non blocking mode */
    listen_fd = open_listenfd(atoi(argv[1]));
    debug("listen fd = %d", listen_fd);
    rcode = make_socket_non_blocking(listen_fd);
    if (rcode == -1) {
        log_err("error when making socket non blocking");
        abort();
    }
    
    /* create epoll event */
    int efd = epoll_create1(0);
    if (efd == -1) {
        log_err("epoll_create");
        abort();
    }
    struct epoll_event event;

    events = (struct epoll_event *)malloc(sizeof(struct epoll_event) * MAXEVENTS);
    
    http_request_t *request = (http_request_t *)malloc(sizeof(http_request_t));
    http_request_init(request, listen_fd);
    
    event.data.ptr = (void *)request;
    event.events = EPOLLIN | EPOLLET;
    
    /* register the listen event */
    rcode = epoll_ctl(efd, EPOLL_CTL_ADD, listen_fd, &event);
    if (rcode == -1) {
        perror("epoll_ctl");
        abort();
    }
    
    threadpool_t *tp = threadpool_init(NUM_OF_THREADS);
    
    /* event loop */
    while (1) {
        int n = epoll_wait(efd, events, MAXEVENTS, -1);
        
        /* process each incoming IO event */
        int i;
        for (i = 0; i < n; i++) {
            http_request_t *r = (http_request_t *)events[i].data.ptr;
            int fd = r->fd;
            debug("event fd = %d", fd);
            if (fd == listen_fd) {  /* incoming connection event */
                
                while (1) {
                    int client_fd;
                    debug("waiting for accept");
                    client_fd = accept(listen_fd, (struct sockaddr *)&client_addr, &client_len);
                    
                    if (client_fd == -1) {
                        if (errno == EAGAIN || errno == EWOULDBLOCK) {
                            // we have already processed the incoming connection
                            debug("incoming connection processed\n");
                            break;
                        }
                        else {
                            log_err("error occured when accepting connection\n");
                            break;
                        }
                    }
                    
                    rcode = make_socket_non_blocking(client_fd);
                    if (rcode == -1) {
                        if (errno == EAGAIN || errno == EWOULDBLOCK)
                            // we have already processed the incoming connection
                            break;
                        log_err("fail to accept the connection\n");
                        break;
                    }
                    debug("new connection fd %d", client_fd);
                    
                    http_request_t *request = (http_request_t *)malloc(sizeof(http_request_t));
                    http_request_init(request, client_fd);
                    event.data.ptr = (void *)request;
                    event.events = EPOLLIN | EPOLLET;
                    /* add the new event into epoll */
                    rcode = epoll_ctl(efd, EPOLL_CTL_ADD, client_fd, &event);
                    if (rcode == - 1) {
                        log_err("fail in epoll_ctl in epoll_wait");
                        abort();
                    }
                }
                debug("end accept");
            }
            else if ((events[i].events & EPOLLERR) || (events[i].events & EPOLLHUP) || (!(events[i].events & EPOLLIN))) {
                /* an error has occured on this fd, or the socket is not ready for reading */
                log_err("error events: %d", events[i].events);
                if (events[i].events & EPOLLERR)
                    log_err("EPOLLERR");
                if (events[i].events & EPOLLHUP)
                    log_err("EPOLLHUP");
                if (!(events[i].events & EPOLLIN))
                    log_err("EPOLLIN");
                close(fd);
                continue;
            }
            else {  /* incoming data read event */
                /* add the event to the thread pool list */
                threadpool_add(tp, handle_http, events[i].data.ptr);
                debug("thread count: %d", tp->thread_count);
                debug("thread queue size: %d", tp->queue_size);
            }
        }
    }
    
    threadpool_destroy(tp);
    return 0;
}
void application_start( void )
{
    wiced_ip_address_t  ip_address;
    wiced_result_t      result;

    /* We need three headers - host, content type, and content length */
    http_header_field_t header[3];
    /* Header 0 is the Host header */
    header[0].field        = HTTP_HEADER_HOST;
    header[0].field_length = strlen( HTTP_HEADER_HOST );
    header[0].value        = SERVER_HOST;
    header[0].value_length = strlen( SERVER_HOST );
    /* Header 1 is the content type (JSON) */
    header[1].field        =  HTTP_HEADER_CONTENT_TYPE;
    header[1].field_length = strlen( HTTP_HEADER_CONTENT_TYPE );
    header[1].value        = "application/json";
    header[1].value_length = strlen( "application/json" );
    /* Header 2 is the content length. In this case, it is the length of the JSON message */
    sprintf(json_len,"%d", strlen(JSON_MSG)); /* Calculate the length of the JSON message and store the value as a string */
    header[2].field        = HTTP_HEADER_CONTENT_LENGTH;
    header[2].field_length = strlen( HTTP_HEADER_CONTENT_LENGTH );
    header[2].value        = json_len; // This holds the length of the JSON message as a sting containing the decimal value
    header[2].value_length = strlen( json_len ); // This is the length of the string that holds the JSON message size. For example, if the JSON is 12 characters, this would be "2" because the string "12" is 2 characters long.

    wiced_init( );

    /* This semaphore will be used to wait for one request to finish before re-initializing and starting the next one */
    wiced_rtos_init_semaphore(&httpWait);

    wiced_network_up(WICED_STA_INTERFACE, WICED_USE_EXTERNAL_DHCP_SERVER, NULL);

    WPRINT_APP_INFO( ( "Resolving IP address of %s\n", SERVER_HOST ) );
    wiced_hostname_lookup( SERVER_HOST, &ip_address, DNS_TIMEOUT_MS, WICED_STA_INTERFACE );
    WPRINT_APP_INFO( ( "%s is at %u.%u.%u.%u\n", SERVER_HOST,
                                                 (uint8_t)(GET_IPV4_ADDRESS(ip_address) >> 24),
                                                 (uint8_t)(GET_IPV4_ADDRESS(ip_address) >> 16),
                                                 (uint8_t)(GET_IPV4_ADDRESS(ip_address) >> 8),
                                                 (uint8_t)(GET_IPV4_ADDRESS(ip_address) >> 0) ) );

    /* Initialize client */
    http_client_init( &client, WICED_STA_INTERFACE, event_handler, NULL );
    client.peer_cn = NULL; /* If you set hostname, library will make sure subject name in the server certificate is matching with host name you are trying to connect. Pass NULL if you don't want to enable this check */

    /* Connect to the server */
    if ( ( result = http_client_connect( &client, (const wiced_ip_address_t*)&ip_address, SERVER_PORT, HTTP_NO_SECURITY, CONNECT_TIMEOUT_MS ) ) == WICED_SUCCESS )
    {
        connected = WICED_TRUE;
        WPRINT_APP_INFO( ( "Connected to %s\n", SERVER_HOST ) );
    }
    else
    {
        WPRINT_APP_INFO( ( "Error: failed to connect to server: %u\n", result) );
        return; /* Connection failed - exit program */
    }

    /* Send a POST to resource /anything */
    http_request_init( &request, &client, HTTP_POST, "/post", HTTP_1_1 );
    http_request_write_header( &request, &header[0], 3 ); // We need 3 headers
    http_request_write_end_header( &request );
    http_request_write( &request, (uint8_t* ) JSON_MSG, strlen(JSON_MSG)); /* Write the content */
    http_request_flush( &request );

    wiced_rtos_get_semaphore(&httpWait, WICED_WAIT_FOREVER); /* Wait for this request to complete before going on */
    /* Disconnect from the server and deinit since we are done now */
    http_client_disconnect( &client );
    http_client_deinit( &client );
}
Exemple #13
0
 Connection(size_t read_buf_capa) : read_buffer(read_buf_capa),
                                    read_clear(true), parse_offset(0), in_body(false) {
   http_parser_init(&parser);
   http_request_init(&req);
 }