17 #include "ev_tcp_socket.h"
19 #define EV_TCP_CHUNKSIZE (16*1024)
22 int misc_lookup_host(char *address
, struct in_addr
*addr
)
25 host
= gethostbyname(address
);
26 if (host
&& host
->h_addr_list
[0]) {
27 memmove(addr
, host
->h_addr_list
[0], sizeof(struct in_addr
));
33 /* Returns the number of bytes remaining to write */
34 int ev_tcp_client_write(ev_tcp_client
*client
, const char *data
, int length
)
36 int sent
= send(client
->fd
, data
, length
, 0);
38 client
->error_cb(EV_TCP_ERROR
, strerror(errno
));
39 ev_tcp_client_close(client
);
45 void ev_tcp_client_on_readable( struct ev_loop
*loop
46 , struct ev_io
*watcher
50 ev_tcp_client
*client
= (ev_tcp_client
*)(watcher
->data
);
51 char buffer
[EV_TCP_CHUNKSIZE
];
54 if(client
->read_cb
== NULL
) return;
56 length
= recv(client
->fd
, buffer
, EV_TCP_CHUNKSIZE
, 0);
59 client
->error_cb(EV_TCP_ERROR
, strerror(errno
));
60 ev_tcp_client_close(client
);
64 /* User needs to copy the data out of the buffer or process it before
65 * leaving this function.
67 client
->read_cb(client
, buffer
, length
);
70 ev_tcp_client
* ev_tcp_client_new(ev_tcp_server
*server
)
73 ev_tcp_client
*client
;
75 client
= g_new0(ev_tcp_client
, 1);
76 client
->error_cb
= server
->error_cb
;
77 client
->parent
= server
;
78 client
->fd
= accept(server
->fd
, (struct sockaddr
*)&(client
->sockaddr
), &len
);
80 client
->error_cb(EV_TCP_ERROR
, "Could not get client socket");
81 ev_tcp_client_free(client
);
85 int r
= fcntl(client
->fd
, F_SETFL
, O_NONBLOCK
);
87 server
->error_cb(EV_TCP_WARNING
, "setting nonblock mode failed");
90 client
->read_watcher
= g_new0(struct ev_io
, 1);
91 client
->read_watcher
->data
= client
;
92 ev_init (client
->read_watcher
, ev_tcp_client_on_readable
);
93 ev_io_set (client
->read_watcher
, client
->fd
, EV_READ
);
94 ev_io_start (server
->loop
, client
->read_watcher
);
99 void ev_tcp_client_free(ev_tcp_client
*client
)
101 ev_tcp_client_close(client
);
105 void ev_tcp_client_close(ev_tcp_client
*client
)
107 if(client
->read_watcher
) {
108 printf("killing read watcher\n");
109 ev_io_stop(client
->parent
->loop
, client
->read_watcher
);
110 free(client
->read_watcher
);
111 client
->read_watcher
= NULL
;
116 ev_tcp_server
* ev_tcp_server_new(ev_tcp_error_cb error_cb
)
119 ev_tcp_server
*server
= g_new0(ev_tcp_server
, 1);
121 server
->fd
= socket(PF_INET
, SOCK_STREAM
, 0);
122 server
->error_cb
= error_cb
;
123 r
= fcntl(server
->fd
, F_SETFL
, O_NONBLOCK
);
125 server
->error_cb(EV_TCP_WARNING
, "setting nonblock mode failed");
129 server
->loop
= ev_default_loop(0);
134 void ev_tcp_server_free(ev_tcp_server
*server
)
136 ev_tcp_server_close(server
);
140 void ev_tcp_server_close(ev_tcp_server
*server
)
142 if(server
->accept_watcher
) {
143 printf("killing accept watcher\n");
144 ev_io_stop(server
->loop
, server
->accept_watcher
);
145 free(server
->accept_watcher
);
146 server
->accept_watcher
= NULL
;
151 void ev_tcp_server_accept( struct ev_loop
*loop
152 , struct ev_io
*watcher
156 ev_tcp_server
*server
= (ev_tcp_server
*)(watcher
->data
);
157 ev_tcp_client
*client
;
159 assert(server
->loop
== loop
);
161 client
= ev_tcp_client_new(server
);
162 //g_queue_push_head(server->children, (gpointer)client);
164 if(server
->accept_cb
!= NULL
)
165 server
->accept_cb(server
, client
);
170 void ev_tcp_server_listen ( ev_tcp_server
*server
174 , ev_tcp_server_accept_cb accept_cb
179 server
->sockaddr
.sin_family
= AF_INET
;
180 server
->sockaddr
.sin_port
= htons(port
);
181 //inet_aton(address, server->sockaddr.sin_addr);
182 misc_lookup_host(address
, &(server
->sockaddr
.sin_addr
));
184 /* Other socket options. This could probably be fine tuned.
185 * SO_SNDBUF set buffer size for output
186 * SO_RCVBUF set buffer size for input
187 * SO_SNDLOWAT set minimum count for output
188 * SO_RCVLOWAT set minimum count for input
189 * SO_SNDTIMEO set timeout value for output
190 * SO_RCVTIMEO set timeout value for input
192 r
= bind(server
->fd
, (struct sockaddr
*)&(server
->sockaddr
), sizeof(server
->sockaddr
));
194 server
->error_cb(EV_TCP_ERROR
, "bind failed");
199 r
= listen(server
->fd
, backlog
);
201 server
->error_cb(EV_TCP_ERROR
, "listen failed");
205 server
->accept_watcher
= g_new0(struct ev_io
, 1);
206 server
->accept_watcher
->data
= server
;
207 server
->accept_cb
= accept_cb
;
209 ev_init (server
->accept_watcher
, ev_tcp_server_accept
);
210 ev_io_set (server
->accept_watcher
, server
->fd
, EV_READ
);
211 ev_io_start (server
->loop
, server
->accept_watcher
);
212 ev_loop (server
->loop
, 0);