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

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.2.2.2 ! misho       6: * $Id: sess.c,v 1.2.2.1 2013/03/19 17:02:58 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: 
                     15: Copyright 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2013
                     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.2.2.1   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.2.2.1   misho      74:                *Sess = e_malloc(sizeof(sess_t));
1.2       misho      75:                if (!*Sess) {
                     76:                        LOGERR;
                     77:                        return -1;
                     78:                }
                     79:        }
1.2.2.1   misho      80:        memset(*Sess, 0, sizeof(sess_t));
                     81:        strlcpy((*Sess)->sess_name, csFName, sizeof (*Sess)->sess_name);
1.2       misho      82: 
1.2.2.1   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.2.2.1   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.2.2.1   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.2.2.1   misho     185: sess_freeSession(sess_t ** __restrict Sess)
1.2       misho     186: {
                    187:        if (!Sess || !(*Sess))
                    188:                return;
                    189: 
1.2.2.1   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.2.2.1   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.2.2.1   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.2.2.1   misho     219:        if (!Sess || !*Sess->sess_name)
1.2       misho     220:                return -1;
                    221: 
1.2.2.1   misho     222:        if (nSeed != SESS_OPT_SEED) {
1.2       misho     223:                /* genkey */
1.2.2.1   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.2.2.1   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.2.2.1   misho     238:        snprintf(szSName[0], SEMNAME_MAX, "/%X.ANS", (u_int) Sess->sess_key);
1.2       misho     239: #ifdef HAVE_SHM_OPEN
1.2.2.1   misho     240:        snprintf(szSName[1], FILENAME_MAX, "/%s-%x.ANM", Sess->sess_name, (u_int) Sess->sess_key);
1.2       misho     241: #else
1.2.2.1   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.2.2.1   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.2.2.1   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.2.2.1   misho     258:        Sess->sess_mem.fd = shm_open(szSName[1], O_RDWR | O_CREAT, SESS_MEM_MODE);
1.2       misho     259: #else
1.2.2.1   misho     260:        Sess->sess_mem.fd = open(szSName[1], O_RDWR | O_CREAT, SESS_MEM_MODE);
1.2       misho     261: #endif
1.2.2.1   misho     262:        if (Sess->sess_mem.fd == -1) {
1.2       misho     263:                LOGERR;
                    264:                map_destroySession(Sess);
                    265:                return -1;
                    266:        }
1.2.2.1   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.2.2.1   misho     274: /* #else */
1.2       misho     275:                /* if is new shared memory session, fill file with zeros */
1.2.2.1   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.2.2.1   misho     282:                        write(Sess->sess_mem.fd, "", 1);
                    283:                lseek(Sess->sess_mem.fd, 0, SEEK_SET);
1.2       misho     284: #endif
1.2.2.1   misho     285: */
1.2       misho     286:        }
1.2.2.1   misho     287:        Sess->sess_size = nSize;
1.2       misho     288: 
1.2.2.1   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.2.2.1   misho     299: map_destroySession(sess_t * __restrict Sess)
1.2       misho     300: {
                    301:        char szSName[2][FILENAME_MAX];
                    302: 
1.2.2.1   misho     303:        if (!Sess || sess_isAttached(Sess) || !*Sess->sess_name)
1.2       misho     304:                return;
                    305: 
                    306:        memset(szSName, 0, sizeof szSName);
1.2.2.1   misho     307:        snprintf(szSName[0], SEMNAME_MAX, "/%X.ANS", (u_int) Sess->sess_key);
1.2       misho     308: #ifdef HAVE_SHM_UNLINK
1.2.2.1   misho     309:        snprintf(szSName[1], FILENAME_MAX, "/%s-%x.ANM", Sess->sess_name, (u_int) Sess->sess_key);
1.2       misho     310: #else
1.2.2.1   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.2.2.1   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.2.2.1   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.2.2.1   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.2.2.1   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.2.2.1   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.2.2.1   misho     347:        if (!Sess || !*Sess->sess_name)
1.2       misho     348:                return -1;
                    349: 
                    350:        if (nSeed != -1) {
                    351:                /* genkey */
1.2.2.1   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.2.2.1   misho     360:                Sess->sess_key = va_arg(lst, key_t);
1.2       misho     361:                va_end(lst);
                    362:        }
                    363: 
                    364:        /* create semaphore */
1.2.2.1   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.2.2.1   misho     372:        if (!Sess->sess_zcpy) {
1.2       misho     373:                sems.val = 1;
1.2.2.1   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.2.2.1   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.2.2.1   misho     388:                Sess->sess_size = nSize;
1.2       misho     389: 
1.2.2.1   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.2.2.1   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.2.2.1   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.2.2.1   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.2.2.1   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.2.2.1   misho     438:                s->sess_addr = NULL;
1.2       misho     439:        }
                    440: 
1.2.2.1   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.2.2.1   misho     451: map_detachSession(sess_t * __restrict s)
1.2       misho     452: {
                    453:        if (!s)
                    454:                return;
                    455: 
1.2.2.1   misho     456:        msync(s->sess_addr, 0, MS_SYNC | MS_INVALIDATE);
1.2       misho     457: 
1.2.2.1   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.2.2.1   misho     472: ipc_attachSession(sess_t * __restrict s, void *procMem)
1.2       misho     473: {
                    474:        if (!s)
                    475:                return NULL;
                    476: 
1.2.2.1   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.2.2.1   misho     480:                s->sess_addr = NULL;
1.2       misho     481:        }
                    482: 
1.2.2.1   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.2.2.1   misho     493: ipc_detachSession(sess_t * __restrict s)
1.2       misho     494: {
                    495:        if (!s)
                    496:                return;
                    497: 
1.2.2.1   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:  */
                    510: inline int
1.2.2.1   misho     511: sess_isAttached(sess_t * __restrict s)
1.2       misho     512: {
                    513:        if (!s)
                    514:                return -1;
                    515: 
1.2.2.1   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.2.2.1   misho     527: map_notSemaphore(sess_t * __restrict s)
1.2       misho     528: {
                    529:        int i = -1;
                    530: 
                    531:        if (!s)
                    532:                return;
                    533: 
1.2.2.1   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.2.2.1   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.2.2.1   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.2.2.1   misho     563: map_incSemaphore(sess_t * __restrict s)
1.2       misho     564: {
                    565:        if (!s)
                    566:                return -1;
                    567: 
1.2.2.1   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.2.2.1   misho     578: map_decSemaphore(sess_t * __restrict s)
1.2       misho     579: {
                    580:        if (!s)
                    581:                return -1;
                    582: 
1.2.2.1   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.2.2.1   misho     593: ipc_notSemaphore(sess_t * __restrict s)
1.2       misho     594: {
                    595:        struct sembuf sb = { 0, 0, 0 };
                    596: 
                    597:        if (s)
1.2.2.1   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.2.2.1   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.2.2.1   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.2.2.1   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.2.2.1   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.2.2.1   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.2.2.1   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.2.2.1   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.2.2.1   misho     663: sess_GetValues(sess_t * __restrict s, array_t ** __restrict Vals)
1.2       misho     664: {
                    665:        register int i;
1.2.2.1   misho     666:        char *Shared = NULL;
1.2       misho     667:        char *peer, *p_brk;
1.2.2.1   misho     668:        ait_val_t *v;
1.2       misho     669: 
1.2.2.1   misho     670:        if (!s || !Vals)
1.2       misho     671:                return -1;
1.2.2.1   misho     672:        *Vals = ait_allocVars(0);
                    673:        if (!*Vals) {
                    674:                io_SetErr(elwix_GetErrno(), "%s", elwix_GetError());
1.2       misho     675:                return -1;
1.2.2.1   misho     676:        }
1.2       misho     677: 
                    678:        /* allocated memory & mirrored shared memory into this */
1.2.2.1   misho     679:        Shared = e_malloc(s->sess_size);
1.2       misho     680:        if (!Shared) {
                    681:                LOGERR;
1.2.2.1   misho     682:                ait_freeVars(Vals);
1.2       misho     683:                return -1;
1.2.2.1   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.2.2.1   misho     697:                if (!(v = ait_allocVar())) {
                    698:                        io_SetErr(elwix_GetErrno(), "%s", elwix_GetError());
1.2       misho     699:                        e_free(Shared);
1.2.2.1   misho     700:                        ait_freeVars(Vals);
1.2       misho     701:                        return -1;
                    702:                } else
1.2.2.1   misho     703:                        AIT_SET_STR(v, peer);
1.2       misho     704: 
1.2.2.1   misho     705:                array_Push(*Vals, v, 0);
1.2       misho     706:        }
                    707: 
                    708:        e_free(Shared);
1.2.2.1   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.2.2.1   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.2.2.1   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.2.2.1   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.2.2.1   misho     732:        if (v) {
1.2.2.2 ! misho     733:                if (!(*v = ait_allocVar())) {
        !           734:                        io_SetErr(elwix_GetErrno(), "%s", elwix_GetError());
        !           735:                        return -1;
1.2.2.1   misho     736:                } else
1.2.2.2 ! misho     737:                        AIT_INIT_VAL2(*v, string);
1.2       misho     738:        }
                    739: 
                    740:        /* allocated memory & mirrored shared memory into this */
1.2.2.1   misho     741:        Shared = e_malloc(s->sess_size);
1.2       misho     742:        if (!Shared) {
                    743:                LOGERR;
1.2.2.1   misho     744:                ait_freeVar(v);
1.2       misho     745:                return -1;
1.2.2.1   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.2.2.1   misho     755:                if (attr && !strncmp(attr, csAttr, SESS_MAX_ATTRIBUTE - 1)) {
1.2       misho     756:                        val = strtok_r(NULL, "=\r\n", &a_brk);
1.2.2.1   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);
1.2.2.1   misho     768:        ait_freeVar(v);
1.2       misho     769:        return 0;
                    770: }
                    771: 
                    772: /*
                    773:  * sess_DelValue() - Delete item from session shared memory
                    774:  *
                    775:  * @s = Session item
                    776:  * @csAttr = Attribute for erasing
1.2.2.1   misho     777:  * return: -1 error: in parameter or !=-1 deleted items
1.2       misho     778:  */
                    779: int
1.2.2.1   misho     780: sess_DelValue(sess_t * __restrict s, const char *csAttr)
1.2       misho     781: {
                    782:        register int i;
1.2.2.1   misho     783:        int attrlen, d = 0;
                    784:        char *Buffer, *Shared, szAttr[SESS_MAX_ATTRIBUTE];
1.2       misho     785:        char *peer, *p_brk;
                    786: 
                    787:        if (!s || !csAttr || !*csAttr)
                    788:                return -1;
                    789:        else
                    790:                attrlen = strlen(csAttr);
                    791:        Buffer = Shared = NULL;
                    792:        strlcpy(szAttr, csAttr, sizeof szAttr);
                    793:        strlcat(szAttr, "=", sizeof szAttr);
                    794: 
1.2.2.1   misho     795:        Buffer = e_malloc(s->sess_size);
1.2       misho     796:        if (!Buffer) {
                    797:                LOGERR;
                    798:                return -1;
                    799:        } else
1.2.2.1   misho     800:                memset(Buffer, 0, s->sess_size);
                    801:        Shared = e_malloc(s->sess_size);
1.2       misho     802:        if (!Shared) {
                    803:                LOGERR;
                    804:                e_free(Buffer);
                    805:                return -1;
                    806:        } else {
                    807:                DEC_SEM(s);
1.2.2.1   misho     808:                memcpy(Shared, s->sess_addr, s->sess_size);
1.2       misho     809:        }
                    810: 
                    811:        for (i = 1, peer = strtok_r(Shared, SESS_MEM_DELIM"\r\n", &p_brk); peer; 
                    812:                        i++, peer = strtok_r(NULL, SESS_MEM_DELIM"\r\n", &p_brk)) {
                    813:                if (!strncmp(peer, csAttr, attrlen))
1.2.2.1   misho     814:                        if (peer[attrlen] == '=' || !peer[attrlen]) {
                    815:                                d++;
1.2       misho     816:                                continue;
1.2.2.1   misho     817:                        }
1.2       misho     818: 
1.2.2.1   misho     819:                strlcat(Buffer, peer, s->sess_size);
                    820:                strlcat(Buffer, SESS_MEM_DELIM, s->sess_size);
1.2       misho     821:        }
                    822: 
1.2.2.1   misho     823:        memcpy(s->sess_addr, Buffer, s->sess_size);
1.2       misho     824: 
1.2.2.1   misho     825:        if (s->sess_type == SHARED_MAP)
                    826:                msync(s->sess_addr, 0, MS_SYNC | MS_INVALIDATE);
1.2       misho     827: 
                    828:        INC_SEM(s);
                    829:        e_free(Shared);
                    830:        e_free(Buffer);
1.2.2.1   misho     831:        return d;
1.2       misho     832: }
                    833: 
                    834: /*
                    835:  * sess_SetValue() - Set item into session shared memory or update if exists
                    836:  *
                    837:  * @s = Session item
                    838:  * @csAttr = Attribute
                    839:  * @psVal = Value
                    840:  * return: 0 nothing, -1 error: in parameter, 
1.2.2.1   misho     841:        >0 set position, if added new item merged with SESS_F_ADD and 
                    842:        if just define item merged with SESS_F_DEF
1.2       misho     843:  */
                    844: int
1.2.2.1   misho     845: sess_SetValue(sess_t * __restrict s, const char *csAttr, const char *psVal)
1.2       misho     846: {
                    847:        register int i;
1.2.2.1   misho     848:        int upd = 0, def = 0;
                    849:        char *Buffer, *Shared, szAttr[SESS_MAX_ATTRIBUTE];
1.2       misho     850:        char *peer, *p_brk;
                    851: 
                    852:        if (!s || !csAttr || !*csAttr)
                    853:                return -1;
                    854:        else
                    855:                Buffer = Shared = NULL;
                    856:        strlcpy(szAttr, csAttr, sizeof szAttr);
                    857:        strlcat(szAttr, "=", sizeof szAttr);
                    858: 
1.2.2.1   misho     859:        Buffer = e_malloc(s->sess_size);
1.2       misho     860:        if (!Buffer) {
                    861:                LOGERR;
                    862:                return -1;
                    863:        } else
1.2.2.1   misho     864:                memset(Buffer, 0, s->sess_size);
                    865:        Shared = e_malloc(s->sess_size);
1.2       misho     866:        if (!Shared) {
                    867:                LOGERR;
                    868:                e_free(Buffer);
                    869:                return -1;
                    870:        } else {
                    871:                DEC_SEM(s);
1.2.2.1   misho     872:                memcpy(Shared, s->sess_addr, s->sess_size);
1.2       misho     873:        }
                    874: 
1.2.2.1   misho     875:        for (i = 1, peer = strtok_r(Shared, SESS_MEM_DELIM"\r\n", &p_brk); peer; 
                    876:                        i++, peer = strtok_r(NULL, SESS_MEM_DELIM"\r\n", &p_brk))
1.2       misho     877:                if (!strncmp(peer, szAttr, strlen(szAttr))) {
                    878:                        upd++;
                    879:                        if (psVal) {
1.2.2.1   misho     880:                                strlcat(Buffer, szAttr, s->sess_size);
                    881:                                strlcat(Buffer, psVal, s->sess_size);
                    882:                                strlcat(Buffer, SESS_MEM_DELIM, s->sess_size);
1.2       misho     883:                        } else {
1.2.2.1   misho     884:                                strlcat(Buffer, csAttr, s->sess_size);
                    885:                                strlcat(Buffer, SESS_MEM_DELIM, s->sess_size);
                    886:                                def = SESS_F_DEF;
1.2       misho     887:                        }
1.2.2.1   misho     888:                } else {
                    889:                        strlcat(Buffer, peer, s->sess_size);
                    890:                        strlcat(Buffer, SESS_MEM_DELIM, s->sess_size);
1.2       misho     891:                }
                    892: 
                    893:        if (!upd) {
                    894:                if (psVal) {
1.2.2.1   misho     895:                        strlcat(Buffer, szAttr, s->sess_size);
                    896:                        strlcat(Buffer, psVal, s->sess_size);
                    897:                        strlcat(Buffer, SESS_MEM_DELIM, s->sess_size);
1.2       misho     898:                } else {
1.2.2.1   misho     899:                        strlcat(Buffer, csAttr, s->sess_size);
                    900:                        strlcat(Buffer, SESS_MEM_DELIM, s->sess_size);
                    901:                        def = SESS_F_DEF;
1.2       misho     902:                }
1.2.2.1   misho     903:                def |= SESS_F_ADD;
1.2       misho     904:        }
                    905: 
1.2.2.1   misho     906:        memcpy(s->sess_addr, Buffer, s->sess_size);
1.2       misho     907: 
1.2.2.1   misho     908:        if (s->sess_type == SHARED_MAP)
                    909:                msync(s->sess_addr, 0, MS_SYNC | MS_INVALIDATE);
1.2       misho     910: 
                    911:        INC_SEM(s);
                    912:        e_free(Shared);
                    913:        e_free(Buffer);
                    914:        return upd | def;
                    915: }
                    916: 
                    917: 
                    918: /*
                    919:  * sess_prepareSession() - Attach to shared memory and de-marshaling data
                    920:  *
                    921:  * @s = Session
                    922:  * @useDirect = Use direct shared memory if !=0 or snapshot of data to array
                    923:  * return: NULL error or no data, !=NULL array with variables, 
                    924:  *             after use must free resources with sess_doneSession()
                    925:  */
                    926: array_t *
1.2.2.1   misho     927: sess_prepareSession(sess_t * __restrict s, char useDirect)
1.2       misho     928: {
                    929:        array_t *arr = NULL;
                    930:        sess_hdr_t *hdr;
                    931: 
                    932:        if (!s) {
                    933:                io_SetErr(EINVAL, "Invalid argument\n");
                    934:                return NULL;
                    935:        }
1.2.2.1   misho     936:        if (s->sess_addr) {
1.2       misho     937:                io_SetErr(EINVAL, "Already attached memory\n");
                    938:                return NULL;
                    939:        }
                    940: 
1.2.2.1   misho     941:        if (!ATTACH_MEMORY(s))
1.2       misho     942:                return NULL;
                    943:        else
1.2.2.1   misho     944:                hdr = (sess_hdr_t*) s->sess_addr;
1.2       misho     945:        if (hdr->hdr_magic != SESS_AIT_MAGIC) {
                    946:                DETACH_MEMORY(s);
                    947: 
                    948:                io_SetErr(EINVAL, "Shared memory not contains values with proper format\n");
                    949:                return NULL;
                    950:        }
                    951: 
                    952:        DEC_SEM(s);
1.2.2.1   misho     953:        s->sess_zcpy = useDirect;
                    954:        arr = ait_map2vars(s->sess_addr + sizeof(sess_hdr_t), s->sess_size - sizeof(sess_hdr_t), 
                    955:                        hdr->hdr_argc, s->sess_zcpy);
1.2       misho     956:        INC_SEM(s);
                    957: 
1.2.2.1   misho     958:        if (!s->sess_zcpy)
1.2       misho     959:                DETACH_MEMORY(s);
                    960:        return arr;
                    961: }
                    962: 
                    963: /*
                    964:  * sess_doneSession() - Free resources allocated with sess_prepareSession()
                    965:  *
                    966:  * @s = Session
                    967:  * @arr = Array with variables for free
                    968:  * return: none
                    969:  */
                    970: void
1.2.2.1   misho     971: sess_doneSession(sess_t * __restrict s, array_t ** __restrict arr)
1.2       misho     972: {
                    973:        if (!s) {
                    974:                io_SetErr(EINVAL, "Invalid argument\n");
                    975:                return;
                    976:        }
                    977: 
1.2.2.1   misho     978:        if (!s->sess_zcpy)
1.2       misho     979:                array_Free(*arr);
                    980:        else
                    981:                DETACH_MEMORY(s);
                    982:        array_Destroy(arr);
                    983: }
                    984: 
                    985: /*
                    986:  * sess_commitSession() - Commit data to shared memory
                    987:  *
                    988:  * @s = Session
                    989:  * @arr = Array with variables for save
                    990:  * return -1 error or !=-1 size of stored variables into shared memory
                    991:  */
                    992: int
1.2.2.1   misho     993: sess_commitSession(sess_t * __restrict s, array_t * __restrict arr)
1.2       misho     994: {
                    995:        sess_hdr_t *hdr;
                    996:        int ret = 0;
                    997: 
                    998:        if (!s || !arr) {
                    999:                io_SetErr(EINVAL, "Invalid argument\n");
                   1000:                return -1;
                   1001:        }
                   1002: 
1.2.2.1   misho    1003:        if (!ATTACH_MEMORY(s)) {
1.2       misho    1004:                DETACH_MEMORY(s);
                   1005:                return -1;
                   1006:        } else
1.2.2.1   misho    1007:                hdr = (sess_hdr_t*) s->sess_addr;
1.2       misho    1008: 
                   1009:        DEC_SEM(s);
1.2.2.1   misho    1010:        if ((ret = ait_vars2map(s->sess_addr + sizeof(sess_hdr_t), 
                   1011:                                        s->sess_size - sizeof(sess_hdr_t), arr)) != -1) {
1.2       misho    1012:                hdr->hdr_magic = SESS_AIT_MAGIC;
                   1013:                hdr->hdr_argc = array_Size(arr);
                   1014:                ret += sizeof(sess_hdr_t);
                   1015:        }
                   1016:        INC_SEM(s);
                   1017: 
                   1018:        DETACH_MEMORY(s);
                   1019:        return ret;
                   1020: }

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