Beispiel #1
0
static inline int method_lookup(struct mk_http_request *req,
                                struct mk_http_parser *p, char *buffer)
{
    int i = 0;
    int len;

    /* Method lenght */
    len = field_len();

    /* Point the buffer */
    req->method = MK_METHOD_UNKNOWN;
    req->method_p.data = buffer + p->start;
    req->method_p.len  = len;

    if (p->method >= 0) {
        if (strncmp(buffer + p->start + 1,
                    mk_methods_table[p->method].name + 1,
                    len - 1) == 0) {
            req->method = p->method;
            return req->method;
        }
    }

    for (i = 0; i < MK_METHOD_SIZEOF; i++) {
        if (len != mk_methods_table[i].len) {
            continue;
        }

        if (strncmp(buffer + p->start, mk_methods_table[i].name, len) == 0) {
            req->method = i;
            return i;
        }
    }
    return MK_METHOD_UNKNOWN;
}
int get_url(unsigned char* buf, int *url_len, const unsigned char *pkt_data, int hdr_len)
{
   const  unsigned char* cur;
    int host_len;
    int uri_len;

    memcpy(buf, "http://", 7);
    buf += 7;
    *url_len = 7;

    cur = strstr(pkt_data, "Host:");
    if (cur == NULL)
        return -1;
    cur += 6;
    host_len = field_len(cur, hdr_len - (cur - pkt_data));

    if (host_len && (*url_len +host_len<1200)){
        memcpy(buf, cur, host_len);
        buf += host_len;
	*url_len += host_len;
    }
    else
    {
        return -1;
    }

    cur = pkt_data;
    if (pkt_data[0] == 'G')
        cur += 4;
    else if (pkt_data[0] == 'P'){
        cur += 5;
    }

    uri_len = field_len(cur, hdr_len - (cur - pkt_data));
    uri_len -= 9;

    if((*url_len + uri_len) < 1200){
	memcpy(buf, cur, uri_len);
    	*url_len += uri_len;
    }
    
    return 0;
    
}
Beispiel #3
0
uint8_t parse_gps_rmc(gps_rmc_state_t * state) {
	if (gps_message_type() != GPS_MESSAGE_GPRMC)
		return E_MSG_TYPE_ERR;

	uint8_t *parse_buffer[16];
	uint8_t i, len;

	state->hour = atos_len(gps_data + GPS_RMC_HOUR_OFFSET, 2);
	state->minute = atos_len(gps_data + GPS_RMC_MINUTE_OFFSET, 2);
	state->second = atos_len(gps_data + GPS_RMC_SECOND_OFFSET, 2);

	if (gps_data[GPS_RMC_VALID_OFFSET] == 'A') {
		state->flags &= ~GPS_DATA_INVALID;
	} else {
		state->flags |= GPS_DATA_INVALID;
	}

	state->latitude_degrees = atos_len(gps_data + GPS_RMC_LATITUDE_DEG_OFFSET, 2);

	state->latitude_seconds = atos_len(gps_data + GPS_RMC_LATITUDE_MIN_VAL_OFFSET, 2) * 10000;
	state->latitude_seconds += atos_len(gps_data + GPS_RMC_LATITUDE_MIN_FRAC_OFFSET, 4);

	state->flags &= ~(LATITUDE_N | LATITUDE_S);

	if (gps_data[GPS_RMC_LATITUDE_NS_OFFSET] == 'N') {
		state->flags |= LATITUDE_N;
	} else if (gps_data[GPS_RMC_LATITUDE_NS_OFFSET] == 'S') {
		state->flags |= LATITUDE_S;
	}

	state->longitude_degrees = atos_len(gps_data + GPS_RMC_LONGITUDE_DEG_OFFSET, 3);
	state->longitude_seconds = atos_len(gps_data + GPS_RMC_LONGITUDE_MIN_VAL_OFFSET, 2) * 10000;
	state->longitude_seconds += atos_len(gps_data + GPS_RMC_LONGITUDE_MIN_FRAC_OFFSET, 4);

	state->flags &= ~(LONGITUDE_E | LONGITUDE_W);

	if (gps_data[GPS_RMC_LONGITUDE_EW_OFFSET] == 'E') {
		state->flags |= LONGITUDE_E;
	} else if (gps_data[GPS_RMC_LONGITUDE_EW_OFFSET] == 'W') {
		state->flags |= LONGITUDE_W;
	}

	i = GPS_RMC_SPEED_OFFSET;

	len = field_len(gps_data + i);

	if (len != 0) {
		state->speed = atos_len(gps_data + i, len) * 100;
		i += len + 1;

		len = field_len(gps_data + i);

		if (len != 0) {
			state->speed += atos_len(gps_data + i, len);
		}
		i += len + 1;
	} else {
		i++;
		state->speed = 0;
	}

	len = field_len(gps_data + i);

	if (len != 0) {
		state->course = atos_len(gps_data + i, len) * 100;
		i += len + 1;

		len = field_len(gps_data + i);

		if (len != 0) {
			state->course += atos_len(gps_data + i, len);
		}
		i += len + 1;
	} else {
		i++;
		state->course = 0;
	}

	// Set data

	state->day = atos_len(gps_data + i, 2);
	i += 2;
	state->month = atos_len(gps_data + i, 2);
	i += 2;
	state->year = atos_len(gps_data + i, 2);

/*
	sdWrite(&SD1, "RMC PARSED:", sizeof("RMC PARSED:") - 1);

	SPRNT(state->hour, "Hour: ", 1);
	SPRNT(state->minute, "Minute: ", 1);
	SPRNT(state->second, "Second: ", 1);

	SPRNT(state->day, "Day: ", 1);
	SPRNT(state->month, "Month: ", 1);
	SPRNT(state->year, "Year: ", 1);

	SPRNT(state->speed, "Speed: ", 1);
	SPRNT(state->course, "Course: ", 1);

	SPRNT(state->flags, "Flags: ", 1);

	SPRNT(state->latitude_degrees, "Lat degrees: ", 1);
	SPRNT(state->latitude_seconds/10000, "Lat seconds: ", 1);
	SPRNT(state->latitude_seconds % 10000, "Lat seconds: ", 1);

	SPRNT(state->longitude_degrees, "Long degrees: ", 1);
	SPRNT(state->longitude_seconds/10000, "Long seconds: ", 1);
	SPRNT(state->longitude_seconds % 10000, "Long seconds: ", 1);
*/


	return E_OK;
}
Beispiel #4
0
/*
 * Parse the protocol and point relevant fields, don't take logic decisions
 * based on this, just parse to locate things.
 */
