static int connection_init( Connection* conn ) { HttpService* service = (HttpService*) conn->root->service; ProxyConnection* root = conn->root; stralloc_t* str = root->str; proxy_connection_rewind(root); stralloc_add_format(str, "CONNECT %s HTTP/" HTTP_VERSION "\r\n", sock_address_to_string(&root->address)); stralloc_add_bytes(str, service->footer, service->footer_len); if (!socket_connect( root->socket, &service->server_addr )) { /* immediate connection ?? */ conn->state = STATE_SEND_HEADER; PROXY_LOG("%s: immediate connection", root->name); } else { if (errno == EINPROGRESS || errno == EWOULDBLOCK) { conn->state = STATE_CONNECTING; PROXY_LOG("%s: connecting", root->name); } else { PROXY_LOG("%s: cannot connect to proxy: %s", root->name, errno_str); return -1; } } return 0; }
int register_fn_get_shard_key (void) { int error; if (shm_proxy_p->shard_key_library_name[0] != '\0' && shm_proxy_p->shard_key_function_name[0] != '\0') { error = load_shard_key_function (shm_proxy_p->shard_key_library_name, shm_proxy_p->shard_key_function_name); if (error < 0) { PROXY_LOG (PROXY_LOG_MODE_ERROR, "Failed to load " "shard hashing library. " "(library_name:[%s], function:[%s]).\n", shm_proxy_p->shard_key_library_name, shm_proxy_p->shard_key_function_name); close_shard_key_function (); return -1; } PROXY_LOG (PROXY_LOG_MODE_NOTICE, "Loading shard hashing " "library was completed. " "(library_name:[%s], function:[%s]).\n", shm_proxy_p->shard_key_library_name, shm_proxy_p->shard_key_function_name); return 0; } fn_get_shard_key = fn_get_shard_key_default; #if defined(SHARD_VERBOSE_DEBUG) printf ("FN_GET_SHARD_KEY REGISTER DEFAULT DONE\n"); #endif return 0; }
static ProxyConnection* http_service_connect( HttpService* service, SocketType sock_type, SockAddress* address ) { /* the HTTP proxy can only handle TCP connections */ if (sock_type != SOCKET_STREAM) return NULL; /* if the client tries to directly connect to the proxy, let it do so */ if (sock_address_equal( address, &service->server_addr )) return NULL; PROXY_LOG("%s: trying to connect to %s", __FUNCTION__, sock_address_to_string(address)); if (sock_address_get_port(address) == 80) { /* use the rewriter for HTTP */ PROXY_LOG("%s: using HTTP rewriter", __FUNCTION__); return http_rewriter_connect(service, address); } else { PROXY_LOG("%s: using HTTP rewriter", __FUNCTION__); return http_connector_connect(service, address); } }
int proxy_find_shard_id_by_hint_value (SP_VALUE * value_p, const char *key_column) { T_SHARD_KEY_RANGE *range_p = NULL; int shard_key_id = -1; INT64 shard_key_val_int; char *shard_key_val_string; int shard_key_val_len; if (value_p->type == VT_INTEGER) { shard_key_val_int = value_p->integer; shard_key_id = (*fn_get_shard_key) (key_column, SHARD_U_TYPE_BIGINT, &shard_key_val_int, sizeof (INT64)); } else if (value_p->type == VT_STRING) { shard_key_val_string = value_p->string.value; shard_key_val_len = value_p->string.length; shard_key_id = (*fn_get_shard_key) (key_column, SHARD_U_TYPE_STRING, shard_key_val_string, shard_key_val_len); } else { PROXY_LOG (PROXY_LOG_MODE_ERROR, "Invalid hint value type. (value_type:%d).", value_p->type); } return shard_key_id; }
static void http_service_free( HttpService* service ) { PROXY_LOG("%s", __FUNCTION__); if (service->footer != service->footer0) qemu_free(service->footer); qemu_free(service); }
int fn_get_shard_key_default (const char *shard_key, T_SHARD_U_TYPE type, const void *value, int value_len) { int modular_key; if (value == NULL) { PROXY_LOG (PROXY_LOG_MODE_ERROR, "Invalid shard key value. " "Shard key value couldn't be NUll."); return ERROR_ON_ARGUMENT; } modular_key = shm_proxy_p->shard_key_modular; if (modular_key < 0) { PROXY_LOG (PROXY_LOG_MODE_ERROR, "Invalid modular key. " "Shard modular key value couldn't be negative integer. " "(modular_key:%d).", modular_key); return ERROR_ON_MAKE_SHARD_KEY; } if (type == SHARD_U_TYPE_INT || type == SHARD_U_TYPE_UINT) { unsigned int ival; ival = (unsigned int) (*(unsigned int *) value); return ival % modular_key; } else if (type == SHARD_U_TYPE_SHORT || type == SHARD_U_TYPE_USHORT) { unsigned short sval; sval = (unsigned short) (*(unsigned short *) value); return sval % modular_key; } else if (type == SHARD_U_TYPE_BIGINT || type == SHARD_U_TYPE_UBIGINT) { UINT64 lval; lval = (UINT64) (*(UINT64 *) value); return lval % modular_key; } else { PROXY_LOG (PROXY_LOG_MODE_ERROR, "Unexpected shard key type. " "(type:%d).", type); return ERROR_ON_ARGUMENT; } }
static void connection_poll( ProxyConnection* root, ProxySelect* sel ) { DataStatus ret = DATA_NEED_MORE; Connection* conn = (Connection*)root; int fd = root->socket; if (!proxy_select_poll(sel, fd)) return; switch (conn->state) { case STATE_CONNECTING: PROXY_LOG("%s: connected to http proxy, sending header", root->name); conn->state = STATE_SEND_HEADER; break; case STATE_SEND_HEADER: ret = proxy_connection_send(root, fd); if (ret == DATA_COMPLETED) { conn->state = STATE_RECEIVE_ANSWER_LINE1; PROXY_LOG("%s: header sent, receiving first answer line", root->name); } break; case STATE_RECEIVE_ANSWER_LINE1: case STATE_RECEIVE_ANSWER_LINE2: ret = proxy_connection_receive_line(root, root->socket); if (ret == DATA_COMPLETED) { if (conn->state == STATE_RECEIVE_ANSWER_LINE1) { int http1, http2, codenum; const char* line = root->str->s; if ( sscanf(line, "HTTP/%d.%d %d", &http1, &http2, &codenum) != 3 ) { PROXY_LOG( "%s: invalid answer from proxy: '%s'", root->name, line ); ret = DATA_ERROR; break; } /* success is 2xx */ if (codenum/2 != 100) { PROXY_LOG( "%s: connection refused, error=%d", root->name, codenum ); proxy_connection_free( root, 0, PROXY_EVENT_CONNECTION_REFUSED ); return; } PROXY_LOG("%s: receiving second answer line", root->name); conn->state = STATE_RECEIVE_ANSWER_LINE2; proxy_connection_rewind(root); } else { /* ok, we're connected */ PROXY_LOG("%s: connection succeeded", root->name); proxy_connection_free( root, 1, PROXY_EVENT_CONNECTED ); } } break; default: PROXY_LOG("%s: invalid state for read event: %d", root->name, conn->state); } if (ret == DATA_ERROR) { proxy_connection_free( root, 0, PROXY_EVENT_SERVER_ERROR ); } }
int proxy_http_setup( const char* servername, int servernamelen, int serverport, int num_options, const ProxyOption* options ) { HttpService* service; SockAddress server_addr; const ProxyOption* opt_nocache = NULL; const ProxyOption* opt_keepalive = NULL; const ProxyOption* opt_auth_user = NULL; const ProxyOption* opt_auth_pass = NULL; const ProxyOption* opt_user_agent = NULL; if (servernamelen < 0) servernamelen = strlen(servername); PROXY_LOG( "%s: creating http proxy service connecting to: %.*s:%d", __FUNCTION__, servernamelen, servername, serverport ); /* resolve server address */ if (proxy_resolve_server(&server_addr, servername, servernamelen, serverport) < 0) { return -1; } /* create service object */ service = qemu_mallocz(sizeof(*service)); if (service == NULL) { PROXY_LOG("%s: not enough memory to allocate new proxy service", __FUNCTION__); return -1; } service->server_addr = server_addr; /* parse options */ { const ProxyOption* opt = options; const ProxyOption* end = opt + num_options; for ( ; opt < end; opt++ ) { switch (opt->type) { case PROXY_OPTION_HTTP_NOCACHE: opt_nocache = opt; break; case PROXY_OPTION_HTTP_KEEPALIVE: opt_keepalive = opt; break; case PROXY_OPTION_AUTH_USERNAME: opt_auth_user = opt; break; case PROXY_OPTION_AUTH_PASSWORD: opt_auth_pass = opt; break; case PROXY_OPTION_HTTP_USER_AGENT: opt_user_agent = opt; break; default: ; } } } /* prepare footer */ { int wlen; char* p = service->footer0; char* end = p + sizeof(service->footer0); /* no-cache */ if (opt_nocache) { p += snprintf(p, end-p, "Pragma: no-cache\r\nCache-Control: no-cache\r\n"); if (p >= end) goto FooterOverflow; } /* keep-alive */ if (opt_keepalive) { p += snprintf(p, end-p, "Connection: Keep-Alive\r\nProxy-Connection: Keep-Alive\r\n"); if (p >= end) goto FooterOverflow; } /* authentication */ if (opt_auth_user && opt_auth_pass) { char user_pass[256]; char encoded[512]; int uplen; uplen = snprintf( user_pass, sizeof(user_pass), "%.*s:%.*s", opt_auth_user->string_len, opt_auth_user->string, opt_auth_pass->string_len, opt_auth_pass->string ); if (uplen >= sizeof(user_pass)) goto FooterOverflow; wlen = proxy_base64_encode(user_pass, uplen, encoded, (int)sizeof(encoded)); if (wlen < 0) { PROXY_LOG( "could not base64 encode '%.*s'", uplen, user_pass); goto FooterOverflow; } p += snprintf(p, end-p, "Proxy-authorization: Basic %.*s\r\n", wlen, encoded); if (p >= end) goto FooterOverflow; } /* user agent */ if (opt_user_agent) { p += snprintf(p, end-p, "User-Agent: %.*s\r\n", opt_user_agent->string_len, opt_user_agent->string); if (p >= end) goto FooterOverflow; } p += snprintf(p, end-p, "\r\n"); if (p >= end) { FooterOverflow: PROXY_LOG( "%s: buffer overflow when creating connection footer", __FUNCTION__); http_service_free(service); return -1; } service->footer = service->footer0; service->footer_len = (p - service->footer); } PROXY_LOG( "%s: creating HTTP Proxy Service Footer is (len=%d):\n'%.*s'", __FUNCTION__, service->footer_len, service->footer_len, service->footer ); service->root->opaque = service; service->root->serv_free = (ProxyServiceFreeFunc) http_service_free; service->root->serv_connect = (ProxyServiceConnectFunc) http_service_connect; if (proxy_manager_add_service( service->root ) < 0) { PROXY_LOG("%s: could not register service ?", __FUNCTION__); http_service_free(service); return -1; } return 0; }