version 1.1, 2013/03/13 14:17:53
|
version 1.2, 2013/03/13 14:54:39
|
Line 0
|
Line 1
|
|
/************************************************************************* |
|
* (C) 2008 AITNET ltd - Sofia/Bulgaria - <misho@aitbg.com> |
|
* by Michael Pounov <misho@openbsd-bg.org> |
|
* |
|
* $Author$ |
|
* $Id$ |
|
* |
|
************************************************************************** |
|
The ELWIX and AITNET software is distributed under the following |
|
terms: |
|
|
|
All of the documentation and software included in the ELWIX and AITNET |
|
Releases is copyrighted by ELWIX - Sofia/Bulgaria <info@elwix.org> |
|
|
|
Copyright 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2013 |
|
by Michael Pounov <misho@elwix.org>. All rights reserved. |
|
|
|
Redistribution and use in source and binary forms, with or without |
|
modification, are permitted provided that the following conditions |
|
are met: |
|
1. Redistributions of source code must retain the above copyright |
|
notice, this list of conditions and the following disclaimer. |
|
2. Redistributions in binary form must reproduce the above copyright |
|
notice, this list of conditions and the following disclaimer in the |
|
documentation and/or other materials provided with the distribution. |
|
3. All advertising materials mentioning features or use of this software |
|
must display the following acknowledgement: |
|
This product includes software developed by Michael Pounov <misho@elwix.org> |
|
ELWIX - Embedded LightWeight unIX and its contributors. |
|
4. Neither the name of AITNET nor the names of its contributors |
|
may be used to endorse or promote products derived from this software |
|
without specific prior written permission. |
|
|
|
THIS SOFTWARE IS PROVIDED BY AITNET AND CONTRIBUTORS ``AS IS'' AND |
|
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
|
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
|
ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE |
|
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL |
|
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS |
|
OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) |
|
HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT |
|
LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY |
|
OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF |
|
SUCH DAMAGE. |
|
*/ |
|
#include "global.h" |
|
|
|
|
|
/* |
|
* sess_initSession() - Initializing session structure, |
|
* if session file not exists creating with specified tech |
|
* |
|
* @id = Technology using in session. SHARED_IPC IPC tech or SHARED_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 |
|
*/ |
|
int |
|
sess_initSession(int id, const char *csFName, ait_sess_t ** __restrict Sess) |
|
{ |
|
int h, ret = 0; |
|
char szStr[STRSIZ]; |
|
|
|
if (!csFName) { |
|
io_SetErr(EINVAL, "Filename is NULL"); |
|
return -1; |
|
} |
|
if (id < SHARED_UNKNOWN || id > SHARED_MAP) { |
|
io_SetErr(EPROTONOSUPPORT, "Session type not supported"); |
|
return -1; |
|
} |
|
|
|
if (!*Sess) { |
|
*Sess = e_malloc(sizeof(ait_sess_t)); |
|
if (!*Sess) { |
|
LOGERR; |
|
return -1; |
|
} |
|
} |
|
memset(*Sess, 0, sizeof(ait_sess_t)); |
|
strlcpy((*Sess)->name, csFName, sizeof (*Sess)->name); |
|
|
|
h = open((*Sess)->name, O_WRONLY | O_CREAT | O_EXCL, SESS_MEM_MODE); |
|
if (h == -1) { |
|
if (errno != EEXIST) { |
|
LOGERR; |
|
e_free(*Sess); |
|
return -1; |
|
} |
|
/* If key file exist, session already connected */ |
|
h = open((*Sess)->name, O_RDONLY); |
|
if (h == -1) { |
|
LOGERR; |
|
e_free(*Sess); |
|
return -1; |
|
} |
|
ret = read(h, szStr, sizeof szStr); |
|
if (ret == -1) { |
|
LOGERR; |
|
close(h); |
|
e_free(*Sess); |
|
return -1; |
|
} |
|
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 { |
|
io_SetErr(EPROTONOSUPPORT, |
|
"Session type not supported or wrong session type"); |
|
close(h); |
|
e_free(*Sess); |
|
return -1; |
|
} |
|
/* key found */ |
|
} else { |
|
/* Build new key & new session */ |
|
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 { |
|
io_SetErr(EINVAL, "Session type must be specified"); |
|
close(h); |
|
unlink(csFName); |
|
e_free(*Sess); |
|
return -1; |
|
} |
|
strlcat(szStr, "ELWIX_Session ("PACKAGE_STRING")\n", sizeof szStr); |
|
write(h, szStr, strlen(szStr)); |
|
|
|
ret = 0; |
|
/* new key created */ |
|
} |
|
close(h); |
|
|
|
(*Sess)->type = id; |
|
(*Sess)->zcpy = (char) ret; |
|
return ret; |
|
} |
|
|
|
/* |
|
* sess_freeSession() - Free allocated memory for session item and delete session file if present name |
|
* |
|
* @Sess = Session item |
|
* return: none |
|
*/ |
|
void |
|
sess_freeSession(ait_sess_t ** __restrict Sess) |
|
{ |
|
if (!Sess || !(*Sess)) |
|
return; |
|
|
|
if ((*Sess)->addr) |
|
DETACH_MEMORY(*Sess); |
|
|
|
/* |
|
memset(&(*Sess)->sess, 0, sizeof (*Sess)->sess); |
|
|
|
(*Sess)->type = SHARED_UNKNOWN; |
|
*/ |
|
|
|
e_free(*Sess); |
|
*Sess = NULL; |
|
} |
|
|
|
|
|
/* |
|
* map_createSession() - MMAP Created session and allocated resources |
|
* |
|
* @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(int nSeed, long nSize, ait_sess_t * __restrict Sess, ...) |
|
{ |
|
char szSName[2][FILENAME_MAX]; |
|
va_list lst; |
|
|
|
if (!Sess || !*Sess->name) |
|
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); |
|
#ifdef HAVE_SHM_OPEN |
|
snprintf(szSName[1], FILENAME_MAX, "/%s-%x.ANM", Sess->name, (u_int) Sess->key); |
|
#else |
|
snprintf(szSName[1], FILENAME_MAX, "%s-%x.ANM", Sess->name, (u_int) Sess->key); |
|
#endif |
|
|
|
/* create semaphore & add 1 */ |
|
Sess->id.sid = sem_open(szSName[0], O_CREAT, SESS_MEM_MODE); |
|
if (Sess->id.sid == SEM_FAILED) { |
|
LOGERR; |
|
map_destroySession(Sess); |
|
return -1; |
|
} |
|
/* if is new shared memory session, init sempahore with 1 */ |
|
if (!Sess->zcpy) |
|
sem_post(Sess->id.sid); |
|
|
|
/* create file for shared memory storage */ |
|
#ifdef HAVE_SHM_OPEN |
|
Sess->mem.fd = shm_open(szSName[1], O_RDWR | O_CREAT, SESS_MEM_MODE); |
|
#else |
|
Sess->mem.fd = open(szSName[1], O_RDWR | O_CREAT, SESS_MEM_MODE); |
|
#endif |
|
if (Sess->mem.fd == -1) { |
|
LOGERR; |
|
map_destroySession(Sess); |
|
return -1; |
|
} |
|
if (!Sess->zcpy) { |
|
#ifdef HAVE_SHM_OPEN |
|
if (ftruncate(Sess->mem.fd, nSize) == -1) { |
|
LOGERR; |
|
map_destroySession(Sess); |
|
return -1; |
|
} |
|
#else |
|
/* if is new shared memory session, fill file with zeros */ |
|
if (lseek(Sess->mem.fd, nSize - 1, SEEK_SET) == -1) { |
|
LOGERR; |
|
map_destroySession(Sess); |
|
return -1; |
|
} else |
|
write(Sess->mem.fd, "", 1); |
|
lseek(Sess->mem.fd, 0, SEEK_SET); |
|
#endif |
|
} |
|
Sess->eom = nSize; |
|
|
|
return (int) Sess->zcpy; |
|
} |
|
|
|
/* |
|
* map_destroySession() - MMAP free shared resources |
|
* |
|
* @Sess = Session item |
|
* return: none |
|
*/ |
|
void |
|
map_destroySession(ait_sess_t * __restrict Sess) |
|
{ |
|
char szSName[2][FILENAME_MAX]; |
|
|
|
if (!Sess || sess_isAttached(Sess) || !*Sess->name) |
|
return; |
|
|
|
memset(szSName, 0, sizeof szSName); |
|
snprintf(szSName[0], MAX_SEMNAME, "/%X.ANS", (u_int) Sess->key); |
|
#ifdef HAVE_SHM_UNLINK |
|
snprintf(szSName[1], FILENAME_MAX, "/%s-%x.ANM", Sess->name, (u_int) Sess->key); |
|
#else |
|
snprintf(szSName[1], FILENAME_MAX, "%s-%x.ANM", Sess->name, (u_int) Sess->key); |
|
#endif |
|
|
|
if (Sess->id.sid != SEM_FAILED) { |
|
sem_close(Sess->id.sid); |
|
sem_unlink(szSName[0]); |
|
} |
|
if (Sess->mem.fd > 2) { |
|
close(Sess->mem.fd); |
|
#ifdef HAVE_SHM_UNLINK |
|
shm_unlink(szSName[1]); |
|
#else |
|
unlink(szSName[1]); |
|
#endif |
|
} |
|
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 |
|
* |
|
* @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(int nSeed, long nSize, ait_sess_t * __restrict Sess, ...) |
|
{ |
|
union semun sems; |
|
va_list lst; |
|
|
|
if (!Sess || !*Sess->name) |
|
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, SESS_MEM_MODE | IPC_CREAT); |
|
if (Sess->id.semid == -1) { |
|
LOGERR; |
|
ipc_destroySession(Sess); |
|
return -1; |
|
} |
|
/* if is new shared memory session, init sempahore with 1 */ |
|
if (!Sess->zcpy) { |
|
sems.val = 1; |
|
if (semctl(Sess->id.semid, 0, SETVAL, sems) == -1) { |
|
LOGERR; |
|
ipc_destroySession(Sess); |
|
return -1; |
|
} |
|
} |
|
|
|
/* create shared memory object */ |
|
Sess->mem.shmid = shmget(Sess->key, nSize, SESS_MEM_MODE | IPC_CREAT); |
|
if (Sess->mem.shmid == -1) { |
|
LOGERR; |
|
ipc_destroySession(Sess); |
|
return -1; |
|
} else |
|
Sess->eom = nSize; |
|
|
|
return (int) Sess->zcpy; |
|
} |
|
|
|
/* |
|
* ipc_destroySession() - IPC free shared resources |
|
* |
|
* @Sess = Session item |
|
* return: none |
|
*/ |
|
void |
|
ipc_destroySession(ait_sess_t * __restrict Sess) |
|
{ |
|
union semun sems; |
|
struct shmid_ds ds; |
|
|
|
if (!Sess || sess_isAttached(Sess)) |
|
return; |
|
|
|
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 |
|
*/ |
|
void * |
|
map_attachSession(ait_sess_t * __restrict s, void *procMem) |
|
{ |
|
if (!s) |
|
return NULL; |
|
|
|
sync(); |
|
|
|
/* attach to memory */ |
|
s->addr = mmap(procMem, s->eom, PROT_READ | PROT_WRITE, MAP_SHARED, s->mem.fd, 0); |
|
if (s->addr == MAP_FAILED) { |
|
LOGERR; |
|
s->addr = NULL; |
|
} |
|
|
|
return s->addr; |
|
} |
|
|
|
/* |
|
* map_detachSession() - MMAP Detach from shared memory |
|
* |
|
* @s = Session item |
|
* return: none |
|
*/ |
|
void |
|
map_detachSession(ait_sess_t * __restrict s) |
|
{ |
|
if (!s) |
|
return; |
|
|
|
msync(s->addr, 0, MS_SYNC | MS_INVALIDATE); |
|
|
|
if (s->addr && s->eom) { |
|
munmap(s->addr, s->eom); |
|
s->addr = NULL; |
|
} |
|
} |
|
|
|
/* |
|
* 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 |
|
*/ |
|
void * |
|
ipc_attachSession(ait_sess_t * __restrict s, void *procMem) |
|
{ |
|
if (!s) |
|
return NULL; |
|
|
|
s->addr = shmat(s->mem.shmid, procMem, 0); |
|
if (s->addr == (void*) -1) { |
|
LOGERR; |
|
s->addr = NULL; |
|
} |
|
|
|
return s->addr; |
|
} |
|
|
|
/* |
|
* ipc_detachSession() - IPC Detach from shared memory |
|
* |
|
* @s = Session item |
|
* return: none |
|
*/ |
|
void |
|
ipc_detachSession(ait_sess_t * __restrict s) |
|
{ |
|
if (!s) |
|
return; |
|
|
|
if (s->addr) { |
|
shmdt(s->addr); |
|
s->addr = NULL; |
|
} |
|
} |
|
|
|
/* |
|
* sess_isAttached() - Check for attached shared memory |
|
* |
|
* @s = Session item |
|
* return: -1 null session item, 0 not attached, 1 attached memory |
|
*/ |
|
inline int |
|
sess_isAttached(ait_sess_t * __restrict s) |
|
{ |
|
if (!s) |
|
return -1; |
|
|
|
return (s->addr ? 1 : 0); |
|
} |
|
|
|
|
|
/* |
|
* map_notSemaphore() - MMAP negative block if semaphore isn`t signaled |
|
* |
|
* @s = Session item |
|
* return: none |
|
*/ |
|
void |
|
map_notSemaphore(ait_sess_t * __restrict s) |
|
{ |
|
int i = -1; |
|
|
|
if (!s) |
|
return; |
|
|
|
sem_getvalue(s->id.sid, &i); |
|
while (i > 0) { |
|
sem_wait(s->id.sid); |
|
i--; |
|
} |
|
} |
|
|
|
/* |
|
* map_isSemaphoreOK() - MMAP Check semaphore |
|
* |
|
* @s = Session item |
|
* return: -1 error: can`t return semaphore, 0 = false, 1 = true |
|
*/ |
|
int |
|
map_isSemaphoreOK(ait_sess_t * __restrict s) |
|
{ |
|
int val = -1; |
|
|
|
if (!s) |
|
return -1; |
|
|
|
sem_getvalue(s->id.sid, &val); |
|
return (val ? 0 : 1); |
|
} |
|
|
|
/* |
|
* map_incSemaphore() - MMAP unblock semaphore, increment semaphore |
|
* |
|
* @s = Session item |
|
* return: 0 Ok, -1 error: can`t increment |
|
*/ |
|
int |
|
map_incSemaphore(ait_sess_t * __restrict s) |
|
{ |
|
if (!s) |
|
return -1; |
|
|
|
return sem_post(s->id.sid); |
|
} |
|
|
|
/* |
|
* map_decSemaphore() - MMAP block semaphore, decrement semaphore |
|
* |
|
* @s = Session item |
|
* return: 0 Ok, -1 error: can`t decrement |
|
*/ |
|
int |
|
map_decSemaphore(ait_sess_t * __restrict s) |
|
{ |
|
if (!s) |
|
return -1; |
|
|
|
return sem_wait(s->id.sid); |
|
} |
|
|
|
/* |
|
* ipc_notSemaphore() - IPC negative block if semaphore isn`t signaled |
|
* |
|
* @s = Session item |
|
* return: none |
|
*/ |
|
void |
|
ipc_notSemaphore(ait_sess_t * __restrict s) |
|
{ |
|
struct sembuf sb = { 0, 0, 0 }; |
|
|
|
if (s) |
|
semop(s->id.semid, &sb, 1); |
|
} |
|
|
|
/* |
|
* ipc_isSemaphoreOK() - IPC Check semaphore |
|
* |
|
* @s = Session item |
|
* return: -1 error: can`t return semaphore, 0 = false, 1 = true |
|
*/ |
|
int |
|
ipc_isSemaphoreOK(ait_sess_t * __restrict s) |
|
{ |
|
struct sembuf sb = { 0, 0, IPC_NOWAIT }; |
|
|
|
if (!s) |
|
return -1; |
|
|
|
return semop(s->id.semid, &sb, 1) + 1; |
|
} |
|
|
|
/* |
|
* ipc_incSemaphore() - IPC unblock semaphore, increment semaphore |
|
* |
|
* @s = Session item |
|
* return: 0 Ok, -1 error: can`t increment |
|
*/ |
|
int |
|
ipc_incSemaphore(ait_sess_t * __restrict s) |
|
{ |
|
struct sembuf sb = { 0, 1, 0 }; |
|
|
|
if (!s) |
|
return -1; |
|
|
|
return semop(s->id.semid, &sb, 1); |
|
} |
|
|
|
/* |
|
* ipc_decSemaphore() - IPC block semaphore, decrement semaphore |
|
* |
|
* @s = Session item |
|
* return: 0 Ok, -1 error: can`t decrement |
|
*/ |
|
int |
|
ipc_decSemaphore(ait_sess_t * __restrict s) |
|
{ |
|
struct sembuf sb = { 0, -1, 0 }; |
|
|
|
if (!s) |
|
return -1; |
|
|
|
return semop(s->id.semid, &sb, 1); |
|
} |
|
|
|
/* --- A/V management --- */ |
|
|
|
/* |
|
* sess_FreeValues() - Free all values from value array allocated from sess_GetValues() |
|
* |
|
* @ppsVals = Array strings |
|
* return: none |
|
*/ |
|
inline void |
|
sess_FreeValues(char *** __restrict ppsVals) |
|
{ |
|
str_FreeNullTerm(ppsVals); |
|
} |
|
|
|
/* |
|
* sess_GetValues() - Get all values from session shared memory |
|
* |
|
* @s = Session item |
|
* @ppsVals = Return array strings |
|
* return: -1 error: in parameter, !=-1 count of returned strings in ppsVals |
|
* (must be sess_FreeValues after use!) |
|
*/ |
|
int |
|
sess_GetValues(ait_sess_t * __restrict s, char ***ppsVals) |
|
{ |
|
register int i; |
|
char **valz, *Shared = NULL; |
|
char *peer, *p_brk; |
|
|
|
if (!s || !ppsVals) |
|
return -1; |
|
valz = e_malloc(sizeof(caddr_t)); |
|
if (!valz) { |
|
LOGERR; |
|
return -1; |
|
} else |
|
*valz = NULL; |
|
|
|
/* allocated memory & mirrored shared memory into this */ |
|
Shared = e_malloc(s->eom); |
|
if (!Shared) { |
|
LOGERR; |
|
e_free(valz); |
|
return -1; |
|
} else |
|
memcpy(Shared, s->addr, s->eom); |
|
|
|
for (i = 0, peer = strtok_r(Shared, SESS_MEM_DELIM"\r\n", &p_brk); peer; |
|
peer = strtok_r(NULL, SESS_MEM_DELIM"\r\n", &p_brk)) { |
|
if (!strchr(peer, '=')) |
|
continue; |
|
else |
|
i++; |
|
|
|
valz = e_realloc(valz, (i + 1) * sizeof(caddr_t)); |
|
if (!valz) { |
|
LOGERR; |
|
e_free(Shared); |
|
return -1; |
|
} else |
|
valz[i] = NULL; |
|
|
|
valz[i - 1] = e_strdup(peer); |
|
} |
|
|
|
e_free(Shared); |
|
*ppsVals = valz; |
|
return i; |
|
} |
|
|
|
/* |
|
* sess_GetValue() - Get value from session shared memory from attribute |
|
* |
|
* @s = Session item |
|
* @csAttr = Attribute for search |
|
* @psVal = Return string buffer |
|
* @pnLen = Length of return string buffer, |
|
// *{pnLen} input is max_size of buffer & output is really taken bytes |
|
* return: 0 not found, -1 error: in parameter, >0 get position, |
|
* if define item merged with IS_DEF |
|
*/ |
|
int |
|
sess_GetValue(ait_sess_t * __restrict s, const char *csAttr, char *psVal, int *pnLen) |
|
{ |
|
register int i; |
|
int def = IS_VAL; |
|
char *Shared = NULL; |
|
char *peer, *p_brk, *a_brk, *attr, *val; |
|
|
|
if (!s || !csAttr || !*csAttr) |
|
return -1; |
|
if (psVal) { |
|
if (pnLen && *pnLen > 0) |
|
memset(psVal, 0, *pnLen); |
|
else |
|
return -1; |
|
} |
|
|
|
/* allocated memory & mirrored shared memory into this */ |
|
Shared = e_malloc(s->eom); |
|
if (!Shared) { |
|
LOGERR; |
|
return -1; |
|
} else |
|
memcpy(Shared, s->addr, s->eom); |
|
|
|
for (i = 1, peer = strtok_r(Shared, SESS_MEM_DELIM"\r\n", &p_brk); peer; |
|
i++, peer = strtok_r(NULL, SESS_MEM_DELIM"\r\n", &p_brk)) { |
|
attr = strtok_r(peer, "=\r\n", &a_brk); |
|
if (attr && !strncmp(attr, csAttr, MAX_ATTRIBUTE - 1)) { |
|
val = strtok_r(NULL, "=\r\n", &a_brk); |
|
if (val && strlen(val)) { |
|
if (psVal) |
|
strlcpy(psVal, val, *pnLen); |
|
if (pnLen) |
|
*pnLen = strlen(val); |
|
} else |
|
def = IS_DEF; |
|
|
|
e_free(Shared); |
|
return i | def; |
|
} |
|
} |
|
|
|
e_free(Shared); |
|
return 0; |
|
} |
|
|
|
/* |
|
* sess_DelValue() - Delete item from session shared memory |
|
* |
|
* @s = Session item |
|
* @csAttr = Attribute for erasing |
|
* return: 0 Ok, -1 error: in parameter |
|
*/ |
|
int |
|
sess_DelValue(ait_sess_t * __restrict s, const char *csAttr) |
|
{ |
|
register int i; |
|
int attrlen; |
|
char *Buffer, *Shared, szAttr[MAX_ATTRIBUTE]; |
|
char *peer, *p_brk; |
|
|
|
if (!s || !csAttr || !*csAttr) |
|
return -1; |
|
else |
|
attrlen = strlen(csAttr); |
|
Buffer = Shared = NULL; |
|
strlcpy(szAttr, csAttr, sizeof szAttr); |
|
strlcat(szAttr, "=", sizeof szAttr); |
|
|
|
Buffer = e_malloc(s->eom); |
|
if (!Buffer) { |
|
LOGERR; |
|
return -1; |
|
} else |
|
memset(Buffer, 0, s->eom); |
|
Shared = e_malloc(s->eom); |
|
if (!Shared) { |
|
LOGERR; |
|
e_free(Buffer); |
|
return -1; |
|
} else { |
|
DEC_SEM(s); |
|
memcpy(Shared, s->addr, s->eom); |
|
} |
|
|
|
for (i = 1, peer = strtok_r(Shared, SESS_MEM_DELIM"\r\n", &p_brk); peer; |
|
i++, peer = strtok_r(NULL, SESS_MEM_DELIM"\r\n", &p_brk)) { |
|
if (!strncmp(peer, csAttr, attrlen)) |
|
if (peer[attrlen] == '=' || peer[attrlen] == *SESS_MEM_DELIM || !peer[attrlen] || |
|
peer[attrlen] == '\r' || peer[attrlen] == '\n') |
|
continue; |
|
|
|
strlcat(Buffer, peer, s->eom); |
|
strlcat(Buffer, SESS_MEM_DELIM, s->eom); |
|
} |
|
|
|
memcpy(s->addr, Buffer, s->eom); |
|
|
|
if (s->type == SHARED_MAP) |
|
msync(s->addr, 0, MS_SYNC | MS_INVALIDATE); |
|
|
|
INC_SEM(s); |
|
e_free(Shared); |
|
e_free(Buffer); |
|
return 0; |
|
} |
|
|
|
/* |
|
* sess_SetValue() - Set item into session shared memory or update if exists |
|
* |
|
* @s = Session item |
|
* @csAttr = Attribute |
|
* @psVal = Value |
|
* return: 0 nothing, -1 error: in parameter, |
|
>0 set position, if add item merged with IS_ADD and if define item merged with IS_DEF |
|
*/ |
|
int |
|
sess_SetValue(ait_sess_t * __restrict s, const char *csAttr, const char *psVal) |
|
{ |
|
register int i; |
|
int upd, def = IS_VAL; |
|
char *Buffer, *Shared, szAttr[MAX_ATTRIBUTE]; |
|
char *peer, *p_brk; |
|
|
|
if (!s || !csAttr || !*csAttr) |
|
return -1; |
|
else |
|
Buffer = Shared = NULL; |
|
strlcpy(szAttr, csAttr, sizeof szAttr); |
|
strlcat(szAttr, "=", sizeof szAttr); |
|
|
|
Buffer = e_malloc(s->eom); |
|
if (!Buffer) { |
|
LOGERR; |
|
return -1; |
|
} else |
|
memset(Buffer, 0, s->eom); |
|
Shared = e_malloc(s->eom); |
|
if (!Shared) { |
|
LOGERR; |
|
e_free(Buffer); |
|
return -1; |
|
} else { |
|
DEC_SEM(s); |
|
memcpy(Shared, s->addr, s->eom); |
|
} |
|
|
|
for (i = 1, upd = 0, peer = strtok_r(Shared, SESS_MEM_DELIM"\r\n", &p_brk); peer; |
|
i++, peer = strtok_r(NULL, SESS_MEM_DELIM"\r\n", &p_brk)) { |
|
if (!strncmp(peer, szAttr, strlen(szAttr))) { |
|
upd++; |
|
if (psVal) { |
|
strlcat(Buffer, szAttr, s->eom); |
|
strlcat(Buffer, psVal, s->eom); |
|
strlcat(Buffer, SESS_MEM_DELIM, s->eom); |
|
} else { |
|
strlcat(Buffer, csAttr, s->eom); |
|
strlcat(Buffer, SESS_MEM_DELIM, s->eom); |
|
def = IS_DEF; |
|
} |
|
continue; |
|
} |
|
|
|
strlcat(Buffer, peer, s->eom); |
|
strlcat(Buffer, SESS_MEM_DELIM, s->eom); |
|
} |
|
|
|
if (!upd) { |
|
if (psVal) { |
|
strlcat(Buffer, szAttr, s->eom); |
|
strlcat(Buffer, psVal, s->eom); |
|
strlcat(Buffer, SESS_MEM_DELIM, s->eom); |
|
} else { |
|
strlcat(Buffer, csAttr, s->eom); |
|
strlcat(Buffer, SESS_MEM_DELIM, s->eom); |
|
def = IS_DEF; |
|
} |
|
def |= IS_ADD; |
|
} |
|
|
|
memcpy(s->addr, Buffer, s->eom); |
|
|
|
if (s->type == SHARED_MAP) |
|
msync(s->addr, 0, MS_SYNC | MS_INVALIDATE); |
|
|
|
INC_SEM(s); |
|
e_free(Shared); |
|
e_free(Buffer); |
|
return upd | def; |
|
} |
|
|
|
|
|
/* |
|
* sess_prepareSession() - Attach to shared memory and de-marshaling data |
|
* |
|
* @s = Session |
|
* @useDirect = Use direct shared memory if !=0 or snapshot of data to array |
|
* return: NULL error or no data, !=NULL array with variables, |
|
* after use must free resources with sess_doneSession() |
|
*/ |
|
array_t * |
|
sess_prepareSession(ait_sess_t * __restrict s, char useDirect) |
|
{ |
|
array_t *arr = NULL; |
|
sess_hdr_t *hdr; |
|
|
|
assert(s); |
|
if (!s) { |
|
io_SetErr(EINVAL, "Invalid argument\n"); |
|
return NULL; |
|
} |
|
if (s->addr) { |
|
io_SetErr(EINVAL, "Already attached memory\n"); |
|
return NULL; |
|
} |
|
|
|
ATTACH_MEMORY(s); |
|
if (!s->addr) |
|
return NULL; |
|
else |
|
hdr = (sess_hdr_t*) s->addr; |
|
if (hdr->hdr_magic != SESS_AIT_MAGIC) { |
|
DETACH_MEMORY(s); |
|
|
|
io_SetErr(EINVAL, "Shared memory not contains values with proper format\n"); |
|
return NULL; |
|
} |
|
|
|
DEC_SEM(s); |
|
s->zcpy = useDirect; |
|
arr = ait_map2vars(s->addr + sizeof(sess_hdr_t), s->eom - sizeof(sess_hdr_t), |
|
hdr->hdr_argc, useDirect); |
|
INC_SEM(s); |
|
|
|
if (!s->zcpy) |
|
DETACH_MEMORY(s); |
|
return arr; |
|
} |
|
|
|
/* |
|
* sess_doneSession() - Free resources allocated with sess_prepareSession() |
|
* |
|
* @s = Session |
|
* @arr = Array with variables for free |
|
* return: none |
|
*/ |
|
void |
|
sess_doneSession(ait_sess_t * __restrict s, array_t ** __restrict arr) |
|
{ |
|
assert(s); |
|
if (!s) { |
|
io_SetErr(EINVAL, "Invalid argument\n"); |
|
return; |
|
} |
|
|
|
if (!s->zcpy) |
|
array_Free(*arr); |
|
else |
|
DETACH_MEMORY(s); |
|
array_Destroy(arr); |
|
} |
|
|
|
/* |
|
* sess_commitSession() - Commit data to shared memory |
|
* |
|
* @s = Session |
|
* @arr = Array with variables for save |
|
* return -1 error or !=-1 size of stored variables into shared memory |
|
*/ |
|
int |
|
sess_commitSession(ait_sess_t * __restrict s, array_t * __restrict arr) |
|
{ |
|
sess_hdr_t *hdr; |
|
int ret = 0; |
|
|
|
assert(s && arr); |
|
if (!s || !arr) { |
|
io_SetErr(EINVAL, "Invalid argument\n"); |
|
return -1; |
|
} |
|
|
|
ATTACH_MEMORY(s); |
|
if (!s->addr) { |
|
DETACH_MEMORY(s); |
|
return -1; |
|
} else |
|
hdr = (sess_hdr_t*) s->addr; |
|
|
|
DEC_SEM(s); |
|
if ((ret = ait_vars2map(s->addr + sizeof(sess_hdr_t), |
|
s->eom - sizeof(sess_hdr_t), arr)) != -1) { |
|
hdr->hdr_magic = SESS_AIT_MAGIC; |
|
hdr->hdr_argc = array_Size(arr); |
|
ret += sizeof(sess_hdr_t); |
|
} |
|
INC_SEM(s); |
|
|
|
DETACH_MEMORY(s); |
|
return ret; |
|
} |