1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185
|
/** @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.
*/
/* SimSynthServerCache.c
*
*
* Description:
* Simulate server response that contains:
* - PSI header
* - PSI include in body
*
* Ratio for generating PSI response is specified in config file.
*
* Added Options in Synth_server.config -
* psi_ratio : percentage of response with psi embedded we want to generate
*/
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include "ServerAPI.h"
#define PSI_TAG_FORMAT "<!--include=file%d.txt-->"
#define PSI_TAG_MAX_SIZE 128
#define PSI_MIME_HEADER "X-Psi: true"
#define MAX_HEADER_RESPONSE 256
#define TRUE 1
#define FALSE 0
typedef struct {
int status_code;
long request_length;
long bytes_not_sent;
char header_response[MAX_HEADER_RESPONSE];
int done_sent_header; /* flag to see if header has been sent or not */
int psi;
} RequestInfo;
typedef struct {
double psi_ratio; /* for psi_ratio */
} SCPlugin;
SCPlugin my_plugin;
/* generate a random number to see if the document should include psi or not */
int
generate_psibility()
{
double rand;
rand = drand48();
if (rand < my_plugin.psi_ratio) {
return TRUE;
} else {
return FALSE;
}
}
void
TSOptionsProcess(char *option, char *value)
{
if (strcmp(option, "psi_ratio") == 0) {
fprintf(stderr, "psi ratio set to %d %%\n", atoi(value));
my_plugin.psi_ratio = (double)(atoi(value)) / 100.0;
}
}
void
TSPluginInit()
{
fprintf(stderr, "*** PSI Server ***\n");
TSFuncRegister(TS_FID_OPTIONS_PROCESS);
TSFuncRegister(TS_FID_RESPONSE_PREPARE);
TSFuncRegister(TS_FID_RESPONSE_PUT);
}
/* prepare response header for a request */
int
TSResponsePrepare(char *req_hdr, int req_len, void **response_id)
{
char *len_string;
RequestInfo *resp_id = (RequestInfo *)malloc(sizeof(RequestInfo));
resp_id->psi = generate_psibility();
resp_id->done_sent_header = FALSE;
if ((len_string = strstr(req_hdr, "length"))) {
len_string += strlen("length");
resp_id->request_length = atoi(len_string);
resp_id->bytes_not_sent = resp_id->request_length;
resp_id->status_code = 200;
if (resp_id->psi) {
sprintf(resp_id->header_response, "%s\r\n%s\r\n%s%ld\r\n%s\r\n\r\n", "HTTP/1.0 200 OK", "Content-type: text/plain",
"Content-length: ", resp_id->request_length, PSI_MIME_HEADER);
} else {
sprintf(resp_id->header_response, "%s\r\n%s\r\n%s%ld\r\n\r\n", "HTTP/1.0 200 OK", "Content-type: text/plain",
"Content-length: ", resp_id->request_length);
}
} else {
resp_id->request_length = -1;
resp_id->status_code = 404;
resp_id->bytes_not_sent = 0;
sprintf(resp_id->header_response, "%s\r\n%s\r\n\r\n", "HTTP/1.0 404 Not Found", "Content-type: text/plain");
}
*response_id = resp_id;
return TRUE;
}
/* put response (response header + response document) into buffer */
void
TSResponsePut(void **resp_id /* return */, void *resp_buffer /* return */, int *resp_bytes /* return */, int resp_buffer_size,
int bytes_last_response)
{
int i = 0;
RequestInfo *rid = *((RequestInfo **)resp_id);
/* copy the header into the response buffer */
if (!rid->done_sent_header) {
i = sprintf((char *)resp_buffer, "%s", rid->header_response);
rid->done_sent_header = TRUE;
}
/* copy the content into the response buffer */
/* for a psi response, it will look like: */
/* XXX...XXX<!--include=fileN.txt-->XXX...XXXE */
/* with 0<= N <= 99 */
/* */
/* for non psi response, it will looke like: */
/* XXX...XXXE */
if (rid->status_code == 200) {
/* buffer is not large enough to handle all content */
if (rid->bytes_not_sent + i > resp_buffer_size) {
memset((void *)((char *)resp_buffer + i), 'X', resp_buffer_size - i);
*resp_bytes = resp_buffer_size;
rid->bytes_not_sent -= (resp_buffer_size - i);
}
/* buffer is large enough to handle it in one shot */
else {
if (rid->psi) {
/* generate our psi tag: <!--include=fileN.txt--> */
char psi_tag[PSI_TAG_MAX_SIZE];
int len = sprintf(psi_tag, PSI_TAG_FORMAT, rand() % 100);
/* hopefully enough space for our include command */
if (rid->bytes_not_sent >= len) {
memcpy((void *)((char *)resp_buffer + i), psi_tag, len);
rid->bytes_not_sent -= len;
i += len;
}
}
memset((void *)((char *)resp_buffer + i), 'X', rid->bytes_not_sent);
memset((void *)((char *)resp_buffer + i + rid->bytes_not_sent - 1), 'E', 1);
*resp_bytes = rid->bytes_not_sent + i;
rid->bytes_not_sent = 0;
}
}
/* return NULL as the resp_id to indicate
* if it is the last TSResponsePut call */
if (rid->bytes_not_sent <= 0 || rid->status_code != 200) {
free(rid);
*((RequestInfo **)resp_id) = NULL;
}
}
|