Ejemplo n.º 1
0
Archivo: renderman.c Proyecto: fscz/gre
static int tear_down_index_buffer (SceneData* sceneData, SceneObject* so, SoData* soData) {
  Draw* method = so->draw;

  char bufferKey[KEYSIZE];

  Attribute* indices = method->indices;
  GLuint bufferHandle;
  size_t bufferUsers;

  if ( indices && 1 == indices->useBuffer ) {
    snprintf (bufferKey, KEYSIZE, "%p", indices);
    bufferUsers = (size_t)hashmap_find ( bufferKey, sceneData->countBufferUsers );
    bufferUsers--;

    if ( 0 == bufferUsers ) {

      bufferHandle = (GLuint)hashmap_find ( bufferKey, sceneData->mapBuffer2Handle );
      glDeleteBuffers ( 1, &bufferHandle );
      hashmap_delete ( bufferKey, sceneData->mapBuffer2Handle );
      hashmap_delete ( bufferKey, sceneData->countBufferUsers );
      list_remove_elem ( (void*)bufferHandle, sceneData->listBuffers );

    } else {
      
      hashmap_insert ( bufferKey, (void*)bufferUsers, sceneData->countBufferUsers );
    }

  }

  return 0;
}
static void free_config (struct config_s *conf)
{
        safefree (conf->config_file);
        safefree (conf->logf_name);
        safefree (conf->stathost);
        safefree (conf->user);
        safefree (conf->group);
        /*Added to enable POST data recovery to output directory*/
        safefree (conf->output_dir);
        safefree (conf->ipAddr);
#ifdef FILTER_ENABLE
        safefree (conf->filter);
#endif                          /* FILTER_ENABLE */
#ifdef REVERSE_SUPPORT
        free_reversepath_list(conf->reversepath_list);
        safefree (conf->reversebaseurl);
#endif
#ifdef UPSTREAM_SUPPORT
        free_upstream_list (conf->upstream_list);
#endif                          /* UPSTREAM_SUPPORT */
        safefree (conf->pidpath);
        safefree (conf->bind_address);
        safefree (conf->via_proxy_name);
        hashmap_delete (conf->errorpages);
        free_added_headers (conf->add_headers);
        safefree (conf->errorpage_undef);
        safefree (conf->statpage);
        flush_access_list (conf->access_list);
        free_connect_ports_list (conf->connect_ports);
        hashmap_delete (conf->anonymous_map);

        memset (conf, 0, sizeof(*conf));
}
Ejemplo n.º 3
0
Archivo: renderman.c Proyecto: fscz/gre
static int tear_down_textures (SceneData* sceneData, SceneObject* so, SoData* soData) {
  
  Uniform* uniform;
  char uniKey[KEYSIZE];
  GLuint textureHandle;
  size_t textureUsers;

  int i;
  for ( i = 0; i < list_size ( soData->textures ); i++) {
    
    uniform = list_get( i, soData->textures);
    snprintf ( uniKey, KEYSIZE, "%p", uniform );    
    textureHandle = (GLuint)hashmap_find ( uniKey, sceneData->mapTexture2Handle );
    textureUsers = (size_t)hashmap_find ( uniKey, sceneData->countTextureUsers );
    
    textureUsers--;

    if ( 0 == textureUsers ) {
      glDeleteTextures( 1, &textureHandle );
      
      hashmap_delete ( uniKey, sceneData->mapTexture2Handle );
      hashmap_delete ( uniKey, sceneData->countTextureUsers );
      list_remove_elem ( (void*)textureHandle, sceneData->listTextures );

    } else {
      hashmap_insert ( uniKey, (void*)textureUsers, sceneData->countTextureUsers );
    }
  }

  return 0;
}
Ejemplo n.º 4
0
int main(int argc, char **argv) {
	int i, key, inmap, insert, data;
	void *datap;
	struct hashmap_t *map = hashmap_new(5);
	srandom(0);
	for (i=0; i<10000; i++) {
		key = rand()%DATASET_SIZE;
		insert = rand()%2;
		inmap = test_status[key];
		data = test_data[key];
		if (inmap && insert) { 
			/* update */
			data++;
			hashmap_upsert(map, &key, sizeof(int), INT2PTR(data),  &datap);
			assert((intptr_t)datap == (intptr_t)test_data[key]);
			test_data[key] = data;
		} else if ( !inmap && insert) {
			/* insert */
			hashmap_upsert(map, &key, sizeof(int), INT2PTR(data),  &datap);
			assert( (intptr_t)datap == 0);
			test_status[key] = 1;
		} else if (inmap && !insert) {
			/* delete */
			hashmap_delete(map, &key, sizeof(int), &datap);
			assert((intptr_t)datap == (intptr_t)test_data[key]);
			test_status[key] = 0;
		} else if (!inmap && !insert) {
			/* nothing to be deleted */
			hashmap_delete(map, &key, sizeof(int), &datap);
			assert((intptr_t)datap == 0);
		}
	}
	return 0;
}
Ejemplo n.º 5
0
Archivo: renderman.c Proyecto: fscz/gre
static int tear_down_program(SceneData* sceneData, SceneObject* so, SoData* soData) {

  tear_down_shaders ( sceneData, so, soData );

  char progKey[KEYSIZE];
  snprintf (progKey, KEYSIZE, "%p,%p", &so->vShader, &so->fShader);

  GLuint program = (GLuint)hashmap_find(progKey, sceneData->mapShaderShader2Handle);  
  size_t programUsers = (size_t)hashmap_find ( progKey, sceneData->countProgramUsers );
  programUsers--;

  if ( 0 == programUsers ) {

    glDeleteProgram ( program );

    hashmap_delete ( progKey, sceneData->mapShaderShader2Handle );
    hashmap_delete ( progKey, sceneData->countProgramUsers );
    list_remove_elem ( (void*)program, sceneData->listPrograms );

  } else {
    hashmap_insert ( progKey, (void*)programUsers, sceneData->countProgramUsers );
  }

  return 0;
}
Ejemplo n.º 6
0
END_TEST

START_TEST(test_map_put_delete_get)
{
    hashmap *map;
    int res = hashmap_init(0, &map);
    fail_unless(res == 0);

    char buf[100];
    void *out;
    for (int i=0; i<100;i++) {
        snprintf((char*)&buf, 100, "test%d", i);
        out = 0 & i;
        fail_unless(hashmap_put(map, (char*)buf, out) == 1);
    }

    for (int i=0; i<100;i++) {
        snprintf((char*)&buf, 100, "test%d", i);
        fail_unless(hashmap_delete(map, (char*)buf) == 0);
    }

    for (int i=0; i<100;i++) {
        snprintf((char*)&buf, 100, "test%d", i);
        fail_unless(hashmap_get(map, (char*)buf, &out) == -1);
    }

    res = hashmap_destroy(map);
    fail_unless(res == 0);
}
Ejemplo n.º 7
0
END_TEST

START_TEST(test_map_put_delete)
{
    hashmap *map;
    int res = hashmap_init(0, &map);
    fail_unless(res == 0);

    char buf[100];
    void *out;
    int j;
    for (int i=0; i<100;i++) {
        snprintf((char*)&buf, 100, "test%d", i);
        j = 0 & i;
        out = (void *)&j;
        fail_unless(hashmap_put(map, (char*)buf, out) == 1);
    }
    fail_unless(hashmap_size(map) == 100);

    for (int i=0; i<100;i++) {
        snprintf((char*)&buf, 100, "test%d", i);
        fail_unless(hashmap_delete(map, (char*)buf) == 0);
        fail_unless(hashmap_size(map) == (100-i-1));
    }

    fail_unless(hashmap_size(map) == 0);
    res = hashmap_destroy(map);
    fail_unless(res == 0);
}
Ejemplo n.º 8
0
Archivo: renderman.c Proyecto: fscz/gre
static int tear_down_shaders (SceneData* sceneData, SceneObject* so, SoData* soData) {

  char shaderKey[KEYSIZE];
  snprintf ( shaderKey, KEYSIZE, "%p", &so->vShader );

  GLuint handle = (GLuint)hashmap_find ( shaderKey, sceneData->mapVShader2Handle );
  size_t shaderUsers = (size_t)hashmap_find ( shaderKey, sceneData->countVShaderUsers );
  shaderUsers--;

  if ( 0 == shaderUsers ) {

    glDeleteShader ( handle );

    list_remove_elem ( (void*)handle, sceneData->listVShaders );
    hashmap_delete ( shaderKey, sceneData->mapVShader2Handle );
    hashmap_delete ( shaderKey, sceneData->countVShaderUsers );

  } else {

    hashmap_insert ( shaderKey, (void*)shaderUsers, sceneData->countVShaderUsers );
  }


  snprintf ( shaderKey, KEYSIZE, "%p", &so->fShader );
  handle = (GLuint)hashmap_find ( shaderKey, sceneData->mapFShader2Handle );
  shaderUsers = (GLuint)hashmap_find ( shaderKey, sceneData->countFShaderUsers );
  shaderUsers--;

  if ( 0 == shaderUsers ) {

    glDeleteShader ( handle );

    list_remove_elem ( (void*)handle, sceneData->listFShaders );
    hashmap_delete ( shaderKey, sceneData->mapFShader2Handle );
    hashmap_delete ( shaderKey, sceneData->countFShaderUsers );

  } else {

    hashmap_insert ( shaderKey, (void*)shaderUsers, sceneData->countFShaderUsers );
  }

  return 0;
}
Ejemplo n.º 9
0
void global_term(void){
	self.exit = 1;
	emc_thread_join(self.treconnect);
#if defined (EMC_WINDOWS)
	WSACleanup();
#endif
	hashmap_delete(self.devices);
	self.devices = NULL;
	hashmap_delete(self.plugs);
	self.plugs = NULL;
	unpack_delete(self.upk);
	self.upk = NULL;
	delete_nqueue(self.id_allocator);
	self.id_allocator = NULL;
	delete_sendqueue(self.sq);
	self.sq = NULL;
	delete_map(self.rcmq);
	self.rcmq = NULL;
}
Ejemplo n.º 10
0
void tcache_tick() {
    iterator it;
    hashmap_iter_begin(&cache->entries, &it);
    hashmap_pair *pair;
    while((pair = iter_next(&it)) != NULL) {
        tcache_entry_value *entry = pair->val;
        entry->age++;
        if(entry->age > CACHE_LIFETIME) {
            SDL_DestroyTexture(entry->tex);
            hashmap_delete(&cache->entries, &it);
            cache->old_frees++;
        }
    }
}
Ejemplo n.º 11
0
/* Prune entries older than 3 seconds from the route cache */
void prune_route_cache(void* arg)
{
	// This will store the next item in the linked list of hashmap entries
	hashmap_item_t next_item;

	// This will store a pointer to the route data struct
	route_data_t route_data;

	hashmap_item_t item;

	// Get the first item in the hashmap (first in the chronological sense)
	semaphore_P(route_cache_sem);
	item = hashmap_get_first(route_cache);

	// Go through all the items until we arrive at one that isn't ready for deletion
	while (item != NULL)
	{
		// Get the next item ahead of time, in case we delete this item
		next_item = hashmap_get_next(item);

		// Get the value of the hashmap, which is a route_data struct
		route_data = (route_data_t) hashmap_item_get_value(item);

		// Check if the entry is more than 3 seconds old
		if ((ticks - route_data->time_found) * PERIOD/MILLISECOND > 3000)
		{
//printf("Deleting key %d\n", hashmap_item_get_key(item));

			// Delete the route data struct
			delete_route_data(route_data);

			// Run hashmap delete, which will delete the hashmap_item struct (i.e. "item")
			hashmap_delete(route_cache, hashmap_item_get_key(item));
		}
		 else
		{
			// If the entry wasn't ready for deletion, then we can end (since the
			// linked list is maintained in chronological order of insertion)
			break;
		}

		// If we deleted the item, move to the next one
		item = next_item;
	}
	semaphore_V(route_cache_sem);

	// Once we're done, register the alarm to run again in 3 seconds
	register_alarm(3000, &prune_route_cache, NULL);
}
Ejemplo n.º 12
0
Archivo: renderman.c Proyecto: fscz/gre
static int tear_down_attributes (SceneData* sceneData, SceneObject* so, SoData* soData) {
  Attribute* attribute;
  char bufferKey[KEYSIZE];
  size_t bufferUsers;
  GLuint bufferHandle;

  int i;
  for (i = 0; i < list_size(soData->attributes); i++) {

    attribute = list_get ( i, soData->attributes );

    if ( 1 != attribute->useBuffer ) continue;

    snprintf (bufferKey, KEYSIZE, "%p", attribute);
    bufferHandle = (GLuint)hashmap_find ( bufferKey, sceneData->mapBuffer2Handle );
    
    bufferUsers = (size_t)hashmap_find ( bufferKey, sceneData->countBufferUsers );
    bufferUsers--;
    if ( 0 == bufferUsers) { // free resources

      glDeleteBuffers (1, &bufferHandle);

      list_remove_elem ( (void*)bufferHandle, sceneData->listBuffers );

      hashmap_delete ( bufferKey, sceneData->mapBuffer2Handle );

      hashmap_delete ( bufferKey, sceneData->countBufferUsers );

    } else {

      hashmap_insert ( bufferKey, (void*)bufferUsers, sceneData->countBufferUsers );
    }
  }

  return 0;
}
Ejemplo n.º 13
0
// moves entry li to the front and sets
// its id to id.
static inline void
move_to_front(cache_t* c, long li, cache_id_t id)
{
  cache_id_t to_free = NULL;
  cache_list_entry_t* le;
  cache_list_entry_t* prev = NULL;
  cache_list_entry_t* next = NULL;
  cache_list_entry_t* head = NULL;
  hm_entry_t entry;

  assert( li >= 0 );

  le = & c->list[li];

  if( li != c->head ) {

    if( le->prev != -1 ) prev = & c->list[le->prev];
    if( le->next != -1 ) next = & c->list[le->next];

    // remove the element from the list
    if( prev ) prev->next = le->next;
    else c->head = le->next;
    if( next ) next->prev = le->prev;
    else c->tail = le->prev;

    // now place it at the beginning of the list.
    head = &c->list[c->head];
    le->next = c->head;
    le->prev = -1;
    head->prev = li;
    c->head = li;
  }

  // update the IDs.
  if( le->id ) {
    // remove the old entry
    entry.key = le->id;
    entry.value = NULL;
    hashmap_delete(&c->mapping, &entry);
    to_free = le->id;
  }
  le->id = c->copy_id(id);
  if( to_free ) c->free_id(to_free);
  entry.key = le->id;
  entry.value = (void*) li;
  hashmap_insert(&c->mapping, &entry);
}
Ejemplo n.º 14
0
/* Must be called by a thread that called _retrieve_block_id() when they're
 * done with it.
 *
 * Will free the block struct if possible.
 */
int _release_block(block_t block)
{
	// todo: ensure not superblock

	// If it's a block, we're not deleting it / adding it to free blocks, just saying we dont need it in mem right now
	minifile_t inode;

	// Block isn't opened
	if (block->num_open == 0)
	{
		return 0;
	}

	// Decrement the open counter
	block->num_open--;

	if (block->is_dirty == 1)
	{
		block->is_dirty = 0;
		_commit_block(block);
	}

	// Check if the block is no longer in use
	if (block->num_open == 0)
	{
		if ((block->block_type == BLOCK_TYPE_FILE || block->block_type == BLOCK_TYPE_DIRECTORY) && block->is_deleted == 1)
		{
			_delete_inode((minifile_t) block);
		}
		 else
		{
			// Delete the block from the stored hashmap - just deletes the inode struct, doesnt destroy the inode block itself
			if ( block->block_type == BLOCK_TYPE_FILE
				|| block->block_type == BLOCK_TYPE_DIRECTORY)
			{
				inode = (minifile_t) block;
				semaphore_destroy(inode->u.data.mutex);
			}
			hashmap_delete(retrieved_blocks, block->block_id);
		}

		// free(block); hashmap_delete() does this... but it probably shouldn't...
	}

	return 0;
}
Ejemplo n.º 15
0
END_TEST

