00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024 #include "Regression.h"
00025 #include "api/ts/ts.h"
00026
00027 #include <arpa/inet.h>
00028 #include "P_Net.h"
00029 #include <records/I_RecHttp.h>
00030
00031 #define SDBG_TAG "SockServer"
00032 #define CDBG_TAG "SockClient"
00033
00034 #define IP(a,b,c,d) htonl((a) << 24 | (b) << 16 | (c) << 8 | (d))
00035
00036 #define SET_TEST_HANDLER(_d, _s) {_d = _s;}
00037
00038 #define MAGIC_ALIVE 0xfeedbaba
00039 #define MAGIC_DEAD 0xdeadbeef
00040
00041 #define SYNSERVER_LISTEN_PORT 3300
00042
00043 #define PROXY_CONFIG_NAME_HTTP_PORT "proxy.config.http.server_port"
00044 #define PROXY_HTTP_DEFAULT_PORT 8080
00045
00046 #define REQUEST_MAX_SIZE 4095
00047 #define RESPONSE_MAX_SIZE 4095
00048
00049 #define HTTP_REQUEST_END "\r\n\r\n"
00050
00051
00052 #define X_REQUEST_ID "X-Request-ID"
00053 #define X_RESPONSE_ID "X-Response-ID"
00054
00055 #define ERROR_BODY "TESTING ERROR PAGE"
00056 #define TRANSFORM_APPEND_STRING "This is a transformed response"
00057
00058
00059
00060
00061
00062 typedef int (*TxnHandler) (TSCont contp, TSEvent event, void *data);
00063
00064
00065 typedef struct
00066 {
00067 TSVConn vconn;
00068
00069 TSVIO read_vio;
00070 TSIOBuffer req_buffer;
00071 TSIOBufferReader req_reader;
00072
00073 TSVIO write_vio;
00074 TSIOBuffer resp_buffer;
00075 TSIOBufferReader resp_reader;
00076
00077 char request[REQUEST_MAX_SIZE + 1];
00078 int request_len;
00079
00080 TxnHandler current_handler;
00081 unsigned int magic;
00082 } ServerTxn;
00083
00084
00085 typedef struct
00086 {
00087 int accept_port;
00088 TSAction accept_action;
00089 TSCont accept_cont;
00090 unsigned int magic;
00091 } SocketServer;
00092
00093 typedef enum
00094 {
00095 REQUEST_SUCCESS,
00096 REQUEST_INPROGRESS,
00097 REQUEST_FAILURE
00098 } RequestStatus;
00099
00100
00101 typedef struct
00102 {
00103 TSVConn vconn;
00104
00105 TSVIO read_vio;
00106 TSIOBuffer req_buffer;
00107 TSIOBufferReader req_reader;
00108
00109 TSVIO write_vio;
00110 TSIOBuffer resp_buffer;
00111 TSIOBufferReader resp_reader;
00112
00113 char *request;
00114 char response[RESPONSE_MAX_SIZE + 1];
00115 int response_len;
00116
00117 RequestStatus status;
00118
00119 int connect_port;
00120 int local_port;
00121 uint64_t connect_ip;
00122 TSAction connect_action;
00123
00124 TxnHandler current_handler;
00125
00126 unsigned int magic;
00127 } ClientTxn;
00128
00129
00130
00131
00132
00133
00134
00135 static char *get_body_ptr(const char *request);
00136 static char *generate_request(int test_case);
00137 static char *generate_response(const char *request);
00138 static int get_request_id(TSHttpTxn txnp);
00139
00140
00141
00142 static ClientTxn *synclient_txn_create(void);
00143 static int synclient_txn_delete(ClientTxn * txn);
00144 static int synclient_txn_close(TSCont contp);
00145 static int synclient_txn_send_request(ClientTxn * txn, char *request);
00146 static int synclient_txn_send_request_to_vc(ClientTxn * txn, char *request, TSVConn vc);
00147 static int synclient_txn_read_response(TSCont contp);
00148 static int synclient_txn_read_response_handler(TSCont contp, TSEvent event, void *data);
00149 static int synclient_txn_write_request(TSCont contp);
00150 static int synclient_txn_write_request_handler(TSCont contp, TSEvent event, void *data);
00151 static int synclient_txn_connect_handler(TSCont contp, TSEvent event, void *data);
00152 static int synclient_txn_main_handler(TSCont contp, TSEvent event, void *data);
00153
00154
00155 SocketServer *synserver_create(int port);
00156 static int synserver_start(SocketServer * s);
00157 static int synserver_stop(SocketServer * s);
00158 static int synserver_delete(SocketServer * s);
00159 static int synserver_accept_handler(TSCont contp, TSEvent event, void *data);
00160 static int synserver_txn_close(TSCont contp);
00161 static int synserver_txn_write_response(TSCont contp);
00162 static int synserver_txn_write_response_handler(TSCont contp, TSEvent event, void *data);
00163 static int synserver_txn_read_request(TSCont contp);
00164 static int synserver_txn_read_request_handler(TSCont contp, TSEvent event, void *data);
00165 static int synserver_txn_main_handler(TSCont contp, TSEvent event, void *data);
00166
00167
00168
00169
00170
00171 static char *
00172 get_body_ptr(const char *request)
00173 {
00174 char *ptr = (char *) strstr((const char *) request, (const char *) "\r\n\r\n");
00175 return (ptr != NULL) ? (ptr + 4) : NULL;
00176 }
00177
00178
00179
00180 static char *
00181 generate_request(int test_case)
00182 {
00183
00184
00185
00186 #define HTTP_REQUEST_DEFAULT_FORMAT "GET http://127.0.0.1:%d/default.html HTTP/1.0\r\n" \
00187 "X-Request-ID: %d\r\n" \
00188 "\r\n"
00189
00190 #define HTTP_REQUEST_FORMAT1 "GET http://127.0.0.1:%d/format1.html HTTP/1.0\r\n" \
00191 "X-Request-ID: %d\r\n" \
00192 "\r\n"
00193
00194 #define HTTP_REQUEST_FORMAT2 "GET http://127.0.0.1:%d/format2.html HTTP/1.0\r\n" \
00195 "X-Request-ID: %d\r\n" \
00196 "Content-Type: text/html\r\n" \
00197 "\r\n"
00198 #define HTTP_REQUEST_FORMAT3 "GET http://127.0.0.1:%d/format3.html HTTP/1.0\r\n" \
00199 "X-Request-ID: %d\r\n" \
00200 "Response: Error\r\n" \
00201 "\r\n"
00202 #define HTTP_REQUEST_FORMAT4 "GET http://127.0.0.1:%d/format4.html HTTP/1.0\r\n" \
00203 "X-Request-ID: %d\r\n" \
00204 "Request:%d\r\n" \
00205 "\r\n"
00206 #define HTTP_REQUEST_FORMAT5 "GET http://127.0.0.1:%d/format5.html HTTP/1.0\r\n" \
00207 "X-Request-ID: %d\r\n" \
00208 "Request:%d\r\n" \
00209 "\r\n"
00210 #define HTTP_REQUEST_FORMAT6 "GET http://127.0.0.1:%d/format.html HTTP/1.0\r\n" \
00211 "X-Request-ID: %d\r\n" \
00212 "Accept-Language: English\r\n" \
00213 "\r\n"
00214 #define HTTP_REQUEST_FORMAT7 "GET http://127.0.0.1:%d/format.html HTTP/1.0\r\n" \
00215 "X-Request-ID: %d\r\n" \
00216 "Accept-Language: French\r\n" \
00217 "\r\n"
00218 #define HTTP_REQUEST_FORMAT8 "GET http://127.0.0.1:%d/format.html HTTP/1.0\r\n" \
00219 "X-Request-ID: %d\r\n" \
00220 "Accept-Language: English,French\r\n" \
00221 "\r\n"
00222 #define HTTP_REQUEST_FORMAT9 "GET http://trafficserver.apache.org/format9.html HTTP/1.0\r\n" \
00223 "X-Request-ID: %d\r\n" \
00224 "\r\n"
00225 #define HTTP_REQUEST_FORMAT10 "GET http://trafficserver.apache.org/format10.html HTTP/1.0\r\n" \
00226 "X-Request-ID: %d\r\n" \
00227 "\r\n"
00228
00229 char *request = (char *) TSmalloc(REQUEST_MAX_SIZE + 1);
00230
00231 switch (test_case) {
00232 case 1:
00233 snprintf(request, REQUEST_MAX_SIZE + 1, HTTP_REQUEST_FORMAT1, SYNSERVER_LISTEN_PORT, test_case);
00234 break;
00235 case 2:
00236 snprintf(request, REQUEST_MAX_SIZE + 1, HTTP_REQUEST_FORMAT2, SYNSERVER_LISTEN_PORT, test_case);
00237 break;
00238 case 3:
00239 snprintf(request, REQUEST_MAX_SIZE + 1, HTTP_REQUEST_FORMAT3, SYNSERVER_LISTEN_PORT, test_case);
00240 break;
00241 case 4:
00242 snprintf(request, REQUEST_MAX_SIZE + 1, HTTP_REQUEST_FORMAT4, SYNSERVER_LISTEN_PORT, test_case, 1);
00243 break;
00244 case 5:
00245 snprintf(request, REQUEST_MAX_SIZE + 1, HTTP_REQUEST_FORMAT5, SYNSERVER_LISTEN_PORT, test_case, 2);
00246 break;
00247 case 6:
00248 snprintf(request, REQUEST_MAX_SIZE + 1, HTTP_REQUEST_FORMAT6, SYNSERVER_LISTEN_PORT, test_case);
00249 break;
00250 case 7:
00251 snprintf(request, REQUEST_MAX_SIZE + 1, HTTP_REQUEST_FORMAT7, SYNSERVER_LISTEN_PORT, test_case - 1);
00252 break;
00253 case 8:
00254 snprintf(request, REQUEST_MAX_SIZE + 1, HTTP_REQUEST_FORMAT8, SYNSERVER_LISTEN_PORT, test_case - 2);
00255 break;
00256 case 9:
00257 snprintf(request, REQUEST_MAX_SIZE + 1, HTTP_REQUEST_FORMAT9, test_case);
00258 break;
00259 case 10:
00260 snprintf(request, REQUEST_MAX_SIZE + 1, HTTP_REQUEST_FORMAT10, test_case);
00261 break;
00262 default:
00263 snprintf(request, REQUEST_MAX_SIZE + 1, HTTP_REQUEST_DEFAULT_FORMAT, SYNSERVER_LISTEN_PORT, test_case);
00264 break;
00265 }
00266
00267 return request;
00268 }
00269
00270
00271
00272 static char *
00273 generate_response(const char *request)
00274 {
00275
00276
00277 #define HTTP_REQUEST_TESTCASE_FORMAT "GET %1024s HTTP/1.%d\r\n" \
00278 "X-Request-ID: %d\r\n"
00279
00280 #define HTTP_RESPONSE_DEFAULT_FORMAT "HTTP/1.0 200 OK\r\n" \
00281 "X-Response-ID: %d\r\n" \
00282 "Cache-Control: max-age=86400\r\n" \
00283 "Content-Type: text/html\r\n" \
00284 "\r\n" \
00285 "Default body"
00286
00287 #define HTTP_RESPONSE_FORMAT1 "HTTP/1.0 200 OK\r\n" \
00288 "X-Response-ID: %d\r\n" \
00289 "Content-Type: text/html\r\n" \
00290 "Cache-Control: no-cache\r\n" \
00291 "\r\n" \
00292 "Body for response 1"
00293
00294 #define HTTP_RESPONSE_FORMAT2 "HTTP/1.0 200 OK\r\n" \
00295 "X-Response-ID: %d\r\n" \
00296 "Cache-Control: max-age=86400\r\n" \
00297 "Content-Type: text/html\r\n" \
00298 "\r\n" \
00299 "Body for response 2"
00300 #define HTTP_RESPONSE_FORMAT4 "HTTP/1.0 200 OK\r\n" \
00301 "X-Response-ID: %d\r\n" \
00302 "Cache-Control: max-age=86400\r\n" \
00303 "Content-Type: text/html\r\n" \
00304 "\r\n" \
00305 "Body for response 4"
00306 #define HTTP_RESPONSE_FORMAT5 "HTTP/1.0 200 OK\r\n" \
00307 "X-Response-ID: %d\r\n" \
00308 "Content-Type: text/html\r\n" \
00309 "\r\n" \
00310 "Body for response 5"
00311 #define HTTP_RESPONSE_FORMAT6 "HTTP/1.0 200 OK\r\n" \
00312 "X-Response-ID: %d\r\n" \
00313 "Cache-Control: max-age=86400\r\n" \
00314 "Content-Language: English\r\n" \
00315 "\r\n" \
00316 "Body for response 6"
00317 #define HTTP_RESPONSE_FORMAT7 "HTTP/1.0 200 OK\r\n" \
00318 "X-Response-ID: %d\r\n" \
00319 "Cache-Control: max-age=86400\r\n" \
00320 "Content-Language: French\r\n" \
00321 "\r\n" \
00322 "Body for response 7"
00323
00324 #define HTTP_RESPONSE_FORMAT8 "HTTP/1.0 200 OK\r\n" \
00325 "X-Response-ID: %d\r\n" \
00326 "Cache-Control: max-age=86400\r\n" \
00327 "Content-Language: French, English\r\n" \
00328 "\r\n" \
00329 "Body for response 8"
00330
00331 #define HTTP_RESPONSE_FORMAT9 "HTTP/1.0 200 OK\r\n" \
00332 "Cache-Control: max-age=86400\r\n" \
00333 "X-Response-ID: %d\r\n" \
00334 "\r\n" \
00335 "Body for response 9"
00336
00337 #define HTTP_RESPONSE_FORMAT10 "HTTP/1.0 200 OK\r\n" \
00338 "Cache-Control: max-age=86400\r\n" \
00339 "X-Response-ID: %d\r\n" \
00340 "\r\n" \
00341 "Body for response 10"
00342
00343
00344 int test_case, match, http_version;
00345
00346 char *response = (char *) TSmalloc(RESPONSE_MAX_SIZE + 1);
00347 char url[1025];
00348
00349
00350 match = sscanf(request, HTTP_REQUEST_TESTCASE_FORMAT, url, &http_version, &test_case);
00351 if (match == 3) {
00352 switch (test_case) {
00353 case 1:
00354 snprintf(response, RESPONSE_MAX_SIZE + 1, HTTP_RESPONSE_FORMAT1, test_case);
00355 break;
00356 case 2:
00357 snprintf(response, RESPONSE_MAX_SIZE + 1, HTTP_RESPONSE_FORMAT2, test_case);
00358 break;
00359 case 4:
00360 snprintf(response, RESPONSE_MAX_SIZE + 1, HTTP_RESPONSE_FORMAT4, test_case);
00361 break;
00362 case 5:
00363 snprintf(response, RESPONSE_MAX_SIZE + 1, HTTP_RESPONSE_FORMAT5, test_case);
00364 break;
00365 case 6:
00366 snprintf(response, RESPONSE_MAX_SIZE + 1, HTTP_RESPONSE_FORMAT6, test_case);
00367 break;
00368 case 7:
00369 snprintf(response, RESPONSE_MAX_SIZE + 1, HTTP_RESPONSE_FORMAT7, test_case);
00370 break;
00371 case 8:
00372 snprintf(response, RESPONSE_MAX_SIZE + 1, HTTP_RESPONSE_FORMAT8, test_case);
00373 break;
00374 case 9:
00375 snprintf(response, RESPONSE_MAX_SIZE + 1, HTTP_RESPONSE_FORMAT9, test_case);
00376 break;
00377 case 10:
00378 snprintf(response, RESPONSE_MAX_SIZE + 1, HTTP_RESPONSE_FORMAT10, test_case);
00379 break;
00380 default:
00381 snprintf(response, RESPONSE_MAX_SIZE + 1, HTTP_RESPONSE_DEFAULT_FORMAT, test_case);
00382 break;
00383 }
00384 } else {
00385
00386 snprintf(response, RESPONSE_MAX_SIZE + 1, HTTP_RESPONSE_DEFAULT_FORMAT, test_case);
00387 }
00388
00389 return response;
00390 }
00391
00392
00393
00394
00395
00396 static int
00397 get_request_id(TSHttpTxn txnp)
00398 {
00399 TSMBuffer bufp;
00400 TSMLoc hdr_loc, id_loc;
00401 int id = -1;
00402
00403 if (TSHttpTxnClientReqGet(txnp, &bufp, &hdr_loc) != TS_SUCCESS) {
00404 return -1;
00405 }
00406
00407 id_loc = TSMimeHdrFieldFind(bufp, hdr_loc, X_REQUEST_ID, -1);
00408 if (id_loc == TS_NULL_MLOC) {
00409 TSHandleMLocRelease(bufp, TS_NULL_MLOC, hdr_loc);
00410 return -1;
00411 }
00412
00413 id = TSMimeHdrFieldValueIntGet(bufp, hdr_loc, id_loc, 0);
00414
00415 TSHandleMLocRelease(bufp, hdr_loc, id_loc);
00416 TSHandleMLocRelease(bufp, TS_NULL_MLOC, hdr_loc);
00417 return id;
00418 }
00419
00420
00421
00422
00423
00424
00425
00426 static ClientTxn *
00427 synclient_txn_create(void)
00428 {
00429 HttpProxyPort* proxy_port;
00430
00431 ClientTxn *txn = (ClientTxn *) TSmalloc(sizeof(ClientTxn));
00432 if (0 == (proxy_port = HttpProxyPort::findHttp(AF_INET)))
00433 txn->connect_port = PROXY_HTTP_DEFAULT_PORT;
00434 else
00435 txn->connect_port = proxy_port->m_port;
00436
00437 txn->local_port = (int) 0;
00438 txn->connect_ip = IP(127, 0, 0, 1);
00439 txn->status = REQUEST_INPROGRESS;
00440 txn->request = NULL;
00441 txn->vconn = NULL;
00442 txn->req_buffer = NULL;
00443 txn->req_reader = NULL;
00444 txn->resp_buffer = NULL;
00445 txn->resp_reader = NULL;
00446 txn->magic = MAGIC_ALIVE;
00447 txn->connect_action = NULL;
00448
00449 TSDebug(CDBG_TAG, "Connecting to proxy 127.0.0.1 on port %d", txn->connect_port);
00450 return txn;
00451 }
00452
00453 static int
00454 synclient_txn_delete(ClientTxn * txn)
00455 {
00456 TSAssert(txn->magic == MAGIC_ALIVE);
00457 if (txn->connect_action && !TSActionDone(txn->connect_action)) {
00458 TSActionCancel(txn->connect_action);
00459 txn->connect_action = NULL;
00460 }
00461
00462 ats_free(txn->request);
00463 txn->magic = MAGIC_DEAD;
00464 TSfree(txn);
00465 return 1;
00466 }
00467
00468 static int
00469 synclient_txn_close(TSCont contp)
00470 {
00471 ClientTxn *txn = (ClientTxn *) TSContDataGet(contp);
00472 TSAssert(txn->magic == MAGIC_ALIVE);
00473
00474 if (txn->vconn != NULL) {
00475 TSVConnClose(txn->vconn);
00476 }
00477 if (txn->req_buffer != NULL) {
00478 TSIOBufferDestroy(txn->req_buffer);
00479 }
00480 if (txn->resp_buffer != NULL) {
00481 TSIOBufferDestroy(txn->resp_buffer);
00482 }
00483
00484 TSContDestroy(contp);
00485
00486 TSDebug(CDBG_TAG, "Client Txn destroyed");
00487 return TS_EVENT_IMMEDIATE;
00488 }
00489
00490 static int
00491 synclient_txn_send_request(ClientTxn * txn, char *request)
00492 {
00493 TSCont cont;
00494 sockaddr_in addr;
00495
00496 TSAssert(txn->magic == MAGIC_ALIVE);
00497 txn->request = ats_strdup(request);
00498 SET_TEST_HANDLER(txn->current_handler, synclient_txn_connect_handler);
00499
00500 cont = TSContCreate(synclient_txn_main_handler, TSMutexCreate());
00501 TSContDataSet(cont, txn);
00502
00503 ats_ip4_set(&addr, txn->connect_ip, htons(txn->connect_port));
00504 TSNetConnect(cont, ats_ip_sa_cast(&addr));
00505 return 1;
00506 }
00507
00508
00509 static int
00510 synclient_txn_send_request_to_vc(ClientTxn * txn, char *request, TSVConn vc)
00511 {
00512 TSCont cont;
00513 TSAssert(txn->magic == MAGIC_ALIVE);
00514 txn->request = ats_strdup(request);
00515 SET_TEST_HANDLER(txn->current_handler, synclient_txn_connect_handler);
00516
00517 cont = TSContCreate(synclient_txn_main_handler, TSMutexCreate());
00518 TSContDataSet(cont, txn);
00519
00520 TSContCall(cont, TS_EVENT_NET_CONNECT, vc);
00521 return 1;
00522 }
00523
00524
00525 static int
00526 synclient_txn_read_response(TSCont contp)
00527 {
00528 ClientTxn *txn = (ClientTxn *) TSContDataGet(contp);
00529 TSAssert(txn->magic == MAGIC_ALIVE);
00530
00531 TSIOBufferBlock block = TSIOBufferReaderStart(txn->resp_reader);
00532 while (block != NULL) {
00533 int64_t blocklen;
00534 const char *blockptr = TSIOBufferBlockReadStart(block, txn->resp_reader, &blocklen);
00535
00536 if (txn->response_len+blocklen <= RESPONSE_MAX_SIZE) {
00537 memcpy((char *) (txn->response + txn->response_len), blockptr, blocklen);
00538 txn->response_len += blocklen;
00539 } else {
00540 TSError("Error: Response length %" PRId64" > response buffer size %d", txn->response_len+blocklen, RESPONSE_MAX_SIZE);
00541 }
00542
00543 block = TSIOBufferBlockNext(block);
00544 }
00545
00546 txn->response[txn->response_len + 1] = '\0';
00547 TSDebug(CDBG_TAG, "Response = |%s|, req len = %d", txn->response, txn->response_len);
00548
00549 return 1;
00550 }
00551
00552 static int
00553 synclient_txn_read_response_handler(TSCont contp, TSEvent event, void * )
00554 {
00555 ClientTxn *txn = (ClientTxn *) TSContDataGet(contp);
00556 TSAssert(txn->magic == MAGIC_ALIVE);
00557
00558 int64_t avail;
00559
00560 switch (event) {
00561 case TS_EVENT_VCONN_READ_READY:
00562 case TS_EVENT_VCONN_READ_COMPLETE:
00563 if (event == TS_EVENT_VCONN_READ_READY) {
00564 TSDebug(CDBG_TAG, "READ_READY");
00565 } else {
00566 TSDebug(CDBG_TAG, "READ_COMPLETE");
00567 }
00568
00569 avail = TSIOBufferReaderAvail(txn->resp_reader);
00570 TSDebug(CDBG_TAG, "%" PRId64" bytes available in buffer", avail);
00571
00572 if (avail > 0) {
00573 synclient_txn_read_response(contp);
00574 TSIOBufferReaderConsume(txn->resp_reader, avail);
00575 }
00576
00577 TSVIOReenable(txn->read_vio);
00578 break;
00579
00580 case TS_EVENT_VCONN_EOS:
00581 TSDebug(CDBG_TAG, "READ_EOS");
00582
00583 txn->status = REQUEST_SUCCESS;
00584 return synclient_txn_close(contp);
00585 break;
00586
00587 case TS_EVENT_ERROR:
00588 TSDebug(CDBG_TAG, "READ_ERROR");
00589 txn->status = REQUEST_FAILURE;
00590 return synclient_txn_close(contp);
00591 break;
00592
00593 default:
00594 TSAssert(!"Invalid event");
00595 break;
00596 }
00597 return 1;
00598 }
00599
00600
00601 static int
00602 synclient_txn_write_request(TSCont contp)
00603 {
00604 ClientTxn *txn = (ClientTxn *) TSContDataGet(contp);
00605 TSAssert(txn->magic == MAGIC_ALIVE);
00606
00607 TSIOBufferBlock block;
00608 char *ptr_block;
00609 int64_t len, ndone, ntodo, towrite, avail;
00610
00611 len = strlen(txn->request);
00612
00613 ndone = 0;
00614 ntodo = len;
00615 while (ntodo > 0) {
00616 block = TSIOBufferStart(txn->req_buffer);
00617 ptr_block = TSIOBufferBlockWriteStart(block, &avail);
00618 towrite = MIN(ntodo, avail);
00619 memcpy(ptr_block, txn->request + ndone, towrite);
00620 TSIOBufferProduce(txn->req_buffer, towrite);
00621 ntodo -= towrite;
00622 ndone += towrite;
00623 }
00624
00625
00626 TSDebug(CDBG_TAG, "Writing |%s| (%" PRId64") bytes", txn->request, len);
00627 txn->write_vio = TSVConnWrite(txn->vconn, contp, txn->req_reader, len);
00628
00629 return 1;
00630 }
00631
00632 static int
00633 synclient_txn_write_request_handler(TSCont contp, TSEvent event, void * )
00634 {
00635 ClientTxn *txn = (ClientTxn *) TSContDataGet(contp);
00636 TSAssert(txn->magic == MAGIC_ALIVE);
00637
00638 switch (event) {
00639 case TS_EVENT_VCONN_WRITE_READY:
00640 TSDebug(CDBG_TAG, "WRITE_READY");
00641 TSVIOReenable(txn->write_vio);
00642 break;
00643
00644 case TS_EVENT_VCONN_WRITE_COMPLETE:
00645 TSDebug(CDBG_TAG, "WRITE_COMPLETE");
00646
00647
00648
00649
00650 SET_TEST_HANDLER(txn->current_handler, synclient_txn_read_response_handler);
00651 txn->read_vio = TSVConnRead(txn->vconn, contp, txn->resp_buffer, INT64_MAX);
00652 break;
00653
00654 case TS_EVENT_VCONN_EOS:
00655 TSDebug(CDBG_TAG, "WRITE_EOS");
00656 txn->status = REQUEST_FAILURE;
00657 return synclient_txn_close(contp);
00658 break;
00659
00660 case TS_EVENT_ERROR:
00661 TSDebug(CDBG_TAG, "WRITE_ERROR");
00662 txn->status = REQUEST_FAILURE;
00663 return synclient_txn_close(contp);
00664 break;
00665
00666 default:
00667 TSAssert(!"Invalid event");
00668 break;
00669 }
00670 return TS_EVENT_IMMEDIATE;
00671 }
00672
00673
00674 static int
00675 synclient_txn_connect_handler(TSCont contp, TSEvent event, void *data)
00676 {
00677 TSAssert((event == TS_EVENT_NET_CONNECT) || (event == TS_EVENT_NET_CONNECT_FAILED));
00678
00679 ClientTxn *txn = (ClientTxn *) TSContDataGet(contp);
00680 TSAssert(txn->magic == MAGIC_ALIVE);
00681
00682 if (event == TS_EVENT_NET_CONNECT) {
00683 TSDebug(CDBG_TAG, "NET_CONNECT");
00684
00685 txn->req_buffer = TSIOBufferCreate();
00686 txn->req_reader = TSIOBufferReaderAlloc(txn->req_buffer);
00687 txn->resp_buffer = TSIOBufferCreate();
00688 txn->resp_reader = TSIOBufferReaderAlloc(txn->resp_buffer);
00689
00690 txn->response[0] = '\0';
00691 txn->response_len = 0;
00692
00693 txn->vconn = (TSVConn) data;
00694 txn->local_port = (int) ((NetVConnection *) data)->get_local_port();
00695
00696 txn->write_vio = NULL;
00697 txn->read_vio = NULL;
00698
00699
00700 SET_TEST_HANDLER(txn->current_handler, synclient_txn_write_request_handler);
00701 synclient_txn_write_request(contp);
00702
00703 return TS_EVENT_IMMEDIATE;
00704 } else {
00705 TSDebug(CDBG_TAG, "NET_CONNECT_FAILED");
00706 txn->status = REQUEST_FAILURE;
00707 synclient_txn_close(contp);
00708 }
00709
00710 return TS_EVENT_IMMEDIATE;
00711 }
00712
00713
00714 static int
00715 synclient_txn_main_handler(TSCont contp, TSEvent event, void *data)
00716 {
00717 ClientTxn *txn = (ClientTxn *) TSContDataGet(contp);
00718 TSAssert(txn->magic == MAGIC_ALIVE);
00719
00720 TxnHandler handler = txn->current_handler;
00721 return (*handler) (contp, event, data);
00722 }
00723
00724
00725
00726
00727
00728
00729 SocketServer *
00730 synserver_create(int port)
00731 {
00732 SocketServer *s = (SocketServer *) TSmalloc(sizeof(SocketServer));
00733 s->magic = MAGIC_ALIVE;
00734 s->accept_port = port;
00735 s->accept_action = NULL;
00736 s->accept_cont = TSContCreate(synserver_accept_handler, TSMutexCreate());
00737 TSContDataSet(s->accept_cont, s);
00738 return s;
00739 }
00740
00741 static int
00742 synserver_start(SocketServer * s)
00743 {
00744 TSAssert(s->magic == MAGIC_ALIVE);
00745 s->accept_action = TSNetAccept(s->accept_cont, s->accept_port, -1, 0);
00746 return 1;
00747 }
00748
00749 static int
00750 synserver_stop(SocketServer * s)
00751 {
00752 TSAssert(s->magic == MAGIC_ALIVE);
00753 if (s->accept_action && !TSActionDone(s->accept_action)) {
00754 TSActionCancel(s->accept_action);
00755 s->accept_action = NULL;
00756 TSDebug(SDBG_TAG, "Had to cancel action");
00757 }
00758 TSDebug(SDBG_TAG, "stopped");
00759 return 1;
00760 }
00761
00762 static int
00763 synserver_delete(SocketServer * s)
00764 {
00765 TSAssert(s->magic == MAGIC_ALIVE);
00766 synserver_stop(s);
00767
00768 if (s->accept_cont) {
00769 TSContDestroy(s->accept_cont);
00770 s->accept_cont = NULL;
00771 TSDebug(SDBG_TAG, "destroyed accept cont");
00772 }
00773 s->magic = MAGIC_DEAD;
00774 TSfree(s);
00775 TSDebug(SDBG_TAG, "deleted server");
00776 return 1;
00777 }
00778
00779 static int
00780 synserver_accept_handler(TSCont contp, TSEvent event, void *data)
00781 {
00782 TSAssert((event == TS_EVENT_NET_ACCEPT) || (event == TS_EVENT_NET_ACCEPT_FAILED));
00783
00784 SocketServer *s = (SocketServer *) TSContDataGet(contp);
00785 TSAssert(s->magic == MAGIC_ALIVE);
00786
00787 if (event == TS_EVENT_NET_ACCEPT_FAILED) {
00788 Warning("Synserver failed to bind to port %d.", ntohs(s->accept_port));
00789 ink_release_assert(!"Synserver must be able to bind to a port, check system netstat");
00790 TSDebug(SDBG_TAG, "NET_ACCEPT_FAILED");
00791 return TS_EVENT_IMMEDIATE;
00792 }
00793
00794 TSDebug(SDBG_TAG, "NET_ACCEPT");
00795
00796
00797 ServerTxn *txn = (ServerTxn *) TSmalloc(sizeof(ServerTxn));
00798 txn->magic = MAGIC_ALIVE;
00799
00800 SET_TEST_HANDLER(txn->current_handler, synserver_txn_read_request_handler);
00801
00802 TSCont txn_cont = TSContCreate(synserver_txn_main_handler, TSMutexCreate());
00803 TSContDataSet(txn_cont, txn);
00804
00805 txn->req_buffer = TSIOBufferCreate();
00806 txn->req_reader = TSIOBufferReaderAlloc(txn->req_buffer);
00807
00808 txn->resp_buffer = TSIOBufferCreate();
00809 txn->resp_reader = TSIOBufferReaderAlloc(txn->resp_buffer);
00810
00811 txn->request[0] = '\0';
00812 txn->request_len = 0;
00813
00814 txn->vconn = (TSVConn) data;
00815
00816 txn->write_vio = NULL;
00817
00818
00819 txn->read_vio = TSVConnRead(txn->vconn, txn_cont, txn->req_buffer, INT64_MAX);
00820
00821 return TS_EVENT_IMMEDIATE;
00822 }
00823
00824
00825 static int
00826 synserver_txn_close(TSCont contp)
00827 {
00828 ServerTxn *txn = (ServerTxn *) TSContDataGet(contp);
00829 TSAssert(txn->magic == MAGIC_ALIVE);
00830
00831 if (txn->vconn != NULL) {
00832 TSVConnClose(txn->vconn);
00833 }
00834 if (txn->req_buffer) {
00835 TSIOBufferDestroy(txn->req_buffer);
00836 }
00837 if (txn->resp_buffer) {
00838 TSIOBufferDestroy(txn->resp_buffer);
00839 }
00840
00841 txn->magic = MAGIC_DEAD;
00842 TSfree(txn);
00843 TSContDestroy(contp);
00844
00845 TSDebug(SDBG_TAG, "Server Txn destroyed");
00846 return TS_EVENT_IMMEDIATE;
00847 }
00848
00849
00850 static int
00851 synserver_txn_write_response(TSCont contp)
00852 {
00853 ServerTxn *txn = (ServerTxn *) TSContDataGet(contp);
00854 TSAssert(txn->magic == MAGIC_ALIVE);
00855
00856 SET_TEST_HANDLER(txn->current_handler, synserver_txn_write_response_handler);
00857
00858 TSIOBufferBlock block;
00859 char *ptr_block;
00860 int64_t len, ndone, ntodo, towrite, avail;
00861 char *response;
00862
00863 response = generate_response(txn->request);
00864 len = strlen(response);
00865
00866 ndone = 0;
00867 ntodo = len;
00868 while (ntodo > 0) {
00869 block = TSIOBufferStart(txn->resp_buffer);
00870 ptr_block = TSIOBufferBlockWriteStart(block, &avail);
00871 towrite = MIN(ntodo, avail);
00872 memcpy(ptr_block, response + ndone, towrite);
00873 TSIOBufferProduce(txn->resp_buffer, towrite);
00874 ntodo -= towrite;
00875 ndone += towrite;
00876 }
00877
00878
00879 TSDebug(SDBG_TAG, "Writing response: |%s| (%" PRId64") bytes)", response, len);
00880 txn->write_vio = TSVConnWrite(txn->vconn, contp, txn->resp_reader, len);
00881
00882
00883 TSfree(response);
00884
00885 return TS_EVENT_IMMEDIATE;
00886 }
00887
00888
00889 static int
00890 synserver_txn_write_response_handler(TSCont contp, TSEvent event, void * )
00891 {
00892 ServerTxn *txn = (ServerTxn *) TSContDataGet(contp);
00893 TSAssert(txn->magic == MAGIC_ALIVE);
00894
00895 switch (event) {
00896 case TS_EVENT_VCONN_WRITE_READY:
00897 TSDebug(SDBG_TAG, "WRITE_READY");
00898 TSVIOReenable(txn->write_vio);
00899 break;
00900
00901 case TS_EVENT_VCONN_WRITE_COMPLETE:
00902 TSDebug(SDBG_TAG, "WRITE_COMPLETE");
00903 TSVConnShutdown(txn->vconn, 0, 1);
00904 return synserver_txn_close(contp);
00905 break;
00906
00907 case TS_EVENT_VCONN_EOS:
00908 TSDebug(SDBG_TAG, "WRITE_EOS");
00909 return synserver_txn_close(contp);
00910 break;
00911
00912 case TS_EVENT_ERROR:
00913 TSDebug(SDBG_TAG, "WRITE_ERROR");
00914 return synserver_txn_close(contp);
00915 break;
00916
00917 default:
00918 TSAssert(!"Invalid event");
00919 break;
00920 }
00921 return TS_EVENT_IMMEDIATE;
00922 }
00923
00924
00925 static int
00926 synserver_txn_read_request(TSCont contp)
00927 {
00928 ServerTxn *txn = (ServerTxn *) TSContDataGet(contp);
00929 TSAssert(txn->magic == MAGIC_ALIVE);
00930
00931 int end;
00932 TSIOBufferBlock block = TSIOBufferReaderStart(txn->req_reader);
00933
00934 while (block != NULL) {
00935 int64_t blocklen;
00936 const char *blockptr = TSIOBufferBlockReadStart(block, txn->req_reader, &blocklen);
00937
00938 if (txn->request_len+blocklen <= REQUEST_MAX_SIZE) {
00939 memcpy((char *) (txn->request + txn->request_len), blockptr, blocklen);
00940 txn->request_len += blocklen;
00941 } else {
00942 TSError("Error: Request length %" PRId64" > request buffer size %d", txn->request_len+blocklen, REQUEST_MAX_SIZE);
00943 }
00944
00945 block = TSIOBufferBlockNext(block);
00946 }
00947
00948 txn->request[txn->request_len] = '\0';
00949 TSDebug(SDBG_TAG, "Request = |%s|, req len = %d", txn->request, txn->request_len);
00950
00951 end = (strstr(txn->request, HTTP_REQUEST_END) != NULL);
00952 TSDebug(SDBG_TAG, "End of request = %d", end);
00953
00954 return end;
00955 }
00956
00957 static int
00958 synserver_txn_read_request_handler(TSCont contp, TSEvent event, void * )
00959 {
00960 ServerTxn *txn = (ServerTxn *) TSContDataGet(contp);
00961 TSAssert(txn->magic == MAGIC_ALIVE);
00962
00963 int64_t avail;
00964 int end_of_request;
00965
00966 switch (event) {
00967 case TS_EVENT_VCONN_READ_READY:
00968 case TS_EVENT_VCONN_READ_COMPLETE:
00969 TSDebug(SDBG_TAG, (event == TS_EVENT_VCONN_READ_READY) ? "READ_READY" : "READ_COMPLETE");
00970 avail = TSIOBufferReaderAvail(txn->req_reader);
00971 TSDebug(SDBG_TAG, "%" PRId64" bytes available in buffer", avail);
00972
00973 if (avail > 0) {
00974 end_of_request = synserver_txn_read_request(contp);
00975 TSIOBufferReaderConsume(txn->req_reader, avail);
00976
00977 if (end_of_request) {
00978 TSVConnShutdown(txn->vconn, 1, 0);
00979 return synserver_txn_write_response(contp);
00980 }
00981 }
00982
00983 TSVIOReenable(txn->read_vio);
00984 break;
00985
00986 case TS_EVENT_VCONN_EOS:
00987 TSDebug(SDBG_TAG, "READ_EOS");
00988 return synserver_txn_close(contp);
00989 break;
00990
00991 case TS_EVENT_ERROR:
00992 TSDebug(SDBG_TAG, "READ_ERROR");
00993 return synserver_txn_close(contp);
00994 break;
00995
00996 default:
00997 TSAssert(!"Invalid event");
00998 break;
00999 }
01000 return TS_EVENT_IMMEDIATE;
01001 }
01002
01003
01004 static int
01005 synserver_txn_main_handler(TSCont contp, TSEvent event, void *data)
01006 {
01007 ServerTxn *txn = (ServerTxn *) TSContDataGet(contp);
01008 TSAssert(txn->magic == MAGIC_ALIVE);
01009
01010 TxnHandler handler = txn->current_handler;
01011 return (*handler) (contp, event, data);
01012 }
01013