Exemplo n.º 1
0
int onData(int epfd,struct epoll_event ev,http_request_r **r)
{
	char buf[1024];
	void *msg;
	int ret;
	int j;

	memset(buf,0,1024);
        ret = recv(ev.data.fd,buf,1024,0);
        if(ret==-1)
        {
              if(errno != EINTR  && errno != EAGAIN){
                    close(ev.data.fd);
                    ev.data.fd = -1;
                    perror("error");
              }else{
                    perror("recive error");
              }
        }
        else if(ret==0)
	{
              close(ev.data.fd);
              ev.data.fd = -1;
        }
        else if(ret>0)
        {
		struct http_request_r *p;
		p = find_http_request(*r,ev.data.fd);
	      	http_request_parse(p,buf);

		if(p->is_end==1)
		{
			struct http_response_r *o;
			o = (struct http_response_r *)malloc(sizeof(struct http_response_r));			
			memset(o,0,sizeof(struct http_response_r));

			static_http_response_out(*r,o);
              		
			ret = send(ev.data.fd,o->buf,o->size,0);
              		if(ret<0)
              		{
                    		perror("send error!");
                    		return -1;
              		}
	
			ret = send(ev.data.fd,o->body,o->content_length,0);
              		if(ret<0)
              		{
                    		perror("send error!");
                    		return -1;
              		}
	
			delete_http_request(r,ev.data.fd);	
		
			close(ev.data.fd);
                	ev.data.fd=-1;		
		}		
        }
	return 0;
}
Exemplo n.º 2
0
int handle_connection(socket_buf sb)
{
	int size;
	http_request rst;
	char response_head[] = "HTTP/1.1 200 OK\r\nContent-Type: text/html\r\n\r\n";
	char response_fail[] = "HTTP/1.1 404 not found\r\nContent-Type: text/html\r\n\r\n<html><body>request not found</body></html>";

	if(http_request_parse(sb->read_buf, &rst) == L_HTTP_FAIL)
		return L_HTTP_FAIL;

	sb->rb_size = 0;
	printf("file:%s\n", rst.file);
	
	if((size = get_file_size(rst.file)) == L_HTTP_FAIL) {
		strcpy(sb->write_buf, response_fail);
		sb->wb_size = strlen(response_fail);
		return L_HTTP_SUCCESS;
	}

	size += strlen(response_head);
	if(size < strlen(response_head))
		return L_HTTP_FAIL;
	if(socket_write_buf_alloc(sb, size) == L_HTTP_FAIL)
		return L_HTTP_FAIL;	

	strncpy(sb->write_buf, response_head, strlen(response_head));
	generate_response(sb->write_buf + strlen(sb->write_buf), rst.file);

	sb->wb_size = size;
	return L_HTTP_SUCCESS;
}
Exemplo n.º 3
0
/*
 * Reads an HTTP request from stream (fd), and writes an HTTP response
 * containing:
 *
 *   1) If user requested an existing file, respond with the file
 *   2) If user requested a directory and index.html exists in the directory,
 *      send the index.html file.
 *   3) If user requested a directory and index.html doesn't exist, send a list
 *      of files in the directory with links to each.
 *   4) Send a 404 Not Found response.
 */
void handle_files_request(int fd) {
  struct http_request*request=http_request_parse(fd);
  char*fullpath,*fullfullpath;
  struct stat st;
  
  if(0==strcmp("GET",request->method)){
    fullpath=conc(server_files_directory,request->path);
    if(0==stat(fullpath,&st)){ // file/dir exists
      if(S_ISREG(st.st_mode)){ // is file
	http_send_file(fd,fullpath);
      }else if(S_ISDIR(st.st_mode)){ // is dir
	fullfullpath=conc(fullpath,"/index.html");
	if(0==stat(fullfullpath,&st)){ // has an index.html
	  http_send_file(fd,fullfullpath);
	}else{ // hasnt. list files
	  DIR*d=opendir(fullpath);
	  struct dirent*di;
	  http_start_response(fd,200);
	  http_send_header(fd,"Content-type","text/html");
	  http_end_headers(fd);
	  while(NULL!=(di=readdir(d)))
	    http_send_anchor(fd,di->d_name);
	}
	free(fullfullpath);
      }
    }else{ // doesnt exist. error 404
      http_start_response(fd,404);
      http_send_header(fd,"Content-type","text/html");
      http_end_headers(fd);
      http_send_string(fd,"<center><p>ERROR 404</p></center>");
    }
    free(fullpath);
  }
}
Exemplo n.º 4
0
Arquivo: httpd.c Projeto: ajsbu/cse506
static void
handle_client(int sock)
{
	struct http_request con_d;
	int r;
	char buffer[BUFFSIZE];
	int received = -1;
	struct http_request *req = &con_d;

	while (1)
	{
		// Receive message
		if ((received = read(sock, buffer, BUFFSIZE)) < 0)
			panic("failed to read");

		memset(req, 0, sizeof(req));

		req->sock = sock;

		r = http_request_parse(req, buffer);
		if (r == -E_BAD_REQ)
			send_error(req, 400);
		else if (r < 0)
			panic("parse failed");
		else
			send_file(req);

		req_free(req);

		// no keep alive
		break;
	}

	close(sock);
}
Exemplo n.º 5
0
int main()
{
    lib_init();
    socket_t * server = socket_new();
    int port = 5001;
    if(-1 == socket_bind(server, port)) {
        printf("port %i is busy\n", port);
        exit(1);
    }
    socket_listen(server);
    char buf[10000];
    socket_t * client = NULL;
     while(1)
    {
        client = socket_accept(server);
        socket_read(client, buf, sizeof(buf));
        printf("%s",buf);
        if (strlen(buf) != 0){
        http_request_t rs;
        rs = http_request_parse(buf);
        if (strcmp(rs.method,"GET") == 0 && strcmp(rs.uri, "/info") == 0 )
        {
            server_info(client);
        }

        }
    }
    return 0;
}
Exemplo n.º 6
0
int main(void) {
	// initializing first three investors for program to start with
	// initializing_END

	int PORT = 5000;
	lib_init();
	winSock = socket_new();
    db_t * db = db_new("teacher.db");
	// Checking if socket is not busy, closing app if it is
	if (socket_bind(winSock, PORT) == SOCKET_ERROR) {
		printf("Cannot bind %i port\n", PORT);
		socket_close(winSock);
		socket_free(winSock);
		return 0;
	}

	socket_listen(winSock);
	char buf[10000];
	socket_t * client = NULL;
	// main cycle of the program
	while (1) {
		printf("Awaiting for connections...\n");
		client = socket_accept(winSock);

		// Checking if client is not null, closing app if he is
		if (client == NULL) {
			printf("NULL client, closing app...\n");
			break;
		}

		int readStatus = socket_read(client, buf, sizeof(buf));

		// Skipping empty request (may appear from time to time)
		if (readStatus <= 0) {
			printf("Empty request, skipping...\n");
			socket_close(client);
			socket_free(client);
			continue;
		}

		// Printing info about the received request to console
		printf(">> Got request (readStatus: %i):\n'%s'\n", readStatus, buf);
		http_request_t request = http_request_parse(buf);

		// check the type/path of request (API/HTML) & analyze the method (GET/POST/DELETE)
		// and provide the client with proper answer
		server_analyzeRequest(&request, client, db);

		socket_free(client);
	}

	// end of program
	socket_close(winSock);
	socket_free(winSock);
	db_free(db);
	lib_free();
	return 0;
}
Exemplo n.º 7
0
/*
 * Reads an HTTP request from stream (fd), and writes an HTTP response
 * containing:
 *
 *   1) If user requested an existing file, respond with the file
 *   2) If user requested a directory and index.html exists in the directory,
 *      send the index.html file.
 *   3) If user requested a directory and index.html doesn't exist, send a list
 *      of files in the directory with links to each.
 *   4) Send a 404 Not Found response.
 */
void handle_files_request(int fd)
{

  /* YOUR CODE HERE */

  struct http_request *request = http_request_parse(fd);

  http_start_response(fd, 200);
  http_send_header(fd, "Content-type", "text/html");
  http_end_headers(fd);
  http_send_string(fd, "<center><h1>Welcome to httpserver!</h1><hr><p>Nothing's here yet.</p></center>");

}
Exemplo n.º 8
0
/* Receives an HTTP request from socket SOCKFD; returns a decoded KVMessage.
 * Returns NULL if there is an error. */