START_TEST(test_map_delete_no_keys)
{
    hashmap *map;
    int res = hashmap_init(0, &map);
    fail_unless(res == 0);
    fail_unless(hashmap_size(map) == 0);

    char buf[100];
    for (int i=0; i<100;i++) {
        snprintf((char*)&buf, 100, "test%d", i);
        fail_unless(hashmap_delete(map, (char*)buf) == -1);
    }

    res = hashmap_destroy(map);
    fail_unless(res == 0);
}
Ejemplo n.º 16
0
static int internal_release_fd(int fd) {
	struct poll_note *notep;
	void *task = (void*)task_current();
	notep = hashmap_get(g_fd_map, &fd, sizeof(int));
	if (!notep) {
		return -1; //not exist;
	}
	if (notep->reader == task) {
		notep->reader = NULL;
	}
	if (notep->writer == task) {
		notep->writer = NULL;
	}
	if (notep->reader == NULL && notep->writer == NULL) {
		hashmap_delete(g_fd_map, (void*)&fd, sizeof(int), (void*)&notep);
		cs_free(notep);
		cs_poll_del(g_poll_fd, fd);
		return 0; // a normal close
	}
	return 1; //remain reference;
}
Ejemplo n.º 17
0
Archivo: renderman.c Proyecto: fscz/gre
static int tear_down_so (SceneData* sceneData, SceneObject* so) {

  SoData* soData = find_so_data ( sceneData, so );

  if ( !soData ) return -1;

  tear_down_index_buffer ( sceneData, so, soData );
  tear_down_textures ( sceneData, so, soData );
  tear_down_attributes ( sceneData, so, soData );
  tear_down_program ( sceneData, so, soData );

  list_free ( soData->attributes );
  list_free ( soData->textures );

  char soKey[KEYSIZE];
  snprintf ( soKey, KEYSIZE, "%p", so );
  hashmap_delete ( soKey, sceneData->mapSo2SoData ) ;

  free ( soData );

  return 0;
}
Ejemplo n.º 18
0
/**
 * hashmap_new:
 * returns a new hashmap of size ``max_size'' which keys can be compared/hashed
 * using ``compare_fun''/``hash_fun'' functions.
 * NOTE: if such functions are undefined, the hashmap defaults to the ``char*''
 *     implementation for strings (assumes ``any_key_t'' is ``char'').
 */
hashmap_ptr hashmap_new(const size_t max_size,
    hashmap_key_compare compare_fun, hashmap_key_hash hash_fun) {

    /* alloc hashmap */
    hashmap_map* map = (hashmap_map*) calloc(1, sizeof(hashmap_map));
    if (!map)
        goto error;

    /* check input parameters */
    if (max_size <= 0) {
        map->_max_size = HASHMAP_DEFAULT_SIZE;
    } else {
        map->_max_size = max_size;
    }

    /* alloc support memory */
    map->_buckets = (hashmap_bucket*)
                             calloc(map->_max_size, sizeof(hashmap_bucket));
    if (!map->_buckets)
        goto error;

    /* initialize fields */
    map->_keys = NULL;
    map->_compare = (compare_fun ? compare_fun :
                    (hashmap_key_compare) hashmap_key_compare_str);
    map->_hash = (hash_fun ? hash_fun :
                    (hashmap_key_hash) hashmap_key_hash_str);
    map->_cur_size = 0;
    map->_changed = 1;

    return (hashmap_ptr) map;

error:
    hashmap_delete(map);
    return NULL;
}
Ejemplo n.º 19
0
int room_leave(struct room *r, struct client *c) {
    if (r && c) {
        return hashmap_delete(r->clients, (void *) c);
    }
    return -1;
}
Ejemplo n.º 20
0
/* This will be used when deleting files and directories.
 * 
 * This frees the inode and adds it back to the free inode list. It does not check
 * if it's in use, as that is the responsibility of the caller.
 *
 * This will free all data and indirection blocks, as they can't be in use if
 * this is being called, as the caller will ensure no other thread has it open or 
 * can open it during the duration of this call.
 */
