httpd-cvs mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From ch...@locus.apache.org
Subject cvs commit: apache-2.0/src/modules/proxy proxy_http.c
Date Sat, 11 Nov 2000 11:06:15 GMT
chuck       00/11/11 03:06:13

  Modified:    src/modules/proxy proxy_http.c
  Log:
  This is the 1.3.x current proxy into 2.0 - first stage
  Obtained from: Sam Magnuson
  Submitted by:  Chuck Murcko
  
  Revision  Changes    Path
  1.17      +171 -166  apache-2.0/src/modules/proxy/proxy_http.c
  
  Index: proxy_http.c
  ===================================================================
  RCS file: /home/cvs/apache-2.0/src/modules/proxy/proxy_http.c,v
  retrieving revision 1.16
  retrieving revision 1.17
  diff -u -r1.16 -r1.17
  --- proxy_http.c	2000/10/08 03:23:05	1.16
  +++ proxy_http.c	2000/11/11 11:06:12	1.17
  @@ -58,7 +58,6 @@
   
   /* HTTP routines for Apache proxy */
   
  -#include "apr_strings.h"
   #include "mod_proxy.h"
   #include "http_log.h"
   #include "http_main.h"
  @@ -83,7 +82,7 @@
       port = def_port;
       err = ap_proxy_canon_netloc(r->pool, &url, NULL, NULL, &host, &port);
       if (err)
  -    return HTTP_BAD_REQUEST;
  +	return HTTP_BAD_REQUEST;
   
   /* now parse path/search args, according to rfc1738 */
   /* N.B. if this isn't a true proxy request, then the URL _path_
  @@ -91,25 +90,25 @@
    * == r->unparsed_uri, and no others have that property.
    */
       if (r->uri == r->unparsed_uri) {
  -    search = strchr(url, '?');
  -    if (search != NULL)
  -        *(search++) = '\0';
  +	search = strchr(url, '?');
  +	if (search != NULL)
  +	    *(search++) = '\0';
       }
       else
  -    search = r->args;
  +	search = r->args;
   
   /* process path */
       path = ap_proxy_canonenc(r->pool, url, strlen(url), enc_path, r->proxyreq);
       if (path == NULL)
  -    return HTTP_BAD_REQUEST;
  +	return HTTP_BAD_REQUEST;
   
       if (port != def_port)
  -    apr_snprintf(sport, sizeof(sport), ":%d", port);
  +	apr_snprintf(sport, sizeof(sport), ":%d", port);
       else
  -    sport[0] = '\0';
  +	sport[0] = '\0';
   
       r->filename = apr_pstrcat(r->pool, "proxy:", scheme, "://", host, sport, "/",
  -           path, (search) ? "?" : "", (search) ? search : "", NULL);
  +		   path, (search) ? "?" : "", (search) ? search : "", NULL);
       return OK;
   }
    
  @@ -135,7 +134,7 @@
       return url;
   }
   
  -/* Clear all connection-based headers from the incoming headers apr_table_t */
  +/* Clear all connection-based headers from the incoming headers table */
   static void clear_connection(apr_pool_t *p, apr_table_t *headers)
   {
       const char *name;
  @@ -143,17 +142,17 @@
   
       apr_table_unset(headers, "Proxy-Connection");
       if (!next)
  -        return;
  +		return;
   
       while (*next) {
  -        name = next;
  -        while (*next && !apr_isspace(*next) && (*next != ','))
  -            ++next;
  -        while (*next && (apr_isspace(*next) || (*next == ','))) {
  -            *next = '\0';
  -            ++next;
  -        }
  -        apr_table_unset(headers, name);
  +	name = next;
  +	while (*next && !apr_isspace(*next) && (*next != ','))
  +	    ++next;
  +	while (*next && (apr_isspace(*next) || (*next == ','))) {
  +	    *next = '\0';
  +	    ++next;
  +	}
  +	apr_table_unset(headers, name);
       }
       apr_table_unset(headers, "Connection");
   }
  @@ -167,34 +166,34 @@
    * we return DECLINED so that we can try another proxy. (Or the direct
    * route.)
    */
  -int ap_proxy_http_handler(request_rec *r, ap_cache_el  *c, char *url,
  -               const char *proxyhost, int proxyport)
  +int ap_proxy_http_handler(request_rec *r, ap_cache_el *c, char *url,
  +		       const char *proxyhost, int proxyport)
   {
       const char *strp;
       char *strp2;
       char *desthost;
       apr_socket_t *sock;
  -    int i, len, backasswards, content_length=-1;
  +    int i, len, backasswards, content_length = -1;
       apr_array_header_t *reqhdrs_arr;
  -    apr_table_t *resp_hdrs=NULL;
  +    apr_table_t *resp_hdrs = NULL;
       apr_table_entry_t *reqhdrs;
       struct sockaddr_in server;
       struct in_addr destaddr;
       BUFF *f;
  -    apr_file_t *cachefp=NULL;
       char buffer[HUGE_STRING_LEN];
       char portstr[32];
       apr_pool_t *p = r->pool;
       const long int zero = 0L;
       int destport = 0;
  -    apr_ssize_t cntr;
       char *destportstr = NULL;
       const char *urlptr = NULL;
       char *datestr, *clen;
  +    apr_ssize_t cntr;
  +    apr_file_t *cachefp = NULL;
   
       void *sconf = r->server->module_config;
       proxy_server_conf *conf =
  -        (proxy_server_conf *) ap_get_module_config(sconf, &proxy_module);
  +    (proxy_server_conf *) ap_get_module_config(sconf, &proxy_module);
       struct noproxy_entry *npent = (struct noproxy_entry *) conf->noproxies->elts;
       struct nocache_entry *ncent = (struct nocache_entry *) conf->nocaches->elts;
       int nocache = 0;
  @@ -206,38 +205,40 @@
   
       urlptr = strstr(url, "://");
       if (urlptr == NULL)
  -        return HTTP_BAD_REQUEST;
  +	return HTTP_BAD_REQUEST;
       urlptr += 3;
       destport = DEFAULT_HTTP_PORT;
       strp = ap_strchr_c(urlptr, '/');
       if (strp == NULL) {
  -        desthost = apr_pstrdup(p, urlptr);
  -        urlptr = "/";
  +	desthost = apr_pstrdup(p, urlptr);
  +	urlptr = "/";
       }
       else {
  -        char *q = apr_palloc(p, strp - urlptr + 1);
  -        memcpy(q, urlptr, strp - urlptr);
  -        q[strp - urlptr] = '\0';
  -        urlptr = strp;
  -        desthost = q;
  +	char *q = apr_palloc(p, strp - urlptr + 1);
  +	memcpy(q, urlptr, strp - urlptr);
  +	q[strp - urlptr] = '\0';
  +	urlptr = strp;
  +	desthost = q;
       }
   
       strp2 = ap_strchr(desthost, ':');
       if (strp2 != NULL) {
  -        *(strp2++) = '\0';
  -        if (apr_isdigit(*strp2)) {
  -            destport = atoi(strp2);
  -            destportstr = strp2;
  -        }
  +	*(strp2++) = '\0';
  +	if (apr_isdigit(*strp2)) {
  +	    destport = atoi(strp2);
  +	    destportstr = strp2;
  +	}
       }
   
   /* check if ProxyBlock directive on this host */
       destaddr.s_addr = apr_inet_addr(desthost);
       for (i = 0; i < conf->noproxies->nelts; i++) {
  -        if ((npent[i].name != NULL && ap_strstr_c(desthost, npent[i].name) != NULL)
  -            || destaddr.s_addr == npent[i].addr.s_addr || npent[i].name[0] == '*')
  -            return ap_proxyerror(r, HTTP_FORBIDDEN,
  -                                 "Connect to remote machine blocked");
  +	if ((npent[i].name != NULL
  +            && ap_strstr_c(desthost, npent[i].name) != NULL)
  +	    || destaddr.s_addr == npent[i].addr.s_addr
  +            || npent[i].name[0] == '*')
  +	    return ap_proxyerror(r, HTTP_FORBIDDEN,
  +				 "Connect to remote machine blocked");
       }
   
       if ((apr_create_tcp_socket(&sock, r->pool)) != APR_SUCCESS) {
  @@ -246,11 +247,14 @@
           return HTTP_INTERNAL_SERVER_ERROR;
       }
   
  -    if (conf->recv_buffer_size > 0 && apr_setsocketopt(sock, APR_SO_RCVBUF,conf->recv_buffer_size))
{
  -        ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r,
  -                      "setsockopt(SO_RCVBUF): Failed to set ProxyReceiveBufferSize, using
default");
  +#if !defined(TPF) && !defined(BEOS)
  +    if (conf->recv_buffer_size > 0 && apr_setsocketopt(sock, APR_SO_RCVBUF,
  +       conf->recv_buffer_size)) {
  +	    ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r,
  +                "setsockopt(SO_RCVBUF): Failed to set ProxyReceiveBufferSize, using default");
       }
  -    
  +#endif
  +
       if (proxyhost != NULL) {
           i = ap_proxy_doconnect(sock, (char *)proxyhost, proxyport, r);
       }
  @@ -259,147 +263,148 @@
       }
   
       if (i == -1) {
  -        if (proxyhost != NULL)
  -            return DECLINED;    /* try again another way */
  -        else
  -            return ap_proxyerror(r, HTTP_BAD_GATEWAY,
  -                apr_pstrcat(r->pool, "Could not connect to remote machine: ",
  -                    strerror(errno), NULL));
  +	if (proxyhost != NULL)
  +	    return DECLINED;	/* try again another way */
  +	else
  +	    return ap_proxyerror(r, HTTP_BAD_GATEWAY, apr_pstrcat(r->pool,
  +				"Could not connect to remote machine: ",
  +				strerror(errno), NULL));
       }
   
  -    clear_connection(r->pool, r->headers_in);    /* Strip connection-based headers
*/
  +    clear_connection(r->pool, r->headers_in);	/* Strip connection-based headers */
   
       f = ap_bcreate(p, B_RDWR);
       ap_bpush_socket(f, sock);
   
       ap_bvputs(f, r->method, " ", proxyhost ? url : urlptr, " HTTP/1.0" CRLF,
  -              NULL);
  +	   NULL);
       if (destportstr != NULL && destport != DEFAULT_HTTP_PORT)
  -        ap_bvputs(f, "Host: ", desthost, ":", destportstr, CRLF, NULL);
  +	ap_bvputs(f, "Host: ", desthost, ":", destportstr, CRLF, NULL);
       else
  -        ap_bvputs(f, "Host: ", desthost, CRLF, NULL);
  +	ap_bvputs(f, "Host: ", desthost, CRLF, NULL);
   
       if (conf->viaopt == via_block) {
  -        /* Block all outgoing Via: headers */
  -        apr_table_unset(r->headers_in, "Via");
  +	/* Block all outgoing Via: headers */
  +	apr_table_unset(r->headers_in, "Via");
       } else if (conf->viaopt != via_off) {
  -        /* Create a "Via:" request header entry and merge it */
  -        i = ap_get_server_port(r);
  -        if (ap_is_default_port(i,r)) {
  -            strcpy(portstr,"");
  -        } else {
  -            apr_snprintf(portstr, sizeof portstr, ":%d", i);
  -        }
  -        /* Generate outgoing Via: header with/without server comment: */
  -        apr_table_mergen(r->headers_in, "Via",
  -                        (conf->viaopt == via_full)
  -                        ? apr_psprintf(p, "%d.%d %s%s (%s)",
  -                                      HTTP_VERSION_MAJOR(r->proto_num),
  -                                      HTTP_VERSION_MINOR(r->proto_num),
  -                                      ap_get_server_name(r), portstr,
  -                                      AP_SERVER_BASEVERSION)
  -                        : apr_psprintf(p, "%d.%d %s%s",
  -                                      HTTP_VERSION_MAJOR(r->proto_num),
  -                                      HTTP_VERSION_MINOR(r->proto_num),
  -                                      ap_get_server_name(r), portstr)
  -            );
  +	/* Create a "Via:" request header entry and merge it */
  +	i = ap_get_server_port(r);
  +	if (ap_is_default_port(i,r)) {
  +	    strcpy(portstr,"");
  +	} else {
  +	    apr_snprintf(portstr, sizeof portstr, ":%d", i);
  +	}
  +	/* Generate outgoing Via: header with/without server comment: */
  +	ap_table_mergen(r->headers_in, "Via",
  +		    (conf->viaopt == via_full)
  +			? apr_psprintf(p, "%d.%d %s%s (%s)",
  +				HTTP_VERSION_MAJOR(r->proto_num),
  +				HTTP_VERSION_MINOR(r->proto_num),
  +				ap_get_server_name(r), portstr,
  +				AP_SERVER_BASEVERSION)
  +			: apr_psprintf(p, "%d.%d %s%s",
  +				HTTP_VERSION_MAJOR(r->proto_num),
  +				HTTP_VERSION_MINOR(r->proto_num),
  +				ap_get_server_name(r), portstr)
  +			);
       }
   
       reqhdrs_arr = apr_table_elts(r->headers_in);
       reqhdrs = (apr_table_entry_t *) reqhdrs_arr->elts;
       for (i = 0; i < reqhdrs_arr->nelts; i++) {
  -        if (reqhdrs[i].key == NULL || reqhdrs[i].val == NULL
  -            /* Clear out headers not to send */
  -            || !strcasecmp(reqhdrs[i].key, "Host")    /* Already sent */
  -            /* XXX: @@@ FIXME: "Proxy-Authorization" should *only* be 
  -             * suppressed if THIS server requested the authentication,
  -             * not when a frontend proxy requested it!
  -             */
  -            || !strcasecmp(reqhdrs[i].key, "Proxy-Authorization"))
  -            continue;
  -        ap_bvputs(f, reqhdrs[i].key, ": ", reqhdrs[i].val, CRLF, NULL);
  +	if (reqhdrs[i].key == NULL || reqhdrs[i].val == NULL
  +	/* Clear out headers not to send */
  +	    || !strcasecmp(reqhdrs[i].key, "Host")	/* Already sent */
  +	    /* XXX: @@@ FIXME: "Proxy-Authorization" should *only* be 
  +	     * suppressed if THIS server requested the authentication,
  +	     * not when a frontend proxy requested it!
  +	     */
  +	    || !strcasecmp(reqhdrs[i].key, "Proxy-Authorization"))
  +	    continue;
  +	ap_bvputs(f, reqhdrs[i].key, ": ", reqhdrs[i].val, CRLF, NULL);
       }
   
       ap_bputs(CRLF, f);
   /* send the request data, if any. */
   
       if (ap_should_client_block(r)) {
  -        while ((i = ap_get_client_block(r, buffer, sizeof buffer)) > 0)
  -            ap_bwrite(f, buffer, i, &cntr);
  +	while ((i = ap_get_client_block(r, buffer, sizeof buffer)) > 0)
  +	    ap_bwrite(f, buffer, i, &cntr);
       }
       ap_bflush(f);
   
       len = ap_bgets(buffer, sizeof buffer - 1, f);
       if (len == -1) {
  -        ap_bclose(f);
  -        ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r,
  -                      "ap_bgets() - proxy receive - Error reading from remote server %s
(length %d)",
  -                      proxyhost ? proxyhost : desthost, len);
  -        return ap_proxyerror(r, HTTP_BAD_GATEWAY,
  -                             "Error reading from remote server");
  +	ap_bclose(f);
  +	ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r,
  +	     "ap_bgets() - proxy receive - Error reading from remote server %s (length %d)",
  +	     proxyhost ? proxyhost : desthost, len);
  +	return ap_proxyerror(r, HTTP_BAD_GATEWAY,
  +			     "Error reading from remote server");
       } else if (len == 0) {
  -        ap_bclose(f);
  -        return ap_proxyerror(r, HTTP_BAD_GATEWAY,
  -                             "Document contains no data");
  +	ap_bclose(f);
  +	return ap_proxyerror(r, HTTP_BAD_GATEWAY,
  +			     "Document contains no data");
       }
   
   /* Is it an HTTP/1 response?  This is buggy if we ever see an HTTP/1.10 */
       if (ap_checkmask(buffer, "HTTP/#.# ###*")) {
  -        int major, minor;
  -        if (2 != sscanf(buffer, "HTTP/%u.%u", &major, &minor)) {
  -            major = 1;
  -            minor = 0;
  -        }
  +	int major, minor;
  +	if (2 != sscanf(buffer, "HTTP/%u.%u", &major, &minor)) {
  +	    major = 1;
  +	    minor = 0;
  +	}
   
   /* If not an HTTP/1 message or if the status line was > 8192 bytes */
  -        if (buffer[5] != '1' || buffer[len - 1] != '\n') {
  -            ap_bclose(f);
  -            return HTTP_BAD_GATEWAY;
  -        }
  -        backasswards = 0;
  -        buffer[--len] = '\0';
  -
  -        buffer[12] = '\0';
  -        r->status = atoi(&buffer[9]);
  -        buffer[12] = ' ';
  -        r->status_line = apr_pstrdup(p, &buffer[9]);
  +	if (buffer[5] != '1' || buffer[len - 1] != '\n') {
  +	    ap_bclose(f);
  +	    return HTTP_BAD_GATEWAY;
  +	}
  +	backasswards = 0;
  +	buffer[--len] = '\0';
  +
  +	buffer[12] = '\0';
  +	r->status = atoi(&buffer[9]);
  +	buffer[12] = ' ';
  +	r->status_line = apr_pstrdup(p, &buffer[9]);
   
   /* read the headers. */
   /* N.B. for HTTP/1.0 clients, we have to fold line-wrapped headers */
   /* Also, take care with headers with multiple occurences. */
  -        resp_hdrs = ap_proxy_read_headers(r, buffer, HUGE_STRING_LEN, f);
  -        if (resp_hdrs == NULL) {
  -            ap_log_error(APLOG_MARK, APLOG_WARNING|APLOG_NOERRNO, 0, r->server,
  -                         "proxy: Bad HTTP/%d.%d header returned by %s (%s)",
  -                         major, minor, r->uri, r->method);
  -            nocache = 1;    /* do not cache this broken file */
  -        }
  +
  +	resp_hdrs = ap_proxy_read_headers(r, buffer, HUGE_STRING_LEN, f);
  +	if (resp_hdrs == NULL) {
  +	    ap_log_error(APLOG_MARK, APLOG_WARNING|APLOG_NOERRNO, 0, r->server,
  +		 "proxy: Bad HTTP/%d.%d header returned by %s (%s)",
  +		 major, minor, r->uri, r->method);
  +	    nocache = 1;    /* do not cache this broken file */
  +	}
           else
           {
               clear_connection(p, resp_hdrs);    /* Strip Connection hdrs */
               ap_cache_el_header_merge(c, resp_hdrs);
           }
  -            
  -        if (conf->viaopt != via_off && conf->viaopt != via_block) {
  -            /* Create a "Via:" response header entry and merge it */
  -            i = ap_get_server_port(r);
  -            if (ap_is_default_port(i,r)) {
  -                strcpy(portstr,"");
  -            } else {
  -                apr_snprintf(portstr, sizeof portstr, ":%d", i);
  -            }
  +
  +	if (conf->viaopt != via_off && conf->viaopt != via_block) {
  +	    /* Create a "Via:" response header entry and merge it */
  +	    i = ap_get_server_port(r);
  +	    if (ap_is_default_port(i,r)) {
  +		strcpy(portstr,"");
  +	    } else {
  +		apr_snprintf(portstr, sizeof portstr, ":%d", i);
  +	    }
               ap_cache_el_header_add(c, "Via", (conf->viaopt == via_full)
  -                         ? apr_psprintf(p, "%d.%d %s%s (%s)", major, minor,
  -                                       ap_get_server_name(r), portstr, AP_SERVER_BASEVERSION)
  -                         : apr_psprintf(p, "%d.%d %s%s", major, minor, ap_get_server_name(r),
portstr)
  -                );
  -        }
  +                ? apr_psprintf(p, "%d.%d %s%s (%s)", major, minor,
  +                ap_get_server_name(r), portstr, AP_SERVER_BASEVERSION)
  +                : apr_psprintf(p, "%d.%d %s%s", major, minor,
  +                ap_get_server_name(r), portstr));
  +	}
       }
       else {
   /* an http/0.9 response */
  -        backasswards = 1;
  -        r->status = 200;
  -        r->status_line = "200 OK";
  +	backasswards = 1;
  +	r->status = 200;
  +	r->status_line = "200 OK";
       }
   
   /*
  @@ -423,44 +428,44 @@
           content_length = atoi(clen ? clen : "-1");
   
       for (i = 0; i < conf->nocaches->nelts; i++) {
  -        if ((ncent[i].name != NULL && ap_strstr_c(desthost, ncent[i].name) != NULL)
  -            || destaddr.s_addr == ncent[i].addr.s_addr || ncent[i].name[0] == '*')
  -            nocache = 1;
  +	if ((ncent[i].name != NULL && ap_strstr_c(desthost, ncent[i].name) != NULL)
  +	  || destaddr.s_addr == ncent[i].addr.s_addr || ncent[i].name[0] == '*')
  +	    nocache = 1;
       }
   
       if(nocache || !ap_proxy_cache_should_cache(r, resp_hdrs, !backasswards))
           ap_proxy_cache_error(&c);
       else
           ap_cache_el_data(c, &cachefp);
  -    
  +
   /* write status line */
       if (!r->assbackwards)
  -        ap_rvputs(r, "HTTP/1.0 ", r->status_line, CRLF, NULL);
  -    if (cachefp &&    apr_puts(apr_pstrcat(r->pool, "HTTP/1.0 ", r->status_line,
CRLF, NULL), cachefp) != APR_SUCCESS) {
  -        ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r,
  -                      "proxy: error writing status line to cache");
  -        ap_proxy_cache_error(&c);
  -        cachefp = NULL;
  +	ap_rvputs(r, "HTTP/1.0 ", r->status_line, CRLF, NULL);
  +    if (cachefp && apr_puts(apr_pstrcat(r->pool, "HTTP/1.0 ",
  +        r->status_line, CRLF, NULL), cachefp) != APR_SUCCESS) {
  +	    ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r,
  +		"proxy: error writing status line to cache");
  +	    ap_proxy_cache_error(&c);
  +            cachefp = NULL;
       }
   
   /* send headers */
       ap_cache_el_header_walk(c, ap_proxy_send_hdr_line, r, NULL);
   
       if (!r->assbackwards)
  -        ap_rputs(CRLF, r);
  +	ap_rputs(CRLF, r);
   
       ap_bsetopt(r->connection->client, BO_BYTECT, &zero);
       r->sent_bodyct = 1;
  -/* Is it an HTTP/0.9 respose? If so, send the extra data */
  +/* Is it an HTTP/0.9 response? If so, send the extra data */
       if (backasswards) {
  -        ap_bwrite(r->connection->client, buffer, len, &cntr);
  +	ap_bwrite(r->connection->client, buffer, len, &cntr);
           cntr = len;
           if (cachefp && apr_write(cachefp, buffer, &cntr) != APR_SUCCESS) {
  -            ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r,
  -                          "proxy: error writing extra data to cache %ld",
  -                          (long)cachefp);
  -            ap_proxy_cache_error(&c);
  -        }
  +	    ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r,
  +		"proxy: error writing extra data to cache");
  +	    ap_proxy_cache_error(&c);
  +	}
       }
   
   #ifdef CHARSET_EBCDIC
  @@ -471,14 +476,14 @@
       ap_bsetflag(r->connection->client, B_ASCII2EBCDIC|B_EBCDIC2ASCII, 0);
   #endif
   
  -    /* send body */
  -    /* if header only, then cache will be NULL */
  -    /* HTTP/1.0 tells us to read to EOF, rather than content-length bytes */
  +	/* send body */
  +	/* if header only, then cache will be NULL */
  +	/* HTTP/1.0 tells us to read to EOF, rather than content-length bytes */
       if (!r->header_only) {
  -        proxy_completion pc;
  -        pc.content_length = content_length;
  -        pc.cache_completion = conf->cache_completion;
  -        ap_proxy_send_fb(&pc, f, r, c);
  +		proxy_completion pc;
  +		pc.content_length = content_length;
  +		pc.cache_completion = conf->cache_completion;
  +		ap_proxy_send_fb(&pc, f, r, c);
       }
   
       ap_bclose(f);
  
  
  

Mime
View raw message