diff --git a/qse/lib/net/httpd.c b/qse/lib/net/httpd.c index 73422e92..5ac89baa 100644 --- a/qse/lib/net/httpd.c +++ b/qse/lib/net/httpd.c @@ -539,6 +539,7 @@ static int activate_listener (qse_httpd_t* httpd, listener_t* l) break; } +#ifdef AF_INET6 case AF_INET6: { addr.in6.sin6_family = l->family; @@ -547,6 +548,7 @@ static int activate_listener (qse_httpd_t* httpd, listener_t* l) /* TODO: addr.in6.sin6_scope_id */ break; } +#endif default: { @@ -720,7 +722,11 @@ static int accept_client_from_listener (qse_httpd_t* httpd, listener_t* l) { int flag, c; sockaddr_t addr; +#ifdef HAVE_SOCKLEN_T socklen_t addrlen = QSE_SIZEOF(addr); +#else + int addrlen = QSE_SIZEOF(addr); +#endif qse_httpd_client_t* client; /* TODO: @@ -915,7 +921,7 @@ qse_fprintf (QSE_STDERR, QSE_T("Error: select returned failure - %S\n"), strerro if (client->bad) { /*send (client->handle, i, "INTERNAL SERVER ERROR..", ...);*/ - /*shutdown (client->handle.i, 0);*/ + /*shutdown (client->handle.i, SHUT_RDWR);*/ pthread_mutex_lock (&httpd->client.mutex); delete_from_client_array (httpd, fd); pthread_mutex_unlock (&httpd->client.mutex); @@ -985,6 +991,7 @@ int qse_httpd_loop (qse_httpd_t* httpd, int threaded) #endif httpd->stopreq = 0; + httpd->threaded = 0; QSE_ASSERTX (httpd->listener.list != QSE_NULL, "Add listeners before calling qse_httpd_loop()" @@ -1008,11 +1015,12 @@ int qse_httpd_loop (qse_httpd_t* httpd, int threaded) pthread_mutex_init (&httpd->client.mutex, QSE_NULL); pthread_cond_init (&httpd->client.cond, QSE_NULL); - if (pthread_create (&response_thread_id, QSE_NULL, response_thread, httpd) != 0) + if (pthread_create ( + &response_thread_id, QSE_NULL, + response_thread, httpd) != 0) { pthread_cond_destroy (&httpd->client.cond); pthread_mutex_destroy (&httpd->client.mutex); - httpd->threaded = 0; } else httpd->threaded = 1; } @@ -1028,9 +1036,13 @@ int qse_httpd_loop (qse_httpd_t* httpd, int threaded) tv.tv_sec = 1; tv.tv_usec = 0; - pthread_mutex_lock (&httpd->client.mutex); +#if defined(HAVE_PTHREAD) + if (httpd->threaded) pthread_mutex_lock (&httpd->client.mutex); +#endif max = make_fd_set_from_client_array (httpd, &r, &w); - pthread_mutex_unlock (&httpd->client.mutex); +#if defined(HAVE_PTHREAD) + if (httpd->threaded) pthread_mutex_unlock (&httpd->client.mutex); +#endif n = select (max + 1, &r, &w, QSE_NULL, &tv); if (n <= -1) @@ -1064,7 +1076,7 @@ qse_fprintf (QSE_STDERR, QSE_T("Error: select returned failure\n")); /* let the writing part handle it, * probably in the next iteration */ qse_httpd_markclientbad (httpd, client); - shutdown (client->handle.i, 0); + shutdown (client->handle.i, SHUT_RDWR); } else { @@ -1083,7 +1095,7 @@ qse_fprintf (QSE_STDERR, QSE_T("Error: select returned failure\n")); if (client->bad) { /*send (client->handle, i, "INTERNAL SERVER ERROR..", ...);*/ - /*shutdown (client->handle.i, 0);*/ + /*shutdown (client->handle.i, SHUT_RDWR);*/ /*pthread_mutex_lock (&httpd->client.mutex);*/ delete_from_client_array (httpd, fd); @@ -1176,6 +1188,7 @@ static listener_t* parse_listener_string ( if (*p != QSE_T('/')) goto oops_einval; p++; /* skip / */ +#ifdef AF_INET6 if (*p == QSE_T('[')) { /* IPv6 address */ @@ -1193,6 +1206,7 @@ static listener_t* parse_listener_string ( } else { +#endif /* host name or IPv4 address */ tmp.ptr = p; while (!QSE_ISSPACE(*p) && @@ -1200,7 +1214,9 @@ static listener_t* parse_listener_string ( *p != QSE_T('\0')) p++; tmp.len = p - tmp.ptr; ltmp->family = AF_INET; +#ifdef AF_INET6 } +#endif ltmp->host = qse_strxdup (tmp.ptr, tmp.len, httpd->mmgr); if (ltmp->host == QSE_NULL) goto oops_enomem; @@ -1314,11 +1330,15 @@ static int delete_listeners (qse_httpd_t* httpd, const qse_char_t* uri) int qse_httpd_addlisteners (qse_httpd_t* httpd, const qse_char_t* uri) { +#if defined(HAVE_PTHREAD) int n; pthread_mutex_lock (&httpd->listener.mutex); n = add_listeners (httpd, uri); pthread_mutex_unlock (&httpd->listener.mutex); return n; +#else + return add_listeners (httpd, uri); +#endif } #if 0 diff --git a/qse/lib/net/httpd.h b/qse/lib/net/httpd.h index 5ef4df4a..bbbff8b2 100644 --- a/qse/lib/net/httpd.h +++ b/qse/lib/net/httpd.h @@ -34,12 +34,18 @@ # include #endif +#ifndef SHUT_RDWR +# define SHUT_RDWR 2 +#endif + typedef struct client_array_t client_array_t; union sockaddr_t { struct sockaddr_in in4; +#ifdef AF_INET6 struct sockaddr_in6 in6; +#endif }; typedef union sockaddr_t sockaddr_t; @@ -90,7 +96,9 @@ struct listener_t union { struct in_addr in4; +#ifdef AF_INET6 struct in6_addr in6; +#endif } addr; int port; @@ -105,9 +113,7 @@ struct qse_httpd_t qse_httpd_cbs_t* cbs; int stopreq; -#if defined(HAVE_PTHREAD) int threaded; -#endif struct { diff --git a/qse/lib/net/httpd_task.c b/qse/lib/net/httpd_task.c index 1af22ae8..a920ee63 100644 --- a/qse/lib/net/httpd_task.c +++ b/qse/lib/net/httpd_task.c @@ -25,16 +25,36 @@ #include #include - -#ifdef HAVE_SYS_SENDFILE_H -#include -#endif - #include #include #define MAX_SENDFILE_SIZE 4096 +#ifdef HAVE_SYS_SENDFILE_H +# include +#else +qse_ssize_t sendfile ( + int out_fd, int in_fd, qse_foff_t* offset, qse_size_t count) +{ + qse_mchar_t buf[MAX_SENDFILE_SIZE]; + qse_ssize_t n; + + if (offset && lseek (in_fd, *offset, SEEK_SET) != *offset) + return (qse_ssize_t)-1; + + if (count > QSE_COUNTOF(buf)) count = QSE_COUNTOF(buf); + n = read (in_fd, buf, count); + if (n == (qse_ssize_t)-1 || n == 0) return n; + + n = write (out_fd, buf, n); + if (n > 0 && offset) *offset = *offset + n; + + return n; +} +#endif + + + /*------------------------------------------------------------------------*/ static int task_main_disconnect ( @@ -481,6 +501,7 @@ static int task_main_path ( if (data->range.to >= st.st_size) data->range.to = st.st_size - 1; +#if (QSE_SIZEOF_LONG_LONG > 0) x = qse_httpd_entaskformat (httpd, client, QSE_MT("HTTP/%d.%d 206 Partial content\r\nContent-Length: %llu\r\nContent-Location: %s\r\nContent-Range: bytes %llu-%llu/%llu\r\n\r\n"), data->version.major, @@ -489,8 +510,20 @@ static int task_main_path ( data->name, (unsigned long long)data->range.from, (unsigned long long)data->range.to, - st.st_size + (unsigned long long)st.st_size ); +#else + x = qse_httpd_entaskformat (httpd, client, + QSE_MT("HTTP/%d.%d 206 Partial content\r\nContent-Length: %lu\r\nContent-Location: %s\r\nContent-Range: bytes %lu-%lu/%lu\r\n\r\n"), + data->version.major, + data->version.minor, + (unsigned long)(data->range.to - data->range.from + 1), + data->name, + (unsigned long)data->range.from, + (unsigned long)data->range.to, + (unsigned long)st.st_size + ); +#endif if (x <= -1) goto oops; x = qse_httpd_entaskfile ( @@ -504,6 +537,7 @@ static int task_main_path ( { /* TODO: int64 format.... don't hard code it llu */ +#if (QSE_SIZEOF_LONG_LONG > 0) x = qse_httpd_entaskformat (httpd, client, QSE_MT("HTTP/%d.%d 200 OK\r\nContent-Length: %llu\r\nContent-Location: %s\r\n\r\n"), data->version.major, @@ -511,6 +545,15 @@ static int task_main_path ( (unsigned long long)st.st_size, data->name ); +#else + x = qse_httpd_entaskformat (httpd, client, + QSE_MT("HTTP/%d.%d 200 OK\r\nContent-Length: %lu\r\nContent-Location: %s\r\n\r\n"), + data->version.major, + data->version.minor, + (unsigned long)st.st_size, + data->name + ); +#endif if (x <= -1) goto oops; x = qse_httpd_entaskfile (httpd, client, handle, 0, st.st_size);