My Project
 All Classes Files Functions Variables Typedefs Enumerations Enumerator Macros
http_msu.c
Go to the documentation of this file.
1 /*
2 START OF LICENSE STUB
3  DeDOS: Declarative Dispersion-Oriented Software
4  Copyright (C) 2017 University of Pennsylvania, Georgetown University
5 
6  This program is free software: you can redistribute it and/or modify
7  it under the terms of the GNU General Public License as published by
8  the Free Software Foundation, either version 3 of the License, or
9  (at your option) any later version.
10 
11  This program is distributed in the hope that it will be useful,
12  but WITHOUT ANY WARRANTY; without even the implied warranty of
13  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14  GNU General Public License for more details.
15 
16  You should have received a copy of the GNU General Public License
17  along with this program. If not, see <http://www.gnu.org/licenses/>.
18 END OF LICENSE STUB
19 */
20 #include "webserver/http_msu.h"
22 #include "webserver/dbops.h"
23 #include "webserver/cache_msu.h"
24 #include "webserver/write_msu.h"
25 #include "webserver/read_msu.h"
26 #include "socket_msu.h"
27 #include "msu_calls.h"
28 #include "logging.h"
29 #include "epollops.h"
30 #include "msu_state.h"
31 #include "unused_def.h"
32 #include "local_msu.h"
34 
35 static int send_error(struct local_msu *self, struct http_state *http_state,
36  struct msu_msg_hdr *hdr) {
37  struct response_state *resp = malloc(sizeof(*resp));
38  init_response_state(resp, &http_state->conn);
39  resp->body_len = craft_error_response(resp->url, resp->body);
40  return call_msu_type(self, &WEBSERVER_WRITE_MSU_TYPE, hdr, sizeof(*resp), resp);
41 }
42 
43 static int handle_db(struct http_state *http_state,
44  struct local_msu *self,
45  struct msu_msg *msg) {
46 
47  http_state->db.data = self->msu_state;
48  int rtn = access_database(http_state->parser.url, &http_state->db);
49 
50  if (rtn & WS_ERROR) {
51  log_warn("Could not access database!");
52  msu_error(self, &msg->hdr, 0);
53 
54  send_error(self, http_state, &msg->hdr);
55  msu_free_state(self, &msg->hdr.key);
56  return -1;
57  } else if (rtn & (WS_INCOMPLETE_READ | WS_INCOMPLETE_WRITE)) {
58  log(LOG_HTTP_MSU, "Partial db access, requeuing state %p", http_state);
59  http_state->conn.status = CON_DB_REQUEST;
60  return msu_monitor_fd(http_state->db.db_fd, RTN_TO_EVT(rtn), self, &msg->hdr);
61 
62  } else if (rtn & WS_COMPLETE) {
63  struct response_state *resp = malloc(sizeof(*resp));
64  init_response_state(resp, &http_state->conn);
65  strcpy(resp->url, http_state->parser.url);
66  msu_free_state(self, &msg->hdr.key);
67 
68  if (!has_regex(resp->url)) {
69  log(LOG_HTTP_MSU, "Crafting response for url %s", resp->url);
70  return call_msu_type(self, &WEBSERVER_CACHE_MSU_TYPE, &msg->hdr, sizeof(*resp), resp);
71  }
72 
73  return call_msu_type(self, &WEBSERVER_REGEX_ROUTING_MSU_TYPE, &msg->hdr, sizeof(*resp), resp);
74  }
75  log_error("Unknown return code from database access: %d", rtn);
76  msu_error(self, &msg->hdr, 0);
77  return -1;
78 }
79 
80 static int clear_state(struct local_msu *self, struct msu_msg *msg) {
81  log(LOG_HTTP_MSU, "Clearing state due to received error message");
82  msu_free_state(self, &msg->hdr.key);
83  return 0;
84 }
85 
87  struct http_state *http_state,
88  struct local_msu *self,
89  struct msu_msg *msg) {
90  if (read_state->req_len == -1) {
91  log(LOG_HTTP_MSU, "Clearing state (fd: %d)", read_state->conn.fd);
92  msu_free_state(self, &msg->hdr.key);
93  return 0;
94  }
95  log(LOG_HTTP_MSU, "Parsing request: %s (fd: %d)", read_state->req, read_state->conn.fd);
96  int rtn = parse_request(read_state->req, read_state->req_len, http_state);
97 
98  if (rtn & WS_COMPLETE) {
99  free(read_state);
100  return handle_db(http_state, self, msg);
101  } else if (rtn & WS_ERROR) {
102  send_error(self, http_state, &msg->hdr);
103  msu_free_state(self, &msg->hdr.key);
104  return 0;
105  } else {
106  http_state->conn.status = CON_READING;
107  log(LOG_PARTIAL_READS, "Got partial request %.*s (fd: %d)",
108  read_state->req_len, read_state->req, read_state->conn.fd);
109  return call_msu_type(self, &WEBSERVER_READ_MSU_TYPE, &msg->hdr, msg->data_size, msg->data);
110  }
111 }
112 
113 static int craft_http_response(struct local_msu *self,
114  struct msu_msg *msg) {
115  struct read_state *read_state = msg->data;
116 
117  size_t size = 0;
118  struct http_state *http_state = msu_get_state(self, &msg->hdr.key, &size);
119  int retrieved = 0;
120  if (http_state == NULL) {
121  http_state = msu_init_state(self, &msg->hdr.key, sizeof(*http_state));
122  read_state->conn.status = CON_READING;
123  init_http_state(http_state, &read_state->conn);
124  memcpy(&http_state->conn, &read_state->conn, sizeof(read_state->conn));
125  } else {
126 
127  log(LOG_HTTP_MSU, "Retrieved state %p (status %d)",
128  http_state, http_state->conn.status);
129  retrieved = 1;
130  if (http_state->conn.status != CON_DB_REQUEST) {
131  log(LOG_PARTIAL_READS, "Recovering partial read state ID: %u",
132  msg->hdr.key.id);
133  }
134  }
135  if (msg->data_size == sizeof(*read_state) && read_state->req_len == -1) {
136  if (http_state->conn.status == CON_DB_REQUEST) {
137  http_state->conn.status = NO_CONNECTION;
138  return 0;
139  } else {
140  msu_free_state(self, &msg->hdr.key);
141  return 0;
142  }
143  }
144 
145 
146  int rtn;
147  switch (http_state->conn.status) {
148  case NIL:
149  case CON_READING:
150  log(LOG_HTTP_MSU, "got CON_READING");
151  rtn = handle_parsing(read_state, http_state, self, msg);
152  if (rtn < 0) {
153  log_error("Error processing fd %d, ID %u, retrieved %d", read_state->conn.fd,
154  (msg->hdr.key.id), retrieved);
155  }
156  return rtn;
157  case CON_DB_REQUEST:
158  log(LOG_HTTP_MSU, "got CON_DB_REQUEST");
159  free(read_state);
160  return handle_db(http_state, self, msg);
161  case NO_CONNECTION:
162  msu_free_state(self, &msg->hdr.key);
163  return 0;
164  default:
165  log_error("Received unknown packet status: %d", read_state->conn.status);
166  return -1;
167  }
168 }
169 
170 static int http_init(struct local_msu *self, struct msu_init_data *data) {
171  self->msu_state = allocate_db_memory();
172 
173  char *init_data = data->init_data;
174 
175  char *ip, *saveptr;
176 
177  if ((ip = strtok_r(init_data, " ", &saveptr)) == NULL) {
178  log_error("Did not provide IP for DB initialization to http MSU");
179  return -1;
180  }
181  char *port_str;
182  if ((port_str = strtok_r(NULL, " ", &saveptr)) == NULL) {
183  log_error("Did not provide port for DB initialization to http MSU");
184  return -1;
185  }
186  int port = atoi(port_str);
187  char *n_files_str;
188  if ((n_files_str = strtok_r(NULL, " ", &saveptr)) == NULL) {
189  log_error("Did not provide n_files for DB initialization to http MSU");
190  return -1;
191  }
192  int n_files = atoi(n_files_str);
193 
194  init_db(ip, port, n_files);
195  return 0;
196 }
197 
198 static void http_destroy(struct local_msu *self) {
199  free_db_memory(self->msu_state);
200 }
201 
203  .name = "Webserver_HTTP_MSU",
205  .init = http_init,
206  .destroy = http_destroy,
207  .receive = craft_http_response,
208  .receive_error = clear_state
209 };
void init_http_state(struct http_state *state, struct connection *conn)
struct connection conn
int msu_error(struct local_msu *msu, struct msu_msg_hdr *hdr, int broadcast)
Definition: local_msu.c:353
int has_regex(char *url)
struct parser_state parser
void * allocate_db_memory()
Definition: dbops.c:87
Header for messages passed to MSUs.
Definition: msu_message.h:85
Macro for declaring functions or variables as unused to avoid compiler warnings.
static int http_init(struct local_msu *self, struct msu_init_data *data)
Definition: http_msu.c:170
void * msu_get_state(struct local_msu *msu, struct msu_msg_key *key, size_t *size)
Gets the state allocated with the given key.
Definition: msu_state.c:82
Wrapper functions for epoll to manage event-based communication.
struct msu_type WEBSERVER_HTTP_MSU_TYPE
Definition: http_msu.c:202
State storage that is tied to a specific MSU mesasge.
int craft_error_response(char *url, char *response)
struct msu_type WEBSERVER_CACHE_MSU_TYPE
Definition: cache_msu.c:300
void * data
Payload.
Definition: msu_message.h:104
int32_t id
A shorter, often hashed id for the key of fixed length (used in routing)
Definition: msu_message.h:52
#define WS_INCOMPLETE_READ
Definition: webserver.h:25
int db_fd
Definition: dbops.h:33
char url[256]
Logging of status messages to the terminal.
struct msu_type WEBSERVER_WRITE_MSU_TYPE
Definition: write_msu.c:69
#define WS_INCOMPLETE_WRITE
Definition: webserver.h:26
void * msu_init_state(struct local_msu *msu, struct msu_msg_key *key, size_t size)
Initializes a new MSU state of the given size with the provided key.
Definition: msu_state.c:55
struct msu_type WEBSERVER_READ_MSU_TYPE
Definition: read_msu.c:194
Declares the methods available for calling an MSU from another MSU.
static void http_destroy(struct local_msu *self)
Definition: http_msu.c:198
size_t data_size
Payload size.
Definition: msu_message.h:103
struct db_state db
void free_db_memory(void *memory)
Definition: dbops.c:93
#define log_error(fmt,...)
Definition: logging.h:101
Declares the structures and functions applicable to MSUs on the local machine.
int parse_request(char *req, int req_len, struct http_state *state)
Definition: webserver.h:30
char req[4096]
struct msu_type WEBSERVER_REGEX_ROUTING_MSU_TYPE
The structure that represents an MSU located on the local machine.
Definition: local_msu.h:38
Data with which an MSU is initialized, and the payload for messages of type CTRL_CREATE_MSU.
Definition: dfg.h:66
int access_database(char *url, struct db_state *state)
int call_msu_type(struct local_msu *sender, struct msu_type *dst_type, struct msu_msg_hdr *hdr, size_t data_size, void *data)
Sends an MSU message to a destination of the given type, utilizing the sending MSU's routing function...
Definition: msu_calls.c:146
void init_db(char *ip, int port, int n_files)
Definition: dbops.c:79
Defines a type of MSU.
Definition: msu_type.h:46
#define RTN_TO_EVT(rtn__)
Definition: webserver.h:40
static int craft_http_response(struct local_msu *self, struct msu_msg *msg)
Definition: http_msu.c:113
void * data
Definition: dbops.h:35
static int send_error(struct local_msu *self, struct http_state *http_state, struct msu_msg_hdr *hdr)
Definition: http_msu.c:35
struct msu_msg_hdr hdr
Definition: msu_message.h:102
struct connection conn
static int handle_db(struct http_state *http_state, struct local_msu *self, struct msu_msg *msg)
Definition: http_msu.c:43
static int clear_state(struct local_msu *self, struct msu_msg *msg)
Definition: http_msu.c:80
#define WS_COMPLETE
Definition: webserver.h:24
#define WS_ERROR
Definition: webserver.h:27
#define WEBSERVER_HTTP_MSU_TYPE_ID
Definition: msu_ids.h:26
char init_data[64]
Definition: dfg.h:67
int msu_monitor_fd(int fd, uint32_t events, struct local_msu *destination, struct msu_msg_hdr *hdr)
Definition: socket_msu.c:58
#define log(level, fmt,...)
Log at a custom level.
Definition: logging.h:147
A message that is to be delivered to an instance of an MSU.
Definition: msu_message.h:101
void init_response_state(struct response_state *state, struct connection *conn)
int msu_free_state(struct local_msu *msu, struct msu_msg_key *key)
Frees the state assocated with the given MSU and key.
Definition: msu_state.c:97
char * name
Name for the msu type.
Definition: msu_type.h:48
#define log_warn(fmt,...)
Definition: logging.h:113
struct msu_msg_key key
Routing/state key.
Definition: msu_message.h:87
static int handle_parsing(struct read_state *read_state, struct http_state *http_state, struct local_msu *self, struct msu_msg *msg)
Definition: http_msu.c:86
enum webserver_status status