apr_status_t
rainx_http_req(struct req_params_store* rps) {
	const dav_resource* resource = rps->resource;
	char* remote_uri = rps->service_address;
	char* req_type = rps->req_type;
	char* header = rps->header;
	char* data = rps->data_to_send;
	int data_length = rps->data_to_send_size;
	char** reply = &(rps->reply);
	apr_pool_t *local_pool = rps->pool;
	dav_rainx_server_conf *server_conf = resource_get_server_config(resource);

	if (NULL == resource || NULL == remote_uri ||
			NULL == req_type || NULL == server_conf) {
		DAV_ERROR_POOL(local_pool, APR_EINVAL, "One of these params is wrong: "
				"remote_uri=%p, req_type=%p, server_conf=%p"
				" (__FILE__:__LINE__)",
				remote_uri, req_type, server_conf);
		return APR_EINVAL;
	}

	const gboolean is_get = (0 == g_strcmp0(req_type, "GET"));

	/* Isolating Rawx IP and port */
	char *temp_remote_uri = apr_pstrdup(local_pool, remote_uri);
	char* last;
	char* full_remote_url = apr_strtok(temp_remote_uri, "/", &last);
	char* content_hexid = apr_pstrdup(local_pool, remote_uri + strlen(full_remote_url));

	char* remote_ip = NULL;
	char* scope_id = NULL;
	apr_port_t remote_port;
	apr_parse_addr_port(&remote_ip, &scope_id, &remote_port, full_remote_url, local_pool);
	/* ------- */

	/* Preparing the socket */
	apr_socket_t* sock;
	apr_sockaddr_t* sockaddr;
	apr_status_t status;

	if ((status = apr_sockaddr_info_get(&sockaddr, remote_ip, APR_INET, remote_port, 0, local_pool)) != APR_SUCCESS) {
		DAV_DEBUG_REQ(resource->info->request, 0, "unable to connect to the rawx %s", full_remote_url);
		return status;
	}

	if ((status = apr_socket_create(&sock, sockaddr->family, SOCK_STREAM, APR_PROTO_TCP, local_pool)) != APR_SUCCESS) {
		DAV_DEBUG_REQ(resource->info->request, 0, "unable to create a socket to the rawx %s", full_remote_url);
		return status;
	}

	if ((status = apr_socket_timeout_set(sock, server_conf->socket_timeout)) != APR_SUCCESS) {
		DAV_DEBUG_REQ(resource->info->request, 0, "unable to set timeout for the socket to the rawx %s", full_remote_url);
		return status;
	}

	if ((status = apr_socket_connect(sock, sockaddr)) != APR_SUCCESS) {
		DAV_DEBUG_REQ(resource->info->request, 0, "unable to establish the connection to the rawx %s", full_remote_url);
		return status;
	}
	/* ------- */

	/* Forging the message */
	char* forged_header = apr_psprintf(local_pool, "%s %s HTTP/1.1\nHost: %s", req_type, content_hexid, full_remote_url);
	if (header)
		forged_header = apr_psprintf(local_pool, "%s\n%s", forged_header, header);
	if (data)
		forged_header = apr_psprintf(local_pool, "%s\nContent-Length: %d\n\n", forged_header, data_length);
	else
		forged_header = apr_psprintf(local_pool, "%s\n\n", forged_header);
	/* ------- */

	/* Sending the message */
	int remaining_to_send = strlen(forged_header);
	char* ptr_start = forged_header;
	apr_size_t send_buffer_size;
	while (remaining_to_send > 0) {
		if (remaining_to_send < REQUEST_BUFFER_SIZE)
			send_buffer_size = (apr_size_t)remaining_to_send;
		else
			send_buffer_size = REQUEST_BUFFER_SIZE;

		if ((status = apr_socket_send(sock, ptr_start, &send_buffer_size)) != APR_SUCCESS) {
            DAV_DEBUG_REQ(resource->info->request, 0, "failed to send the %s request to the rawx %s", req_type, full_remote_url);
            apr_status_t status_sav = status;
            apr_socket_close(sock);
            return status_sav;
        }

		remaining_to_send -= send_buffer_size;
		ptr_start = ptr_start + send_buffer_size;
	}
	if (NULL != data) {
		remaining_to_send = data_length;
		ptr_start = data;
		while (remaining_to_send > 0) {
			if (remaining_to_send < REQUEST_BUFFER_SIZE)
				send_buffer_size = (apr_size_t)remaining_to_send;
			else
				send_buffer_size = REQUEST_BUFFER_SIZE;

			if ((status = apr_socket_send(sock, ptr_start, &send_buffer_size)) != APR_SUCCESS) {
				DAV_DEBUG_REQ(resource->info->request, 0, "failed to send the %s request to the rawx %s", req_type, full_remote_url);
				apr_status_t status_sav = status;
				apr_socket_close(sock);
				return status_sav;
			}

			remaining_to_send -= send_buffer_size;
			ptr_start = ptr_start + send_buffer_size;
		}
	}

	if (is_get) {
		/* This avoids a ~5s delay in the communication */
		apr_socket_shutdown(sock, APR_SHUTDOWN_WRITE);
	}

	DAV_DEBUG_REQ(resource->info->request, 0, "%s request to the rawx %s sent for the content %s", req_type, full_remote_url, content_hexid);
    /* ------ */

	/* Getting the reply */
	char* reply_ptr = *reply;
	apr_size_t total_size;
	if (!is_get)
		total_size = REPLY_BUFFER_SIZE; // PUT or DELETE
	else
		total_size = MAX_REPLY_HEADER_SIZE + data_length; // GET
	apr_size_t reply_size = (apr_size_t)total_size;
	apr_size_t total_replied_size;
	do {
		status = apr_socket_recv(sock, reply_ptr, &reply_size);
		reply_ptr += reply_size;
		total_replied_size = reply_ptr - *reply;
		/* Leave when OK, or error != timeout, or buffer full */
        if (status == APR_EOF || (status == APR_SUCCESS && !is_get) ||
				(reply_size == 0) ||
				total_replied_size >= total_size) {
            break;
		}
		/* Take care of overflows! */
		reply_size = total_size - total_replied_size;
	} while (total_replied_size < total_size);
	/* ------- */

	apr_socket_close(sock);

	return status;
}
Example #2
0
static apr_status_t
socket_write(serv_ctx_t *serv_ctx, const char *data,
             apr_size_t *len)
{
    return apr_socket_send(serv_ctx->client_sock, data, len);
}
Example #3
0
bool LLPluginMessagePipe::pumpOutput()
{
	bool result = true;
	
	if(mSocket)
	{
		apr_status_t status;
		apr_size_t in_size, out_size;
		
		LLMutexLock lock(&mOutputMutex);

		const char * output_data = &(mOutput.data()[mOutputStartIndex]);
		if(*output_data != '\0')
		{
			// write any outgoing messages
			in_size = (apr_size_t) (mOutput.size() - mOutputStartIndex);
			out_size = in_size;
			
			setSocketTimeout(0);
			
//			LL_INFOS("Plugin") << "before apr_socket_send, size = " << size << LL_ENDL;

			status = apr_socket_send(mSocket->getSocket(),
									 output_data,
									 &out_size);

//			LL_INFOS("Plugin") << "after apr_socket_send, size = " << size << LL_ENDL;
			
			if((status == APR_SUCCESS) || APR_STATUS_IS_EAGAIN(status))
			{
				// Success or Socket buffer is full... 
				
				// If we've pumped the entire string, clear it
				if (out_size == in_size)
				{
					mOutputStartIndex = 0;
					mOutput.clear();
				}
				else
				{
					llassert(in_size > out_size);
					
					// Remove the written part from the buffer and try again later.
					mOutputStartIndex += out_size;
				}
			}
			else if(APR_STATUS_IS_EOF(status))
			{
				// This is what we normally expect when a plugin exits.
				llinfos << "Got EOF from plugin socket. " << llendl;

				if(mOwner)
				{
					mOwner->socketError(status);
				}
				result = false;
			}
			else 
			{
				// some other error
				// Treat this as fatal.
				ll_apr_warn_status(status);
				
				if(mOwner)
				{
					mOwner->socketError(status);
				}
				result = false;
			}
		}
	}
	
	return result;
}
/* return 0 means OK, return -1 means ERROR */
static int update_expired_data_from_remote_info (request_rec *r,
                                                 REMOTE_INFO *p_remote_info)
{
    apr_size_t len;
    char errmsg_buf[120];
    apr_pool_t *rp = r->pool;
    apr_time_t cur_time = apr_time_now ();
    int redirect_cnt;

    char *now_url = apr_pstrdup (rp, p_remote_info->remote_url);
    char *hostname;
    apr_int64_t port;
    char *filepath;
    
    apr_status_t rv;
    apr_socket_t *s;
    apr_sockaddr_t *sa;

    char *req_msg;
    char header[HEADER_SIZE + 10], redundant[HEADER_SIZE + 10];
    apr_size_t hlen, rlen;
    char *status_code;
    apr_size_t expect_len;
    char *content_type;
    char *file_content;
    apr_size_t flen;
    char *ts;

#ifdef DEBUG
    ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, "before loop");
#endif

    for (redirect_cnt = 0; redirect_cnt <= MAX_REDIRECT_TIME; redirect_cnt++) {

        if (parse_url (r, now_url, &hostname, &port, &filepath) == -1) {
            ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r,
                          "the module fail to get info from remote url,"
                          " remote url in configuration file may be invalid.");
#ifdef DEBUG
            ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r,
                          "fail to parse %s", now_url);
#endif
            return -1;
        }

#ifdef DEBUG
        ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, "before build connection");
        ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r,
                      "hostname: %s | filepath: %s | port: %lld",
                      hostname, filepath, port);
#endif
            /* build connection */
        rv = build_connection (r, hostname, port, &s, &sa);
        if (rv != APR_SUCCESS) {
            apr_strerror (rv, errmsg_buf, sizeof (errmsg_buf));
            ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r,
                          "connection error: %s", errmsg_buf);
            return -1;
        }

            /* set timeout */
        apr_socket_opt_set (s, APR_SO_NONBLOCK, 1);
        apr_socket_timeout_set (s, DEF_SOCK_TIMEOUT);

            /* send request */
        req_msg = apr_pstrcat(rp, "GET ", filepath, " HTTP/1.0", CRLF_STR,
                              "If-Modified-Since: ",
                              p_remote_info->last_update_time,
                              CRLF_STR, CRLF_STR, NULL);
        len = strlen (req_msg);
        rv = apr_socket_send (s, req_msg, &len);
        if (rv != APR_SUCCESS) {
            apr_strerror (rv, errmsg_buf, sizeof (errmsg_buf));
            ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r,
                          "fail to send the request to url: %s", errmsg_buf);
            return -1;
        }

#ifdef DEBUG
        ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, "before get header");
#endif
            /* get response header */
        hlen = rlen = HEADER_SIZE;
        if (get_header_from_response (r, s, header, &hlen, redundant, &rlen)
            == -1)
            return -1;

#ifdef DEBUG
        header[hlen] = '\0';
        ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, "header: %s", header);
#endif

            /* get status code */
        if (get_status_code_from_header (r, header, hlen, &status_code) == -1)
            return -1;

#ifdef DEBUG
        ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r,
                      "status code: %s", status_code);
#endif
        
            /* deal with different status_code */
        if (strcmp (status_code, "200") == 0
            || (strcmp (status_code, "304") == 0
                && strcmp (now_url, p_remote_info->last_update_url) != 0)) {
                /* need to update */
            if (get_content_length_from_header
                (r, header, hlen, FILE_SIZE, &expect_len)
                == -1)
                return -1;

            if (get_content_type_from_header (r, header, hlen, &content_type)
                == -1)
                return -1;
#ifdef DEBUG
            ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r,
                          "Content-Type: %s", content_type);
