Exemplo n.º 1
0
// construct tree nodes for an sexp, adding them to the list and returning first node
int sexp_event_tree::load_sub_tree(int index)
{
	int cur;

	if (index < 0) {
		cur = allocate_node(-1);
		set_node(cur, SEXPT_OPERATOR, "do-nothing");  // setup a default tree if none
		return cur;
	}

	// assumption: first token is an operator.  I require this because it would cause problems
	// with child/parent relations otherwise, and it should be this way anyway, since the
	// return type of the whole sexp is boolean, and only operators can satisfy this.
	Assert(Sexp_nodes[index].subtype == SEXP_ATOM_OPERATOR);
	cur = get_new_node_position();
	load_branch(index, -1);
	return cur;
}
Exemplo n.º 2
0
/*
 * shallow copy of a sorted_btree object
 */
static bt_node_t *
copy_node(bt_node_t *node, int depth, int leaf_depth, int order) {
    int i;
    bt_node_t *result = allocate_node(depth < leaf_depth, order);

    for (i = 0; i < node->filled; ++i) {
        result->values[i] = node->values[i];
        Py_INCREF(node->values[i]);
    }
    result->filled = node->filled;

    if (depth < leaf_depth)
        for (i = 0; i <= node->filled; ++i) {
            ((bt_branch_t *)result)->children[i] = copy_node(
                ((bt_branch_t *)node)->children[i], depth + 1, leaf_depth, order);
        }

    return result;
}
Exemplo n.º 3
0
/* Family of Universal hashing function, for null terminated strings
 * it takes in a link list of parameters, where
 * the first is the table size
 * the second is coefficient_b randomly chosen from [0, RAND()]
 * and the third and onward are coefficient_a each randomly chosen from [0, RAND()]
 * where RAND() returns a value from  [0, RAND_MAX]
 * RAND_MAX is system dependent, if integer is 32 bits it should 2147483647 or 0x7fffffff largest positive integer.
 * all have to be less than MAX_PRIME.
 * note that we need as many coefficient_a as the length of the string
 * shorter strings simply are interpret as being padded by 0s so the hash values aren't affected when we increment the list.
 *
 * The function using python notation.
 * hash(string) = (sum( (char_value * coefficient_as[index]) % MAX_PRIME
 *                          for index, char_value in enumerate(string)
 *                    ) + coefficient_b) % table_size
 */
word_type universal_hash_function(char_type *char_value, hash_function_parameters_type *hash_func_parameter)
{
    word_type max_value = table_size(hash_func_parameter),
              sum       = coefficient_b(hash_func_parameter);

    hash_func_parameter = initial_coefficient_a(hash_func_parameter);
    char_value--; /* subtract the pointer by one so every time we begin at the loop we just need increment and check it */
                  /* note that ++ is applied on the pointer. */
    while (*++char_value) /* while we haven't read the null character, '\0'. */
    {
        if (!next_parameter(hash_func_parameter)) /* if we need a new coefficient_a add it */
        {
            set_next_parameter(hash_func_parameter, allocate_node());
            set_coefficient_a(next_parameter(hash_func_parameter), (((word_type)rand()) % MAX_PRIME));
        }
        sum += (coefficient_a(hash_func_parameter) * ((word_type) *char_value)) % MAX_PRIME;

        hash_func_parameter = next_parameter(hash_func_parameter); /* move to next parameter. */
    }

    return (sum % max_value);
}
Exemplo n.º 4
0
void init_root (int length)
// Initialize the root node of the suffix tree.
{
	// Give root node unique (no edge) attributes
	root = (struct node*) malloc (sizeof(struct node));
	root -> id = 0;
	root -> sfxnum = -1;
	root -> strdepth = 0;
	root -> starti = -1;
	root -> endi = -1;

	// suffix link of root is itself.
	root -> sfxlink = root;

	// Initialize the first child of root with suffix corresponding to the
	// entire input string.
	allocate_node (&(root -> leftchild), 0, 0, length, root);

	// Root has no sibs or parent.
	root -> rightsib = NULL;
	root -> parent = NULL;
}
Exemplo n.º 5
0
static int
sorted_btree_object_init(PyObject *self, PyObject *args, PyObject *kwargs) {
    PyObject *order;
    btsort_pyobject *tree = (btsort_pyobject *)self;

    tree->flags = 0;

    if (!PyArg_ParseTupleAndKeywords(
                args, kwargs, "O!", btree_init_args, &PyInt_Type, &order))
        return -1;

    tree->order = (int)PyInt_AsLong(order);
    tree->depth = 0;
    tree->root = allocate_node(0, tree->order);
    tree->flags |= BT_FLAG_INITED;

    if (tree->order < 2) {
        PyErr_SetString(PyExc_ValueError, "btree order must be >1");
        return -1;
    }

    return 0;
}
Exemplo n.º 6
0
void qInsert(queueObj_t *qObj, void *data)
{
	if (!qObj || !data) {	
		return;
	}
	
	Q_LOCK(&qObj->qMutex);

	NODE *node = allocate_node(data);

	if (!qObj->qHead) {
		qObj->qHead = qObj->qTail = node;
		++qObj->qCount;

	} else {

		qObj->qTail->next = node;
		node->prev = qObj->qTail;
		qObj->qTail = node;
		++qObj->qCount;
	}			

	Q_UNLOCK(&qObj->qMutex);
}
Exemplo n.º 7
0
/*
 * Reads one entry in directory at position pointed by iterator and fills
 * node structure.
 */
static int readdir(struct exfat* ef, const struct exfat_node* parent,
		struct exfat_node** node, struct iterator* it)
{
	int rc = -EIO;
	const struct exfat_entry* entry;
	const struct exfat_entry_meta1* meta1;
	const struct exfat_entry_meta2* meta2;
	const struct exfat_entry_name* file_name;
	const struct exfat_entry_upcase* upcase;
	const struct exfat_entry_bitmap* bitmap;
	const struct exfat_entry_label* label;
	uint8_t continuations = 0;
	le16_t* namep = NULL;
	uint16_t reference_checksum = 0;
	uint16_t actual_checksum = 0;
	uint64_t real_size = 0;

	*node = NULL;

	for (;;)
	{
		if (it->offset >= parent->size)
		{
			if (continuations != 0)
			{
				exfat_error("expected %hhu continuations", continuations);
				goto error;
			}
			return -ENOENT; /* that's OK, means end of directory */
		}

		entry = get_entry_ptr(ef, it);
		switch (entry->type)
		{
		case EXFAT_ENTRY_FILE:
			if (continuations != 0)
			{
				exfat_error("expected %hhu continuations before new entry",
						continuations);
				goto error;
			}
			meta1 = (const struct exfat_entry_meta1*) entry;
			continuations = meta1->continuations;
			/* each file entry must have at least 2 continuations:
			   info and name */
			if (continuations < 2)
			{
				exfat_error("too few continuations (%hhu)", continuations);
				goto error;
			}
			if (continuations > 1 +
					DIV_ROUND_UP(EXFAT_NAME_MAX, EXFAT_ENAME_MAX))
			{
				exfat_error("too many continuations (%hhu)", continuations);
				goto error;
			}
			reference_checksum = le16_to_cpu(meta1->checksum);
			actual_checksum = exfat_start_checksum(meta1);
			*node = allocate_node();
			if (*node == NULL)
			{
				rc = -ENOMEM;
				goto error;
			}
			/* new node has zero reference counter */
			(*node)->entry_cluster = it->cluster;
			(*node)->entry_offset = it->offset;
			init_node_meta1(*node, meta1);
			namep = (*node)->name;
			break;

		case EXFAT_ENTRY_FILE_INFO:
			if (continuations < 2)
			{
				exfat_error("unexpected continuation (%hhu)",
						continuations);
				goto error;
			}
			meta2 = (const struct exfat_entry_meta2*) entry;
			if (meta2->flags & ~(EXFAT_FLAG_ALWAYS1 | EXFAT_FLAG_CONTIGUOUS))
			{
				exfat_error("unknown flags in meta2 (0x%hhx)", meta2->flags);
				goto error;
			}
			init_node_meta2(*node, meta2);
			actual_checksum = exfat_add_checksum(entry, actual_checksum);
			real_size = le64_to_cpu(meta2->real_size);
			/* empty files must be marked as non-contiguous */
			if ((*node)->size == 0 && (meta2->flags & EXFAT_FLAG_CONTIGUOUS))
			{
				exfat_error("empty file marked as contiguous (0x%hhx)",
						meta2->flags);
				goto error;
			}
			/* directories must be aligned on at cluster boundary */
			if (((*node)->flags & EXFAT_ATTRIB_DIR) &&
				(*node)->size % CLUSTER_SIZE(*ef->sb) != 0)
			{
				exfat_error("directory has invalid size %"PRIu64" bytes",
						(*node)->size);
				goto error;
			}
			--continuations;
			break;

		case EXFAT_ENTRY_FILE_NAME:
			if (continuations == 0)
			{
				exfat_error("unexpected continuation");
				goto error;
			}
			file_name = (const struct exfat_entry_name*) entry;
			actual_checksum = exfat_add_checksum(entry, actual_checksum);

			memcpy(namep, file_name->name,
					MIN(EXFAT_ENAME_MAX,
						((*node)->name + EXFAT_NAME_MAX - namep)) *
					sizeof(le16_t));
			namep += EXFAT_ENAME_MAX;
			if (--continuations == 0)
			{
				/*
				   There are two fields that contain file size. Maybe they
				   plan to add compression support in the future and one of
				   those fields is visible (uncompressed) size and the other
				   is real (compressed) size. Anyway, currently it looks like
				   exFAT does not support compression and both fields must be
				   equal.

				   There is an exception though: pagefile.sys (its real_size
				   is always 0).
				*/
				if (real_size != (*node)->size)
				{
					char buffer[UTF8_BYTES(EXFAT_NAME_MAX) + 1];

					exfat_get_name(*node, buffer, sizeof(buffer) - 1);
					exfat_error("`%s' real size does not equal to size "
							"(%"PRIu64" != %"PRIu64")", buffer,
							real_size, (*node)->size);
					goto error;
				}
				if (actual_checksum != reference_checksum)
				{
					char buffer[UTF8_BYTES(EXFAT_NAME_MAX) + 1];

					exfat_get_name(*node, buffer, sizeof(buffer) - 1);
					exfat_error("`%s' has invalid checksum (0x%hx != 0x%hx)",
							buffer, actual_checksum, reference_checksum);
					goto error;
				}
				if (fetch_next_entry(ef, parent, it) != 0)
					goto error;
				return 0; /* entry completed */
			}
			break;

		case EXFAT_ENTRY_UPCASE:
			if (ef->upcase != NULL)
				break;
			upcase = (const struct exfat_entry_upcase*) entry;
			if (CLUSTER_INVALID(le32_to_cpu(upcase->start_cluster)))
			{
				exfat_error("invalid cluster 0x%x in upcase table",
						le32_to_cpu(upcase->start_cluster));
				goto error;
			}
			if (le64_to_cpu(upcase->size) == 0 ||
				le64_to_cpu(upcase->size) > 0xffff * sizeof(uint16_t) ||
				le64_to_cpu(upcase->size) % sizeof(uint16_t) != 0)
			{
				exfat_error("bad upcase table size (%"PRIu64" bytes)",
						le64_to_cpu(upcase->size));
				goto error;
			}
			ef->upcase = malloc(le64_to_cpu(upcase->size));
			if (ef->upcase == NULL)
			{
				exfat_error("failed to allocate upcase table (%"PRIu64" bytes)",
						le64_to_cpu(upcase->size));
				rc = -ENOMEM;
				goto error;
			}
			ef->upcase_chars = le64_to_cpu(upcase->size) / sizeof(le16_t);

			if (exfat_pread(ef->dev, ef->upcase, le64_to_cpu(upcase->size),
					exfat_c2o(ef, le32_to_cpu(upcase->start_cluster))) < 0)
			{
				exfat_error("failed to read upper case table "
						"(%"PRIu64" bytes starting at cluster %#x)",
						le64_to_cpu(upcase->size),
						le32_to_cpu(upcase->start_cluster));
				goto error;
			}
			break;

		case EXFAT_ENTRY_BITMAP:
			bitmap = (const struct exfat_entry_bitmap*) entry;
			ef->cmap.start_cluster = le32_to_cpu(bitmap->start_cluster);
			if (CLUSTER_INVALID(ef->cmap.start_cluster))
			{
				exfat_error("invalid cluster 0x%x in clusters bitmap",
						ef->cmap.start_cluster);
				goto error;
			}
			ef->cmap.size = le32_to_cpu(ef->sb->cluster_count) -
				EXFAT_FIRST_DATA_CLUSTER;
			if (le64_to_cpu(bitmap->size) < DIV_ROUND_UP(ef->cmap.size, 8))
			{
				exfat_error("invalid clusters bitmap size: %"PRIu64
						" (expected at least %u)",
						le64_to_cpu(bitmap->size),
						DIV_ROUND_UP(ef->cmap.size, 8));
				goto error;
			}
			/* FIXME bitmap can be rather big, up to 512 MB */
			ef->cmap.chunk_size = ef->cmap.size;
			ef->cmap.chunk = malloc(BMAP_SIZE(ef->cmap.chunk_size));
			if (ef->cmap.chunk == NULL)
			{
				exfat_error("failed to allocate clusters bitmap chunk "
						"(%"PRIu64" bytes)", le64_to_cpu(bitmap->size));
				rc = -ENOMEM;
				goto error;
			}

			if (exfat_pread(ef->dev, ef->cmap.chunk,
					BMAP_SIZE(ef->cmap.chunk_size),
					exfat_c2o(ef, ef->cmap.start_cluster)) < 0)
			{
				exfat_error("failed to read clusters bitmap "
						"(%"PRIu64" bytes starting at cluster %#x)",
						le64_to_cpu(bitmap->size), ef->cmap.start_cluster);
				goto error;
			}
			break;

		case EXFAT_ENTRY_LABEL:
			label = (const struct exfat_entry_label*) entry;
			if (label->length > EXFAT_ENAME_MAX)
			{
				exfat_error("too long label (%hhu chars)", label->length);
				goto error;
			}
			if (utf16_to_utf8(ef->label, label->name,
						sizeof(ef->label) - 1, EXFAT_ENAME_MAX) != 0)
				goto error;
			break;

		default:
			if (entry->type & EXFAT_ENTRY_VALID)
			{
				exfat_error("unknown entry type 0x%hhx", entry->type);
				goto error;
			}
			break;
		}

		if (fetch_next_entry(ef, parent, it) != 0)
			goto error;
	}
	/* we never reach here */

error:
	free(*node);
	*node = NULL;
	return rc;
}
Exemplo n.º 8
0
/*
 * loading a sorted list into a new btree
 */
static int
load_generation(PyObject **items, int item_count, bt_node_t **children,
        int order, char is_branch, bt_node_t **nodes, PyObject **separators) {
    int i, j, node_counter = 0, needed, offset;
    bt_node_t *node;
    bt_node_t *neighbor;

    /* this path object is for use in node_sizechange calls. the depth is
       always 0 so that every node put in it looks like a root, so that
       node_sizechange never iterates up to any parents */
    bt_path_t dummy_path;
    bt_node_t *_dummy_lineage[1];
    int _dummy_indexes[1];
    dummy_path.tree = NULL;
    dummy_path.depth = 0;
    dummy_path.indexes = _dummy_indexes;
    dummy_path.indexes[0] = 0;
    dummy_path.lineage = _dummy_lineage;
    dummy_path.lineage[0] = NULL;

    /*
     * pull `order` items into a new node, then 1 item as a separator, repeat
     */
    node = allocate_node(is_branch, order);
    for (i = 0; i < item_count; ++i) {
        if (i % (order + 1) == order) {
            /* at a separator value */
            node->filled = order;
            nodes[node_counter] = node;
            separators[node_counter] = items[i];
            node = allocate_node(is_branch, order);
            node_counter++;
        }
        else {
            /* still inside a node */
            node->values[i % (order + 1)] = items[i];
        }
    }
    node->filled = i % (order + 1);
    nodes[node_counter] = node;

    /*
     * if the generation's final node didn't wind up with enough items,
     * pass enough over from the penultimate node to make both legal
     */
    if (node_counter && node->filled < (order / 2)) {
        /* get some items from the previous node to make everything legal */
        needed = (order / 2) - node->filled;
        neighbor = nodes[node_counter - 1];

        /* make space for the items to be moved */
        memmove(node->values + needed, node->values,
                sizeof(PyObject *) * node->filled);

        /* prepend the item from the separators */
        node->values[needed - 1] = separators[node_counter - 1];

        /* make the first item to be moved be the separator */
        separators[node_counter - 1] = neighbor->values[
            neighbor->filled - needed];

        /* copy the other items to be moved */
        memcpy(node->values, neighbor->values + neighbor->filled - needed + 1,
                sizeof(PyObject *) * (needed - 1));

        node->filled += needed;
        neighbor->filled -= needed;
    }

    /*
     * if a non-leaf generation, hand out the children to the new nodes
     */
    if (is_branch)
        for (i = offset = 0; i <= node_counter; ++i) {
            node = nodes[i];
            for (j = 0; j <= node->filled; ++j)
                ((bt_branch_t *)node)->children[j] = children[offset++];

            /* record the size changes of the new nodes */
            dummy_path.lineage[0] = node;
            node_sizechange(&dummy_path);
        }

    return node_counter + 1;
}
Exemplo n.º 9
0
/*
 * shrink a node by at least 1 to preserve the btree invariants
 */
static void
shrink_node(bt_path_t *path) {
    int parent_index = -1;
    bt_branch_t *parent = NULL;
    bt_node_t *sibling;
    bt_node_t *node = path->lineage[path->depth];

    int middle;
    PyObject *median;

    /* if we aren't the root, try passing an item to a neighbor */
    if (path->depth) {
        parent_index = path->indexes[path->depth - 1];
        parent = (bt_branch_t *)path->lineage[path->depth - 1];

        /* try passing it left first */
        if (parent_index) {
            sibling = parent->children[parent_index - 1];
            if (sibling->filled < path->tree->order) {
                node_pass_left(path, 1);
                return;
            }
        }

        /* try passing it right */
        if (parent_index < parent->filled) {
            sibling = parent->children[parent_index + 1];

            if (sibling->filled < path->tree->order) {
                node_pass_right(path, 1);
                return;
            }
        }
    }

    /*
     * fallback plan: split the current node into two
     */

    /* pull the median value, it's going up to the parent node */
    middle = node->filled / 2;
    median = node->values[middle];

    /* put the second half of the node's data in a new sibling */
    sibling = allocate_node(
            path->depth < path->tree->depth, path->tree->order);
    sibling->filled = node->filled - middle - 1;
    memcpy(sibling->values, node->values + middle + 1,
            sizeof(PyObject *) * sibling->filled);
    if (path->depth < path->tree->depth)
        memcpy(((bt_branch_t *)sibling)->children,
                ((bt_branch_t *)node)->children + middle + 1,
                sizeof(bt_node_t *) * (node->filled - middle));

    /* cut off the original node's data in the middle */
    node->filled = middle;

    /* the node's size has changed */
    path->lineage[path->depth] = node;
    node_sizechange(path);

    /* the new sibling's size has changed */
    path->indexes[path->depth - 1]++;
    path->lineage[path->depth] = sibling;
    node_sizechange(path);

    /*
     * push the median value up to the parent
     */

    if (!(path->depth)) {
        /* if we were the root, we're going to need a parent now */
        parent = (bt_branch_t *)allocate_node(1, path->tree->order);

        /* insert the siblings as children, and the median value */
        parent->children[0] = node;
        parent->children[1] = sibling;
        parent->values[0] = median;
        parent->filled = 1;
        path->tree->root = (bt_node_t *)parent;
        path->tree->depth++;
    } else {
        /* if we need to, make space in the parent's arrays */
        if (parent_index < parent->filled) {
            memmove(parent->values + parent_index + 1,
                    parent->values + parent_index,
                    sizeof(PyObject *) * (parent->filled - parent_index));
            memmove(parent->children + parent_index + 2,
                    parent->children + parent_index + 1,
                    sizeof(bt_node_t *) * (parent->filled - parent_index));
        }

        parent->values[parent_index] = median;
        parent->children[parent_index + 1] = sibling;
        parent->filled += 1;
    }

    /* the parent's size has changed in either of the above branches */
    path->depth--;
    node_sizechange(path);

    /* now if the parent node is overflowed then it too needs to shrink */
    if (parent->filled > path->tree->order)
        shrink_node(path);
}
Exemplo n.º 10
0
/* return the number of blocks or zero if not enough memory */
long cachelru_construct(long _n_data, long _n_blocks, size_t block_size) {
  
  long i;
  Node *node;
  Node *current;
  long memory_block_size =0;

  n_data = _n_data;
  n_blocks = _n_blocks;

#ifdef DEBUG_CACHELRU
  fprintf(stderr, "cachelru_construct : n_data\t = %ld\n", n_data);
  fprintf(stderr, "cachelru_construct : n_blocks\t = %ld\n", n_blocks);
  fprintf(stderr, "cachelru_construct : block_size\t = %d\n", block_size);
#endif 
  
  /* allocate and initialize data_index */
  data_index = (Node **) ut_calloc (n_data, sizeof(Node *));
  for (i=0; i<n_data; i++)
    data_index[i]=NULL;
  
#ifdef DEBUG_CACHELRU1
  fprintf(stderr, "cachelru_construct : data_index initilized %ld units of size %d\n", n_data,sizeof(Node*));
#endif 
  

#ifdef DEBUG_CACHELRU
  fprintf(stderr, "cachelru_construct : n_blocks = min(%ld,%ld)\n",n_blocks, 
(long)(((((double)MB) * ((double)MEMORY_SIZE)) / (((double)block_size) + ((double)(sizeof(Node)))))));
#endif 
  

  memory_block_size = block_size + sizeof(Node);
  n_blocks = MIN(n_blocks, ((long) ((((double)MB) * ((double)MEMORY_SIZE)) / ((double) memory_block_size))));

  memory_block = calloc(n_blocks, memory_block_size);

#ifdef DEBUG_CACHELRU
  fprintf(stderr, "cachelru_construct : n_blocks\t = %ld\n", n_blocks);
  fprintf(stderr, "cachelru_construct : memory_block_size\t= %ld B\n", memory_block_size);
#endif 
  
  while (memory_block == NULL) {
    n_blocks--;
    
#ifdef DEBUG_CACHELRU1
  fprintf(stderr, "cachelru_construct : n_blocks\t = %ld\n", n_blocks);
#endif 
  
  memory_block = calloc(n_blocks, memory_block_size);
  }
  
  start_memory_block = memory_block;

  //printf("CacheLRU allocated %ld blocks of size %10.3fKb\n",n_blocks,(double)memory_block_size/(double)KB); fflush(stdout);
  //printf("Allocated total %7.3fMb (Internal bound %dMb)\n"
	 //,((double)n_blocks * (double)memory_block_size)/(double)MB, 
	 //MEMORY_SIZE); fflush(stdout);
  

#ifdef DEBUG_CACHELRU
  fprintf(stderr, "cachelru_construct : allocated %ld blocks of size %ldB at address %p\n", 
	  n_blocks,memory_block_size, memory_block);
#endif


#ifdef DEBUG_CACHELRU1
  {
    long i,j;
    fprintf(stderr, "cachelru_construct : scanning memory\n");
      
      for (i=0; i<n_blocks; i++)
	for (j=0; j<memory_block_size; j++)
	  *((char*)(memory_block+j+i*memory_block_size)) = 0;
  }
#endif 
  

  /* allocate and initialize tail */
  tail = allocate_node(block_size);
  if (tail == NULL) {
    free(data_index);
    return (0);
  }
  current = tail;
    
#ifdef DEBUG_CACHELRU1
  fprintf(stderr, "cachelru_construct : initilized tail in pointer %p\n", tail);
#endif 
  
  /* allocate and initialize rest of list */
  for (i=1; i<n_blocks; i++) {
    node = allocate_node(block_size);
  
    if (node == NULL) {          /* if not enough memory */
      
#ifdef DEBUG_CACHELRU1
      fprintf(stderr, "cachelru_construct : can't allocate more blocks\n");
#endif 
      n_blocks = i;            /* and auto size        */
      break;                   /* resize cache         */
    }
    else {                       /* node allocated add it to end of list */
            
      current->next = node;
      node->prev = current;
      current = node;
    }
  }

  /* circle the list */
  current->next = tail;
  tail->prev = current;
  
#ifdef DEBUG_CACHELRU1
  fprintf(stderr, "cachelru_construct : n_blocks = %ld\n",n_blocks);
  fprintf(stderr, "cachelru_construct : total allocated memory > %ld Kb\n",((n_blocks*(block_size+sizeof(Node)))+n_data*sizeof(Node*))/1024);
#endif 
  return (n_blocks);
}
Exemplo n.º 11
0
bool net::connection_list::add(const struct iphdr* ip_header, const struct tcphdr* tcp_header, size_t payload, time_t t, connection*& conn, unsigned char& direction)
{
	ip_address addresses[2];
	unsigned short ports[2];
	size_t transferred[2];

	unsigned short srcport = ntohs(tcp_header->source);
	unsigned short destport = ntohs(tcp_header->dest);

	if (srcport >= destport) {
		addresses[0].ipv4 = ip_header->saddr;
		addresses[1].ipv4 = ip_header->daddr;

		ports[0] = srcport;
		ports[1] = destport;

		transferred[0] = payload;
		transferred[1] = 0;

		direction = kOutgoingPacket;
	} else {
		addresses[0].ipv4 = ip_header->daddr;
		addresses[1].ipv4 = ip_header->saddr;

		ports[0] = destport;
		ports[1] = srcport;

		transferred[0] = 0;
		transferred[1] = payload;

		direction = kIncomingPacket;
	}

	ip_fragments* fragments = &_M_fragments[ports[0]];

	// Search IP fragment.
	ip_fragment* fragment;
	size_t pos;
	if ((fragment = search(fragments, addresses[0], pos)) == NULL) {
		// If not a SYN + ACK...
		if ((!tcp_header->syn) || (!tcp_header->ack)) {
			// Ignore packet.
			conn = NULL;
			return true;
		}

		if (!allocate_ip_fragment(fragments)) {
			return false;
		}

		if (pos < fragments->used) {
			memmove(&fragments->fragments[pos + 1], &fragments->fragments[pos], (fragments->used - pos) * sizeof(struct ip_fragment));
		}

		fragment = &fragments->fragments[pos];
		fragment->data = ((const unsigned char*) addresses)[sizeof(ip_address) - 1];

		fragment->indices = NULL;
		fragment->size = 0;
		fragment->used = 0;

		fragments->used++;
	}

	// Search index in IP fragment.
	size_t index;
	if (!search(fragment, addresses[0], ports[0], addresses[1], ports[1], index)) {
		// If not a SYN + ACK...
		if ((!tcp_header->syn) || (!tcp_header->ack)) {
			// Ignore packet.
			conn = NULL;
			return true;
		}

		node* n;
		if ((!allocate_index(fragment)) || ((n = allocate_node()) == NULL)) {
			return false;
		}

		if (index < fragment->used) {
			memmove(&fragment->indices[index + 1], &fragment->indices[index], (fragment->used - index) * sizeof(unsigned));
		}

		fragment->indices[index] = _M_head;

		// Initialize connection.
		conn = &n->conn;

		conn->init();

		conn->srcip = addresses[0];
		conn->destip = addresses[1];

		conn->srcport = ports[0];
		conn->destport = ports[1];

		conn->creation = t;
		conn->timestamp = t;

		conn->uploaded = transferred[0];
		conn->downloaded = transferred[1];

		conn->direction = !direction; // Invert direction (this is the second packet).

		fragment->used++;

		return true;
	}

	// If the connection has to be deleted...
	if ((tcp_header->rst) || (tcp_header->fin)) {
		delete_node(ports[0], pos, index);

		conn = NULL;
		return true;
	}

	conn = &_M_nodes.nodes[fragment->indices[index]].conn;

	conn->timestamp = t;

	conn->uploaded += transferred[0];
	conn->downloaded += transferred[1];

	return true;
}
Exemplo n.º 12
0
 ::rapidxml::xml_node<>* Document::AppendChildNode( ::rapidxml::xml_node<>* Parent, const char* type )
 {
    ::rapidxml::xml_node<>* ChildElement = allocate_node( ::rapidxml::node_element, PrefixType( type ) );
    Parent->append_node( ChildElement );
    return ChildElement;
 }