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;
}
Example #2
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);
    }
}
Example #4
0
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);
}
Example #6
0
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;
}