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; }
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); }
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; }
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; }
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); }
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; }
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; }
static void closeConnection(apr_socket_t *sock) { apr_size_t len = 0; apr_socket_send(sock, NULL, &len); }
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; }
// 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; }
/* 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; }
/* 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; }
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; }
/* * 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; }
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; }
// 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; }
/* 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; }
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; }
/* 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; }
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; }
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); }
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; }