#endif
            if (strncasecmp (content_type, "text", 4) != 0) {
                ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r,
                              "the module fail to get info from "
                              "remote url, remote url in configuration"
                              " file may be invalid.");
                return -1;
            }
            
            file_content = apr_palloc (rp, expect_len + 2);
            if (get_body_from_response
                (r, s, expect_len, redundant, rlen, file_content, &flen)
                == -1)
                return -1;

#ifdef DEBUG
            file_content[flen] = '\0';
            ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r,
                          "file_content: %s", file_content);
#endif

                /* clear the pool, preventing leakage */
            apr_pool_clear (p_remote_info->subpool);
                /* update last_update_time */
            if (get_date_from_header (r, header, hlen, &ts) == -1) {
                ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, "date unfound");
                p_remote_info->last_update_time = NULL;
            }
            else {
                p_remote_info->last_update_time =
                    apr_pstrdup (p_remote_info->subpool, ts);
            }
                /* update last_update_url */
            p_remote_info->last_update_url =
                apr_pstrdup (p_remote_info->subpool, now_url);
                /* get the ipsubnet_list from file_content*/
            file_content[flen] = '\n';
            get_ipsubnet_list_from_file_content (r,
                                                 p_remote_info->subpool,
                                                 file_content,
                                                 flen,
                                                 &(p_remote_info->p_ipsubnet_list));

            return 0;
        }
        else if (strcmp (status_code, "304") == 0) {/* not modified */
            return 0;
        }
        else if (strcmp (status_code, "300") == 0
                 || strcmp (status_code, "301") == 0
                 || strcmp (status_code, "302") == 0
                 || strcmp (status_code, "307") == 0) {/* redirect */
            if (get_location_from_header (r, header, hlen, &now_url) == -1) {
                ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r,
                              "the module fail to get info"
                              " from remote url, remote url in "
                              "configuration file may be invalid.");
                return -1;
            }
            continue;
        }
        else {
            ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r,
                          "the module fail to get info"
                          " from remote url, remote url in "
                          "configuration file may be invalid.");
            return -1;
        }
    }

    ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r,
                  "the remote url redirects too many times,"
                  " auth_remote_module stop updating data from"
                  " url to prevent infinite redirection loop");
    return -1;
}
/* Send the OCSP request serialized into BIO 'request' to the
 * responder at given server given by URI.  Returns socket object or
 * NULL on error. */
static apr_socket_t *send_request(BIO *request, const apr_uri_t *uri,
                                  apr_interval_time_t timeout,
                                  conn_rec *c, apr_pool_t *p,
                                  const apr_uri_t *proxy_uri)
{
    apr_status_t rv;
    apr_sockaddr_t *sa;
    apr_socket_t *sd;
    char buf[HUGE_STRING_LEN];
    int len;
    const apr_uri_t *next_hop_uri;

    if (proxy_uri) {
        next_hop_uri = proxy_uri;
    }
    else {
        next_hop_uri = uri;
    }

    rv = apr_sockaddr_info_get(&sa, next_hop_uri->hostname, APR_UNSPEC,
                               next_hop_uri->port, 0, p);
    if (rv) {
        ap_log_cerror(APLOG_MARK, APLOG_ERR, rv, c, APLOGNO(01972)
                      "could not resolve address of %s %s",
                      proxy_uri ? "proxy" : "OCSP responder",
                      next_hop_uri->hostinfo);
        return NULL;
    }

    /* establish a connection to the OCSP responder */
    ap_log_cerror(APLOG_MARK, APLOG_DEBUG, 0, c, APLOGNO(01973)
                  "connecting to %s '%s'",
                  proxy_uri ? "proxy" : "OCSP responder",
                  uri->hostinfo);

    /* Cycle through address until a connect() succeeds. */
    for (; sa; sa = sa->next) {
        rv = apr_socket_create(&sd, sa->family, SOCK_STREAM, APR_PROTO_TCP, p);
        if (rv == APR_SUCCESS) {
            apr_socket_timeout_set(sd, timeout);

            rv = apr_socket_connect(sd, sa);
            if (rv == APR_SUCCESS) {
                break;
            }
            apr_socket_close(sd);
        }
    }

    if (sa == NULL) {
        ap_log_cerror(APLOG_MARK, APLOG_ERR, rv, c, APLOGNO(01974)
                      "could not connect to %s '%s'",
                      proxy_uri ? "proxy" : "OCSP responder",
                      next_hop_uri->hostinfo);
        return NULL;
    }

    /* send the request and get a response */
    ap_log_cerror(APLOG_MARK, APLOG_DEBUG, 0, c, APLOGNO(01975)
                 "sending request to OCSP responder");

    while ((len = BIO_read(request, buf, sizeof buf)) > 0) {
        char *wbuf = buf;
        apr_size_t remain = len;

        do {
            apr_size_t wlen = remain;

            rv = apr_socket_send(sd, wbuf, &wlen);
            wbuf += remain;
            remain -= wlen;
        } while (rv == APR_SUCCESS && remain > 0);

        if (rv) {
            apr_socket_close(sd);
            ap_log_cerror(APLOG_MARK, APLOG_ERR, rv, c, APLOGNO(01976)
                          "failed to send request to OCSP responder '%s'",
                          uri->hostinfo);
            return NULL;
        }
    }

    return sd;
}
Example #6
0
bool LLPluginMessagePipe::pumpOutput()
{
	bool result = true;
	
	if(mSocket)
	{
		apr_status_t status;
		apr_size_t size;
		
		LLMutexLock lock(&mOutputMutex);
		if(!mOutput.empty())
		{
			// write any outgoing messages
			size = (apr_size_t)mOutput.size();
			
			setSocketTimeout(0);
			
//			LL_INFOS("Plugin") << "before apr_socket_send, size = " << size << LL_ENDL;

			status = apr_socket_send(
					mSocket->getSocket(),
					(const char*)mOutput.data(),
					&size);

//			LL_INFOS("Plugin") << "after apr_socket_send, size = " << size << LL_ENDL;
			
			if(status == APR_SUCCESS)
			{
				// success
				mOutput = mOutput.substr(size);
			}
			else if(APR_STATUS_IS_EAGAIN(status))
			{
				// Socket buffer is full... 
				// remove the written part from the buffer and try again later.
				mOutput = mOutput.substr(size);
			}
			else if(APR_STATUS_IS_EOF(status))
			{
				// This is what we normally expect when a plugin exits.
				llinfos << "Got EOF from plugin socket. " << llendl;

				if(mOwner)
				{
					mOwner->socketError(status);
				}
				result = false;
			}
			else 
			{
				// some other error
				// Treat this as fatal.
				ll_apr_warn_status(status);
				
				if(mOwner)
				{
					mOwner->socketError(status);
				}
				result = false;
			}
		}
	}
	
	return result;
}
/**
 * Process input stream
 */
