/* ** Setup a new buffer. Never fails. */ FDBUF * fd_create(int fd, int flags) { FDBUF *fdp; A_NEW(fdp); pthread_mutex_init(&fdp->refcnt_lock, NULL); fdp->refcnt = 1; fdp->flags = flags; fdp->fd = fd; pthread_mutex_init(&fdp->in_lock, NULL); fdp->ungetc = -1; fdp->in_start = 0; fdp->in_end = 0; fdp->inbufsize = FDBUF_INBUFSIZE; fdp->inbuf = a_malloc(fdp->inbufsize, "FDBUF inbuf"); pthread_mutex_init(&fdp->out_lock, NULL); fdp->lastc = -1; fdp->outbuflen = 0; fdp->outbufsize = FDBUF_OUTBUFSIZE; fdp->outbuf = a_malloc(fdp->outbufsize, "FDBUF outbuf"); return fdp; }
/* * \brief Allocate memory from our buffer, storing it in a memory nugget */ void *CNotAmnesia::Allocate( size_t numBytes, const char* file, int line ) { MemoryNugget *newNugget = nullptr; // see if we can re-use a free nugget if (m_freeNugget != nullptr) { newNugget = MergeMemoryNuggets(numBytes); if (newNugget != nullptr) { #ifndef OPTIMIZED CheckForBufferOverflow(newNugget); memset(newNugget->ptr, 0x00000000, newNugget->totalSize); #endif return newNugget->ptr; } } // tried to allocate more than what we have if (m_totalSize - m_amountAllocated < numBytes) { return nullptr; } if (newNugget == nullptr) { // no free nuggets available, so create a new one newNugget = A_NEW(MemoryNugget); if (newNugget == nullptr) return nullptr; newNugget->ptr = m_nextFreePtr; newNugget->totalSize = numBytes; m_nextFreePtr += newNugget->totalSize; m_amountAllocated += newNugget->totalSize; } #ifndef OPTIMIZED newNugget->file = file; newNugget->line = line; #endif PushNuggetToAllocatedList(newNugget); #ifndef OPTIMIZED CheckForBufferOverflow(newNugget); memset(newNugget->ptr, 0x00000000, newNugget->totalSize); #endif return newNugget->ptr; }
SERVER * server_init(int fd, const struct sockaddr_gen *sg, int backlog, int max_clients, void (*handler)(CLIENT *cp)) { static int one = 1; socklen_t slen; SERVER *sp; if (debug) fprintf(stderr, "server_init(%d, ..., %d, %d, ...): Start\n", fd, backlog, max_clients); A_NEW(sp); sp->fd = -1; sp->state = 0; pthread_attr_init(&sp->ca_detached); pthread_attr_setdetachstate(&sp->ca_detached, PTHREAD_CREATE_DETACHED); pthread_mutex_init(&sp->clients_mtx, NULL); pthread_cond_init(&sp->clients_cv, NULL); sp->clients_cur = 0; sp->clients_max = max_clients; if (fd < 0) { if (sg == NULL) { syslog(LOG_ERR, "server_init: NULL address and no file descriptor"); server_destroy(sp); if (debug) fprintf(stderr, "server_init(): End: Failure\n"); return NULL; } sp->sin = *sg; sp->fd = socket(SGFAM(sp->sin), SOCK_STREAM, 0); #ifdef HAVE_IPV6 if (sp->fd < 0 && (errno == EAFNOSUPPORT || errno == EPFNOSUPPORT) && SGFAM(sp->sin) == AF_INET6) { #if 0 /* Try to convert to IPv4 format... */ struct in6_addr *addr6 = (struct in6_addr *) SGADDRP(sp->sin); if (IN6_IS_ADDR_V4MAPPED(addr6)) { UINT32 addr4 = addr6->s6_addr32[3]; SGFAM(sp->sin) = AF_INET; * (UINT32 *) SGADDRP(sp->sin) = addr4; } #endif /* Let's try with an IPv4 socket - who knows, it might work */ errno = 0; sp->fd = socket(PF_INET, SOCK_STREAM, 0); } #endif if (sp->fd < 0) { syslog(LOG_ERR, "socket(%s, SOCK_STREAM) failed (errno=%d): %m", (SGFAM(sp->sin) == AF_INET ? "AF_INET" : "AF_INET6"), errno); server_destroy(sp); if (debug) fprintf(stderr, "server_init(): End: Failure\n"); return NULL; } (void) setsockopt(sp->fd, SOL_SOCKET, SO_REUSEADDR, (void *) &one, sizeof(one)); if (s_bind(sp->fd, (struct sockaddr *) &sp->sin, SGSOCKSIZE(sp->sin)) < 0) { char buf1[16]; syslog(LOG_ERR, "bind(%d,%s:%d) failed: %m", sp->fd, s_inet_ntox(&sp->sin, buf1, sizeof(buf1)), ntohs(SGPORT(sp->sin))); server_destroy(sp); if (debug) fprintf(stderr, "server_init(): End: Failure\n"); return NULL; } } else { sp->fd = fd; slen = sizeof(sp->sin); getsockname(sp->fd, (struct sockaddr *) &sp->sin, &slen); } /* We do this outside the 'if' clause to support broken Inetd implementations */ if (backlog >= 0 && listen(sp->fd, backlog) < 0) { syslog(LOG_ERR, "listen(%d, %d) failed: %m", sp->fd, backlog); server_destroy(sp); if (debug) fprintf(stderr, "server_init(): End: Failure\n"); return NULL; } sp->handler = handler; if (debug) fprintf(stderr, "server_init(): End: OK\n"); return sp; }
int server_run_one(SERVER *sp, int client_fd, int nofork) { CLIENT *cp; pthread_t tid; #ifndef HAVE_THREADS pid_t pid; int status; #endif int ecode; socklen_t slen; pthread_mutex_lock(&sp->clients_mtx); sp->clients_cur++; if (debug) fprintf(stderr, "server_run_one: Number of clients is now: %d\n", sp->clients_cur); pthread_mutex_unlock(&sp->clients_mtx); if (debug) fprintf(stderr, "server_run_one(..., %d, %d): Start\n", client_fd, nofork); A_NEW(cp); cp->fd = client_fd; cp->sp = sp; slen = sizeof(cp->rsin); if (getpeername(cp->fd, (struct sockaddr *) &cp->rsin, &slen) < 0) { syslog(LOG_ERR, "getpeername(%d): %m", cp->fd); if (debug) fprintf(stderr, "server_run_one(...): End: FAILURE\n"); return EXIT_FAILURE; } slen = sizeof(cp->lsin); if (getsockname(cp->fd, (struct sockaddr *) &cp->lsin, &slen) < 0) { syslog(LOG_ERR, "getsockname(%d): %m", cp->fd); if (debug) fprintf(stderr, "server_run_one(...): End: FAILURE\n"); return EXIT_FAILURE; } if (nofork) { (void) client_thread(cp); if (debug) fprintf(stderr, "server_run_one(...): End: OK\n"); return EXIT_SUCCESS; } else { #ifdef HAVE_THREADS ecode = pthread_create(&tid, &sp->ca_detached, client_thread, (void *) cp); if (ecode) { syslog(LOG_ERR, "pthread_create(client_thread) failed: %s", strerror(ecode)); if (debug) fprintf(stderr, "server_run_one(...): End: FAILURE\n"); return EXIT_FAILURE; } #else /* Try to reap the status of as many subprocesses as possible */ /* ** XXX: This will break if we are using multiple ** SERVER's in a single process and aren't using ** threads. */ while (sp->clients_cur > 0 && (pid = waitpid((pid_t) -1, &status, WNOHANG)) > 0) { if (WIFEXITED(status) || WIFSIGNALED(status)) { sp->clients_cur--; } } if (sp->clients_max > 0) { /* Wait for atleast one slot to be available */ while (sp->clients_cur >= sp->clients_max && (pid = waitpid((pid_t) -1, &status, 0)) > 0) { if (WIFEXITED(status) || WIFSIGNALED(status)) { sp->clients_cur--; } } } while ((status = fork()) < 0 && errno == EAGAIN) { /* Fork failed - too many processes */ sleep(1); pid = waitpid((pid_t) -1, &status, (sp->clients_cur > 0) ? 0 : WNOHANG); if (pid > 0 && (WIFEXITED(status) || WIFSIGNALED(status))) { sp->clients_cur--; } } if (status < 0) { syslog(LOG_ERR, "fork() failed: %m"); s_abort(); } if (status == 0) { /* In child process */ (void) client_thread(cp); _exit(EXIT_SUCCESS); } sp->clients_cur++; s_close(cp->fd); a_free(cp); #endif } if (debug) fprintf(stderr, "server_run_one(...): End: OK\n"); return EXIT_SUCCESS; }
/* * \brief Allocate memory from our buffer, aligned to a given alignment, storing it in a memory nugget */ void *CNotAmnesia::AllocateAligned( size_t numBytes, size_t alignment, const char* file, int line ) { size_t alignOffset = alignment - (reinterpret_cast<size_t>(m_nextFreePtr) % alignment); // if the pointer isn't already aligned, make a padded nugget, // to push the address to an aligned value. Put the padded nugget // on to the list of free nuggets if (alignOffset != alignment) { MemoryNugget *const paddingNugget = A_NEW(MemoryNugget); if (paddingNugget == nullptr) return nullptr; paddingNugget->ptr = m_nextFreePtr; paddingNugget->totalSize = alignOffset; m_nextFreePtr += paddingNugget->totalSize; m_amountAllocated += paddingNugget->totalSize; #ifndef OPTIMIZED paddingNugget->file = file; paddingNugget->line = line; #endif if (m_freeNugget == nullptr) { #ifndef OPTIMIZED m_noofFreeNuggets++; #endif m_freeNugget = paddingNugget; m_freeNugget->nextNugget = nullptr; m_freeNugget->prevNugget = nullptr; } else { #ifndef OPTIMIZED m_noofFreeNuggets++; #endif m_freeNugget->nextNugget = paddingNugget; paddingNugget->prevNugget = m_freeNugget; paddingNugget->nextNugget = nullptr; m_freeNugget = paddingNugget; } } // The memory address should now be aligned to the given alignment MemoryNugget *const newNugget = A_NEW(MemoryNugget); if (newNugget == nullptr) return nullptr; newNugget->ptr = m_nextFreePtr; newNugget->totalSize = numBytes; m_nextFreePtr += newNugget->totalSize; m_amountAllocated += newNugget->totalSize; #ifndef OPTIMIZED newNugget->file = file; newNugget->line = line; #endif PushNuggetToAllocatedList(newNugget); #ifndef OPTIMIZED CheckForBufferOverflow(newNugget); memset(newNugget->ptr, 0x00000000, newNugget->totalSize); #endif return newNugget->ptr; }