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