/** * Convert current header to a string. * * @attention * NB: returns pointer to static data! */ const char * header_fmt_to_string(const header_fmt_t *hf) { static char line[HEADER_FMT_MAX_SIZE + 1]; header_fmt_check(hf); if (str_len(hf->header) >= sizeof line) { g_warning("trying to format too long an HTTP line (%lu bytes)", (unsigned long) str_len(hf->header)); } clamp_strncpy(line, sizeof line, str_2c(hf->header), str_len(hf->header)); return line; }
/** * Get the raw message name present at the start of a G2 packet. * * @param start start of message * @param len amount of consecutive bytes we have so far * * @return the message name if we can intuit it, an empty string otherwise. */ const char * g2_msg_raw_name(const void *start, size_t len) { const char *name; size_t namelen; char buf[G2_FRAME_NAME_LEN_MAX + 1]; name = g2_frame_name(start, len, &namelen); if (NULL == name) return ""; clamp_strncpy(buf, sizeof buf, name, namelen); return constant_str(buf); }
/** * Fetch next token from input string. */ static struct ctl_tok * ctl_next_token(struct ctl_string *s) { /* * If we have a read-ahead token, reuse it. */ if (s->unread != NULL) { struct ctl_tok *tok = s->unread; s->unread = NULL; return tok; } /* * Read next token. */ s->p = skip_ascii_blanks(s->p); if ('\0' == *s->p) return ctl_token_alloc(CTL_TOK_EOF, s->p); switch (*s->p) { case '{': s->p++; return ctl_token_alloc(CTL_TOK_LBRACE, s->p); case '}': s->p++; return ctl_token_alloc(CTL_TOK_RBRACE, s->p); case ':': s->p++; return ctl_token_alloc(CTL_TOK_COLON, s->p); case ',': s->p++; return ctl_token_alloc(CTL_TOK_COMMA, s->p); default: break; } if (is_ascii_alnum(*s->p)) { const char *start = s->p; struct ctl_tok *tok = ctl_token_alloc(CTL_TOK_ID, s->p); size_t len; s->p = skip_ascii_alnum(s->p); len = s->p - start; tok->val.s = halloc(len + 1); clamp_strncpy(tok->val.s, len + 1, start, len); return tok; } else { struct ctl_tok *tok = ctl_token_alloc(CTL_TOK_ERROR, s->p); tok->val.c = *s->p; return tok; } g_assert_not_reached(); return NULL; }
/** * Adds the X-Features header to a HTTP request. * * @param xfeatures structure holding the collected features * @param buf should point to the beginning of the header. * @param len no brief description. * @param rw the number of bytes that were already written. * * *rw is changed too *rw + bytes written */ void header_features_generate(xfeature_t xf, char *dst, size_t len, size_t *rw) { static const char hdr[] = "X-Features"; struct features *features; GList *cur; header_fmt_t *fmt; g_assert(len <= INT_MAX); g_assert(*rw <= INT_MAX); g_assert(len >= *rw); if (len - *rw < (sizeof(hdr) + sizeof(": \r\n") - 1)) return; features = features_get(xf); g_return_if_fail(features); if (g_list_first(features->list) == NULL) return; fmt = header_fmt_make(hdr, ", ", 0, len - *rw); for (cur = g_list_first(features->list); cur; cur = g_list_next(cur)) { struct header_x_feature *item = cur->data; char buf[50]; if (item->guard && !*item->guard) continue; if (item->guardfn && !(*item->guardfn)()) continue; gm_snprintf(buf, sizeof buf, "%s/%d.%d", item->name, item->major, item->minor); header_fmt_append_value(fmt, buf); } header_fmt_end(fmt); if (header_fmt_length(fmt) < len - *rw) { *rw += clamp_strncpy(&dst[*rw], len - *rw, header_fmt_string(fmt), header_fmt_length(fmt)); } header_fmt_free(&fmt); }
/** * Convert current header to a string. * * @attention * NB: returns pointer to static data! */ const char * header_fmt_to_string(const header_fmt_t *hf) { buf_t *b = buf_private(G_STRFUNC, HEADER_FMT_MAX_SIZE + 1); char *p = buf_data(b); size_t n = buf_size(b); header_fmt_check(hf); if (str_len(hf->header) >= n) { g_warning("trying to format too long an HTTP line (%zu bytes)", str_len(hf->header)); } clamp_strncpy(p, n, str_2c(hf->header), str_len(hf->header)); return p; }