--- libaitsess/src/aitsess.c 2011/09/07 13:11:56 1.3 +++ libaitsess/src/aitsess.c 2012/02/10 23:38:30 1.4 @@ -3,7 +3,7 @@ * by Michael Pounov * * $Author: misho $ -* $Id: aitsess.c,v 1.3 2011/09/07 13:11:56 misho Exp $ +* $Id: aitsess.c,v 1.4 2012/02/10 23:38:30 misho Exp $ * ************************************************************************** The ELWIX and AITNET software is distributed under the following @@ -86,31 +86,39 @@ sess_SetErr(int eno, char *estr, ...) // ----------------------------------------------------------- /* - * initSession() Initializing session structure, if session file not exists creating with specified tech - * @pnID = Technology using in session. - SHARED_IPC IPC tech; SHARED_MAP BSD MemoryMap tech or if =NULL SHARED_IPC + * sess_initSession() Initializing session structure, if session file not exists creating with specified tech + * + * @id = Technology using in session. SHARED_IPC IPC tech orSHARED_MAP BSD MemoryMap tech * @csFName = Session filename for build key and identified * @Sess = Session item, if =NULL allocate memory for session after use must be free! * return: 0 OK new key created, -1 error: no memory or file not created, 1 OK key finded */ -inline int -initSession(int *pnID, const char *csFName, tagSess ** __restrict Sess) +int +sess_initSession(int id, const char *csFName, ait_sess_t ** __restrict Sess) { - int h, ret = 0, id = SHARED_IPC; + int h, ret = 0; char szStr[STRSIZ]; + if (!csFName) { + sess_SetErr(EINVAL, "Filename is NULL"); + return -1; + } + if (id < SHARED_UNKNOWN || id > SHARED_MAP) { + sess_SetErr(EPROTONOSUPPORT, "Session type not supported"); + return -1; + } + if (!*Sess) { - *Sess = malloc(sizeof(tagSess)); + *Sess = malloc(sizeof(ait_sess_t)); if (!*Sess) { LOGERR; return -1; } - } else - memset(*Sess, 0, sizeof(tagSess)); - if (pnID && *pnID) - id = *pnID; + } + memset(*Sess, 0, sizeof(ait_sess_t)); + strlcpy((*Sess)->name, csFName, sizeof (*Sess)->name); - h = open(csFName, O_WRONLY | O_CREAT | O_EXCL, MEM_MODE); + h = open((*Sess)->name, O_WRONLY | O_CREAT | O_EXCL, MEM_MODE); if (h == -1) { if (errno != EEXIST) { LOGERR; @@ -118,7 +126,7 @@ initSession(int *pnID, const char *csFName, tagSess ** return -1; } /* If key file exist, session already connected */ - h = open(csFName, O_RDONLY); + h = open((*Sess)->name, O_RDONLY); if (h == -1) { LOGERR; free(*Sess); @@ -131,268 +139,309 @@ initSession(int *pnID, const char *csFName, tagSess ** free(*Sess); return -1; } - if (!strncmp(szStr, "IPC@", 4)) - id = SHARED_IPC; - else if (!strncmp(szStr, "MAP@", 4)) - id = SHARED_MAP; - else { - sess_SetErr(EPROTONOSUPPORT, "Error:: Session type not supported"); + if (!strncmp(szStr, "IPC@", 4) && id == SHARED_IPC) { + ret = 1; + + (*Sess)->sess.create = (int (*)(int, long, void*, ...)) ipc_createSession; + (*Sess)->sess.destroy = (void (*)(void*)) ipc_destroySession; + (*Sess)->sess.attach = (void* (*)(void*, void*)) ipc_attachSession; + (*Sess)->sess.detach = (void (*)(void*)) ipc_detachSession; + (*Sess)->sess.notSem = (void (*)(void*)) ipc_notSemaphore; + (*Sess)->sess.isSemOK = (int (*)(void*)) ipc_isSemaphoreOK; + (*Sess)->sess.incSem = (int (*)(void*)) ipc_incSemaphore; + (*Sess)->sess.decSem = (int (*)(void*)) ipc_decSemaphore; + } else if (!strncmp(szStr, "MAP@", 4) && id == SHARED_MAP) { + ret = 1; + + (*Sess)->sess.create = (int (*)(int, long, void*, ...)) map_createSession; + (*Sess)->sess.destroy = (void (*)(void*)) map_destroySession; + (*Sess)->sess.attach = (void* (*)(void*, void*)) map_attachSession; + (*Sess)->sess.detach = (void (*)(void*)) map_detachSession; + (*Sess)->sess.notSem = (void (*)(void*)) map_notSemaphore; + (*Sess)->sess.isSemOK = (int (*)(void*)) map_isSemaphoreOK; + (*Sess)->sess.incSem = (int (*)(void*)) map_incSemaphore; + (*Sess)->sess.decSem = (int (*)(void*)) map_decSemaphore; + } else { + sess_SetErr(EPROTONOSUPPORT, + "Session type not supported or wrong session type"); close(h); free(*Sess); return -1; } - - ret = 1; /* key found */ + /* key found */ } else { /* Build new key & new session */ - switch (id) { - case SHARED_IPC: - strlcpy(szStr, "IPC@", sizeof szStr); - break; - case SHARED_MAP: - strlcpy(szStr, "MAP@", sizeof szStr); - break; - default: - sess_SetErr(EPROTONOSUPPORT, "Error:: Session type not supported"); - close(h); - unlink(csFName); - free(*Sess); - return -1; + if (id == SHARED_IPC) { + strlcpy(szStr, "IPC@", sizeof szStr); + + (*Sess)->sess.create = (int (*)(int, long, void*, ...)) ipc_createSession; + (*Sess)->sess.destroy = (void (*)(void*)) ipc_destroySession; + (*Sess)->sess.attach = (void* (*)(void*, void*)) ipc_attachSession; + (*Sess)->sess.detach = (void (*)(void*)) ipc_detachSession; + (*Sess)->sess.notSem = (void (*)(void*)) ipc_notSemaphore; + (*Sess)->sess.isSemOK = (int (*)(void*)) ipc_isSemaphoreOK; + (*Sess)->sess.incSem = (int (*)(void*)) ipc_incSemaphore; + (*Sess)->sess.decSem = (int (*)(void*)) ipc_decSemaphore; + } else if (id == SHARED_MAP) { + strlcpy(szStr, "MAP@", sizeof szStr); + + (*Sess)->sess.create = (int (*)(int, long, void*, ...)) map_createSession; + (*Sess)->sess.destroy = (void (*)(void*)) map_destroySession; + (*Sess)->sess.attach = (void* (*)(void*, void*)) map_attachSession; + (*Sess)->sess.detach = (void (*)(void*)) map_detachSession; + (*Sess)->sess.notSem = (void (*)(void*)) map_notSemaphore; + (*Sess)->sess.isSemOK = (int (*)(void*)) map_isSemaphoreOK; + (*Sess)->sess.incSem = (int (*)(void*)) map_incSemaphore; + (*Sess)->sess.decSem = (int (*)(void*)) map_decSemaphore; + } else { + sess_SetErr(EINVAL, "Session type must be specified"); + close(h); + unlink(csFName); + free(*Sess); + return -1; } strlcat(szStr, "ELWIX_Session ("PACKAGE_STRING")\n", sizeof szStr); write(h, szStr, strlen(szStr)); - ret = 0; /* new key created */ + ret = 0; + /* new key created */ } close(h); (*Sess)->type = id; + (*Sess)->zcpy = (char) ret; return ret; } /* - * freeSession() Free allocated memory for session item and delete session file if present name - * @csFName = Session filename for delete, if NULL nothing delete + * sess_freeSession() Free allocated memory for session item and delete session file if present name + * * @Sess = Session item + * return: none */ -inline void -freeSession(const char *csFName, tagSess ** __restrict Sess) +void +sess_freeSession(ait_sess_t ** __restrict Sess) { - assert(Sess); - if (!Sess) + if (!Sess || !(*Sess)) return; + if ((*Sess)->addr) + DETACH_MEMORY(*Sess); + + /* + memset(&(*Sess)->sess, 0, sizeof (*Sess)->sess); + (*Sess)->type = SHARED_UNKNOWN; - if (csFName) - unlink(csFName); - if (*Sess) - free(*Sess); + */ + + free(*Sess); *Sess = NULL; } /* * map_createSession() MMAP Created session and allocated resources - * @csFName = Session name for identified - * @cnSeed = Seed for securing key - * @cnSize = Allocated shared memory size in bytes + * + * @nSeed = Seed for securing key, if =-1 must add ready for use key + * @nSize = Allocated shared memory size in bytes * @Sess = Session item + * @... = If nSeed == -1 add ready for use key value * return: 0 Ok successful, -1 error: not allocated resources */ int -map_createSession(const char *csFName, const int cnSeed, const u_int cnSize, tagSess ** __restrict Sess) +map_createSession(int nSeed, long nSize, ait_sess_t * __restrict Sess, ...) { - int ret = 0, id = SHARED_MAP; char szSName[2][FILENAME_MAX]; + va_list lst; - ret = initSession(&id, csFName, Sess); - if (ret == -1 || !*Sess) + if (!Sess || !*Sess->name) return -1; - /* genkey */ - (*Sess)->key = ftok(csFName, cnSeed); - if ((*Sess)->key == -1) { - LOGERR; - freeSession(csFName, Sess); - return -1; + if (nSeed != -1) { + /* genkey */ + Sess->key = ftok(Sess->name, nSeed); + if (Sess->key == -1) { + LOGERR; + return -1; + } + } else { + /* get key from va_args */ + va_start(lst, Sess); + Sess->key = va_arg(lst, key_t); + va_end(lst); } /* build semaphore & shared memory name */ memset(szSName, 0, sizeof szSName); - snprintf(szSName[0], MAX_SEMNAME, "/%X.ANS", (u_int) (*Sess)->key); - snprintf(szSName[1], FILENAME_MAX, "%s-%x.ANM", csFName, (u_int) (*Sess)->key); + snprintf(szSName[0], MAX_SEMNAME, "/%X.ANS", (u_int) Sess->key); + snprintf(szSName[1], FILENAME_MAX, "%s-%x.ANM", Sess->name, (u_int) Sess->key); /* create semaphore & add 1 */ - (*Sess)->id.sid = sem_open(szSName[0], O_CREAT, MEM_MODE); - if ((*Sess)->id.sid == SEM_FAILED) { + Sess->id.sid = sem_open(szSName[0], O_CREAT, MEM_MODE); + if (Sess->id.sid == SEM_FAILED) { LOGERR; - map_destroySession(csFName, Sess); + map_destroySession(Sess); return -1; - } else - sem_post((*Sess)->id.sid); + } + /* if is new shared memory session, init sempahore with 1 */ + if (!Sess->zcpy) + sem_post(Sess->id.sid); /* create file for shared memory storage */ - (*Sess)->mem.fd = open(szSName[1], O_RDWR | O_CREAT, MEM_MODE); - if ((*Sess)->mem.fd == -1) { + Sess->mem.fd = open(szSName[1], O_RDWR | O_CREAT, MEM_MODE); + if (Sess->mem.fd == -1) { LOGERR; - map_destroySession(csFName, Sess); + map_destroySession(Sess); return -1; } /* if is new shared memory session, fill file with zeros */ - if (!ret) { - if (lseek((*Sess)->mem.fd, cnSize - 1, SEEK_SET) == -1) { + if (!Sess->zcpy) { + if (lseek(Sess->mem.fd, nSize - 1, SEEK_SET) == -1) { LOGERR; - map_destroySession(csFName, Sess); + map_destroySession(Sess); return -1; } else - write((*Sess)->mem.fd, "", 1); - lseek((*Sess)->mem.fd, 0, SEEK_SET); + write(Sess->mem.fd, "", 1); + lseek(Sess->mem.fd, 0, SEEK_SET); } - (*Sess)->eom = cnSize; + Sess->eom = nSize; - return ret; + return (int) Sess->zcpy; } /* * map_destroySession() MMAP free shared resources - * @csFName = Session name for delete + * * @Sess = Session item + * return: none */ void -map_destroySession(const char *csFName, tagSess ** __restrict Sess) +map_destroySession(ait_sess_t * __restrict Sess) { - int flg = 1; char szSName[2][FILENAME_MAX]; - assert(Sess); - if (!Sess || !*Sess) + if (!Sess || sess_isAttached(Sess) || !*Sess->name) return; memset(szSName, 0, sizeof szSName); - snprintf(szSName[0], MAX_SEMNAME, "/%X.ANS", (u_int) (*Sess)->key); - snprintf(szSName[1], FILENAME_MAX, "%s-%x.ANM", csFName, (u_int) (*Sess)->key); + snprintf(szSName[0], MAX_SEMNAME, "/%X.ANS", (u_int) Sess->key); + snprintf(szSName[1], FILENAME_MAX, "%s-%x.ANM", Sess->name, (u_int) Sess->key); - if ((*Sess)->id.sid != SEM_FAILED) { - if (sem_close((*Sess)->id.sid) == -1) - flg = 0; - if (sem_unlink(szSName[0]) == -1) - /*flg = 0*/; + if (Sess->id.sid != SEM_FAILED) { + sem_close(Sess->id.sid); + sem_unlink(szSName[0]); } - if ((*Sess)->mem.fd != -1) { - if (close((*Sess)->mem.fd) == -1) - flg = 0; - if (unlink(szSName[1]) == -1) - /*flg = 0*/; + if (Sess->mem.fd > 2) { + close(Sess->mem.fd); + unlink(szSName[1]); } - (*Sess)->eom ^= (*Sess)->eom; - - freeSession(flg ? csFName : NULL, Sess); + unlink(Sess->name); + memset(Sess->name, 0, sizeof Sess->name); + Sess->eom ^= Sess->eom; + Sess->key ^= Sess->key; } /* * ipc_createSession() IPC Created session and allocated resources - * @csFName = Session name for identified - * @cnSeed = Seed for securing key - * @cnSize = Allocated shared memory size in bytes + * + * @nSeed = Seed for securing key, if =-1 must add ready for use key + * @nSize = Allocated shared memory size in bytes * @Sess = Session item + * @... = If nSeed == -1 add ready for use key value * return: 0 Ok successful, -1 error: not allocated resources -*/ + */ int -ipc_createSession(const char *csFName, const int cnSeed, const u_int cnSize, tagSess ** __restrict Sess) +ipc_createSession(int nSeed, long nSize, ait_sess_t * __restrict Sess, ...) { - int ret = 0, id = SHARED_IPC; union semun sems; + va_list lst; - ret = initSession(&id, csFName, Sess); - if (ret == -1 || !*Sess) + if (!Sess || !*Sess->name) return -1; - /* genkey */ - (*Sess)->key = ftok(csFName, cnSeed); - if ((*Sess)->key == -1) { - LOGERR; - freeSession(csFName, Sess); - return -1; + if (nSeed != -1) { + /* genkey */ + Sess->key = ftok(Sess->name, nSeed); + if (Sess->key == -1) { + LOGERR; + return -1; + } + } else { + /* get key from va_args */ + va_start(lst, Sess); + Sess->key = va_arg(lst, key_t); + va_end(lst); } /* create semaphore */ - (*Sess)->id.semid = semget((*Sess)->key, 1, MEM_MODE | IPC_CREAT); - if ((*Sess)->id.semid == -1) { + Sess->id.semid = semget(Sess->key, 1, MEM_MODE | IPC_CREAT); + if (Sess->id.semid == -1) { LOGERR; - ipc_destroySession(csFName, Sess); + ipc_destroySession(Sess); return -1; } /* if is new shared memory session, init sempahore with 1 */ - if (!ret) { + if (!Sess->zcpy) { sems.val = 1; - if (semctl((*Sess)->id.semid, 0, SETVAL, sems) == -1) { + if (semctl(Sess->id.semid, 0, SETVAL, sems) == -1) { LOGERR; - ipc_destroySession(csFName, Sess); + ipc_destroySession(Sess); return -1; } } /* create shared memory object */ - (*Sess)->mem.shmid = shmget((*Sess)->key, cnSize, MEM_MODE | IPC_CREAT); - if ((*Sess)->mem.shmid == -1) { + Sess->mem.shmid = shmget(Sess->key, nSize, MEM_MODE | IPC_CREAT); + if (Sess->mem.shmid == -1) { LOGERR; - ipc_destroySession(csFName, Sess); + ipc_destroySession(Sess); return -1; - } - (*Sess)->eom = cnSize; + } else + Sess->eom = nSize; - return ret; + return (int) Sess->zcpy; } /* * ipc_destroySession() IPC free shared resources - * @csFName = Session name for delete + * * @Sess = Session item -*/ + * return: none + */ void -ipc_destroySession(const char *csFName, tagSess ** __restrict Sess) +ipc_destroySession(ait_sess_t * __restrict Sess) { - int flg = 1; union semun sems; struct shmid_ds ds; - assert(Sess); - if (!Sess || !*Sess) + if (!Sess || sess_isAttached(Sess)) return; - if ((*Sess)->id.semid != -1) - if (semctl((*Sess)->id.semid, 0, IPC_RMID, &sems) == -1) - flg = 0; - if ((*Sess)->mem.shmid != -1) - if (shmctl((*Sess)->mem.shmid, IPC_RMID, &ds) == -1) - flg = 0; - (*Sess)->eom ^= (*Sess)->eom; - - freeSession(flg ? csFName : NULL, Sess); + if (Sess->id.semid != -1) + semctl(Sess->id.semid, 0, IPC_RMID, &sems); + if (Sess->mem.shmid != -1) + shmctl(Sess->mem.shmid, IPC_RMID, &ds); + unlink(Sess->name); + memset(Sess->name, 0, sizeof Sess->name); + Sess->eom ^= Sess->eom; + Sess->key ^= Sess->key; } /* * map_attachSession() MMAP Attach to shared memory & return begin address + * * @s = Session item * @procMem = Custom start address (optionl) *default must be 0* * return: NULL failed attach, !=NULL begin address of memory -*/ -inline void * -map_attachSession(tagSess * __restrict s, void *procMem) + */ +void * +map_attachSession(ait_sess_t * __restrict s, void *procMem) { - struct stat sb; - if (!s) return NULL; - /* Learn size of shared memory block */ sync(); - if (fstat(s->mem.fd, &sb) == -1) { - LOGERR; - return NULL; - } else - s->eom = sb.st_size; /* attach to memory */ s->addr = mmap(procMem, s->eom, PROT_READ | PROT_WRITE, MAP_SHARED, s->mem.fd, 0); @@ -406,10 +455,12 @@ map_attachSession(tagSess * __restrict s, void *procMe /* * map_detachSession() MMAP Detach from shared memory + * * @s = Session item -*/ -inline void -map_detachSession(tagSess * __restrict s) + * return: none + */ +void +map_detachSession(ait_sess_t * __restrict s) { if (!s) return; @@ -424,12 +475,13 @@ map_detachSession(tagSess * __restrict s) /* * ipc_attachSession() IPC Attach to shared memory & return begin address + * * @s = Session item * @procMem = Custom start address (optionl) *default must be 0* * return: NULL failed attach, !=NULL begin address of memory -*/ -inline void * -ipc_attachSession(tagSess * __restrict s, void *procMem) + */ +void * +ipc_attachSession(ait_sess_t * __restrict s, void *procMem) { if (!s) return NULL; @@ -445,10 +497,12 @@ ipc_attachSession(tagSess * __restrict s, void *procMe /* * ipc_detachSession() IPC Detach from shared memory + * * @s = Session item -*/ -inline void -ipc_detachSession(tagSess * __restrict s) + * return: none + */ +void +ipc_detachSession(ait_sess_t * __restrict s) { if (!s) return; @@ -460,12 +514,13 @@ ipc_detachSession(tagSess * __restrict s) } /* - * isAttached() Check for mapped/(attached) shared memory + * sess_isAttached() Check for attached shared memory + * * @s = Session item * return: -1 null session item, 0 not attached, 1 attached memory -*/ + */ inline int -isAttached(tagSess * __restrict s) +sess_isAttached(ait_sess_t * __restrict s) { if (!s) return -1; @@ -476,10 +531,12 @@ isAttached(tagSess * __restrict s) /* * map_notSemaphore() MMAP negative block if semaphore isn`t signaled + * * @s = Session item -*/ -inline void -map_notSemaphore(tagSess * __restrict s) + * return: none + */ +void +map_notSemaphore(ait_sess_t * __restrict s) { int i = -1; @@ -487,17 +544,20 @@ map_notSemaphore(tagSess * __restrict s) return; sem_getvalue(s->id.sid, &i); - for (;i > 0; i--) + while (i > 0) { sem_wait(s->id.sid); + i--; + } } /* - * map_isSemaphored() MMAP Check semaphore + * map_isSemaphoreOK() MMAP Check semaphore + * * @s = Session item * return: -1 error: can`t return semaphore, 0 = false, 1 = true -*/ -inline int -map_isSemaphored(tagSess * __restrict s) + */ +int +map_isSemaphoreOK(ait_sess_t * __restrict s) { int val = -1; @@ -505,16 +565,17 @@ map_isSemaphored(tagSess * __restrict s) return -1; sem_getvalue(s->id.sid, &val); - return val ? 0 : 1; + return (val ? 0 : 1); } /* - * map_addSemaphore() MMAP unblock semaphore, increment semaphore + * map_incSemaphore() MMAP unblock semaphore, increment semaphore + * * @s = Session item * return: 0 Ok, -1 error: can`t increment -*/ -inline int -map_addSemaphore(tagSess * __restrict s) + */ +int +map_incSemaphore(ait_sess_t * __restrict s) { if (!s) return -1; @@ -524,11 +585,12 @@ map_addSemaphore(tagSess * __restrict s) /* * map_decSemaphore() MMAP block semaphore, decrement semaphore + * * @s = Session item * return: 0 Ok, -1 error: can`t decrement -*/ -inline int -map_decSemaphore(tagSess * __restrict s) + */ +int +map_decSemaphore(ait_sess_t * __restrict s) { if (!s) return -1; @@ -538,10 +600,12 @@ map_decSemaphore(tagSess * __restrict s) /* * ipc_notSemaphore() IPC negative block if semaphore isn`t signaled + * * @s = Session item -*/ -inline void -ipc_notSemaphore(tagSess * __restrict s) + * return: none + */ +void +ipc_notSemaphore(ait_sess_t * __restrict s) { struct sembuf sb = { 0, 0, 0 }; @@ -550,12 +614,13 @@ ipc_notSemaphore(tagSess * __restrict s) } /* - * ipc_isSemaphored() IPC Check semaphore + * ipc_isSemaphoreOK() IPC Check semaphore + * * @s = Session item * return: -1 error: can`t return semaphore, 0 = false, 1 = true -*/ -inline int -ipc_isSemaphored(tagSess * __restrict s) + */ +int +ipc_isSemaphoreOK(ait_sess_t * __restrict s) { struct sembuf sb = { 0, 0, IPC_NOWAIT }; @@ -566,12 +631,13 @@ ipc_isSemaphored(tagSess * __restrict s) } /* - * ipc_addSemaphore() IPC unblock semaphore, increment semaphore + * ipc_incSemaphore() IPC unblock semaphore, increment semaphore + * * @s = Session item * return: 0 Ok, -1 error: can`t increment -*/ -inline int -ipc_addSemaphore(tagSess * __restrict s) + */ +int +ipc_incSemaphore(ait_sess_t * __restrict s) { struct sembuf sb = { 0, 1, 0 }; @@ -583,11 +649,12 @@ ipc_addSemaphore(tagSess * __restrict s) /* * ipc_decSemaphore() IPC block semaphore, decrement semaphore + * * @s = Session item * return: 0 Ok, -1 error: can`t decrement -*/ -inline int -ipc_decSemaphore(tagSess * __restrict s) + */ +int +ipc_decSemaphore(ait_sess_t * __restrict s) { struct sembuf sb = { 0, -1, 0 };