static apr_status_t helocon_filter_in(ap_filter_t *f, apr_bucket_brigade *b, ap_input_mode_t mode, apr_read_type_e block, apr_off_t readbytes)
{
    conn_rec *c = f->c;
    my_ctx *ctx = f->ctx;

    // Fail quickly if the connection has already been aborted.
    if (c->aborted) {
        apr_brigade_cleanup(b);
        return APR_ECONNABORTED;
    }
    // Fast passthrough
    if (ctx->phase == PHASE_DONE) {
        return ap_get_brigade(f->next, b, mode, block, readbytes);
    }

    // Process Head
    do {
#ifdef DEBUG
        ap_log_error(APLOG_MARK, APLOG_WARNING, 0, NULL, MODULE_NAME "::helocon_filter_in from: %s:%d to port=%d need=%" APR_OFF_T_FMT " phase=%d (1)", _CLIENT_IP, _CLIENT_ADDR->port, c->local_addr->port, ctx->need, ctx->phase);
#endif

        if (APR_BRIGADE_EMPTY(b)) {
#ifdef DEBUG
            ap_log_error(APLOG_MARK, APLOG_WARNING, 0, NULL, MODULE_NAME "::helocon_filter_in from: %s:%d to port=%d need=%" APR_OFF_T_FMT " phase=%d (2)", _CLIENT_IP, _CLIENT_ADDR->port, c->local_addr->port, ctx->need, ctx->phase);
#endif
            apr_status_t s = ap_get_brigade(f->next, b, ctx->mode, APR_BLOCK_READ, ctx->need);
            if (s != APR_SUCCESS) {
#ifdef DEBUG
                ap_log_error(APLOG_MARK, APLOG_WARNING, 0, NULL, MODULE_NAME "::helocon_filter_in from: %s:%d to port=%d need=%" APR_OFF_T_FMT " phase=%d (fail)(1)", _CLIENT_IP, _CLIENT_ADDR->port, c->local_addr->port, ctx->need, ctx->phase);
#endif
                return s;
            }
        }
        if (ctx->phase == PHASE_DONE) {
            return APR_SUCCESS;
        }
        if (APR_BRIGADE_EMPTY(b)) {
#ifdef DEBUG
            ap_log_error(APLOG_MARK, APLOG_WARNING, 0, NULL, MODULE_NAME "::helocon_filter_in from: %s:%d to port=%d need=%" APR_OFF_T_FMT " phase=%d (empty)", _CLIENT_IP, _CLIENT_ADDR->port, c->local_addr->port, ctx->need, ctx->phase);
#endif
            return APR_SUCCESS;
        }
        apr_bucket *e = NULL;
        for (e = APR_BRIGADE_FIRST(b); e != APR_BRIGADE_SENTINEL(b); e = APR_BUCKET_NEXT(e)) {
            if (e->type == NULL) {
#ifdef DEBUG
                ap_log_error(APLOG_MARK, APLOG_WARNING, 0, NULL, MODULE_NAME "::helocon_filter_in from: %s:%d to port=%d need=%" APR_OFF_T_FMT " phase=%d (type=NULL)", _CLIENT_IP, _CLIENT_ADDR->port, c->local_addr->port, ctx->need, ctx->phase);
#endif
                return APR_SUCCESS;
            }

            // We need more data
            if (ctx->need > 0) {
                const char *str = NULL;
                apr_size_t length = 0;
                apr_status_t s = apr_bucket_read(e, &str, &length, APR_BLOCK_READ);
                if (s != APR_SUCCESS) {
#ifdef DEBUG
                    ap_log_error(APLOG_MARK, APLOG_WARNING, 0, NULL, MODULE_NAME "::helocon_filter_in from: %s:%d to port=%d need=%" APR_OFF_T_FMT " recv=%" APR_OFF_T_FMT " phase=%d readed=%" APR_SIZE_T_FMT " (fail)(2)", _CLIENT_IP, _CLIENT_ADDR->port, c->local_addr->port, ctx->need, ctx->recv, ctx->phase, length);
#endif
                    return s;
                }
#ifdef DEBUG
                ap_log_error(APLOG_MARK, APLOG_WARNING, 0, NULL, MODULE_NAME "::helocon_filter_in from: %s:%d to port=%d need=%" APR_OFF_T_FMT " recv=%" APR_OFF_T_FMT " phase=%d readed=%" APR_SIZE_T_FMT " (3)", _CLIENT_IP, _CLIENT_ADDR->port, c->local_addr->port, ctx->need, ctx->recv, ctx->phase, length);
#endif
                if (length > 0) {
                    if ((ctx->offset + length) > PROXY_MAX_LENGTH) { // Overflow
                        ap_log_error(APLOG_MARK, APLOG_WARNING, 0, NULL, MODULE_NAME "::helocon_filter_in ERROR: PROXY protocol header overflow from=%s to port=%d length=%" APR_OFF_T_FMT, _CLIENT_IP, c->local_addr->port, (ctx->offset + length));
                        goto ABORT_CONN2;
                    }
                    memcpy(ctx->buf + ctx->offset, str, length);
                    if (ctx->pad != ctx->magic) {
                        ap_log_error(APLOG_MARK, APLOG_WARNING, 0, NULL, MODULE_NAME "::helocon_filter_in padding magic fail (bad=%d vs good=%d)", ctx->pad, ctx->magic);
                        goto ABORT_CONN;
                    }
                    ctx->offset += length;
                    ctx->recv += length;
                    ctx->need -= length;
                    ctx->buf[ctx->offset] = 0;
                    // delete HEAD
                    if (e->length > length) {
                        apr_bucket_split(e, length);
                    }
                }
                apr_bucket_delete(e);
                if (length == 0) {
#ifdef DEBUG
                    ap_log_error(APLOG_MARK, APLOG_WARNING, 0, NULL, MODULE_NAME "::helocon_filter_in DEBUG bucket flush=%d meta=%d", APR_BUCKET_IS_FLUSH(e) ? 1 : 0, APR_BUCKET_IS_METADATA(e) ? 1 : 0);
#endif
                    continue;
                }
            }
            // Handle GETLINE mode
            if (ctx->mode == AP_MODE_GETLINE) {
                if ((ctx->need > 0) && (ctx->recv > 2)) {
                    char *end = memchr(ctx->buf, '\r', ctx->offset - 1);
                    if (end) {
#ifdef DEBUG
                        ap_log_error(APLOG_MARK, APLOG_WARNING, 0, NULL, MODULE_NAME "::helocon_filter_in DEBUG: GETLINE OK");
#endif
                        if ((end[0] == '\r') && (end[1] == '\n')) {
                            ctx->need = 0;
                        }
                    }
                }
            }
            if (ctx->need <= 0) {
#ifdef DEBUG
                ap_log_error(APLOG_MARK, APLOG_WARNING, 0, NULL, MODULE_NAME "::helocon_filter_in from: %s:%d to port=%d need=%" APR_OFF_T_FMT " recv=%" APR_OFF_T_FMT " phase=%d (4)", _CLIENT_IP, _CLIENT_ADDR->port, c->local_addr->port, ctx->need, ctx->recv, ctx->phase);
#endif
                switch (ctx->phase) {
                case PHASE_WANT_HEAD: {
#ifdef DEBUG
                    ap_log_error(APLOG_MARK, APLOG_WARNING, 0, NULL, MODULE_NAME "::helocon_filter_in from: %s:%d to port=%d phase=%d checking=%s buf=%s", _CLIENT_IP, _CLIENT_ADDR->port, c->local_addr->port, ctx->phase, "HEAD", ctx->buf);
#endif
                    // TEST Command
#ifdef DEBUG
                    ap_log_error(APLOG_MARK, APLOG_WARNING, 0, NULL, MODULE_NAME "::helocon_filter_in DEBUG: CMD=TEST CHECK");
#endif
                    if (strncmp(TEST, ctx->buf, 4) == 0) {
                        apr_socket_t *csd = ap_get_module_config(c->conn_config, &core_module);
                        apr_size_t length = strlen(TEST_RES_OK);
                        apr_socket_send(csd, TEST_RES_OK, &length);
                        apr_socket_shutdown(csd, APR_SHUTDOWN_WRITE);
                        apr_socket_close(csd);

#ifdef DEBUG
                        ap_log_error(APLOG_MARK, APLOG_WARNING, 0, NULL, MODULE_NAME "::helocon_filter_in DEBUG: CMD=TEST OK");
#endif

                        // No need to check for SUCCESS, we did that above
                        c->aborted = 1;
                        apr_brigade_cleanup(b);
                        return APR_ECONNABORTED;
                    }
                    // HELO Command
#ifdef DEBUG
                    ap_log_error(APLOG_MARK, APLOG_WARNING, 0, NULL, MODULE_NAME "::helocon_filter_in DEBUG: CMD=HELO CHECK");
#endif
                    if (strncmp(HELO, ctx->buf, 4) == 0) {
#ifdef DEBUG
                        ap_log_error(APLOG_MARK, APLOG_WARNING, 0, NULL, MODULE_NAME "::helocon_filter_in DEBUG: CMD=HELO OK");
#endif
                        ctx->phase = PHASE_WANT_BINIP;
                        ctx->mode = AP_MODE_READBYTES;
                        ctx->need = 4;
                        ctx->recv = 0;
                        break;
                    }
                    // PROXY Command
#ifdef DEBUG
                    ap_log_error(APLOG_MARK, APLOG_WARNING, 0, NULL, MODULE_NAME "::helocon_filter_in DEBUG: CMD=PROXY CHECK");
#endif
                    if (strncmp(PROXY, ctx->buf, 4) == 0) {
#ifdef DEBUG
                        ap_log_error(APLOG_MARK, APLOG_WARNING, 0, NULL, MODULE_NAME "::helocon_filter_in DEBUG: CMD=PROXY OK");
#endif
                        ctx->phase = PHASE_WANT_LINE;
                        ctx->mode = AP_MODE_GETLINE;
                        ctx->need = PROXY_MAX_LENGTH - ctx->offset;
                        ctx->recv = 0;
                        break;
                    }
                    // ELSE... GET / POST / etc
                    ctx->phase = PHASE_DONE;
#ifdef DEBUG
                    ap_log_error(APLOG_MARK, APLOG_WARNING, 0, NULL, MODULE_NAME "::helocon_filter_in DEBUG from: %s:%d to port=%d newBucket (1) size=%" APR_OFF_T_FMT, _CLIENT_IP, _CLIENT_ADDR->port, c->local_addr->port, ctx->offset);
#endif
                    // Restore original data
                    if (ctx->offset) {
                        e = apr_bucket_heap_create(ctx->buf, ctx->offset, NULL, c->bucket_alloc);
                        APR_BRIGADE_INSERT_HEAD(b, e);
                        goto END_CONN;
                    }
                    break;
                }
                case PHASE_WANT_BINIP: {
#ifdef DEBUG
                    ap_log_error(APLOG_MARK, APLOG_WARNING, 0, NULL, MODULE_NAME "::helocon_filter_in from: %s:%d to port=%d phase=%d checking=%s", _CLIENT_IP, _CLIENT_ADDR->port, c->local_addr->port, ctx->phase, "BINIP");
#endif
                    // REWRITE CLIENT IP
                    const char *new_ip = fromBinIPtoString(c->pool, ctx->buf+4);
                    if (!new_ip) {
                        ap_log_error(APLOG_MARK, APLOG_WARNING, 0, NULL, MODULE_NAME "::helocon_filter_in ERROR: HELO+IP invalid");
                        goto ABORT_CONN;
                    }

                    apr_table_set(c->notes, NOTE_REWRITE_IP, new_ip);
                    ctx->phase = PHASE_DONE;
#ifdef DEBUG
                    ap_log_error(APLOG_MARK, APLOG_WARNING, 0, NULL, MODULE_NAME "::helocon_filter_in DEBUG from: %s:%d to port=%d newip=%s", _CLIENT_IP, _CLIENT_ADDR->port, c->local_addr->port, new_ip);
#endif
                    break;
                }
                case PHASE_WANT_LINE: {
#ifdef DEBUG
                    ap_log_error(APLOG_MARK, APLOG_WARNING, 0, NULL, MODULE_NAME "::helocon_filter_in from: %s:%d to port=%d phase=%d checking=%s buf=%s", _CLIENT_IP, _CLIENT_ADDR->port, c->local_addr->port, ctx->phase, "LINE", ctx->buf);
#endif
                    ctx->phase = PHASE_DONE;
                    char *end = memchr(ctx->buf, '\r', ctx->offset - 1);
                    if (!end) {
                        goto ABORT_CONN;
                    }
                    if ((end[0] != '\r') || (end[1] != '\n')) {
                        goto ABORT_CONN;
                    }
                    if (!process_proxy_header(f)) {
                        goto ABORT_CONN;
                    }
                    // Restore original data
                    int count = (ctx->offset - ((end - ctx->buf) + 2));
#ifdef DEBUG
                    ap_log_error(APLOG_MARK, APLOG_WARNING, 0, NULL, MODULE_NAME "::helocon_filter_in DEBUG from: %s:%d to port=%d newBucket (2) size=%d rest=%s", _CLIENT_IP, _CLIENT_ADDR->port, c->local_addr->port, count, end + 2);
#endif
                    if (count > 0) {
                        e = apr_bucket_heap_create(end + 2, count, NULL, c->bucket_alloc);
                        APR_BRIGADE_INSERT_HEAD(b, e);
                        goto END_CONN;
                    }
                    break;
                }
                }
                if (ctx->phase == PHASE_DONE) {
#ifdef DEBUG
                    ap_log_error(APLOG_MARK, APLOG_WARNING, 0, NULL, MODULE_NAME "::helocon_filter_in from: %s:%d to port=%d phase=%d (DONE)", _CLIENT_IP, _CLIENT_ADDR->port, c->local_addr->port, ctx->phase);
#endif
                    ctx->mode = mode;
                    ctx->need = 0;
                    ctx->recv = 0;
                }
                break;
            }
        }
    } while (ctx->phase != PHASE_DONE);

END_CONN:
    return ap_get_brigade(f->next, b, mode, block, readbytes);

ABORT_CONN:
    ap_log_error(APLOG_MARK, APLOG_WARNING, 0, NULL, MODULE_NAME "::helocon_filter_in ERROR: PROXY protocol header invalid from=%s to port=%d", _CLIENT_IP, c->local_addr->port);
ABORT_CONN2:
    c->aborted = 1;
    apr_brigade_cleanup(b);
    return APR_ECONNABORTED;
}
static size_t CALLBACK tcp_proxy_on_message(void *plugin_private,
                                            const WebSocketServer * server,
                                            const int type,
                                            unsigned char *buffer,
                                            const size_t buffer_size)
{
    TcpProxyData *tpd = (TcpProxyData *) plugin_private;

    request_rec *r = server->request(server);

    if (tpd && tpd->tcpsocket) {
        apr_size_t len = buffer_size;
        apr_status_t rv;
        unsigned char *towrite = buffer;

        if (tpd->base64) {
            /* Unfortunately we cannot guarantee our buffer is 0 terminated, which irritatingly
             * means we have to copy it
             */
            towrite = NULL;
            unsigned char *ztbuf = calloc(1, len + 1);
            if (!ztbuf)
                goto fail;
            towrite = calloc(1, len + 1);
            if (!towrite) {
                free(ztbuf);
                goto fail;
            }
            memcpy(ztbuf, buffer, len);
            len = apr_base64_decode_binary(towrite, ztbuf);
            free(ztbuf);
            if (len <= 0) {
                free(towrite);
                towrite = NULL;
            }
          fail:
            if (!towrite) {
                APACHELOG(APLOG_DEBUG, r,
                          "tcp_proxy_on_message: apr_base64_decode_binary failed");
                tcp_proxy_shutdown_socket(tpd);
                tpd->server->close(tpd->server);
                return 0;
            }
        }

        rv = apr_socket_send(tpd->tcpsocket, towrite, &len);
        if (tpd->base64)
            free(towrite);

        if (rv != APR_SUCCESS) {
            char s[1024];
            apr_strerror(rv, s, sizeof(s));
            APACHELOG(APLOG_DEBUG, r,
                      "tcp_proxy_on_message: apr_socket_send failed, rv=%d, sent=%lu, %s",
                      rv, (unsigned long) len, s);
            tcp_proxy_shutdown_socket(tpd);
            tpd->server->close(tpd->server);
            return 0;
        }

        /*
           len = 2;
           rv = apr_socket_send(tpd->tcpsocket, "\r\n", &len);
         */
    }

    return 0;
}
// DO NOT SET 'flush' TO TRUE WHEN CALLED ON THE VIEWER SIDE!
// flush is only intended for plugin-side.
bool LLPluginMessagePipe::pumpOutput(bool flush)
{
	bool result = true;
	
	if(mSocket)
	{
		apr_interval_time_t flush_time_left_usec = flush_max_block_time;
		apr_interval_time_t timeout_usec = flush ? flush_min_timeout : 0;
		
		LLMutexLock lock(&mOutputMutex);
		while(result && !mOutput.empty())
		{
			// write any outgoing messages
			apr_size_t size = (apr_size_t)mOutput.size();
			
			setSocketTimeout(timeout_usec);
			
//			LL_INFOS("Plugin") << "before apr_socket_send, size = " << size << LL_ENDL;

			apr_status_t status = apr_socket_send(
					mSocket->getSocket(),
					(const char*)mOutput.data(),
					&size);

//			LL_INFOS("Plugin") << "after apr_socket_send, size = " << size << LL_ENDL;
			
			if(status == APR_SUCCESS)
			{
				// success
				mOutput = mOutput.substr(size);
				break;
			}
			else if(APR_STATUS_IS_EAGAIN(status) || APR_STATUS_IS_TIMEUP(status))
			{
				// Socket buffer is full... 
				// remove the written part from the buffer and try again later.
				mOutput = mOutput.substr(size);
				if (!flush)
					break;
				flush_time_left_usec -= timeout_usec;
				if (flush_time_left_usec <= 0)
				{
					result = false;
				}
				else if (size == 0)
				{
					// Nothing at all was written. Increment wait time.
					timeout_usec = llmin(flush_max_timeout, 2 * timeout_usec);
				}
				else
				{
					timeout_usec = llmax(flush_min_timeout, timeout_usec / 2);
				}
			}
			else if(APR_STATUS_IS_EOF(status))
			{
				// This is what we normally expect when a plugin exits.
				llinfos << "Got EOF from plugin socket. " << llendl;

				if(mOwner)
				{
					mOwner->socketError(status);
				}
				result = false;
			}
			else 
			{
				// some other error
				// Treat this as fatal.
				ll_apr_warn_status(status);
				
				if(mOwner)
				{
					mOwner->socketError(status);
				}
				result = false;
			}
		}
	}
	
	return result;
}
Example #10
0
int
thrasher_query(request_rec * rec, webfw2_config_t * config,
               webfw2_filter_t * filter, thrasher_pkt_type type,
               const char *srcaddr, uint32_t ident, char *reason, int sendMethod)
{
    /*
     * returns 0 if the host is allowed, 
     * returns 1 if the host has been denied,
     * returns -1 if there was an error 
     */
    int             ret;
    thrasher_pkt_t *pkt;

    pkt = NULL;
    ret = 0;
    int   urilen;
    char *uri;
    char  uribuf[4000];

    if (sendMethod) {
        uri = uribuf;
        urilen = snprintf(uribuf, sizeof(uribuf), "[%s]%s", rec->method, rec->uri);
    } else {
        uri = rec->uri;
        urilen = strlen(uri);
    }

    if (!thrasher_is_connected(filter->thrasher_sock))
        return -1;

    switch (type) {
    case TYPE_THRESHOLD_v1:
        pkt = thrasher_create_v1_pkt(rec->pool,
                                     (char *) rec->hostname,
                                     (char *) uri, inet_addr(srcaddr),
                                     strlen(rec->hostname),
                                     urilen);
        break;
    case TYPE_THRESHOLD_v2:
        pkt = thrasher_create_v2_pkt(rec->pool, inet_addr(srcaddr));
        break;
    case TYPE_THRESHOLD_v3:
        pkt = thrasher_create_v3_pkt(rec->pool,
                                     ident, (char *) rec->hostname,
                                     uri, inet_addr(srcaddr),
                                     strlen(rec->hostname),
                                     urilen);
        break;
    case TYPE_THRESHOLD_v4:
        pkt = thrasher_create_v4_pkt(rec->pool,
                                     ident, (char *) rec->hostname,
                                     uri, inet_addr(srcaddr),
                                     strlen(rec->hostname),
                                     urilen,
                                     reason, strlen(reason));
        break;
    case TYPE_THRESHOLD_v6:
        pkt = thrasher_create_v6_pkt(rec->pool,
                                     ident, (char *) rec->hostname,
                                     uri, srcaddr,
                                     strlen(rec->hostname),
                                     urilen,
                                     reason, strlen(reason));
        break;
    default:
        return -1;
    }

    if (!pkt)
        return -1;

    if (apr_socket_send(filter->thrasher_sock,
                        (const char *) pkt->packet,
                        &pkt->len) != APR_SUCCESS)
        return -1;

    return pkt->thrasher_recv_cb(pkt, filter->thrasher_sock);
}
Example #11
0
static void do_client_state_machine(const apr_pollfd_t *s,
                                    apr_pollset_t *pollset)
{
	struct per_client *c = s->client_data;
	apr_socket_t *client = s->desc.s;
	per_client_state old_state = c->state, new_state;
	apr_int16_t old_reqevents = s->reqevents, new_reqevents;
	apr_int16_t send_reqevents = APR_POLLOUT | APR_POLLHUP | APR_POLLERR;
	apr_int16_t recv_reqevents = APR_POLLIN | APR_POLLHUP | APR_POLLERR;
	byte_buffer *q = &c->query;

	switch (old_state) {
	case LM_S_INIT_CLIENT: {
		DEBUG("LM_S_INIT_CLIENT\n");
		new_state = LM_S_SEND_HI;
		new_reqevents = send_reqevents;
		c->bytes_sent = 0;
		byte_buffer_init(&c->query);
		byte_buffer_init(&c->reply);
		break;
	}
	case LM_S_SEND_HI: {
		DEBUG("LM_S_SEND_HI\n");
		apr_size_t send_sz = (sizeof LM_SERVER_HI) - c->bytes_sent;
		apr_status_t send_err;
		send_err = apr_socket_send(client, LM_SERVER_HI, &send_sz);
		if (send_err && !(APR_STATUS_IS_EAGAIN(send_err))) {
			APR_FAIL(send_err);
			new_state = LM_S_CLOSING;
			break;
		}
		c->bytes_sent += send_sz;
		if (c->bytes_sent == (sizeof LM_SERVER_HI)) {
			new_state = LM_S_GET_QUERY;
			new_reqevents = recv_reqevents;
		} else {
			new_state = LM_S_SEND_HI;
			new_reqevents = send_reqevents;
		}
		break;
	}
	case LM_S_GET_QUERY: {
		DEBUG("LM_S_GET_QUERY\n");
		apr_status_t recv_err;
		size_t bigger = q->used + 64;
		if (q->size < bigger) {
			if (byte_buffer_grow_to(&c->query, bigger)) {
				FAIL("can't grow receive buffer\n");
				new_state = LM_S_CLOSING;
				break;
			}
		}
		char *put_bytes_here = q->buf + q->used;
		apr_size_t bytes_read = q->size - q->used;
		DEBUG("put_bytes_here = %p\n", put_bytes_here);
		recv_err = apr_socket_recv(client, put_bytes_here, &bytes_read);
		DEBUG("recv %zu bytes, %d.\n", bytes_read, recv_err);
		if ((bytes_read == 0) || (APR_STATUS_IS_EOF(recv_err))) {
			if (q->used == 0) {
				DEBUG("clean disconnect :)\n");
			} else {
				DEBUG("dirty disconnect :| (%zd)\n", q->used);
			}
			new_state = LM_S_CLOSING;
			break;
		}
		if (recv_err) {
			APR_FAIL(recv_err);
			new_state = LM_S_CLOSING;
			break;
		}
		q->used += bytes_read;

		char *null_here;
	do_you_want_to_try_a_query:
		null_here = memchr(q->buf, '\x00', q->used);
		if (null_here) {
			new_state = LM_S_SEND_REPLY;
			new_reqevents = send_reqevents;
			bytes query_bytes;
			query_bytes.start = c->query.buf;
			query_bytes.end = null_here;
			if (do_client_query(c->lmdb, query_bytes, &c->reply)) {
				new_state = LM_S_CLOSING;
				break;
			}
			/* How many bytes of the buffered input did that */
			/* query occupy? Copy any leftovers back up to */
			/* the beginning of the 'query' buffer. */
			size_t q_consumed = 1 + null_here - c->query.buf;
			q->used -= q_consumed;
			if (q->used) {
				memcpy(q->buf, 1 + null_here, q->used);
			}
			c->bytes_sent = 0;
			if (c->reply.used == 0) {
				goto do_you_want_to_try_a_query;
			}
		} else {
			new_state = LM_S_GET_QUERY;
			new_reqevents = recv_reqevents;
		}
		break;
	}
	case LM_S_SEND_REPLY: {
		DEBUG("LM_S_SEND_REPLY\n");
		apr_size_t nbytes = c->reply.used - c->bytes_sent;
		char *bytes = c->reply.buf + c->bytes_sent;
		apr_status_t send_err = apr_socket_send(client, bytes, &nbytes);
		if (send_err && !(APR_STATUS_IS_EAGAIN(send_err))) {
			APR_FAIL(send_err);
			new_state = LM_S_CLOSING;
			break;
		}
		c->bytes_sent += nbytes;
		if (c->bytes_sent == c->reply.used) {
			goto do_you_want_to_try_a_query;
		} else {
			new_state = LM_S_SEND_REPLY;
			new_reqevents = send_reqevents;
		}
		break;
	}
	default: {
		FAIL("Invalid client state.\n");
		abort();
		break;
	}
	}

	if (new_state == LM_S_CLOSING) {
		apr_pollset_remove(pollset, s);
		apr_socket_close(s->desc.s);
		byte_buffer_free(&c->query);
		byte_buffer_free(&c->reply);
	} else if (old_reqevents != new_reqevents) {
		apr_pollfd_t s1;
		memset(&s1, 0, sizeof s1);
		s1.p = s->p;
		s1.client_data = s->client_data;
		s1.desc_type = s->desc_type;
		s1.desc.s = s->desc.s;
		s1.reqevents = new_reqevents;

		apr_pollset_remove(pollset, s);
		apr_pollset_add(pollset, &s1);
	}
	c->state = new_state;
}
Example #12
0
static apr_status_t sendRecvBuffer(apr_time_t *t, const char *buf, 
                                   apr_size_t size, apr_pool_t *pool)
{
    apr_socket_t *sock;
    apr_status_t rv;
    apr_size_t len = size, thistime = size;
    char *recvBuf;
    apr_time_t testStart = apr_time_now(), testEnd;
    int i;

    if (! sockAddr) {
        rv = apr_sockaddr_info_get(&sockAddr, "127.0.0.1", APR_UNSPEC,
                                   testPort, 0, pool);
        if (rv != APR_SUCCESS) {
            reportError("Unable to get socket info", rv, pool);
            return rv;
        }

        /* make sure we can connect to daemon before we try tests */

        rv = apr_socket_create(&sock, APR_INET, SOCK_STREAM, APR_PROTO_TCP,
                           pool);
        if (rv != APR_SUCCESS) {
            reportError("Unable to create IPv4 stream socket", rv, pool);
            return rv;
        }

        rv = apr_socket_connect(sock, sockAddr);
        if (rv != APR_SUCCESS) {
            reportError("Unable to connect to echod!", rv, pool);
            apr_socket_close(sock);
            return rv;
        }
        apr_socket_close(sock);

    }

    recvBuf = apr_palloc(pool, size);
    if (! recvBuf) {
        reportError("Unable to allocate buffer", ENOMEM, pool);
        return ENOMEM;
    }

    *t = 0;

    /* START! */
    testStart = apr_time_now();
    rv = apr_socket_create(&sock, APR_INET, SOCK_STREAM, APR_PROTO_TCP,
                           pool);
    if (rv != APR_SUCCESS) {
        reportError("Unable to create IPv4 stream socket", rv, pool);
        return rv;
    }

    rv = apr_socket_connect(sock, sockAddr);
    if (rv != APR_SUCCESS) {
        reportError("Unable to connect to echod!", rv, pool);
        apr_socket_close(sock);
        return rv;
    }

    for (i = 0; i < 3; i++) {

        len = size;
        thistime = size;

        rv = apr_socket_send(sock, buf, &len);
        if (rv != APR_SUCCESS || len != size) {
            reportError(apr_psprintf(pool, 
                         "Unable to send data correctly (iteration %d of 3)",
                         i) , rv, pool);
            closeConnection(sock);
            apr_socket_close(sock);
            return rv;
        }
    
        do {
            len = thistime;
            rv = apr_socket_recv(sock, &recvBuf[size - thistime], &len);
            if (rv != APR_SUCCESS) {
                reportError("Error receiving from socket", rv, pool);
                break;
            }
            thistime -= len;
        } while (thistime);
    }

    closeConnection(sock);
    apr_socket_close(sock);
    testEnd = apr_time_now();
    /* STOP! */

    if (thistime) {
        reportError("Received less than we sent :-(", rv, pool);
        return rv;
    }        
    if (strncmp(recvBuf, buf, size) != 0) {
        reportError("Received corrupt data :-(", 0, pool);
        printf("We sent:\n%s\nWe received:\n%s\n", buf, recvBuf);
        return EINVAL;
    }
    *t = testEnd - testStart;
    return APR_SUCCESS;
}
Example #13
0
static void closeConnection(apr_socket_t *sock)
{
    apr_size_t len = 0;
    apr_socket_send(sock, NULL, &len);
}
Example #14
0
int main(int argc, char *argv[])
{
    apr_pool_t *context;
    apr_socket_t *sock;
    apr_size_t length;
    apr_status_t stat;
    char datasend[STRLEN] = "Send data test";
    char datarecv[STRLEN];
    char msgbuf[80];
    char *local_ipaddr, *remote_ipaddr;
    char *dest = "127.0.0.1";
    apr_port_t local_port, remote_port;
    apr_interval_time_t timeout = apr_time_from_sec(2);
    apr_sockaddr_t *local_sa, *remote_sa;

    setbuf(stdout, NULL);
    if (argc > 1) {
        dest = argv[1];
    }

    if (argc > 2) {
        timeout = atoi(argv[2]);
    }

    fprintf(stdout, "Initializing.........");
    if (apr_initialize() != APR_SUCCESS) {
        fprintf(stderr, "Something went wrong\n");
        exit(-1);
    }
    fprintf(stdout, "OK\n");
    atexit(apr_terminate);

    fprintf(stdout, "Creating context.......");
    if (apr_pool_create(&context, NULL) != APR_SUCCESS) {
        fprintf(stderr, "Something went wrong\n");
        exit(-1);
    }
    fprintf(stdout, "OK\n");

    fprintf(stdout,"\tClient:  Making socket address...............");
    if ((stat = apr_sockaddr_info_get(&remote_sa, dest, APR_UNSPEC, 8021, 0, context)) 
        != APR_SUCCESS) {
        fprintf(stdout, "Failed!\n");
        fprintf(stdout, "Address resolution failed for %s: %s\n", 
                dest, apr_strerror(stat, msgbuf, sizeof(msgbuf)));
        exit(-1);
    }
    fprintf(stdout,"OK\n");

    fprintf(stdout, "\tClient:  Creating new socket.......");
    if (apr_socket_create(&sock, remote_sa->family, SOCK_STREAM,
                          context) != APR_SUCCESS) {
        fprintf(stderr, "Couldn't create socket\n");
        exit(-1);
    }
    fprintf(stdout, "OK\n");

    fprintf(stdout, "\tClient:  Setting socket timeout.......");
    stat = apr_socket_timeout_set(sock, timeout);
    if (stat) {
        fprintf(stderr, "Problem setting timeout: %d\n", stat);
        exit(-1);
    }
    fprintf(stdout, "OK\n");

    fprintf(stdout, "\tClient:  Connecting to socket.......");

    stat = apr_socket_connect(sock, remote_sa);

    if (stat != APR_SUCCESS) {
        apr_socket_close(sock);
        fprintf(stderr, "Could not connect: %s (%d)\n", 
		apr_strerror(stat, msgbuf, sizeof(msgbuf)), stat);
        fflush(stderr);
        exit(-1);
    }
    fprintf(stdout, "OK\n");

    apr_socket_addr_get(&remote_sa, APR_REMOTE, sock);
    apr_sockaddr_ip_get(&remote_ipaddr, remote_sa);
    apr_sockaddr_port_get(&remote_port, remote_sa);
    apr_socket_addr_get(&local_sa, APR_LOCAL, sock);
    apr_sockaddr_ip_get(&local_ipaddr, local_sa);
    apr_sockaddr_port_get(&local_port, local_sa);
    fprintf(stdout, "\tClient socket: %s:%u -> %s:%u\n", local_ipaddr, local_port, remote_ipaddr, remote_port);

    fprintf(stdout, "\tClient:  Trying to send data over socket.......");
    length = STRLEN;
    if ((stat = apr_socket_send(sock, datasend, &length) != APR_SUCCESS)) {
        apr_socket_close(sock);
        fprintf(stderr, "Problem sending data: %s (%d)\n",
		apr_strerror(stat, msgbuf, sizeof(msgbuf)), stat);
        exit(-1);
    }
    fprintf(stdout, "OK\n");
   
    length = STRLEN; 
    fprintf(stdout, "\tClient:  Trying to receive data over socket.......");

    if ((stat = apr_socket_recv(sock, datarecv, &length)) != APR_SUCCESS) {
        apr_socket_close(sock);
        fprintf(stderr, "Problem receiving data: %s (%d)\n", 
		apr_strerror(stat, msgbuf, sizeof(msgbuf)), stat);
        exit(-1);
    }
    if (strcmp(datarecv, "Recv data test")) {
        apr_socket_close(sock);
        fprintf(stderr, "I did not receive the correct data %s\n", datarecv);
        exit(-1);
    }
    fprintf(stdout, "OK\n");

    fprintf(stdout, "\tClient:  Shutting down socket.......");
    if (apr_socket_shutdown(sock, APR_SHUTDOWN_WRITE) != APR_SUCCESS) {
        apr_socket_close(sock);
        fprintf(stderr, "Could not shutdown socket\n");
        exit(-1);
    }
    fprintf(stdout, "OK\n");

    fprintf(stdout, "\tClient:  Closing down socket.......");
    if (apr_socket_close(sock) != APR_SUCCESS) {
        fprintf(stderr, "Could not shutdown socket\n");
        exit(-1);
    }
    fprintf(stdout, "OK\n");

    return 1;
}
Example #15
0
// static
bool LLMail::send(
	const std::string& header,
	const std::string& raw_message,
	const char* from_address,
	const char* to_address)
{
	if(!from_address || !to_address)
	{
		llinfos << "send_mail reject: missing to and/or from address."
			<< llendl;
		return false;
	}

	// remove any "." SMTP commands to prevent injection (DEV-35777)
	// we don't need to worry about "\r\n.\r\n" because of the 
	// "\n" --> "\n\n" conversion going into rfc2822_msg below
	std::string message = raw_message;
	std::string bad_string = "\n.\n";
	std::string good_string = "\n..\n";
	while (1)
	{
		int index = message.find(bad_string);
		if (index == std::string::npos) break;
		message.replace(index, bad_string.size(), good_string);
	}

	// convert all "\n" into "\r\n"
	std::ostringstream rfc2822_msg;
	for(U32 i = 0; i < message.size(); ++i)
	{
		switch(message[i])
		{
		case '\0':
			break;
		case '\n':
			// *NOTE: this is kinda busted if we're fed \r\n
			rfc2822_msg << "\r\n";
			break;
		default:
			rfc2822_msg << message[i];
			break;
		}
	}

	if(!gMailEnabled)
	{
		llinfos << "send_mail reject: mail system is disabled: to=<"
			<< to_address << ">, from=<" << from_address
			<< ">" << llendl;
		// Any future interface to SMTP should return this as an
		// error.  --mark
		return true;
	}
	if(!gSockAddr)
	{
		llwarns << "send_mail reject: mail system not initialized: to=<"
			<< to_address << ">, from=<" << from_address
			<< ">" << llendl;
		return false;
	}

	if(!connect_smtp())
	{
		llwarns << "send_mail reject: SMTP connect failure: to=<"
			<< to_address << ">, from=<" << from_address
			<< ">" << llendl;
		return false;
	}

	std::ostringstream smtp_fmt;
	smtp_fmt << header << rfc2822_msg.str() << "\r\n" << ".\r\n" << "QUIT\r\n";
	std::string smtp_transaction = smtp_fmt.str();
	size_t original_size = smtp_transaction.size();
	apr_size_t send_size = original_size;
	apr_status_t status = apr_socket_send(
		gMailSocket,
		smtp_transaction.c_str(),
		(apr_size_t*)&send_size);
	disconnect_smtp();
	if(ll_apr_warn_status(status))
	{
		llwarns << "send_mail socket failure: unable to write "
			<< "to=<" << to_address
			<< ">, from=<" << from_address << ">"
			<< ", bytes=" << original_size
			<< ", sent=" << send_size << llendl;
		return false;
	}
	if(send_size >= LL_MAX_KNOWN_GOOD_MAIL_SIZE)
	{
		llwarns << "send_mail message has been shown to fail in testing "
			<< "when sending messages larger than " << LL_MAX_KNOWN_GOOD_MAIL_SIZE
			<< " bytes. The next log about success is potentially a lie." << llendl;
	}
	lldebugs << "send_mail success: "
		<< "to=<" << to_address
		<< ">, from=<" << from_address << ">"
		<< ", bytes=" << original_size
		<< ", sent=" << send_size << llendl;

#if LL_LOG_ENTIRE_MAIL_MESSAGE_ON_SEND
	llinfos << rfc2822_msg.str() << llendl;
#endif
	return true;
}
Example #16
0
/* This function connects to the server, then immediately closes the connection.
 * This permits the MPM to skip the poll when there is only one listening
 * socket, because it provides a alternate way to unblock an accept() when
 * the pod is used.
 */
