Пример #1
0
/*
** 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;
}
Пример #3
0
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;
}
Пример #4
0
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;
}