kvrequest_t *kvrequest_recieve(int sockfd) {
  kvrequest_t *kvreq = calloc(1, sizeof(kvrequest_t));
  kvreq->type = EMPTY;

  struct url_params *params = NULL;
  struct http_request *req = http_request_parse(sockfd);
  if (!req) goto error;
  params = url_decode(req->path);
  if (!params) goto error;

  if (!strcmp(req->method, "GET")) {
    if (!params->key) {
      kvreq->type = INDEX;
    } else {
      kvreq->type = GETREQ;
    }
  } else if (!strcmp(req->method, "PUT")) {
    if (!params->key || !params->val) goto error;
    kvreq->type = PUTREQ;
  } else if (!strcmp(req->method, "DELETE")) {
    if (!params->key) goto error;
    kvreq->type = DELREQ;
  } else if (!strcmp(req->method, "POST")) {  /* REGISTER, COMMIT, ABORT */
    if (!params->path) goto error;
    if (!strcmp(params->path, REGISTER_PATH)) {
      if (!params->key || !params->val) goto error;
      kvreq->type = REGISTER;
    } else if (!strcmp(params->path, COMMIT_PATH)) {
      kvreq->type = COMMIT;
    } else if (!strcmp(params->path, ABORT_PATH)) {
      kvreq->type = ABORT;
    }
  }
  if (kvreq->type == EMPTY)
    goto error;
  kvreq->key = params->key;
  kvreq->val = params->val;

  http_request_free(req);
  free(params->path);
  free(params);
  return kvreq;

error:
  http_request_free(req);
  url_params_free(params);
  kvrequest_free(kvreq);
  return NULL;
}
Exemplo n.º 9
0
int main(){

    lib_init();

    socket_t * serverSocket = socket_new();
    socket_bind(serverSocket, 5000);
    socket_listen(serverSocket);

    film_maker_t*  film_makers[FILM_MAKERS_AMOUNT];

     for (int i = 0; i < FILM_MAKERS_AMOUNT; i++) {
        film_makers[i] = film_maker_new();

    }

       parse(film_makers,"XML_format.xml");


    while(1) {
        socket_t * clientSocket = socket_accept(serverSocket);
        char buf[102400];

        if(socket_read(clientSocket, buf, 102400) == 0) {
            socket_close(clientSocket);
            socket_free(clientSocket);
            puts("Skipping empty request");
            continue;
        }



        http_request_t req = http_request_parse(buf);

        server_reply(clientSocket, req, film_makers);
//puts("fghj");

        socket_close(clientSocket);
        socket_free(clientSocket);
    }

    for (int i = 0; i < 3; i++)
        film_maker_free(film_makers[i]);

    socket_close(serverSocket);
    socket_free(serverSocket);
          lib_free();
        return 0;
}
Exemplo n.º 10
0
int main() {
    lib_init();

    list_t* list=list_new();

    lanser * freeLanser[10];

    for (int i = 0; i < 10; i++)
        freeLanser[i] = Freelanser_new();

  //  parse(freeLanser);

    socket_t * serverSocket = socket_new();
    socket_bind(serverSocket, 5000);
    socket_listen(serverSocket);


   while (1) {
        socket_t * clientSocket = socket_accept(serverSocket);

        char buf[10000]="";

        if (!socket_read(clientSocket, buf, sizeof(buf))) {
            puts("Skipping empty request");
            socket_close(clientSocket);
            socket_free(clientSocket);
            continue;
        }

        http_request_t req = http_request_parse(buf);

        server_answer(list,req,clientSocket,freeLanser);

        socket_close(clientSocket);
        socket_free(clientSocket);
    }

    socket_close(serverSocket);
    socket_free(serverSocket);

    lib_free();
    list_free(list);
    return 0;
}
Exemplo n.º 11
0
void server_newHtmlPupil(socket_t * client,list_t * pupils,char * buf,db_t * db){
     http_request_t req = http_request_parse(buf);
         char * id = (char *)http_request_getArg(&req, "id");
        char * name = (char *)http_request_getArg(&req, "name");
        char * surname = (char *)http_request_getArg(&req, "surname");
        char * score = (char *)http_request_getArg(&req, "score");
        char * Class = (char *)http_request_getArg(&req, "class");
        char * growth = (char *)http_request_getArg(&req,"growth");

//        if(checkInputData(name,surname,birthday,sex,Class,score,year) == 1){
            pupil_t * p = pupil_create();
            pupil_addInfo(p,db_getNewId(db),name,surname, atoi(Class),atof(score),atof(growth));
            printf("%s",pupil_getName(p));
            list_push_back(pupils,p);
            db_addPupil(db,pupils,buf);

            server_sendHtml(client,pupil_getHtml(p,atoi(id)));
 //       }

}
Exemplo n.º 12
0
int main() {
    lib_init();
    socket_t * server = socket_new();
    socket_bind(server, 5000);
    socket_listen(server);
	
   char buf[10000];
    char pathBuf[256];
    socket_t * client = NULL;

    while(1) {
		client = socket_accept(server);
        socket_read(client, buf, sizeof(buf));
		if (strlen(buf) == 0)
			continue;
        printf(">> Got request:\n%s\n", buf);

        http_getPath(buf, pathBuf, sizeof(pathBuf));

        http_request_t request = http_request_parse(buf);

        if (strcmp(request.uri, "/") == 0) {
            server_homepage(client);
        } else if (strcmp(request.uri, "/database") == 0) {
            server_students(client, &request);
        }  
        else if (strcmp(request.uri, "/info") == 0) {
            server_info(client);
        }
        else if (strcmp(request.uri, "/filename") == 0) {
            server_file_parse(client);
        }
        else {
            server_notFound(client);
        }
		socket_free(client);
    }
    socket_free(server);
    lib_free();
    return 0;
}
Exemplo n.º 13
0
void http_request_startServer(pupils_t pupils){
    lib_init();
    socket_t * serverSocket = socket_new();
    socket_bind(serverSocket, 5000);
    socket_listen(serverSocket);
    while(1){
        puts("Waiting for connections");
        socket_t * clientSocket = socket_accept(serverSocket);
        puts("New client");
        char buff[BUFFER_LENGTH];
        int readLength = socket_read(clientSocket, buff, BUFFER_LENGTH);
        if(readLength == 0){
            socket_close(clientSocket);
            socket_free(clientSocket);
            puts("Skipping empty request");
            continue;
        }

        printf("Got Request:\n---------------\n%s\n----------------\n", buff);

        http_request_t req = http_request_parse(buff);

        printf("Method: %s\nURI: %s\n", req.method, req.uri);
        puts("Data:");
        for(int i = 0; i < req.formLength; i++){
            char * kvStr = keyvalue_toString(&req.form[i]);
            printf("\t%s\n", kvStr);
            free(kvStr);
        }
        http_request_chooseMethod(req, clientSocket, pupils);
        socket_close(clientSocket);
        socket_free(clientSocket);
    }
    socket_close(serverSocket);
    socket_free(serverSocket);
    lib_free();
}
static int http_request_parse_request_line(struct http_request_parser *parser,
					   pool_t pool)
{
	struct http_message_parser *_parser = &parser->parser;
	const unsigned char *begin;
	size_t size, old_bytes = 0;
	int ret;

	while ((ret = i_stream_read_data(_parser->input, &begin, &size,
					 old_bytes)) > 0) {
		_parser->cur = begin;
		_parser->end = _parser->cur + size;

		if ((ret = http_request_parse(parser, pool)) < 0)
			return -1;

		i_stream_skip(_parser->input, _parser->cur - begin);
		if (ret > 0)
			return 1;
		old_bytes = i_stream_get_data_size(_parser->input);
	}

	if (ret == -2) {
		parser->error_code = HTTP_REQUEST_PARSE_ERROR_BROKEN_REQUEST;
		_parser->error = "HTTP request line is too long";
		return -1;
	}
	if (ret < 0) {
		if (_parser->input->eof &&
	    parser->state == HTTP_REQUEST_PARSE_STATE_INIT)
			return 0;
		parser->error_code = HTTP_REQUEST_PARSE_ERROR_BROKEN_STREAM;
		_parser->error = "Broken stream";
		return -1;
	}
	return 0;
}
Exemplo n.º 15
0
int main()
{
    lib_init();
    socket_t * server = socket_new();
    socket_bind(server, 5000);
    socket_listen(server);

    char buf[10000];
    char pathBuf[256];
    socket_t * client = NULL;
    while(1)
    {
        client = socket_accept(server);
        socket_read(client, buf, sizeof(buf));
        http_request_t rs;
        rs = http_request_parse(buf);
        server_reply(client,rs);

    }
    socket_free(server);
    socket_free(client);
    lib_free();
    return 0;
}
Exemplo n.º 16
0
int main()
{
    db_t* base = db_new("workers.db");
    lib_init();

    socket_t* server = socket_new();
    socket_bind(server, PORT);
    socket_listen(server);

    char buffer[10000];
    while(true)
    {
        puts("Waiting for client...!");
        socket_t* client = socket_accept(server);

        if(socket_read(client, buffer, sizeof(buffer)) <= 0)
        {
            socket_close(client);
            socket_free(client);
            continue;
        }

        printf("Request:\n%s\n", buffer);

        http_request_t request = http_request_parse(buffer);

        server_answerRequest(request, client, base);

        socket_free(client);
    }

    socket_free(server);
    lib_free();
    db_free(base);
    return 0;
}
Exemplo n.º 17
0
int main() {
    lib_init();
    socket_t * server = socket_new();
    socket_bind(server, 5000);
    socket_listen(server);

   char buf[10000];
    char pathBuf[256];
    socket_t * client = NULL;

    while(1) {
		client = socket_accept(server);
        socket_read(client, buf, sizeof(buf));
		if (strlen(buf) == 0)
			continue;
        printf(">> Got request:\n%s\n", buf);

        http_getPath(buf, pathBuf, sizeof(pathBuf));

        http_request_t request = http_request_parse(buf);

        if (strcmp(request.uri, "/") == 0) {
            server_homepage(client);
        } else if (strcmp(request.uri, "/api/admins") == 0) {
			server_database(client);
		} else if (strcmp(request.uri, "/api/admins/") > 0) {
			server_database_id(client, &request);
		} else {
            error_massage(client, "404 - NOT FOUND!");
        }
		socket_free(client);
    }
    socket_free(server);
    lib_free();
    return 0;
}
Exemplo n.º 18
0
int connection_state_machine(server *srv, connection *con) {
	int done = 0, r;
#ifdef USE_OPENSSL
	server_socket *srv_sock = con->srv_socket;
#endif
        chunkqueue *dst_cq = con->request_content_queue;
	if (srv->srvconf.log_state_handling) {
		log_error_write(srv, __FILE__, __LINE__, "sds",
				"state at start",
				con->fd,
				connection_get_state(con->state));
	}

	while (done == 0) {
		size_t ostate = con->state;
		int b;

		switch (con->state) {
		case CON_STATE_REQUEST_START: /* transient */
			if (srv->srvconf.log_state_handling) {
				log_error_write(srv, __FILE__, __LINE__, "sds",
						"state for fd", con->fd, connection_get_state(con->state));
			}

			con->request_start = srv->cur_ts;
			con->read_idle_ts = srv->cur_ts;

			con->request_count++;
			con->loops_per_request = 0;

			connection_set_state(srv, con, CON_STATE_READ);

			/* patch con->conf.is_ssl if the connection is a ssl-socket already */

#ifdef USE_OPENSSL
			con->conf.is_ssl = srv_sock->is_ssl;
#endif

			break;
		case CON_STATE_REQUEST_END: /* transient */
			if (srv->srvconf.log_state_handling) {
				log_error_write(srv, __FILE__, __LINE__, "sds",
						"state for fd", con->fd, connection_get_state(con->state));
			}

			if (http_request_parse(srv, con)) {
				/* we have to read some data from the POST request */

				connection_set_state(srv, con, CON_STATE_READ_POST);

				break;
			}

			connection_set_state(srv, con, CON_STATE_HANDLE_REQUEST);

			break;
		case CON_STATE_HANDLE_REQUEST:
			/*
			 * the request is parsed
			 *
			 * decided what to do with the request
			 * -
			 *
			 *
			 */

			if (srv->srvconf.log_state_handling) {
				log_error_write(srv, __FILE__, __LINE__, "sds",
						"state for fd", con->fd, connection_get_state(con->state));
			}

			switch (r = http_response_prepare(srv, con)) {
			case HANDLER_FINISHED:
				if (con->mode == DIRECT) {
					if (con->http_status == 404 ||
					    con->http_status == 403) {
						/* 404 error-handler */

						if (con->in_error_handler == 0 &&
						    (!buffer_is_empty(con->conf.error_handler) ||
						     !buffer_is_empty(con->error_handler))) {
							/* call error-handler */

							con->error_handler_saved_status = con->http_status;
							//log_error_write(srv, __FILE__, __LINE__, "s", "http_status set to 0");
							con->http_status = 0;

							if (buffer_is_empty(con->error_handler)) {
								buffer_copy_string_buffer(con->request.uri, con->conf.error_handler);
							} else {
								buffer_copy_string_buffer(con->request.uri, con->error_handler);
							}
							buffer_reset(con->physical.path);

							con->in_error_handler = 1;

							connection_set_state(srv, con, CON_STATE_HANDLE_REQUEST);

							done = -1;
							break;
						} else if (con->in_error_handler) {
							/* error-handler is a 404 */

							con->http_status = con->error_handler_saved_status;
						}
					} else if (con->in_error_handler) {
						/* error-handler is back and has generated content */
						/* if Status: was set, take it otherwise use 200 */
					}
				}
				if (con->http_status == 0) con->http_status = 200;

				/* we have something to send, go on */
				connection_set_state(srv, con, CON_STATE_RESPONSE_START);
				break;
			case HANDLER_WAIT_FOR_FD:
				srv->want_fds++;

				fdwaitqueue_append(srv, con);

				connection_set_state(srv, con, CON_STATE_READ_POST);

				break;
			case HANDLER_COMEBACK:
				done = -1;
			case HANDLER_WAIT_FOR_EVENT:
				/* come back here */
				connection_set_state(srv, con, CON_STATE_HANDLE_REQUEST);

				break;
			case HANDLER_ERROR:
				/* something went wrong */
				connection_set_state(srv, con, CON_STATE_ERROR);
				break;
			default:
				log_error_write(srv, __FILE__, __LINE__, "sdd", "unknown ret-value: ", con->fd, r);
				break;
			}

			break;
		case CON_STATE_RESPONSE_START:
			/*
			 * the decision is done
			 * - create the HTTP-Response-Header
			 *
			 */

			if (srv->srvconf.log_state_handling) {
				log_error_write(srv, __FILE__, __LINE__, "sds",
						"state for fd", con->fd, connection_get_state(con->state));
			}

			if (-1 == connection_handle_write_prepare(srv, con)) {
				connection_set_state(srv, con, CON_STATE_ERROR);

				break;
			}
			if (con->http_status = 416){
			  //log_error_write(srv, __FILE__, __LINE__, "s", "Resetting read_queue");
			  chunkqueue_reset(con->read_queue);

			}

			connection_set_state(srv, con, CON_STATE_WRITE);
			break;
		case CON_STATE_RESPONSE_END: /* transient */
			/* log the request */

			if (srv->srvconf.log_state_handling) {
				log_error_write(srv, __FILE__, __LINE__, "sds",
						"state for fd", con->fd, connection_get_state(con->state));
			}

			plugins_call_handle_request_done(srv, con);

			srv->con_written++;

			if (con->keep_alive) {
				connection_set_state(srv, con, CON_STATE_REQUEST_START);

#if 0
				con->request_start = srv->cur_ts;
				con->read_idle_ts = srv->cur_ts;
#endif
			} else {
				switch(r = plugins_call_handle_connection_close(srv, con)) {
				case HANDLER_GO_ON:
				case HANDLER_FINISHED:
					break;
				default:
					log_error_write(srv, __FILE__, __LINE__, "sd", "unhandling return value", r);
					break;
				}

#ifdef USE_OPENSSL
				if (srv_sock->is_ssl) {
					switch (SSL_shutdown(con->ssl)) {
					case 1:
						/* done */
						break;
					case 0:
						/* wait for fd-event
						 *
						 * FIXME: wait for fdevent and call SSL_shutdown again
						 *
						 */

						break;
					default:
						log_error_write(srv, __FILE__, __LINE__, "ss", "SSL:",
								ERR_error_string(ERR_get_error(), NULL));
					}
				}
#endif
				connection_close(srv, con);

				srv->con_closed++;
			}

			connection_reset(srv, con);

			break;
		case CON_STATE_CONNECT:
			if (srv->srvconf.log_state_handling) {
				log_error_write(srv, __FILE__, __LINE__, "sds",
						"state for fd", con->fd, connection_get_state(con->state));
			}

			/*
			if (con->read_queue != NULL) {
			  chunk *c;
			  size_t avail = 0;
			  for (c= con->read_queue->first; c != NULL; c = c->next) {
			    if(c->type == MEM_CHUNK)
			      avail += c->mem->used - c->offset -1;
			  }
			  log_error_write(srv, __FILE__, __LINE__, "sd", "con->read_queue is not empty!", avail);
			}*/
			chunkqueue_reset(con->read_queue);

			con->request_count = 0;

			break;
		case CON_STATE_CLOSE:
		  //log_error_write(srv, __FILE__, __LINE__, "so", "con->range_offset", con->range_offset);
		  //log_error_write(srv, __FILE__, __LINE__, "sdsd", "CON_STATE_ERROR: Bytes in", dst_cq->bytes_in, "Bytes out", dst_cq->bytes_out);
               		  /* Flush out any data that is currently sitting in the chunqueue */
		          if ((dst_cq->bytes_in - dst_cq->bytes_out) > 0) {
			            log_error_write(srv, __FILE__, __LINE__, "sd", "Flush data, handle remaining chunks", dst_cq->bytes_in);
				    connection_set_state(srv, con, CON_STATE_HANDLE_REQUEST);
				    break;
			  }

			if (srv->srvconf.log_state_handling) {
				log_error_write(srv, __FILE__, __LINE__, "sds",
						"state for fd", con->fd, connection_get_state(con->state));
			}

			if (con->keep_alive) {
				if (ioctl(con->fd, FIONREAD, &b)) {
					log_error_write(srv, __FILE__, __LINE__, "ss",
							"ioctl() failed", strerror(errno));
				}
				if (b > 0) {
					char buf[1024];
					log_error_write(srv, __FILE__, __LINE__, "sdd",
							"CLOSE-read()", con->fd, b);

					/* */
					read(con->fd, buf, sizeof(buf));
				} else {
					/* nothing to read */

					con->close_timeout_ts = 0;
				}
			} else {
				con->close_timeout_ts = 0;
			}

			if (srv->cur_ts - con->close_timeout_ts > 1) {
				connection_close(srv, con);
				log_error_write(srv, __FILE__, __LINE__, "so", "con->range_offset", con->range_offset);
				log_error_write(srv, __FILE__, __LINE__, "sdsd", "CON_STATE_ERROR: Bytes in", dst_cq->bytes_in, "Bytes out", dst_cq->bytes_out);
				/* Flush out any data that is currently sitting in the chunqueue */
				if ((dst_cq->bytes_in - dst_cq->bytes_out) > 0) {
				      log_error_write(srv, __FILE__, __LINE__, "sd", "Flush data, handle remaining chunks", dst_cq->bytes_in);
				      connection_set_state(srv, con, CON_STATE_HANDLE_REQUEST);
				      break;
				}

				if (srv->srvconf.log_state_handling) {
					log_error_write(srv, __FILE__, __LINE__, "sd",
							"connection closed for fd", con->fd);
				}
			}

			break;
		case CON_STATE_READ_POST:
		case CON_STATE_READ:
			if (srv->srvconf.log_state_handling) {
				log_error_write(srv, __FILE__, __LINE__, "sds",
						"state for fd", con->fd, connection_get_state(con->state));
			}

			connection_handle_read_state(srv, con);
			break;
		case CON_STATE_WRITE:
			if (srv->srvconf.log_state_handling) {
				log_error_write(srv, __FILE__, __LINE__, "sds",
						"state for fd", con->fd, connection_get_state(con->state));
			}

			/* only try to write if we have something in the queue */
			if (!chunkqueue_is_empty(con->write_queue)) {
#if 0
				log_error_write(srv, __FILE__, __LINE__, "dsd",
						con->fd,
						"packets to write:",
						con->write_queue->used);
#endif
			}
			if (!chunkqueue_is_empty(con->write_queue) && con->is_writable) {
				if (-1 == connection_handle_write(srv, con)) {
					log_error_write(srv, __FILE__, __LINE__, "ds",
							con->fd,
							"handle write failed.");
					connection_set_state(srv, con, CON_STATE_ERROR);
				} else if (con->state == CON_STATE_WRITE) {
					con->write_request_ts = srv->cur_ts;
				}
			}

			break;
		case CON_STATE_ERROR: /* transient */
		  //log_error_write(srv, __FILE__, __LINE__, "so", "con->range_offset", con->range_offset);
		  //log_error_write(srv, __FILE__, __LINE__, "sdsd", "CON_STATE_ERROR: Bytes in", dst_cq->bytes_in, "Bytes out", dst_cq->bytes_out);
               		  /* Flush out any data that is currently sitting in the chunqueue */
		          if ((dst_cq->bytes_in - dst_cq->bytes_out) > 0) {
			            log_error_write(srv, __FILE__, __LINE__, "sd", "Flush data, handle remaining chunks", dst_cq->bytes_in);
				    connection_set_state(srv, con, CON_STATE_HANDLE_REQUEST);
				    break;
			  }

			/* even if the connection was drop we still have to write it to the access log */
			if (con->http_status) {
				plugins_call_handle_request_done(srv, con);
			}
#ifdef USE_OPENSSL
			if (srv_sock->is_ssl) {
				int ret, ssl_r;
				unsigned long err;
				ERR_clear_error();
				switch ((ret = SSL_shutdown(con->ssl))) {
				case 1:
					/* ok */
					break;
				case 0:
					ERR_clear_error();
					if (-1 != (ret = SSL_shutdown(con->ssl))) break;

					/* fall through */
				default:

					switch ((ssl_r = SSL_get_error(con->ssl, ret))) {
					case SSL_ERROR_WANT_WRITE:
					case SSL_ERROR_WANT_READ:
						break;
					case SSL_ERROR_SYSCALL:
						/* perhaps we have error waiting in our error-queue */
						if (0 != (err = ERR_get_error())) {
							do {
								log_error_write(srv, __FILE__, __LINE__, "sdds", "SSL:",
										ssl_r, ret,
										ERR_error_string(err, NULL));
							} while((err = ERR_get_error()));
						} else {
							log_error_write(srv, __FILE__, __LINE__, "sddds", "SSL (error):",
									ssl_r, ret, errno,
									strerror(errno));
						}

						break;
					default:
						while((err = ERR_get_error())) {
							log_error_write(srv, __FILE__, __LINE__, "sdds", "SSL:",
									ssl_r, ret,
									ERR_error_string(err, NULL));
						}

						break;
					}
				}
			}
			ERR_clear_error();
#endif

			switch(con->mode) {
			case DIRECT:
#if 0
				log_error_write(srv, __FILE__, __LINE__, "sd",
						"emergency exit: direct",
						con->fd);
#endif
				break;
			default:
				switch(r = plugins_call_handle_connection_close(srv, con)) {
				case HANDLER_GO_ON:
				case HANDLER_FINISHED:
					break;
				default:
					log_error_write(srv, __FILE__, __LINE__, "");
					break;
				}
				break;
			}

			connection_reset(srv, con);

			/* close the connection */
			if ((con->keep_alive == 1) &&
			    (0 == shutdown(con->fd, SHUT_WR))) {
				con->close_timeout_ts = srv->cur_ts;
				connection_set_state(srv, con, CON_STATE_CLOSE);

				if (srv->srvconf.log_state_handling) {
					log_error_write(srv, __FILE__, __LINE__, "sd",
							"shutdown for fd", con->fd);
				}
			} else {
				connection_close(srv, con);
			}

			con->keep_alive = 0;

			srv->con_closed++;

			break;
		default:
			log_error_write(srv, __FILE__, __LINE__, "sdd",
					"unknown state:", con->fd, con->state);

			break;
		}

		if (done == -1) {
			done = 0;
		} else if (ostate == con->state) {
			done = 1;
		}
	}

	if (srv->srvconf.log_state_handling) {
		log_error_write(srv, __FILE__, __LINE__, "sds",
				"state at exit:",
				con->fd,
				connection_get_state(con->state));
	}

	switch(con->state) {
	case CON_STATE_READ_POST:
	case CON_STATE_READ:
	case CON_STATE_CLOSE:
		fdevent_event_add(srv->ev, &(con->fde_ndx), con->fd, FDEVENT_IN);
		break;
	case CON_STATE_WRITE:
		/* request write-fdevent only if we really need it
		 * - if we have data to write
		 * - if the socket is not writable yet
		 */
		if (!chunkqueue_is_empty(con->write_queue) &&
		    (con->is_writable == 0) &&
		    (con->traffic_limit_reached == 0)) {
			fdevent_event_add(srv->ev, &(con->fde_ndx), con->fd, FDEVENT_OUT);
		} else {
			fdevent_event_del(srv->ev, &(con->fde_ndx), con->fd);
		}
		break;
	default:
		fdevent_event_del(srv->ev, &(con->fde_ndx), con->fd);
		break;
	}

	return 0;
}
Exemplo n.º 19
0
int main()
{
    lib_init();
    printf("PORT: %i\n\n", PORT);
    socket_t * server = socket_new();
    socket_bind(server, PORT);
    socket_listen(server);

    char buffer[10000];
    socket_t * client = NULL;

    // работа с базой данных
    const char * dbFile = "ScrumMaster.db";
    db_t * db = db_new(dbFile);
    // работа с базой данных

    while(1)
    {
        client = socket_accept(server);
        socket_read(client, buffer, sizeof(buffer));

        if(strlen(buffer) != 0)
        {
            printf(">> Got request:\n%s\n", buffer);
            http_request_t request = http_request_parse(buffer);

            if (strcmp(request.uri, "/") == 0)
            {
                server_homepage(client);
            }
            else if (strcmp(request.uri, "/api/ScrumMasters") == 0)  // else if (strncmp(request.uri, "/api/ScrumMasters?", 18) == 0)
            {
                server_masters(client, &request, db);
            }
            else if (strncmp(request.uri, "/api/ScrumMasters/", 18) == 0)
            {
                server_mastersByID(client, &request, db);
            }
            else if (strcmp(request.uri, "/ScrumMasters") == 0)
            {
                server_mastersHtml(client, &request, db);
            }
            else if (strncmp(request.uri, "/ScrumMasters/", 14) == 0)
            {
                server_mastersHtmlByID(client, &request, db);
            }
            else if (strcmp(request.uri, "/new-ScrumMaster") == 0)
            {
                server_mastersHtmlPOST(client, &request, db);
            }
            else
            {
                server_notFound(client);
            }
        }
    }

    db_free(db);
    socket_free(client);
    socket_free(server);
    lib_free();
    return 0;
}
Exemplo n.º 20
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;
}
Exemplo n.º 21
0
Arquivo: http.c Projeto: azzurra/apm
static void http_check(void) {

	http_struct *conn;

#if defined(HAVE_SYS_POLL_H) && !defined(FORCE_SELECT)
	static struct pollfd ufds[EVENT_CHUNK];
	unsigned long size, i;
#else /* select() */
	fd_set w_fdset;
	fd_set r_fdset;
	struct timeval http_timeout;
	int highfd = 0;
#endif /* HAVE_SYS_POLL_H */

#if defined(HAVE_SYS_POLL_H) && !defined(FORCE_SELECT)

	size = i = 0;

	/* Get size of list we're interested in. */
	for (conn = HTTPREQUESTS; conn; conn = conn->next) {

		if ((conn->state == STATE_ESTABLISHED) || (conn->state == STATE_SENT))
			++size;
	}

	/* Setup each element now. */
	for (conn = HTTPREQUESTS; conn; conn = conn->next) {

		if ((conn->state != STATE_ESTABLISHED) && (conn->state != STATE_SENT))
			continue;

		ufds[i].events = 0;
		ufds[i].revents = 0;
		ufds[i].fd = conn->fd;

		/* Check for HUNG UP. */
		ufds[i].events |= POLLHUP;

		/* Check for INVALID FD */
		ufds[i].events |= POLLNVAL;

		switch (conn->state) {

			case STATE_ESTABLISHED:
				/* Check for NO BLOCK ON WRITE. */
				ufds[i].events |= POLLOUT;
				break;

			case STATE_SENT:
				/* Check for data to be read. */
				ufds[i].events |= POLLIN;
				break;
		}

		if (++i >= EVENT_CHUNK)
			break;
	}

#else /* select() */
	FD_ZERO(&w_fdset);
	FD_ZERO(&r_fdset);

	/* Add connections to appropriate sets. */

	for (conn = HTTPREQUESTS; conn; conn = conn->next) {

		if (conn->state == STATE_ESTABLISHED) {

			if (conn->fd > highfd)
				highfd = conn->fd;

			FD_SET(conn->fd, &w_fdset);
		}
		else if (conn->state == STATE_SENT) {

			if (conn->fd > highfd)
				highfd = conn->fd;

			FD_SET(conn->fd, &r_fdset);
		}
	}

	/* No timeout. */
	http_timeout.tv_sec = 0;
	http_timeout.tv_usec= 0;

#endif /* HAVE_SYS_POLL_H */

#if defined(HAVE_SYS_POLL_H) && !defined(FORCE_SELECT)
	switch (poll(ufds, size, 0)) {
#else /* select() */
	switch (select((highfd + 1), &r_fdset, &w_fdset, 0, &http_timeout)) {
#endif /* HAVE_SYS_POLL_H */

		case -1:	/* Error in select/poll. */
		case 0:		/* Nothing to do. */
			return;

		default:
			/* Pass pointer to connection to handler. */

#if defined(HAVE_SYS_POLL_H) && !defined(FORCE_SELECT)

			for (conn = HTTPREQUESTS; conn; conn = conn->next) {

				for (i = 0; i < size; ++i) {

					if ((ufds[i].fd == conn->fd) && (conn->state != STATE_CLOSED) && (conn->state != STATE_POSITIVE)) {

						if (ufds[i].revents & POLLIN)
							http_readready(conn);

						if (ufds[i].revents & POLLOUT)
							http_writeready(conn);

						if (ufds[i].revents & POLLHUP) {

							/* Negotiation failed (read returned false). Discard the connection as a closed proxy. */

							log_event(6, "HTTP -> [Socket %d] Negotiation failed on %s for IP %s [Read: %s]",
								conn->fd, conn->zone->name, conn->ip, (conn->bytes_read > 0) ? ascii2char(conn->response, conn->bytes_read) : "Nothing");

							conn->state = STATE_CLOSED;
						}

						break;
					}
				}
			}
#else

			for (conn = HTTPREQUESTS; conn; conn = conn->next) {

				if (conn->state == STATE_ESTABLISHED) {

					if (FD_ISSET(conn->fd, &w_fdset))
						http_writeready(conn);
				}
				else if (conn->state == STATE_SENT) {

					if (FD_ISSET(conn->fd, &r_fdset))
						http_readready(conn);
				}
			}
#endif /* HAVE_SYS_POLL_H */
	}
}


/*********************************************************
 * Poll or select returned back that this connection is  *
 * ready for read. Get the data, and pass it to the      *
 * protocol check handler.                               *
 *********************************************************/

static void http_readready(http_struct *conn) {

	int len;

	memset(conn->response, 0, sizeof(conn->response));
	conn->bytes_read = 0;

	len = recv(conn->fd, conn->response, sizeof(conn->response), MSG_WAITALL);

	switch (len) {

		case -1:	/* Error, or socket was closed. */
		case 0:		/* No data read from socket. */
			return;

		default:
			if (len >= sizeof(conn->response)) {

				char dump[1024];

				log_event(6, "HTTP -> [Socket %d] Read more than %d bytes, discarding the rest", conn->fd, sizeof(conn->response));

				/* Get rid of whatever was left on the socket. */
				while (recv(conn->fd, dump, sizeof(dump), MSG_WAITALL) > 0)
					;
			}

			conn->bytes_read = len;

			log_event(6, "HTTP -> [Socket %d] Reading data from %s for IP %s: %s",
				conn->fd, conn->zone->name, conn->ip, ascii2char(conn->response, conn->bytes_read));

			http_request_parse(conn);

			conn->state = STATE_CLOSED;
			return;
	}
}
Exemplo n.º 22
0
connection *connection_accept(server *srv, server_socket *srv_socket) {
	/* accept everything */

	/* search an empty place */
	int cnt;
	sock_addr cnt_addr;
#ifndef HAVE_LIBMTCP
	socklen_t cnt_len;
#endif
	/* accept it and register the fd */

	/**
	 * check if we can still open a new connections
	 *
	 * see #1216
	 */

	if (srv->conns->used >= srv->max_conns) {
		return NULL;
	}

#ifdef HAVE_LIBMTCP
	if (-1 == (cnt = mtcp_accept(srv->mctx, srv_socket->fd, NULL, NULL))) {
#else
	cnt_len = sizeof(cnt_addr);
	if (-1 == (cnt = accept(srv_socket->fd, (struct sockaddr *) &cnt_addr, &cnt_len))) {
#endif
		switch (errno) {
		case EAGAIN:
#if EWOULDBLOCK != EAGAIN
		case EWOULDBLOCK:
#endif
		case EINTR:
			/* we were stopped _before_ we had a connection */
		case ECONNABORTED: /* this is a FreeBSD thingy */
			/* we were stopped _after_ we had a connection */
			break;
		case EMFILE:
			/* out of fds */
			break;
		default:
			log_error_write(srv, __FILE__, __LINE__, "ssd", "accept failed:", strerror(errno), errno);
		}
		return NULL;
	} else {
		connection *con;

		srv->cur_fds++;

		/* ok, we have the connection, register it */
#if 0
		log_error_write(srv, __FILE__, __LINE__, "sd",
				"appected()", cnt);
#endif
		srv->con_opened++;

		con = connections_get_new_connection(srv);

		con->fd = cnt;
		con->fde_ndx = -1;
#if 0
		gettimeofday(&(con->start_tv), NULL);
#endif
		fdevent_register(srv->ev, con->fd, connection_handle_fdevent, con);

		connection_set_state(srv, con, CON_STATE_REQUEST_START);

		con->connection_start = srv->cur_ts;
		con->dst_addr = cnt_addr;
		buffer_copy_string(con->dst_addr_buf, inet_ntop_cache_get_ip(srv, &(con->dst_addr)));
		con->srv_socket = srv_socket;

		if (-1 == (fdevent_fcntl_set(srv->ev, con->fd))) {
			log_error_write(srv, __FILE__, __LINE__, "ss", "fcntl failed: ", strerror(errno));
			return NULL;
		}
#ifdef USE_OPENSSL
		/* connect FD to SSL */
		if (srv_socket->is_ssl) {
			if (NULL == (con->ssl = SSL_new(srv_socket->ssl_ctx))) {
				log_error_write(srv, __FILE__, __LINE__, "ss", "SSL:",
						ERR_error_string(ERR_get_error(), NULL));

				return NULL;
			}

			con->renegotiations = 0;
			SSL_set_app_data(con->ssl, con);
			SSL_set_accept_state(con->ssl);
			con->conf.is_ssl=1;

			if (1 != (SSL_set_fd(con->ssl, cnt))) {
				log_error_write(srv, __FILE__, __LINE__, "ss", "SSL:",
						ERR_error_string(ERR_get_error(), NULL));
				return NULL;
			}
		}
#endif
		return con;
	}
}


int connection_state_machine(server *srv, connection *con) {
	int done = 0, r;
#ifdef USE_OPENSSL
	server_socket *srv_sock = con->srv_socket;
#endif

	if (srv->srvconf.log_state_handling) {
		log_error_write(srv, __FILE__, __LINE__, "sds",
				"state at start",
				con->fd,
				connection_get_state(con->state));
	}

	while (done == 0) {
		size_t ostate = con->state;

		switch (con->state) {
		case CON_STATE_REQUEST_START: /* transient */
			if (srv->srvconf.log_state_handling) {
				log_error_write(srv, __FILE__, __LINE__, "sds",
						"state for fd", con->fd, connection_get_state(con->state));
			}

			con->request_start = srv->cur_ts;
			con->read_idle_ts = srv->cur_ts;

			con->request_count++;
			con->loops_per_request = 0;

			connection_set_state(srv, con, CON_STATE_READ);

			/* patch con->conf.is_ssl if the connection is a ssl-socket already */

#ifdef USE_OPENSSL
			con->conf.is_ssl = srv_sock->is_ssl;
#endif

			break;
		case CON_STATE_REQUEST_END: /* transient */
			if (srv->srvconf.log_state_handling) {
				log_error_write(srv, __FILE__, __LINE__, "sds",
						"state for fd", con->fd, connection_get_state(con->state));
			}

			buffer_reset(con->uri.authority);
			buffer_reset(con->uri.path);
			buffer_reset(con->uri.query);
			buffer_reset(con->request.orig_uri);

			if (http_request_parse(srv, con)) {
				/* we have to read some data from the POST request */

				connection_set_state(srv, con, CON_STATE_READ_POST);

				break;
			}

			connection_set_state(srv, con, CON_STATE_HANDLE_REQUEST);

			break;
		case CON_STATE_HANDLE_REQUEST:
			/*
			 * the request is parsed
			 *
			 * decided what to do with the request
			 * -
			 *
			 *
			 */

			if (srv->srvconf.log_state_handling) {
				log_error_write(srv, __FILE__, __LINE__, "sds",
						"state for fd", con->fd, connection_get_state(con->state));
			}

			switch (r = http_response_prepare(srv, con)) {
			case HANDLER_FINISHED:
				if (con->mode == DIRECT) {
					if (con->http_status == 404 ||
					    con->http_status == 403) {
						/* 404 error-handler */

						if (con->in_error_handler == 0 &&
						    (!buffer_is_empty(con->conf.error_handler) ||
						     !buffer_is_empty(con->error_handler))) {
							/* call error-handler */

							con->error_handler_saved_status = con->http_status;
							con->http_status = 0;

							if (buffer_is_empty(con->error_handler)) {
								buffer_copy_string_buffer(con->request.uri, con->conf.error_handler);
							} else {
								buffer_copy_string_buffer(con->request.uri, con->error_handler);
							}
							buffer_reset(con->physical.path);

							con->in_error_handler = 1;

							connection_set_state(srv, con, CON_STATE_HANDLE_REQUEST);

							done = -1;
							break;
						} else if (con->in_error_handler) {
							/* error-handler is a 404 */

							con->http_status = con->error_handler_saved_status;
						}
					} else if (con->in_error_handler) {
						/* error-handler is back and has generated content */
						/* if Status: was set, take it otherwise use 200 */
					}
				}
				if (con->http_status == 0) con->http_status = 200;

				/* we have something to send, go on */
				connection_set_state(srv, con, CON_STATE_RESPONSE_START);
				break;
			case HANDLER_WAIT_FOR_FD:
				srv->want_fds++;

				fdwaitqueue_append(srv, con);

				connection_set_state(srv, con, CON_STATE_HANDLE_REQUEST);

				break;
			case HANDLER_COMEBACK:
				done = -1;
			case HANDLER_WAIT_FOR_EVENT:
				/* come back here */
				connection_set_state(srv, con, CON_STATE_HANDLE_REQUEST);

				break;
			case HANDLER_ERROR:
				/* something went wrong */
				connection_set_state(srv, con, CON_STATE_ERROR);
				break;
			default:
				log_error_write(srv, __FILE__, __LINE__, "sdd", "unknown ret-value: ", con->fd, r);
				break;
			}

			break;
		case CON_STATE_RESPONSE_START:
			/*
			 * the decision is done
			 * - create the HTTP-Response-Header
			 *
			 */

			if (srv->srvconf.log_state_handling) {
				log_error_write(srv, __FILE__, __LINE__, "sds",
						"state for fd", con->fd, connection_get_state(con->state));
			}

			if (-1 == connection_handle_write_prepare(srv, con)) {
				connection_set_state(srv, con, CON_STATE_ERROR);

				break;
			}

			connection_set_state(srv, con, CON_STATE_WRITE);
			break;
		case CON_STATE_RESPONSE_END: /* transient */
			/* log the request */

			if (srv->srvconf.log_state_handling) {
				log_error_write(srv, __FILE__, __LINE__, "sds",
						"state for fd", con->fd, connection_get_state(con->state));
			}

			plugins_call_handle_request_done(srv, con);

			srv->con_written++;

			if (con->keep_alive) {
				connection_set_state(srv, con, CON_STATE_REQUEST_START);

#if 0
				con->request_start = srv->cur_ts;
				con->read_idle_ts = srv->cur_ts;
#endif
			} else {
				switch(r = plugins_call_handle_connection_close(srv, con)) {
				case HANDLER_GO_ON:
				case HANDLER_FINISHED:
					break;
				default:
					log_error_write(srv, __FILE__, __LINE__, "sd", "unhandling return value", r);
					break;
				}

#ifdef USE_OPENSSL
				if (srv_sock->is_ssl) {
					switch (SSL_shutdown(con->ssl)) {
					case 1:
						/* done */
						break;
					case 0:
						/* wait for fd-event
						 *
						 * FIXME: wait for fdevent and call SSL_shutdown again
						 *
						 */

						break;
					default:
						log_error_write(srv, __FILE__, __LINE__, "ss", "SSL:",
								ERR_error_string(ERR_get_error(), NULL));
					}
				}
#endif
				if ((0 == shutdown(con->fd, SHUT_WR))) {
					con->close_timeout_ts = srv->cur_ts;
					connection_set_state(srv, con, CON_STATE_CLOSE);
				} else {
					connection_close(srv, con);
				}

				srv->con_closed++;
			}

			connection_reset(srv, con);

			break;
		case CON_STATE_CONNECT:
			if (srv->srvconf.log_state_handling) {
				log_error_write(srv, __FILE__, __LINE__, "sds",
						"state for fd", con->fd, connection_get_state(con->state));
			}

			chunkqueue_reset(con->read_queue);

			con->request_count = 0;

			break;
		case CON_STATE_CLOSE:
			if (srv->srvconf.log_state_handling) {
				log_error_write(srv, __FILE__, __LINE__, "sds",
						"state for fd", con->fd, connection_get_state(con->state));
			}

			/* we have to do the linger_on_close stuff regardless
			 * of con->keep_alive; even non-keepalive sockets may
			 * still have unread data, and closing before reading
			 * it will make the client not see all our output.
			 */
			{
				int len;
				char buf[1024];
#ifdef HAVE_LIBMTCP
				len = mtcp_read(srv->mctx, con->fd, buf, sizeof(buf));
#else
				len = read(con->fd, buf, sizeof(buf));
#endif
				if (len == 0 || (len < 0 && errno != EAGAIN && errno != EINTR) ) {
					con->close_timeout_ts = srv->cur_ts - (HTTP_LINGER_TIMEOUT+1);
				}
			}

			if (srv->cur_ts - con->close_timeout_ts > HTTP_LINGER_TIMEOUT) {
				connection_close(srv, con);

				if (srv->srvconf.log_state_handling) {
					log_error_write(srv, __FILE__, __LINE__, "sd",
							"connection closed for fd", con->fd);
				}
			}

			break;
		case CON_STATE_READ_POST:
		case CON_STATE_READ:
			if (srv->srvconf.log_state_handling) {
				log_error_write(srv, __FILE__, __LINE__, "sds",
						"state for fd", con->fd, connection_get_state(con->state));
			}

			connection_handle_read_state(srv, con);
			break;
		case CON_STATE_WRITE:
			if (srv->srvconf.log_state_handling) {
				log_error_write(srv, __FILE__, __LINE__, "sds",
						"state for fd", con->fd, connection_get_state(con->state));
			}

			/* only try to write if we have something in the queue */
			if (!chunkqueue_is_empty(con->write_queue)) {
#if 0
				log_error_write(srv, __FILE__, __LINE__, "dsd",
						con->fd,
						"packets to write:",
						con->write_queue->used);
#endif
			}
			if (!chunkqueue_is_empty(con->write_queue) && con->is_writable) {
				if (-1 == connection_handle_write(srv, con)) {
					log_error_write(srv, __FILE__, __LINE__, "ds",
							con->fd,
							"handle write failed.");
					connection_set_state(srv, con, CON_STATE_ERROR);
				}
			}

			break;
		case CON_STATE_ERROR: /* transient */

			/* even if the connection was drop we still have to write it to the access log */
			if (con->http_status) {
				plugins_call_handle_request_done(srv, con);
			}
#ifdef USE_OPENSSL
			if (srv_sock->is_ssl) {
				int ret, ssl_r;
				unsigned long err;
				ERR_clear_error();
				switch ((ret = SSL_shutdown(con->ssl))) {
				case 1:
					/* ok */
					break;
				case 0:
					ERR_clear_error();
					if (-1 != (ret = SSL_shutdown(con->ssl))) break;

					/* fall through */
				default:

					switch ((ssl_r = SSL_get_error(con->ssl, ret))) {
					case SSL_ERROR_WANT_WRITE:
					case SSL_ERROR_WANT_READ:
						break;
					case SSL_ERROR_SYSCALL:
						/* perhaps we have error waiting in our error-queue */
						if (0 != (err = ERR_get_error())) {
							do {
								log_error_write(srv, __FILE__, __LINE__, "sdds", "SSL:",
										ssl_r, ret,
										ERR_error_string(err, NULL));
							} while((err = ERR_get_error()));
						} else if (errno != 0) { /* ssl bug (see lighttpd ticket #2213): sometimes errno == 0 */
							switch(errno) {
							case EPIPE:
							case ECONNRESET:
								break;
							default:
								log_error_write(srv, __FILE__, __LINE__, "sddds", "SSL (error):",
									ssl_r, ret, errno,
									strerror(errno));
								break;
							}
						}

						break;
					default:
						while((err = ERR_get_error())) {
							log_error_write(srv, __FILE__, __LINE__, "sdds", "SSL:",
									ssl_r, ret,
									ERR_error_string(err, NULL));
						}

						break;
					}
				}
			}
			ERR_clear_error();
#endif

			switch(con->mode) {
			case DIRECT:
#if 0
				log_error_write(srv, __FILE__, __LINE__, "sd",
						"emergency exit: direct",
						con->fd);
#endif
				break;
			default:
				switch(r = plugins_call_handle_connection_close(srv, con)) {
				case HANDLER_GO_ON:
				case HANDLER_FINISHED:
					break;
				default:
					log_error_write(srv, __FILE__, __LINE__, "sd", "unhandling return value", r);
					break;
				}
				break;
			}

			connection_reset(srv, con);

			/* close the connection */
			if ((0 == shutdown(con->fd, SHUT_WR))) {
				con->close_timeout_ts = srv->cur_ts;
				connection_set_state(srv, con, CON_STATE_CLOSE);

				if (srv->srvconf.log_state_handling) {
					log_error_write(srv, __FILE__, __LINE__, "sd",
							"shutdown for fd", con->fd);
				}
			} else {
				connection_close(srv, con);
			}

			con->keep_alive = 0;

			srv->con_closed++;

			break;
		default:
			log_error_write(srv, __FILE__, __LINE__, "sdd",
					"unknown state:", con->fd, con->state);

			break;
		}

		if (done == -1) {
			done = 0;
		} else if (ostate == con->state) {
			done = 1;
		}
	}

	if (srv->srvconf.log_state_handling) {
		log_error_write(srv, __FILE__, __LINE__, "sds",
				"state at exit:",
				con->fd,
				connection_get_state(con->state));
	}

	switch(con->state) {
	case CON_STATE_READ_POST:
	case CON_STATE_READ:
	case CON_STATE_CLOSE:
		fdevent_event_set(srv->ev, &(con->fde_ndx), con->fd, FDEVENT_IN);
		break;
	case CON_STATE_WRITE:
		/* request write-fdevent only if we really need it
		 * - if we have data to write
		 * - if the socket is not writable yet
		 */
		if (!chunkqueue_is_empty(con->write_queue) &&
		    (con->is_writable == 0) &&
		    (con->traffic_limit_reached == 0)) {
			fdevent_event_set(srv->ev, &(con->fde_ndx), con->fd, FDEVENT_OUT);
		} else {
			fdevent_event_del(srv->ev, &(con->fde_ndx), con->fd);
		}
		break;
	default:
		fdevent_event_del(srv->ev, &(con->fde_ndx), con->fd);
		break;
	}

	return 0;
}
Exemplo n.º 23
0
int connection_state_machine(server *srv, connection *con) {
	int done = 0, r;

	if (srv->srvconf.log_state_handling) {
		log_error_write(srv, __FILE__, __LINE__, "sds",
				"state at start",
				con->fd,
				connection_get_state(con->state));
	}

	while (done == 0) {
		size_t ostate = con->state;

		if (srv->srvconf.log_state_handling) {
			log_error_write(srv, __FILE__, __LINE__, "sds",
					"state for fd", con->fd, connection_get_state(con->state));
		}

		switch (con->state) {
		case CON_STATE_REQUEST_START: /* transient */
			con->request_start = srv->cur_ts;
			con->read_idle_ts = srv->cur_ts;
			if (con->conf.high_precision_timestamps)
				log_clock_gettime_realtime(&con->request_start_hp);

			con->request_count++;
			con->loops_per_request = 0;

			connection_set_state(srv, con, CON_STATE_READ);

			break;
		case CON_STATE_REQUEST_END: /* transient */
			buffer_reset(con->uri.authority);
			buffer_reset(con->uri.path);
			buffer_reset(con->uri.query);
			buffer_reset(con->request.orig_uri);

			if (http_request_parse(srv, con)) {
				/* we have to read some data from the POST request */

				connection_set_state(srv, con, CON_STATE_READ_POST);

				break;
			}

			connection_set_state(srv, con, CON_STATE_HANDLE_REQUEST);

			break;
		case CON_STATE_READ_POST:
		case CON_STATE_HANDLE_REQUEST:
			/*
			 * the request is parsed
			 *
			 * decided what to do with the request
			 * -
			 *
			 *
			 */

			switch (r = http_response_prepare(srv, con)) {
			case HANDLER_WAIT_FOR_EVENT:
				if (!con->file_finished && (!con->file_started || 0 == con->conf.stream_response_body)) {
					break; /* come back here */
				}
				/* response headers received from backend; fall through to start response */
			case HANDLER_FINISHED:
				if (con->error_handler_saved_status > 0) {
					con->request.http_method = con->error_handler_saved_method;
				}
				if (con->mode == DIRECT) {
					if (con->error_handler_saved_status) {
						if (con->error_handler_saved_status > 0) {
							con->http_status = con->error_handler_saved_status;
						} else if (con->http_status == 404 || con->http_status == 403) {
							/* error-handler-404 is a 404 */
							con->http_status = -con->error_handler_saved_status;
						} else {
							/* error-handler-404 is back and has generated content */
							/* if Status: was set, take it otherwise use 200 */
						}
					} else if (con->http_status >= 400) {
						buffer *error_handler = NULL;
						if (!buffer_string_is_empty(con->conf.error_handler)) {
							error_handler = con->conf.error_handler;
						} else if ((con->http_status == 404 || con->http_status == 403)
							   && !buffer_string_is_empty(con->conf.error_handler_404)) {
							error_handler = con->conf.error_handler_404;
						}

						if (error_handler) {
							/* call error-handler */

							/* set REDIRECT_STATUS to save current HTTP status code
							 * for access by dynamic handlers
							 * https://redmine.lighttpd.net/issues/1828 */
							data_string *ds;
							if (NULL == (ds = (data_string *)array_get_unused_element(con->environment, TYPE_STRING))) {
								ds = data_string_init();
							}
							buffer_copy_string_len(ds->key, CONST_STR_LEN("REDIRECT_STATUS"));
							buffer_append_int(ds->value, con->http_status);
							array_insert_unique(con->environment, (data_unset *)ds);

							if (error_handler == con->conf.error_handler) {
								plugins_call_connection_reset(srv, con);

								if (con->request.content_length) {
									if (con->request.content_length != con->request_content_queue->bytes_in) {
										con->keep_alive = 0;
									}
									con->request.content_length = 0;
									chunkqueue_reset(con->request_content_queue);
								}

								con->is_writable = 1;
								con->file_finished = 0;
								con->file_started = 0;
								con->got_response = 0;
								con->parsed_response = 0;
								con->response.keep_alive = 0;
								con->response.content_length = -1;
								con->response.transfer_encoding = 0;

								con->error_handler_saved_status = con->http_status;
								con->error_handler_saved_method = con->request.http_method;

								con->request.http_method = HTTP_METHOD_GET;
							} else { /*(preserve behavior for server.error-handler-404)*/
								con->error_handler_saved_status = -con->http_status; /*(negative to flag old behavior)*/
							}

							buffer_copy_buffer(con->request.uri, error_handler);
							connection_handle_errdoc_init(srv, con);
							con->http_status = 0; /*(after connection_handle_errdoc_init())*/

							done = -1;
							break;
						}
					}
				}
				if (con->http_status == 0) con->http_status = 200;

				/* we have something to send, go on */
				connection_set_state(srv, con, CON_STATE_RESPONSE_START);
				break;
			case HANDLER_WAIT_FOR_FD:
				srv->want_fds++;

				fdwaitqueue_append(srv, con);

				break;
			case HANDLER_COMEBACK:
				done = -1;
				break;
			case HANDLER_ERROR:
				/* something went wrong */
				connection_set_state(srv, con, CON_STATE_ERROR);
				break;
			default:
				log_error_write(srv, __FILE__, __LINE__, "sdd", "unknown ret-value: ", con->fd, r);
				break;
			}

			if (con->state == CON_STATE_HANDLE_REQUEST && ostate == CON_STATE_READ_POST) {
				ostate = CON_STATE_HANDLE_REQUEST;
			}
			break;
		case CON_STATE_RESPONSE_START:
			/*
			 * the decision is done
			 * - create the HTTP-Response-Header
			 *
			 */

			if (-1 == connection_handle_write_prepare(srv, con)) {
				connection_set_state(srv, con, CON_STATE_ERROR);

				break;
			}

			connection_set_state(srv, con, CON_STATE_WRITE);
			break;
		case CON_STATE_RESPONSE_END: /* transient */
		case CON_STATE_ERROR:        /* transient */
			connection_handle_response_end_state(srv, con);
			break;
		case CON_STATE_CONNECT:
			chunkqueue_reset(con->read_queue);

			con->request_count = 0;

			break;
		case CON_STATE_CLOSE:
			connection_handle_close_state(srv, con);
			break;
		case CON_STATE_READ:
			connection_handle_read_state(srv, con);
			break;
		case CON_STATE_WRITE:
			do {
				/* only try to write if we have something in the queue */
				if (!chunkqueue_is_empty(con->write_queue)) {
					if (con->is_writable) {
						if (-1 == connection_handle_write(srv, con)) {
							log_error_write(srv, __FILE__, __LINE__, "ds",
									con->fd,
									"handle write failed.");
							connection_set_state(srv, con, CON_STATE_ERROR);
							break;
						}
						if (con->state != CON_STATE_WRITE) break;
					}
				} else if (con->file_finished) {
					connection_set_state(srv, con, CON_STATE_RESPONSE_END);
					break;
				}

				if (con->mode != DIRECT && !con->file_finished) {
					switch(r = plugins_call_handle_subrequest(srv, con)) {
					case HANDLER_WAIT_FOR_EVENT:
					case HANDLER_FINISHED:
					case HANDLER_GO_ON:
						break;
					case HANDLER_WAIT_FOR_FD:
						srv->want_fds++;
						fdwaitqueue_append(srv, con);
						break;
					case HANDLER_COMEBACK:
					default:
						log_error_write(srv, __FILE__, __LINE__, "sdd", "unexpected subrequest handler ret-value: ", con->fd, r);
						/* fall through */
					case HANDLER_ERROR:
						connection_set_state(srv, con, CON_STATE_ERROR);
						break;
					}
				}
			} while (con->state == CON_STATE_WRITE && (!chunkqueue_is_empty(con->write_queue) ? con->is_writable : con->file_finished));

			break;
		default:
			log_error_write(srv, __FILE__, __LINE__, "sdd",
					"unknown state:", con->fd, con->state);

			break;
		}

		if (done == -1) {
			done = 0;
		} else if (ostate == con->state) {
			done = 1;
		}
	}

	if (srv->srvconf.log_state_handling) {
		log_error_write(srv, __FILE__, __LINE__, "sds",
				"state at exit:",
				con->fd,
				connection_get_state(con->state));
	}

	r = 0;
	switch(con->state) {
	case CON_STATE_READ:
	case CON_STATE_CLOSE:
		r = FDEVENT_IN;
		break;
	case CON_STATE_WRITE:
		/* request write-fdevent only if we really need it
		 * - if we have data to write
		 * - if the socket is not writable yet
		 */
		if (!chunkqueue_is_empty(con->write_queue) &&
		    (con->is_writable == 0) &&
		    (con->traffic_limit_reached == 0)) {
			r |= FDEVENT_OUT;
		}
		/* fall through */
	case CON_STATE_READ_POST:
		if (con->conf.stream_request_body & FDEVENT_STREAM_REQUEST_POLLIN) {
			r |= FDEVENT_IN;
		}
		break;
	default:
		break;
	}
	if (-1 != con->fd) {
		const int events = fdevent_event_get_interest(srv->ev, con->fd);
		if (con->is_readable < 0) {
			con->is_readable = 0;
			r |= FDEVENT_IN;
		}
		if (con->is_writable < 0) {
			con->is_writable = 0;
			r |= FDEVENT_OUT;
		}
		if (r != events) {
			/* update timestamps when enabling interest in events */
			if ((r & FDEVENT_IN) && !(events & FDEVENT_IN)) {
				con->read_idle_ts = srv->cur_ts;
			}
			if ((r & FDEVENT_OUT) && !(events & FDEVENT_OUT)) {
				con->write_request_ts = srv->cur_ts;
			}
			fdevent_event_set(srv->ev, &con->fde_ndx, con->fd, r);
		}
	}

	return 0;
}
Exemplo n.º 24
0
int connection_state_machine(server *srv, connection *con) {
	int done = 0, r;
#ifdef USE_OPENSSL
	server_socket *srv_sock = con->srv_socket;
#endif

	if (srv->srvconf.log_state_handling) {
		log_error_write(srv, __FILE__, __LINE__, "sds",
				"state at start",
				con->fd,
				connection_get_state(con->state));
	}

	while (done == 0) {
		size_t ostate = con->state;

		switch (con->state) {
		case CON_STATE_REQUEST_START: /* transient */
			if (srv->srvconf.log_state_handling) {
				log_error_write(srv, __FILE__, __LINE__, "sds",
						"state for fd", con->fd, connection_get_state(con->state));
			}

			con->request_start = srv->cur_ts;
			con->read_idle_ts = srv->cur_ts;

			con->request_count++;
			con->loops_per_request = 0;

			connection_set_state(srv, con, CON_STATE_READ);

			break;
		case CON_STATE_REQUEST_END: /* transient */
			if (srv->srvconf.log_state_handling) {
				log_error_write(srv, __FILE__, __LINE__, "sds",
						"state for fd", con->fd, connection_get_state(con->state));
			}

			buffer_reset(con->uri.authority);
			buffer_reset(con->uri.path);
			buffer_reset(con->uri.query);
			buffer_reset(con->request.orig_uri);

			if (http_request_parse(srv, con)) {
				/* we have to read some data from the POST request */

				connection_set_state(srv, con, CON_STATE_READ_POST);

				break;
			}

			connection_set_state(srv, con, CON_STATE_HANDLE_REQUEST);

			break;
		case CON_STATE_HANDLE_REQUEST:
			/*
			 * the request is parsed
			 *
			 * decided what to do with the request
			 * -
			 *
			 *
			 */

			if (srv->srvconf.log_state_handling) {
				log_error_write(srv, __FILE__, __LINE__, "sds",
						"state for fd", con->fd, connection_get_state(con->state));
			}

			switch (r = http_response_prepare(srv, con)) {
			case HANDLER_FINISHED:
				if (con->mode == DIRECT) {
					if (con->http_status == 404 ||
					    con->http_status == 403) {
						/* 404 error-handler */

						if (con->in_error_handler == 0 &&
						    (!buffer_string_is_empty(con->conf.error_handler) ||
						     !buffer_string_is_empty(con->error_handler))) {
							/* call error-handler */

							con->error_handler_saved_status = con->http_status;
							con->http_status = 0;

							if (buffer_string_is_empty(con->error_handler)) {
								buffer_copy_buffer(con->request.uri, con->conf.error_handler);
							} else {
								buffer_copy_buffer(con->request.uri, con->error_handler);
							}
							buffer_reset(con->physical.path);

							con->in_error_handler = 1;

							connection_set_state(srv, con, CON_STATE_HANDLE_REQUEST);

							done = -1;
							break;
						} else if (con->in_error_handler) {
							/* error-handler is a 404 */

							con->http_status = con->error_handler_saved_status;
						}
					} else if (con->in_error_handler) {
						/* error-handler is back and has generated content */
						/* if Status: was set, take it otherwise use 200 */
					}
				}
				if (con->http_status == 0) con->http_status = 200;

				/* we have something to send, go on */
				connection_set_state(srv, con, CON_STATE_RESPONSE_START);
				break;
			case HANDLER_WAIT_FOR_FD:
				srv->want_fds++;

				fdwaitqueue_append(srv, con);

				connection_set_state(srv, con, CON_STATE_HANDLE_REQUEST);

				break;
			case HANDLER_COMEBACK:
				done = -1;
				/* fallthrough */
			case HANDLER_WAIT_FOR_EVENT:
				/* come back here */
				connection_set_state(srv, con, CON_STATE_HANDLE_REQUEST);

				break;
			case HANDLER_ERROR:
				/* something went wrong */
				connection_set_state(srv, con, CON_STATE_ERROR);
				break;
			default:
				log_error_write(srv, __FILE__, __LINE__, "sdd", "unknown ret-value: ", con->fd, r);
				break;
			}

			break;
		case CON_STATE_RESPONSE_START:
			/*
			 * the decision is done
			 * - create the HTTP-Response-Header
			 *
			 */

			if (srv->srvconf.log_state_handling) {
				log_error_write(srv, __FILE__, __LINE__, "sds",
						"state for fd", con->fd, connection_get_state(con->state));
			}

			if (-1 == connection_handle_write_prepare(srv, con)) {
				connection_set_state(srv, con, CON_STATE_ERROR);

				break;
			}

			connection_set_state(srv, con, CON_STATE_WRITE);
			break;
		case CON_STATE_RESPONSE_END: /* transient */
			/* log the request */

			if (srv->srvconf.log_state_handling) {
				log_error_write(srv, __FILE__, __LINE__, "sds",
						"state for fd", con->fd, connection_get_state(con->state));
			}

			plugins_call_handle_request_done(srv, con);

			srv->con_written++;

			if (con->keep_alive) {
				connection_set_state(srv, con, CON_STATE_REQUEST_START);

#if 0
				con->request_start = srv->cur_ts;
				con->read_idle_ts = srv->cur_ts;
#endif
			} else {
				switch(r = plugins_call_handle_connection_close(srv, con)) {
				case HANDLER_GO_ON:
				case HANDLER_FINISHED:
					break;
				default:
					log_error_write(srv, __FILE__, __LINE__, "sd", "unhandling return value", r);
					break;
				}

#ifdef USE_OPENSSL
				if (srv_sock->is_ssl) {
					switch (SSL_shutdown(con->ssl)) {
					case 1:
						/* done */
						break;
					case 0:
						/* wait for fd-event
						 *
						 * FIXME: wait for fdevent and call SSL_shutdown again
						 *
						 */

						break;
					default:
						log_error_write(srv, __FILE__, __LINE__, "ss", "SSL:",
								ERR_error_string(ERR_get_error(), NULL));
					}
				}
#endif
				if ((0 == shutdown(con->fd, SHUT_WR))) {
					con->close_timeout_ts = srv->cur_ts;
					connection_set_state(srv, con, CON_STATE_CLOSE);
				} else {
					connection_close(srv, con);
				}

				srv->con_closed++;
			}

			connection_reset(srv, con);

			break;
		case CON_STATE_CONNECT:
			if (srv->srvconf.log_state_handling) {
				log_error_write(srv, __FILE__, __LINE__, "sds",
						"state for fd", con->fd, connection_get_state(con->state));
			}

			chunkqueue_reset(con->read_queue);

			con->request_count = 0;

			break;
		case CON_STATE_CLOSE:
			if (srv->srvconf.log_state_handling) {
				log_error_write(srv, __FILE__, __LINE__, "sds",
						"state for fd", con->fd, connection_get_state(con->state));
			}

			/* we have to do the linger_on_close stuff regardless
			 * of con->keep_alive; even non-keepalive sockets may
			 * still have unread data, and closing before reading
			 * it will make the client not see all our output.
			 */
			{
				int len;
				char buf[1024];

				len = read(con->fd, buf, sizeof(buf));
				if (len == 0 || (len < 0 && errno != EAGAIN && errno != EINTR) ) {
					con->close_timeout_ts = srv->cur_ts - (HTTP_LINGER_TIMEOUT+1);
				}
			}

			if (srv->cur_ts - con->close_timeout_ts > HTTP_LINGER_TIMEOUT) {
				connection_close(srv, con);

				if (srv->srvconf.log_state_handling) {
					log_error_write(srv, __FILE__, __LINE__, "sd",
							"connection closed for fd", con->fd);
				}
			}

			break;
		case CON_STATE_READ_POST:
		case CON_STATE_READ:
			if (srv->srvconf.log_state_handling) {
				log_error_write(srv, __FILE__, __LINE__, "sds",
						"state for fd", con->fd, connection_get_state(con->state));
			}

			connection_handle_read_state(srv, con);
			break;
		case CON_STATE_WRITE:
			if (srv->srvconf.log_state_handling) {
				log_error_write(srv, __FILE__, __LINE__, "sds",
						"state for fd", con->fd, connection_get_state(con->state));
			}

			/* only try to write if we have something in the queue */
			if (!chunkqueue_is_empty(con->write_queue)) {
				if (con->is_writable) {
					if (-1 == connection_handle_write(srv, con)) {
						log_error_write(srv, __FILE__, __LINE__, "ds",
								con->fd,
								"handle write failed.");
						connection_set_state(srv, con, CON_STATE_ERROR);
					}
				}
			} else if (con->file_finished) {
				connection_set_state(srv, con, CON_STATE_RESPONSE_END);
			}

			break;
		case CON_STATE_ERROR: /* transient */

			/* even if the connection was drop we still have to write it to the access log */
			if (con->http_status) {
				plugins_call_handle_request_done(srv, con);
			}
#ifdef USE_OPENSSL
			if (srv_sock->is_ssl) {
				int ret, ssl_r;
				unsigned long err;
				ERR_clear_error();
				switch ((ret = SSL_shutdown(con->ssl))) {
				case 1:
					/* ok */
					break;
				case 0:
					ERR_clear_error();
					if (-1 != (ret = SSL_shutdown(con->ssl))) break;

					/* fall through */
				default:

					switch ((ssl_r = SSL_get_error(con->ssl, ret))) {
					case SSL_ERROR_WANT_WRITE:
					case SSL_ERROR_WANT_READ:
						break;
					case SSL_ERROR_SYSCALL:
						/* perhaps we have error waiting in our error-queue */
						if (0 != (err = ERR_get_error())) {
							do {
								log_error_write(srv, __FILE__, __LINE__, "sdds", "SSL:",
										ssl_r, ret,
										ERR_error_string(err, NULL));
							} while((err = ERR_get_error()));
						} else if (errno != 0) { /* ssl bug (see lighttpd ticket #2213): sometimes errno == 0 */
							switch(errno) {
							case EPIPE:
							case ECONNRESET:
								break;
							default:
								log_error_write(srv, __FILE__, __LINE__, "sddds", "SSL (error):",
									ssl_r, ret, errno,
									strerror(errno));
								break;
							}
						}

						break;
					default:
						while((err = ERR_get_error())) {
							log_error_write(srv, __FILE__, __LINE__, "sdds", "SSL:",
									ssl_r, ret,
									ERR_error_string(err, NULL));
						}

						break;
					}
				}
				ERR_clear_error();
			}
#endif

			switch(con->mode) {
			case DIRECT:
#if 0
				log_error_write(srv, __FILE__, __LINE__, "sd",
						"emergency exit: direct",
						con->fd);
#endif
				break;
			default:
				switch(r = plugins_call_handle_connection_close(srv, con)) {
				case HANDLER_GO_ON:
				case HANDLER_FINISHED:
					break;
				default:
					log_error_write(srv, __FILE__, __LINE__, "sd", "unhandling return value", r);
					break;
				}
				break;
			}

			connection_reset(srv, con);

			/* close the connection */
			if ((0 == shutdown(con->fd, SHUT_WR))) {
				con->close_timeout_ts = srv->cur_ts;
				connection_set_state(srv, con, CON_STATE_CLOSE);

				if (srv->srvconf.log_state_handling) {
					log_error_write(srv, __FILE__, __LINE__, "sd",
							"shutdown for fd", con->fd);
				}
			} else {
				connection_close(srv, con);
			}

			con->keep_alive = 0;

			srv->con_closed++;

			break;
		default:
			log_error_write(srv, __FILE__, __LINE__, "sdd",
					"unknown state:", con->fd, con->state);

			break;
		}

		if (done == -1) {
			done = 0;
		} else if (ostate == con->state) {
			done = 1;
		}
	}

	if (srv->srvconf.log_state_handling) {
		log_error_write(srv, __FILE__, __LINE__, "sds",
				"state at exit:",
				con->fd,
				connection_get_state(con->state));
	}

	switch(con->state) {
	case CON_STATE_READ_POST:
	case CON_STATE_READ:
	case CON_STATE_CLOSE:
		fdevent_event_set(srv->ev, &(con->fde_ndx), con->fd, FDEVENT_IN);
		break;
	case CON_STATE_WRITE:
		/* request write-fdevent only if we really need it
		 * - if we have data to write
		 * - if the socket is not writable yet
		 */
		if (!chunkqueue_is_empty(con->write_queue) &&
		    (con->is_writable == 0) &&
		    (con->traffic_limit_reached == 0)) {
			fdevent_event_set(srv->ev, &(con->fde_ndx), con->fd, FDEVENT_OUT);
		} else {
			fdevent_event_del(srv->ev, &(con->fde_ndx), con->fd);
		}
		break;
	default:
		fdevent_event_del(srv->ev, &(con->fde_ndx), con->fd);
		break;
	}

	return 0;
}
Exemplo n.º 25
0
int main(void) {

    WSADATA Data;
    SOCKADDR_IN recvSockAddr;
    SOCKET recvSocket;
    int status;
    int numrcv = 0;
    struct hostent * remoteHost;
    char * ip;
    const char * host_name = "pb-homework.appspot.com";
    char buffer[MAXBUFLEN];
    memset(buffer,0,MAXBUFLEN);
    // Initialize Windows Socket DLL
    status = WSAStartup(MAKEWORD(2, 2), &Data);
    if(status != 0)
    {
        printf("ERROR: WSAStartup unsuccessful\r\n");
        return 0;
    }
	// Get IP address from host name
	remoteHost = gethostbyname(host_name);
	ip = inet_ntoa(*(struct in_addr *)*remoteHost->h_addr_list);
	printf("IP address is: %s.\n", ip);
    memset(&recvSockAddr, 0, sizeof(recvSockAddr)); // zero the sockaddr_in structure
    recvSockAddr.sin_port=htons(PORT); // specify the port portion of the address
    recvSockAddr.sin_family=AF_INET; // specify the address family as Internet
    recvSockAddr.sin_addr.s_addr= inet_addr(ip); // specify ip address
	// Create socket
	recvSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
	if(recvSocket == INVALID_SOCKET)
	{
		printf("ERROR: socket unsuccessful\r\n");
             WSACleanup();
		system("pause");
		return 0;
	}
    // Connect
    if(connect(recvSocket,(SOCKADDR*)&recvSockAddr,sizeof(SOCKADDR_IN)) == SOCKET_ERROR)
    {
        printf("ERROR: socket could not connect\r\n");
        closesocket(recvSocket);
        WSACleanup();
        return 0;
    }
    // Send request
    char request[200];
    sprintf(request, "GET /test/var/24?format=json HTTP/1.1\r\nHost:%s\r\n\r\n", host_name);  // add Host header with host_name value
    send(recvSocket, request, strlen(request), 0);

	// Receieve
    numrcv = recv(recvSocket, buffer, MAXBUFLEN, NO_FLAGS_SET);
    if (numrcv == SOCKET_ERROR)
    {
        printf("ERROR: recvfrom unsuccessful\r\n");
        status = closesocket(recvSocket);
        if(status == SOCKET_ERROR)
			printf("ERROR: closesocket unsuccessful\r\n");
        status = WSACleanup();
        if (status == SOCKET_ERROR)
			printf("ERROR: WSACleanup unsuccessful\r\n");
        system("pause");
        return(1);
    }
	// Print out receieved socket data
    printf("%s\r\n", buffer);

    char * json=strstr(buffer,"{");


    cJSON * SI = cJSON_CreateObject();

    SI=cJSON_Parse(json);


    author_t * author=malloc(sizeof(author_t));

    author->author=malloc(strlen(cJSON_GetObjectItem(SI,"author")->valuestring)+1);
    strcpy(author->author,cJSON_GetObjectItem(SI,"author")->valuestring);

    author->quote=malloc(strlen(cJSON_GetObjectItem(SI,"quote")->valuestring)+1);
    strcpy(author->quote,cJSON_GetObjectItem(SI,"quote")->valuestring);

    time_t rawtime;
    struct tm * timeinfo;

    time ( &rawtime );
    timeinfo = localtime ( &rawtime );

    author->time=malloc(strlen(asctime(timeinfo)));
    strcpy(author->time,asctime(timeinfo));
    author->time[strlen(author->time)-1]='\0';

    cJSON * SM = cJSON_CreateObject();
    cJSON_AddItemToObject(SM, "author", cJSON_CreateString(author->author));
    cJSON_AddItemToObject(SM, "quote", cJSON_CreateString(author->quote));
    cJSON_AddItemToObject(SM, "time", cJSON_CreateString(author->time));
    char * jsonSM = cJSON_Print(SM);



    system("pause");



        lib_init();
    socket_t * server = socket_new();
    socket_bind(server, 5000);
    socket_listen(server);
    char buf[10000];
    socket_t * client = NULL;
     while(1)
    {
        client = socket_accept(server);
        socket_read(client, buf, sizeof(buf));
        printf("%s",buf);
        if (strlen(buf) != 0){
        http_request_t rs;
        rs = http_request_parse(buf);
        if (strcmp(rs.method,"GET") == 0 && strcmp(rs.uri, "/info") == 0 )
        {
            server_info(client);

        }
         if (strcmp(rs.method,"GET") == 0 && strcmp(rs.uri, "/external") == 0 )
        {
            server_sent(client,jsonSM);
        }

        }
    }
      system("pause");
    return 0;
}