static apr_status_t dummy_connection(ap_pod_t *pod)
{
    char *srequest;
    apr_status_t rv;
    apr_socket_t *sock;
    apr_pool_t *p;
    apr_size_t len;

    /* create a temporary pool for the socket.  pconf stays around too long */
    rv = apr_pool_create(&p, pod->p);
    if (rv != APR_SUCCESS) {
        return rv;
    }

    rv = apr_socket_create(&sock, ap_listeners->bind_addr->family,
                           SOCK_STREAM, 0, p);
    if (rv != APR_SUCCESS) {
        ap_log_error(APLOG_MARK, APLOG_WARNING, rv, ap_server_conf,
                     "get socket to connect to listener");
        apr_pool_destroy(p);
        return rv;
    }

    /* on some platforms (e.g., FreeBSD), the kernel won't accept many
     * queued connections before it starts blocking local connects...
     * we need to keep from blocking too long and instead return an error,
     * because the MPM won't want to hold up a graceful restart for a
     * long time
     */
    rv = apr_socket_timeout_set(sock, apr_time_from_sec(3));
    if (rv != APR_SUCCESS) {
        ap_log_error(APLOG_MARK, APLOG_WARNING, rv, ap_server_conf,
                     "set timeout on socket to connect to listener");
        apr_socket_close(sock);
        apr_pool_destroy(p);
        return rv;
    }

    rv = apr_socket_connect(sock, ap_listeners->bind_addr);
    if (rv != APR_SUCCESS) {
        int log_level = APLOG_WARNING;

        if (APR_STATUS_IS_TIMEUP(rv)) {
            /* probably some server processes bailed out already and there
             * is nobody around to call accept and clear out the kernel
             * connection queue; usually this is not worth logging
             */
            log_level = APLOG_DEBUG;
        }

        ap_log_error(APLOG_MARK, log_level, rv, ap_server_conf,
                     "connect to listener on %pI", ap_listeners->bind_addr);
    }

    /* Create the request string. We include a User-Agent so that
     * adminstrators can track down the cause of the odd-looking
     * requests in their logs.
     */
    srequest = apr_pstrcat(p, "GET / HTTP/1.0\r\nUser-Agent: ",
                           ap_get_server_banner(),
                           " (internal dummy connection)\r\n\r\n", NULL);

    /* Since some operating systems support buffering of data or entire
     * requests in the kernel, we send a simple request, to make sure
     * the server pops out of a blocking accept().
     */
    /* XXX: This is HTTP specific. We should look at the Protocol for each
     * listener, and send the correct type of request to trigger any Accept
     * Filters.
     */
    len = strlen(srequest);
    apr_socket_send(sock, srequest, &len);
    apr_socket_close(sock);
    apr_pool_destroy(p);

    return rv;
}
Example #17
0
/* This function connects to the server and sends enough data to
 * ensure the child wakes up and processes a new connection.  This
 * permits the MPM to skip the poll when there is only one listening
 * socket, because it provides a alternate way to unblock an accept()
 * when the pod is used.  */
