2 * Copyright (c) 2007 Ry Dahl <ry.d4hl@gmail.com>
3 * This software is released under the "MIT License". See README file for details.
6 /* TODO: add timeouts for clients */
10 #include <arpa/inet.h>
25 #define TCP_CHUNKSIZE (16*1024)
27 /* Private function */
28 void tcp_client_stop_read_watcher(tcp_client
*client
);
30 /* Returns the number of bytes remaining to write */
31 int tcp_client_write(tcp_client
*client
, const char *data
, int length
)
34 tcp_warning("Trying to write to a client that isn't open.");
38 int sent
= send(client
->fd
, data
, length
, 0);
40 tcp_warning("Error writing: %s", strerror(errno
));
41 tcp_client_close(client
);
44 ev_timer_again(client
->parent
->loop
, client
->timeout_watcher
);
49 void tcp_client_on_timeout( struct ev_loop
*loop
50 , struct ev_timer
*watcher
54 tcp_client
*client
= (tcp_client
*)(watcher
->data
);
56 assert(client
->parent
->loop
== loop
);
57 assert(client
->timeout_watcher
== watcher
);
59 tcp_client_close(client
);
60 tcp_info("client timed out");
63 void tcp_client_on_readable( struct ev_loop
*loop
64 , struct ev_io
*watcher
68 tcp_client
*client
= (tcp_client
*)(watcher
->data
);
71 // check for error in revents
72 if(EV_ERROR
& revents
) {
73 tcp_error("tcp_client_on_readable() got error event, closing client");
78 assert(client
->parent
->open
);
79 assert(client
->parent
->loop
== loop
);
80 assert(client
->read_watcher
== watcher
);
82 if(client
->read_cb
== NULL
) return;
84 length
= recv(client
->fd
, client
->read_buffer
, TCP_CHUNKSIZE
, 0);
87 g_debug("zero length read? what to do? killing read watcher");
88 tcp_client_stop_read_watcher(client
);
90 } else if(length
< 0) {
91 if(errno
== EBADF
|| errno
== ECONNRESET
)
92 g_debug("errno says Connection reset by peer");
94 tcp_error("Error recving data: %s", strerror(errno
));
98 ev_timer_again(loop
, client
->timeout_watcher
);
99 // g_debug("Read %d bytes", length);
101 client
->read_cb(client
->read_buffer
, length
, client
->read_cb_data
);
102 /* Cannot access client beyond this point because it's possible that the
107 tcp_client_close(client
);
110 tcp_client
* tcp_client_new(tcp_server
*server
)
115 client
= g_new0(tcp_client
, 1);
117 client
->parent
= server
;
119 client
->fd
= accept(server
->fd
, (struct sockaddr
*)&(client
->sockaddr
), &len
);
121 tcp_error("Could not get client socket");
127 int r
= fcntl(client
->fd
, F_SETFL
, O_NONBLOCK
);
129 tcp_error("Setting nonblock mode on socket failed");
133 client
->read_buffer
= (char*)malloc(sizeof(char)*TCP_CHUNKSIZE
);
135 client
->read_watcher
= g_new0(struct ev_io
, 1);
136 client
->read_watcher
->data
= client
;
137 ev_init(client
->read_watcher
, tcp_client_on_readable
);
138 ev_io_set(client
->read_watcher
, client
->fd
, EV_READ
| EV_ERROR
);
139 ev_io_start(server
->loop
, client
->read_watcher
);
141 client
->timeout_watcher
= g_new0(struct ev_timer
, 1);
142 client
->timeout_watcher
->data
= client
;
143 ev_timer_init(client
->timeout_watcher
, tcp_client_on_timeout
, 60., 60.);
144 ev_timer_start(server
->loop
, client
->timeout_watcher
);
149 tcp_client_close(client
);
153 void tcp_client_stop_read_watcher(tcp_client
*client
)
155 //assert(client->open);
156 assert(client
->parent
->open
);
157 //assert(client->read_watcher);
159 if(client
->read_watcher
!= NULL
) {
160 //g_debug("killing read watcher");
161 ev_io_stop(client
->parent
->loop
, client
->read_watcher
);
162 free(client
->read_watcher
);
163 client
->read_watcher
= NULL
;
167 void tcp_client_free(tcp_client
*client
)
169 tcp_client_close(client
);
170 free(client
->read_buffer
);
172 //g_debug("tcp client closed");
175 void tcp_client_close(tcp_client
*client
)
178 tcp_client_stop_read_watcher(client
);
180 ev_timer_stop(client
->parent
->loop
, client
->timeout_watcher
);
181 free(client
->timeout_watcher
);
182 client
->timeout_watcher
= NULL
;
185 client
->open
= FALSE
;
186 //g_debug("tcp client closed");
190 tcp_server
* tcp_server_new()
194 tcp_server
*server
= g_new0(tcp_server
, 1);
196 server
->fd
= socket(PF_INET
, SOCK_STREAM
, 0);
197 r
= fcntl(server
->fd
, F_SETFL
, O_NONBLOCK
);
199 tcp_error("Setting nonblock mode on socket failed");
204 r
= setsockopt(server
->fd
, SOL_SOCKET
, SO_REUSEADDR
, &flags
, sizeof(flags
));
206 tcp_error("failed to set setsock to reuseaddr");
210 r = setsockopt(server->fd, IPPROTO_TCP, TCP_NODELAY, &flags, sizeof(flags));
212 tcp_error("failed to set socket to nodelay");
213 tcp_server_free(server);
218 server
->loop
= ev_loop_new(0);
220 server
->clients
= g_queue_new();
221 server
->open
= FALSE
;
225 tcp_server_free(server
);
229 void tcp_server_free(tcp_server
*server
)
231 tcp_server_close(server
);
232 g_queue_free(server
->clients
);
235 g_debug("tcp server freed.");
238 void tcp_server_close(tcp_server
*server
)
240 printf("closeserver\n");
241 assert(server
->open
);
244 while((client
= g_queue_pop_head(server
->clients
)))
245 tcp_client_close(client
);
248 free(server
->port_s
);
249 server
->port_s
= NULL
;
251 if(server
->dns_info
) {
252 free(server
->dns_info
);
253 server
->dns_info
= NULL
;
255 if(server
->accept_watcher
) {
256 printf("killing accept watcher\n");
257 ev_io_stop(server
->loop
, server
->accept_watcher
);
258 free(server
->accept_watcher
);
259 server
->accept_watcher
= NULL
;
261 ev_unloop(server
->loop
, EVUNLOOP_ALL
);
262 ev_loop_destroy (server
->loop
);
266 server
->open
= FALSE
;
269 void tcp_server_accept( struct ev_loop
*loop
270 , struct ev_io
*watcher
274 tcp_server
*server
= (tcp_server
*)(watcher
->data
);
277 assert(server
->open
);
278 assert(server
->loop
== loop
);
280 // check for error in revents
281 if(EV_ERROR
& revents
) {
282 tcp_error("tcp_client_on_readable() got error event, closing free");
283 tcp_server_free(server
);
287 client
= tcp_client_new(server
);
288 g_queue_push_head(server
->clients
, (gpointer
)client
);
290 if(server
->accept_cb
!= NULL
)
291 server
->accept_cb(client
, server
->accept_cb_data
);
296 void tcp_server_listen ( tcp_server
*server
300 , tcp_server_accept_cb_t accept_cb
301 , void *accept_cb_data
306 server
->sockaddr
.sin_family
= AF_INET
;
307 server
->sockaddr
.sin_port
= htons(port
);
309 /* for easy access to the port */
310 server
->port_s
= malloc(sizeof(char)*8);
311 sprintf(server
->port_s
, "%d", port
);
313 server
->dns_info
= gethostbyname(address
);
314 if (!(server
->dns_info
&& server
->dns_info
->h_addr
)) {
315 tcp_error("Could not look up hostname %s", address
);
318 memmove(&(server
->sockaddr
.sin_addr
), server
->dns_info
->h_addr
, sizeof(struct in_addr
));
320 /* Other socket options. These could probably be fine tuned.
321 * SO_SNDBUF set buffer size for output
322 * SO_RCVBUF set buffer size for input
323 * SO_SNDLOWAT set minimum count for output
324 * SO_RCVLOWAT set minimum count for input
325 * SO_SNDTIMEO set timeout value for output
326 * SO_RCVTIMEO set timeout value for input
328 r
= bind(server
->fd
, (struct sockaddr
*)&(server
->sockaddr
), sizeof(server
->sockaddr
));
330 tcp_error("Failed to bind to %s %d", address
, port
);
334 r
= listen(server
->fd
, backlog
);
336 tcp_error("listen() failed");
340 assert(server
->open
== FALSE
);
343 server
->accept_watcher
= g_new0(struct ev_io
, 1);
344 server
->accept_watcher
->data
= server
;
345 server
->accept_cb
= accept_cb
;
346 server
->accept_cb_data
= accept_cb_data
;
348 ev_init (server
->accept_watcher
, tcp_server_accept
);
349 ev_io_set (server
->accept_watcher
, server
->fd
, EV_READ
| EV_ERROR
);
350 ev_io_start (server
->loop
, server
->accept_watcher
);
351 ev_loop (server
->loop
, 0);
355 tcp_server_close(server
);
359 char* tcp_server_address(tcp_server
*server
)
362 return server
->dns_info
->h_name
;