From a97567ce8a5c4cdde3248b189c76323cab88551a Mon Sep 17 00:00:00 2001 From: =?utf8?q?Petr=20P=C3=ADsa=C5=99?= Date: Sun, 16 Dec 2012 18:22:28 +0100 Subject: [PATCH] test: server: Pass http_connection to HTTP funcation --- test/simline/http.c | 138 ++++++++++++++++--------------- test/simline/http.h | 72 ++++++++++------- test/simline/server.c | 216 ++++++++++++++++++++++++++----------------------- test/simline/server.h | 19 ++--- test/simline/service.c | 75 +++++++++-------- test/simline/service.h | 3 +- 6 files changed, 287 insertions(+), 236 deletions(-) diff --git a/test/simline/http.c b/test/simline/http.c index 3a685ee..3f255a1 100644 --- a/test/simline/http.c +++ b/test/simline/http.c @@ -230,14 +230,8 @@ static char *uri_decode(const char *coded) { } -/* Call-backs set by application */ -http_recv_callback_t http_recv_callback = NULL; -http_send_callback_t http_send_callback = NULL; -void *http_recv_context = NULL; -void *http_send_context = NULL; - /* Read a line from HTTP socket. - * @socket is descriptor to read from. + * @connection is HTTP connection to read from. * @line is auto-allocated just read line. Will be NULL if EOF has been * reached or error occured. * @buffer is automatically reallocated buffer for the socket. It can preserve @@ -245,14 +239,17 @@ void *http_send_context = NULL; * @buffer_size is allocated size of @buffer * @buffer_length is size of head of the buffer that holds read data. * @return 0 in success. */ -static int http_read_line(int socket, char **line, - char **buffer, size_t *buffer_size, size_t *buffer_used) { +static int http_read_line(const struct http_connection *connection, + char **line, char **buffer, size_t *buffer_size, + size_t *buffer_used) { ssize_t got; char *p, *tmp; if (line == NULL) return HTTP_ERROR_SERVER; *line = NULL; + if (connection == NULL || connection->recv_callback == NULL) + return HTTP_ERROR_SERVER; if (buffer == NULL || buffer_size == NULL || buffer_used == NULL) return HTTP_ERROR_SERVER; if (*buffer == NULL && *buffer_size > 0) return HTTP_ERROR_SERVER; @@ -294,8 +291,8 @@ static int http_read_line(int socket, char **line, } /* Read data */ - got = http_recv_callback(http_recv_context, *buffer + *buffer_used, - *buffer_size - *buffer_used, 0); + got = connection->recv_callback(connection, *buffer + *buffer_used, + *buffer_size - *buffer_used); if (got == -1) return HTTP_ERROR_CLIENT; /* Check for EOF */ @@ -311,19 +308,21 @@ static int http_read_line(int socket, char **line, /* Write a bulk data into HTTP socket. - * @socket is descriptor to write to. + * @connection is HTTP connection to write to. * @data are bitstream to send to client. * @length is size of @data in bytes. * @return 0 in success. */ -static int http_write_bulk(int socket, const void *data, size_t length) { +static int http_write_bulk(const struct http_connection *connection, + const void *data, size_t length) { ssize_t written; const void *end; + if (connection == NULL || connection->send_callback == NULL) + return HTTP_ERROR_SERVER; if (data == NULL && length > 0) return HTTP_ERROR_SERVER; for (end = data + length; data != end; data += written, length -= written) { - written = http_send_callback(http_send_context, data, length, - MSG_NOSIGNAL); + written = connection->send_callback(connection, data, length); if (written == -1) return HTTP_ERROR_CLIENT; } @@ -332,21 +331,22 @@ static int http_write_bulk(int socket, const void *data, size_t length) { /* Write a line into HTTP socket. - * @socket is descriptor to write to. + * @connection is HTTP connection to write to. * @line is NULL terminated string to send to client. HTTP EOL will be added. * @return 0 in success. */ -static int http_write_line(int socket, const char *line) { +static int http_write_line(const struct http_connection *connection, + const char *line) { int error; if (line == NULL) return HTTP_ERROR_SERVER; fprintf(stderr, "Response: <%s>\n", line); /* Send the line */ - if ((error = http_write_bulk(socket, line, strlen(line)))) + if ((error = http_write_bulk(connection, line, strlen(line)))) return error; /* Send EOL */ - if ((error = http_write_bulk(socket, "\r\n", 2))) + if ((error = http_write_bulk(connection, "\r\n", 2))) return error; return HTTP_ERROR_SUCCESS; @@ -354,7 +354,7 @@ static int http_write_line(int socket, const char *line) { /* Read data of given length from HTTP socket. - * @socket is descriptor to read from. + * @connection is HTTP connection to read from. * @data is auto-allocated just read data bulk. Will be NULL if EOF has been * reached or error occured. * @data_length is size of bytes to read. @@ -363,7 +363,8 @@ static int http_write_line(int socket, const char *line) { * @buffer_size is allocated size of @buffer * @buffer_length is size of head of the buffer that holds read data. * @return 0 in success. */ -static int http_read_bulk(int socket, void **data, size_t data_length, +static int http_read_bulk(const struct http_connection *connection, + void **data, size_t data_length, char **buffer, size_t *buffer_size, size_t *buffer_used) { ssize_t got; char *tmp; @@ -371,6 +372,8 @@ static int http_read_bulk(int socket, void **data, size_t data_length, if (data == NULL) return HTTP_ERROR_SERVER; *data = NULL; + if (connection == NULL || connection->recv_callback == NULL) + return HTTP_ERROR_SERVER; if (buffer == NULL || buffer_size == NULL || buffer_used == NULL) return HTTP_ERROR_SERVER; if (*buffer == NULL && *buffer_size > 0) return HTTP_ERROR_SERVER; @@ -404,8 +407,8 @@ static int http_read_bulk(int socket, void **data, size_t data_length, } /* Read data */ - got = http_recv_callback(http_recv_context, *buffer + *buffer_used, - *buffer_size - *buffer_used, 0); + got = connection->recv_callback(connection, *buffer + *buffer_used, + *buffer_size - *buffer_used); if (got == -1) return HTTP_ERROR_CLIENT; /* Check for EOF */ @@ -456,7 +459,7 @@ static int http_parse_request_header(char *line, /* Send HTTP response status line to client. * @return 0 if success. */ -static int http_write_response_status(int socket, +static int http_write_response_status(const struct http_connection *connection, const struct http_response *response) { char *buffer = NULL; int error; @@ -466,7 +469,7 @@ static int http_write_response_status(int socket, if (-1 == test_asprintf(&buffer, "HTTP/1.0 %u %s", response->status, (response->reason == NULL) ? "" : response->reason)) return HTTP_ERROR_SERVER; - error = http_write_line(socket, buffer); + error = http_write_line(connection, buffer); free(buffer); return error; @@ -540,7 +543,8 @@ static int http_parse_header(char *line, struct http_request *request) { /* Send HTTP header to client. * @return 0 if success. */ -static int http_write_header(int socket, const struct http_header *header) { +static int http_write_header(const struct http_connection *connection, + const struct http_header *header) { char *buffer = NULL; int error; @@ -552,7 +556,7 @@ static int http_write_header(int socket, const struct http_header *header) { if (-1 == test_asprintf(&buffer, "%s: %s", header->name, (header->value == NULL) ? "" : header->value)) return HTTP_ERROR_SERVER; - error = http_write_line(socket, buffer); + error = http_write_line(connection, buffer); free(buffer); return error; @@ -605,11 +609,12 @@ static void dump_body(const void *data, size_t length) { } -/* Read a HTTP request from connected socket. +/* Read a HTTP request from connection. * @http_request is heap-allocated received HTTP request, * or NULL in case of error. * @return http_error code. */ -http_error http_read_request(int socket, struct http_request **request) { +http_error http_read_request(const struct http_connection *connection, + struct http_request **request) { char *line = NULL; char *buffer = NULL; size_t buffer_size = 0, buffer_used = 0; @@ -621,7 +626,7 @@ http_error http_read_request(int socket, struct http_request **request) { if (*request == NULL) return HTTP_ERROR_SERVER; /* Get request header */ - if ((error = http_read_line(socket, &line, &buffer, &buffer_size, + if ((error = http_read_line(connection, &line, &buffer, &buffer_size, &buffer_used))) goto leave; if ((error = http_parse_request_header(line, *request))) @@ -629,7 +634,7 @@ http_error http_read_request(int socket, struct http_request **request) { /* Get other headers */ while (1) { - if ((error = http_read_line(socket, &line, &buffer, &buffer_size, + if ((error = http_read_line(connection, &line, &buffer, &buffer_size, &buffer_used))) { fprintf(stderr, "Error while reading HTTP request line\n"); goto leave; @@ -652,7 +657,7 @@ http_error http_read_request(int socket, struct http_request **request) { fprintf(stderr, "Could not determine length of body\n"); goto leave; } - if ((error = http_read_bulk(socket, + if ((error = http_read_bulk(connection, &(*request)->body, (*request)->body_length, &buffer, &buffer_size, &buffer_used))) { fprintf(stderr, "Could not read request body\n"); @@ -670,37 +675,39 @@ leave: } -/* Write a HTTP response to connected socket. Auto-add Content-Length header. +/* Write a HTTP response to connection. Auto-add Content-Length header. * @return 0 in case of success. */ -int http_write_response(int socket, const struct http_response *response) { +int http_write_response(const struct http_connection *connection, + const struct http_response *response) { char *buffer = NULL; int error = -1; if (response == NULL) return HTTP_ERROR_SERVER; /* Status line */ - error = http_write_response_status(socket, response); + error = http_write_response_status(connection, response); if (error) return error; /* Headers */ for (struct http_header *header = response->headers; header != NULL; header = header->next) { - error = http_write_header(socket, header); + error = http_write_header(connection, header); if (error) return error; } if (-1 == test_asprintf(&buffer, "Content-Length: %u", response->body_length)) return HTTP_ERROR_SERVER; - error = http_write_line(socket, buffer); + error = http_write_line(connection, buffer); if (error) return error; /* Headers trailer */ - error = http_write_line(socket, ""); + error = http_write_line(connection, ""); if (error) return error; /* Body */ if (response->body_length > 0) { - error = http_write_bulk(socket, response->body, response->body_length); + error = http_write_bulk(connection, response->body, + response->body_length); if (error) return error; } fprintf(stderr, "Body of size %zu B has been sent:\n", @@ -757,7 +764,7 @@ ok: /* Send a 200 Ok response with a cookie */ -int http_send_response_200_cookie(int client_socket, +int http_send_response_200_cookie(const struct http_connection *connection, const char *cokie_name, const char *cookie_value, const char *cookie_domain, const char *cookie_path, const void *body, size_t body_length, const char *type) { @@ -779,7 +786,7 @@ int http_send_response_200_cookie(int client_socket, if (cokie_name != NULL) { if (NULL == (header_cookie = http_build_setcookie_header( cokie_name, cookie_value, cookie_domain, cookie_path))) - return http_send_response_500(client_socket, + return http_send_response_500(connection, "Could not build Set-Cookie header"); } @@ -792,25 +799,26 @@ int http_send_response_200_cookie(int client_socket, response.headers = header_cookie; } - retval = http_write_response(client_socket, &response); + retval = http_write_response(connection, &response); http_header_free(&header_cookie); return retval; } /* Send a 200 Ok response */ -int http_send_response_200(int client_socket, +int http_send_response_200(const struct http_connection *connection, const void *body, size_t body_length, const char *type) { - return http_send_response_200_cookie(client_socket, + return http_send_response_200_cookie(connection, NULL, NULL, NULL, NULL, body, body_length, type); } /* Send a 302 Found response setting a cookie */ -int http_send_response_302_cookie(int client_socket, const char *cokie_name, - const char *cookie_value, const char *cookie_domain, - const char *cookie_path, const char *location) { +int http_send_response_302_cookie(const struct http_connection *connection, + const char *cokie_name, const char *cookie_value, + const char *cookie_domain, const char *cookie_path, + const char *location) { int retval; struct http_header *header_cookie = NULL; struct http_header header_location = { @@ -829,7 +837,7 @@ int http_send_response_302_cookie(int client_socket, const char *cokie_name, if (cokie_name != NULL) { if (NULL == (header_cookie = http_build_setcookie_header( cokie_name, cookie_value, cookie_domain, cookie_path))) - return http_send_response_500(client_socket, + return http_send_response_500(connection, "Could not build Set-Cookie header"); } @@ -842,14 +850,14 @@ int http_send_response_302_cookie(int client_socket, const char *cokie_name, response.headers = header_cookie; } - retval = http_write_response(client_socket, &response); + retval = http_write_response(connection, &response); http_header_free(&header_cookie); return retval; } /* Send a 302 Found response with totp authentication scheme header */ -int http_send_response_302_totp(int client_socket, +int http_send_response_302_totp(const struct http_connection *connection, const char *code, const char *text, const char *location) { struct http_header header_code = { .name = "X-Response-message-code", @@ -887,13 +895,14 @@ int http_send_response_302_totp(int client_socket, response.headers = &header_code; } - return http_write_response(client_socket, &response); + return http_write_response(connection, &response); } /* Send a 400 Bad Request response. * Use non-NULL @reason to override status message. */ -int http_send_response_400(int client_socket, const char *reason) { +int http_send_response_400(const struct http_connection *connection, + const char *reason) { struct http_response response = { .status = 400, .reason = (reason == NULL) ? "Bad Request" : (char *) reason, @@ -902,12 +911,12 @@ int http_send_response_400(int client_socket, const char *reason) { .body = NULL }; - return http_write_response(client_socket, &response); + return http_write_response(connection, &response); } /* Send a 401 Unauthorized response with Basic authentication scheme header */ -int http_send_response_401_basic(int client_socket) { +int http_send_response_401_basic(const struct http_connection *connection) { struct http_header header = { .name = "WWW-Authenticate", .value = "Basic realm=\"SimulatedISDSServer\"", @@ -921,13 +930,13 @@ int http_send_response_401_basic(int client_socket) { .body = NULL }; - return http_write_response(client_socket, &response); + return http_write_response(connection, &response); } /* Send a 401 Unauthorized response with OTP authentication scheme header for * given @method. */ -int http_send_response_401_otp(int client_socket, +int http_send_response_401_otp(const struct http_connection *connection, const char *method, const char *code, const char *text) { int retval; struct http_header header = { @@ -955,7 +964,7 @@ int http_send_response_401_otp(int client_socket, if (-1 == test_asprintf(&header.value, "%s realm=\"SimulatedISDSServer\"", method)) { - return http_send_response_500(client_socket, + return http_send_response_500(connection, "Could not build WWW-Authenticate header value"); } @@ -968,14 +977,14 @@ int http_send_response_401_otp(int client_socket, header.next = &header_text; } - retval = http_write_response(client_socket, &response); + retval = http_write_response(connection, &response); free(header.value); return retval; } /* Send a 403 Forbidden response */ -int http_send_response_403(int client_socket) { +int http_send_response_403(const struct http_connection *connection) { struct http_response response = { .status = 403, .reason = "Forbidden", @@ -984,13 +993,14 @@ int http_send_response_403(int client_socket) { .body = NULL }; - return http_write_response(client_socket, &response); + return http_write_response(connection, &response); } /* Send a 500 Internal Server Error response. * Use non-NULL @reason to override status message. */ -int http_send_response_500(int client_socket, const char *reason) { +int http_send_response_500(const struct http_connection *connection, + const char *reason) { struct http_response response = { .status = 500, .reason = (NULL == reason) ? "Internal Server Error" : (char *) reason, @@ -999,12 +1009,12 @@ int http_send_response_500(int client_socket, const char *reason) { .body = NULL }; - return http_write_response(client_socket, &response); + return http_write_response(connection, &response); } /* Send a 503 Service Temporarily Unavailable response */ -int http_send_response_503(int client_socket, +int http_send_response_503(const struct http_connection *connection, const void *body, size_t body_length, const char *type) { struct http_header header = { .name = "Content-Type", @@ -1018,7 +1028,7 @@ int http_send_response_503(int client_socket, .body = (void *)body }; - return http_write_response(client_socket, &response); + return http_write_response(connection, &response); } diff --git a/test/simline/http.h b/test/simline/http.h index 4b31bfd..6799464 100644 --- a/test/simline/http.h +++ b/test/simline/http.h @@ -3,21 +3,32 @@ #include +/* Forward declarations */ +struct http_connection; + /* Call-back type for non-interrupting receiving from socket. See recv(2). - * @context is opaque pointer passed to the call-back. */ -typedef ssize_t (*http_recv_callback_t) (void *context, void *buffer, - size_t length, int flags); -/* Application must set these pointers. */ -extern http_recv_callback_t http_recv_callback; -extern void *http_recv_context; + * @buffer is data to send by the call-back + * @lentgh is number of bytes to send + * @connection carries socket and callback_data. */ +typedef ssize_t (*http_recv_callback_t) ( + const struct http_connection *connection, void *buffer, size_t length); /* Call-back type for non-interrupting sending to socket. See send(2). - * @context is opaque pointer passed to the call-back. */ -typedef ssize_t (*http_send_callback_t) (void *context, const void *buffer, - size_t length, int flags); -/* Application must set these pointers. */ -extern http_send_callback_t http_send_callback; -extern void *http_send_context; + * @buffer is memory to store received data by the call-back + * @lentgh is size of the @buffer in bytes + * @connection carries socket and callback_data. */ +typedef ssize_t (*http_send_callback_t) ( + const struct http_connection *connection, const void *buffer, + size_t length); + +struct http_connection { + int socket; /* Accepted TCP client socket */ + http_recv_callback_t recv_callback; /* Non-interrupting reading + from socket */ + http_send_callback_t send_callback; /* Non-interrupting writing + to socket */ + void *callback_data; /* Pointer to pass to callbacks */ +}; typedef enum { HTTP_ERROR_SERVER = -1, @@ -65,56 +76,61 @@ void http_request_free(struct http_request **request); /* Free HTTP response and set it to NULL */ void http_response_free(struct http_response **response); -/* Read a HTTP request from connected socket. +/* Read a HTTP request from connection. * @http_request is heap-allocated received HTTP request, * or NULL in case of error. * @return http_error code. */ -http_error http_read_request(int socket, struct http_request **request); +http_error http_read_request(const struct http_connection *connection, + struct http_request **request); -/* Write a HTTP response to connected socket. Auto-add Content-Length header. +/* Write a HTTP response to connection. Auto-add Content-Length header. * @return 0 in case of success. */ -int http_write_response(int socket, const struct http_response *response); +int http_write_response(const struct http_connection *connection, + const struct http_response *response); /* Send a 200 Ok response with a cookie */ -int http_send_response_200_cookie(int client_socket, +int http_send_response_200_cookie(const struct http_connection *connection, const char *cokie_name, const char *cookie_value, const char *cookie_domain, const char *cookie_path, const void *body, size_t body_length, const char *type); /* Send a 200 Ok response */ -int http_send_response_200(int client_socket, +int http_send_response_200(const struct http_connection *connection, const void *body, size_t body_length, const char *type); /* Send a 302 Found response setting a cookie */ -int http_send_response_302_cookie(int client_socket, const char *cokie_name, - const char *cookie_value, const char *cookie_domain, - const char *cookie_path, const char *location); +int http_send_response_302_cookie(const struct http_connection *connection, + const char *cokie_name, const char *cookie_value, + const char *cookie_domain, const char *cookie_path, + const char *location); /* Send a 302 Found response with totp authentication scheme header */ -int http_send_response_302_totp(int client_socket, +int http_send_response_302_totp(const struct http_connection *connection, const char *code, const char *text, const char *location); /* Send a 400 Bad Request response. * Use non-NULL @reason to override status message. */ -int http_send_response_400(int client_socket, const char *reason); +int http_send_response_400(const struct http_connection *connection, + const char *reason); /* Send a 401 Unauthorized response with Basic authentication scheme header */ -int http_send_response_401_basic(int client_socket); +int http_send_response_401_basic(const struct http_connection *connection); /* Send a 401 Unauthorized response with OTP authentication scheme header for * given @method. */ -int http_send_response_401_otp(int client_socket, +int http_send_response_401_otp(const struct http_connection *connection, const char *method, const char *code, const char *text); /* Send a 403 Forbidden response */ -int http_send_response_403(int client_socket); +int http_send_response_403(const struct http_connection *connection); /* Send a 500 Internal Server Error response. * Use non-NULL @reason to override status message. */ -int http_send_response_500(int client_socket, const char *reason); +int http_send_response_500(const struct http_connection *connection, + const char *reason); /* Send a 503 Service Temporarily Unavailable response */ -int http_send_response_503(int client_socket, +int http_send_response_503(const struct http_connection *connection, const void *body, size_t body_length, const char *type); /* Returns true if request carries WWW-Authenticate header */ diff --git a/test/simline/server.c b/test/simline/server.c index 885dee5..d36a220 100644 --- a/test/simline/server.c +++ b/test/simline/server.c @@ -126,13 +126,13 @@ char *socket2address(int socket) { /* Process ISDS web service */ -static void do_ws(int client_socket, +static void do_ws(const struct http_connection *connection, const struct service_configuration *ws_configuration, const struct http_request *request, const char *required_base_path) { char *end_point = request->uri; /* Pointer to string in the request */ if (request->method != HTTP_METHOD_POST) { - http_send_response_400(client_socket, + http_send_response_400(connection, "Regular ISDS web service request must be POST"); return; } @@ -140,24 +140,23 @@ static void do_ws(int client_socket, if (required_base_path != NULL) { size_t required_base_path_length = strlen(required_base_path); if (strncmp(end_point, required_base_path, required_base_path_length)) { - http_send_response_400(client_socket, - "Request sent to invalid path"); + http_send_response_400(connection, "Request sent to invalid path"); return; } end_point += required_base_path_length; } - soap(client_socket, ws_configuration, request->body, request->body_length, + soap(connection, ws_configuration, request->body, request->body_length, end_point); } /* Do the server protocol. - * @client_socket is accpeted TCP socket + * @connection is HTTP connection * @server_arguments is pointer to structure: * @request is parsed HTTP client request * @return 0 to accept new client, return -1 in case of fatal error. */ -int server_basic_authentication(int client_socket, +int server_basic_authentication(const struct http_connection *connection, const void *server_arguments, const struct http_request *request) { const struct arguments_basic_authentication *arguments = (const struct arguments_basic_authentication *) server_arguments; @@ -173,30 +172,30 @@ int server_basic_authentication(int client_socket, switch(http_authenticate_basic(request, arguments->username, arguments->password)) { case HTTP_ERROR_SUCCESS: - do_ws(client_socket, arguments->services, request, + do_ws(connection, arguments->services, request, ws_base_path_basic); break; case HTTP_ERROR_CLIENT: if (arguments->isds_deviations) - http_send_response_401_basic(client_socket); + http_send_response_401_basic(connection); else - http_send_response_403(client_socket); + http_send_response_403(connection); break; default: - http_send_response_500(client_socket, + http_send_response_500(connection, "Server error while verifying Basic " "authentication"); } } else { - http_send_response_401_basic(client_socket); + http_send_response_401_basic(connection); } } else { - do_ws(client_socket, arguments->services, request, + do_ws(connection, arguments->services, request, ws_base_path_basic); } } else { /* HTTP method unsupported per ISDS specification */ - http_send_response_400(client_socket, + http_send_response_400(connection, "Only POST method is allowed"); } @@ -205,22 +204,23 @@ int server_basic_authentication(int client_socket, /* Process first phase of TOTP request */ -static void do_as_sendsms(int client_socket, const struct http_request *request, +static void do_as_sendsms(const struct http_connection *connection, + const struct http_request *request, const struct arguments_otp_authentication *arguments) { if (arguments == NULL) { - http_send_response_500(client_socket, + http_send_response_500(connection, "Third argument of do_as_sendsms() is NULL"); return; } if (request->method != HTTP_METHOD_POST) { - http_send_response_400(client_socket, + http_send_response_400(connection, "First phase TOTP request must be POST"); return; } if (!http_client_authenticates(request)) { - http_send_response_401_otp(client_socket, + http_send_response_401_otp(connection, "totpsendsms", "authentication.error.userIsNotAuthenticated", "Client did not send any authentication header"); @@ -233,7 +233,7 @@ static void do_as_sendsms(int client_socket, const struct http_request *request, /* Find final URI */ char *uri = strstr(request->uri, "&uri="); if (uri == NULL) { - http_send_response_400(client_socket, + http_send_response_400(connection, "Missing uri parameter in Request URI"); return; } @@ -241,7 +241,7 @@ static void do_as_sendsms(int client_socket, const struct http_request *request, /* Build new location for second OTP phase */ char *location = NULL; if (-1 == test_asprintf(&location, "%s%s", as_path_dontsendsms, uri)) { - http_send_response_500(client_socket, + http_send_response_500(connection, "Could not build new localtion for " "second OTP phase"); return; @@ -249,7 +249,7 @@ static void do_as_sendsms(int client_socket, const struct http_request *request, char *terminator = strchr(uri, '&'); if (NULL != terminator) location[strlen(as_path_dontsendsms) + (uri - terminator)] = '\0'; - http_send_response_302_totp(client_socket, + http_send_response_302_totp(connection, "authentication.info.totpSended", "=?UTF-8?B?SmVkbm9yw6F6b3bDvSBrw7NkIG9kZXNsw6FuLg==?=", location); @@ -258,7 +258,7 @@ static void do_as_sendsms(int client_socket, const struct http_request *request, break; case HTTP_ERROR_CLIENT: if (arguments->isds_deviations) - http_send_response_401_otp(client_socket, + http_send_response_401_otp(connection, "totpsendsms", "authentication.error.userIsNotAuthenticated", " Retry: Bad user name or password in first OTP phase.\r\n" @@ -266,10 +266,10 @@ static void do_as_sendsms(int client_socket, const struct http_request *request, " which should span to more lines.\r\n" " Surrounding LWS are meaning-less. "); else - http_send_response_403(client_socket); + http_send_response_403(connection); break; default: - http_send_response_500(client_socket, + http_send_response_500(connection, "Could not verify Basic authentication"); } } @@ -287,22 +287,23 @@ static const char *auth_otp_method2string(enum auth_otp_method method) { /* Process second phase of OTP request */ -static void do_as_phase_two(int client_socket, const struct http_request *request, +static void do_as_phase_two(const struct http_connection *connection, + const struct http_request *request, const struct arguments_otp_authentication *arguments) { if (arguments == NULL) { - http_send_response_500(client_socket, + http_send_response_500(connection, "Third argument of do_as_phase_two() is NULL"); return; } if (request->method != HTTP_METHOD_POST) { - http_send_response_400(client_socket, + http_send_response_400(connection, "Second phase OTP request must be POST"); return; } if (!http_client_authenticates(request)) { - http_send_response_401_otp(client_socket, + http_send_response_401_otp(connection, auth_otp_method2string(arguments->method), "authentication.error.userIsNotAuthenticated", "Client did not send any authentication header"); @@ -315,7 +316,7 @@ static void do_as_phase_two(int client_socket, const struct http_request *reques /* Find final URI */ char *uri = strstr(request->uri, "&uri="); if (uri == NULL) { - http_send_response_400(client_socket, + http_send_response_400(connection, "Missing uri parameter in Request URI"); return; } @@ -323,7 +324,7 @@ static void do_as_phase_two(int client_socket, const struct http_request *reques /* Build new location for final request */ char *location = NULL; if (NULL == (location = strdup(uri))) { - http_send_response_500(client_socket, + http_send_response_500(connection, "Could not build new location for final request"); return; } @@ -335,7 +336,7 @@ static void do_as_phase_two(int client_socket, const struct http_request *reques * same seed to get reproducible tests. */ if (-1 == test_asprintf(&authorization_cookie_value, "%d", rand())) { - http_send_response_500(client_socket, + http_send_response_500(connection, "Could not generate cookie value"); free(location); return; @@ -343,7 +344,7 @@ static void do_as_phase_two(int client_socket, const struct http_request *reques /* XXX: Add Path parameter to cookie, otherwise * different paths will not match. * FIXME: Domain argument does not work with cURL. Report a bug. */ - http_send_response_302_cookie(client_socket, + http_send_response_302_cookie(connection, authorization_cookie_name, authorization_cookie_value, /*http_find_host(request)*/NULL, @@ -354,7 +355,7 @@ static void do_as_phase_two(int client_socket, const struct http_request *reques break; case HTTP_ERROR_CLIENT: if (arguments->isds_deviations) - http_send_response_401_otp(client_socket, + http_send_response_401_otp(connection, auth_otp_method2string(arguments->method), "authentication.error.userIsNotAuthenticated", " Retry: Bad user name or password in second OTP phase.\r\n" @@ -362,10 +363,10 @@ static void do_as_phase_two(int client_socket, const struct http_request *reques " which should span to more lines.\r\n" " Surrounding LWS are meaning-less. "); else - http_send_response_403(client_socket); + http_send_response_403(connection); break; default: - http_send_response_500(client_socket, + http_send_response_500(connection, "Could not verify OTP authentication"); } } @@ -378,23 +379,23 @@ static void do_as_phase_two(int client_socket, const struct http_request *reques * decide which authentication to enforce without understadning request body. * I will just try both of them to choose the service. * But I hope official server implementation does it in more clever way. */ -static void do_asws(int client_socket, const struct http_request *request, +static void do_asws(const struct http_connection *connection, + const struct http_request *request, const struct arguments_otp_authentication *arguments) { http_error error; if (arguments == NULL) { - http_send_response_500(client_socket, + http_send_response_500(connection, "Third argument of do_asws() is NULL"); return; } if (request->method != HTTP_METHOD_POST) { - http_send_response_400(client_socket, - "ASWS request must be POST"); + http_send_response_400(connection, "ASWS request must be POST"); return; } if (!http_client_authenticates(request)) { - http_send_response_401_otp(client_socket, + http_send_response_401_otp(connection, auth_otp_method2string(arguments->method), "authentication.error.userIsNotAuthenticated", "Client did not send any authentication header"); @@ -407,7 +408,7 @@ static void do_asws(int client_socket, const struct http_request *request, if (HTTP_ERROR_SUCCESS == error) { /* This will be request for password change because OTP * authentication succeeded. */ - do_ws(client_socket, arguments->services, request, NULL); + do_ws(connection, arguments->services, request, NULL); return; } @@ -418,14 +419,14 @@ static void do_asws(int client_socket, const struct http_request *request, if (HTTP_ERROR_SUCCESS == error) { /* This will be request for time code for password change because * basic authentication succeeded. */ - do_ws(client_socket, arguments->services, request, NULL); + do_ws(connection, arguments->services, request, NULL); return; } } if (HTTP_ERROR_CLIENT == error) { if (arguments->isds_deviations) - http_send_response_401_otp(client_socket, + http_send_response_401_otp(connection, auth_otp_method2string(arguments->method), "authentication.error.userIsNotAuthenticated", " Retry: Bad user name or password in Authorization.\r\n" @@ -433,26 +434,27 @@ static void do_asws(int client_socket, const struct http_request *request, " which should span to more lines.\r\n" " Surrounding LWS are meaning-less. "); else - http_send_response_403(client_socket); + http_send_response_403(connection); return; } - http_send_response_500(client_socket, + http_send_response_500(connection, "Could not verify OTP authentication"); } /* Process OTP session cookie invalidation request */ -static void do_as_logout(int client_socket, const struct http_request *request, +static void do_as_logout(const struct http_connection *connection, + const struct http_request *request, const struct arguments_otp_authentication *arguments) { if (arguments == NULL) { - http_send_response_500(client_socket, + http_send_response_500(connection, "Third argument of do_as_logout() is NULL"); return; } if (request->method != HTTP_METHOD_GET) { - http_send_response_400(client_socket, + http_send_response_400(connection, "OTP cookie invalidation request must be GET"); return; } @@ -462,14 +464,14 @@ static void do_as_logout(int client_socket, const struct http_request *request, if (authorization_cookie_value == NULL || received_cookie == NULL || strcmp(authorization_cookie_value, received_cookie)) { - http_send_response_403(client_socket); + http_send_response_403(connection); return; } /* XXX: Add Path parameter to cookie, otherwise * different paths will not match. * FIXME: Domain argument does not work with cURL. Report a bug. */ - http_send_response_200_cookie(client_socket, + http_send_response_200_cookie(connection, authorization_cookie_name, "", /*http_find_host(request)*/ NULL, @@ -479,7 +481,7 @@ static void do_as_logout(int client_socket, const struct http_request *request, /* Process ISDS WS ping authorized by cookie */ -static void do_ws_with_cookie(int client_socket, +static void do_ws_with_cookie(const struct http_connection *connection, const struct http_request *request, const struct arguments_otp_authentication *arguments, const char *valid_base_path) { @@ -488,19 +490,19 @@ static void do_ws_with_cookie(int client_socket, if (authorization_cookie_value != NULL && received_cookie != NULL && !strcmp(authorization_cookie_value, received_cookie)) - do_ws(client_socket, arguments->services, request, valid_base_path); + do_ws(connection, arguments->services, request, valid_base_path); else - http_send_response_403(client_socket); + http_send_response_403(connection); } /* Do the server protocol with OTP authentication. - * @client_socket is accepted TCP socket + * @connection is HTTP connection * @server_arguments is pointer to structure arguments_otp_authentication. It * selects OTP method to enable. * @request is parsed HTTP client requrest * @return 0 to accept new client, return -1 in case of fatal error. */ -int server_otp_authentication(int client_socket, +int server_otp_authentication(const struct http_connection *connection, const void *server_arguments, const struct http_request *request) { const struct arguments_otp_authentication *arguments = (const struct arguments_otp_authentication *) server_arguments; @@ -512,33 +514,33 @@ int server_otp_authentication(int client_socket, if (arguments->username != NULL) { if (arguments->method == AUTH_OTP_HMAC && !strncmp(request->uri, as_path_hotp, strlen(as_path_hotp))) { - do_as_phase_two(client_socket, request, arguments); + do_as_phase_two(connection, request, arguments); } else if (arguments->method == AUTH_OTP_TIME && !strncmp(request->uri, as_path_sendsms, strlen(as_path_sendsms))) { - do_as_sendsms(client_socket, request, arguments); + do_as_sendsms(connection, request, arguments); } else if (arguments->method == AUTH_OTP_TIME && !strncmp(request->uri, as_path_dontsendsms, strlen(as_path_dontsendsms))) { - do_as_phase_two(client_socket, request, arguments); + do_as_phase_two(connection, request, arguments); } else if (!strncmp(request->uri, as_path_logout, strlen(as_path_logout))) { - do_as_logout(client_socket, request, arguments); + do_as_logout(connection, request, arguments); } else if (!strcmp(request->uri, asws_path)) { - do_asws(client_socket, request, arguments); + do_asws(connection, request, arguments); } else if (!strcmp(request->uri, ws_path)) { - do_ws_with_cookie(client_socket, request, arguments, + do_ws_with_cookie(connection, request, arguments, ws_base_path_otp); } else { - http_send_response_400(client_socket, + http_send_response_400(connection, "Unknown path for OTP authenticating service"); } } else { if (!strcmp(request->uri, ws_path)) { - do_ws(client_socket, arguments->services, request, + do_ws(connection, arguments->services, request, ws_base_path_otp); } else { - http_send_response_400(client_socket, + http_send_response_400(connection, "Unknown path for OTP authenticating service"); } } @@ -549,16 +551,16 @@ int server_otp_authentication(int client_socket, /* Implementation of server that is out of order. * It always sends back SOAP Fault with HTTP error 503. - * @client_socket is accepted TCP socket + * @connection is HTTP connection * @server_arguments is ununsed pointer * @request is parsed HTTP client request * @return 0 to accept new client, return -1 in case of fatal error. */ -int server_out_of_order(int client_socket, +int server_out_of_order(const struct http_connection *connection, const void *server_arguments, const struct http_request *request) { const char *soap_mime_type = "text/xml"; /* SOAP/1.1 requires text/xml */ const char *fault = "Probíhá plánovaná údržbaOmlouváme se všem uživatelům datových schránek za dočasné omezení přístupu do systému datových schránek z důvodu plánované údržby systému. Děkujeme za pochopení."; - http_send_response_503(client_socket, fault, strlen(fault), + http_send_response_503(connection, fault, strlen(fault), soap_mime_type); return 0; } @@ -566,11 +568,11 @@ int server_out_of_order(int client_socket, /* Call-back for HTTP to receive data from socket * API is equivalent to recv(2) except automatic interrupt handling. */ -static ssize_t recv_plain(void *context, void *buffer, size_t length, - int flags) { +static ssize_t recv_plain(const struct http_connection *connection, + void *buffer, size_t length) { ssize_t retval; do { - retval = recv(*(int *)context, buffer, length, flags); + retval = recv(connection->socket, buffer, length, 0); } while (-1 == retval && EINTR == errno); return retval; } @@ -578,11 +580,11 @@ static ssize_t recv_plain(void *context, void *buffer, size_t length, /* Call-back for HTTP to sending data to socket * API is equivalent to send(2) except automatic interrupt handling. */ -static ssize_t send_plain(void *context, const void *buffer, size_t length, - int flags) { +static ssize_t send_plain(const struct http_connection *connection, + const void *buffer, size_t length) { ssize_t retval; do { - retval = send(*(int *)context, buffer, length, flags); + retval = send(connection->socket, buffer, length, MSG_NOSIGNAL); } while (-1 == retval && EINTR == errno); return retval; } @@ -590,15 +592,15 @@ static ssize_t send_plain(void *context, const void *buffer, size_t length, /* Call-back for HTTP to receive data from TLS socket * API is equivalent to recv(2) except automatic interrupt handling. */ -static ssize_t recv_tls(void *context, void *buffer, size_t length, - int flags) { +static ssize_t recv_tls(const struct http_connection *connection, + void *buffer, size_t length) { ssize_t retval; do { - retval = gnutls_record_recv(context, buffer, length); + retval = gnutls_record_recv(connection->callback_data, buffer, length); if (GNUTLS_E_REHANDSHAKE == retval) { int error; do { - error = gnutls_handshake(context); + error = gnutls_handshake(connection->callback_data); } while (error < 0 && !gnutls_error_is_fatal(error)); if (error < 0) { fprintf(stderr, "TLS rehandshake failed: %s\n", @@ -613,21 +615,33 @@ static ssize_t recv_tls(void *context, void *buffer, size_t length, /* Call-back for HTTP to sending data to TLS socket * API is equivalent to send(2) except automatic interrupt handling. */ -static ssize_t send_tls(void *context, const void *buffer, size_t length, - int flags) { +static ssize_t send_tls(const struct http_connection *connection, + const void *buffer, size_t length) { ssize_t retval; do { - retval = gnutls_record_send(context, buffer, length); + retval = gnutls_record_send(connection->callback_data, buffer, length); } while (GNUTLS_E_INTERRUPTED == retval || GNUTLS_E_AGAIN == retval); return (retval < 0) ? -1 : retval; } +/* Call-back fot GnuTLS to receive data from TCP socket. + * We override default implementation to unify passing http_connection as + * @context. Also otherwise there is need for ugly type cast from integer to + * pointer. */ +static ssize_t tls_pull(gnutls_transport_ptr_t context, void* buffer, + size_t length) { + return recv( ((struct http_connection*)context)->socket, + buffer, length, 0); +} + + /* Call-back fot GnuTLS to send data to TCP socket. - * GnuTLS does not call send(2) with MSG_NOSIGNAL, we must do it manually */ + * GnuTLS does not call send(2) with MSG_NOSIGNAL, we must do it manually. */ static ssize_t tls_push(gnutls_transport_ptr_t context, const void* buffer, size_t length) { - return send((int)context, buffer, length, MSG_NOSIGNAL); + return send( ((struct http_connection*)context)->socket, + buffer, length, MSG_NOSIGNAL); } @@ -650,8 +664,8 @@ static ssize_t tls_push(gnutls_transport_ptr_t context, const void* buffer, * @tls sets TLS layer. Pass NULL for plain HTTP. * @return -1 in case of error. */ int start_server(pid_t *server_process, char **server_address, - int (*server_implementation)(int, const void *, - const struct http_request *), + int (*server_implementation)(const struct http_connection *, + const void *, const struct http_request *), const void *server_arguments, const struct tls_authentication *tls) { int server_socket; int error; @@ -782,6 +796,7 @@ int start_server(pid_t *server_process, char **server_address, if (*server_process == 0) { int client_socket; gnutls_session_t tls_session; + struct http_connection connection; struct http_request *request = NULL; http_error error; int terminate = 0; @@ -825,18 +840,20 @@ int start_server(pid_t *server_process, char **server_address, continue; } fprintf(stderr, "Connection accepted\n"); + connection.socket = client_socket; if (NULL == tls) { - http_recv_callback = recv_plain; - http_send_callback = send_plain; - http_recv_context = http_send_context = &client_socket; + connection.recv_callback = recv_plain; + connection.send_callback = send_plain; + connection.callback_data = NULL; } else { - /* XXX: The double type caset is to silent warning due to flaw - * GnuTLS API - * - */ - gnutls_transport_set_ptr(tls_session, - (gnutls_transport_ptr_t)(uintptr_t)client_socket); + connection.recv_callback = recv_tls; + connection.send_callback = send_tls; + connection.callback_data = tls_session; + gnutls_transport_set_pull_function(tls_session, tls_pull); + gnutls_transport_set_push_function(tls_session, tls_push); + gnutls_transport_set_ptr2(tls_session, + &connection, &connection); do { error = gnutls_handshake(tls_session); } while (error < 0 && !gnutls_error_is_fatal(error)); @@ -847,26 +864,23 @@ int start_server(pid_t *server_process, char **server_address, gnutls_deinit(tls_session); continue; } - http_recv_callback = recv_tls; - http_send_callback = send_tls; - http_recv_context = http_send_context = tls_session; - gnutls_transport_set_push_function(tls_session, tls_push); } - error = http_read_request(client_socket, &request); + error = http_read_request(&connection, &request); if (error) { fprintf(stderr, "Error while reading request\n"); if (error == HTTP_ERROR_CLIENT) - http_send_response_400(client_socket, "Error in request"); + http_send_response_400(&connection, "Error in request"); else - http_send_response_500(client_socket, "Could not read request"); + http_send_response_500(&connection, + "Could not read request"); close(client_socket); if (NULL != tls) gnutls_deinit(tls_session); continue; } - terminate = server_implementation(client_socket, server_arguments, + terminate = server_implementation(&connection, server_arguments, request); http_request_free(&request); diff --git a/test/simline/server.h b/test/simline/server.h index 1600c9d..5976192 100644 --- a/test/simline/server.h +++ b/test/simline/server.h @@ -5,7 +5,8 @@ #include "server_types.h" #include "services.h" -struct http_request; /* Declare opaque not to export http.h */ +struct http_connection; /* Declare opaque not to export http.h */ +struct http_request; /* Declare opaque not to export http.h */ extern char *server_error; /* Save error message if not yet set. The message will be duplicated. @@ -48,11 +49,11 @@ struct arguments_basic_authentication { }; /* Do the server protocol. - * @client_socket is accpeted TCP socket + * @connection is HTTP connection * @server_arguments is pointer to structure: * @request is parsed HTTP client request * @return 0 to accept new client, return -1 in case of fatal error. */ -int server_basic_authentication(int client_socket, +int server_basic_authentication(const struct http_connection *connection, const void *server_arguments, const struct http_request *request); @@ -73,21 +74,21 @@ struct arguments_otp_authentication { }; /* Do the server protocol with OTP authentication. - * @client_socket is accepted TCP socket + * @connection is HTTP connection * @server_arguments is pointer to structure arguments_otp_authentication. It * selects OTP method to enable. * @request is parsed HTTP client requrest * @return 0 to accept new client, return -1 in case of fatal error. */ -int server_otp_authentication(int client_socket, +int server_otp_authentication(const struct http_connection *connection, const void *server_arguments, const struct http_request *request); /* Implementation of server that is out of order. * It always sends back SOAP Fault with HTTP error 503. - * @client_socket is accepted TCP socket + * @connection is HTTP connection * @server_arguments is ununsed pointer * @request is parsed HTTP client request * @return 0 to accept new client, return -1 in case of fatal error. */ -int server_out_of_order(int client_socket, +int server_out_of_order(const struct http_connection *connection, const void *server_arguments, const struct http_request *request); @@ -110,8 +111,8 @@ int server_out_of_order(int client_socket, * @tls sets TLS layer. Pass NULL for plain HTTP. * @return -1 in case of error. */ int start_server(pid_t *server_process, char **server_address, - int (*server_implementation)(int, const void *, - const struct http_request *), + int (*server_implementation)(const struct http_connection *, + const void *, const struct http_request *), const void *server_arguments, const struct tls_authentication *tls); diff --git a/test/simline/service.c b/test/simline/service.c index 97fc140..6467327 100644 --- a/test/simline/service.c +++ b/test/simline/service.c @@ -38,8 +38,9 @@ struct service { const char *end_point; const xmlChar *name_space; const xmlChar *name; - http_error (*function) (int, xmlDocPtr, xmlXPathContextPtr, xmlNodePtr, - xmlDocPtr, xmlNodePtr, const void *arguments); + http_error (*function) (const struct http_connection *, xmlDocPtr, + xmlXPathContextPtr, xmlNodePtr, xmlDocPtr, xmlNodePtr, + const void *arguments); }; /* Following EXTRACT_* macros expect @xpath_ctx, @message, and leave label */ @@ -154,7 +155,8 @@ leave: /* Implement DummyOperation */ -static http_error service_DummyOperation(int socket, const xmlDocPtr soap_request, +static http_error service_DummyOperation( + const struct http_connection *connection, const xmlDocPtr soap_request, xmlXPathContextPtr xpath_ctx, xmlNodePtr isds_request, xmlDocPtr soap_response, xmlNodePtr isds_response, const void *arguments) { @@ -165,7 +167,7 @@ static http_error service_DummyOperation(int socket, const xmlDocPtr soap_reques /* Implement EraseMessage. * @arguments is pointer to struct arguments_DS_DsManage_ChangeISDSPassword */ -static http_error service_EraseMessage(int socket, +static http_error service_EraseMessage(const struct http_connection *connection, const xmlDocPtr soap_request, xmlXPathContextPtr xpath_ctx, const xmlNodePtr isds_request, xmlDocPtr soap_response, xmlNodePtr isds_response, @@ -359,7 +361,8 @@ leave: /* Implement ChangeISDSPassword. * @arguments is pointer to struct arguments_DS_DsManage_ChangeISDSPassword */ -static http_error service_ChangeISDSPassword(int socket, +static http_error service_ChangeISDSPassword( + const struct http_connection *connection, const xmlDocPtr soap_request, xmlXPathContextPtr xpath_ctx, const xmlNodePtr isds_request, xmlDocPtr soap_response, xmlNodePtr isds_response, @@ -394,7 +397,8 @@ leave: /* Implement ChangePasswordOTP. * @arguments is pointer to struct * arguments_asws_changePassword_ChangePasswordOTP */ -static http_error service_ChangePasswordOTP(int socket, +static http_error service_ChangePasswordOTP( + const struct http_connection *connection, const xmlDocPtr soap_request, xmlXPathContextPtr xpath_ctx, const xmlNodePtr isds_request, xmlDocPtr soap_response, xmlNodePtr isds_response, @@ -446,7 +450,8 @@ leave: /* Implement SendSMSCode. * @arguments is pointer to struct arguments_asws_changePassword_SendSMSCode */ -static http_error service_SendSMSCode(int socket, +static http_error service_SendSMSCode( + const struct http_connection *connection, const xmlDocPtr soap_request, xmlXPathContextPtr xpath_ctx, const xmlNodePtr isds_request, xmlDocPtr soap_response, xmlNodePtr isds_response, @@ -538,7 +543,8 @@ static int register_namespaces(xmlXPathContextPtr xpath_ctx, /* Parse soap request, pass it to service endpoint and respond to it. * It sends final HTTP response. */ -void soap(int socket, const struct service_configuration *configuration, +void soap(const struct http_connection *connection, + const struct service_configuration *configuration, const void *request, size_t request_length, const char *end_point) { xmlDocPtr request_doc = NULL; xmlXPathContextPtr xpath_ctx = NULL; @@ -555,32 +561,33 @@ void soap(int socket, const struct service_configuration *configuration, if (NULL == configuration) { - http_send_response_500(socket, "Second argument of soap() is NULL"); + http_send_response_500(connection, + "Second argument of soap() is NULL"); return; } if (NULL == request || request_length == 0) { - http_send_response_400(socket, "Client sent empty body"); + http_send_response_400(connection, "Client sent empty body"); return; } request_doc = xmlParseMemory(request, request_length); if (NULL == request_doc) { - http_send_response_400(socket, "Client sent invalid XML document"); + http_send_response_400(connection, "Client sent invalid XML document"); return; } xpath_ctx = xmlXPathNewContext(request_doc); if (NULL == xpath_ctx) { xmlFreeDoc(request_doc); - http_send_response_500(socket, "Could not create XPath context"); + http_send_response_500(connection, "Could not create XPath context"); return; } if (register_namespaces(xpath_ctx, 0, MESSAGE_NS_UNSIGNED)) { xmlXPathFreeContext(xpath_ctx); xmlFreeDoc(request_doc); - http_send_response_500(socket, + http_send_response_500(connection, "Could not register name spaces to the XPath context"); return; } @@ -591,14 +598,14 @@ void soap(int socket, const struct service_configuration *configuration, if (NULL == request_soap_body) { xmlXPathFreeContext(xpath_ctx); xmlFreeDoc(request_doc); - http_send_response_400(socket, "Client sent invalid SOAP request"); + http_send_response_400(connection, "Client sent invalid SOAP request"); return; } if (xmlXPathNodeSetIsEmpty(request_soap_body->nodesetval)) { xmlXPathFreeObject(request_soap_body); xmlXPathFreeContext(xpath_ctx); xmlFreeDoc(request_doc); - http_send_response_400(socket, + http_send_response_400(connection, "SOAP request does not contain SOAP Body element"); return; } @@ -606,7 +613,7 @@ void soap(int socket, const struct service_configuration *configuration, xmlXPathFreeObject(request_soap_body); xmlXPathFreeContext(xpath_ctx); xmlFreeDoc(request_doc); - http_send_response_400(socket, + http_send_response_400(connection, "SOAP response has more than one Body element"); return; } @@ -615,7 +622,7 @@ void soap(int socket, const struct service_configuration *configuration, xmlXPathFreeObject(request_soap_body); xmlXPathFreeContext(xpath_ctx); xmlFreeDoc(request_doc); - http_send_response_400(socket, "SOAP body has more than one child"); + http_send_response_400(connection, "SOAP body has more than one child"); return; } if (isds_request->type != XML_ELEMENT_NODE || isds_request->ns == NULL || @@ -623,7 +630,7 @@ void soap(int socket, const struct service_configuration *configuration, xmlXPathFreeObject(request_soap_body); xmlXPathFreeContext(xpath_ctx); xmlFreeDoc(request_doc); - http_send_response_400(socket, + http_send_response_400(connection, "SOAP body does not contain a name-space-qualified element"); return; } @@ -631,12 +638,14 @@ void soap(int socket, const struct service_configuration *configuration, /* Build SOAP response envelope */ response_doc = xmlNewDoc(BAD_CAST "1.0"); if (!response_doc) { - http_send_response_500(socket, "Could not build SOAP response document"); + http_send_response_500(connection, + "Could not build SOAP response document"); goto leave; } response_soap_envelope = xmlNewNode(NULL, BAD_CAST "Envelope"); if (!response_soap_envelope) { - http_send_response_500(socket, "Could not build SOAP response envelope"); + http_send_response_500(connection, + "Could not build SOAP response envelope"); goto leave; } xmlDocSetRootElement(response_doc, response_soap_envelope); @@ -644,21 +653,21 @@ void soap(int socket, const struct service_configuration *configuration, * otherwise we get namespace prefix without definition */ soap_ns = xmlNewNs(response_soap_envelope, BAD_CAST SOAP_NS, NULL); if(NULL == soap_ns) { - http_send_response_500(socket, "Could not create SOAP name space"); + http_send_response_500(connection, "Could not create SOAP name space"); goto leave; } xmlSetNs(response_soap_envelope, soap_ns); response_soap_body = xmlNewChild(response_soap_envelope, NULL, BAD_CAST "Body", NULL); if (!response_soap_body) { - http_send_response_500(socket, + http_send_response_500(connection, "Could not add Body to SOAP response envelope"); goto leave; } /* Append ISDS response element */ if (-1 == test_asprintf(&response_name, "%s%s", isds_request->name, "Response")) { - http_send_response_500(socket, + http_send_response_500(connection, "Could not buld ISDS resposne element name"); goto leave; } @@ -666,13 +675,13 @@ void soap(int socket, const struct service_configuration *configuration, BAD_CAST response_name, NULL); free(response_name); if (NULL == isds_response) { - http_send_response_500(socket, + http_send_response_500(connection, "Could not add ISDS response element to SOAP response body"); goto leave; } isds_ns = xmlNewNs(isds_response, isds_request->ns->href, NULL); if(NULL == isds_ns) { - http_send_response_500(socket, + http_send_response_500(connection, "Could not create a name space for the response body"); goto leave; } @@ -692,20 +701,20 @@ void soap(int socket, const struct service_configuration *configuration, /* Alias "isds" XPath identifier to OISDS_NS */ if (register_namespaces(xpath_ctx, 1, MESSAGE_NS_UNSIGNED)) { - http_send_response_500(socket, + http_send_response_500(connection, "Could not register name spaces to the " "XPath context"); break; } } xpath_ctx->node = isds_request; - if (HTTP_ERROR_SERVER != services[i].function(socket, + if (HTTP_ERROR_SERVER != services[i].function(connection, request_doc, xpath_ctx, isds_request, response_doc, isds_response, service->arguments)) { service_passed = 1; } else { - http_send_response_500(socket, + http_send_response_500(connection, "Internal server error while processing " "ISDS request"); } @@ -720,7 +729,7 @@ void soap(int socket, const struct service_configuration *configuration, /* Serialize the SOAP response */ http_response_body = xmlBufferCreate(); if (NULL == http_response_body) { - http_send_response_500(socket, + http_send_response_500(connection, "Could not create xmlBuffer for response serialization"); goto leave; } @@ -729,19 +738,19 @@ void soap(int socket, const struct service_configuration *configuration, * elements. */ save_ctx = xmlSaveToBuffer(http_response_body, "UTF-8", 0); if (NULL == save_ctx) { - http_send_response_500(socket, "Could not create XML serializer"); + http_send_response_500(connection, "Could not create XML serializer"); goto leave; } /* XXX: According LibXML documentation, this function does not return * meaningful value yet */ xmlSaveDoc(save_ctx, response_doc); if (-1 == xmlSaveFlush(save_ctx)) { - http_send_response_500(socket, + http_send_response_500(connection, "Could not serialize SOAP response"); goto leave; } - http_send_response_200(socket, http_response_body->content, + http_send_response_200(connection, http_response_body->content, http_response_body->use, soap_mime_type); } @@ -756,7 +765,7 @@ leave: xmlFreeDoc(request_doc); if (!service_handled) { - http_send_response_500(socket, + http_send_response_500(connection, "Requested ISDS service not implemented"); } diff --git a/test/simline/service.h b/test/simline/service.h index f312eb2..93b2b37 100644 --- a/test/simline/service.h +++ b/test/simline/service.h @@ -5,7 +5,8 @@ /* Parse soap request, pass it to service endpoint and respond to it. * It sends final HTTP response. */ -void soap(int socket, const struct service_configuration *configuration, +void soap(const struct http_connection *connection, + const struct service_configuration *configuration, const void *request, size_t request_length, const char *end_point); #endif -- 2.11.4.GIT