lwip-1.4.1 (partial)
http-server/htserv.c@1:119c4f7144c8, 2018-07-24 (annotated)
- Committer:
- ua1arn
- Date:
- Tue Jul 24 17:36:01 2018 +0000
- Revision:
- 1:119c4f7144c8
lwip 1.4.1 with necessary servers
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
ua1arn | 1:119c4f7144c8 | 1 | /* |
ua1arn | 1:119c4f7144c8 | 2 | * The MIT License (MIT) |
ua1arn | 1:119c4f7144c8 | 3 | * |
ua1arn | 1:119c4f7144c8 | 4 | * Copyright (c) 2015 by Sergey Fetisov <fsenok@gmail.com> |
ua1arn | 1:119c4f7144c8 | 5 | * |
ua1arn | 1:119c4f7144c8 | 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy |
ua1arn | 1:119c4f7144c8 | 7 | * of this software and associated documentation files (the "Software"), to deal |
ua1arn | 1:119c4f7144c8 | 8 | * in the Software without restriction, including without limitation the rights |
ua1arn | 1:119c4f7144c8 | 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell |
ua1arn | 1:119c4f7144c8 | 10 | * copies of the Software, and to permit persons to whom the Software is |
ua1arn | 1:119c4f7144c8 | 11 | * furnished to do so, subject to the following conditions: |
ua1arn | 1:119c4f7144c8 | 12 | * |
ua1arn | 1:119c4f7144c8 | 13 | * The above copyright notice and this permission notice shall be included in all |
ua1arn | 1:119c4f7144c8 | 14 | * copies or substantial portions of the Software. |
ua1arn | 1:119c4f7144c8 | 15 | * |
ua1arn | 1:119c4f7144c8 | 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
ua1arn | 1:119c4f7144c8 | 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
ua1arn | 1:119c4f7144c8 | 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE |
ua1arn | 1:119c4f7144c8 | 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |
ua1arn | 1:119c4f7144c8 | 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, |
ua1arn | 1:119c4f7144c8 | 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE |
ua1arn | 1:119c4f7144c8 | 22 | * SOFTWARE. |
ua1arn | 1:119c4f7144c8 | 23 | */ |
ua1arn | 1:119c4f7144c8 | 24 | |
ua1arn | 1:119c4f7144c8 | 25 | /* |
ua1arn | 1:119c4f7144c8 | 26 | * version: 1.0 demo (7.02.2015) |
ua1arn | 1:119c4f7144c8 | 27 | * brief: tiny http ipv4 server using lwip (pcb) |
ua1arn | 1:119c4f7144c8 | 28 | */ |
ua1arn | 1:119c4f7144c8 | 29 | |
ua1arn | 1:119c4f7144c8 | 30 | #include "htserv.h" |
ua1arn | 1:119c4f7144c8 | 31 | |
ua1arn | 1:119c4f7144c8 | 32 | static struct tcp_pcb *http_pcb = NULL; |
ua1arn | 1:119c4f7144c8 | 33 | |
ua1arn | 1:119c4f7144c8 | 34 | htserv_on_req_t htserv_on_req = NULL; |
ua1arn | 1:119c4f7144c8 | 35 | htserv_on_con_t htserv_on_con = NULL; |
ua1arn | 1:119c4f7144c8 | 36 | htserv_on_err_t htserv_on_err = NULL; |
ua1arn | 1:119c4f7144c8 | 37 | |
ua1arn | 1:119c4f7144c8 | 38 | typedef enum htcon_state_priv |
ua1arn | 1:119c4f7144c8 | 39 | { |
ua1arn | 1:119c4f7144c8 | 40 | CSP_ACTIVE, // as CON_ACTIVE |
ua1arn | 1:119c4f7144c8 | 41 | CSP_CLOSING, // as CON_CLOSING |
ua1arn | 1:119c4f7144c8 | 42 | CSP_CLOSED, // as CON_CLOSED |
ua1arn | 1:119c4f7144c8 | 43 | CSP_RD_REQ, |
ua1arn | 1:119c4f7144c8 | 44 | CSP_WR_RESP, |
ua1arn | 1:119c4f7144c8 | 45 | CSP_NONE, |
ua1arn | 1:119c4f7144c8 | 46 | } htcon_state_priv_t; |
ua1arn | 1:119c4f7144c8 | 47 | |
ua1arn | 1:119c4f7144c8 | 48 | typedef struct htcon_priv |
ua1arn | 1:119c4f7144c8 | 49 | { |
ua1arn | 1:119c4f7144c8 | 50 | htcon_t htcon; // user connection struct |
ua1arn | 1:119c4f7144c8 | 51 | char buff[HTTP_CON_BUFF_SIZE]; // request/response buffer |
ua1arn | 1:119c4f7144c8 | 52 | htcon_state_priv_t state; // connection state |
ua1arn | 1:119c4f7144c8 | 53 | struct tcp_pcb *pcb; // connection pcb |
ua1arn | 1:119c4f7144c8 | 54 | http_reqb_t reqb; // request buffer |
ua1arn | 1:119c4f7144c8 | 55 | http_resp_t resp; // responce |
ua1arn | 1:119c4f7144c8 | 56 | // writing managment |
ua1arn | 1:119c4f7144c8 | 57 | char *wbuff; // writing buffer |
ua1arn | 1:119c4f7144c8 | 58 | int wsize; // writing buffer size |
ua1arn | 1:119c4f7144c8 | 59 | int writed; // writed to buffer |
ua1arn | 1:119c4f7144c8 | 60 | int wsended; // sended by tcp |
ua1arn | 1:119c4f7144c8 | 61 | int wacksize; // acknowledged |
ua1arn | 1:119c4f7144c8 | 62 | } htcon_priv_t; |
ua1arn | 1:119c4f7144c8 | 63 | |
ua1arn | 1:119c4f7144c8 | 64 | htcon_priv_t htcons[HTTP_SERVER_MAX_CON]; |
ua1arn | 1:119c4f7144c8 | 65 | |
ua1arn | 1:119c4f7144c8 | 66 | void htserv_io(void); |
ua1arn | 1:119c4f7144c8 | 67 | |
ua1arn | 1:119c4f7144c8 | 68 | void http_prepare_resp(http_resp_t *resp, int code) |
ua1arn | 1:119c4f7144c8 | 69 | { |
ua1arn | 1:119c4f7144c8 | 70 | resp->code = code; |
ua1arn | 1:119c4f7144c8 | 71 | resp->server = HTTP_SERVER_NAME; |
ua1arn | 1:119c4f7144c8 | 72 | resp->cont_lang = HTTP_DEF_CONT_LANG; |
ua1arn | 1:119c4f7144c8 | 73 | resp->mime = MIME_TEXT_HTML; |
ua1arn | 1:119c4f7144c8 | 74 | resp->cont_len = 0; |
ua1arn | 1:119c4f7144c8 | 75 | resp->conn_type = CT_CLOSE; |
ua1arn | 1:119c4f7144c8 | 76 | } |
ua1arn | 1:119c4f7144c8 | 77 | |
ua1arn | 1:119c4f7144c8 | 78 | void htcon_req_finished(htcon_priv_t *con) |
ua1arn | 1:119c4f7144c8 | 79 | { |
ua1arn | 1:119c4f7144c8 | 80 | // 1. check request |
ua1arn | 1:119c4f7144c8 | 81 | if (con->reqb.req.method != METHOD_GET) |
ua1arn | 1:119c4f7144c8 | 82 | { |
ua1arn | 1:119c4f7144c8 | 83 | //http_prepare_resp(&con->resp, 405); // Method Not Allowed |
ua1arn | 1:119c4f7144c8 | 84 | //con->state = CSP_WR_RESP; |
ua1arn | 1:119c4f7144c8 | 85 | con->state = CSP_CLOSING; |
ua1arn | 1:119c4f7144c8 | 86 | htserv_io(); |
ua1arn | 1:119c4f7144c8 | 87 | return; |
ua1arn | 1:119c4f7144c8 | 88 | } |
ua1arn | 1:119c4f7144c8 | 89 | // 2. ask user |
ua1arn | 1:119c4f7144c8 | 90 | if (htserv_on_req == NULL) |
ua1arn | 1:119c4f7144c8 | 91 | { |
ua1arn | 1:119c4f7144c8 | 92 | con->state = CSP_CLOSING; |
ua1arn | 1:119c4f7144c8 | 93 | htserv_io(); |
ua1arn | 1:119c4f7144c8 | 94 | return; |
ua1arn | 1:119c4f7144c8 | 95 | } |
ua1arn | 1:119c4f7144c8 | 96 | |
ua1arn | 1:119c4f7144c8 | 97 | http_prepare_resp(&con->resp, 200); |
ua1arn | 1:119c4f7144c8 | 98 | |
ua1arn | 1:119c4f7144c8 | 99 | if (htserv_on_req(&con->reqb.req, &con->resp, &con->htcon.arg)) |
ua1arn | 1:119c4f7144c8 | 100 | { |
ua1arn | 1:119c4f7144c8 | 101 | int len; |
ua1arn | 1:119c4f7144c8 | 102 | con->wbuff = con->buff + con->reqb.size; |
ua1arn | 1:119c4f7144c8 | 103 | con->wsize = HTTP_CON_BUFF_SIZE - con->reqb.size; |
ua1arn | 1:119c4f7144c8 | 104 | len = http_resp_str(&con->resp, con->wbuff, con->wsize); |
ua1arn | 1:119c4f7144c8 | 105 | if (len >= con->wsize) |
ua1arn | 1:119c4f7144c8 | 106 | { |
ua1arn | 1:119c4f7144c8 | 107 | if (htserv_on_err != NULL) |
ua1arn | 1:119c4f7144c8 | 108 | htserv_on_err(HTTP_RESP_NOMEM); |
ua1arn | 1:119c4f7144c8 | 109 | con->state = CSP_CLOSING; |
ua1arn | 1:119c4f7144c8 | 110 | } |
ua1arn | 1:119c4f7144c8 | 111 | else |
ua1arn | 1:119c4f7144c8 | 112 | { |
ua1arn | 1:119c4f7144c8 | 113 | con->state = CSP_WR_RESP; |
ua1arn | 1:119c4f7144c8 | 114 | con->wacksize = 0; |
ua1arn | 1:119c4f7144c8 | 115 | con->writed = len; |
ua1arn | 1:119c4f7144c8 | 116 | con->wsended = 0; |
ua1arn | 1:119c4f7144c8 | 117 | } |
ua1arn | 1:119c4f7144c8 | 118 | } |
ua1arn | 1:119c4f7144c8 | 119 | else |
ua1arn | 1:119c4f7144c8 | 120 | con->state = CSP_CLOSING; |
ua1arn | 1:119c4f7144c8 | 121 | |
ua1arn | 1:119c4f7144c8 | 122 | htserv_io(); |
ua1arn | 1:119c4f7144c8 | 123 | } |
ua1arn | 1:119c4f7144c8 | 124 | |
ua1arn | 1:119c4f7144c8 | 125 | void htcon_received(htcon_priv_t *con, const char *data, int size) |
ua1arn | 1:119c4f7144c8 | 126 | { |
ua1arn | 1:119c4f7144c8 | 127 | htserv_err_t err; |
ua1arn | 1:119c4f7144c8 | 128 | err = HTTP_NO_ERROR; |
ua1arn | 1:119c4f7144c8 | 129 | |
ua1arn | 1:119c4f7144c8 | 130 | if (con->state == CSP_RD_REQ) |
ua1arn | 1:119c4f7144c8 | 131 | { |
ua1arn | 1:119c4f7144c8 | 132 | http_reqb_push(&con->reqb, data, size); |
ua1arn | 1:119c4f7144c8 | 133 | switch (con->reqb.state) |
ua1arn | 1:119c4f7144c8 | 134 | { |
ua1arn | 1:119c4f7144c8 | 135 | case REQB_UNFINISHED: |
ua1arn | 1:119c4f7144c8 | 136 | return; |
ua1arn | 1:119c4f7144c8 | 137 | case REQB_FINISHED: |
ua1arn | 1:119c4f7144c8 | 138 | htcon_req_finished(con); |
ua1arn | 1:119c4f7144c8 | 139 | return; |
ua1arn | 1:119c4f7144c8 | 140 | case REQB_REQ_TO_BIG: |
ua1arn | 1:119c4f7144c8 | 141 | err = HTTP_BIG_REQUEST; |
ua1arn | 1:119c4f7144c8 | 142 | break; |
ua1arn | 1:119c4f7144c8 | 143 | case REQB_SYNT_ERROR: |
ua1arn | 1:119c4f7144c8 | 144 | err = HTTP_REQ_SYNT_ERR; |
ua1arn | 1:119c4f7144c8 | 145 | break; |
ua1arn | 1:119c4f7144c8 | 146 | } |
ua1arn | 1:119c4f7144c8 | 147 | } |
ua1arn | 1:119c4f7144c8 | 148 | if (err != HTTP_NO_ERROR) |
ua1arn | 1:119c4f7144c8 | 149 | { |
ua1arn | 1:119c4f7144c8 | 150 | if (htserv_on_err != NULL) |
ua1arn | 1:119c4f7144c8 | 151 | htserv_on_err(err); |
ua1arn | 1:119c4f7144c8 | 152 | con->htcon.state = CON_CLOSING; |
ua1arn | 1:119c4f7144c8 | 153 | con->state = CSP_CLOSING; |
ua1arn | 1:119c4f7144c8 | 154 | htserv_io(); |
ua1arn | 1:119c4f7144c8 | 155 | } |
ua1arn | 1:119c4f7144c8 | 156 | } |
ua1arn | 1:119c4f7144c8 | 157 | |
ua1arn | 1:119c4f7144c8 | 158 | err_t htcon_recv(void *arg, struct tcp_pcb *pcb, struct pbuf *p, err_t err) |
ua1arn | 1:119c4f7144c8 | 159 | { |
ua1arn | 1:119c4f7144c8 | 160 | htcon_priv_t *con; |
ua1arn | 1:119c4f7144c8 | 161 | |
ua1arn | 1:119c4f7144c8 | 162 | con = (htcon_priv_t *)arg; |
ua1arn | 1:119c4f7144c8 | 163 | |
ua1arn | 1:119c4f7144c8 | 164 | if (err == ERR_OK && p != NULL) |
ua1arn | 1:119c4f7144c8 | 165 | { |
ua1arn | 1:119c4f7144c8 | 166 | tcp_recved(pcb, p->tot_len); |
ua1arn | 1:119c4f7144c8 | 167 | if (con != NULL) |
ua1arn | 1:119c4f7144c8 | 168 | htcon_received(con, p->payload, p->tot_len); |
ua1arn | 1:119c4f7144c8 | 169 | } |
ua1arn | 1:119c4f7144c8 | 170 | |
ua1arn | 1:119c4f7144c8 | 171 | if (err == ERR_OK && p == NULL) |
ua1arn | 1:119c4f7144c8 | 172 | { |
ua1arn | 1:119c4f7144c8 | 173 | if (con != NULL) |
ua1arn | 1:119c4f7144c8 | 174 | if (con->state != CSP_CLOSED) |
ua1arn | 1:119c4f7144c8 | 175 | { |
ua1arn | 1:119c4f7144c8 | 176 | con->state = CSP_CLOSING; |
ua1arn | 1:119c4f7144c8 | 177 | con->htcon.state = CON_CLOSING; |
ua1arn | 1:119c4f7144c8 | 178 | } |
ua1arn | 1:119c4f7144c8 | 179 | } |
ua1arn | 1:119c4f7144c8 | 180 | |
ua1arn | 1:119c4f7144c8 | 181 | if (p != NULL) |
ua1arn | 1:119c4f7144c8 | 182 | pbuf_free(p); |
ua1arn | 1:119c4f7144c8 | 183 | |
ua1arn | 1:119c4f7144c8 | 184 | return ERR_OK; |
ua1arn | 1:119c4f7144c8 | 185 | } |
ua1arn | 1:119c4f7144c8 | 186 | |
ua1arn | 1:119c4f7144c8 | 187 | static int find_free_con(void) |
ua1arn | 1:119c4f7144c8 | 188 | { |
ua1arn | 1:119c4f7144c8 | 189 | int i; |
ua1arn | 1:119c4f7144c8 | 190 | for (i = 0; i < HTTP_SERVER_MAX_CON; i++) |
ua1arn | 1:119c4f7144c8 | 191 | if (htcons[i].state == CSP_NONE) return i; |
ua1arn | 1:119c4f7144c8 | 192 | return -1; |
ua1arn | 1:119c4f7144c8 | 193 | } |
ua1arn | 1:119c4f7144c8 | 194 | |
ua1arn | 1:119c4f7144c8 | 195 | err_t htcon_sent(void *arg, struct tcp_pcb *tpcb, u16_t len) |
ua1arn | 1:119c4f7144c8 | 196 | { |
ua1arn | 1:119c4f7144c8 | 197 | htcon_priv_t *con; |
ua1arn | 1:119c4f7144c8 | 198 | con = (htcon_priv_t *)arg; |
ua1arn | 1:119c4f7144c8 | 199 | if (con == NULL) return ERR_OK; |
ua1arn | 1:119c4f7144c8 | 200 | con->wacksize += len; |
ua1arn | 1:119c4f7144c8 | 201 | // if (con->state == CSP_ACTIVE) |
ua1arn | 1:119c4f7144c8 | 202 | // con->htcon.writed += len; |
ua1arn | 1:119c4f7144c8 | 203 | return ERR_OK; |
ua1arn | 1:119c4f7144c8 | 204 | } |
ua1arn | 1:119c4f7144c8 | 205 | |
ua1arn | 1:119c4f7144c8 | 206 | void htcon_err(void *arg, err_t err) |
ua1arn | 1:119c4f7144c8 | 207 | { |
ua1arn | 1:119c4f7144c8 | 208 | htcon_priv_t *con; |
ua1arn | 1:119c4f7144c8 | 209 | con = (htcon_priv_t *)arg; |
ua1arn | 1:119c4f7144c8 | 210 | if (con == NULL) return; |
ua1arn | 1:119c4f7144c8 | 211 | if (htserv_on_err != NULL) |
ua1arn | 1:119c4f7144c8 | 212 | htserv_on_err(HTTP_TRANSP_ERR); |
ua1arn | 1:119c4f7144c8 | 213 | con->htcon.state = CON_CLOSING; |
ua1arn | 1:119c4f7144c8 | 214 | con->state = CSP_CLOSING; |
ua1arn | 1:119c4f7144c8 | 215 | } |
ua1arn | 1:119c4f7144c8 | 216 | |
ua1arn | 1:119c4f7144c8 | 217 | err_t htserv_accept(void *arg, struct tcp_pcb *newpcb, err_t err) |
ua1arn | 1:119c4f7144c8 | 218 | { |
ua1arn | 1:119c4f7144c8 | 219 | int index; |
ua1arn | 1:119c4f7144c8 | 220 | htcon_priv_t *con; |
ua1arn | 1:119c4f7144c8 | 221 | |
ua1arn | 1:119c4f7144c8 | 222 | LWIP_UNUSED_ARG(arg); |
ua1arn | 1:119c4f7144c8 | 223 | LWIP_UNUSED_ARG(err); |
ua1arn | 1:119c4f7144c8 | 224 | |
ua1arn | 1:119c4f7144c8 | 225 | index = find_free_con(); |
ua1arn | 1:119c4f7144c8 | 226 | if (index < 0) return ERR_MEM; |
ua1arn | 1:119c4f7144c8 | 227 | con = &htcons[index]; |
ua1arn | 1:119c4f7144c8 | 228 | |
ua1arn | 1:119c4f7144c8 | 229 | con->pcb = newpcb; |
ua1arn | 1:119c4f7144c8 | 230 | http_reqb_init(&con->reqb, con->buff, HTTP_REQ_MAX_SIZE); |
ua1arn | 1:119c4f7144c8 | 231 | con->wbuff = NULL; |
ua1arn | 1:119c4f7144c8 | 232 | con->wsize = 0; |
ua1arn | 1:119c4f7144c8 | 233 | con->wsended = 0; |
ua1arn | 1:119c4f7144c8 | 234 | con->wacksize = 0; |
ua1arn | 1:119c4f7144c8 | 235 | con->state = CSP_RD_REQ; |
ua1arn | 1:119c4f7144c8 | 236 | |
ua1arn | 1:119c4f7144c8 | 237 | con->htcon.req = &con->reqb.req; |
ua1arn | 1:119c4f7144c8 | 238 | con->htcon.resp = &con->resp; |
ua1arn | 1:119c4f7144c8 | 239 | con->htcon.writed = 0; |
ua1arn | 1:119c4f7144c8 | 240 | con->htcon.arg = NULL; |
ua1arn | 1:119c4f7144c8 | 241 | |
ua1arn | 1:119c4f7144c8 | 242 | |
ua1arn | 1:119c4f7144c8 | 243 | tcp_setprio(newpcb, TCP_PRIO_MIN); |
ua1arn | 1:119c4f7144c8 | 244 | tcp_arg(newpcb, con); |
ua1arn | 1:119c4f7144c8 | 245 | tcp_recv(newpcb, htcon_recv); |
ua1arn | 1:119c4f7144c8 | 246 | tcp_err(newpcb, htcon_err); |
ua1arn | 1:119c4f7144c8 | 247 | tcp_sent(newpcb, htcon_sent); |
ua1arn | 1:119c4f7144c8 | 248 | tcp_poll(newpcb, NULL, 4); // No polling here |
ua1arn | 1:119c4f7144c8 | 249 | |
ua1arn | 1:119c4f7144c8 | 250 | return ERR_OK; |
ua1arn | 1:119c4f7144c8 | 251 | } |
ua1arn | 1:119c4f7144c8 | 252 | |
ua1arn | 1:119c4f7144c8 | 253 | void htserv_io(void) // state machine |
ua1arn | 1:119c4f7144c8 | 254 | { |
ua1arn | 1:119c4f7144c8 | 255 | for (int i = 0; i < HTTP_SERVER_MAX_CON; i++) |
ua1arn | 1:119c4f7144c8 | 256 | { |
ua1arn | 1:119c4f7144c8 | 257 | htcon_priv_t *con; |
ua1arn | 1:119c4f7144c8 | 258 | con = &htcons[i]; |
ua1arn | 1:119c4f7144c8 | 259 | if (con->state == CSP_NONE || con->state == CSP_CLOSED) |
ua1arn | 1:119c4f7144c8 | 260 | continue; |
ua1arn | 1:119c4f7144c8 | 261 | |
ua1arn | 1:119c4f7144c8 | 262 | // have data to send? |
ua1arn | 1:119c4f7144c8 | 263 | if (con->state != CSP_CLOSING && con->writed > con->wsended) |
ua1arn | 1:119c4f7144c8 | 264 | { |
ua1arn | 1:119c4f7144c8 | 265 | int count; |
ua1arn | 1:119c4f7144c8 | 266 | err_t err; |
ua1arn | 1:119c4f7144c8 | 267 | count = con->writed - con->wsended; |
ua1arn | 1:119c4f7144c8 | 268 | if (count > tcp_sndbuf(con->pcb)) |
ua1arn | 1:119c4f7144c8 | 269 | count = tcp_sndbuf(con->pcb); |
ua1arn | 1:119c4f7144c8 | 270 | err = tcp_write(con->pcb, con->wbuff + con->wsended, count, TCP_WRITE_FLAG_COPY); |
ua1arn | 1:119c4f7144c8 | 271 | if (err == ERR_OK) |
ua1arn | 1:119c4f7144c8 | 272 | { |
ua1arn | 1:119c4f7144c8 | 273 | con->wsended += count; |
ua1arn | 1:119c4f7144c8 | 274 | tcp_output(con->pcb); |
ua1arn | 1:119c4f7144c8 | 275 | } |
ua1arn | 1:119c4f7144c8 | 276 | } |
ua1arn | 1:119c4f7144c8 | 277 | |
ua1arn | 1:119c4f7144c8 | 278 | // data was successfully sended? |
ua1arn | 1:119c4f7144c8 | 279 | if (con->state != CSP_CLOSING && con->wacksize >= con->wsended && con->wsended > 0) |
ua1arn | 1:119c4f7144c8 | 280 | { |
ua1arn | 1:119c4f7144c8 | 281 | con->writed = 0; |
ua1arn | 1:119c4f7144c8 | 282 | con->wsended = 0; |
ua1arn | 1:119c4f7144c8 | 283 | con->wacksize = 0; |
ua1arn | 1:119c4f7144c8 | 284 | // is it http-response? |
ua1arn | 1:119c4f7144c8 | 285 | if (con->state == CSP_WR_RESP) |
ua1arn | 1:119c4f7144c8 | 286 | { |
ua1arn | 1:119c4f7144c8 | 287 | con->htcon.state = CON_ACTIVE; |
ua1arn | 1:119c4f7144c8 | 288 | con->state = CSP_ACTIVE; |
ua1arn | 1:119c4f7144c8 | 289 | if (htserv_on_con != NULL) |
ua1arn | 1:119c4f7144c8 | 290 | htserv_on_con(i); |
ua1arn | 1:119c4f7144c8 | 291 | } |
ua1arn | 1:119c4f7144c8 | 292 | else |
ua1arn | 1:119c4f7144c8 | 293 | // is it document? |
ua1arn | 1:119c4f7144c8 | 294 | if (con->state == CSP_ACTIVE && con->resp.conn_type != CT_KEEP_ALIVE) |
ua1arn | 1:119c4f7144c8 | 295 | if (con->htcon.writed >= con->resp.cont_len) |
ua1arn | 1:119c4f7144c8 | 296 | { |
ua1arn | 1:119c4f7144c8 | 297 | con->htcon.state = CON_CLOSING; |
ua1arn | 1:119c4f7144c8 | 298 | con->state = CSP_CLOSING; |
ua1arn | 1:119c4f7144c8 | 299 | } |
ua1arn | 1:119c4f7144c8 | 300 | } |
ua1arn | 1:119c4f7144c8 | 301 | |
ua1arn | 1:119c4f7144c8 | 302 | // closing connection? |
ua1arn | 1:119c4f7144c8 | 303 | if (con->state == CSP_CLOSING) |
ua1arn | 1:119c4f7144c8 | 304 | // if (tcp_close(con->pcb) == ERR_OK) |
ua1arn | 1:119c4f7144c8 | 305 | { |
ua1arn | 1:119c4f7144c8 | 306 | con->htcon.state = CON_CLOSED; |
ua1arn | 1:119c4f7144c8 | 307 | con->state = CSP_CLOSED; |
ua1arn | 1:119c4f7144c8 | 308 | con->pcb = NULL; |
ua1arn | 1:119c4f7144c8 | 309 | } |
ua1arn | 1:119c4f7144c8 | 310 | } |
ua1arn | 1:119c4f7144c8 | 311 | } |
ua1arn | 1:119c4f7144c8 | 312 | |
ua1arn | 1:119c4f7144c8 | 313 | err_t htserv_init(uint16_t port) |
ua1arn | 1:119c4f7144c8 | 314 | { |
ua1arn | 1:119c4f7144c8 | 315 | int i; |
ua1arn | 1:119c4f7144c8 | 316 | err_t err; |
ua1arn | 1:119c4f7144c8 | 317 | tcp_init(); |
ua1arn | 1:119c4f7144c8 | 318 | htserv_free(); |
ua1arn | 1:119c4f7144c8 | 319 | if (http_pcb != NULL) |
ua1arn | 1:119c4f7144c8 | 320 | return ERR_USE; |
ua1arn | 1:119c4f7144c8 | 321 | http_pcb = tcp_new(); |
ua1arn | 1:119c4f7144c8 | 322 | if (http_pcb == NULL) return ERR_MEM; |
ua1arn | 1:119c4f7144c8 | 323 | err = tcp_bind(http_pcb, IP_ADDR_ANY, port); |
ua1arn | 1:119c4f7144c8 | 324 | if (err != ERR_OK) |
ua1arn | 1:119c4f7144c8 | 325 | { |
ua1arn | 1:119c4f7144c8 | 326 | htserv_free(); |
ua1arn | 1:119c4f7144c8 | 327 | return err; |
ua1arn | 1:119c4f7144c8 | 328 | } |
ua1arn | 1:119c4f7144c8 | 329 | for (i = 0; i < HTTP_SERVER_MAX_CON; i++) |
ua1arn | 1:119c4f7144c8 | 330 | htcons[i].state = CSP_NONE; |
ua1arn | 1:119c4f7144c8 | 331 | return ERR_OK; |
ua1arn | 1:119c4f7144c8 | 332 | } |
ua1arn | 1:119c4f7144c8 | 333 | |
ua1arn | 1:119c4f7144c8 | 334 | void htserv_free(void) |
ua1arn | 1:119c4f7144c8 | 335 | { |
ua1arn | 1:119c4f7144c8 | 336 | if (http_pcb == NULL) return; |
ua1arn | 1:119c4f7144c8 | 337 | if (tcp_close(http_pcb) == ERR_OK) |
ua1arn | 1:119c4f7144c8 | 338 | http_pcb = NULL; |
ua1arn | 1:119c4f7144c8 | 339 | } |
ua1arn | 1:119c4f7144c8 | 340 | |
ua1arn | 1:119c4f7144c8 | 341 | void htserv_tmr(uint32_t time_ms) //TODO |
ua1arn | 1:119c4f7144c8 | 342 | { |
ua1arn | 1:119c4f7144c8 | 343 | http_pcb = tcp_listen(http_pcb); |
ua1arn | 1:119c4f7144c8 | 344 | if (http_pcb != NULL) |
ua1arn | 1:119c4f7144c8 | 345 | { |
ua1arn | 1:119c4f7144c8 | 346 | tcp_accept(http_pcb, htserv_accept); |
ua1arn | 1:119c4f7144c8 | 347 | } |
ua1arn | 1:119c4f7144c8 | 348 | htserv_io(); |
ua1arn | 1:119c4f7144c8 | 349 | } |
ua1arn | 1:119c4f7144c8 | 350 | |
ua1arn | 1:119c4f7144c8 | 351 | const htcon_t *htcon(int index) |
ua1arn | 1:119c4f7144c8 | 352 | { |
ua1arn | 1:119c4f7144c8 | 353 | if (index < 0 || index >= HTTP_SERVER_MAX_CON) |
ua1arn | 1:119c4f7144c8 | 354 | return NULL; |
ua1arn | 1:119c4f7144c8 | 355 | if (htcons[index].state > CSP_CLOSED) return NULL; |
ua1arn | 1:119c4f7144c8 | 356 | return &htcons[index].htcon; |
ua1arn | 1:119c4f7144c8 | 357 | } |
ua1arn | 1:119c4f7144c8 | 358 | |
ua1arn | 1:119c4f7144c8 | 359 | void htcon_close(int index) |
ua1arn | 1:119c4f7144c8 | 360 | { |
ua1arn | 1:119c4f7144c8 | 361 | htcon_priv_t *con; |
ua1arn | 1:119c4f7144c8 | 362 | con = (htcon_priv_t *)htcon(index); |
ua1arn | 1:119c4f7144c8 | 363 | if (con == NULL) return; |
ua1arn | 1:119c4f7144c8 | 364 | if (con->state == CSP_CLOSED) return; |
ua1arn | 1:119c4f7144c8 | 365 | con->htcon.state = CON_CLOSING; |
ua1arn | 1:119c4f7144c8 | 366 | con->state = CSP_CLOSING; |
ua1arn | 1:119c4f7144c8 | 367 | htserv_io(); |
ua1arn | 1:119c4f7144c8 | 368 | } |
ua1arn | 1:119c4f7144c8 | 369 | |
ua1arn | 1:119c4f7144c8 | 370 | void htcon_free(int index) |
ua1arn | 1:119c4f7144c8 | 371 | { |
ua1arn | 1:119c4f7144c8 | 372 | htcon_priv_t *con; |
ua1arn | 1:119c4f7144c8 | 373 | con = (htcon_priv_t *)htcon(index); |
ua1arn | 1:119c4f7144c8 | 374 | if (con == NULL) return; |
ua1arn | 1:119c4f7144c8 | 375 | if (con->state != CSP_CLOSED) return; |
ua1arn | 1:119c4f7144c8 | 376 | htcons[index].state = CSP_NONE; |
ua1arn | 1:119c4f7144c8 | 377 | } |
ua1arn | 1:119c4f7144c8 | 378 | |
ua1arn | 1:119c4f7144c8 | 379 | int htcon_write_avail(int index) |
ua1arn | 1:119c4f7144c8 | 380 | { |
ua1arn | 1:119c4f7144c8 | 381 | htcon_priv_t *con; |
ua1arn | 1:119c4f7144c8 | 382 | con = (htcon_priv_t *)htcon(index); |
ua1arn | 1:119c4f7144c8 | 383 | if (con == NULL) return 0; |
ua1arn | 1:119c4f7144c8 | 384 | if (con->state != CSP_ACTIVE) return 0; |
ua1arn | 1:119c4f7144c8 | 385 | return con->wsize - con->writed; |
ua1arn | 1:119c4f7144c8 | 386 | } |
ua1arn | 1:119c4f7144c8 | 387 | |
ua1arn | 1:119c4f7144c8 | 388 | int htcon_write(int index, const char *data, int size) |
ua1arn | 1:119c4f7144c8 | 389 | { |
ua1arn | 1:119c4f7144c8 | 390 | int res; |
ua1arn | 1:119c4f7144c8 | 391 | htcon_priv_t *con; |
ua1arn | 1:119c4f7144c8 | 392 | con = (htcon_priv_t *)htcon(index); |
ua1arn | 1:119c4f7144c8 | 393 | if (con == NULL) return 0; |
ua1arn | 1:119c4f7144c8 | 394 | if (con->state != CSP_ACTIVE) return 0; |
ua1arn | 1:119c4f7144c8 | 395 | res = con->resp.cont_len - con->htcon.writed; |
ua1arn | 1:119c4f7144c8 | 396 | if (size < res) res = size; |
ua1arn | 1:119c4f7144c8 | 397 | if (con->wsize - con->writed < res) |
ua1arn | 1:119c4f7144c8 | 398 | res = con->wsize - con->writed; |
ua1arn | 1:119c4f7144c8 | 399 | if (res <= 0) return 0; |
ua1arn | 1:119c4f7144c8 | 400 | memcpy(con->wbuff + con->writed, data, res); |
ua1arn | 1:119c4f7144c8 | 401 | con->writed += res; |
ua1arn | 1:119c4f7144c8 | 402 | con->htcon.writed += res; |
ua1arn | 1:119c4f7144c8 | 403 | htserv_io(); |
ua1arn | 1:119c4f7144c8 | 404 | return res; |
ua1arn | 1:119c4f7144c8 | 405 | } |