| /** @file |
| |
| A brief file description |
| |
| @section license License |
| |
| Licensed to the Apache Software Foundation (ASF) under one |
| or more contributor license agreements. See the NOTICE file |
| distributed with this work for additional information |
| regarding copyright ownership. The ASF licenses this file |
| to you under the Apache License, Version 2.0 (the |
| "License"); you may not use this file except in compliance |
| with the License. You may obtain a copy of the License at |
| |
| http://www.apache.org/licenses/LICENSE-2.0 |
| |
| Unless required by applicable law or agreed to in writing, software |
| distributed under the License is distributed on an "AS IS" BASIS, |
| WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| See the License for the specific language governing permissions and |
| limitations under the License. |
| */ |
| |
| /**************************************************************************** |
| |
| load_http_hdr.cc |
| |
| Description: |
| |
| Opens a file with a dbx dump of an http hdr and loads it |
| |
| |
| ****************************************************************************/ |
| |
| /*************************************************************************** |
| * USAGE NOTE: This program was orignally built for reading TS 3.0.X & |
| * TS 3.5.X header dumps. These data structures were always continguous. |
| * TS 4.0.X and later have completely redesigned data structures that |
| * are more complicated but much faster. This program has been adapted |
| * read headers that have been unmarshalled from cache, in which |
| * case they are contiguious. It's conversion is in a half baked |
| * state and is therefore not useful for must purposes. |
| ***************************************************************************/ |
| |
| #include "HdrHeap.h" |
| #include "MIME.h" |
| #include "HTTP.h" |
| #include "tscore/Tokenizer.h" |
| #include "tscore/Diags.h" |
| #include <stdio.h> |
| #include <errno.h> |
| #include <sys/types.h> |
| #include <sys/stat.h> |
| #include <fcntl.h> |
| #include <unistd.h> |
| |
| void *low_load_addr = NULL; |
| void *high_load_addr = NULL; |
| int heap_load_size = 0; |
| int marshalled = 0; |
| |
| // Diags *diags; |
| |
| enum hdr_type { |
| UNKNOWN_HDR, |
| REQUEST_HDR, |
| RESPONSE_HDR, |
| HTTP_INFO_HDR, |
| RAW_MBUFFER, |
| }; |
| |
| char * |
| load_string(const char *s, int len, int offset) |
| { |
| const char *copy_from; |
| if (marshalled == 0 && s > low_load_addr && s + len < high_load_addr) { |
| copy_from = s + offset; |
| } else if (marshalled && ((unsigned int)s) + len < (unsigned int)heap_load_size) { |
| copy_from = s + offset; |
| } else { |
| copy_from = "<BAD>"; |
| len = strlen(copy_from); |
| } |
| char *r = (char *)ats_malloc(len + 1); |
| memcpy(r, copy_from, len); |
| r[len] = '\0'; |
| return r; |
| } |
| |
| void |
| process_http_hdr_impl(HdrHeapObjImpl *obj, int offset) |
| { |
| char *s; |
| HTTPHdrImpl *hhdr = (HTTPHdrImpl *)obj; |
| |
| if (hhdr->m_polarity == HTTP_TYPE_REQUEST) { |
| printf(" is a request hdr\n"); |
| s = load_string(hhdr->u.req.m_ptr_method, hhdr->u.req.m_len_method, offset); |
| printf(" method: %s\n", s); |
| ats_free(s); |
| } else if (hhdr->m_polarity == HTTP_TYPE_RESPONSE) { |
| printf(" is a response hdr\n"); |
| printf(" status code: %d\n", (int)hhdr->u.resp.m_status); |
| s = load_string(hhdr->u.resp.m_ptr_reason, hhdr->u.resp.m_len_reason, offset); |
| printf(" method: %s\n", s); |
| ats_free(s); |
| } |
| } |
| |
| void |
| process_mime_block_impl(MIMEFieldBlockImpl *mblock, int offset) |
| { |
| printf(" Processing mime_flock_impl - freetop %d\n", mblock->m_freetop); |
| int freetop; |
| if (mblock->m_freetop <= MIME_FIELD_BLOCK_SLOTS) { |
| freetop = mblock->m_freetop; |
| } else { |
| freetop = MIME_FIELD_BLOCK_SLOTS; |
| } |
| |
| char *n, *v; |
| for (unsigned int i = 0; i < freetop; i++) { |
| MIMEField *f = &mblock->m_field_slots[i]; |
| if (hdrtoken_is_valid_wks_idx(f->m_wks_idx)) { |
| n = ats_strdup(hdrtoken_index_to_wks(f->m_wks_idx)); |
| } else { |
| n = load_string(f->m_ptr_name, f->m_len_name, offset); |
| } |
| v = load_string(f->m_ptr_value, f->m_len_value, offset); |
| printf(" (%d) %s: %s\n", i, n, v); |
| ats_free(n); |
| ats_free(v); |
| } |
| } |
| |
| void |
| process_mime_hdr_impl(HdrHeapObjImpl *obj, int offset) |
| { |
| MIMEHdrImpl *mhdr = (MIMEHdrImpl *)obj; |
| |
| process_mime_block_impl(&mhdr->m_first_fblock, offset); |
| } |
| |
| void |
| loop_over_heap_objs(HdrHeap *hdr_heap, int offset) |
| { |
| char *buffer_end; |
| |
| printf("Looping over HdrHeap objects @ 0x%X\n", hdr_heap); |
| |
| if (hdr_heap->m_magic == HDR_BUF_MAGIC_MARSHALED) { |
| printf(" marshalled heap - size %d\n", hdr_heap->m_size); |
| hdr_heap->m_data_start = ((char *)hdr_heap) + ROUND(sizeof(HdrHeap), HDR_PTR_SIZE); |
| hdr_heap->m_free_start = ((char *)hdr_heap) + hdr_heap->m_size; |
| } else { |
| buffer_end = hdr_heap->m_free_start; |
| } |
| |
| printf(" heap len is %d bytes\n", hdr_heap->m_free_start - hdr_heap->m_data_start); |
| |
| char *obj_data = hdr_heap->m_data_start; |
| while (obj_data < hdr_heap->m_free_start) { |
| HdrHeapObjImpl *obj = (HdrHeapObjImpl *)obj_data; |
| |
| switch (obj->m_type) { |
| case HDR_HEAP_OBJ_HTTP_HEADER: |
| printf(" HDR_HEAP_OBJ_HTTP_HEADER %d bytes\n", obj->m_length); |
| process_http_hdr_impl(obj, offset); |
| break; |
| case HDR_HEAP_OBJ_URL: |
| printf(" HDR_HEAP_OBJ_URL %d bytes\n", obj->m_length); |
| break; |
| case HDR_HEAP_OBJ_FIELD_BLOCK: |
| printf(" HDR_HEAP_OBJ_FIELD_BLOCK %d bytes\n", obj->m_length); |
| break; |
| case HDR_HEAP_OBJ_MIME_HEADER: |
| printf(" HDR_HEAP_OBJ_MIME_HEADER %d bytes\n", obj->m_length); |
| process_mime_hdr_impl(obj, offset); |
| break; |
| case HDR_HEAP_OBJ_EMPTY: |
| printf(" HDR_HEAP_OBJ_EMPTY %d bytes\n", obj->m_length); |
| break; |
| default: |
| printf(" OBJ UNKONWN (%d) %d bytes\n", obj->m_type, obj->m_length); |
| } |
| |
| if (obj->m_length == 0) { |
| printf(" ERROR zero length object\n"); |
| break; |
| } |
| obj_data = obj_data + obj->m_length; |
| } |
| } |
| |
| void |
| load_buffer(int fd, hdr_type h_type) |
| { |
| struct stat s_info; |
| |
| if (fstat(fd, &s_info) < 0) { |
| fprintf(stderr, "Failed to stat data file : %s\n", strerror(errno)); |
| exit(1); |
| } |
| |
| char *file_buf = (char *)ats_malloc(sizeof(char) * (s_info.st_size + 1)); |
| file_buf[s_info.st_size] = '\0'; |
| |
| // Read in the entire file |
| int bytes_to_read = s_info.st_size; |
| while (bytes_to_read > 0) { |
| int done = read(fd, file_buf, bytes_to_read); |
| |
| if (done < 0) { |
| fprintf(stderr, "Failed to read data file : %s\n", strerror(errno)); |
| exit(1); |
| } else if (done == 0) { |
| fprintf(stderr, "EOF encounted\n"); |
| exit(1); |
| } |
| |
| bytes_to_read -= done; |
| } |
| |
| Tokenizer line_tok("\n"); |
| Tokenizer el_tok(" \t"); |
| |
| int num_lines = line_tok.Initialize(file_buf); |
| int num_el = el_tok.Initialize(line_tok[0]); |
| |
| if (num_el < 3) { |
| fprintf(stderr, "Corrupted data file\n"); |
| exit(1); |
| } |
| |
| void *old_addr = NULL; |
| if (sscanf(el_tok[0], "%x:", &old_addr) != 1) { |
| fprintf(stderr, "Corrupted data file\n"); |
| exit(1); |
| } |
| low_load_addr = old_addr; |
| |
| int hdr_size; |
| if (sscanf(el_tok[4], "%x", &hdr_size) != 1) { |
| fprintf(stderr, "Corrupted data file\n"); |
| exit(1); |
| } |
| hdr_size = (num_lines * 16); |
| heap_load_size = hdr_size; |
| |
| char *hdr_heap = (char *)ats_malloc(hdr_size); |
| int bytes_read = 0; |
| int cur_line = 0; |
| |
| while (cur_line < num_lines && bytes_read < hdr_size) { |
| int *cur_ptr; |
| num_el = el_tok.Initialize(line_tok[cur_line]); |
| |
| if (sscanf(el_tok[0], "%x:", &high_load_addr) != 1) { |
| fprintf(stderr, "Corrupted data file\n"); |
| exit(1); |
| } |
| high_load_addr = ((char *)high_load_addr) + (num_el * 4); |
| |
| int el; |
| for (int i = 1; i < num_el; i++) { |
| if (sscanf(el_tok[i], "%x", &el) != 1) { |
| fprintf(stderr, "Corrupted data file\n"); |
| exit(1); |
| } |
| cur_ptr = (int *)(hdr_heap + bytes_read); |
| *cur_ptr = el; |
| bytes_read += 4; |
| } |
| cur_line++; |
| } |
| |
| HdrHeap *my_heap = (HdrHeap *)hdr_heap; |
| int offset = hdr_heap - (char *)old_addr; |
| |
| // Patch up some values |
| if (my_heap->m_magic == HDR_BUF_MAGIC_MARSHALED) { |
| // HdrHeapObjImpl* obj; |
| // my_heap->unmarshal(hdr_size, HDR_HEAP_OBJ_HTTP_HEADER, &obj, NULL); |
| marshalled = 1; |
| offset = (int)hdr_heap; |
| } else { |
| my_heap->m_free_start = my_heap->m_free_start + offset; |
| my_heap->m_data_start = my_heap->m_data_start + offset; |
| my_heap->m_ronly_heap[0].m_heap_start = my_heap->m_ronly_heap[0].m_heap_start + offset; |
| } |
| loop_over_heap_objs(my_heap, offset); |
| } |
| |
| int |
| main(int argc, const char *argv[]) |
| { |
| hdr_type h_type = UNKNOWN_HDR; |
| |
| http_init(); |
| diags = new Diags(NULL, NULL); |
| if (argc != 3) { |
| fprintf(stderr, "Usage: %s req|res <file>\n", argv[0]); |
| exit(1); |
| } |
| |
| if (strcasecmp(argv[1], "req") == 0) { |
| h_type = REQUEST_HDR; |
| } else if (strcasecmp(argv[1], "resp") == 0) { |
| h_type = RESPONSE_HDR; |
| } else if (strcasecmp(argv[1], "hinfo") == 0) { |
| h_type = HTTP_INFO_HDR; |
| } else if (strcasecmp(argv[1], "mbuf") == 0) { |
| h_type = RAW_MBUFFER; |
| } else { |
| fprintf(stderr, "Usage: %s req|resp|hinfo|mbuf <file>\n", argv[0]); |
| exit(1); |
| } |
| |
| int fd = open(argv[2], O_RDONLY); |
| |
| if (fd < 0) { |
| fprintf(stderr, "Could not open file %s : %s\n", argv[2], strerror(errno)); |
| exit(1); |
| } |
| load_buffer(fd, h_type); |
| |
| return 0; |
| } |