static apr_status_t dummy_connection(ap_pod_t *pod)
{
    const char *data;
    apr_status_t rv;
    apr_socket_t *sock;
    apr_pool_t *p;
    apr_size_t len;
    ap_listen_rec *lp;

    /* create a temporary pool for the socket.  pconf stays around too long */
    rv = apr_pool_create(&p, pod->p);
    if (rv != APR_SUCCESS) {
        return rv;
    }

    /* If possible, find a listener which is configured for
     * plain-HTTP, not SSL; using an SSL port would either be
     * expensive to do correctly (performing a complete SSL handshake)
     * or cause log spam by doing incorrectly (simply sending EOF). */
    lp = ap_listeners;
    while (lp && lp->protocol && strcasecmp(lp->protocol, "http") != 0) {
        lp = lp->next;
    }
    if (!lp) {
        lp = ap_listeners;
    }

    rv = apr_socket_create(&sock, lp->bind_addr->family, SOCK_STREAM, 0, p);
    if (rv != APR_SUCCESS) {
        ap_log_error(APLOG_MARK, APLOG_WARNING, rv, ap_server_conf, APLOGNO(00054)
                     "get socket to connect to listener");
        apr_pool_destroy(p);
        return rv;
    }

    /* on some platforms (e.g., FreeBSD), the kernel won't accept many
     * queued connections before it starts blocking local connects...
     * we need to keep from blocking too long and instead return an error,
     * because the MPM won't want to hold up a graceful restart for a
     * long time
     */
    rv = apr_socket_timeout_set(sock, apr_time_from_sec(3));
    if (rv != APR_SUCCESS) {
        ap_log_error(APLOG_MARK, APLOG_WARNING, rv, ap_server_conf, APLOGNO(00055)
                     "set timeout on socket to connect to listener");
        apr_socket_close(sock);
        apr_pool_destroy(p);
        return rv;
    }

    rv = apr_socket_connect(sock, lp->bind_addr);
    if (rv != APR_SUCCESS) {
        int log_level = APLOG_WARNING;

        if (APR_STATUS_IS_TIMEUP(rv)) {
            /* probably some server processes bailed out already and there
             * is nobody around to call accept and clear out the kernel
             * connection queue; usually this is not worth logging
             */
            log_level = APLOG_DEBUG;
        }

        ap_log_error(APLOG_MARK, log_level, rv, ap_server_conf, APLOGNO(00056)
                     "connect to listener on %pI", lp->bind_addr);
        apr_pool_destroy(p);
        return rv;
    }

    if (lp->protocol && strcasecmp(lp->protocol, "https") == 0) {
        /* Send a TLS 1.0 close_notify alert.  This is perhaps the
         * "least wrong" way to open and cleanly terminate an SSL
         * connection.  It should "work" without noisy error logs if
         * the server actually expects SSLv3/TLSv1.  With
         * SSLv23_server_method() OpenSSL's SSL_accept() fails
         * ungracefully on receipt of this message, since it requires
         * an 11-byte ClientHello message and this is too short. */
        static const unsigned char tls10_close_notify[7] = {
            '\x15',         /* TLSPlainText.type = Alert (21) */
            '\x03', '\x01', /* TLSPlainText.version = {3, 1} */
            '\x00', '\x02', /* TLSPlainText.length = 2 */
            '\x01',         /* Alert.level = warning (1) */
            '\x00'          /* Alert.description = close_notify (0) */
        };
        data = (const char *)tls10_close_notify;
        len = sizeof(tls10_close_notify);
    }
    else /* ... XXX other request types here? */ {
        /* Create an HTTP request string.  We include a User-Agent so
         * that adminstrators can track down the cause of the
         * odd-looking requests in their logs.  A complete request is
         * used since kernel-level filtering may require that much
         * data before returning from accept(). */
        data = apr_pstrcat(p, "OPTIONS * HTTP/1.0\r\nUser-Agent: ",
                           ap_get_server_description(),
                           " (internal dummy connection)\r\n\r\n", NULL);
        len = strlen(data);
    }

    apr_socket_send(sock, data, &len);
    apr_socket_close(sock);
    apr_pool_destroy(p);

    return rv;
}
Example #18
0
static int websync_handler(request_rec *r)
{
    apr_socket_t *sock = NULL;
    apr_sockaddr_t *sa = NULL;
    apr_status_t rv;
    char errorbuf[120];

    char *urip, *hostp;

    /* some sanitation checks */
    if (strcmp(r->handler, "websync")) {
        return DECLINED;
    }
    if (M_GET != r->method_number) {
        return HTTP_METHOD_NOT_ALLOWED;
    }

    /* move the urip past the first portion of the uri, to the start of
     * the file path to sync
     *
     * http://web1/websync/img/test.gif
     *       urip ^
     *
     * http://web1/websync/img/test.gif
     *               urip ^
     */
    urip = r->uri;
    if ('/' != *urip)
        return HTTP_INTERNAL_SERVER_ERROR;
    do {
        ++urip;
    } while ('/' != *urip && '\0' != *urip);

    /* ensure we have f= args */
    if (NULL == r->args)
        return HTTP_INTERNAL_SERVER_ERROR;

    /* move hostp to the beginning of the hostname */
    /* TODO: clean this up */
    hostp = r->args;
    if ('f' != *hostp && '=' != *(hostp+1))
        return HTTP_INTERNAL_SERVER_ERROR;
    hostp += 2;

    /* if we detect the X-Requestor: header then don't continue incase of recursive loop */
    const char *x_requestor = NULL;
    x_requestor = apr_table_get(r->headers_in, "X-Requestor");
    if (NULL != x_requestor)
        return HTTP_INTERNAL_SERVER_ERROR;

    /* some temporary debug info */
    r->content_type = "text/html";      
    ap_rprintf(r, "the uri is %s<br>", r->uri);
    ap_rprintf(r, "the args %s<br>", r->args);
    ap_rprintf(r, "the file is %s<br>", urip);
    ap_rprintf(r, "calling GET : http://%s%s<br>", hostp, urip);
    ap_rprintf(r, "document root: %s<br>", ap_document_root(r));

    /**
     * now create the return request and download the file
     *
     * Note, HTTP 1.1 must send Host: header
     */

    const char *req_hdr = apr_pstrcat(r->pool, 
                                      "GET ", urip, " ", "HTTP/1.1\r\n",
                                      "Host: ", hostp, "\r\n",
                                      "X-Requested-With: ", MODULE_VERSION, "\r\n",
                                      "\r\n",
                                      NULL);

    apr_size_t len = strlen(req_hdr);

    rv = apr_sockaddr_info_get(&sa, hostp, APR_INET, DEFAULT_HTTP_PORT, 0, r->pool);
    if (APR_SUCCESS != rv)
        return HTTP_INTERNAL_SERVER_ERROR;

    rv = apr_socket_create(&sock, APR_INET, SOCK_STREAM, APR_PROTO_TCP, r->pool);
    if (APR_SUCCESS != rv)
        return rv;

    rv = apr_socket_connect(sock, sa);
    if (APR_SUCCESS != rv)
        return HTTP_INTERNAL_SERVER_ERROR;

    rv = apr_socket_send(sock, req_hdr, &len);
    if (APR_SUCCESS != rv)
        return HTTP_INTERNAL_SERVER_ERROR;

    apr_file_t *fp;
    const char *filepath = apr_pstrcat(r->pool, ap_document_root(r), urip, NULL);

    ap_rprintf(r, "filepath %s<br>", filepath);

    rv = apr_file_open(&fp,
                       filepath,
                       APR_FOPEN_TRUNCATE | 
                       APR_FOPEN_WRITE |
                       APR_FOPEN_CREATE, 
                       APR_OS_DEFAULT, 
                       r->pool);

    if (APR_SUCCESS != rv) {
        /* TODO: attempt to create the parent dir if it's missing */
        ap_rprintf(r, "the file result %d : %s<br>", rv, (apr_strerror(rv, errorbuf, sizeof(errorbuf))));
    }
    else {

        char buf[NET_BUFSIZE];
        apr_size_t len = sizeof(buf);

        while (1) {

            rv = apr_socket_recv(sock, buf, &len);
            if (APR_EOF == rv || 0 == len)
                break;
            
            char *bufp = buf;
            int found = 0;

            /* skip the http headers ending at \r\n\r\n, TODO: find a more elegant method */
            while (!found) {
                if (*bufp == 13 && *(bufp+1) == 10 && *(bufp+2) == 13 && *(bufp+3) == 10)
                    ++found;

                ++bufp;
            }
            bufp += 3; /* adjust */
            apr_file_write(fp, bufp, &len);
        }

        apr_file_close(fp);
    }

    apr_socket_close(sock);

    return OK;
}
Example #19
0
/*
 * emulate_sendfile()
 * Sends the contents of file fd along with header/trailer bytes, if any,
 * to the network. emulate_sendfile will return only when all the bytes have been
 * sent (i.e., it handles partial writes) or on a network error condition.
 */
