Asterisk - The Open Source Telephony Project  21.4.1
Data Structures | Functions

Data Structures

struct  curl_header_data
 Context structure passed to ast_curl_header_default_cb. More...
 

Functions

size_t curl_header_cb (char *data, size_t size, size_t nitems, void *client_data)
 A default implementation of a header callback. More...
 
void curl_header_data_free (void *obj)
 

Detailed Description

If you need to access the headers returned on the response, you can define a callback that curl will call for every header it receives.

Your callback must follow the specification defined for CURLOPT_HEADERFUNCTION and implement the curl_write_callback prototype.

The following ast_curl_headers objects compose a default implementation that will accumulate the headers in an ast_variable list.

Function Documentation

size_t curl_header_cb ( char *  data,
size_t  size,
size_t  nitems,
void *  client_data 
)

A default implementation of a header callback.

This is an implementation of #CURLOPT_HEADERFUNCTION that performs basic sanity checks and saves headers in the ast_curl_header_data.headers ast_variable list.

The curl prototype for this function is curl_write_callback

Warning
If you decide to write your own callback, curl doesn't guarantee a terminating NULL in data passed to the callbacks!
Parameters
dataWill contain a header line that may not be NULL terminated.
sizeAlways 1.
nitemsThe number of bytes in data.
client_dataA pointer to whatever structure you passed to ast_curler in the curl_header_data parameter.
Returns
Number of bytes handled. Must be (size * nitems) or an error is signalled.

Definition at line 39 of file curl_utils.c.

References ast_alloca, ast_begins_with(), ast_copy_string(), ast_skip_blanks(), ast_trim_blanks(), curl_header_data::debug_info, curl_header_data::headers, curl_header_data::max_header_len, S_OR, and ast_variable::value.

Referenced by curler().

41 {
42  struct curl_header_data *cb_data = client_data;
43  size_t realsize = size * nitems;
44  size_t adjusted_size = realsize;
45  char *debug_info = S_OR(cb_data->debug_info, "");
46  char *start = data;
47  char *colon = NULL;
48  struct ast_variable *h;
49  char *header;
50  char *value;
51  SCOPE_ENTER(5, "'%s': Header received with %zu bytes\n",
52  debug_info, realsize);
53 
54  if (cb_data->max_header_len == 0) {
55  cb_data->max_header_len = AST_CURL_DEFAULT_MAX_HEADER_LEN;
56  }
57 
58  if (realsize > cb_data->max_header_len) {
59  /*
60  * Silently ignore any header over the length limit.
61  */
62  SCOPE_EXIT_RTN_VALUE(realsize, "oversize header: %zu > %zu\n",
63  realsize, cb_data->max_header_len);
64  }
65 
66  /* Per CURL: buffer may not be NULL terminated. */
67 
68  /* Skip blanks */
69  while (*start && ((unsigned char) *start) < 33 && start < data + realsize) {
70  start++;
71  adjusted_size--;
72  }
73 
74  if (adjusted_size < strlen("HTTP/") + 1) {
75  /* this is probably the \r\n\r\n sequence that ends the headers */
76  cb_data->_capture = 0;
77  SCOPE_EXIT_RTN_VALUE(realsize, "undersized header. probably end-of-headers marker: %zu\n",
78  adjusted_size);
79  }
80 
81  /*
82  * We only want headers from a 2XX response
83  * so don't start capturing until we see
84  * the 2XX.
85  */
86  if (ast_begins_with(start, "HTTP/")) {
87  int code;
88  /*
89  * HTTP/1.1 200 OK
90  * We want there to be a version after the HTTP/
91  * and reason text after the code but we don't care
92  * what they are.
93  */
94  int rc = sscanf(start, "HTTP/%*s %d %*s", &code);
95  if (rc == 1) {
96  if (code / 100 == 2) {
97  cb_data->_capture = 1;
98  }
99  }
100  SCOPE_EXIT_RTN_VALUE(realsize, "HTTP response code: %d\n",
101  code);
102  }
103 
104  if (!cb_data->_capture) {
105  SCOPE_EXIT_RTN_VALUE(realsize, "not capturing\n");
106  }
107 
108  header = ast_alloca(adjusted_size + 1);
109  ast_copy_string(header, start, adjusted_size + 1);
110 
111  /* We have a NULL terminated string now */
112 
113  colon = strchr(header, ':');
114  if (!colon) {
115  SCOPE_EXIT_RTN_VALUE(realsize, "No colon in the header. Weird\n");
116  }
117 
118  *colon++ = '\0';
119  value = colon;
120  value = ast_skip_blanks(ast_trim_blanks(value));
121 
122  h = ast_variable_new(header, value, __FILE__);
123  if (!h) {
124  SCOPE_EXIT_LOG_RTN_VALUE(CURL_WRITEFUNC_ERROR, LOG_WARNING,
125  "'%s': Unable to allocate memory for header '%s'\n",
126  debug_info, header);
127  }
128  ast_variable_list_append(&cb_data->headers, h);
129 
130  SCOPE_EXIT_RTN_VALUE(realsize, "header: <%s> value: <%s>",
131  header, value);
132 }
size_t max_header_len
Definition: curl_utils.h:173
Structure for variables, used for configurations and for channel variables.
Context structure passed to ast_curl_header_default_cb.
Definition: curl_utils.h:163
#define ast_alloca(size)
call __builtin_alloca to ensure we get gcc builtin semantics
Definition: astmm.h:288
char * ast_skip_blanks(const char *str)
Gets a pointer to the first non-whitespace character in a string.
Definition: strings.h:161
char * ast_trim_blanks(char *str)
Trims trailing whitespace characters from a string.
Definition: strings.h:186
void ast_copy_string(char *dst, const char *src, size_t size)
Size-limited null-terminating string copy.
Definition: strings.h:425
#define S_OR(a, b)
returns the equivalent of logic or for strings: first one if not empty, otherwise second one...
Definition: strings.h:80
static int force_inline attribute_pure ast_begins_with(const char *str, const char *prefix)
Checks whether a string begins with another.
Definition: strings.h:97
struct ast_variable * headers
Definition: curl_utils.h:182