mirror of
https://git.gnunet.org/libmicrohttpd.git
synced 2026-09-28 04:09:31 +03:00
essentials implemented
This commit is contained in:
@@ -5,11 +5,6 @@ things need to be implemented (in list of importance)
|
||||
before certain features can be used at all:
|
||||
|
||||
|
||||
For ANYTHING:
|
||||
=============
|
||||
session.c:
|
||||
- MHD_session_get_fdset (essentially not implemented)
|
||||
|
||||
For GET args:
|
||||
=============
|
||||
session.c:
|
||||
@@ -26,6 +21,13 @@ For COOKIES:
|
||||
session.c:
|
||||
- MHD_parse_session_headers: take cookie header apart
|
||||
|
||||
For http-compliance:
|
||||
====================
|
||||
session.c:
|
||||
- send proper error code back if headers are too long
|
||||
(investigate what we should do with those headers,
|
||||
read? give user control?)
|
||||
|
||||
For IPv6:
|
||||
=========
|
||||
daemon.c:
|
||||
|
||||
+18
-3
@@ -163,7 +163,8 @@ MHD_handle_connection(void * data) {
|
||||
|
||||
if (con == NULL)
|
||||
abort();
|
||||
while (! con->daemon->shutdown) {
|
||||
while ( (! con->daemon->shutdown) &&
|
||||
(con->socket_fd != -1) ) {
|
||||
FD_ZERO(&rs);
|
||||
FD_ZERO(&ws);
|
||||
FD_ZERO(&es);
|
||||
@@ -189,8 +190,10 @@ MHD_handle_connection(void * data) {
|
||||
(MHD_YES != MHD_session_handle_write(con)) ) )
|
||||
break;
|
||||
}
|
||||
close(con->socket_fd);
|
||||
con->socket_fd = -1;
|
||||
if (con->socket_fd != -1) {
|
||||
close(con->socket_fd);
|
||||
con->socket_fd = -1;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -260,6 +263,11 @@ MHD_accept_connection(struct MHD_Daemon * daemon) {
|
||||
* Free resources associated with all closed sessions.
|
||||
* (destroy responses, free buffers, etc.). A session
|
||||
* is known to be closed if the socket_fd is -1.
|
||||
*
|
||||
* Also performs session actions that need to be run
|
||||
* even if the session is not selectable (such as
|
||||
* calling the application again with upload data when
|
||||
* the upload data buffer is full).
|
||||
*/
|
||||
static void
|
||||
MHD_cleanup_sessions(struct MHD_Daemon * daemon) {
|
||||
@@ -295,6 +303,13 @@ MHD_cleanup_sessions(struct MHD_Daemon * daemon) {
|
||||
MHD_destroy_response(pos->response);
|
||||
free(pos);
|
||||
}
|
||||
|
||||
if ( (pos->headersReceived == 1) &&
|
||||
(pos->read_buffer_size == pos->readLoc) &&
|
||||
(pos->readLoc > 0) )
|
||||
MHD_call_session_handler(pos);
|
||||
|
||||
|
||||
prev = pos;
|
||||
pos = pos->next;
|
||||
}
|
||||
|
||||
+85
-47
@@ -109,7 +109,9 @@ MHD_queue_response(struct MHD_Session * session,
|
||||
struct MHD_Response * response) {
|
||||
if ( (session == NULL) ||
|
||||
(response == NULL) ||
|
||||
(session->response != NULL) )
|
||||
(session->response != NULL) ||
|
||||
(session->bodyReceived == 0) ||
|
||||
(session->headers_received == 0) )
|
||||
return MHD_NO;
|
||||
MHD_increment_response_rc(response);
|
||||
session->response = response;
|
||||
@@ -129,13 +131,15 @@ MHD_session_get_fdset(struct MHD_Session * session,
|
||||
fd_set * write_fd_set,
|
||||
fd_set * except_fd_set,
|
||||
int * max_fd) {
|
||||
/* FIXME: need to be VERY careful here
|
||||
determining when the socket is ready for
|
||||
reading/writing; plenty of cases to handle!
|
||||
(the current code is one big bug) */
|
||||
FD_SET(session->socket_fd, read_fd_set);
|
||||
FD_SET(session->socket_fd, write_fd_set);
|
||||
if (session->socket_fd > *max_fd)
|
||||
if ( (session->headers_received == 0) ||
|
||||
(session->readLoc < session->read_buffer_size) )
|
||||
FD_SET(session->socket_fd, read_fd_set);
|
||||
if (session->response != NULL)
|
||||
FD_SET(session->socket_fd, write_fd_set);
|
||||
if ( (session->socket_fd > *max_fd) &&
|
||||
( (session->headers_received == 0) ||
|
||||
(session->readLoc < session->read_buffer_size) ||
|
||||
(session->response != NULL) ) )
|
||||
*max_fd = session->socket_fd;
|
||||
return MHD_YES;
|
||||
}
|
||||
@@ -233,6 +237,7 @@ MHD_parse_session_headers(struct MHD_Session * session) {
|
||||
httpType = strstr(uri, " ");
|
||||
if (httpType != NULL)
|
||||
httpType[0] = '\0';
|
||||
/* FIXME: parse URI some more here */
|
||||
session->url = strdup(uri);
|
||||
/* do we want to do anything with httpType? */
|
||||
free(line);
|
||||
@@ -267,9 +272,9 @@ MHD_parse_session_headers(struct MHD_Session * session) {
|
||||
hdr->kind = MHD_HEADER_KIND;
|
||||
session->headers_received = hdr;
|
||||
}
|
||||
/* FIXME: here: find cookie header and parse that! */
|
||||
if (session->bodyReceived == 0)
|
||||
return;
|
||||
/* FIXME: here: find cookie header and parse that! */
|
||||
return;
|
||||
DIE:
|
||||
close(session->socket_fd);
|
||||
@@ -294,6 +299,48 @@ MHD_find_access_handler(struct MHD_Session * session) {
|
||||
return &session->daemon->default_handler;
|
||||
}
|
||||
|
||||
/**
|
||||
* Call the handler of the application for this
|
||||
* session.
|
||||
*/
|
||||
void
|
||||
MHD_call_session_handler(struct MHD_Session * session) {
|
||||
struct MHD_Access_Handler * ah;
|
||||
unsigned int processed;
|
||||
|
||||
if (session->headers_received == 0)
|
||||
abort(); /* bad timing... */
|
||||
ah = MHD_find_access_handler(session);
|
||||
processed = session->readLoc;
|
||||
if (MHD_NO == ah->dh(ah->dh_cls,
|
||||
session,
|
||||
session->url,
|
||||
session->method,
|
||||
session->read_buffer,
|
||||
&processed)) {
|
||||
/* serios internal error, close connection */
|
||||
MHD_DLOG(session->daemon,
|
||||
"Internal application error, closing connection.");
|
||||
close(session->socket_fd);
|
||||
session->socket_fd = -1;
|
||||
return;
|
||||
}
|
||||
/* dh left "processed" bytes in buffer for next time... */
|
||||
memmove(session->read_buffer,
|
||||
&session->read_buffer[session->readLoc - processed],
|
||||
processed);
|
||||
session->readLoc = processed;
|
||||
session->uploadSize -= processed;
|
||||
if (session->uploadSize == 0) {
|
||||
session->bodyReceived = 1;
|
||||
session->readLoc = 0;
|
||||
session->read_buffer_size = 0;
|
||||
free(session->read_buffer);
|
||||
session->read_buffer = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* This function handles a particular connection when it has been
|
||||
* determined that there is data to be read off a socket. All implementations
|
||||
@@ -304,16 +351,10 @@ int
|
||||
MHD_session_handle_read(struct MHD_Session * session) {
|
||||
int bytes_read;
|
||||
void * tmp;
|
||||
struct MHD_Access_Handler * ah;
|
||||
unsigned int processed;
|
||||
|
||||
|
||||
if (session->bodyReceived) {
|
||||
MHD_DLOG(session->daemon,
|
||||
"Unexpected call to %s.\n",
|
||||
__FUNCTION__);
|
||||
return MHD_NO;
|
||||
}
|
||||
if (session->readLoc >= session->read_buffer_size) {
|
||||
if ( (session->readLoc >= session->read_buffer_size) &&
|
||||
(session->headers_received == 0) ) {
|
||||
/* need to grow read buffer */
|
||||
tmp = malloc(session->read_buffer_size * 2 + MHD_MAX_BUF_SIZE);
|
||||
memcpy(tmp,
|
||||
@@ -321,6 +362,12 @@ MHD_session_handle_read(struct MHD_Session * session) {
|
||||
session->read_buffer_size);
|
||||
session->read_buffer_size = session->read_buffer_size * 2 + MHD_MAX_BUF_SIZE;
|
||||
}
|
||||
if (session->readLoc >= session->read_buffer_size) {
|
||||
MHD_DLOG(session->daemon,
|
||||
"Unexpected call to %s.\n",
|
||||
__FUNCTION__);
|
||||
return MHD_NO;
|
||||
}
|
||||
bytes_read = recv(session->socket_fd,
|
||||
&session->read_buffer[session->readLoc],
|
||||
session->read_buffer_size - session->readLoc,
|
||||
@@ -331,39 +378,24 @@ MHD_session_handle_read(struct MHD_Session * session) {
|
||||
MHD_DLOG(session->daemon,
|
||||
"Failed to receive data: %s\n",
|
||||
strerror(errno));
|
||||
return MHD_NO;
|
||||
close(session->socket_fd);
|
||||
session->socket_fd = -1;
|
||||
return MHD_YES;
|
||||
}
|
||||
if (bytes_read == 0) {
|
||||
/* other side closed connection */
|
||||
/* FIXME: proper handling of end of upload!
|
||||
If we were receiving an unbounded upload,
|
||||
we should finish up nicely now! */
|
||||
close(session->socket_fd);
|
||||
session->socket_fd = -1;
|
||||
return MHD_NO;
|
||||
return MHD_YES;
|
||||
}
|
||||
session->readLoc += bytes_read;
|
||||
if (session->headersReceived == 0)
|
||||
MHD_parse_session_headers(session);
|
||||
if (session->headersReceived == 1) {
|
||||
ah = MHD_find_access_handler(session);
|
||||
processed = session->readLoc;
|
||||
if (MHD_NO == ah->dh(ah->dh_cls,
|
||||
session,
|
||||
session->url,
|
||||
session->method,
|
||||
session->read_buffer,
|
||||
&processed)) {
|
||||
/* serios error, close connection */
|
||||
close(session->socket_fd);
|
||||
session->socket_fd = -1;
|
||||
return MHD_NO;
|
||||
}
|
||||
/* dh left "processed" bytes in buffer for next time... */
|
||||
memmove(session->read_buffer,
|
||||
&session->read_buffer[session->readLoc - processed],
|
||||
processed);
|
||||
session->readLoc = processed;
|
||||
session->uploadSize -= processed;
|
||||
/* FIXME: proper handling of end of upload! */
|
||||
}
|
||||
if (session->headersReceived == 1)
|
||||
MHD_call_session_handler(session);
|
||||
return MHD_YES;
|
||||
}
|
||||
|
||||
@@ -447,7 +479,7 @@ MHD_session_handle_write(struct MHD_Session * session) {
|
||||
strerror(errno));
|
||||
close(session->socket_fd);
|
||||
session->socket_fd = -1;
|
||||
return MHD_NO;
|
||||
return MHD_YES;
|
||||
}
|
||||
session->writeLoc += ret;
|
||||
if (session->writeLoc == session->write_buffer_size) {
|
||||
@@ -489,7 +521,7 @@ MHD_session_handle_write(struct MHD_Session * session) {
|
||||
response->data_start = session->messagePos;
|
||||
response->data_size = ret;
|
||||
if (ret == 0)
|
||||
return MHD_YES; /* or NO? */
|
||||
return MHD_YES;
|
||||
}
|
||||
|
||||
/* transmit */
|
||||
@@ -499,17 +531,23 @@ MHD_session_handle_write(struct MHD_Session * session) {
|
||||
0);
|
||||
if (response->crc != NULL)
|
||||
pthread_mutex_unlock(&response->mutex);
|
||||
if (ret == -1) {
|
||||
if (ret < 0) {
|
||||
if (errno == EINTR)
|
||||
return MHD_YES;
|
||||
MHD_DLOG(session->daemon,
|
||||
"Failed to send data: %s\n",
|
||||
strerror(errno));
|
||||
return MHD_NO;
|
||||
close(session->socket_fd);
|
||||
session->socket_fd = -1;
|
||||
return MHD_YES;
|
||||
}
|
||||
session->messagePos += ret;
|
||||
if (session->messagePos > response->data_size)
|
||||
abort(); /* internal error */
|
||||
if (session->messagePos == response->data_size) {
|
||||
/* reset session, wait for next request! */
|
||||
if ( (session->bodyReceived == 0) ||
|
||||
(session->headers_received == 0) )
|
||||
abort(); /* internal error */
|
||||
MHD_destroy_response(response);
|
||||
session->responseCode = 0;
|
||||
session->response = NULL;
|
||||
|
||||
@@ -43,6 +43,13 @@ MHD_session_get_fdset(struct MHD_Session * session,
|
||||
int * max_fd);
|
||||
|
||||
|
||||
/**
|
||||
* Call the handler of the application for this
|
||||
* session.
|
||||
*/
|
||||
void
|
||||
MHD_call_session_handler(struct MHD_Session * session);
|
||||
|
||||
/**
|
||||
* This function handles a particular connection when it has been
|
||||
* determined that there is data to be read off a socket. All implementations
|
||||
|
||||
Reference in New Issue
Block a user