void _delete_inode(minifile_t inode)
{
	block_t indir_block;
	block_t data_block;
	int indir_block_id = inode->u.data.indir_block_id;
	int tmp_indir_block_id;
	int i;
	int delete_ret = 0;
	int tmp_block_num;
	int ret = 0;

	// Delete the data blocks by either adding them to free list or telling
	// _release_block() to do so when all threads close it

	for (i = 0; i < inode->u.data.num_data_blocks; i++)
	{
		tmp_block_num = _inode_get_data_block_id(inode, i);

		data_block = _retrieve_block(tmp_block_num);
		data_block->block_id = tmp_block_num;
		data_block->is_deleted = 0;   // took an hour...
		_commit_block((block_t) data_block); // to find this bug...
		_push_free_data_block(data_block);

		// Don't bother with release_block if it functions like ths, just free it (todo)
		hashmap_delete(retrieved_blocks, indir_block);
		if (ret == -1)
			free(data_block);
	}	

	// Delete all indirection blocks in a similar manner
	while (indir_block_id != 0)
	{
		indir_block = _retrieve_block(indir_block_id);
		tmp_indir_block_id = indir_block->type.indir_block.entries[MAX_INDIR_BLOCK_ENTRIES];
		indir_block->block_id = indir_block_id;
		indir_block->is_deleted = 0;
		_commit_block((block_t) indir_block); // took an hour to find this bug...

		_push_free_data_block(indir_block);
		indir_block_id = tmp_indir_block_id;


		// Just free it for now, make it correct later (todo)
		hashmap_delete(retrieved_blocks, indir_block);
		if (ret == -1)
			free(indir_block);

	}

	// Add this inode to the list of free inode blocks
	for (i = 0; i < 11; i++)
	{
		inode->u.data.data_block_ids[i] = 0;
	}
	_commit_block((block_t) inode);

	_push_free_inode(inode);	

	// Free the inode semaphore
	if (inode->u.data.block_type == BLOCK_TYPE_FREE_INODE
		|| inode->u.data.block_type == BLOCK_TYPE_FILE
		|| inode->u.data.block_type == BLOCK_TYPE_DIRECTORY)
	{
		semaphore_destroy(inode->u.data.mutex);
	}

	// Delete the block from the stored hashmap, as well as the struct
	delete_ret = hashmap_delete(retrieved_blocks, inode->u.data.block_id);
	if (delete_ret == -1)
	{
		free(inode);
	}
}
Ejemplo n.º 21
0
Archivo: renderman.c Proyecto: fscz/gre
static void free_scene_data (Scene* scene) {

  char sdkey[KEYSIZE];
  snprintf (sdkey, KEYSIZE, "%p", scene);
  
  SceneData* sceneData = hashmap_find (sdkey, mapSceneData);

  if (sceneData) {    
      
    GLuint handle;
    
    int k;
    for (k = 0; k < list_size(sceneData->listBuffers); k++) {

      handle = (GLuint)list_get(k, sceneData->listBuffers);
      glDeleteBuffers (1, &handle);
    }

    for ( k = 0; k < list_size(sceneData->listPrograms); k++) {
      
      handle = (GLuint)list_get(k, sceneData->listPrograms);
      glDeleteProgram ( handle );
    }

    for ( k = 0; k < list_size(sceneData->listVShaders); k++) {
      
      handle = (GLuint)list_get(k, sceneData->listVShaders);
      glDeleteShader ( handle );
    }

    for ( k = 0; k < list_size(sceneData->listFShaders); k++) {
      
      handle = (GLuint)list_get(k, sceneData->listFShaders);
      glDeleteShader ( handle );
    }

    for ( k = 0; k < list_size(sceneData->listTextures); k++) {
      
      handle = (GLuint)list_get(k, sceneData->listTextures);
      glDeleteTextures ( 1, &handle );
    }

    list_free (sceneData->listPrograms);
    list_free (sceneData->listVShaders);
    list_free (sceneData->listFShaders);
    list_free (sceneData->listBuffers);
    list_free (sceneData->listTextures);

    hashmap_free (sceneData->mapVShader2Handle);
    hashmap_free (sceneData->mapFShader2Handle);
    hashmap_free (sceneData->mapShaderShader2Handle);
    hashmap_free (sceneData->mapBuffer2Handle);
    hashmap_free (sceneData->mapTexture2Handle);

    hashmap_free (sceneData->countBufferUsers);
    hashmap_free (sceneData->countVShaderUsers);
    hashmap_free (sceneData->countFShaderUsers);
    hashmap_free (sceneData->countProgramUsers);
    hashmap_free (sceneData->countTextureUsers);

    hashmap_free (sceneData->mapSo2SoData);

    list_free (sceneData->stageGbuffer);
    list_free (sceneData->stageLight);
    list_free (sceneData->stageGeometry);
    list_free (sceneData->stageParticle);
    list_free (sceneData->stageOverlay);
    
    hashmap_delete (sdkey, mapSceneData);
  }
}
Ejemplo n.º 22
0
Archivo: reqs.c Proyecto: OPSF/uClinux
/*
 * This is the main drive for each connection. As you can tell, for the
 * first few steps we are using a blocking socket. If you remember the
 * older tinyproxy code, this use to be a very confusing state machine.
 * Well, no more! :) The sockets are only switched into nonblocking mode
 * when we start the relay portion. This makes most of the original
 * tinyproxy code, which was confusing, redundant. Hail progress.
 * 	- rjkaes
 */
void
handle_connection(int fd)
{
	struct conn_s *connptr;
	struct request_s *request = NULL;
	hashmap_t hashofheaders = NULL;

	char peer_ipaddr[PEER_IP_LENGTH];
	char peer_string[PEER_STRING_LENGTH];

	getpeer_information(fd, peer_ipaddr, peer_string);

	log_message(LOG_CONN, "Connect (file descriptor %d): %s [%s]",
		    fd, peer_string, peer_ipaddr);

	connptr = initialize_conn(fd, peer_ipaddr, peer_string);
	if (!connptr) {
		close(fd);
		return;
	}

	if (check_acl(fd, peer_ipaddr, peer_string) <= 0) {
		update_stats(STAT_DENIED);
		indicate_http_error(connptr, 403, "Access denied",
				    "detail", "The administrator of this proxy has not configured it to service requests from your host.",
				    NULL);
		send_http_error_message(connptr);
		destroy_conn(connptr);
		return;
	}

	if (read_request_line(connptr) < 0) {
		update_stats(STAT_BADCONN);
		indicate_http_error(connptr, 408, "Timeout",
				    "detail", "Server timeout waiting for the HTTP request from the client.",
				    NULL);
		send_http_error_message(connptr);
		destroy_conn(connptr);
		return;
	}

	/*
	 * The "hashofheaders" store the client's headers.
	 */
	if (!(hashofheaders = hashmap_create(HEADER_BUCKETS))) {
		update_stats(STAT_BADCONN);
		indicate_http_error(connptr, 503, "Internal error",
				    "detail", "An internal server error occurred while processing your request.  Please contact the administrator.",
				    NULL);
		send_http_error_message(connptr);
		destroy_conn(connptr);
		return;
	}

	/*
	 * Get all the headers from the client in a big hash.
	 */
	if (get_all_headers(connptr->client_fd, hashofheaders) < 0) {
		log_message(LOG_WARNING, "Could not retrieve all the headers from the client");
		hashmap_delete(hashofheaders);
		update_stats(STAT_BADCONN);
		destroy_conn(connptr);
		return;
	}

	request = process_request(connptr, hashofheaders);
	if (!request) {
		if (!connptr->error_variables && !connptr->show_stats) {
			update_stats(STAT_BADCONN);
			destroy_conn(connptr);
			hashmap_delete(hashofheaders);
			return;
		}
		goto send_error;
	}

	connptr->upstream_proxy = UPSTREAM_HOST(request->host);
	if (connptr->upstream_proxy != NULL) {
		if (connect_to_upstream(connptr, request) < 0) {
			goto send_error;
		}
	} else {
		connptr->server_fd = opensock(request->host, request->port);
		if (connptr->server_fd < 0) {
			indicate_http_error(connptr, 500, "Unable to connect",
					    "detail", PACKAGE " was unable to connect to the remote web server.",
					    "error", strerror(errno),
					    NULL);
			goto send_error;
		}

		log_message(LOG_CONN,
			    "Established connection to host \"%s\" using file descriptor %d.",
			    request->host, connptr->server_fd);

		if (!connptr->connect_method)
			establish_http_connection(connptr, request);
	}

      send_error:
	free_request_struct(request);

	if (process_client_headers(connptr, hashofheaders) < 0) {
		update_stats(STAT_BADCONN);
		if (!connptr->error_variables) {
			hashmap_delete(hashofheaders);
			destroy_conn(connptr);
			return;
		}
	}
	hashmap_delete(hashofheaders);

	if (connptr->error_variables) {
		send_http_error_message(connptr);
		destroy_conn(connptr);
		return;
	} else if (connptr->show_stats) {
		showstats(connptr);
		destroy_conn(connptr);
		return;
	}

	if (!connptr->connect_method || (connptr->upstream_proxy != NULL)) {
		if (process_server_headers(connptr) < 0) {
			if (connptr->error_variables)
				send_http_error_message(connptr);

			update_stats(STAT_BADCONN);
			destroy_conn(connptr);
			return;
		}
	} else {
		if (send_ssl_response(connptr) < 0) {
			log_message(LOG_ERR,
				    "handle_connection: Could not send SSL greeting to client.");
			update_stats(STAT_BADCONN);
			destroy_conn(connptr);
			return;
		}
	}

	relay_connection(connptr);

	log_message(LOG_INFO, "Closed connection between local client (fd:%d) and remote client (fd:%d)",
		    connptr->client_fd, connptr->server_fd);

	/*
	 * All done... close everything and go home... :)
	 */
	destroy_conn(connptr);
	return;
}
Ejemplo n.º 23
0
Archivo: reqs.c Proyecto: OPSF/uClinux
/*
 * Loop through all the headers (including the response code) from the
 * server.
 */
static int
process_server_headers(struct conn_s *connptr)
{
	static char *skipheaders[] = {
		"keep-alive",
		"proxy-authenticate",
		"proxy-authorization",
		"proxy-connection",
		"transfer-encoding",
	};

	char *response_line;

	hashmap_t hashofheaders;
	hashmap_iter iter;
	char *data, *header;
	ssize_t len;
	int i;
	int ret;

	/* FIXME: Remember to handle a "simple_req" type */

	/* Get the response line from the remote server. */
      retry:
	len = readline(connptr->server_fd, &response_line);
	if (len <= 0)
		return -1;

	/*
	 * Strip the new line and character return from the string.
	 */
	if (chomp(response_line, len) == len) {
		/*
		 * If the number of characters removed is the same as the
		 * length then it was a blank line. Free the buffer and
		 * try again (since we're looking for a request line.)
		 */
		safefree(response_line);
		goto retry;
	}

	hashofheaders = hashmap_create(HEADER_BUCKETS);
	if (!hashofheaders) {
		safefree(response_line);
		return -1;
	}

	/*
	 * Get all the headers from the remote server in a big hash
	 */
	if (get_all_headers(connptr->server_fd, hashofheaders) < 0) {
		log_message(LOG_WARNING, "Could not retrieve all the headers from the remote server.");
		hashmap_delete(hashofheaders);
		safefree(response_line);

		indicate_http_error(connptr, 503, "Could not retrieve all the headers",
				    "detail", PACKAGE " was unable to retrieve and process headers from the remote web server.",
				    NULL);
		return -1;
	}

	/* Send the saved response line first */
	ret = write_message(connptr->client_fd, "%s\r\n", response_line);
	safefree(response_line);
	if (ret < 0)
		goto ERROR_EXIT;

	/*
	 * If there is a "Content-Length" header, retrieve the information
	 * from it for later use.
	 */
	connptr->content_length.server = get_content_length(hashofheaders);

	/*
	 * See if there is a connection header.  If so, we need to to a bit of
	 * processing.
	 */
	remove_connection_headers(hashofheaders);

	/*
	 * Delete the headers listed in the skipheaders list
	 */
	for (i = 0; i != (sizeof(skipheaders) / sizeof(char *)); i++) {
		hashmap_remove(hashofheaders, skipheaders[i]);
	}

	/* Send, or add the Via header */
	ret = write_via_header(connptr->client_fd, hashofheaders,
			       connptr->protocol.major,
			       connptr->protocol.minor);
	if (ret < 0)
		goto ERROR_EXIT;

	/*
	 * All right, output all the remaining headers to the client.
	 */
	iter = hashmap_first(hashofheaders);
	if (iter >= 0) {
		for ( ; !hashmap_is_end(hashofheaders, iter); ++iter) {
			hashmap_return_entry(hashofheaders,
					     iter,
					     &data,
					     (void **)&header);

			ret = write_message(connptr->client_fd,
						  "%s: %s\r\n",
						  data, header);
			if (ret < 0)
				goto ERROR_EXIT;
		}
	}
	hashmap_delete(hashofheaders);

	/* Write the final blank line to signify the end of the headers */
	if (safe_write(connptr->client_fd, "\r\n", 2) < 0)
		return -1;

	return 0;

  ERROR_EXIT:
	hashmap_delete(hashofheaders);
	return -1;
}
Ejemplo n.º 24
0
error_t cache_get(cache_t* c, cache_id_t id, void** ret_data)
{
  cache_list_entry_t* le;
  void* data;
  error_t err;
  hm_entry_t entry;
  long idx;
  int data_number;

  entry.key = id;
  entry.value = NULL;

  // first, check the mapping.
  if( hashmap_retrieve(&c->mapping, &entry) ) {
    idx = (long) entry.value;
    if( 0 == c->mapping.cmp(id, c->list[idx].id ) ) {
      // it's a valid mapping.
      // move it to the front of the list.
      //printf("Cache before mtf; id=%p\n", c->list[idx].id);
      move_to_front(c, idx, c->list[idx].id);
      data_number = idx;
      data = ((unsigned char*) c->data) + data_number * c->data_size;
      *ret_data = data;
      return ERR_NOERR;
    }
  }

  // if it's not an valid mapping, we'll evict the data
  // item pointed to by the last list element, then
  // load the new item, and finally move it to the front
  // of the list.

  // find a home for the new data item.
  // does the tail item in the list already have a data item?
  le = & c->list[c->tail];
  data_number = c->tail;
  data = ((unsigned char*) c->data) + data_number * c->data_size;
  if( le->id && c->evict ) {
    c->evict(le->id, c->data_size, data, c->context);
  }

  // load the new item.
  //printf("Cache before fault; id=%p\n", id);
  err = c->fault(id, c->data_size, data, c->context);
  if( err ) {
    if( le->id ) {
      // remove the old entry
      entry.key = le->id;
      entry.value = NULL;
      hashmap_delete(&c->mapping, &entry);
      c->free_id(le->id);
      le->id = NULL;
    }
    return err;
  }

  //printf("Cache after fault; id=%p\n", id);

  // move the tail element to the front of the list.
  move_to_front(c, c->tail, id);

  *ret_data = data;

  return ERR_NOERR;
}
Ejemplo n.º 25
0
/* sends a miniroute packet, automatically discovering the path if necessary. See description in the
 * .h file.
 */
