diff options
Diffstat (limited to 'ot_http.c')
| -rw-r--r-- | ot_http.c | 93 |
1 files changed, 56 insertions, 37 deletions
| @@ -121,9 +121,10 @@ ssize_t http_issue_error( const int64 sock, struct ot_workstruct *ws, int code ) | |||
| 121 | return ws->reply_size = -2; | 121 | return ws->reply_size = -2; |
| 122 | } | 122 | } |
| 123 | 123 | ||
| 124 | ssize_t http_sendiovecdata( const int64 sock, struct ot_workstruct *ws, int iovec_entries, struct iovec *iovector ) { | 124 | ssize_t http_sendiovecdata( const int64 sock, struct ot_workstruct *ws, int iovec_entries, struct iovec *iovector, int is_partial ) { |
| 125 | struct http_data *cookie = io_getcookie( sock ); | 125 | struct http_data *cookie = io_getcookie( sock ); |
| 126 | char *header; | 126 | char *header; |
| 127 | const char *encoding = ""; | ||
| 127 | int i; | 128 | int i; |
| 128 | size_t header_size, size = iovec_length( &iovec_entries, (const struct iovec **)&iovector ); | 129 | size_t header_size, size = iovec_length( &iovec_entries, (const struct iovec **)&iovector ); |
| 129 | tai6464 t; | 130 | tai6464 t; |
| @@ -140,54 +141,72 @@ ssize_t http_sendiovecdata( const int64 sock, struct ot_workstruct *ws, int iove | |||
| 140 | /* If we came here, wait for the answer is over */ | 141 | /* If we came here, wait for the answer is over */ |
| 141 | cookie->flag &= ~STRUCT_HTTP_FLAG_WAITINGFORTASK; | 142 | cookie->flag &= ~STRUCT_HTTP_FLAG_WAITINGFORTASK; |
| 142 | 143 | ||
| 143 | /* Our answers never are 0 vectors. Return an error. */ | 144 | fprintf(stderr, "http_sendiovecdata sending %d iovec entries found cookie->batch == %p\n", iovec_entries, cookie->batch); |
| 144 | if( !iovec_entries ) { | ||
| 145 | HTTPERROR_500; | ||
| 146 | } | ||
| 147 | 145 | ||
| 148 | /* Prepare space for http header */ | 146 | if( iovec_entries ) { |
| 149 | header = malloc( SUCCESS_HTTP_HEADER_LENGTH + SUCCESS_HTTP_HEADER_LENGTH_CONTENT_ENCODING ); | ||
| 150 | if( !header ) { | ||
| 151 | iovec_free( &iovec_entries, &iovector ); | ||
| 152 | HTTPERROR_500; | ||
| 153 | } | ||
| 154 | 147 | ||
| 155 | if( cookie->flag & STRUCT_HTTP_FLAG_GZIP ) | 148 | /* Prepare space for http header */ |
| 156 | header_size = sprintf( header, "HTTP/1.0 200 OK\r\nContent-Type: text/plain\r\nContent-Encoding: gzip\r\nContent-Length: %zd\r\n\r\n", size ); | 149 | header = malloc( SUCCESS_HTTP_HEADER_LENGTH + SUCCESS_HTTP_HEADER_LENGTH_CONTENT_ENCODING ); |
| 157 | else if( cookie->flag & STRUCT_HTTP_FLAG_BZIP2 ) | 150 | if( !header ) { |
| 158 | header_size = sprintf( header, "HTTP/1.0 200 OK\r\nContent-Type: text/plain\r\nContent-Encoding: bzip2\r\nContent-Length: %zd\r\n\r\n", size ); | 151 | iovec_free( &iovec_entries, &iovector ); |
| 159 | else | 152 | HTTPERROR_500; |
| 160 | header_size = sprintf( header, "HTTP/1.0 200 OK\r\nContent-Type: text/plain\r\nContent-Length: %zd\r\n\r\n", size ); | 153 | } |
| 161 | 154 | ||
| 162 | if (!cookie->batch ) { | 155 | if( cookie->flag & STRUCT_HTTP_FLAG_GZIP ) |
| 163 | cookie->batch = malloc( sizeof(io_batch) ); | 156 | encoding = "Content-Encoding: gzip\r\n"; |
| 164 | memset( cookie->batch, 0, sizeof(io_batch) ); | 157 | else if( cookie->flag & STRUCT_HTTP_FLAG_BZIP2 ) |
| 165 | cookie->batches = 1; | 158 | encoding = "Content-Encoding: bzip2\r\n"; |
| 166 | } | 159 | |
| 167 | iob_addbuf_free( cookie->batch, header, header_size ); | 160 | if( !(cookie->flag & STRUCT_HTTP_FLAG_CHUNKED) ) |
| 161 | header_size = sprintf( header, "HTTP/1.0 200 OK\r\nContent-Type: text/plain\r\n%sContent-Length: %zd\r\n\r\n", encoding, size ); | ||
| 162 | else { | ||
| 163 | if ( !(cookie->flag & STRUCT_HTTP_FLAG_CHUNKED_IN_TRANSFER )) { | ||
| 164 | header_size = sprintf( header, "HTTP/1.0 200 OK\r\nContent-Type: text/plain\r\n%sTransfer-Encoding: chunked\r\n\r\n%zx\r\n", encoding, size ); | ||
| 165 | cookie->flag |= STRUCT_HTTP_FLAG_CHUNKED_IN_TRANSFER; | ||
| 166 | } else | ||
| 167 | header_size = sprintf( header, "%zx\r\n", size ); | ||
| 168 | } | ||
| 168 | 169 | ||
| 169 | /* Split huge iovectors into separate io_batches */ | 170 | if (!cookie->batch ) { |
| 170 | for( i=0; i<iovec_entries; ++i ) { | 171 | cookie->batch = malloc( sizeof(io_batch) ); |
| 171 | io_batch *current = cookie->batch + cookie->batches - 1; | 172 | memset( cookie->batch, 0, sizeof(io_batch) ); |
| 173 | cookie->batches = 1; | ||
| 174 | } | ||
| 175 | iob_addbuf_free( cookie->batch, header, header_size ); | ||
| 172 | 176 | ||
| 173 | /* If the current batch's limit is reached, try to reallocate a new batch to work on */ | 177 | /* Split huge iovectors into separate io_batches */ |
| 174 | if( current->bytesleft > OT_BATCH_LIMIT ) { | 178 | for( i=0; i<iovec_entries; ++i ) { |
| 175 | io_batch * new_batch = realloc( current, (cookie->batches + 1) * sizeof(io_batch) ); | 179 | io_batch *current = cookie->batch + cookie->batches - 1; |
| 180 | |||
| 181 | /* If the current batch's limit is reached, try to reallocate a new batch to work on */ | ||
| 182 | if( current->bytesleft > OT_BATCH_LIMIT ) { | ||
| 183 | fprintf(stderr, "http_sendiovecdata found batch above limit: %zd\n", current->bytesleft); | ||
| 184 | io_batch * new_batch = realloc( cookie->batch, (cookie->batches + 1) * sizeof(io_batch) ); | ||
| 176 | if( new_batch ) { | 185 | if( new_batch ) { |
| 177 | cookie->batches++; | 186 | cookie->batch = new_batch; |
| 178 | current = cookie->batch = new_batch; | 187 | current = cookie->batch + cookie->batches++; |
| 179 | memset( current, 0, sizeof(io_batch) ); | 188 | memset( current, 0, sizeof(io_batch) ); |
| 180 | } | 189 | } |
| 190 | } | ||
| 191 | fprintf(stderr, "http_sendiovecdata calling iob_addbuf_free with %zd\n", iovector[i].iov_len); | ||
| 192 | iob_addbuf_free( current, iovector[i].iov_base, iovector[i].iov_len ); | ||
| 181 | } | 193 | } |
| 194 | free( iovector ); | ||
| 195 | if ( cookie->flag & STRUCT_HTTP_FLAG_CHUNKED_IN_TRANSFER ) | ||
| 196 | iob_addbuf(cookie->batch + cookie->batches - 1, "\r\n", 2); | ||
| 197 | } | ||
| 182 | 198 | ||
| 183 | iob_addbuf_free( current, iovector[i].iov_base, iovector[i].iov_len ); | 199 | if ((cookie->flag & STRUCT_HTTP_FLAG_CHUNKED_IN_TRANSFER) && cookie->batch && !is_partial) { |
| 200 | fprintf(stderr, "http_sendiovecdata adds a terminating 0 size buffer to batch\n"); | ||
| 201 | iob_addbuf(cookie->batch + cookie->batches - 1, "0\r\n\r\n", 5); | ||
| 202 | cookie->flag &= ~STRUCT_HTTP_FLAG_CHUNKED_IN_TRANSFER; | ||
| 184 | } | 203 | } |
| 185 | free( iovector ); | ||
| 186 | 204 | ||
| 187 | /* writeable sockets timeout after 10 minutes */ | 205 | /* writeable sockets timeout after 10 minutes */ |
| 188 | taia_now( &t ); taia_addsec( &t, &t, OT_CLIENT_TIMEOUT_SEND ); | 206 | taia_now( &t ); taia_addsec( &t, &t, OT_CLIENT_TIMEOUT_SEND ); |
| 189 | io_timeout( sock, t ); | 207 | io_timeout( sock, t ); |
| 190 | io_dontwantread( sock ); | 208 | io_dontwantread( sock ); |
| 209 | fprintf (stderr, "http_sendiovecdata marks socket %lld as wantwrite\n", sock); | ||
| 191 | io_wantwrite( sock ); | 210 | io_wantwrite( sock ); |
| 192 | return 0; | 211 | return 0; |
| 193 | } | 212 | } |
| @@ -254,7 +273,7 @@ static const ot_keywords keywords_format[] = | |||
| 254 | #endif | 273 | #endif |
| 255 | #endif | 274 | #endif |
| 256 | /* Pass this task to the worker thread */ | 275 | /* Pass this task to the worker thread */ |
| 257 | cookie->flag |= STRUCT_HTTP_FLAG_WAITINGFORTASK; | 276 | cookie->flag |= STRUCT_HTTP_FLAG_WAITINGFORTASK | STRUCT_HTTP_FLAG_CHUNKED; |
| 258 | 277 | ||
| 259 | /* Clients waiting for us should not easily timeout */ | 278 | /* Clients waiting for us should not easily timeout */ |
| 260 | taia_uint( &t, 0 ); io_timeout( sock, t ); | 279 | taia_uint( &t, 0 ); io_timeout( sock, t ); |
| @@ -278,7 +297,7 @@ static const ot_keywords keywords_format[] = | |||
| 278 | } | 297 | } |
| 279 | 298 | ||
| 280 | #ifdef WANT_MODEST_FULLSCRAPES | 299 | #ifdef WANT_MODEST_FULLSCRAPES |
| 281 | static pthread_mutex_t g_modest_fullscrape_mutex = PTHREAD_MUTEX_INITIALIZER; | 300 | static pthread_mutex_t g_modest_fullscrape_mutex = PTHREAD_MUTEX_INITIALIZER; |
| 282 | static ot_vector g_modest_fullscrape_timeouts; | 301 | static ot_vector g_modest_fullscrape_timeouts; |
| 283 | typedef struct { ot_ip6 ip; ot_time last_fullscrape; } ot_scrape_log; | 302 | typedef struct { ot_ip6 ip; ot_time last_fullscrape; } ot_scrape_log; |
| 284 | #endif | 303 | #endif |
| @@ -325,7 +344,7 @@ static ssize_t http_handle_fullscrape( const int64 sock, struct ot_workstruct *w | |||
| 325 | #endif | 344 | #endif |
| 326 | 345 | ||
| 327 | /* Pass this task to the worker thread */ | 346 | /* Pass this task to the worker thread */ |
| 328 | cookie->flag |= STRUCT_HTTP_FLAG_WAITINGFORTASK; | 347 | cookie->flag |= STRUCT_HTTP_FLAG_WAITINGFORTASK | STRUCT_HTTP_FLAG_CHUNKED; |
| 329 | /* Clients waiting for us should not easily timeout */ | 348 | /* Clients waiting for us should not easily timeout */ |
| 330 | taia_uint( &t, 0 ); io_timeout( sock, t ); | 349 | taia_uint( &t, 0 ); io_timeout( sock, t ); |
| 331 | fullscrape_deliver( sock, TASK_FULLSCRAPE | format ); | 350 | fullscrape_deliver( sock, TASK_FULLSCRAPE | format ); |