static apr_status_t emulate_sendfile(core_net_rec *c, apr_file_t *fd,
                                     apr_hdtr_t *hdtr, apr_off_t offset,
                                     apr_size_t length, apr_size_t *nbytes)
{
    apr_status_t rv = APR_SUCCESS;
    apr_size_t togo;        /* Remaining number of bytes in the file to send */
    apr_size_t sendlen = 0;
    apr_size_t bytes_sent;
    apr_int32_t i;
    apr_off_t o;             /* Track the file offset for partial writes */
    char buffer[8192];

    *nbytes = 0;

    /* Send the headers
     * writev_it_all handles partial writes.
     * XXX: optimization... if headers are less than MIN_WRITE_SIZE, copy
     * them into buffer
     */
    if (hdtr && hdtr->numheaders > 0 ) {
        for (i = 0; i < hdtr->numheaders; i++) {
            sendlen += hdtr->headers[i].iov_len;
        }

        rv = writev_it_all(c->client_socket, hdtr->headers, hdtr->numheaders,
                           sendlen, &bytes_sent);
        *nbytes += bytes_sent;     /* track total bytes sent */
    }

    /* Seek the file to 'offset' */
    if (offset >= 0 && rv == APR_SUCCESS) {
        rv = apr_file_seek(fd, APR_SET, &offset);
    }

    /* Send the file, making sure to handle partial writes */
    togo = length;
    while (rv == APR_SUCCESS && togo) {
        sendlen = togo > sizeof(buffer) ? sizeof(buffer) : togo;
        o = 0;
        rv = apr_file_read(fd, buffer, &sendlen);
        while (rv == APR_SUCCESS && sendlen) {
            bytes_sent = sendlen;
            rv = apr_socket_send(c->client_socket, &buffer[o], &bytes_sent);
            *nbytes += bytes_sent;
            if (rv == APR_SUCCESS) {
                sendlen -= bytes_sent; /* sendlen != bytes_sent ==> partial write */
                o += bytes_sent;       /* o is where we are in the buffer */
                togo -= bytes_sent;    /* track how much of the file we've sent */
            }
        }
    }

    /* Send the trailers
     * XXX: optimization... if it will fit, send this on the last send in the
     * loop above
     */
    sendlen = 0;
    if ( rv == APR_SUCCESS && hdtr && hdtr->numtrailers > 0 ) {
        for (i = 0; i < hdtr->numtrailers; i++) {
            sendlen += hdtr->trailers[i].iov_len;
        }
        rv = writev_it_all(c->client_socket, hdtr->trailers, hdtr->numtrailers,
                           sendlen, &bytes_sent);
        *nbytes += bytes_sent;
    }

    return rv;
}
Example #20
0
static int zevent_process_connection(conn_state_t *cs)
{
	/*
	 * code for your app,this just an example for echo test.
	 */
	apr_bucket *b;
	char *msg;
	apr_size_t len=0;
	int olen = 0;
	const char *buf;
	apr_status_t rv;

	cs->pfd->reqevents = APR_POLLIN;

	if(cs->pfd->rtnevents & APR_POLLIN){
		len = 4096;
		msg = (char *)apr_bucket_alloc(len,cs->baout);
		if (msg == NULL) {
			return -1;
		}
		rv = apr_socket_recv(cs->pfd->desc.s,msg,&len);
		if(rv != APR_SUCCESS)
		{
			zevent_log_error(APLOG_MARK,NULL,"close socket!");
			return -1;
		}

		zevent_log_error(APLOG_MARK,NULL,"recv:%s",msg);

		b = apr_bucket_heap_create(msg,len,NULL,cs->baout);
		apr_bucket_free(msg);
		APR_BRIGADE_INSERT_TAIL(cs->bbout,b);
		cs->pfd->reqevents |= APR_POLLOUT;
		
	}
	else {
		if(cs->bbout){
			for (b = APR_BRIGADE_FIRST(cs->bbout);
					b != APR_BRIGADE_SENTINEL(cs->bbout);
					b = APR_BUCKET_NEXT(b))
			{
				apr_bucket_read(b,&buf,&len,APR_BLOCK_READ);
				olen = len;
				//apr_brigade_flatten(cs->bbout,buf,&len);
				rv = apr_socket_send(cs->pfd->desc.s,buf,&len);

				if((rv == APR_SUCCESS) && (len>=olen))
				{
	//				zevent_log_error(APLOG_MARK,NULL,"send:%d bytes\n",
	//						len);
					apr_bucket_delete(b);
				}

				if((rv == APR_SUCCESS && len < olen) || 
						(rv != APR_SUCCESS))
				{
					if(rv == APR_SUCCESS){
						apr_bucket_split(b,len);
						apr_bucket *bucket = APR_BUCKET_NEXT(b);
						apr_bucket_delete(b);
						b = bucket;
					}
					break;
				}
			}
			if(b != APR_BRIGADE_SENTINEL(cs->bbout))
				cs->pfd->reqevents |= APR_POLLOUT;
		}
	}

	apr_pollset_add(cs->pollset,cs->pfd);
	return 0;
}
Example #21
0
// virtual
LLIOPipe::EStatus LLIOSocketWriter::process_impl(
	const LLChannelDescriptors& channels,
	buffer_ptr_t& buffer,
	bool& eos,
	LLSD& context,
	LLPumpIO* pump)
{
	PUMP_DEBUG;
	LLMemType m1(LLMemType::MTYPE_IO_TCP);
	if(!mDestination) return STATUS_PRECONDITION_NOT_MET;
	if(!mInitialized)
	{
		PUMP_DEBUG;
		// Since the write will not block, it's ok to initialize and
		// attempt to write immediately.
		mInitialized = true;
		if(pump)
		{
			PUMP_DEBUG;
			lldebugs << "Initializing poll descriptor for LLIOSocketWriter."
					 << llendl;
			apr_pollfd_t poll_fd;
			poll_fd.p = NULL;
			poll_fd.desc_type = APR_POLL_SOCKET;
			poll_fd.reqevents = APR_POLLOUT;
			poll_fd.rtnevents = 0x0;
			poll_fd.desc.s = mDestination->getSocket();
			poll_fd.client_data = NULL;
			pump->setConditional(this, &poll_fd);
		}
	}

	PUMP_DEBUG;
	// *FIX: Some sort of writev implementation would be much more
	// efficient - not only because writev() is better, but also
	// because we won't have to do as much work to find the start
	// address.
	LLBufferArray::segment_iterator_t it;
	LLBufferArray::segment_iterator_t end = buffer->endSegment();
	LLSegment segment;
	it = buffer->constructSegmentAfter(mLastWritten, segment);
	/*
	if(NULL == mLastWritten)
	{
		it = buffer->beginSegment();
		segment = (*it);
	}
	else
	{
		it = buffer->getSegment(mLastWritten);
		segment = (*it);
		S32 size = segment.size();
		U8* data = segment.data();
		if((data + size) == mLastWritten)
		{
			++it;
			segment = (*it);
		}
		else
		{
			// *FIX: check the math on this one
			segment = LLSegment(
				(*it).getChannelMask(),
				mLastWritten + 1,
				size - (mLastWritten - data));
		}
	}
	*/

	PUMP_DEBUG;
	apr_size_t len;
	bool done = false;
	apr_status_t status = APR_SUCCESS;
	while(it != end)
	{

		PUMP_DEBUG;
		if((*it).isOnChannel(channels.in()))
		{
			PUMP_DEBUG;
			len = (apr_size_t)segment.size();
			status = apr_socket_send(
				mDestination->getSocket(),
				(const char*)segment.data(),
				&len);
			// We sometimes get a 'non-blocking socket operation could not be 
			// completed immediately' error from apr_socket_send.  In this
			// case we break and the data will be sent the next time the chain
			// is pumped.
			if(APR_STATUS_IS_EAGAIN(status))
			{
				ll_apr_warn_status(status);
				break;
			}

			mLastWritten = segment.data() + len - 1;

			PUMP_DEBUG;
			if((S32)len < segment.size())
			{
				break;
			}
			
		}

		++it;
		if(it != end)
		{
			segment = (*it);
		}
		else
		{
			done = true;
		}

	}
	PUMP_DEBUG;
	if(done && eos)
	{
		return STATUS_DONE;
	}
	return STATUS_OK;
}
Example #22
0
/* deprecated */
apr_status_t apr_send(apr_socket_t *sock, const char *buf, apr_size_t *len)
{
    return apr_socket_send(sock, buf, len);
}
bool LLPluginMessagePipe::pump(F64 timeout)
{
	bool result = true;
	
	if(mSocket)
	{
		apr_status_t status;
		apr_size_t size;
		
		if(!mOutput.empty())
		{
			// write any outgoing messages
			size = (apr_size_t)mOutput.size();
			
			setSocketTimeout(0);
			
//			LL_INFOS("Plugin") << "before apr_socket_send, size = " << size << LL_ENDL;

			status = apr_socket_send(
					mSocket->getSocket(),
					(const char*)mOutput.data(),
					&size);

//			LL_INFOS("Plugin") << "after apr_socket_send, size = " << size << LL_ENDL;
			
			if(status == APR_SUCCESS)
			{
				// success
				mOutput = mOutput.substr(size);
			}
			else if(APR_STATUS_IS_EAGAIN(status))
			{
				// Socket buffer is full... 
				// remove the written part from the buffer and try again later.
				mOutput = mOutput.substr(size);
			}
			else 
			{
				// some other error
				// Treat this as fatal.
				ll_apr_warn_status(status);
				
				if(mOwner)
				{
					mOwner->socketError(status);
				}
				result = false;
			}
		}

		// FIXME: For some reason, the apr timeout stuff isn't working properly on windows.
		// Until such time as we figure out why, don't try to use the socket timeout -- just sleep here instead.
#if LL_WINDOWS
		if(result)
		{
			if(timeout != 0.0f)
			{
				ms_sleep((int)(timeout * 1000.0f));
				timeout = 0.0f;
			}
		}
#endif
		
		// Check for incoming messages
		if(result)
		{
			char input_buf[1024];
			apr_size_t request_size;
			
			// Start out by reading one byte, so that any data received will wake us up.
			request_size = 1;
			
			// and use the timeout so we'll sleep if no data is available.
			setSocketTimeout((apr_interval_time_t)(timeout * 1000000));

			while(1)		
			{
				size = request_size;

//				LL_INFOS("Plugin") << "before apr_socket_recv, size = " << size << LL_ENDL;

				status = apr_socket_recv(
						mSocket->getSocket(), 
						input_buf, 
						&size);

//				LL_INFOS("Plugin") << "after apr_socket_recv, size = " << size << LL_ENDL;
				
				if(size > 0)
					mInput.append(input_buf, size);

				if(status == APR_SUCCESS)
				{
//					llinfos << "success, read " << size << llendl;

					if(size != request_size)
					{
						// This was a short read, so we're done.
						break;
					}
				}
				else if(APR_STATUS_IS_TIMEUP(status))
				{
//					llinfos << "TIMEUP, read " << size << llendl;

					// Timeout was hit.  Since the initial read is 1 byte, this should never be a partial read.
					break;
				}
				else if(APR_STATUS_IS_EAGAIN(status))
				{
//					llinfos << "EAGAIN, read " << size << llendl;

					// We've been doing partial reads, and we're done now.
					break;
				}
				else
				{
					// some other error
					// Treat this as fatal.
					ll_apr_warn_status(status);

					if(mOwner)
					{
						mOwner->socketError(status);
					}
					result = false;
					break;
				}

				// Second and subsequent reads should not use the timeout
				setSocketTimeout(0);
				// and should try to fill the input buffer
				request_size = sizeof(input_buf);
			}
			
			processInput();
		}
	}

	if(!result)
	{
		// If we got an error, we're done.
		LL_INFOS("Plugin") << "Error from socket, cleaning up." << LL_ENDL;
		delete this;
	}
	
	return result;	
}
Example #24
0
static apr_status_t socket_pipe_create(apr_socket_t **rd, apr_socket_t **wr, apr_pool_t *pool)
{
	static int id = 0;

	apr_socket_t *ls = NULL;
	apr_sockaddr_t *pa = NULL;
	apr_sockaddr_t *ca = NULL;
	apr_size_t nrd;
	int uid[2];
	int iid[2];

	/* Create the unique socket identifier
	 * so that we know the connection originated
	 * from us.
	 */
	uid[0] = getpid();
	uid[1] = id++;
	if(apr_socket_create(&ls, AF_INET, SOCK_STREAM, APR_PROTO_TCP, pool) != APR_SUCCESS) {
		return apr_get_netos_error();
	}
	apr_socket_opt_set(ls, APR_SO_REUSEADDR, 1);

	if(apr_sockaddr_info_get(&pa,"127.0.0.1",APR_INET,0,0,pool) != APR_SUCCESS) {
		apr_socket_close(ls);
		return apr_get_netos_error();
	}

	if(apr_socket_bind(ls, pa) != APR_SUCCESS) {
		apr_socket_close(ls);
		return apr_get_netos_error();
	}
	
	if(apr_socket_addr_get(&ca,APR_LOCAL,ls) != APR_SUCCESS) {
		apr_socket_close(ls);
		return apr_get_netos_error();
	}

	if(apr_socket_listen(ls,1) != APR_SUCCESS) {
		apr_socket_close(ls);
		return apr_get_netos_error();
	}

	if(apr_socket_create(wr, AF_INET, SOCK_STREAM, APR_PROTO_TCP, pool) != APR_SUCCESS) {
		apr_socket_close(ls);
		return apr_get_netos_error();
	}
	apr_socket_opt_set(*wr, APR_SO_REUSEADDR, 1);

	if(apr_socket_connect(*wr, ca) != APR_SUCCESS) {
		apr_socket_close(ls);
		apr_socket_close(*wr);
		return apr_get_netos_error();
	}
	nrd = sizeof(uid);
	if(apr_socket_send(*wr, (char *)uid, &nrd) != APR_SUCCESS) {
		apr_socket_close(ls);
		apr_socket_close(*wr);
		return apr_get_netos_error();
	}
	
	apr_socket_opt_set(ls, APR_SO_NONBLOCK, 0);
	/* Listening socket is blocking by now. The accept should 
	 * return immediatelly because we connected already.
	 */
	if(apr_socket_accept(rd, ls, pool) != APR_SUCCESS) {
		apr_socket_close(ls);
		apr_socket_close(*wr);
		return apr_get_netos_error();
	}

	/* Put read side of the pipe to the blocking mode */
	apr_socket_opt_set(*rd, APR_SO_NONBLOCK, 0);

	for (;;) {
		/* Verify the connection by reading the sent identification */
		nrd = sizeof(iid);
		if(apr_socket_recv(*rd, (char *)iid, &nrd) != APR_SUCCESS) {
			apr_socket_close(ls);
			apr_socket_close(*wr);
			apr_socket_close(*rd);
			return apr_get_netos_error();
		}
		if(nrd == sizeof(iid)) {
			if(memcmp(uid, iid, sizeof(uid)) == 0) {
				/* Wow, we recived what we sent */
				break;
			}
		}
	}

	/* We don't need the listening socket any more */
	apr_socket_close(ls);
	return APR_SUCCESS;
}
Example #25
0
/* Exchange data between proxy and server */
static apr_status_t proxy_replay(serv_ctx_t *servctx,
                                 apr_int16_t rtnevents,
                                 apr_pool_t *pool)
{
    apr_status_t status;

    if (rtnevents & APR_POLLIN) {
        apr_size_t len;
        char buf[BUFSIZE];
        serf_bucket_t *tmp;

        serf__log(TEST_VERBOSE, __FILE__, "proxy_replay: POLLIN\n");
        /* Read all incoming data from the server to forward it to the
           client later. */
        do
        {
            len = BUFSIZE;

            status = apr_socket_recv(servctx->proxy_client_sock, buf, &len);
            if (SERF_BUCKET_READ_ERROR(status))
                return status;

            serf__log(TEST_VERBOSE, __FILE__,
                      "proxy: reading %d bytes %.*s from server.\n",
                      len, len, buf);
            tmp = serf_bucket_simple_copy_create(buf, len,
                                                 servctx->allocator);
            serf_bucket_aggregate_append(servctx->clientstream, tmp);
        } while (!status);
    }

    if (rtnevents & APR_POLLOUT) {
        apr_size_t len;
        char *buf;

        serf__log(TEST_VERBOSE, __FILE__, "proxy_replay: POLLOUT\n");
        /* Send all data received from the client to the server. */
        do
        {
            apr_size_t readlen;

            readlen = BUFSIZE;

            if (!servctx->servstream)
                servctx->servstream = serf__bucket_stream_create(
                                          servctx->allocator,
                                          detect_eof,servctx);
            status = serf_bucket_read(servctx->servstream, BUFSIZE,
                                      &buf, &readlen);
            if (SERF_BUCKET_READ_ERROR(status))
                return status;
            if (!readlen)
                break;

            len = readlen;

            serf__log(TEST_VERBOSE, __FILE__,
                      "proxy: sending %d bytes %.*s to server.\n",
                      len, len, buf);
            status = apr_socket_send(servctx->proxy_client_sock, buf, &len);
            if (status != APR_SUCCESS) {
                return status;
            }

            if (len != readlen) /* abort for now */
                return APR_EGENERAL;
        } while (!status);
    }
    else if (rtnevents & APR_POLLIN) {
        /* ignore */
    }
    else {
        printf("Unknown rtnevents: %d\n", rtnevents);
        abort();
    }

    return status;
}
Example #26
0
int
cluscom_query( char* host,
	       int port,
	       char* input,
	       int len_in,
	       char* output,
	       int len_out,
	       apr_pool_t* mempool )
{
	apr_socket_t* sock;
	apr_sockaddr_t* sock_addr;
	apr_sockaddr_info_get(&sock_addr, host, APR_INET, port, 0, mempool);
	apr_socket_create(&sock, sock_addr->family, SOCK_STREAM, APR_PROTO_TCP, mempool);
	apr_socket_opt_set(sock, APR_SO_NONBLOCK, 0);
	apr_socket_timeout_set(sock, DEF_SOCKET_TIMEOUT);
	apr_socket_opt_set(sock, APR_SO_REUSEADDR, 1);

	apr_status_t rv;
	char rv_words[100];
	rv = apr_socket_connect(sock, sock_addr);
	if (rv != APR_SUCCESS)
	{
#ifdef FRL_DEBUGGING
		apr_strerror(rv, rv_words, 100);
		printf("[cluscom_query]: Socket Connect Error: Code: %d - %s\n", rv, rv_words);
#endif
		apr_socket_close(sock);
		return -1;
	}
	apr_uint32_t len_in_a = len_in;
	rv = apr_socket_send(sock, input, &len_in_a);
	if ((rv == APR_SUCCESS)&&(len_in_a == len_in))
	{
		apr_uint32_t len_out_a = len_out;
		apr_socket_timeout_set(sock, DEF_PROCESS_TIMEOUT);
		rv = apr_socket_recv(sock, output, &len_out_a);
		apr_socket_close(sock);
		if ((rv != APR_SUCCESS)||(len_out_a != len_out))
		{
#ifdef FRL_DEBUGGING
			if (rv != APR_SUCCESS)
			{
				apr_strerror(rv, rv_words, 100);
				printf("[cluscom_query]: Socket Receive Error: Code: %d - %s\n", rv, rv_words);
			} else {
				printf("[cluscom_query]: Socket Receive Warning: Not Correct Size.\n");
			}
#endif
			return -1;
		}
	} else {
#ifdef FRL_DEBUGGING
		if (rv != APR_SUCCESS)
		{
			apr_strerror(rv, rv_words, 100);
			printf("[cluscom_query]: Socket Send Error: Code: %d - %s\n", rv, rv_words);
		} else {
			printf("[cluscom_query]: Socket Send Warning: Not Correct Size.\n");
		}
#endif
		apr_socket_close(sock);
		return -1;
	}
	return 0;
}
Example #27
0
int main(int argc, char *argv[])
{
    apr_pool_t *p;
    apr_socket_t *sock;
    apr_status_t rv;
    apr_sockaddr_t *remote_sa;

    apr_initialize();
    atexit(apr_terminate);
    apr_pool_create(&p, NULL);

    if (argc < 3) {
        exit(-1);
    }

    rv = apr_sockaddr_info_get(&remote_sa, argv[2], APR_UNSPEC, 8021, 0, p);
    if (rv != APR_SUCCESS) {
        exit(-1);
    }

    if (apr_socket_create(&sock, remote_sa->family, SOCK_STREAM, 0,
                p) != APR_SUCCESS) {
        exit(-1);
    }

    rv = apr_socket_timeout_set(sock, apr_time_from_sec(3));
    if (rv) {
        exit(-1);
    }

    apr_socket_connect(sock, remote_sa);
        
    if (!strcmp("read", argv[1])) {
        char datarecv[STRLEN];
        apr_size_t length = STRLEN;
        apr_status_t rv;

        memset(datarecv, 0, STRLEN);
        rv = apr_socket_recv(sock, datarecv, &length);
        apr_socket_close(sock);
        if (APR_STATUS_IS_TIMEUP(rv)) {
            exit(SOCKET_TIMEOUT); 
        }

        if (strcmp(datarecv, DATASTR)) {
            exit(-1);
        }
        
        exit((int)length);
    }
    else if (!strcmp("write", argv[1])
             || !strcmp("write_after_delay", argv[1])) {
        apr_size_t length = strlen(DATASTR);

        if (!strcmp("write_after_delay", argv[1])) {
            apr_sleep(apr_time_from_sec(2));
        }

        apr_socket_send(sock, DATASTR, &length);

        apr_socket_close(sock);
        exit((int)length);
    }
    else if (!strcmp("close", argv[1])) {
        apr_socket_close(sock);
        exit(0);
    }
    exit(-1);
}
Example #28
0
static apr_status_t replay(test_baton_t *tb,
                           apr_pool_t *pool)
{
    apr_status_t status = APR_SUCCESS;
    test_server_action_t *action;

    if (tb->cur_action >= tb->action_count) {
        char buf[128];
        apr_size_t len = sizeof(buf);

        status = apr_socket_recv(tb->client_sock, buf, &len);
        if (! APR_STATUS_IS_EAGAIN(status)) {
            /* we're out of actions! */
            printf("Received more requests than expected\n");

            return APR_EGENERAL;
        }

        return status;
    }

    if (tb->action_list == NULL)
    {
        /* we're not expecting any requests to reach this server! */
        printf("Received request where none was expected\n");

        return APR_EGENERAL;
    }

    action = &tb->action_list[tb->cur_action];

    if (action->kind == SERVER_RECV)
    {
        apr_size_t msg_len, len;
        char buf[128];

        msg_len = strlen(action->text);

        len = msg_len - tb->action_buf_pos;
        if (len > sizeof(buf))
            len = sizeof(buf);

        status = apr_socket_recv(tb->client_sock, buf, &len);
        if (status != APR_SUCCESS)
            return status;

        if (tb->options & TEST_SERVER_DUMP)
            fwrite(buf, len, 1, stdout);

        if (strncmp(buf, action->text + tb->action_buf_pos, len) != 0) {
            /* ## TODO: Better diagnostics. */
            printf("Expected: (\n");
            fwrite(action->text + tb->action_buf_pos, len, 1, stdout);
            printf(")\n");
            printf("Actual: (\n");
            fwrite(buf, len, 1, stdout);
            printf(")\n");

            return APR_EGENERAL;
        }

        tb->action_buf_pos += len;

        if (tb->action_buf_pos >= msg_len)
            next_action(tb);
    }
    else if (action->kind == SERVER_SEND) {
        apr_size_t msg_len;
        apr_size_t len;

        msg_len = strlen(action->text);
        len = msg_len - tb->action_buf_pos;

        status = apr_socket_send(tb->client_sock,
                                 action->text + tb->action_buf_pos, &len);
        if (status != APR_SUCCESS)
            return status;

        if (tb->options & TEST_SERVER_DUMP)
            fwrite(action->text + tb->action_buf_pos, len, 1, stdout);

        tb->action_buf_pos += len;

        if (tb->action_buf_pos >= msg_len)
            next_action(tb);
    }
    else if (action->kind == SERVER_KILL_CONNECTION) {
        apr_socket_close(tb->client_sock);
        tb->client_sock = NULL;
        next_action(tb);
    }
    else {
        abort();
    }

    return status;
}