int mk_http_parser(struct mk_http_request *req, struct mk_http_parser *p,
                   char *buffer, int buf_len, struct mk_server *server)
{
    int s;
    int tmp;
    int ret;
    int len;

    /* lazy test

    printf("p->i=%i buf_len=%i\n",
           p->i, buf_len);

    for (s = p->i; s < buf_len; s++) {
        if (buffer[s] == '\r') {
            printf("CR");
        }
        else if (buffer[s] == '\n') {
            printf("LF");
        }
        else {
            printf("%c", buffer[s]);
        }
    }
    printf("\n");
    */

    len = buf_len;
    for (; p->i < len; p->i++, p->chars++) {
        /* FIRST LINE LEVEL: Method, URI & Protocol */
        if (p->level == REQ_LEVEL_FIRST) {
            switch (p->status) {
            case MK_ST_REQ_METHOD:                      /* HTTP Method */
                if (p->chars == -1) {
                    switch (buffer[p->i]) {
                    case 'G':
                        p->method = MK_METHOD_GET;
                        break;
                    case 'P':
                        p->method = MK_METHOD_POST;
                        break;
                    case 'H':
                        p->method = MK_METHOD_HEAD;
                        break;
                    case 'D':
                        p->method = MK_METHOD_DELETE;
                        break;
                    case 'O':
                        p->method = MK_METHOD_OPTIONS;
                        break;
                    }
                    continue;
                }

                if (buffer[p->i] == ' ') {
                    mark_end();
                    p->status = MK_ST_REQ_URI;
                    if (p->end < 2) {
                        return MK_HTTP_PARSER_ERROR;
                    }
                    method_lookup(req, p, buffer);
                    start_next();
                }
                else {
                    if ((p->i - p->start) > 10) {
                        return MK_HTTP_PARSER_ERROR;
                    }
                }
                break;
            case MK_ST_REQ_URI:                         /* URI */
                if (buffer[p->i] == ' ') {
                    mark_end();
                    p->status = MK_ST_REQ_PROT_VERSION;
                    if (field_len() < 1) {
                        return MK_HTTP_PARSER_ERROR;
                    }
                    request_set(&req->uri, p, buffer);
                    start_next();
                }
                else if (buffer[p->i] == '?') {
                    mark_end();
                    request_set(&req->uri, p, buffer);
                    p->status = MK_ST_REQ_QUERY_STRING;
                    start_next();
                }
                else if (buffer[p->i] == '\r' || buffer[p->i] == '\n') {
                    mk_http_error(MK_CLIENT_BAD_REQUEST, req->session,
                                  req, server);
                    return MK_HTTP_PARSER_ERROR;
                }
                break;
            case MK_ST_REQ_QUERY_STRING:                /* Query string */
                char_lookup(buffer, ' ', len, p);
                if (buffer[p->i] == ' ') {
                    mark_end();
                    request_set(&req->query_string, p, buffer);
                    p->status = MK_ST_REQ_PROT_VERSION;
                    start_next();
                }
                else if (buffer[p->i] == '\r' || buffer[p->i] == '\n') {
                    mk_http_error(MK_CLIENT_BAD_REQUEST, req->session,
                                  req, server);
                    return MK_HTTP_PARSER_ERROR;
                }
                break;
            case MK_ST_REQ_PROT_VERSION:                /* Protocol Version */
                /*
                 * Most of the time we already have the string version in our
                 * buffer, for that case try to match the version and avoid
                 * loop rounds.
                 */
                if (p->start + 6 >= p->i) {
                    continue;
                }

                tmp = p->start;
                if (buffer[tmp] == 'H' &&
                    buffer[tmp + 1] == 'T' &&
                    buffer[tmp + 2] == 'T' &&
                    buffer[tmp + 3] == 'P' &&
                    buffer[tmp + 4] == '/' &&
                    buffer[tmp + 5] == '1' &&
                    buffer[tmp + 6] == '.') {

                    request_set(&req->protocol_p, p, buffer);
                    req->protocol_p.len = 8;
                    mk_http_set_minor_version(buffer[tmp + 7]);
                }
                else {
                    mk_http_error(MK_SERVER_HTTP_VERSION_UNSUP,
                                  req->session, req, server);
                    return MK_HTTP_PARSER_ERROR;
                }
                p->status = MK_ST_FIRST_CONTINUE;
                break;
            case MK_ST_FIRST_CONTINUE:
                if (buffer[p->i] == '\r') {
                    p->status = MK_ST_FIRST_FINALIZING;
                }
                else {
                    return MK_HTTP_PARSER_ERROR;
                }
                break;
            case MK_ST_FIRST_FINALIZING:                  /* New Line */
                if (buffer[p->i] == '\n') {
                    p->level = REQ_LEVEL_CONTINUE;
                    start_next();
                }
                else {
                    return MK_HTTP_PARSER_ERROR;
                }
                break;
            case MK_ST_BLOCK_END:
                if (buffer[p->i] == '\n') {
                    return mk_http_parser_ok(req, p, server);
                }
                else {
                    return MK_HTTP_PARSER_ERROR;
                }
                break;
            };
        }
        else if (p->level == REQ_LEVEL_CONTINUE) {
            if (buffer[p->i] == '\r') {
                p->level  = REQ_LEVEL_FIRST;
                p->status = MK_ST_BLOCK_END;
            }
            else {
                p->level  = REQ_LEVEL_HEADERS;
                p->status = MK_ST_HEADER_KEY;
                p->chars  = 0;
            }
        }
        /* HEADERS: all headers stuff */
        if (p->level == REQ_LEVEL_HEADERS) {
            /* Expect a Header key */
            if (p->status == MK_ST_HEADER_KEY) {
                if (buffer[p->i] == '\r') {
                    if (p->chars == 0) {
                        p->level = REQ_LEVEL_END;
                        start_next();
                    }
                    else {
                        return MK_HTTP_PARSER_ERROR;
                    }
                }

                if (p->chars == 0) {
                    /*
                     * We reach the start of a Header row, lets catch the most
                     * probable header.
                     *
                     * The goal of this 'first row character lookup', is to define a
                     * small range set of probable headers comparison once we catch
                     * a header end.
                     */
                    s = tolower(buffer[p->i]);
                    switch (s) {
                    case 'a':
                        p->header_min = MK_HEADER_ACCEPT;
                        p->header_max = MK_HEADER_AUTHORIZATION;
                        break;
                    case 'c':
                        p->header_min = MK_HEADER_CACHE_CONTROL;
                        p->header_max = MK_HEADER_CONTENT_TYPE;
                        break;
                    case 'h':
                        p->header_min = MK_HEADER_HOST;
                        p->header_max = MK_HEADER_HTTP2_SETTINGS;
                        break;
                    case 'i':
                        header_scope_eq(p, MK_HEADER_IF_MODIFIED_SINCE);
                        break;
                    case 'l':
                        p->header_min = MK_HEADER_LAST_MODIFIED;
                        p->header_max = MK_HEADER_LAST_MODIFIED_SINCE;
                        break;
                    case 'r':
                        p->header_min = MK_HEADER_RANGE;
                        p->header_max = MK_HEADER_REFERER;
                        break;
                    case 'u':
                        p->header_min = MK_HEADER_UPGRADE;
                        p->header_max = MK_HEADER_USER_AGENT;
                        break;
                    default:
                        p->header_key = -1;
                        p->header_sep = -1;
                        p->header_min = -1;
                        p->header_max = -1;
                    };
                    p->header_key = p->i;
                    continue;
                }

                /* Found key/value separator */
                char_lookup(buffer, ':', len, p);
                if (buffer[p->i] == ':') {
                    /* Set the key/value middle point */
                    p->header_sep = p->i;

                    /* validate length */
                    mark_end();
                    if (field_len() < 1) {
                        return MK_HTTP_PARSER_ERROR;
                    }

                    /* Wait for a value */
                    p->status = MK_ST_HEADER_VALUE;
                    start_next();
                }
            }
            /* Parsing the header value */
            else if (p->status == MK_ST_HEADER_VALUE) {
                /* Trim left, set starts only when found something != ' ' */
                if (buffer[p->i] == '\r' || buffer[p->i] == '\n') {
                    return MK_HTTP_PARSER_ERROR;
                }
                else if (buffer[p->i] != ' ') {
                    p->status = MK_ST_HEADER_VAL_STARTS;
                    p->start = p->header_val = p->i;
                }
                continue;
            }
            /* New header row starts */
            else if (p->status == MK_ST_HEADER_VAL_STARTS) {
                /* Maybe there is no more headers and we reach the end ? */
                if (buffer[p->i] == '\r') {
                    mark_end();
                    if (field_len() <= 0) {
                        return MK_HTTP_PARSER_ERROR;
                    }

                    /*
                     * A header row has ended, lets lookup the header and populate
                     * our headers table index.
                     */
                    ret = header_lookup(p, buffer);
                    if (ret != 0) {
                        if (ret < -1) {
                            mk_http_error(-ret, req->session, req, server);
                        }
                        return MK_HTTP_PARSER_ERROR;
                    }

                    /* Try to catch next LF */
                    if (p->i + 1 < len) {
                        if (buffer[p->i + 1] == '\n') {
                            p->i++;
                            p->status = MK_ST_HEADER_KEY;
                            p->chars = -1;
                            start_next();
                        }
                    }

                    p->status = MK_ST_HEADER_END;
                    start_next();
                }
                else if (buffer[p->i] == '\n' && buffer[p->i - 1] != '\r') {
                    return MK_HTTP_PARSER_ERROR;
                }
            }
            else if (p->status == MK_ST_HEADER_END) {
                if (buffer[p->i] == '\n') {
                    p->status = MK_ST_HEADER_KEY;
                    p->chars = -1;
                    start_next();
                }
                else {
                    return MK_HTTP_PARSER_ERROR;
                }
            }
        }
        else if (p->level == REQ_LEVEL_END) {
            if (buffer[p->i] == '\n') {
                if (p->header_content_length > 0) {
                    p->level = REQ_LEVEL_BODY;
                    p->chars = -1;
                    start_next();
                }
                else {
                    return mk_http_parser_ok(req, p, server);
                }
            }
            else {
                return MK_HTTP_PARSER_ERROR;
            }
        }
        else if (p->level == REQ_LEVEL_BODY) {
            /*
             * Reaching this level can means two things:
             *
             * - A Pipeline Request
             * - A Body content (POST/PUT methods)
             */
            if (p->header_content_length > 0) {

                p->body_received = len - p->start;
                if ((len - p->start) < p->header_content_length) {
                    return MK_HTTP_PARSER_PENDING;
                }

                /* Cut off */
                p->i += p->body_received;
                req->data.len  = p->body_received;
                req->data.data = (buffer + p->start);
            }
            return mk_http_parser_ok(req, p, server);
        }
    }

    return MK_HTTP_PARSER_PENDING;
}
Beispiel #5
0
static inline void request_set(mk_ptr_t *ptr, struct mk_http_parser *p, char *buffer)
{
    ptr->data = buffer + p->start;
    ptr->len  = field_len();
}