⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 http.c

📁 The Kannel Open Source WAP and SMS gateway works as both an SMS gateway, for implementing keyword b
💻 C
📖 第 1 页 / 共 5 页
字号:
            debug("gwlib.http",0,"Failed while sending request");            goto error;          }          break;	case reading_status:	    ret = client_read_status(trans);	    if (ret < 0) {		/*		 * Couldn't read the status from the socket. This may mean 		 * that the socket had been closed by the server after an 		 * idle timeout, so we close the connection and try again, 		 * opening a new socket, but only once.		 */		if (trans->retrying) {                    debug("gwlib.http",0,"Failed while retrying");		    goto error;		} else {                    /* implicit conn_unregister */		    conn_destroy(trans->conn);		    trans->conn = NULL;		    trans->retrying = 1;		    trans->state = request_not_sent;		    list_produce(pending_requests, trans);		    return;		}	    } else if (ret == 0) {		/* Got the status, go read headers and body next. */		trans->state = reading_entity;		trans->response =		    entity_create(response_expectation(trans->method, trans->status));	    } else		return;	    break;	    	case reading_entity:	    ret = entity_read(trans->response, conn);	    if (ret < 0) {	        debug("gwlib.http",0,"Failed reading entity");	        goto error;	    } else if (ret == 0 &&                     http_status_class(trans->status) == HTTP_STATUS_PROVISIONAL) {                /* This was a provisional reply; get the real one now. */                trans->state = reading_status;                entity_destroy(trans->response);                trans->response = NULL;            } else if (ret == 0) {                trans->state = transaction_done;#ifdef DUMP_RESPONSE                /* Dump the response */                debug("wsp.http", 0, "HTTP: Received response:");                h = build_response(trans->response->headers, trans->response->body);                octstr_dump(h, 0);                octstr_destroy(h);#endif	    } else {                return;            }	    break;	default:	    panic(0, "Internal error: Invalid HTTPServer state.");	}    }    conn_unregister(trans->conn);    h = http_header_find_first(trans->response->headers, "Connection");    if (h != NULL && octstr_compare(h, octstr_imm("close")) == 0)	trans->persistent = 0;    octstr_destroy(h);#ifdef USE_KEEPALIVE     if (trans->persistent) {        if (proxy_used_for_host(trans->host))            conn_pool_put(trans->conn, proxy_hostname, proxy_port);        else            conn_pool_put(trans->conn, trans->host, trans->port);    } else#endif    	conn_destroy(trans->conn);    trans->conn = NULL;    /*      * Check if the HTTP server told us to look somewhere else,     * hence if we got one of the following response codes:     *   HTTP_MOVED_PERMANENTLY (301)     *   HTTP_FOUND (302)     *   HTTP_SEE_OTHER (303)     *   HTTP_TEMPORARY_REDIRECT (307)     */    if ((h = get_redirection_location(trans)) != NULL) {        /*          * This is a redirected response, we have to follow.         * Clean up all trans stuff for the next request we do.         */        octstr_strip_blanks(h);        octstr_destroy(trans->url);        octstr_destroy(trans->host);        trans->port = 0;        octstr_destroy(trans->uri);        octstr_destroy(trans->username);        octstr_destroy(trans->password);        trans->host = NULL;        trans->port = 0;        trans->uri = NULL;        trans->username = NULL;        trans->password = NULL;        trans->ssl = 0;        trans->url = h; /* apply new absolute URL to next request */        trans->state = request_not_sent;        trans->status = -1;        http_destroy_headers(trans->response->headers);        trans->response->headers = list_create();        octstr_destroy(trans->response->body);        trans->response->body = octstr_create("");        --trans->follow_remaining;        conn_destroy(trans->conn);        trans->conn = NULL;        /* re-inject request to queue */        list_produce(pending_requests, trans);    } else {        /* handle this response as usual */        list_produce(trans->caller, trans);    }    return;error:    conn_destroy(trans->conn);    trans->conn = NULL;    error(0, "Couldn't fetch <%s>", octstr_get_cstr(trans->url));    trans->status = -1;    list_produce(trans->caller, trans);}/* * Build a complete HTTP request given the host, port, path and headers.  * Add Host: and Content-Length: headers (and others that may be necessary). * Return the request as an Octstr. */static Octstr *build_request(char *method_name, Octstr *path_or_url,                              Octstr *host, long port, List *headers,                              Octstr *request_body){    /* XXX headers missing */    Octstr *request;    int i;    request = octstr_format("%s %S HTTP/1.1\r\n",                            method_name, path_or_url);    octstr_format_append(request, "Host: %S", host);    if (port != HTTP_PORT)        octstr_format_append(request, ":%ld", port);    octstr_append(request, octstr_imm("\r\n"));    for (i = 0; headers != NULL && i < list_len(headers); ++i) {        octstr_append(request, list_get(headers, i));        octstr_append(request, octstr_imm("\r\n"));    }    octstr_append(request, octstr_imm("\r\n"));    if (request_body != NULL)        octstr_append(request, request_body);    return request;}/* * Re-build the HTTP response given the headers and the body. * Return the response as an Octstr. */static Octstr *build_response(List *headers, Octstr *body){    Octstr *response;    int i;    response = octstr_create("");    for (i = 0; headers != NULL && i < list_len(headers); ++i) {        octstr_append(response, list_get(headers, i));        octstr_append(response, octstr_imm("\r\n"));    }    octstr_append(response, octstr_imm("\r\n"));    if (body != NULL)        octstr_append(response, body);    return response;}HTTPURLParse *http_urlparse_create(void){    HTTPURLParse *p;    p = gw_malloc(sizeof(HTTPURLParse));    p->url = NULL;    p->scheme = NULL;    p->host = NULL;    p->port = 0;    p->user = NULL;    p->pass = NULL;    p->path = NULL;    p->query = NULL;    p->fragment = NULL;        return p;}void http_urlparse_destroy(HTTPURLParse *p){    gw_assert(p != NULL);    octstr_destroy(p->url);    octstr_destroy(p->scheme);    octstr_destroy(p->host);    octstr_destroy(p->user);    octstr_destroy(p->pass);    octstr_destroy(p->path);    octstr_destroy(p->query);    octstr_destroy(p->fragment);    gw_free(p);}void parse_dump(HTTPURLParse *p) {    if (p == NULL)        return;    debug("http.parse_url",0,"Parsing URL `%s':", octstr_get_cstr(p->url));    debug("http.parse_url",0,"  Scheme: %s", octstr_get_cstr(p->scheme));      debug("http.parse_url",0,"  Host: %s", octstr_get_cstr(p->host));      debug("http.parse_url",0,"  Port: %ld", p->port);      debug("http.parse_url",0,"  Username: %s", octstr_get_cstr(p->user));      debug("http.parse_url",0,"  Password: %s", octstr_get_cstr(p->pass));      debug("http.parse_url",0,"  Path: %s", octstr_get_cstr(p->path));      debug("http.parse_url",0,"  Query: %s", octstr_get_cstr(p->query));      debug("http.parse_url",0,"  Fragment: %s", octstr_get_cstr(p->fragment));  }/* * Parse the URL to get all components, which are: scheme, hostname,  * port, username, password, path (URI), query (the CGI parameter list),  * fragment (#). * * On success return the HTTPURLParse structure, otherwise NULL if the URL  * seems malformed. * * We assume HTTP URLs of the form specified in "3.2.2 http URL" in * RFC 2616: *  *  http_URL = "http:" "//" [ userid : password "@"] host [ ":" port ] [ abs_path [ "?" query ]]  */HTTPURLParse *parse_url(Octstr *url){    HTTPURLParse *p;    Octstr *prefix, *prefix_https;    long prefix_len;    int host_len, colon, slash, at, auth_sep, query;    host_len = colon = slash = at = auth_sep = query = 0;    prefix = octstr_imm("http://");    prefix_https = octstr_imm("https://");    prefix_len = octstr_len(prefix);    if (octstr_case_search(url, prefix, 0) != 0) {        if (octstr_case_search(url, prefix_https, 0) == 0) {#ifdef HAVE_LIBSSL            debug("gwlib.http", 0, "HTTPS URL; Using SSL for the connection");            prefix = prefix_https;            prefix_len = octstr_len(prefix_https);	#else            error(0, "Attempt to use HTTPS <%s> but SSL not compiled in",                   octstr_get_cstr(url));            return NULL;#endif        } else {            error(0, "URL <%s> doesn't start with `%s' nor `%s'",            octstr_get_cstr(url), octstr_get_cstr(prefix),            octstr_get_cstr(prefix_https));            return NULL;        }    }    /* an URL should be more (at least one charset) then the scheme itself */    if (octstr_len(url) == prefix_len) {        error(0, "URL <%s> is malformed.", octstr_get_cstr(url));        return NULL;    }    /* check if colon and slashes are within scheme */    colon = octstr_search_char(url, ':', prefix_len);    slash = octstr_search_char(url, '/', prefix_len);    if (colon == prefix_len || slash == prefix_len) {        error(0, "URL <%s> is malformed.", octstr_get_cstr(url));        return NULL;    }    /* create struct and add values succesively while parsing */    p = http_urlparse_create();    p->url = octstr_duplicate(url);    p->scheme = octstr_duplicate(prefix);    /* try to parse authentication separator */    at = octstr_search_char(url, '@', prefix_len);    if (at != -1) {        if ((slash == -1 || ( slash != -1 && at < slash))) {            auth_sep = octstr_search_char(url, ':', prefix_len);            if (auth_sep != -1 && (auth_sep < at)) {                octstr_set_char(url, auth_sep, '@');                colon = octstr_search_char(url, ':', prefix_len);            }        } else {            at = -1;        }    }    /*     * We have to watch out here for 4 cases:     *  a) hostname, no port or path     *  b) hostname, port, no path     *  c) hostname, path, no port     *  d) hostname, port and path     */        /* we only have the hostname, no port or path. */    if (slash == -1 && colon == -1) {        host_len = octstr_len(url) - prefix_len;#ifdef HAVE_LIBSSL        p->port = (octstr_compare(p->scheme, octstr_imm("https://")) == 0) ?             HTTPS_PORT : HTTP_PORT;#else        p->port = HTTP_PORT;#endif /* HAVE_LIBSSL */    }     /* we have a port, but no path. */    else if (slash == -1) {        host_len = colon - prefix_len;        if (octstr_parse_long(&(p->port), url, colon + 1, 10) == -1) {            error(0, "URL <%s> has malformed port number.",                  octstr_get_cstr(url));            http_urlparse_destroy(p);            return NULL;        }    }     /* we have a path, but no port. */    else if (colon == -1 || colon > slash) {        host_len = slash - prefix_len;#ifdef HAVE_LIBSSL        p->port = (octstr_compare(p->scheme, octstr_imm("https://")) == 0) ?             HTTPS_PORT : HTTP_PORT;#else        p->port = HTTP_PORT;#endif /* HAVE_LIBSSL */    }     /* we have both, path and port. */    else if (colon < slash) {        host_len = colon - prefix_len;        if (octstr_parse_long(&(p->port), url, colon + 1, 10) == -1) {            error(0, "URL <%s> has malformed port number.",                  octstr_get_cstr(url));            http_urlparse_destroy(p);            return NULL;        }    /* none of the above, so there is something wrong here */    } else {        error(0, "Internal error in URL parsing logic.");        http_urlparse_destroy(p);        return NULL;    }    /* there was an authenticator separator, so try to parse      * the username and password credentials */    if (at != -1) {        int at2;        at2 = octstr_search_char(url, '@', prefix_len);        p->user = octstr_copy(url, prefix_len, at2 - prefix_len);        p->pass = (at2 != at) ? octstr_copy(url, at2 + 1, at - at2 - 1) : NULL;        if (auth_sep != -1)            octstr_set_char(url, auth_sep, ':');          host_len = host_len - at + prefix_len - 1;        prefix_len = at + 1;    }    /* query (CGI vars) */    query = octstr_search_char(url, '?', (slash == -1) ? prefix_len : slash);    if (query != -1) {        p->query = octstr_copy(url, query + 1, octstr_len(url));    }    /* path */    p->path = (slash == -1) ?         octstr_create("/") : ((query != -1) && (query > slash) ?             octstr_copy(url, slash, query - slash) :            octstr_copy(url, slash, octstr_len(url) - slash));     /* hostname */    p->host = octstr_copy(url, prefix_len,         (query == -1 || slash != -1) ? host_len : query - prefix_len);    /* XXX add fragment too */       /* dump components */    parse_dump(p);    return p;}/* copy all relevant parsed data to the server info struct */static void parse2trans(HTTPURLParse *p, HTTPServer *t){    if (p == NULL || t == NULL)        return;    if (p->user && !t->username)        t->username = octstr_duplicate(p->user);    if (p->pass && !t->password)        t->password = octstr_duplicate(p->pass);    if (p->host && !t->host)         t->host = octstr_duplicate(p->host);    if (p->port && !t->port)        t->port = p->port;    if (p->path && !t->uri) {        t->uri = octstr_duplicate(p->path);        if (p->query) { /* add the query too */            octstr_append_char(t->uri, '?');            octstr_append(t->uri, p->query);        }    }    t->ssl = (p->scheme && (octstr_compare(p->scheme, octstr_imm("https://")) == 0)               && !t->ssl) ? 1 : 0;}static Connection *get_connection(HTTPServer *trans) {    Connection *conn;    Octstr *host;    HTTPURLParse *p;    int port;    conn = NULL;    /* if the parsing has not yet been done, then do it now */    if (!trans->host && trans->port == 0 && trans->url != NULL) {        if ((p = parse_url(trans->url)) != NULL) {            parse2trans(p, trans);            http_urlparse_destroy(p);        } else {            goto error;        }    }    if (proxy_used_for_host(trans->host)) {        host = proxy_hostname;        port = proxy_port;    } else {        host = trans->host;        port = trans->port;    }    if (trans->retrying) {#ifdef HAVE_LIBSSL    if (trans->ssl) conn = conn_open_ssl(host, port, trans->certkeyfile, http_interface);        else#endif /* HAVE_LIBSSL */      conn = conn_open_tcp_nb(host, port, http_interface);            debug("gwlib.http", 0, "HTTP: Opening NEW connection to `%s:%d' (fd=%d).",                  octstr_get_cstr(host), port, conn_get_id(conn));    } else    conn = conn_pool_get(host, port, trans->ssl, trans->certkeyfile,                         http_interface);    if (conn == NULL)        goto error;  return conn;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -