Prusa MINI Firmware overview
Context Class Reference

Internal connection structure which is used in LwIP tcp_ callbacks as arg. More...

#include <connection.hpp>

Inheritance diagram for Context:
Collaboration diagram for Context:

Public Types

enum  State { FIRST, WAIT_FOR_EOH, PAYLOAD }
 

Public Member Functions

 Context (struct tcp_pcb *pcb)
 
 ~Context ()
 
err_t fill_request_buffer (const struct pbuf *p)
 Append pbuf to request_buffer. More...
 
size_t find_eoh (const void *data=nullptr, size_t length=0)
 Try to find End Of Header (\r
\r
) in buffer. More...
 
err_t parse_request (const void *data=nullptr, size_t length=0)
 parste the request header (request line + request headers) More...
 
err_t prepare_response ()
 Process message.response to internal buffer. More...
 
err_t prepare_header ()
 Process message.headers to internal buffer. More...
 
void free_buffer ()
 
- Public Member Functions inherited from LwIPClass
virtual ~LwIPClass ()
 

Static Public Member Functions

static voidoperator new (size_t size) noexcept
 
static void operator delete (void *ptr)
 
- Static Public Member Functions inherited from LwIPClass
static voidoperator new (size_t size)
 
static void operator delete (void *ptr)
 

Public Attributes

struct tcp_pcb * pcb
 
uint8_t retries
 
State state
 
Environment env
 
Message_t message
 
char * buffer
 
size_t m_position
 
size_t end_of_header
 
IResponse::unique_ptr_t response
 

Detailed Description

Internal connection structure which is used in LwIP tcp_ callbacks as arg.

Member Enumeration Documentation

◆ State

Enumerator
FIRST 
WAIT_FOR_EOH 
PAYLOAD 
22  {
23  FIRST, // firt call of recv callback after constructor
24  WAIT_FOR_EOH, // wait for end of header \r\n\r\n
25  PAYLOAD // pbuf containt payload
26  };

Constructor & Destructor Documentation

◆ Context()

Context::Context ( struct tcp_pcb *  pcb)
57  : pcb(pcb)
58  , retries(0)
59  , state(FIRST)
60  , message({ nullptr, nullptr, nullptr, 0 })
61  , buffer(nullptr)
62  , m_position(0)
63  , end_of_header(0)
64  , response(nullptr)
65  , request_buffer(nullptr)
66  , request_buffer_size(0) {
67  tcp_arg(pcb, this);
68  }

◆ ~Context()

Context::~Context ( )
70  {
71  lwsapi_free(buffer); // when buffer is not deleted
72  lwsapi_free(request_buffer); // when request_buffer is not deleted
73  tcp_arg(this->pcb, nullptr);
74  }

Member Function Documentation

◆ operator new()

static void* Context::operator new ( size_t  size)
staticnoexcept
39  {
40  if (Context::instances == Context::MAX) {
41  lwsapi_error("Context::new Too many connections\n");
42  return nullptr;
43  }
44  void *rv = mem_malloc(size);
45  if (rv != nullptr) {
46  Context::instances++;
47  }
48  return rv;
49  }
Here is the call graph for this function:

◆ operator delete()

static void Context::operator delete ( void ptr)
static
51  {
52  Context::instances--;
53  mem_free(ptr);
54  }
Here is the call graph for this function:

◆ fill_request_buffer()

err_t Context::fill_request_buffer ( const struct pbuf p)

Append pbuf to request_buffer.

17  {
18  if (request_buffer == nullptr) {
19  /* TODO: alloacate onle part for non parsed data
20  for example, if 500 bytes are parsed, allocat only
21  MAX_HTTP_REQUEST - 500*/
22  request_buffer = reinterpret_cast<char *>(mem_malloc(MAX_HTTP_REQUEST));
23  if (request_buffer == nullptr) {
24  return ERR_MEM;
25  }
26  }
27  for (auto it = p; it != nullptr; it = it->next) {
28  uint16_t len = it->len;
29  if (request_buffer_size + len > MAX_HTTP_REQUEST) {
30  len = MAX_HTTP_REQUEST - request_buffer_size;
31  }
32  std::strncpy(request_buffer + request_buffer_size,
33  reinterpret_cast<char *>(it->payload), len);
34  request_buffer_size += len;
35  }
36  return ERR_OK;
37 }
Here is the call graph for this function:
Here is the caller graph for this function:

◆ find_eoh()

size_t Context::find_eoh ( const void data = nullptr,
size_t  length = 0 
)

Try to find End Of Header (\r
\r
) in buffer.

Returns
position in data of \r
\r
. Return value can't be less then MINIMAL_REQUEST_LENGTH. If EOH sequence is not found, zero is returned.
39  {
40  if (data == nullptr) {
41  data = request_buffer;
42  length = request_buffer_size;
43  }
44 
45  // skip minimal request length
46  for (size_t i = MINIMAL_REQUEST_LENGTH; i < (length - 3); i++) {
47  if (!std::memcmp(memshift(data, i), CRLF CRLF, 4)) {
48  return i + 3;
49  }
50  }
51  return 0;
52 }
Here is the caller graph for this function:

◆ parse_request()

err_t Context::parse_request ( const void data = nullptr,
size_t  length = 0 
)

parste the request header (request line + request headers)

Parse and set request method and uri from input buffer.

110  {
111  if (request_buffer != nullptr) {
112  data = request_buffer;
113  length = request_buffer_size;
114  }
115 
116  const void *end = std::memchr(data, '\n', length);
117  if (end == nullptr || chrshift(end, -1)[0] != '\r') { // end of line not found
118  return ERR_VAL;
119  }
120 
121  if (parse_request_line(data, memlen(data, end)) != ERR_OK) {
122  return ERR_VAL;
123  }
124 
125  length -= memlen(data, end);
126  const void *start = memshift(end, 1);
127  end = std::memchr(start, '\n', length);
128 
129  while (end != nullptr) {
130  if (chrshift(end, -1)[0] != '\r') {
131  return ERR_VAL;
132  }
133 
134  // EOH detected
135  if (memlen(start, end) == 2 && (!std::memcmp(start, CRLF, 2))) {
136  return ERR_OK;
137  }
138 
139  if (parse_header(start, memlen(start, end)) != ERR_OK) {
140  return ERR_VAL;
141  }
142  length -= memlen(start, end);
143  start = memshift(end, 1);
144  end = std::memchr(start, '\n', length);
145  }
146 
147  // EOH not found, that is error
148  return ERR_VAL;
149 }
Here is the caller graph for this function:

◆ prepare_response()

err_t Context::prepare_response ( )

Process message.response to internal buffer.

152  {
153  // HTTP/1.0\ 200 OK\r\n\0
154  size_t size = strlen(HTTP_10) + strlen(message.response) + 4;
155  // TODO: check size
156  if (buffer != nullptr) {
157  mem_free(buffer); // repet call of this method could be possible
158  }
159 
160  buffer = reinterpret_cast<char *>(mem_calloc(size, sizeof(char)));
161  if (buffer == nullptr) {
162  // no nullptr to response means try to prepare response in next call
163  return ERR_MEM;
164  }
165  snprintf(buffer, size, "%s %s\r\n", HTTP_10, message.response);
166  message.response = nullptr;
167  return ERR_OK;
168 }
Here is the call graph for this function:
Here is the caller graph for this function:

◆ prepare_header()

err_t Context::prepare_header ( )

Process message.headers to internal buffer.

171  {
172  const IHeader *header = message.headers;
173  size_t size = header->length() + 2; // + \r\n when it is last header
174  // TODO: check size
175  if (buffer != nullptr) {
176  mem_free(buffer); // repet call of this method could be possible
177  }
178 
179  buffer = reinterpret_cast<char *>(mem_calloc(size, sizeof(char)));
180  if (buffer == nullptr) {
181  return ERR_MEM; // no memmory yet
182  }
183 
184  header->snprintf(buffer);
185  if (header->next == nullptr) {
186  buffer[size - 3] = '\r';
187  buffer[size - 2] = '\n';
188  buffer[size - 1] = '\0';
189  }
190  message.headers = header->next;
191  return ERR_OK;
192 }
Here is the call graph for this function:
Here is the caller graph for this function:

◆ free_buffer()

void Context::free_buffer ( )
94  {
96  }
Here is the caller graph for this function:

Member Data Documentation

◆ pcb

struct tcp_pcb* Context::pcb

◆ retries

uint8_t Context::retries

◆ state

State Context::state

◆ env

Environment Context::env

Request WSAPI environment

◆ message

Message_t Context::message

Last message returned from application

◆ buffer

char* Context::buffer

Buffer for internal output data

◆ m_position

size_t Context::m_position

Position of data in last message which is write not yet.

◆ end_of_header

size_t Context::end_of_header

◆ response

IResponse::unique_ptr_t Context::response

Response object with generator function.

pbuf::len
u16_t len
Definition: pbuf.h:159
Message_t::response
const char * response
Definition: lwsapi_app.hpp:212
Context::state
State state
Definition: connection.hpp:30
Context::message
Message_t message
Definition: connection.hpp:32
Context::WAIT_FOR_EOH
Definition: connection.hpp:24
MAX_HTTP_REQUEST
#define MAX_HTTP_REQUEST
LwIP WSAPI C/C++ implementation.
Definition: lwsapi_app.hpp:33
IHeader
Headers list. Creator is responsible to clean the values.
Definition: lwsapi_app.hpp:70
g29_auto.start
start
Definition: g29_auto.py:150
data
uint8_t data[8]
Definition: masstorage.h:49
Context::FIRST
Definition: connection.hpp:23
i
uint8_t i
Definition: screen_test_graph.c:72
lwsapi_error
#define lwsapi_error
Definition: lwsapi_app.hpp:42
CRLF
#define CRLF
Definition: connection.hpp:7
memlen
#define memlen(start, end)
return lenght of data from start to end
Definition: connection.hpp:16
mem_calloc
void * mem_calloc(mem_size_t count, mem_size_t size)
Definition: mem.c:765
createSpeedLookupTable.end
end
Definition: createSpeedLookupTable.py:33
ERR_MEM
Definition: err.h:65
IHeader::snprintf
virtual void snprintf(char *buff) const =0
Context::retries
uint8_t retries
Definition: connection.hpp:29
chrshift
#define chrshift(ptr, size)
Definition: connection.hpp:12
Context::pcb
struct tcp_pcb * pcb
Definition: connection.hpp:28
Context::response
IResponse::unique_ptr_t response
Definition: connection.hpp:37
IHeader::next
IHeader * next
Definition: lwsapi_app.hpp:73
IHeader::length
virtual size_t length() const =0
ERR_OK
Definition: err.h:63
Context::PAYLOAD
Definition: connection.hpp:25
Context::end_of_header
size_t end_of_header
Definition: connection.hpp:36
MINIMAL_REQUEST_LENGTH
#define MINIMAL_REQUEST_LENGTH
Definition: connection.hpp:8
lwsapi_free
#define lwsapi_free(arg)
Definition: lwsapi_app.hpp:44
Context::m_position
size_t m_position
Definition: connection.hpp:34
mem_malloc
void * mem_malloc(mem_size_t size)
Definition: mem.c:603
HTTP_10
static const char * HTTP_10
Definition: connection.cpp:8
length
png_uint_32 length
Definition: png.c:2247
mem_free
void mem_free(void *rmem)
Definition: mem.c:419
ERR_VAL
Definition: err.h:75
memshift
#define memshift(ptr, size)
Definition: connection.hpp:10
Message_t::headers
const IHeader * headers
Definition: lwsapi_app.hpp:213
size
static png_bytep size_t size
Definition: pngwrite.c:2170
Context::buffer
char * buffer
Definition: connection.hpp:33