void on_accept(int fd, short ev, void *arg) { int client_fd; struct sockaddr_in client_addr; socklen_t client_len = sizeof(client_addr); workqueue_t *workqueue = (workqueue_t *)arg; client_t *client; job_t *job; client_fd = accept(fd, (struct sockaddr *)&client_addr, &client_len); if (client_fd < 0) { warn("accept failed"); return; } if (setnonblock(client_fd) < 0) { warn("failed to set client socket to non-blocking"); close(client_fd); return; } if ((client = malloc(sizeof(*client))) == NULL) { warn("failed to allocate memory for client state"); close(client_fd); return; } memset(client, 0, sizeof(*client)); client->fd = client_fd; if ((client->output_buffer = evbuffer_new()) == NULL) { warn("client output buffer allocation failed"); closeAndFreeClient(client); return; } if ((client->evbase = event_base_new()) == NULL) { warn("client event_base creation failed"); closeAndFreeClient(client); return; } if ((client->buf_ev = bufferevent_new(client_fd, buffered_on_read, buffered_on_write, buffered_on_error, client)) == NULL) { warn("client bufferevent creation failed"); closeAndFreeClient(client); return; } bufferevent_base_set(client->evbase, client->buf_ev); bufferevent_enable(client->buf_ev, EV_READ); if ((job = malloc(sizeof(*job))) == NULL) { warn("failed to allocate memory for job state"); closeAndFreeClient(client); return; } job->job_function = server_job_function; job->user_data = client; workqueue_add_job(workqueue, job); }
/** * Called by libevent when there is data to read. */ void buffered_on_read(struct bufferevent *bev, void *arg) { client_t *client = (client_t *)arg; job_t *job; /* Create a job object and add it to the work queue. */ if ((job = malloc(sizeof(*job))) == NULL) { warn("failed to allocate memory for job state"); closeAndFreeClient(client); return; } job->job_function = server_job_function; job->user_data = client; workqueue_add_job(&workqueue, job); }
/** * This function will be called by libevent when there is a connection * ready to be accepted. */ void on_accept(int fd, short ev, void *arg) { int client_fd; struct sockaddr_in client_addr; socklen_t client_len = sizeof(client_addr); workqueue_t *workqueue = (workqueue_t *)arg; client_t *client; job_t *job; client_fd = accept(fd, (struct sockaddr *)&client_addr, &client_len); if (client_fd < 0) { warn("accept failed"); return; } printf("Run accept fd:%d\n", fd); /* Set the client socket to non-blocking mode. */ if (setnonblock(client_fd) < 0) { ; warn("failed to set client socket to non-blocking"); close(client_fd); return; } /* Create a client object. */ if ((client = (client_t *)malloc(sizeof(*client))) == NULL) { warn("failed to allocate memory for client state"); close(client_fd); return; } memset(client, 0, sizeof(*client)); client->fd = client_fd; /* Add any custom code anywhere from here to the end of this function * to initialize your application-specific attributes in the client struct. */ if ((client->output_buffer = evbuffer_new()) == NULL) { warn("client output buffer allocation failed"); closeAndFreeClient(client); return; } if ((client->evbase = event_base_new()) == NULL) { warn("client event_base creation failed"); closeAndFreeClient(client); return; } /* Create the buffered event. * * The first argument is the file descriptor that will trigger * the events, in this case the clients socket. * * The second argument is the callback that will be called * when data has been read from the socket and is available to * the application. * * The third argument is a callback to a function that will be * called when the write buffer has reached a low watermark. * That usually means that when the write buffer is 0 length, * this callback will be called. It must be defined, but you * don't actually have to do anything in this callback. * * The fourth argument is a callback that will be called when * there is a socket error. This is where you will detect * that the client disconnected or other socket errors. * * The fifth and final argument is to store an argument in * that will be passed to the callbacks. We store the client * object here. */ if ((client->buf_ev = bufferevent_new(client_fd, buffered_on_read, buffered_on_write, buffered_on_error, client)) == NULL) { warn("client bufferevent creation failed"); closeAndFreeClient(client); return; } bufferevent_base_set(client->evbase, client->buf_ev); bufferevent_settimeout(client->buf_ev, SOCKET_READ_TIMEOUT_SECONDS, SOCKET_WRITE_TIMEOUT_SECONDS); /* We have to enable it before our callbacks will be * called. */ bufferevent_enable(client->buf_ev, EV_READ); /* Create a job object and add it to the work queue. */ if ((job = (job_t *)malloc(sizeof(*job))) == NULL) { warn("failed to allocate memory for job state"); closeAndFreeClient(client); return; } job->job_function = server_job_function; job->user_data = client; workqueue_add_job(workqueue, job); }