libuv/test/echo-server.c

176 lines
4.0 KiB
C
Raw Normal View History

/* Copyright Joyent, Inc. and other Node contributors. All rights reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to
* deal in the Software without restriction, including without limitation the
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
* sell copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
* IN THE SOFTWARE.
*/
2011-04-07 09:02:54 +00:00
#include "../oio.h"
2011-04-19 02:26:32 +00:00
#include "task.h"
2011-03-28 08:55:29 +00:00
#include <stdio.h>
2011-03-28 10:26:00 +00:00
#include <stdlib.h>
2011-03-28 08:55:29 +00:00
typedef struct {
2011-05-08 09:40:09 +00:00
oio_req_t req;
2011-04-07 09:02:54 +00:00
oio_buf buf;
2011-05-03 19:30:09 +00:00
} write_req_t;
2011-03-28 08:55:29 +00:00
2011-05-08 09:40:09 +00:00
static oio_handle_t server;
2011-03-28 08:55:29 +00:00
2011-05-03 19:30:09 +00:00
2011-05-08 09:40:09 +00:00
static void after_write(oio_req_t* req, int status);
static void after_read(oio_handle_t* handle, int nread, oio_buf buf);
static void on_close(oio_handle_t* peer, int status);
static void on_accept(oio_handle_t* handle);
2011-03-31 22:09:06 +00:00
2011-05-08 09:40:09 +00:00
static void after_write(oio_req_t* req, int status) {
2011-05-03 19:30:09 +00:00
write_req_t* wr;
2011-05-03 18:24:59 +00:00
if (status) {
2011-05-09 09:30:11 +00:00
oio_err_t err = oio_last_error();
2011-05-03 18:24:59 +00:00
fprintf(stderr, "oio_write error: %s\n", oio_strerror(err));
ASSERT(0);
}
2011-05-03 19:30:09 +00:00
wr = (write_req_t*) req;
2011-05-03 22:38:32 +00:00
2011-05-03 19:30:09 +00:00
/* Free the read/write buffer and the request */
free(wr->buf.base);
free(wr);
2011-03-28 08:55:29 +00:00
}
2011-05-08 09:40:09 +00:00
static void after_shutdown(oio_req_t* req, int status) {
free(req);
}
2011-05-08 09:40:09 +00:00
static void after_read(oio_handle_t* handle, int nread, oio_buf buf) {
2011-05-03 19:30:09 +00:00
write_req_t *wr;
2011-05-08 09:40:09 +00:00
oio_req_t* req;
2011-05-03 22:38:32 +00:00
if (nread < 0) {
/* Error or EOF */
ASSERT (oio_last_error().code == OIO_EOF);
2011-05-03 22:38:32 +00:00
if (buf.base) {
free(buf.base);
}
2011-05-08 09:40:09 +00:00
req = (oio_req_t*) malloc(sizeof *req);
oio_req_init(req, handle, after_shutdown);
oio_shutdown(req);
return;
2011-05-03 22:38:32 +00:00
}
2011-04-07 02:51:59 +00:00
2011-03-31 12:22:20 +00:00
if (nread == 0) {
/* Everything OK, but nothing read. */
free(buf.base);
return;
2011-03-28 08:55:29 +00:00
}
2011-05-03 19:30:09 +00:00
wr = (write_req_t*) malloc(sizeof *wr);
2011-05-03 00:55:51 +00:00
2011-05-03 19:30:09 +00:00
oio_req_init(&wr->req, handle, after_write);
wr->buf.base = buf.base;
wr->buf.len = nread;
if (oio_write(&wr->req, &wr->buf, 1)) {
FATAL("oio_write failed");
2011-04-16 21:04:45 +00:00
}
2011-03-28 08:55:29 +00:00
}
2011-05-08 09:40:09 +00:00
static void on_close(oio_handle_t* peer, int status) {
if (status != 0) {
2011-03-28 10:17:52 +00:00
fprintf(stdout, "Socket error\n");
2011-03-28 08:55:29 +00:00
}
}
2011-05-08 09:40:09 +00:00
static void on_accept(oio_handle_t* server) {
oio_handle_t* handle = (oio_handle_t*) malloc(sizeof *handle);
2011-03-29 23:34:56 +00:00
2011-05-03 19:30:09 +00:00
if (oio_accept(server, handle, on_close, NULL)) {
2011-04-18 19:53:02 +00:00
FATAL("oio_accept failed");
}
2011-03-28 08:55:29 +00:00
2011-05-03 19:30:09 +00:00
oio_read_start(handle, after_read);
2011-03-31 22:09:06 +00:00
}
2011-03-28 08:55:29 +00:00
2011-03-31 22:09:06 +00:00
2011-05-08 09:40:09 +00:00
static void on_server_close(oio_handle_t* handle, int status) {
ASSERT(handle == &server);
ASSERT(status == 0);
2011-03-28 08:55:29 +00:00
}
static int echo_start(int port) {
2011-04-07 09:02:54 +00:00
struct sockaddr_in addr = oio_ip4_addr("0.0.0.0", port);
2011-03-31 22:09:06 +00:00
int r;
2011-04-18 20:01:50 +00:00
r = oio_tcp_init(&server, on_server_close, NULL);
2011-04-07 02:51:59 +00:00
if (r) {
/* TODO: Error codes */
fprintf(stderr, "Socket creation error\n");
return 1;
}
2011-03-28 08:55:29 +00:00
2011-04-07 09:02:54 +00:00
r = oio_bind(&server, (struct sockaddr*) &addr);
2011-03-29 17:08:45 +00:00
if (r) {
/* TODO: Error codes */
2011-03-29 17:08:45 +00:00
fprintf(stderr, "Bind error\n");
return 1;
}
2011-04-07 09:02:54 +00:00
r = oio_listen(&server, 128, on_accept);
2011-03-29 17:08:45 +00:00
if (r) {
/* TODO: Error codes */
2011-03-29 17:08:45 +00:00
fprintf(stderr, "Listen error\n");
return 1;
}
2011-03-28 08:55:29 +00:00
return 0;
}
2011-03-31 22:09:06 +00:00
2011-04-04 23:43:17 +00:00
static int echo_stop() {
2011-04-07 09:02:54 +00:00
return oio_close(&server);
2011-04-04 23:43:17 +00:00
}
2011-05-08 09:40:09 +00:00
static oio_buf echo_alloc(oio_handle_t* handle, size_t suggested_size) {
oio_buf buf;
buf.base = (char*) malloc(suggested_size);
buf.len = suggested_size;
return buf;
}
HELPER_IMPL(echo_server) {
oio_init(echo_alloc);
if (echo_start(TEST_PORT))
return 1;
fprintf(stderr, "Listening!\n");
oio_run();
return 0;
}