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

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.1 ! misho       6: * $Id: sess.c,v 1.2 2013/03/13 14:54:39 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) {
        !           733:                if (!*v) {
        !           734:                        if (!(*v = ait_allocVar())) {
        !           735:                                io_SetErr(elwix_GetErrno(), "%s", elwix_GetError());
        !           736:                                return -1;
        !           737:                        }
        !           738:                } else
        !           739:                        AIT_FREE_VAL(*v);
        !           740:                AIT_INIT_VAL2(*v, string);
1.2       misho     741:        }
                    742: 
                    743:        /* allocated memory & mirrored shared memory into this */
1.2.2.1 ! misho     744:        Shared = e_malloc(s->sess_size);
1.2       misho     745:        if (!Shared) {
                    746:                LOGERR;
1.2.2.1 ! misho     747:                ait_freeVar(v);
1.2       misho     748:                return -1;
1.2.2.1 ! misho     749:        }
        !           750: 
        !           751:        DEC_SEM(s);
        !           752:        memcpy(Shared, s->sess_addr, s->sess_size);
        !           753:        INC_SEM(s);
1.2       misho     754: 
                    755:        for (i = 1, peer = strtok_r(Shared, SESS_MEM_DELIM"\r\n", &p_brk); peer; 
                    756:                        i++, peer = strtok_r(NULL, SESS_MEM_DELIM"\r\n", &p_brk)) {
                    757:                attr = strtok_r(peer, "=\r\n", &a_brk);
1.2.2.1 ! misho     758:                if (attr && !strncmp(attr, csAttr, SESS_MAX_ATTRIBUTE - 1)) {
1.2       misho     759:                        val = strtok_r(NULL, "=\r\n", &a_brk);
1.2.2.1 ! misho     760:                        if (val && strlen(val))
        !           761:                                AIT_SET_STR(*v, val);
        !           762:                        else
        !           763:                                def = SESS_F_DEF;
1.2       misho     764: 
                    765:                        e_free(Shared);
                    766:                        return i | def;
                    767:                }
                    768:        }
                    769: 
                    770:        e_free(Shared);
1.2.2.1 ! misho     771:        ait_freeVar(v);
1.2       misho     772:        return 0;
                    773: }
                    774: 
                    775: /*
                    776:  * sess_DelValue() - Delete item from session shared memory
                    777:  *
                    778:  * @s = Session item
                    779:  * @csAttr = Attribute for erasing
1.2.2.1 ! misho     780:  * return: -1 error: in parameter or !=-1 deleted items
1.2       misho     781:  */
                    782: int
1.2.2.1 ! misho     783: sess_DelValue(sess_t * __restrict s, const char *csAttr)
1.2       misho     784: {
                    785:        register int i;
1.2.2.1 ! misho     786:        int attrlen, d = 0;
        !           787:        char *Buffer, *Shared, szAttr[SESS_MAX_ATTRIBUTE];
1.2       misho     788:        char *peer, *p_brk;
                    789: 
                    790:        if (!s || !csAttr || !*csAttr)
                    791:                return -1;
                    792:        else
                    793:                attrlen = strlen(csAttr);
                    794:        Buffer = Shared = NULL;
                    795:        strlcpy(szAttr, csAttr, sizeof szAttr);
                    796:        strlcat(szAttr, "=", sizeof szAttr);
                    797: 
1.2.2.1 ! misho     798:        Buffer = e_malloc(s->sess_size);
1.2       misho     799:        if (!Buffer) {
                    800:                LOGERR;
                    801:                return -1;
                    802:        } else
1.2.2.1 ! misho     803:                memset(Buffer, 0, s->sess_size);
        !           804:        Shared = e_malloc(s->sess_size);
1.2       misho     805:        if (!Shared) {
                    806:                LOGERR;
                    807:                e_free(Buffer);
                    808:                return -1;
                    809:        } else {
                    810:                DEC_SEM(s);
1.2.2.1 ! misho     811:                memcpy(Shared, s->sess_addr, s->sess_size);
1.2       misho     812:        }
                    813: 
                    814:        for (i = 1, peer = strtok_r(Shared, SESS_MEM_DELIM"\r\n", &p_brk); peer; 
                    815:                        i++, peer = strtok_r(NULL, SESS_MEM_DELIM"\r\n", &p_brk)) {
                    816:                if (!strncmp(peer, csAttr, attrlen))
1.2.2.1 ! misho     817:                        if (peer[attrlen] == '=' || !peer[attrlen]) {
        !           818:                                d++;
1.2       misho     819:                                continue;
1.2.2.1 ! misho     820:                        }
1.2       misho     821: 
1.2.2.1 ! misho     822:                strlcat(Buffer, peer, s->sess_size);
        !           823:                strlcat(Buffer, SESS_MEM_DELIM, s->sess_size);
1.2       misho     824:        }
                    825: 
1.2.2.1 ! misho     826:        memcpy(s->sess_addr, Buffer, s->sess_size);
1.2       misho     827: 
1.2.2.1 ! misho     828:        if (s->sess_type == SHARED_MAP)
        !           829:                msync(s->sess_addr, 0, MS_SYNC | MS_INVALIDATE);
1.2       misho     830: 
                    831:        INC_SEM(s);
                    832:        e_free(Shared);
                    833:        e_free(Buffer);
1.2.2.1 ! misho     834:        return d;
1.2       misho     835: }
                    836: 
                    837: /*
                    838:  * sess_SetValue() - Set item into session shared memory or update if exists
                    839:  *
                    840:  * @s = Session item
                    841:  * @csAttr = Attribute
                    842:  * @psVal = Value
                    843:  * return: 0 nothing, -1 error: in parameter, 
1.2.2.1 ! misho     844:        >0 set position, if added new item merged with SESS_F_ADD and 
        !           845:        if just define item merged with SESS_F_DEF
1.2       misho     846:  */
                    847: int
1.2.2.1 ! misho     848: sess_SetValue(sess_t * __restrict s, const char *csAttr, const char *psVal)
1.2       misho     849: {
                    850:        register int i;
1.2.2.1 ! misho     851:        int upd = 0, def = 0;
        !           852:        char *Buffer, *Shared, szAttr[SESS_MAX_ATTRIBUTE];
1.2       misho     853:        char *peer, *p_brk;
                    854: 
                    855:        if (!s || !csAttr || !*csAttr)
                    856:                return -1;
                    857:        else
                    858:                Buffer = Shared = NULL;
                    859:        strlcpy(szAttr, csAttr, sizeof szAttr);
                    860:        strlcat(szAttr, "=", sizeof szAttr);
                    861: 
1.2.2.1 ! misho     862:        Buffer = e_malloc(s->sess_size);
1.2       misho     863:        if (!Buffer) {
                    864:                LOGERR;
                    865:                return -1;
                    866:        } else
1.2.2.1 ! misho     867:                memset(Buffer, 0, s->sess_size);
        !           868:        Shared = e_malloc(s->sess_size);
1.2       misho     869:        if (!Shared) {
                    870:                LOGERR;
                    871:                e_free(Buffer);
                    872:                return -1;
                    873:        } else {
                    874:                DEC_SEM(s);
1.2.2.1 ! misho     875:                memcpy(Shared, s->sess_addr, s->sess_size);
1.2       misho     876:        }
                    877: 
1.2.2.1 ! misho     878:        for (i = 1, peer = strtok_r(Shared, SESS_MEM_DELIM"\r\n", &p_brk); peer; 
        !           879:                        i++, peer = strtok_r(NULL, SESS_MEM_DELIM"\r\n", &p_brk))
1.2       misho     880:                if (!strncmp(peer, szAttr, strlen(szAttr))) {
                    881:                        upd++;
                    882:                        if (psVal) {
1.2.2.1 ! misho     883:                                strlcat(Buffer, szAttr, s->sess_size);
        !           884:                                strlcat(Buffer, psVal, s->sess_size);
        !           885:                                strlcat(Buffer, SESS_MEM_DELIM, s->sess_size);
1.2       misho     886:                        } else {
1.2.2.1 ! misho     887:                                strlcat(Buffer, csAttr, s->sess_size);
        !           888:                                strlcat(Buffer, SESS_MEM_DELIM, s->sess_size);
        !           889:                                def = SESS_F_DEF;
1.2       misho     890:                        }
1.2.2.1 ! misho     891:                } else {
        !           892:                        strlcat(Buffer, peer, s->sess_size);
        !           893:                        strlcat(Buffer, SESS_MEM_DELIM, s->sess_size);
1.2       misho     894:                }
                    895: 
                    896:        if (!upd) {
                    897:                if (psVal) {
1.2.2.1 ! misho     898:                        strlcat(Buffer, szAttr, s->sess_size);
        !           899:                        strlcat(Buffer, psVal, s->sess_size);
        !           900:                        strlcat(Buffer, SESS_MEM_DELIM, s->sess_size);
1.2       misho     901:                } else {
1.2.2.1 ! misho     902:                        strlcat(Buffer, csAttr, s->sess_size);
        !           903:                        strlcat(Buffer, SESS_MEM_DELIM, s->sess_size);
        !           904:                        def = SESS_F_DEF;
1.2       misho     905:                }
1.2.2.1 ! misho     906:                def |= SESS_F_ADD;
1.2       misho     907:        }
                    908: 
1.2.2.1 ! misho     909:        memcpy(s->sess_addr, Buffer, s->sess_size);
1.2       misho     910: 
1.2.2.1 ! misho     911:        if (s->sess_type == SHARED_MAP)
        !           912:                msync(s->sess_addr, 0, MS_SYNC | MS_INVALIDATE);
1.2       misho     913: 
                    914:        INC_SEM(s);
                    915:        e_free(Shared);
                    916:        e_free(Buffer);
                    917:        return upd | def;
                    918: }
                    919: 
                    920: 
                    921: /*
                    922:  * sess_prepareSession() - Attach to shared memory and de-marshaling data
                    923:  *
                    924:  * @s = Session
                    925:  * @useDirect = Use direct shared memory if !=0 or snapshot of data to array
                    926:  * return: NULL error or no data, !=NULL array with variables, 
                    927:  *             after use must free resources with sess_doneSession()
                    928:  */
                    929: array_t *
