Esempio n. 1
0
static void log_access(h2o_logger_t *_self, h2o_req_t *req)
{
    struct st_h2o_access_logger_t *self = (struct st_h2o_access_logger_t*)_self;
    char *line, *pos, *line_end;
    size_t element_index;

    line = alloca(LOG_ALLOCA_SIZE);
    pos = line;
    line_end = line + LOG_ALLOCA_SIZE;

    for (element_index = 0; element_index != self->num_elements; ++element_index) {
        struct log_element_t *element = self->elements + element_index;

    /* reserve capacity + suffix.len */
#define RESERVE(capacity) \
    do { \
        if ((capacity) + element->suffix.len > line_end - pos) { \
            size_t off = pos - line; \
            line = expand_line_buf(line, line_end - line, off + (capacity) + element->suffix.len); \
            pos = line + off; \
        } \
    } while (0)

        switch (element->type) {
        case ELEMENT_TYPE_EMPTY:
            RESERVE(0);
            break;
        case ELEMENT_TYPE_REMOTE_ADDR:
            if (req->conn->peername != NULL && req->conn->peername->sa_family == AF_INET) {
                uint32_t addr;
                RESERVE(sizeof("255.255.255.255") - 1);
                addr = htonl(((struct sockaddr_in*)req->conn->peername)->sin_addr.s_addr);
                pos += sprintf(pos, "%d.%d.%d.%d", addr >> 24, (addr >> 16) & 255, (addr >> 8) & 255, addr & 255);
            } else {
                RESERVE(1);
                *pos++ = '-';
            }
            break;
        case ELEMENT_TYPE_LOGNAME:
        case ELEMENT_TYPE_REMOTE_USER:
            RESERVE(1);
            *pos++ = '-';
            break;
        case ELEMENT_TYPE_TIMESTAMP:
            RESERVE(H2O_TIMESTR_LOG_LEN + 2);
            *pos++ = '[';
            pos = append_safe_string(pos, req->processed_at.str->log, H2O_TIMESTR_LOG_LEN);
            *pos++ = ']';
            break;
        case ELEMENT_TYPE_REQUEST_LINE:
            RESERVE((req->method.len + req->path.len) * 4 + sizeof("  HTTP/1.2147483647") - 1);
            pos = append_unsafe_string(pos, req->method.base, req->method.len);
            *pos++ = ' ';
            pos = append_unsafe_string(pos, req->path.base, req->path.len);
            *pos++ = ' ';
            if (req->version < 0x200) {
                pos = append_safe_string(pos, H2O_STRLIT("HTTP/1."));
                if ((req->version & 0xff) <= 9) {
                    *pos++ = '0' + (req->version & 0xff);
                } else {
                    pos += sprintf(pos, "%d", req->version);
                }
            } else {
                pos = append_safe_string(pos, H2O_STRLIT("HTTP/2"));
            }
            break;
        case ELEMENT_TYPE_STATUS:
            RESERVE(sizeof("2147483647") - 1);
            pos += sprintf(pos, "%d", req->res.status);
            break;
        case ELEMENT_TYPE_BYTES_SENT:
            RESERVE(sizeof("18446744073709551615") - 1);
            pos += sprintf(pos, "%llu", (unsigned long long)req->bytes_sent);
            break;
        default:
            assert(!"unknown type");
            break;
        }
Esempio n. 2
0
static void log_access(h2o_logger_t *_self, h2o_req_t *req)
{
    struct st_h2o_access_logger_t *self = (struct st_h2o_access_logger_t *)_self;
    h2o_access_log_filehandle_t *fh = self->fh;
    char *line, *pos, *line_end;
    size_t element_index;

    /* note: LOG_ALLOCA_SIZE should be much greater than NI_MAXHOST to avoid unnecessary reallocations */
    line = alloca(LOG_ALLOCA_SIZE);
    pos = line;
    line_end = line + LOG_ALLOCA_SIZE;

    for (element_index = 0; element_index != fh->num_elements; ++element_index) {
        struct log_element_t *element = fh->elements + element_index;

/* reserve capacity + suffix.len */
#define RESERVE(capacity)                                                                                                          \
    do {                                                                                                                           \
        if ((capacity) + element->suffix.len > line_end - pos) {                                                                   \
            size_t off = pos - line;                                                                                               \
            line = expand_line_buf(line, line_end - line, off + (capacity) + element->suffix.len);                                 \
            pos = line + off;                                                                                                      \
        }                                                                                                                          \
    } while (0)

        switch (element->type) {
        case ELEMENT_TYPE_EMPTY:
            RESERVE(0);
            break;
        case ELEMENT_TYPE_BYTES_SENT: /* %b */
            RESERVE(sizeof("18446744073709551615") - 1);
            pos += sprintf(pos, "%llu", (unsigned long long)req->bytes_sent);
            break;
        case ELEMENT_TYPE_PROTOCOL: /* %H */
            RESERVE(sizeof("HTTP/1.1"));
            pos += h2o_stringify_protocol_version(pos, req->version);
            break;
        case ELEMENT_TYPE_REMOTE_ADDR: /* %h */ {
            struct sockaddr_storage ss;
            socklen_t sslen;
            if ((sslen = req->conn->get_peername(req->conn, (void *)&ss)) != 0) {
                RESERVE(NI_MAXHOST);
                size_t l = h2o_socket_getnumerichost((void *)&ss, sslen, pos);
                if (l != SIZE_MAX)
                    pos += l;
                else
                    *pos++ = '-';
            } else {
                RESERVE(1);
                *pos++ = '-';
            }
        } break;
        case ELEMENT_TYPE_METHOD: /* %m */
            RESERVE(req->input.method.len * 4);
            pos = append_unsafe_string(pos, req->input.method.base, req->input.method.len);
            break;
        case ELEMENT_TYPE_QUERY: /* %q */
            if (req->input.query_at != SIZE_MAX) {
                size_t len = req->input.path.len - req->input.query_at;
                RESERVE(len * 4);
                pos = append_unsafe_string(pos, req->input.path.base + req->input.query_at, len);
            }
            break;
        case ELEMENT_TYPE_REQUEST_LINE: /* %r */
            RESERVE((req->input.method.len + req->input.path.len) * 4 + sizeof("  HTTP/1.1"));
            pos = append_unsafe_string(pos, req->input.method.base, req->input.method.len);
            *pos++ = ' ';
            pos = append_unsafe_string(pos, req->input.path.base, req->input.path.len);
            *pos++ = ' ';
            pos += h2o_stringify_protocol_version(pos, req->version);
            break;
        case ELEMENT_TYPE_STATUS: /* %s */
            RESERVE(sizeof("2147483647") - 1);
            pos += sprintf(pos, "%d", req->res.status);
            break;
        case ELEMENT_TYPE_TIMESTAMP: /* %t */
            RESERVE(H2O_TIMESTR_LOG_LEN + 2);
            *pos++ = '[';
            pos = append_safe_string(pos, req->processed_at.str->log, H2O_TIMESTR_LOG_LEN);
            *pos++ = ']';
            break;
        case ELEMENT_TYPE_URL_PATH: /* %U */
        {
            size_t path_len = req->input.query_at == SIZE_MAX ? req->input.path.len : req->input.query_at;
            RESERVE(req->input.scheme->name.len + (sizeof("://") - 1) + (req->input.authority.len + path_len) * 4);
            pos = append_safe_string(pos, req->input.scheme->name.base, req->input.scheme->name.len);
            pos = append_safe_string(pos, H2O_STRLIT("://"));
            pos = append_unsafe_string(pos, req->input.authority.base, req->input.authority.len);
            pos = append_unsafe_string(pos, req->input.path.base, path_len);
        } break;
        case ELEMENT_TYPE_AUTHORITY: /* %V */
            RESERVE(req->input.authority.len * 4);
            pos = append_unsafe_string(pos, req->input.authority.base, req->input.authority.len);
            break;
        case ELEMENT_TYPE_HOSTCONF: /* %v */
            RESERVE(req->hostconf->authority.hostport.len * 4);
            pos = append_unsafe_string(pos, req->hostconf->authority.hostport.base, req->hostconf->authority.hostport.len);
            break;

        case ELEMENT_TYPE_LOGNAME:     /* %l */
        case ELEMENT_TYPE_REMOTE_USER: /* %u */
            RESERVE(1);
            *pos++ = '-';
            break;

#define EMIT_HEADER(headers, _index)                                                                                               \
    do {                                                                                                                           \
        ssize_t index = (_index);                                                                                                  \
        if (index != -1) {                                                                                                         \
            const h2o_header_t *header = (headers)->entries + index;                                                               \
            RESERVE(header->value.len * 4);                                                                                        \
            pos = append_unsafe_string(pos, header->value.base, header->value.len);                                                \
        } else {                                                                                                                   \
            RESERVE(1);                                                                                                            \
            *pos++ = '-';                                                                                                          \
        }                                                                                                                          \
    } while (0)
        case ELEMENT_TYPE_IN_HEADER_TOKEN:
            EMIT_HEADER(&req->headers, h2o_find_header(&req->headers, element->data.header_token, SIZE_MAX));
            break;
        case ELEMENT_TYPE_IN_HEADER_STRING:
            EMIT_HEADER(&req->headers, h2o_find_header_by_str(&req->headers, element->data.header_string.base,
                                                              element->data.header_string.len, SIZE_MAX));
            break;
        case ELEMENT_TYPE_OUT_HEADER_TOKEN:
            EMIT_HEADER(&req->res.headers, h2o_find_header(&req->res.headers, element->data.header_token, SIZE_MAX));
            break;
        case ELEMENT_TYPE_OUT_HEADER_STRING:
            EMIT_HEADER(&req->res.headers, h2o_find_header_by_str(&req->res.headers, element->data.header_string.base,
                                                                  element->data.header_string.len, SIZE_MAX));
            break;
#undef EMIT_HEADER

        default:
            assert(!"unknown type");
            break;
        }

#undef RESERVE

        pos = append_safe_string(pos, element->suffix.base, element->suffix.len);
    }

    write(fh->fd, line, pos - line);

    if (line_end - line != LOG_ALLOCA_SIZE)
        free(line);
}
Esempio n. 3
0
        case ELEMENT_TYPE_STATUS:
            RESERVE(sizeof("2147483647") - 1);
            pos += sprintf(pos, "%d", req->res.status);
            break;
        case ELEMENT_TYPE_BYTES_SENT:
            RESERVE(sizeof("18446744073709551615") - 1);
            pos += sprintf(pos, "%llu", (unsigned long long)req->bytes_sent);
            break;
        default:
            assert(!"unknown type");
            break;
        }

#undef RESERVE

        pos = append_safe_string(pos, element->suffix.base, element->suffix.len);
    }

    write(self->fd, line, pos - line);

    if (line_end - line != LOG_ALLOCA_SIZE)
        free(line);
}

static void destroy(h2o_logger_t *_self)
{
    struct st_h2o_access_logger_t *self = (void*)_self;
    size_t i;

    for (i = 0; i != self->num_elements; ++i)
        free(self->elements[i].suffix.base);