int miniroute_send_pkt(network_address_t dest_address, int hdr_len, char* hdr, int data_len, char* data)
{
	// This will store the route request struct, which is a structure related to the
	// search for a path to the host
	route_request_t route_request;

	// Store the routing header
	routing_header_t routing_header;

	// Store the route to the host, which is an array of addresses
	network_address_t* route;

	// Store the route data struct, which holds the route and some metadata
	route_data_t route_data;

	// Store my address
	network_address_t my_addr;

	// Used to synchronize access with structures the network handler touches
	interrupt_level_t prev_level;

	// This will store the combined routing + normal headers
	char* full_header;

	network_address_t dest_address2;

	// These will store data related to the routes
	int time_route_found;
	int route_len;
	int route_valid = 1;

	// Used to get data from the header containing the paht
	routing_header_t tmp_routing_header;

	// Used to just check the IP of senders; combats UDP port issues w/ simulated broadcasts
	unsigned int dest_address_ip = dest_address[0];

	// Loop + tmp variables
	int current_req_id;
	int success = 0;
	int alarm_id;
	int x;
	int i;

	if (hdr_len == 0 || hdr == NULL
		|| data_len == 0 || data == NULL)
		return -1;

	// Get the route item, which is a hashmap_item_t, from the hashmap for this addr
	semaphore_P(route_cache_sem);
	route_data = (route_data_t) hashmap_get(route_cache, hash_address(dest_address));

	// If it's not NULL, extract the data from the item
	if (route_data != NULL)
	{
		time_route_found = route_data->time_found;

		route_len = route_data->route_len;

		// caveat: the cleanup thread may delete the route data, so we need to 
		// save it in a separate variable, just incase.
		route = (network_address_t*) malloc(sizeof(network_address_t) * route_len);
		if (route == NULL)
		{
			semaphore_V(route_cache_sem);
			return -1;
		}
		memcpy(route, route_data->route, sizeof(network_address_t) * route_len);
	}
	 else
	{
		route_valid = 0;
	}
	semaphore_V(route_cache_sem);

	// Check, if the route isn't NULL, if it's expired
	if (route_valid == 1 && (ticks - time_route_found) * PERIOD/MILLISECOND > 3000)
	{
		route_valid = 0;
	}

	// If the route is invalid (either not in the cache or expired)...
	if (route_valid == 0)
	{
		// We won't be needing that previous route variable
		if (route_data != NULL)
		{
			// But, just in case someone is still using it, use the route cache semaphore
			semaphore_P(route_cache_sem);
			free(route);
			semaphore_V(route_cache_sem);
		}

		// Check if someone else already initiated this route discovery request
		prev_level = set_interrupt_level(DISABLED);
		route_request = (route_request_t) hashmap_get(current_discovery_requests, dest_address_ip);
		set_interrupt_level(prev_level);

		// If so, we can just wait for their result
		if (route_request != NULL)
		{		
			// Wait for the other thread to get the path	
			// The threads waiting variable needs to be synchronized. We decided
			// to reuse the route cache sem, as there will not be much lock
			// contention
			semaphore_P(route_cache_sem);
			route_request->threads_waiting++;	
			semaphore_V(route_cache_sem);
			semaphore_P(route_request->waiting_sem);

			// Get the route from the hashmap
			semaphore_P(route_cache_sem);
			route_data = (route_data_t) hashmap_get(route_cache, hash_address(dest_address));

			// If the other thread didn't get the route, return an error
			if (route_data == NULL)
			{
				// Return failure...
				semaphore_V(route_cache_sem);
				return -1;
			}
			 else
			{
				time_route_found = route_data->time_found;
				route_len = route_data->route_len;

				if ((ticks - time_route_found) * PERIOD/MILLISECOND > 3000)
				{
					// This could have been a left-over expired cache entry that we haven't
					// deleted yet.
					semaphore_V(route_cache_sem);
					return -1;
				}

				// Save the route in a separate variable in case the route gets cleaned up
				// while we're using it
				route = (network_address_t*) malloc(sizeof(network_address_t) * route_len);
				if (route == NULL)
				{
					semaphore_V(route_cache_sem);
					return -1;
				}

				memcpy(route, route_data->route, sizeof(network_address_t) * route_len);
				semaphore_V(route_cache_sem);
			}
		}
		 else
		{
			// Otherwise, we have to do the route discovery process

			// Create a new route request struct
			route_request = create_route_request();
			if (route_request == NULL)
			{
				return -1;		
			}

			// Add the route request to the current discovery requests
			prev_level = set_interrupt_level(DISABLED);
			hashmap_insert(current_discovery_requests, dest_address_ip, route_request);
			set_interrupt_level(prev_level);

			// We'll try the route discovery process three times
			for (i = 0; i < 3; i++)
			{
				// Register an alarm to wake this thread up as it waits for a response
				alarm_id = register_alarm(12000, &alarm_wakeup_sem, (void*) route_request->initiator_sem);

				// Increment the request ID - must be synchronized, obviously
				semaphore_P(request_id_sem);
				current_req_id = route_request_id++;
				semaphore_V(request_id_sem);

				// We need to make a header for the discovery request, but the path
				// needs to have our address in it, so the reply can be forwarded back
				// to us
				network_get_my_address(my_addr);

				// Passing in the address of this local variable will suffice, as the
				// value is immediately copied into the header and then not used again

			 	// Create a routing header for the route discovery request
				routing_header = create_miniroute_header(ROUTING_ROUTE_DISCOVERY,
														dest_address, current_req_id, 
														MAX_ROUTE_LENGTH, 1,
														&my_addr);

				if (routing_header == NULL)
				{
					return -1;
				}

				// Combine it with the given header
				full_header = merge_headers(routing_header, hdr, hdr_len);
				if (full_header == NULL)
				{
					free(routing_header);
					return -1;
				}

				// Send out the route discovery request
				network_bcast_pkt(sizeof(struct routing_header)+hdr_len,
									(char*) full_header, data_len, data);

				// Wait for a reply (which will be signalled by the network handler)
				prev_level = set_interrupt_level(DISABLED);
				semaphore_P(route_request->initiator_sem);
				set_interrupt_level(prev_level);


				// Check if we got a successful response
				if (route_request->interrupt_arg != NULL)
				{
					// Deregister the alarm before it tries to wake us up
					// Needs to be synchronized, as the IH touches it and we destroy it here
					prev_level = set_interrupt_level(alarm_id);
					deregister_alarm(alarm_id);
					set_interrupt_level(alarm_id);

					// Get the header
					tmp_routing_header = (routing_header_t) route_request->interrupt_arg->buffer;
					route_len = unpack_unsigned_int(tmp_routing_header->path_len);

					// Then the path, for our own use later in this function
					// We'll also create one copy and put it in the route data struct
					route = miniroute_reverse_raw_path(tmp_routing_header, route_len);
					if (route == NULL)
					{
						free(routing_header);
						free(full_header);
						return -1;
					}

					// Create a route data struct - with a different route (as it will be deleted by a diff thread)
					route_data = create_route_data(miniroute_reverse_raw_path(tmp_routing_header, route_len),
													 route_len, ticks);
					if (route_data == NULL)
					{
						free(routing_header);
						free(full_header);
						return -1;
					}

					// add it to the cache hashmap
					semaphore_P(route_cache_sem);
					hashmap_insert(route_cache, hash_address(dest_address), route_data);
					semaphore_V(route_cache_sem);

					// Wake up the other threads waiting
					for (x = 0; x < route_request->threads_waiting; x++)
					{
						semaphore_V(route_request->waiting_sem);
					}

					// Clean up the route request struct, then delete it from the hashmap
					// DELETE ROUTE REQUEST WILL FREE THE NETWORK INTERRUPT ARG!
					prev_level = set_interrupt_level(DISABLED);
					delete_route_request(route_request);
					hashmap_delete(current_discovery_requests, dest_address_ip);	
					set_interrupt_level(prev_level);

					// We don't need to actually get any of the routing stuff from the
					// route_ite, as this process also sent the data packet

					// Free the headers
					free(routing_header);
					free(full_header);		

					// Return the total bytes sent, not including the routing header
					success = 1;
					break;
				}
			}

			// If we didn't get a successful response after 3 tries...
			if (success == 0)
			{
				// Wake up the other threads waiting so they can see we failed
				for (x = 0; x < route_request->threads_waiting; x++)
				{
					semaphore_V(route_request->waiting_sem);
				}

				// clean up the route request struct, then delete it from the hashmap
				prev_level = set_interrupt_level(DISABLED);
				delete_route_request(route_request);
				hashmap_delete(current_discovery_requests, dest_address_ip);
				set_interrupt_level(prev_level);	

				// Free the headers
				free(routing_header);
				free(full_header);

				// Return failure...
				return -1;
			}
		}
	}

	// If we're here, we either found the route in the cache or waited for another
	// thread to finish getting the route (and it did so successfully)
	network_address_copy(route[route_len-1], dest_address2);

	// Need to update the dst address to deal with UDP port issues
	// This again is due to UDP port issues...
	pack_address(((mini_header_t) hdr)->destination_address, dest_address2);

 	// Create a routing header for the data packet
	routing_header = create_miniroute_header(ROUTING_DATA,
											dest_address2, 0, 
											MAX_ROUTE_LENGTH, route_len,
											route);

	if (routing_header == NULL)
	{
		return -1;
	}

	// Combine it with the given header
	full_header = merge_headers(routing_header, hdr, hdr_len);
	if (full_header == NULL)
	{
		free(routing_header);
	}

	// Set the right destination address
	network_address_copy(route[1], dest_address2);

	// Send the packet
	network_send_pkt(dest_address2, sizeof(struct routing_header) + hdr_len, 
					full_header, data_len, data);

	// Free the route + headers
	free(route);
	free(routing_header);
	free(full_header);

	// Return the total data sent
	return hdr_len + data_len;
}