Created
November 10, 2009 22:53
-
-
Save jon/231346 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
void init_shm() { | |
shm_global_key = ftok(IPC_KEY_FILE, SHM_GLOBAL_KEY); | |
shm_thread_key = ftok(IPC_KEY_FILE, SHM_THREAD_KEY); | |
if ((shm_global_d = shmget(shm_global_key, sizeof(shm_global_t), | |
IPC_CREAT | 0660)) < 0) { | |
perror("shmget-global"); | |
return 5; | |
} | |
if ((shm_thread_d = shmget(shm_thread_key, | |
sizeof(shm_thread_t) * num_threads, | |
IPC_CREAT | 0660)) < 0) { | |
perror("shmget-thread"); | |
return 6; | |
} | |
shm_global = shmat(shm_global_d, NULL, 0); | |
shm_thread = shmat(shm_thread_d, NULL, 0); | |
if (-1 == (int) shm_global || -1 == (int) shm_thread) { | |
perror("shmat"); | |
return 7; | |
} | |
memset(shm_global, 0, sizeof(shm_global_t)); | |
memset(shm_thread, 0, sizeof(shm_thread_t) * num_threads); | |
pthread_mutex_init(&shm_global->request_mutex, NULL); | |
pthread_cond_init(&shm_global->request, NULL); | |
pthread_mutex_init(&shm_global->segment_id_mutex, NULL); | |
pthread_cond_init(&shm_global->ready, NULL); | |
shm_global->requests_pending = 0; | |
shm_global->segment_id = 0; | |
shm_global->segment_count = num_threads; | |
pthread_attr_init(&pthread_attrs); | |
pthread_attr_setdetachstate(&pthread_attrs, PTHREAD_CREATE_DETACHED); | |
for (i = 0; i < num_threads; ++i) { | |
pthread_mutex_init(&shm_thread[i].mutex, NULL); | |
pthread_cond_init(&shm_thread[i].cond, NULL); | |
pthread_create(&thread_id, &pthread_attrs, worker_routine, (void *) i); | |
} | |
pthread_create(&thread_id, &pthread_attrs, shmem_routine, NULL); | |
} | |
void *shmem_routine(void *nothing) { | |
while (1) { | |
pthread_mutex_lock(&shm_global->request_mutex); | |
pthread_cond_wait(&shm_global->request, &shm_global->request_mutex); | |
printf("Checking pending\n"); | |
for (; shm_global->requests_pending > 0; shm_global->requests_pending--) { | |
printf("Enqueuing request...\n"); | |
enqueue(&socket_queue, USE_SHMEM, 0); | |
} | |
pthread_mutex_unlock(&shm_global->request_mutex); | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
static void service_local_request(FILE *stream, char *path) | |
{ | |
int segment_id; | |
shm_thread_t *srv_thread; | |
printf("Entering service_local_request\n"); | |
pthread_mutex_lock(&server_shm->request_mutex); | |
server_shm->requests_pending++; | |
pthread_cond_signal(&server_shm->request); | |
pthread_mutex_lock(&server_shm->segment_id_mutex); | |
pthread_mutex_unlock(&server_shm->request_mutex); | |
pthread_cond_wait(&server_shm->ready, &server_shm->segment_id_mutex); | |
/* Server thread segment id is in server_shm */ | |
segment_id = server_shm->segment_id; | |
printf("Got segment_id: %d\n", segment_id); | |
fflush(stdout); | |
srv_thread = &server_threads_shm[segment_id]; | |
pthread_mutex_unlock(&server_shm->segment_id_mutex); | |
pthread_mutex_lock(&srv_thread->mutex); | |
strncpy(srv_thread->data, path, 512 * 1024); | |
srv_thread->data_size = strlen(path) > 512 * 1024 ? 512 * 1024 : strlen(path); | |
pthread_cond_signal(&srv_thread->cond); | |
pthread_cond_wait(&srv_thread->cond, &srv_thread->mutex); | |
do { | |
if (srv_thread->data_size > 0) { | |
fwrite(srv_thread->data, srv_thread->data_size, 1, stream); | |
fflush(stream); | |
} | |
pthread_cond_signal(&srv_thread->cond); | |
pthread_cond_wait(&srv_thread->cond, &srv_thread->mutex); | |
} while (!srv_thread->done); | |
pthread_cond_signal(&srv_thread->cond); | |
pthread_mutex_unlock(&srv_thread->mutex); | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
static void service_shm(int segment_id) { | |
char *file; | |
char *response; | |
int fd, len; | |
struct stat sb; | |
shm_thread_t *shm = &shm_thread[segment_id]; | |
pthread_cond_wait(&shm->cond, &shm->mutex); | |
file = strdup(&shm->data[1]); | |
strdecode(file, file); | |
if (file[0] == '\0') | |
file = "./"; | |
len = strlen(file); | |
if (file[0] == '/' || strcmp(file, "..") == 0 || strncmp(file, "../", 3) == 0 || strstr(file, "/../") != (char *) 0 || strcmp(&(file[len - 3]), "/..") == 0) { | |
free(file); | |
response = make_error(400, "Bad Request", (char *) 0, "Illegal filename."); | |
write_shm(segment_id, response, strlen(response)); | |
free(response); | |
close_shm(segment_id); | |
return; | |
} | |
if (stat(file, &sb) < 0) { | |
free(file); | |
response = make_error(404, "Not Found", (char *) 0, "File not found."); | |
write_shm(segment_id, response, strlen(response)); | |
free(response); | |
close_shm(segment_id); | |
return; | |
} | |
fd = open(file, O_RDONLY, 0); | |
if (fd < 0) { | |
free(file); | |
response = make_error(403, "Forbidden", (char *) 0, "File is protected."); | |
write_shm(segment_id, response, strlen(response)); | |
free(response); | |
close_shm(segment_id); | |
return; | |
} | |
free(file); | |
response = make_headers(200, "Ok", (char *) 0, get_mime_type(file), sb.st_size, sb.st_mtime); | |
write_shm(segment_id, response, strlen(response)); | |
free(response); | |
do { | |
len = read(fd, shm->data, SHM_BUF_SIZE); | |
shm->data_size = len; | |
pthread_cond_signal(&shm->cond); | |
pthread_cond_wait(&shm->cond, &shm->mutex); | |
} while (len > 0); | |
close(fd); | |
close_shm(segment_id); | |
} | |
static void write_shm(int segment_id, char *data, int len) { | |
shm_thread_t *shm = &shm_thread[segment_id]; | |
shm->data_size = len < SHM_BUF_SIZE ? len : SHM_BUF_SIZE; | |
memcpy(shm->data, data, shm->data_size); | |
pthread_cond_signal(&shm->cond); | |
pthread_cond_wait(&shm->cond, &shm->mutex); | |
} | |
static void close_shm(int segment_id) { | |
shm_thread_t *shm = &shm_thread[segment_id]; | |
shm->data_size = 0; | |
shm->done = 1; | |
pthread_cond_signal(&shm->cond); | |
pthread_cond_wait(&shm->cond, &shm->mutex); | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/****************************************************************************/ | |
/** Kevin Webb gtg247r **/ | |
/** Jon Olson gtg620b **/ | |
/****************************************************************************/ | |
#ifndef _SHMEM_STUFF_H | |
#define _SHMEM_STUFF_H | |
#define IPC_KEY_FILE "/" | |
#define SHM_GLOBAL_KEY 0xf00d | |
#define SHM_THREAD_KEY 0xf00f | |
#define SHM_BUF_SIZE 512 * 1024 | |
#include <pthread.h> | |
typedef struct { | |
pthread_mutex_t request_mutex; | |
pthread_cond_t request; | |
pthread_mutex_t segment_id_mutex; | |
pthread_cond_t ready; | |
int requests_pending; | |
int segment_id; | |
int segment_count; | |
} shm_global_t; | |
typedef struct { | |
pthread_mutex_t mutex; | |
pthread_cond_t cond; | |
int done; | |
size_t data_size; | |
char data[SHM_BUF_SIZE]; | |
} shm_thread_t; | |
#endif /* _SHMEM_STUFF_H */ |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment