36 #include <arpa/inet.h>
54 if (sa->sa_family == AF_INET) {
56 return &(((
struct sockaddr_in*)sa)->sin_addr.s_addr);
59 return &(((
struct sockaddr_in6*)sa)->sin6_addr.s6_addr);
80 char buffer[max_data_size];
84 if ((received = recv(watcher->fd, buffer, max_data_size-1, 0)) < 0) {
86 if (received == -1 && errno == EWOULDBLOCK) {
87 HPD_LOG_WARN(context,
"libev callback called without data to receive (conn: %s)", conn->
ip);
93 }
else if (received == 0) {
102 buffer, (
size_t) received)) {
103 HPD_LOG_ERROR(context,
"Failed to handle new data, killing it.");
138 }
else if (sent == conn->
send_len) {
144 char *s = malloc(conn->
send_len*
sizeof(
char));
176 HPD_LOG_INFO(context,
"Timeout on %s [%ld].", conn->
ip, (
long)conn);
195 char ip_string[INET6_ADDRSTRLEN];
198 struct sockaddr_storage in_addr_storage;
199 struct sockaddr *in_addr = (
struct sockaddr *)&in_addr_storage;
206 in_size =
sizeof *in_addr;
207 if ((in_fd = accept(watcher->fd, in_addr, &in_size)) < 0) {
214 inet_ntop(in_addr_storage.ss_family,
tcpd_get_in_addr(in_addr), ip_string,
sizeof ip_string);
215 HPD_LOG_INFO(context,
"Got connection from %s.", ip_string);
220 HPD_LOG_ERROR(context,
"Cannot allocation memory for connection.");
224 conn->
tcpd = watcher->data;
225 strcpy(conn->
ip, ip_string);
241 HPD_LOG_ERROR(context,
"Failed to handle new connection, killing it.");
272 if (settings == NULL || context == NULL || loop == NULL)
return HPD_E_NULL;
273 if (settings->
port <= HPD_TCPD_P_SYSTEM_PORTS_START || settings->
port > HPD_TCPD_P_DYNAMIC_PORTS_END)
return HPD_E_ARGUMENT;
279 sprintf((*tcpd)->port_str,
"%i", settings->
port);
281 (*tcpd)->context = context;
282 (*tcpd)->loop =
loop;
283 TAILQ_INIT(&(*tcpd)->conns);
323 struct addrinfo hints;
324 struct addrinfo *servinfo, *p;
327 memset(&hints, 0,
sizeof hints);
328 hints.ai_family = AF_UNSPEC;
329 hints.ai_socktype = SOCK_STREAM;
330 hints.ai_flags = AI_PASSIVE;
333 if ((rc = getaddrinfo(NULL, tcpd->
port_str, &hints, &servinfo)) != 0) {
339 freeaddrinfo(servinfo);
344 freeaddrinfo(servinfo);
351 for (p = servinfo; p != NULL; p=p->ai_next) {
354 if ((tcpd->
sockfd = socket(p->ai_family, p->ai_socktype, p->ai_protocol)) < 0) {
361 if (fcntl(tcpd->
sockfd, F_SETFL, O_NONBLOCK)) {
371 if (setsockopt(tcpd->
sockfd, SOL_SOCKET, SO_REUSEADDR, &yes,
sizeof(
int)) == -1) {
380 if (bind(tcpd->
sockfd, p->ai_addr, p->ai_addrlen) != 0) {
393 freeaddrinfo(servinfo);
398 freeaddrinfo(servinfo);
401 if (listen(tcpd->
sockfd, SOMAXCONN) < 0) {
443 if (close(tcpd->
sockfd) != 0) {
546 new_len = vsnprintf(
"", 0, fmt, vp);
555 (conn->
send_len + new_len + 1)*
sizeof(
char));
hpd_error_t hpd_tcpd_destroy(hpd_tcpd_t *tcpd)
Destroy tcpd and free used memory.
int timeout
Restart timeout watcher ?
hpd_error_t hpd_tcpd_stop(hpd_tcpd_t *tcpd)
Stop an already running tcpd.
ev_io send_watcher
Send watcher.
static void tcpd_on_ev_send(hpd_ev_loop_t *loop, struct ev_io *watcher, int revents)
Send callback for io-watcher.
hpd_tcpd_port_t port
Port number.
ev_timer timeout_watcher
Timeout watcher.
hpd_error_t hpd_tcpd_conn_keep_open(hpd_tcpd_conn_t *conn)
Disable timeout on connection.
struct hp_settings settings
#define HPD_LOG_INFO(CONTEXT, FMT,...)
char * send_msg
Data to send.
hpd_error_t hpd_tcpd_start(hpd_tcpd_t *tcpd)
Start the tcpd.
hpd_tcpd_t * tcpd
Webserver instance.
static void tcpd_on_ev_timeout(hpd_ev_loop_t *loop, struct ev_timer *watcher, int revents)
Timeout callback for timeout watcher.
hpd_tcpd_nodata_f on_disconnect
hpd_error_t hpd_tcpd_conn_get_ip(hpd_tcpd_conn_t *conn, const char **ip)
Get the IP address of the client.
#define HPD_LOG_VERBOSE(CONTEXT, FMT,...)
hpd_error_t hpd_tcpd_conn_sendf(hpd_tcpd_conn_t *conn, const char *fmt,...)
Send message on connection.
int send_close
Close socket after send ?
int sockfd
Socket file descriptor.
enum hpd_error hpd_error_t
#define HPD_LOG_RETURN_E_ALLOC(CONTEXT)
char ip[INET6_ADDRSTRLEN]
IP address of client.
hpd_error_t hpd_tcpd_conn_kill(hpd_tcpd_conn_t *conn)
Kill and clean up after a connection.
hpd_tcpd_settings_t settings
Settings.
const hpd_module_t * context
hpd_ev_loop_t * loop
Event loop.
static void * tcpd_get_in_addr(struct sockaddr *sa)
Get the in_addr from a sockaddr (IPv4 or IPv6)
hpd_tcpd_conns_t conns
Linked List of connections.
All data to represent a connection.
static struct ev_loop * loop
hpd_error_t hpd_tcpd_conn_close(hpd_tcpd_conn_t *conn)
Close a connection, after the remaining data has been sent.
hpd_error_t hpd_tcpd_conn_vsendf(hpd_tcpd_conn_t *conn, const char *fmt, va_list vp)
Send message on connection.
hpd_tcpd_data_f on_receive
size_t send_len
Length of data to send.
#define HPD_LOG_WARN(CONTEXT, FMT,...)
hpd_error_t hpd_tcpd_create(hpd_tcpd_t **tcpd, hpd_tcpd_settings_t *settings, const hpd_module_t *context, hpd_ev_loop_t *loop)
Create new tcpd instance.
void * ctx
Connection context.
struct ev_loop hpd_ev_loop_t
char port_str[6]
Port number - as a string.
ev_io watcher
New connection watcher.
Settings struct for tcpd.
#define HPD_LOG_ERROR(CONTEXT, FMT,...)
ev_io recv_watcher
Recieve watcher.
static void tcpd_on_ev_conn(hpd_ev_loop_t *loop, struct ev_io *watcher, int revents)
Initialise and accept connection.
#define HPD_LOG_DEBUG(CONTEXT, FMT,...)
static void tcpd_on_ev_recv(hpd_ev_loop_t *loop, struct ev_io *watcher, int revents)
Recieve callback for io-watcher.