1.2.2.1 ! misho     930: sess_prepareSession(sess_t * __restrict s, char useDirect)
1.2       misho     931: {
                    932:        array_t *arr = NULL;
                    933:        sess_hdr_t *hdr;
                    934: 
                    935:        if (!s) {
                    936:                io_SetErr(EINVAL, "Invalid argument\n");
                    937:                return NULL;
                    938:        }
1.2.2.1 ! misho     939:        if (s->sess_addr) {
1.2       misho     940:                io_SetErr(EINVAL, "Already attached memory\n");
                    941:                return NULL;
                    942:        }
                    943: 
1.2.2.1 ! misho     944:        if (!ATTACH_MEMORY(s))
1.2       misho     945:                return NULL;
                    946:        else
1.2.2.1 ! misho     947:                hdr = (sess_hdr_t*) s->sess_addr;
1.2       misho     948:        if (hdr->hdr_magic != SESS_AIT_MAGIC) {
                    949:                DETACH_MEMORY(s);
                    950: 
                    951:                io_SetErr(EINVAL, "Shared memory not contains values with proper format\n");
                    952:                return NULL;
                    953:        }
                    954: 
                    955:        DEC_SEM(s);
1.2.2.1 ! misho     956:        s->sess_zcpy = useDirect;
        !           957:        arr = ait_map2vars(s->sess_addr + sizeof(sess_hdr_t), s->sess_size - sizeof(sess_hdr_t), 
        !           958:                        hdr->hdr_argc, s->sess_zcpy);
1.2       misho     959:        INC_SEM(s);
                    960: 
1.2.2.1 ! misho     961:        if (!s->sess_zcpy)
1.2       misho     962:                DETACH_MEMORY(s);
                    963:        return arr;
                    964: }
                    965: 
                    966: /*
                    967:  * sess_doneSession() - Free resources allocated with sess_prepareSession()
                    968:  *
                    969:  * @s = Session
                    970:  * @arr = Array with variables for free
                    971:  * return: none
                    972:  */
                    973: void
1.2.2.1 ! misho     974: sess_doneSession(sess_t * __restrict s, array_t ** __restrict arr)
1.2       misho     975: {
                    976:        if (!s) {
                    977:                io_SetErr(EINVAL, "Invalid argument\n");
                    978:                return;
                    979:        }
                    980: 
1.2.2.1 ! misho     981:        if (!s->sess_zcpy)
1.2       misho     982:                array_Free(*arr);
                    983:        else
                    984:                DETACH_MEMORY(s);
                    985:        array_Destroy(arr);
                    986: }
                    987: 
                    988: /*
                    989:  * sess_commitSession() - Commit data to shared memory
                    990:  *
                    991:  * @s = Session
                    992:  * @arr = Array with variables for save
                    993:  * return -1 error or !=-1 size of stored variables into shared memory
                    994:  */
                    995: int
1.2.2.1 ! misho     996: sess_commitSession(sess_t * __restrict s, array_t * __restrict arr)
1.2       misho     997: {
                    998:        sess_hdr_t *hdr;
                    999:        int ret = 0;
                   1000: 
                   1001:        if (!s || !arr) {
                   1002:                io_SetErr(EINVAL, "Invalid argument\n");
                   1003:                return -1;
                   1004:        }
                   1005: 
1.2.2.1 ! misho    1006:        if (!ATTACH_MEMORY(s)) {
1.2       misho    1007:                DETACH_MEMORY(s);
                   1008:                return -1;
                   1009:        } else
1.2.2.1 ! misho    1010:                hdr = (sess_hdr_t*) s->sess_addr;
1.2       misho    1011: 
                   1012:        DEC_SEM(s);
1.2.2.1 ! misho    1013:        if ((ret = ait_vars2map(s->sess_addr + sizeof(sess_hdr_t), 
        !          1014:                                        s->sess_size - sizeof(sess_hdr_t), arr)) != -1) {
1.2       misho    1015:                hdr->hdr_magic = SESS_AIT_MAGIC;
                   1016:                hdr->hdr_argc = array_Size(arr);
                   1017:                ret += sizeof(sess_hdr_t);
                   1018:        }
                   1019:        INC_SEM(s);
                   1020: 
                   1021:        DETACH_MEMORY(s);
                   1022:        return ret;
                   1023: }

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