static int sendResponse(Session *sn, Request *rq, HTTPResponse *resp) { pb_param *pb_entry; /* * collect up the headers */ pb_entry = pblock_remove(CONTENT_TYPE,rq->srvhdrs); /* remove default */ param_free(pb_entry); /* aB. Need to free parameters we remove from pblocks !!! */ st_perform(resp->headers,gethdr,rq); /* * ensure a content length */ if (pblock_findval(CONTENT_LENGTH, rq->srvhdrs) == NULL) { char length[64]; util_itoa(resp->content_length,length); pblock_nvinsert(CONTENT_LENGTH,length, rq->srvhdrs); } protocol_status(sn, rq, resp->status, resp->statusMsg); if (protocol_start_response(sn, rq) == REQ_NOACTION) { WOLog(WO_ERR,"protocol_start_response() returned REQ_NOACTION (!?)"); return REQ_PROCEED; } if (resp->content_length) if (net_write(sn->csd, resp->content, resp->content_length) == IO_ERROR) { WOLog(WO_ERR,"Failed to send content to client"); return REQ_EXIT; } return REQ_PROCEED; }
HTTPResponse *resp_getResponseHeaders(WOConnection *instanceConnection, WOInstanceHandle instHandle) { HTTPResponse *resp; String *response; /* * get the status */ response = transport->recvline(instanceConnection->fd); if (!response) return NULL; WOLog(WO_INFO,"New response: %s", response->text); resp = resp_new(response->text, instHandle, instanceConnection); str_free(response); if (resp == NULL) return NULL; /* * followed by the headers... */ while ((response = transport->recvline(instanceConnection->fd)) != NULL) { if (response->length == 0) break; WOLog(WO_DBG,"Header read: %s", response->text); // mstoll 13.10.2005 debug output added resp_addHeader(resp, response); } if((resp->flags & RESP_LENGTH_EXPLICIT) != RESP_LENGTH_EXPLICIT) { if((resp->flags & RESP_CONTENT_TYPE_SET) != RESP_CONTENT_TYPE_SET) { // no content type: no body, so content-length is implicit 0 resp->content_length = 0; } else { // 2009/06/10: no content-length defined. To be able to process the // request although, we set the maximum allowed value and close // the client socket communication if the end-of-response- // stream was reached. The maximum allowed value is UINT_MAX, // because resp->content_length is defined as "unsigned". // But the function used to convert a content-length string // returns an int and assignments like // int value = resp->content_length; // can be found in the adaptor source code. Therefore, we // should better use INT_MAX! resp->content_length = INT_MAX; WOLog(WO_WARN, "Response doesn't specify a content-length: assuming %u bytes!", resp->content_length); } } if (response) str_free(response); else { /* recvline() must have failed */ resp_free(resp); WOLog(WO_ERR, "Error receiving headers - response dropped"); return NULL; } return resp; }
/* * Writes len bytes of zeros at the end of the open file fd. * Returns the number of bytes actually written. If this is * less than len, an error occurred (which was logged). * In general the size written may be larger than what was requested. */ static int append_zeros(int fd, int len) { /* write zeros to initialize */ int buff[1024], result, ret = 0; char *errMsg = NULL; memset(buff, 0, sizeof(buff)); while (len > 0 && !errMsg) { if (lseek(WOShmem_fd, 0, SEEK_END) == -1) { errMsg = WA_errorDescription(WA_error()); WOLog(WO_ERR, "append_zeros: lseek() failed: %s", errMsg); } if (!errMsg) { result = write(WOShmem_fd, buff, sizeof(buff)); if (result == -1) { errMsg = WA_errorDescription(WA_error()); WOLog(WO_ERR, "append_zeros: write() failed: %s", errMsg); } else { len -= result; ret += result; } } } if (errMsg) WA_freeErrorDescription(errMsg); return ret; }
void *sha_checkout(ShmemArray *array, unsigned int elementNumber) { void *element; if (elementNumber < array->elementCount) { /* read locks block if a write is pending */ #ifdef EXTRA_DEBUGGING_LOGS WOLog(WO_DBG, "sha_checkout(): about to check out %s element %d", array->name, elementNumber); #endif WA_lock(array->elements[elementNumber].writeLock); WA_lock(array->elements[elementNumber].lock); WA_unlock(array->elements[elementNumber].writeLock); element = array->elements[elementNumber].element; /* if this was the first read lock by this process, obtain a file lock on the data as well */ if (array->elements[elementNumber].lockCount == 0) array->elements[elementNumber].lockHandle = WOShmem_lock(element, array->elementSize, 0); array->elements[elementNumber].lockCount++; WA_unlock(array->elements[elementNumber].lock); #ifdef EXTRA_DEBUGGING_LOGS WOLog(WO_DBG, "sha_checkout(): checked out %s element %d", array->name, elementNumber); #endif } else { element = NULL; WOLog(WO_ERR, "sha_checkout(): failed to check out %s element %d", array->name, elementNumber); } return element; }
inline static int lock_file_section(int fd, off_t start, off_t len, struct flock *lockInfo, int exclusive) { int err, errCount = 0; do { lockInfo->l_start = start; lockInfo->l_len = len; lockInfo->l_type = exclusive ? F_WRLCK : F_RDLCK; lockInfo->l_whence = SEEK_SET; if (fcntl(WOShmem_fd, F_SETLKW, lockInfo) == -1) { err = WA_error(); errCount++; if (err != EAGAIN || errCount % 10 == 0) { char *errMsg = WA_errorDescription(err); WOLog(WO_ERR, "lock_file_section(): failed to lock (%d attempts): %s", errCount, errMsg); WA_freeErrorDescription(errMsg); } if (err == EAGAIN) { WA_yield(); if (errCount > LOCK_RETRY_SLEEP_COUNT) sleep(1); if (errCount > LOCK_RETRY_FAIL_COUNT) { WOLog(WO_ERR, "lock_file_section(): could not aquire lock after %d attempts. Giving up.", LOCK_RETRY_FAIL_COUNT); } } } else err = 0; } while (err == EAGAIN && errCount < LOCK_RETRY_FAIL_COUNT); return err; }
static TR_STATUS sendbytes(net_fd appfd, const char *buf, int len) { int remaining, sent, n; int s = appfd->s; struct timeval tv; fd_set wset; TR_STATUS ret = TR_OK; if (appfd->status != TR_OK) return TR_ERROR; remaining = len; while (remaining > 0 && ret == TR_OK) { while((sent = send(s, (void *)buf, remaining, 0)) < 0 && ret == TR_OK) { int ec = WA_error(); if (WA_wouldBlock(ec)) { FD_ZERO(&wset); FD_SET(s, &wset); tv.tv_sec = appfd->send_to; tv.tv_usec = 0; n = select(s + 1, NULL, &wset, NULL, &tv); if (n == 0) { /* Timed out */ WOLog(WO_DBG, "sendbytes(): timed out"); ret = TR_TIMEOUT; break; } else if (n < 0) { char *errMsg = WA_errorDescription(WA_error()); WOLog(WO_ERR, "sendbytes(): select error: %s", errMsg); WA_freeErrorDescription(errMsg); ret = TR_ERROR; break; } /* Drop back into the while loop and retry the send() */ } else if (WA_intr(ec)) { /* Try send again */ } else if (WA_brokenPipe(ec)) { ret = TR_RESET; } else { /* If we get EPIPE or any other error, bail out. */ char *errMsg = WA_errorDescription(WA_error()); WOLog(WO_ERR, "sendbytes(): send error: %s", errMsg); WA_freeErrorDescription(errMsg); ret = TR_ERROR; break; } } /* if we get here with sent < 0, we have a failure */ if (ret != TR_OK && ret != TR_RESET) { WOLog(WO_ERR,"sendbytes(): failed to send data to app"); } else { remaining -= sent; buf += sent; } } return ret; }
int req_sendRequest(HTTPRequest *req, net_fd socket) { struct iovec *buffers, *bufferIterator; int bufferCount, result; buffers = WOMALLOC((st_count(req->headers) * 4 + 3) * sizeof(struct iovec)); buffers[0].iov_base = req->request_str; buffers[0].iov_len = strlen(req->request_str); bufferIterator = &buffers[1]; st_perform(req->headers, (st_perform_callback)setupIOVec, &bufferIterator); bufferIterator->iov_base = "\r\n"; bufferIterator->iov_len = 2; bufferCount = st_count(req->headers) * 4 + 2; if (req->content_length > 0) { bufferCount++; bufferIterator++; bufferIterator->iov_base = req->content; bufferIterator->iov_len = req->content_buffer_size; } result = transport->sendBuffers(socket, buffers, bufferCount); /* If we are streaming the content data, continue until we have sent everything. */ /* Note that we reuse buffers, and the existing content-data buffer. */ if (req->content_length > req->content_buffer_size) { long total_sent = req->content_buffer_size; long len_read, amount_to_read; req->haveReadStreamedData = 1; while (total_sent < req->content_length && result == 0) { amount_to_read = req->content_length - total_sent; if (amount_to_read > req->content_buffer_size) amount_to_read = req->content_buffer_size; len_read = req->getMoreContent(req, req->content, amount_to_read, 0); if (len_read > 0) { buffers[0].iov_base = req->content; buffers[0].iov_len = len_read; result = transport->sendBuffers(socket, buffers, 1); total_sent += len_read; } else if (len_read < 0) { WOLog(WO_ERR, "Failed to read streamed content."); result = -1; } } } WOFREE(buffers); if (result == 0) result = transport->flush_connection(socket); else WOLog(WO_ERR, "error sending request"); return result; }
/* * The entry point for the parser. * Returns nonzero if there was an error during parsing. */ static int xml_parseConfiguration(char *buf, int len) { XMLCDocumentHandler handler; WOXMLEdits config; XMLCParser *parser; int error = 0, i; /* initialize the config struct */ config.current_element = NULL; config.new_apps = wolist_new(16); config.current_app = NULL; config.current_app_instances = NULL; config.current_instance = NULL; config.new_app_instances = wolist_new(16); config.error = 0; config.errorLocation = buf; if (len == 0) return 1; /* no content is considered an error */ /* Set up a new document handler struct for the parser */ memcpy(&handler, &_document, sizeof(XMLCDocumentHandler)); handler.document = (XMLCDocument *)(&config); /* set up and invoke the xml parser */ parser = xmlcParserInit(); xmlcTokenizerSetBuffer(parser->tokenizer, buf, len); xmlcParserSetPreserveWhiteSpace(parser, 0); error = (int)xmlcParserParse(parser, &handler); if (error != 0) { /* config error */ WOLog(WO_ERR,"Error parsing configuration: %s", xmlcParserErrorDescription(error)); if ((intptr_t)config.errorLocation < (intptr_t)buf + len) { char *badconfig = WOMALLOC((len+1)*sizeof(char)); strncpy(badconfig, buf, len); badconfig[len] = '\0'; WOLog(WO_ERR,"Error near:\n%s", config.errorLocation); WOFREE(badconfig); } } else { /* * load the new settings... */ if (config.new_apps) for (i=0; i<wolist_count(config.new_apps); i++) ac_updateApplication((strtbl *)wolist_elementAt(config.new_apps, i), (list *)wolist_elementAt(config.new_app_instances, i)); } /* clean up and return */ freeWOXMLEdits(&config); xmlcParserDealloc(parser); return error; }
static void copyHeaderForServerVariable(char *var, EXTENSION_CONTROL_BLOCK *p, HTTPRequest *req) { char *buf, *value, stackBuf[2048]; DWORD bufsz = sizeof(stackBuf), pos; WOLog(WO_DBG, "reading buffer for server variable %s", var); if (p->GetServerVariable(p->ConnID, var, stackBuf, &bufsz) == TRUE) { buf = stackBuf; } else { if(GetLastError() == 122) // ERROR_INSUFFICIENT_BUFFER { WOLog(WO_DBG, "buffer too small; need %d", bufsz); buf = WOMALLOC(bufsz); if (p->GetServerVariable(p->ConnID, var, buf, &bufsz) != TRUE) { WOFREE(buf); WOLog(WO_ERR, "Could not get header."); return; } } else return; // header not set } if (buf) { //WOLog(WO_DBG, "got raw buffer: %s", buf); pos = 0; while (pos < bufsz) { while (pos < bufsz && buf[pos] < 33) pos++; if (pos < bufsz) { /* got start of new value */ value = &buf[pos]; do { while (pos < bufsz && buf[pos] != '\r') pos++; if (pos + 2 < bufsz && buf[pos+1] == '\n' && (buf[pos+2] == ' ' || buf[pos+2] == '\t')) { /* got a multiline header; change CRLF to whitespace and keep parsing */ buf[pos] = ' '; buf[pos+1] = ' '; } else { buf[pos] = 0; } } while (pos < bufsz && buf[pos] != 0); WOLog(WO_DBG, "found value=\"%s\"", value ? value : "(NULL)"); if (value) req_addHeader(req, var, value, STR_COPYKEY|STR_COPYVALUE); else req_addHeader(req, var, "", STR_COPYKEY); } } if (buf != stackBuf) WOFREE(buf); } return; }
static int nonBlockingConnectHostent(int sd, int connectTimeout, struct hostent *hostentry, unsigned int port) { int n, rc; fd_set wset; struct timeval tval; struct sockaddr_in connect_addr; int connect_addr_len; rc = 0; if (hostentry) { connect_addr.sin_family = AF_INET; connect_addr.sin_port = htons((unsigned short)port); memcpy(&connect_addr.sin_addr, hostentry->h_addr_list[0], hostentry->h_length); connect_addr_len = sizeof(struct sockaddr_in); /* Since we're non-blocking, we expect an EINPROGRESS error. */ if ((n = connect(sd, (struct sockaddr *)&connect_addr, connect_addr_len)) < 0) { int ec = WA_error(); /* Note that on Windows, connect returns WSAEWOULDBLOCK, not WSAEINPROGRESS. */ if (!WA_inProgress(ec) && !WA_wouldBlock(ec)) { char *errMsg = WA_errorDescription(ec); WOLog(WO_ERR, "WOSocket: connect error in NB connect: %s", errMsg); WA_freeErrorDescription(errMsg); return -1; } } /* If n = 0, we connected immediately (e.g. client = host). */ if (n) { FD_ZERO(&wset); FD_SET(sd, &wset); tval.tv_sec = connectTimeout; tval.tv_usec = 0; if ((n = select(sd + 1, NULL, &wset, NULL, &tval)) < 0) { WOLog(WO_DBG, "WOSocket: select failed"); return -1; } if (n == 0) { /* timed out */ WOLog(WO_DBG, "WOSocket: connect timeout in NB connect"); return -2; } } } else { WOLog(WO_ERR, "WOSocket: hostent NULL - unknown host?"); rc = -1; } return rc; }
void resp_addHeader(HTTPResponse *resp, String *rawhdr) { char *key, *value; /* keep track of the String */ resp_addStringToResponse(resp, rawhdr); /* * break into key/value, make key lowercase * Note that this walks over the String's buffer, but * at this point the response owns the String so that's ok. * The String buffer will get reclaimed when responseStrings * is freed, in resp_free(). */ for (key = rawhdr->text, value = key; *value != ':'; value++) { if(*value == '\0') // mstoll 13.10.2005 check added { WOLog(WO_ERR,"Header without ':': %s", rawhdr->text); break; } if (isupper((int)*value)) *value = tolower((int)*value); /* ... and change to lowercase. */ } if (*value == ':') { *value++ = '\0'; /* terminate key string */ while (*value && isspace((int)*value)) value++; } else { return; /* Zounds ! something wrong with header... */ } st_add(resp->headers, key, value, 0); /* * scan inline for content-length */ if ((resp->content_length == 0) && ((strcasecmp(CONTENT_LENGTH,key) == 0) || strcasecmp("content_length", key) == 0)) { // 2009/06/10: an explicit content-length value is available. // Update response flag information: resp->flags |= RESP_LENGTH_EXPLICIT; resp->content_length = atoi(value); WOLog(WO_INFO,"content-length was set expl.: %d", resp->content_length); } if (((strcasecmp(CONTENT_TYPE,key) == 0) || strcasecmp("content_type", key) == 0)) { // 2011/11/16: an explicit content-type value is available. // Update response flag information: resp->flags |= RESP_CONTENT_TYPE_SET; } return; }
static void sig_handler(int signum) { switch (signum) { case SIGUSR1 : should_terminate = 1; WOLog(WO_INFO,"<FastCGI> Signal %s caught", strsignal(signum)); break; case SIGPIPE : WOLog(WO_WARN,"<FastCGI> Signal %s caught", strsignal(signum)); break; case SIGTERM : WOLog(WO_ERR,"<FastCGI> Signal %s caught", strsignal(signum)); exit(-1); default: WOLog( WO_INFO,"<FastCGI> Signal %s caught", strsignal(signum)); } }
/* * Called from the xml parser. * Here is where we begin parsing <application>... or <instance>... * or <adaptor>... */ static void createElement(XMLCDocument *document, const XMLCCharacter *name, const unsigned int length) { WOXMLEdits *config = (WOXMLEdits *)document; if (config->error != 0) /* would be nice to tell parser to stop */ return; config->errorLocation = name; if (length == 7 && strncasecmp(name, "adaptor", length) == 0) { /* do nothing; don't generate a warning */ } else if (length == 11 && strncasecmp(name, "application", length) == 0) { /* begin <application> */ if (config->current_element != NULL) { WOLog(WO_ERR,"Error parsing config: found unexpected <application> tag"); config->error = 1; return; } /* create new app settings dictionary, instance list, and set current_element to the app dictionary*/ config->current_app = st_new(8); wolist_add(config->new_apps, config->current_app); config->current_app_instances = wolist_new(8); wolist_add(config->new_app_instances, config->current_app_instances); config->current_element = config->current_app; } else if (length == 8 && strncasecmp(name, "instance", length) == 0) { /* begin <instance> */ if (config->current_element != config->current_app || config->current_app == NULL) { WOLog(WO_ERR,"Error parsing config: found unexpected <instance> tag"); config->error = 1; return; } /* create new instance settings dictionary and set current_element to point to it */ config->current_instance = st_new(8); wolist_add(config->current_app_instances, config->current_instance); config->current_element = config->current_instance; } else { /* Got something unexpected. Ignore the tag. */ char *buffer = WOMALLOC(length+1); strncpy(buffer,name,length); buffer[length] = '\0'; WOLog(WO_WARN,"Unknown tag in XML: \"%s\"",buffer); config->current_element = NULL; WOFREE(buffer); } return; }
/* Returns the number of bytes read, or -1 on error. */ static int readContentData(HTTPRequest *req, void *buffer, int dataSize, int mustFill) { WOLog (WO_INFO, "data size: %d", dataSize ); //int n = fread(buffer, 1, dataSize, stdin); int n = FCGX_GetStr(buffer, dataSize, in); if (n != dataSize) { //int err = ferror(stdin); int err = FCGX_GetError(in); if (err) WOLog(WO_ERR,"Error getting content data: %s (%d)", strerror(errno), err); } /* *((char*)buffer+dataSize) = '\0'; WOLog ( WO_INFO, "buffer: %s", (char *)buffer );*/ return n == dataSize ? n : -1; }
static DWORD die(EXTENSION_CONTROL_BLOCK *p, const char *msg, int status) { HTTPResponse *resp; WOLog(WO_ERR,"Sending aborting request - %s",msg); resp = resp_errorResponse(msg, status); return die_resp(p, resp); }
void st_add(strtbl *st, const char *key, const char *value, int flags) { strtblelem *kv; kv = st_newKV(st); if (kv != NULL) { st->count++; kv->flags = flags; if (flags & STR_COPYKEY) { kv->key = WOSTRDUP(key); kv->flags |= STR_FREEKEY; } else kv->key = key; if (flags & STR_COPYVALUE) { kv->value = WOSTRDUP(value); kv->flags |= STR_FREEVALUE; } else kv->value = value; } else WOLog(WO_ERR, "st_add(): no space to add element: %s = %s", key, value); return; }
const char *documentRoot() { static char path[MAXPATHLEN+1] = ""; if (path[0] == '\0') { #ifdef WIN32 WOReadKeyFromConfiguration(CGI_DOCUMENT_ROOT, path, MAXPATHLEN); #else const char *doc_root; /* Apache provides this as an environment variable straight */ if ((doc_root = FCGX_GetParam(CGI_DOCUMENT_ROOT, hdrp)) != NULL) { strncpy(path, doc_root, MAXPATHLEN); } else { const char *path_trans, *path_info; path_trans = FCGX_GetParam(PATH_TRANSLATED, hdrp); path_info = FCGX_GetParam(CGI_PATH_INFO, hdrp); if (path_trans && path_info) { char *e = strstr(path_trans,path_info); if (e) { strncpy(path,path_trans,e-path_trans); } } } #endif } if (path[0] != '\0') return path; else { WOLog(WO_ERR,"<FastCGI> Can't find document root in CGI variables"); return "/usr/local/apache/htdocs"; /* this is bad.... */ } }
void *sd_add(strdict *sd, const char *key, void *value) { strdictel *kv; void *oldValue; oldValue = sd_removeKey(sd, key); if (value != NULL) { if (sd->count == sd->capacity) { kv = findNull(sd); /* try to recycle space */ if (kv == NULL) { sd_setCapacity(sd, sd->capacity * 2); /* make more space */ if (sd->count == sd->capacity) { WOLog(WO_ERR, "sd_add(): could not add element (%s = %s) due to allocation failure", key, value); return oldValue; } else { kv = sd->head + sd->count; sd->count++; } } } else { kv = sd->head + sd->count; sd->count++; } kv->key = WOSTRDUP(key); kv->value = value; } return oldValue; }
HTTPResponse *resp_new(char *statusStr, WOInstanceHandle instHandle, WOConnection *instanceConnection) { HTTPResponse *resp; char *status = statusStr; /* * reformat the status line from * "HTTP/1.0 200 OK Apple WebObjects" to "OK Apple..." */ while (status && *status && !isspace((int)*status)) status++; while (*status && !isdigit((int)*status)) status++; if ( !(status && *status) ) { WOLog(WO_ERR,"Invalid response!"); return NULL; } resp = WOCALLOC(1,sizeof(HTTPResponse)); resp->status = atoi(status); resp->statusMsg = (char *)apple; if (strncmp(statusStr, "HTTP/1.", 7) == 0) { if (statusStr[7] == '0') resp->flags |= RESP_HTTP10; else if (statusStr[7] == '1') resp->flags |= RESP_HTTP11; } resp->headers = st_new(10); resp->instanceConnection = instanceConnection; resp->instHandle = instHandle; return resp; }
static HTTPResponse *_errorResponse(WOAppReq *app, WOURLComponents *wc, HTTPRequest *req) { HTTPResponse *resp; const char *redirect_url = &app->redirect_url[0]; WOLog(WO_ERR,"Request handling error: %s",_errors[app->error]); if (app->redirect_url[0] == 0) redirect_url = adaptor_valueForKey(WOERRREDIR); /* * try to do the right thing... */ if (redirect_url != NULL) { resp = resp_redirectedResponse(redirect_url); } else if (app->error == err_notFound) { if (ac_authorizeAppListing(wc)) resp = WOAdaptorInfo(NULL, wc); else { resp = resp_errorResponse(NOT_FOUND_APP, HTTP_NOT_FOUND); if (resp->statusMsg) WOFREE(resp->statusMsg); resp->statusMsg = WOSTRDUP("File Not Found"); } } else resp = resp_errorResponse(_errors[app->error], HTTP_SERVER_ERROR); if (resp) { st_add(resp->headers, "Cache-Control", "no-cache, private, no-store, must-revalidate, max-age=0", 0); st_add(resp->headers, "Expires", "Thu, 01 Jan 1970 00:00:00 GMT", 0); st_add(resp->headers, "date", "Thu, 01 Jan 1970 00:00:00 GMT", 0); st_add(resp->headers, "pragma", "no-cache", 0); } return resp; }
/* * common routing to add header called by both addHeader() */ inline static const char *req_AddHeader_common(HTTPRequest *req,const char *key,const char *value) { const char *customKey; const char *hdrkey; customKey = customHeaderFor(key); hdrkey = (customKey != NULL) ? customKey : key; if (req->headers == NULL) req->headers = st_new(HEADER_CNT); /* * we inspect the headers in line here to grab the content length */ if ((req->content_length == 0) && ((strcasecmp(key, CONTENT_LENGTH) == 0) || (strcasecmp(key, "content_length") == 0))) /* get content-length */ req->content_length = atol(value); #ifdef DEBUG WOLog(WO_DBG,"(req-hdr) %s: %s",key, value); #endif return hdrkey; }
/* * Ensure that the open file fd is at least size bytes long. * Expands the file as needed using append_zeros(). File locking * is used to ensure no data is overwritten. * Returns the actual size of the file on success, -1 on error. */ static int ensure_file_size(int fd, size_t size) { struct stat st; struct flock lockInfo; char *errMsg = NULL; int error = 0; if (fstat(WOShmem_fd, &st)) { errMsg = WA_errorDescription(WA_error()); WOLog(WO_ERR, "ensure_file_size(): initial fstat() failed: %s", errMsg); error = 1; } if (!error && st.st_size < size) { if (lock_file_section(WOShmem_fd, st.st_size, size - st.st_size, &lockInfo, 1)) { error = 1; } else { /* someone else may have just changed the size, so repeat the stat */ if (fstat(WOShmem_fd, &st)) { errMsg = WA_errorDescription(WA_error()); WOLog(WO_ERR, "ensure_file_size(): second fstat() failed: %s", errMsg); WA_freeErrorDescription(errMsg); error = 1; } if (!error && st.st_size < size) { st.st_size += append_zeros(WOShmem_fd, size - st.st_size); if (st.st_size < size) error = 1; } lockInfo.l_type = F_UNLCK; if (fcntl(WOShmem_fd, F_SETLK, &lockInfo) == -1) { errMsg = WA_errorDescription(WA_error()); WOLog(WO_ERR, "ensure_file_size(): failed to unlock: %s", errMsg); WA_freeErrorDescription(errMsg); error = 1; } } } return error ? -1 : st.st_size; }
/* * here's where we end application/instance/error parsing */ static void endElementNamed(XMLCDocument *document, const XMLCCharacter *name, const unsigned int length) { WOXMLEdits *config = (WOXMLEdits *)document; if (config->error != 0) /* would be nice to tell parser to stop */ return; if (length == 7 && strncasecmp(name, "adaptor", 7) == 0) { /* do nothing; don't generate a warning */ } else if (length == 11 && strncasecmp(name, "application", 11) == 0) { if (config->current_element != config->current_app) { WOLog(WO_ERR,"Error parsing config: </application> found at top level or with open <instance> tag"); config->error = 1; return; } config->current_element = NULL; config->current_app = NULL; config->current_app_instances = NULL; } else if (length == 8 && strncasecmp(name, "instance", 8) == 0) { if (config->current_element != config->current_instance) { WOLog(WO_ERR,"Error parsing config: unexpected </instance>"); config->error = 1; return; } config->current_element = config->current_app; config->current_instance = NULL; } else if (length == 7 && strncasecmp(name, "adaptor", 7) == 0) { config->current_element = NULL; } else { #ifdef _MSC_VER // SWK VC can't allocate dynamic char buffer[length + 1] char *buffer = (char *)alloca((length+1) * sizeof(char)); #else char buffer[length+1]; #endif strncpy(buffer,name,length); buffer[length] = '\0'; WOLog(WO_WARN,"Unknown end tag in XML: %s",buffer); if (config->current_element != NULL) /* only an error if we were parsing something we know about */ config->error = 1; } return; }
void sha_unlock(ShmemArray *array, unsigned int elementNumber) { if (elementNumber < array->elementCount) { #ifdef EXTRA_DEBUGGING_LOGS WOLog(WO_DBG, "sha_unlock(): about to unlock %s element %d", array->name, elementNumber); #endif WA_lock(array->elements[elementNumber].lock); /* release the file lock on the data */ WOShmem_unlock(array->elements[elementNumber].lockHandle); array->elements[elementNumber].lockHandle = NULL; WA_unlock(array->elements[elementNumber].lock); WA_unlock(array->elements[elementNumber].writeLock); #ifdef EXTRA_DEBUGGING_LOGS WOLog(WO_DBG, "sha_unlock(): unlocked %s element %d", array->name, elementNumber); #endif } }
void WA_lock(WA_recursiveLock _lock) #endif { WinRecursiveLock *lock = (WinRecursiveLock *)_lock; #ifdef EXTRA_DEBUGGING_LOGS if (_lock != logMutex) WOLog(WO_DBG, "locking %s from %s:%d", lock->name, file, line); #endif WaitForSingleObject(lock->lock, INFINITE); }
void WA_unlock(WA_recursiveLock _lock) #endif { WinRecursiveLock *lock = (WinRecursiveLock *)_lock; #ifdef EXTRA_DEBUGGING_LOGS if (_lock != logMutex) WOLog(WO_DBG, "unlocking %s from %s:%d", lock->name, file, line); #endif ReleaseMutex(lock->lock); }
static TR_STATUS reset(net_fd appfd) { int result, warned = 0, n; struct timeval tv; fd_set wset; if (appfd->status != TR_OK) return TR_ERROR; /* drain any data from the socket */ do { result = nonBlockingRecv(appfd, 0, appfd->buf, NETBUFSZ); if (result > 0 && warned == 0) { WOLog(WO_WARN, "reset(): leftover data in socket buffer"); warned = 1; } if (result == -1 && appfd->status == TR_TIMEOUT) appfd->status = TR_OK; } while (result > 0); /* clear our buffer */ if (appfd->status == TR_OK) { if (appfd->count != 0) WOLog(WO_WARN, "reset(): leftover data in buffer"); appfd->count = 0; appfd->pos = appfd->buf; FD_ZERO(&wset); FD_SET(appfd->s, &wset); tv.tv_sec = 0; tv.tv_usec = 0; n = select(appfd->s + 1, NULL, &wset, NULL, &tv); if (n != 1) { WOLog(WO_WARN, "reset(): connection dropped"); appfd->status = TR_RESET; } } return appfd->status; }
void sha_checkin(ShmemArray *array, unsigned int elementNumber) { if (elementNumber < array->elementCount) { #ifdef EXTRA_DEBUGGING_LOGS WOLog(WO_DBG, "sha_checkin(): about to check in %s element %d", array->name, elementNumber); #endif WA_lock(array->elements[elementNumber].lock); array->elements[elementNumber].lockCount--; /* if this was the last read lock by this process, release the file lock on the data as well */ if (array->elements[elementNumber].lockCount == 0) { WOShmem_unlock(array->elements[elementNumber].lockHandle); array->elements[elementNumber].lockHandle = NULL; } WA_unlock(array->elements[elementNumber].lock); #ifdef EXTRA_DEBUGGING_LOGS WOLog(WO_DBG, "sha_checkin(): checked in %s element %d", array->name, elementNumber); #endif } }
static void sendResponse(EXTENSION_CONTROL_BLOCK *p, HTTPResponse *resp) { String *resphdrs; char status[128]; DWORD len; p->dwHttpStatusCode = resp->status; sprintf(status, "%d %s",resp->status, resp->statusMsg); /* * send the headers (collected into one buffer) */ resphdrs = resp_packageHeaders(resp); if (resphdrs) { len = resphdrs->length; /* ccording to the Microsoft web site, HSE_REQ_SEND_RESPONSE_HEADER is depreciated */ /* HSE_REQ_SEND_RESPONSE_HEADER_EX is preferred. */ /* However, moving to HSE_REQ_SEND_RESPONSE_HEADER_EX will not work if we must support IIS 3.0. */ if (p->ServerSupportFunction(p->ConnID, HSE_REQ_SEND_RESPONSE_HEADER, status, &len, (LPDWORD)resphdrs->text) != TRUE) { WOLog(WO_ERR,"Failed to send response headers (%d)", GetLastError()); } else { len = 2; if (p->WriteClient(p->ConnID, CRLF, &len, 0) != TRUE) WOLog(WO_ERR,"Failed to send \\r\\n (%d)", GetLastError()); /* * send the content data */ len = resp->content_length; if (len && (p->WriteClient(p->ConnID, resp->content, &len, 0) != TRUE)) WOLog(WO_ERR,"Failed to send content (%d)", GetLastError()); } str_free(resphdrs); } /* else? return warning */ return; }
void *sha_lock(ShmemArray *array, unsigned int elementNumber) { void *element; if (elementNumber < array->elementCount) { #ifdef EXTRA_DEBUGGING_LOGS WOLog(WO_DBG, "sha_lock(): about to lock %s element %d", array->name, elementNumber); #endif /* block read lock requests */ WA_lock(array->elements[elementNumber].writeLock); WA_lock(array->elements[elementNumber].lock); int maxTry = 10000; while (array->elements[elementNumber].lockCount > 0 && maxTry-- > 0) { WA_unlock(array->elements[elementNumber].lock); WA_yield(); WA_lock(array->elements[elementNumber].lock); } if(array->elements[elementNumber].lockCount <= 0) { element = array->elements[elementNumber].element; array->elements[elementNumber].lockHandle = WOShmem_lock(element, array->elementSize, 1); WA_unlock(array->elements[elementNumber].lock); #ifdef EXTRA_DEBUGGING_LOGS WOLog(WO_DBG, "sha_lock(): locked %s element %d", array->name, elementNumber); #endif } else { WA_unlock(array->elements[elementNumber].lock); WA_unlock(array->elements[elementNumber].writeLock); element = NULL; WOLog(WO_ERR, "sha_lock(): element already locked: %s / %d", array->name, elementNumber); } } else { element = NULL; WOLog(WO_ERR, "sha_lock(): failed to lock %s element %d", array->name, elementNumber); } return element; }