Annotation of libaitio/src/sess.c, revision 1.5

1.2       misho       1: /*************************************************************************
                      2: * (C) 2008 AITNET ltd - Sofia/Bulgaria - <misho@aitbg.com>
                      3: *  by Michael Pounov <misho@openbsd-bg.org>
                      4: *
                      5: * $Author: misho $
1.5     ! misho       6: * $Id: sess.c,v 1.4.34.1 2014/02/05 02:24:28 misho Exp $
1.2       misho       7: *
                      8: **************************************************************************
                      9: The ELWIX and AITNET software is distributed under the following
                     10: terms:
                     11: 
                     12: All of the documentation and software included in the ELWIX and AITNET
                     13: Releases is copyrighted by ELWIX - Sofia/Bulgaria <info@elwix.org>
                     14: 
1.5     ! misho      15: Copyright 2004 - 2014
1.2       misho      16:        by Michael Pounov <misho@elwix.org>.  All rights reserved.
                     17: 
                     18: Redistribution and use in source and binary forms, with or without
                     19: modification, are permitted provided that the following conditions
                     20: are met:
                     21: 1. Redistributions of source code must retain the above copyright
                     22:    notice, this list of conditions and the following disclaimer.
                     23: 2. Redistributions in binary form must reproduce the above copyright
                     24:    notice, this list of conditions and the following disclaimer in the
                     25:    documentation and/or other materials provided with the distribution.
                     26: 3. All advertising materials mentioning features or use of this software
                     27:    must display the following acknowledgement:
                     28: This product includes software developed by Michael Pounov <misho@elwix.org>
                     29: ELWIX - Embedded LightWeight unIX and its contributors.
                     30: 4. Neither the name of AITNET nor the names of its contributors
                     31:    may be used to endorse or promote products derived from this software
                     32:    without specific prior written permission.
                     33: 
                     34: THIS SOFTWARE IS PROVIDED BY AITNET AND CONTRIBUTORS ``AS IS'' AND
                     35: ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
                     36: IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
                     37: ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
                     38: FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
                     39: DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
                     40: OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
                     41: HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
                     42: LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
                     43: OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
                     44: SUCH DAMAGE.
                     45: */
                     46: #include "global.h"
                     47: 
                     48: 
                     49: /*
                     50:  * sess_initSession() - Initializing session structure, 
                     51:  *                     if session file not exists creating with specified tech
                     52:  *
                     53:  * @id = Technology using in session. SHARED_IPC IPC tech or SHARED_MAP BSD MemoryMap tech
                     54:  * @csFName = Session filename for build key and identified
                     55:  * @Sess = Session item, if =NULL allocate memory for session after use must be free!
                     56:  * return: 0 OK new key created, -1 error: no memory or file not created, 1 OK key finded
                     57: */
                     58: int
1.3       misho      59: sess_initSession(int id, const char *csFName, sess_t ** __restrict Sess)
1.2       misho      60: {
                     61:        int h, ret = 0;
                     62:        char szStr[STRSIZ];
                     63: 
                     64:        if (!csFName) {
                     65:                io_SetErr(EINVAL, "Filename is NULL");
                     66:                return -1;
                     67:        }
                     68:        if (id < SHARED_UNKNOWN || id > SHARED_MAP) {
                     69:                io_SetErr(EPROTONOSUPPORT, "Session type not supported");
                     70:                return -1;
                     71:        }
                     72: 
                     73:        if (!*Sess) {
1.3       misho      74:                *Sess = e_malloc(sizeof(sess_t));
1.2       misho      75:                if (!*Sess) {
                     76:                        LOGERR;
                     77:                        return -1;
                     78:                }
                     79:        }
1.3       misho      80:        memset(*Sess, 0, sizeof(sess_t));
                     81:        strlcpy((*Sess)->sess_name, csFName, sizeof (*Sess)->sess_name);
1.2       misho      82: 
1.3       misho      83:        h = open((*Sess)->sess_name, O_WRONLY | O_CREAT | O_EXCL, SESS_MEM_MODE);
1.2       misho      84:        if (h == -1) {
                     85:                if (errno != EEXIST) {
                     86:                        LOGERR;
                     87:                        e_free(*Sess);
                     88:                        return -1;
                     89:                }
                     90:                /* If key file exist, session already connected */
1.3       misho      91:                h = open((*Sess)->sess_name, O_RDONLY);
1.2       misho      92:                if (h == -1) {
                     93:                        LOGERR;
                     94:                        e_free(*Sess);
                     95:                        return -1;
                     96:                }
                     97:                ret = read(h, szStr, sizeof szStr);
                     98:                if (ret == -1) {
                     99:                        LOGERR;
                    100:                        close(h);
                    101:                        e_free(*Sess);
                    102:                        return -1;
                    103:                }
                    104:                if (!strncmp(szStr, "IPC@", 4) && id == SHARED_IPC) {
                    105:                        ret = 1;
                    106: 
                    107:                        (*Sess)->sess.create = (int (*)(int, long, void*, ...)) ipc_createSession;
                    108:                        (*Sess)->sess.destroy = (void (*)(void*)) ipc_destroySession;
                    109:                        (*Sess)->sess.attach = (void* (*)(void*, void*)) ipc_attachSession;
                    110:                        (*Sess)->sess.detach = (void (*)(void*)) ipc_detachSession;
                    111:                        (*Sess)->sess.notSem = (void (*)(void*)) ipc_notSemaphore;
                    112:                        (*Sess)->sess.isSemOK = (int (*)(void*)) ipc_isSemaphoreOK;
                    113:                        (*Sess)->sess.incSem = (int (*)(void*)) ipc_incSemaphore;
                    114:                        (*Sess)->sess.decSem = (int (*)(void*)) ipc_decSemaphore;
                    115:                } else if (!strncmp(szStr, "MAP@", 4) && id == SHARED_MAP) {
                    116:                        ret = 1;
                    117: 
                    118:                        (*Sess)->sess.create = (int (*)(int, long, void*, ...)) map_createSession;
                    119:                        (*Sess)->sess.destroy = (void (*)(void*)) map_destroySession;
                    120:                        (*Sess)->sess.attach = (void* (*)(void*, void*)) map_attachSession;
                    121:                        (*Sess)->sess.detach = (void (*)(void*)) map_detachSession;
                    122:                        (*Sess)->sess.notSem = (void (*)(void*)) map_notSemaphore;
                    123:                        (*Sess)->sess.isSemOK = (int (*)(void*)) map_isSemaphoreOK;
                    124:                        (*Sess)->sess.incSem = (int (*)(void*)) map_incSemaphore;
                    125:                        (*Sess)->sess.decSem = (int (*)(void*)) map_decSemaphore;
                    126:                } else {
                    127:                        io_SetErr(EPROTONOSUPPORT, 
                    128:                                        "Session type not supported or wrong session type");
                    129:                        close(h);
                    130:                        e_free(*Sess);
                    131:                        return -1;
                    132:                }
                    133:                /* key found */
                    134:        } else {
                    135:                /* Build new key & new session */
                    136:                if (id == SHARED_IPC) {
                    137:                        strlcpy(szStr, "IPC@", sizeof szStr);
                    138: 
                    139:                        (*Sess)->sess.create = (int (*)(int, long, void*, ...)) ipc_createSession;
                    140:                        (*Sess)->sess.destroy = (void (*)(void*)) ipc_destroySession;
                    141:                        (*Sess)->sess.attach = (void* (*)(void*, void*)) ipc_attachSession;
                    142:                        (*Sess)->sess.detach = (void (*)(void*)) ipc_detachSession;
                    143:                        (*Sess)->sess.notSem = (void (*)(void*)) ipc_notSemaphore;
                    144:                        (*Sess)->sess.isSemOK = (int (*)(void*)) ipc_isSemaphoreOK;
                    145:                        (*Sess)->sess.incSem = (int (*)(void*)) ipc_incSemaphore;
                    146:                        (*Sess)->sess.decSem = (int (*)(void*)) ipc_decSemaphore;
                    147:                } else if (id == SHARED_MAP) {
                    148:                        strlcpy(szStr, "MAP@", sizeof szStr);
                    149: 
                    150:                        (*Sess)->sess.create = (int (*)(int, long, void*, ...)) map_createSession;
                    151:                        (*Sess)->sess.destroy = (void (*)(void*)) map_destroySession;
                    152:                        (*Sess)->sess.attach = (void* (*)(void*, void*)) map_attachSession;
                    153:                        (*Sess)->sess.detach = (void (*)(void*)) map_detachSession;
                    154:                        (*Sess)->sess.notSem = (void (*)(void*)) map_notSemaphore;
                    155:                        (*Sess)->sess.isSemOK = (int (*)(void*)) map_isSemaphoreOK;
                    156:                        (*Sess)->sess.incSem = (int (*)(void*)) map_incSemaphore;
                    157:                        (*Sess)->sess.decSem = (int (*)(void*)) map_decSemaphore;
                    158:                } else {
                    159:                        io_SetErr(EINVAL, "Session type must be specified");
                    160:                        close(h);
                    161:                        unlink(csFName);
                    162:                        e_free(*Sess);
                    163:                        return -1;
                    164:                }
                    165:                strlcat(szStr, "ELWIX_Session ("PACKAGE_STRING")\n", sizeof szStr);
                    166:                write(h, szStr, strlen(szStr));
                    167: 
                    168:                ret = 0;
                    169:                /* new key created */
                    170:        }
                    171:        close(h);
                    172: 
1.3       misho     173:        (*Sess)->sess_type = id;
                    174:        (*Sess)->sess_zcpy = (char) ret;
1.2       misho     175:        return ret;
                    176: }
                    177: 
                    178: /*
                    179:  * sess_freeSession() - Free allocated memory for session item and delete session file if present name
                    180:  *
                    181:  * @Sess = Session item
                    182:  * return: none
                    183: */
                    184: void
1.3       misho     185: sess_freeSession(sess_t ** __restrict Sess)
1.2       misho     186: {
                    187:        if (!Sess || !(*Sess))
                    188:                return;
                    189: 
1.3       misho     190:        if ((*Sess)->sess_addr)
1.2       misho     191:                DETACH_MEMORY(*Sess);
                    192: 
                    193:        /*
                    194:        memset(&(*Sess)->sess, 0, sizeof (*Sess)->sess);
                    195: 
                    196:        (*Sess)->type = SHARED_UNKNOWN;
                    197:        */
                    198: 
                    199:        e_free(*Sess);
                    200:        *Sess = NULL;
                    201: }
                    202: 
                    203: 
                    204: /*
                    205:  * map_createSession() - MMAP Created session and allocated resources
                    206:  *
1.3       misho     207:  * @nSeed = Seed for securing key, if =SESS_OPT_SEED must add ready for use key
1.2       misho     208:  * @nSize = Allocated shared memory size in bytes
                    209:  * @Sess = Session item
                    210:  * @... = If nSeed == -1 add ready for use key value
                    211:  * return: 0 Ok successful, -1 error: not allocated resources
                    212: */
                    213: int
1.3       misho     214: map_createSession(int nSeed, long nSize, sess_t * __restrict Sess, ...)
1.2       misho     215: {
                    216:        char szSName[2][FILENAME_MAX];
                    217:        va_list lst;
                    218: 
1.3       misho     219:        if (!Sess || !*Sess->sess_name)
1.2       misho     220:                return -1;
                    221: 
1.3       misho     222:        if (nSeed != SESS_OPT_SEED) {
1.2       misho     223:                /* genkey */
1.3       misho     224:                Sess->sess_key = ftok(Sess->sess_name, nSeed);
                    225:                if (Sess->sess_key == -1) {
1.2       misho     226:                        LOGERR;
                    227:                        return -1;
                    228:                }
                    229:        } else {
                    230:                /* get key from va_args */
                    231:                va_start(lst, Sess);
1.3       misho     232:                Sess->sess_key = va_arg(lst, key_t);
1.2       misho     233:                va_end(lst);
                    234:        }
                    235: 
                    236:        /* build semaphore & shared memory name */
                    237:        memset(szSName, 0, sizeof szSName);
1.3       misho     238:        snprintf(szSName[0], SEMNAME_MAX, "/%X.ANS", (u_int) Sess->sess_key);
1.2       misho     239: #ifdef HAVE_SHM_OPEN
1.3       misho     240:        snprintf(szSName[1], FILENAME_MAX, "/%s-%x.ANM", Sess->sess_name, (u_int) Sess->sess_key);
1.2       misho     241: #else
1.3       misho     242:        snprintf(szSName[1], FILENAME_MAX, "%s-%x.ANM", Sess->sess_name, (u_int) Sess->sess_key);
1.2       misho     243: #endif
                    244: 
                    245:        /* create semaphore & add 1 */
1.3       misho     246:        Sess->sess_id.sid = sem_open(szSName[0], O_CREAT, SESS_MEM_MODE);
                    247:        if (Sess->sess_id.sid == SEM_FAILED) {
1.2       misho     248:                LOGERR;
                    249:                map_destroySession(Sess);
                    250:                return -1;
                    251:        }
                    252:        /* if is new shared memory session, init sempahore with 1 */
1.3       misho     253:        if (!Sess->sess_zcpy)
                    254:                sem_post(Sess->sess_id.sid);
1.2       misho     255: 
                    256:        /* create file for shared memory storage */
                    257: #ifdef HAVE_SHM_OPEN
1.3       misho     258:        Sess->sess_mem.fd = shm_open(szSName[1], O_RDWR | O_CREAT, SESS_MEM_MODE);
1.2       misho     259: #else
1.3       misho     260:        Sess->sess_mem.fd = open(szSName[1], O_RDWR | O_CREAT, SESS_MEM_MODE);
1.2       misho     261: #endif
1.3       misho     262:        if (Sess->sess_mem.fd == -1) {
1.2       misho     263:                LOGERR;
                    264:                map_destroySession(Sess);
                    265:                return -1;
                    266:        }
1.3       misho     267:        if (!Sess->sess_zcpy) {
                    268: /* #ifdef HAVE_SHM_OPEN */
                    269:                if (ftruncate(Sess->sess_mem.fd, nSize) == -1) {
1.2       misho     270:                        LOGERR;
                    271:                        map_destroySession(Sess);
                    272:                        return -1;
                    273:                }
1.3       misho     274: /* #else */
1.2       misho     275:                /* if is new shared memory session, fill file with zeros */
1.3       misho     276:                /*
                    277:                if (lseek(Sess->sess_mem.fd, nSize - 1, SEEK_SET) == -1) {
1.2       misho     278:                        LOGERR;
                    279:                        map_destroySession(Sess);
                    280:                        return -1;
                    281:                } else
1.3       misho     282:                        write(Sess->sess_mem.fd, "", 1);
                    283:                lseek(Sess->sess_mem.fd, 0, SEEK_SET);
1.2       misho     284: #endif
1.3       misho     285: */
1.2       misho     286:        }
1.3       misho     287:        Sess->sess_size = nSize;
1.2       misho     288: 
1.3       misho     289:        return (int) Sess->sess_zcpy;
1.2       misho     290: }
                    291: 
                    292: /*
                    293:  * map_destroySession() - MMAP free shared resources
                    294:  *
                    295:  * @Sess = Session item
                    296:  * return: none
                    297: */
                    298: void
1.3       misho     299: map_destroySession(sess_t * __restrict Sess)
1.2       misho     300: {
                    301:        char szSName[2][FILENAME_MAX];
                    302: 
1.3       misho     303:        if (!Sess || sess_isAttached(Sess) || !*Sess->sess_name)
1.2       misho     304:                return;
                    305: 
                    306:        memset(szSName, 0, sizeof szSName);
1.3       misho     307:        snprintf(szSName[0], SEMNAME_MAX, "/%X.ANS", (u_int) Sess->sess_key);
1.2       misho     308: #ifdef HAVE_SHM_UNLINK
1.3       misho     309:        snprintf(szSName[1], FILENAME_MAX, "/%s-%x.ANM", Sess->sess_name, (u_int) Sess->sess_key);
1.2       misho     310: #else
1.3       misho     311:        snprintf(szSName[1], FILENAME_MAX, "%s-%x.ANM", Sess->sess_name, (u_int) Sess->sess_key);
1.2       misho     312: #endif
                    313: 
1.3       misho     314:        if (Sess->sess_id.sid != SEM_FAILED) {
                    315:                sem_close(Sess->sess_id.sid);
1.2       misho     316:                sem_unlink(szSName[0]);
                    317:        }
1.3       misho     318:        if (Sess->sess_mem.fd > 2) {
                    319:                close(Sess->sess_mem.fd);
1.2       misho     320: #ifdef HAVE_SHM_UNLINK
                    321:                shm_unlink(szSName[1]);
                    322: #else
                    323:                unlink(szSName[1]);
                    324: #endif
                    325:        }
1.3       misho     326:        unlink(Sess->sess_name);
                    327:        memset(Sess->sess_name, 0, sizeof Sess->sess_name);
                    328:        Sess->sess_size ^= Sess->sess_size;
                    329:        Sess->sess_key ^= Sess->sess_key;
1.2       misho     330: }
                    331: 
                    332: /*
                    333:  * ipc_createSession() - IPC Created session and allocated resources
                    334:  *
1.3       misho     335:  * @nSeed = Seed for securing key, if =SESS_OPT_SEED must add ready for use key
1.2       misho     336:  * @nSize = Allocated shared memory size in bytes
                    337:  * @Sess = Session item
                    338:  * @... = If nSeed == -1 add ready for use key value
                    339:  * return: 0 Ok successful, -1 error: not allocated resources
                    340:  */
                    341: int
1.3       misho     342: ipc_createSession(int nSeed, long nSize, sess_t * __restrict Sess, ...)
1.2       misho     343: {
                    344:        union semun sems;
                    345:        va_list lst;
                    346: 
1.3       misho     347:        if (!Sess || !*Sess->sess_name)
1.2       misho     348:                return -1;
                    349: 
                    350:        if (nSeed != -1) {
                    351:                /* genkey */
1.3       misho     352:                Sess->sess_key = ftok(Sess->sess_name, nSeed);
                    353:                if (Sess->sess_key == -1) {
1.2       misho     354:                        LOGERR;
                    355:                        return -1;
                    356:                }
                    357:        } else {
                    358:                /* get key from va_args */
                    359:                va_start(lst, Sess);
1.3       misho     360:                Sess->sess_key = va_arg(lst, key_t);
1.2       misho     361:                va_end(lst);
                    362:        }
                    363: 
                    364:        /* create semaphore */
1.3       misho     365:        Sess->sess_id.semid = semget(Sess->sess_key, 1, SESS_MEM_MODE | IPC_CREAT);
                    366:        if (Sess->sess_id.semid == -1) {
1.2       misho     367:                LOGERR;
                    368:                ipc_destroySession(Sess);
                    369:                return -1;
                    370:        }
                    371:        /* if is new shared memory session, init sempahore with 1 */
1.3       misho     372:        if (!Sess->sess_zcpy) {
1.2       misho     373:                sems.val = 1;
1.3       misho     374:                if (semctl(Sess->sess_id.semid, 0, SETVAL, sems) == -1) {
1.2       misho     375:                        LOGERR;
                    376:                        ipc_destroySession(Sess);
                    377:                        return -1;
                    378:                }
                    379:        }
                    380: 
                    381:        /* create shared memory object */
1.3       misho     382:        Sess->sess_mem.shmid = shmget(Sess->sess_key, nSize, SESS_MEM_MODE | IPC_CREAT);
                    383:        if (Sess->sess_mem.shmid == -1) {
1.2       misho     384:                LOGERR;
                    385:                ipc_destroySession(Sess);
                    386:                return -1;
                    387:        } else
1.3       misho     388:                Sess->sess_size = nSize;
1.2       misho     389: 
1.3       misho     390:        return (int) Sess->sess_zcpy;
1.2       misho     391: }
                    392: 
                    393: /*
                    394:  * ipc_destroySession() - IPC free shared resources
                    395:  *
                    396:  * @Sess = Session item
                    397:  * return: none
                    398:  */
                    399: void
1.3       misho     400: ipc_destroySession(sess_t * __restrict Sess)
1.2       misho     401: {
                    402:        union semun sems;
                    403:        struct shmid_ds ds;
                    404: 
                    405:        if (!Sess || sess_isAttached(Sess))
                    406:                return;
                    407: 
1.3       misho     408:        if (Sess->sess_id.semid != -1)
                    409:                semctl(Sess->sess_id.semid, 0, IPC_RMID, &sems);
                    410:        if (Sess->sess_mem.shmid != -1)
                    411:                shmctl(Sess->sess_mem.shmid, IPC_RMID, &ds);
                    412:        unlink(Sess->sess_name);
                    413:        memset(Sess->sess_name, 0, sizeof Sess->sess_name);
                    414:        Sess->sess_size ^= Sess->sess_size;
                    415:        Sess->sess_key ^= Sess->sess_key;
1.2       misho     416: }
                    417: 
                    418: 
                    419: /*
                    420:  * map_attachSession() - MMAP Attach to shared memory & return begin address
                    421:  *
                    422:  * @s = Session item
                    423:  * @procMem = Custom start address (optionl) *default must be 0*
                    424:  * return: NULL failed attach, !=NULL begin address of memory
                    425:  */
                    426: void *
1.3       misho     427: map_attachSession(sess_t * __restrict s, void *procMem)
1.2       misho     428: {
                    429:        if (!s)
                    430:                return NULL;
                    431: 
                    432:        sync();
                    433: 
                    434:        /* attach to memory */
1.3       misho     435:        s->sess_addr = mmap(procMem, s->sess_size, PROT_READ | PROT_WRITE, MAP_SHARED, s->sess_mem.fd, 0);
                    436:        if (s->sess_addr == MAP_FAILED) {
1.2       misho     437:                LOGERR;
1.3       misho     438:                s->sess_addr = NULL;
1.2       misho     439:        }
                    440: 
1.3       misho     441:        return s->sess_addr;
1.2       misho     442: }
                    443: 
                    444: /*
                    445:  * map_detachSession() - MMAP Detach from shared memory
                    446:  *
                    447:  * @s = Session item
                    448:  * return: none
                    449:  */
                    450: void
1.3       misho     451: map_detachSession(sess_t * __restrict s)
1.2       misho     452: {
                    453:        if (!s)
                    454:                return;
                    455: 
1.3       misho     456:        msync(s->sess_addr, 0, MS_SYNC | MS_INVALIDATE);
1.2       misho     457: 
1.3       misho     458:        if (s->sess_size) {
                    459:                munmap(s->sess_addr, s->sess_size);
                    460:                s->sess_addr = NULL;
1.2       misho     461:        }
                    462: }
                    463: 
                    464: /*
                    465:  * ipc_attachSession() - IPC Attach to shared memory & return begin address
                    466:  *
                    467:  * @s = Session item
                    468:  * @procMem = Custom start address (optionl) *default must be 0*
                    469:  * return: NULL failed attach, !=NULL begin address of memory
                    470:  */
                    471: void *
1.3       misho     472: ipc_attachSession(sess_t * __restrict s, void *procMem)
1.2       misho     473: {
                    474:        if (!s)
                    475:                return NULL;
                    476: 
1.3       misho     477:        s->sess_addr = shmat(s->sess_mem.shmid, procMem, 0);
                    478:        if (s->sess_addr == (void*) -1) {
1.2       misho     479:                LOGERR;
1.3       misho     480:                s->sess_addr = NULL;
1.2       misho     481:        }
                    482: 
1.3       misho     483:        return s->sess_addr;
1.2       misho     484: }
                    485: 
                    486: /*
                    487:  * ipc_detachSession() - IPC Detach from shared memory
                    488:  *
                    489:  * @s = Session item
                    490:  * return: none
                    491:  */
                    492: void
1.3       misho     493: ipc_detachSession(sess_t * __restrict s)
1.2       misho     494: {
                    495:        if (!s)
                    496:                return;
                    497: 
1.3       misho     498:        if (s->sess_size) {
                    499:                shmdt(s->sess_addr);
                    500:                s->sess_addr = NULL;
1.2       misho     501:        }
                    502: }
                    503: 
                    504: /*
                    505:  * sess_isAttached() - Check for attached shared memory
                    506:  *
                    507:  * @s = Session item
                    508:  * return: -1 null session item, 0 not attached, 1 attached memory
                    509:  */
1.4       misho     510: int
1.3       misho     511: sess_isAttached(sess_t * __restrict s)
1.2       misho     512: {
                    513:        if (!s)
                    514:                return -1;
                    515: 
1.3       misho     516:        return !!s->sess_addr;
1.2       misho     517: }
                    518: 
                    519: 
                    520: /*
                    521:  * map_notSemaphore() - MMAP negative block if semaphore isn`t signaled
                    522:  *
                    523:  * @s = Session item
                    524:  * return: none
                    525:  */
                    526: void
1.3       misho     527: map_notSemaphore(sess_t * __restrict s)
1.2       misho     528: {
                    529:        int i = -1;
                    530: 
                    531:        if (!s)
                    532:                return;
                    533: 
1.3       misho     534:        sem_getvalue(s->sess_id.sid, &i);
                    535:        for (; i; i--)
                    536:                sem_wait(s->sess_id.sid);
1.2       misho     537: }
                    538: 
                    539: /*
                    540:  * map_isSemaphoreOK() - MMAP Check semaphore
                    541:  *
                    542:  * @s = Session item
                    543:  * return: -1 error: can`t return semaphore, 0 = false, 1 = true
                    544:  */
                    545: int
1.3       misho     546: map_isSemaphoreOK(sess_t * __restrict s)
1.2       misho     547: {
                    548:        int val = -1;
                    549: 
                    550:        if (!s)
                    551:                return -1;
                    552: 
1.3       misho     553:        return sem_getvalue(s->sess_id.sid, &val) + 1;
1.2       misho     554: }
                    555: 
                    556: /*
                    557:  * map_incSemaphore() - MMAP unblock semaphore, increment semaphore
                    558:  *
                    559:  * @s = Session item
                    560:  * return: 0 Ok, -1 error: can`t increment 
                    561:  */
                    562: int
1.3       misho     563: map_incSemaphore(sess_t * __restrict s)
1.2       misho     564: {
                    565:        if (!s)
                    566:                return -1;
                    567: 
1.3       misho     568:        return sem_post(s->sess_id.sid);
1.2       misho     569: }
                    570: 
                    571: /*
                    572:  * map_decSemaphore() - MMAP block semaphore, decrement semaphore
                    573:  *
                    574:  * @s = Session item
                    575:  * return: 0 Ok, -1 error: can`t decrement 
                    576:  */
                    577: int
1.3       misho     578: map_decSemaphore(sess_t * __restrict s)
1.2       misho     579: {
                    580:        if (!s)
                    581:                return -1;
                    582: 
1.3       misho     583:        return sem_wait(s->sess_id.sid);
1.2       misho     584: }
                    585: 
                    586: /*
                    587:  * ipc_notSemaphore() - IPC negative block if semaphore isn`t signaled
                    588:  *
                    589:  * @s = Session item
                    590:  * return: none
                    591:  */
                    592: void
1.3       misho     593: ipc_notSemaphore(sess_t * __restrict s)
1.2       misho     594: {
                    595:        struct sembuf sb = { 0, 0, 0 };
                    596: 
                    597:        if (s)
1.3       misho     598:                semop(s->sess_id.semid, &sb, 1);
1.2       misho     599: }
                    600: 
                    601: /*
                    602:  * ipc_isSemaphoreOK() - IPC Check semaphore
                    603:  *
                    604:  * @s = Session item
                    605:  * return: -1 error: can`t return semaphore, 0 = false, 1 = true
                    606:  */
                    607: int
1.3       misho     608: ipc_isSemaphoreOK(sess_t * __restrict s)
1.2       misho     609: {
                    610:        struct sembuf sb = { 0, 0, IPC_NOWAIT };
                    611: 
                    612:        if (!s)
                    613:                return -1;
                    614: 
1.3       misho     615:        return semop(s->sess_id.semid, &sb, 1) + 1;
1.2       misho     616: }
                    617: 
                    618: /*
                    619:  * ipc_incSemaphore() - IPC unblock semaphore, increment semaphore
                    620:  *
                    621:  * @s = Session item
                    622:  * return: 0 Ok, -1 error: can`t increment 
                    623:  */
                    624: int
1.3       misho     625: ipc_incSemaphore(sess_t * __restrict s)
1.2       misho     626: {
                    627:        struct sembuf sb = { 0, 1, 0 };
                    628: 
                    629:        if (!s)
                    630:                return -1;
                    631: 
1.3       misho     632:        return semop(s->sess_id.semid, &sb, 1);
1.2       misho     633: }
                    634: 
                    635: /*
                    636:  * ipc_decSemaphore() - IPC block semaphore, decrement semaphore
                    637:  *
                    638:  * @s = Session item
                    639:  * return: 0 Ok, -1 error: can`t decrement 
                    640:  */
                    641: int
1.3       misho     642: ipc_decSemaphore(sess_t * __restrict s)
1.2       misho     643: {
                    644:        struct sembuf sb = { 0, -1, 0 };
                    645: 
                    646:        if (!s)
                    647:                return -1;
                    648: 
1.3       misho     649:        return semop(s->sess_id.semid, &sb, 1);
1.2       misho     650: }
                    651: 
                    652: /* --- A/V management --- */
                    653: 
                    654: /*
                    655:  * sess_GetValues() - Get all values from session shared memory
                    656:  *
                    657:  * @s = Session item
1.3       misho     658:  * @Vals = Return array strings
                    659:  * return: -1 error: in parameter, !=-1 count of returned strings in Vals 
                    660:  *             (must call ait_freeVars() after use!)
1.2       misho     661:  */
                    662: int
1.3       misho     663: sess_GetValues(sess_t * __restrict s, array_t ** __restrict Vals)
1.2       misho     664: {
                    665:        register int i;
1.3       misho     666:        char *Shared = NULL;
1.2       misho     667:        char *peer, *p_brk;
1.3       misho     668:        ait_val_t *v;
1.2       misho     669: 
1.3       misho     670:        if (!s || !Vals)
1.2       misho     671:                return -1;
1.3       misho     672:        *Vals = ait_allocVars(0);
                    673:        if (!*Vals) {
                    674:                io_SetErr(elwix_GetErrno(), "%s", elwix_GetError());
1.2       misho     675:                return -1;
1.3       misho     676:        }
1.2       misho     677: 
                    678:        /* allocated memory & mirrored shared memory into this */
1.3       misho     679:        Shared = e_malloc(s->sess_size);
1.2       misho     680:        if (!Shared) {
                    681:                LOGERR;
1.3       misho     682:                ait_freeVars(Vals);
1.2       misho     683:                return -1;
1.3       misho     684:        }
                    685: 
                    686:        DEC_SEM(s);
                    687:        memcpy(Shared, s->sess_addr, s->sess_size);
                    688:        INC_SEM(s);
1.2       misho     689: 
                    690:        for (i = 0, peer = strtok_r(Shared, SESS_MEM_DELIM"\r\n", &p_brk); peer; 
                    691:                        peer = strtok_r(NULL, SESS_MEM_DELIM"\r\n", &p_brk)) {
                    692:                if (!strchr(peer, '='))
                    693:                        continue;
                    694:                else
                    695:                        i++;
                    696: 
1.3       misho     697:                if (!(v = ait_allocVar())) {
                    698:                        io_SetErr(elwix_GetErrno(), "%s", elwix_GetError());
1.2       misho     699:                        e_free(Shared);
1.3       misho     700:                        ait_freeVars(Vals);
1.2       misho     701:                        return -1;
                    702:                } else
1.3       misho     703:                        AIT_SET_STR(v, peer);
1.2       misho     704: 
1.3       misho     705:                array_Push(*Vals, v, 0);
1.2       misho     706:        }
                    707: 
                    708:        e_free(Shared);
1.3       misho     709:        ait_hashKeyVars(*Vals);
1.2       misho     710:        return i;
                    711: }
                    712: 
                    713: /*
                    714:  * sess_GetValue() - Get value from session shared memory from attribute
                    715:  *
                    716:  * @s = Session item
                    717:  * @csAttr = Attribute for search
1.3       misho     718:  * @v = Return string value and after use must call ait_freeVar(), also may be =NULL
1.2       misho     719:  * return: 0 not found, -1 error: in parameter, >0 get position, 
                    720:  *     if define item merged with IS_DEF
                    721:  */
                    722: int
1.3       misho     723: sess_GetValue(sess_t * __restrict s, const char *csAttr, ait_val_t ** __restrict v)
1.2       misho     724: {
                    725:        register int i;
1.3       misho     726:        int def = 0;
1.2       misho     727:        char *Shared = NULL;
                    728:        char *peer, *p_brk, *a_brk, *attr, *val;
                    729: 
                    730:        if (!s || !csAttr || !*csAttr)
                    731:                return -1;
1.3       misho     732:        if (v) {
                    733:                if (!(*v = ait_allocVar())) {
                    734:                        io_SetErr(elwix_GetErrno(), "%s", elwix_GetError());
1.2       misho     735:                        return -1;
1.3       misho     736:                } else
                    737:                        AIT_INIT_VAL2(*v, string);
1.2       misho     738:        }
                    739: 
                    740:        /* allocated memory & mirrored shared memory into this */
1.3       misho     741:        Shared = e_malloc(s->sess_size);
1.2       misho     742:        if (!Shared) {
                    743:                LOGERR;
1.3       misho     744:                ait_freeVar(v);
1.2       misho     745:                return -1;
1.3       misho     746:        }
                    747: 
                    748:        DEC_SEM(s);
                    749:        memcpy(Shared, s->sess_addr, s->sess_size);
                    750:        INC_SEM(s);
1.2       misho     751: 
                    752:        for (i = 1, peer = strtok_r(Shared, SESS_MEM_DELIM"\r\n", &p_brk); peer; 
                    753:                        i++, peer = strtok_r(NULL, SESS_MEM_DELIM"\r\n", &p_brk)) {
                    754:                attr = strtok_r(peer, "=\r\n", &a_brk);
1.3       misho     755:                if (attr && !strncmp(attr, csAttr, SESS_MAX_ATTRIBUTE - 1)) {
1.2       misho     756:                        val = strtok_r(NULL, "=\r\n", &a_brk);
1.3       misho     757:                        if (val && strlen(val))
                    758:                                AIT_SET_STR(*v, val);
                    759:                        else
                    760:                                def = SESS_F_DEF;
1.2       misho     761: 
                    762:                        e_free(Shared);
                    763:                        return i | def;
                    764:                }
                    765:        }
                    766: 
                    767:        e_free(Shared);
                    768:        return 0;
                    769: }
                    770: 
                    771: /*
                    772:  * sess_DelValue() - Delete item from session shared memory
                    773:  *
                    774:  * @s = Session item
                    775:  * @csAttr = Attribute for erasing
1.3       misho     776:  * return: -1 error: in parameter or !=-1 deleted items
1.2       misho     777:  */
                    778: int
1.3       misho     779: sess_DelValue(sess_t * __restrict s, const char *csAttr)
1.2       misho     780: {
                    781:        register int i;
1.3       misho     782:        int attrlen, d = 0;
                    783:        char *Buffer, *Shared, szAttr[SESS_MAX_ATTRIBUTE];
1.2       misho     784:        char *peer, *p_brk;
                    785: 
                    786:        if (!s || !csAttr || !*csAttr)
                    787:                return -1;
                    788:        else
                    789:                attrlen = strlen(csAttr);
                    790:        Buffer = Shared = NULL;
                    791:        strlcpy(szAttr, csAttr, sizeof szAttr);
                    792:        strlcat(szAttr, "=", sizeof szAttr);
                    793: 
1.3       misho     794:        Buffer = e_malloc(s->sess_size);
1.2       misho     795:        if (!Buffer) {
                    796:                LOGERR;
                    797:                return -1;
                    798:        } else
1.3       misho     799:                memset(Buffer, 0, s->sess_size);
                    800:        Shared = e_malloc(s->sess_size);
1.2       misho     801:        if (!Shared) {
                    802:                LOGERR;
                    803:                e_free(Buffer);
                    804:                return -1;
                    805:        } else {
                    806:                DEC_SEM(s);
1.3       misho     807:                memcpy(Shared, s->sess_addr, s->sess_size);
1.2       misho     808:        }
                    809: 
                    810:        for (i = 1, peer = strtok_r(Shared, SESS_MEM_DELIM"\r\n", &p_brk); peer; 
                    811:                        i++, peer = strtok_r(NULL, SESS_MEM_DELIM"\r\n", &p_brk)) {
                    812:                if (!strncmp(peer, csAttr, attrlen))
1.3       misho     813:                        if (peer[attrlen] == '=' || !peer[attrlen]) {
                    814:                                d++;
1.2       misho     815:                                continue;
1.3       misho     816:                        }
1.2       misho     817: 
1.3       misho     818:                strlcat(Buffer, peer, s->sess_size);
                    819:                strlcat(Buffer, SESS_MEM_DELIM, s->sess_size);
1.2       misho     820:        }
                    821: 
1.3       misho     822:        memcpy(s->sess_addr, Buffer, s->sess_size);
1.2       misho     823: 
1.3       misho     824:        if (s->sess_type == SHARED_MAP)
                    825:                msync(s->sess_addr, 0, MS_SYNC | MS_INVALIDATE);
1.2       misho     826: 
                    827:        INC_SEM(s);
                    828:        e_free(Shared);
                    829:        e_free(Buffer);
1.3       misho     830:        return d;
1.2       misho     831: }
                    832: 
                    833: /*
                    834:  * sess_SetValue() - Set item into session shared memory or update if exists
                    835:  *
                    836:  * @s = Session item
                    837:  * @csAttr = Attribute
                    838:  * @psVal = Value
                    839:  * return: 0 nothing, -1 error: in parameter, 
1.3       misho     840:        >0 set position, if added new item merged with SESS_F_ADD and 
                    841:        if just define item merged with SESS_F_DEF
1.2       misho     842:  */
                    843: int
1.3       misho     844: sess_SetValue(sess_t * __restrict s, const char *csAttr, const char *psVal)
1.2       misho     845: {
                    846:        register int i;
1.3       misho     847:        int upd = 0, def = 0;
                    848:        char *Buffer, *Shared, szAttr[SESS_MAX_ATTRIBUTE];
1.2       misho     849:        char *peer, *p_brk;
                    850: 
                    851:        if (!s || !csAttr || !*csAttr)
                    852:                return -1;
                    853:        else
                    854:                Buffer = Shared = NULL;
                    855:        strlcpy(szAttr, csAttr, sizeof szAttr);
                    856:        strlcat(szAttr, "=", sizeof szAttr);
                    857: 
1.3       misho     858:        Buffer = e_malloc(s->sess_size);
1.2       misho     859:        if (!Buffer) {
                    860:                LOGERR;
                    861:                return -1;
                    862:        } else
1.3       misho     863:                memset(Buffer, 0, s->sess_size);
                    864:        Shared = e_malloc(s->sess_size);
1.2       misho     865:        if (!Shared) {
                    866:                LOGERR;
                    867:                e_free(Buffer);
                    868:                return -1;
                    869:        } else {
                    870:                DEC_SEM(s);
1.3       misho     871:                memcpy(Shared, s->sess_addr, s->sess_size);
1.2       misho     872:        }
                    873: 
1.3       misho     874:        for (i = 1, peer = strtok_r(Shared, SESS_MEM_DELIM"\r\n", &p_brk); peer; 
                    875:                        i++, peer = strtok_r(NULL, SESS_MEM_DELIM"\r\n", &p_brk))
1.2       misho     876:                if (!strncmp(peer, szAttr, strlen(szAttr))) {
                    877:                        upd++;
                    878:                        if (psVal) {
1.3       misho     879:                                strlcat(Buffer, szAttr, s->sess_size);
                    880:                                strlcat(Buffer, psVal, s->sess_size);
                    881:                                strlcat(Buffer, SESS_MEM_DELIM, s->sess_size);
1.2       misho     882:                        } else {
1.3       misho     883:                                strlcat(Buffer, csAttr, s->sess_size);
                    884:                                strlcat(Buffer, SESS_MEM_DELIM, s->sess_size);
                    885:                                def = SESS_F_DEF;
1.2       misho     886:                        }
1.3       misho     887:                } else {
                    888:                        strlcat(Buffer, peer, s->sess_size);
                    889:                        strlcat(Buffer, SESS_MEM_DELIM, s->sess_size);
1.2       misho     890:                }
                    891: 
                    892:        if (!upd) {
                    893:                if (psVal) {
1.3       misho     894:                        strlcat(Buffer, szAttr, s->sess_size);
                    895:                        strlcat(Buffer, psVal, s->sess_size);
                    896:                        strlcat(Buffer, SESS_MEM_DELIM, s->sess_size);
1.2       misho     897:                } else {
1.3       misho     898:                        strlcat(Buffer, csAttr, s->sess_size);
                    899:                        strlcat(Buffer, SESS_MEM_DELIM, s->sess_size);
                    900:                        def = SESS_F_DEF;
1.2       misho     901:                }
1.3       misho     902:                def |= SESS_F_ADD;
1.2       misho     903:        }
                    904: 
1.3       misho     905:        memcpy(s->sess_addr, Buffer, s->sess_size);
1.2       misho     906: 
1.3       misho     907:        if (s->sess_type == SHARED_MAP)
                    908:                msync(s->sess_addr, 0, MS_SYNC | MS_INVALIDATE);
1.2       misho     909: 
                    910:        INC_SEM(s);
                    911:        e_free(Shared);
                    912:        e_free(Buffer);
                    913:        return upd | def;
                    914: }
                    915: 
                    916: 
                    917: /*
                    918:  * sess_prepareSession() - Attach to shared memory and de-marshaling data
                    919:  *
                    920:  * @s = Session
                    921:  * @useDirect = Use direct shared memory if !=0 or snapshot of data to array
                    922:  * return: NULL error or no data, !=NULL array with variables, 
                    923:  *             after use must free resources with sess_doneSession()
                    924:  */
                    925: array_t *
1.3       misho     926: sess_prepareSession(sess_t * __restrict s, char useDirect)
1.2       misho     927: {
                    928:        array_t *arr = NULL;
                    929:        sess_hdr_t *hdr;
                    930: 
                    931:        if (!s) {
                    932:                io_SetErr(EINVAL, "Invalid argument\n");
                    933:                return NULL;
                    934:        }
1.3       misho     935:        if (s->sess_addr) {
1.2       misho     936:                io_SetErr(EINVAL, "Already attached memory\n");
                    937:                return NULL;
                    938:        }
                    939: 
1.3       misho     940:        if (!ATTACH_MEMORY(s))
1.2       misho     941:                return NULL;
                    942:        else
1.3       misho     943:                hdr = (sess_hdr_t*) s->sess_addr;
1.2       misho     944:        if (hdr->hdr_magic != SESS_AIT_MAGIC) {
                    945:                DETACH_MEMORY(s);
                    946: 
                    947:                io_SetErr(EINVAL, "Shared memory not contains values with proper format\n");
                    948:                return NULL;
                    949:        }
                    950: 
                    951:        DEC_SEM(s);
1.3       misho     952:        s->sess_zcpy = useDirect;
                    953:        arr = ait_map2vars(s->sess_addr + sizeof(sess_hdr_t), s->sess_size - sizeof(sess_hdr_t), 
                    954:                        hdr->hdr_argc, s->sess_zcpy);
1.2       misho     955:        INC_SEM(s);
                    956: 
1.3       misho     957:        if (!s->sess_zcpy)
1.2       misho     958:                DETACH_MEMORY(s);
                    959:        return arr;
                    960: }
                    961: 
                    962: /*
                    963:  * sess_doneSession() - Free resources allocated with sess_prepareSession()
                    964:  *
                    965:  * @s = Session
                    966:  * @arr = Array with variables for free
                    967:  * return: none
                    968:  */
                    969: void
1.3       misho     970: sess_doneSession(sess_t * __restrict s, array_t ** __restrict arr)
1.2       misho     971: {
                    972:        if (!s) {
                    973:                io_SetErr(EINVAL, "Invalid argument\n");
                    974:                return;
                    975:        }
                    976: 
1.3       misho     977:        if (!s->sess_zcpy)
1.2       misho     978:                array_Free(*arr);
                    979:        else
                    980:                DETACH_MEMORY(s);
                    981:        array_Destroy(arr);
                    982: }
                    983: 
                    984: /*
                    985:  * sess_commitSession() - Commit data to shared memory
                    986:  *
                    987:  * @s = Session
                    988:  * @arr = Array with variables for save
                    989:  * return -1 error or !=-1 size of stored variables into shared memory
                    990:  */
                    991: int
1.3       misho     992: sess_commitSession(sess_t * __restrict s, array_t * __restrict arr)
1.2       misho     993: {
                    994:        sess_hdr_t *hdr;
                    995:        int ret = 0;
                    996: 
                    997:        if (!s || !arr) {
                    998:                io_SetErr(EINVAL, "Invalid argument\n");
                    999:                return -1;
                   1000:        }
                   1001: 
1.3       misho    1002:        if (!ATTACH_MEMORY(s)) {
1.2       misho    1003:                DETACH_MEMORY(s);
                   1004:                return -1;
                   1005:        } else
1.3       misho    1006:                hdr = (sess_hdr_t*) s->sess_addr;
1.2       misho    1007: 
                   1008:        DEC_SEM(s);
1.3       misho    1009:        if ((ret = ait_vars2map(s->sess_addr + sizeof(sess_hdr_t), 
                   1010:                                        s->sess_size - sizeof(sess_hdr_t), arr)) != -1) {
1.2       misho    1011:                hdr->hdr_magic = SESS_AIT_MAGIC;
                   1012:                hdr->hdr_argc = array_Size(arr);
                   1013:                ret += sizeof(sess_hdr_t);
                   1014:        }
                   1015:        INC_SEM(s);
                   1016: 
                   1017:        DETACH_MEMORY(s);
                   1018:        return ret;
                   1019: }

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>