Annotation of libaitsess/src/aitsess.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: aitsess.c,v 1.2 2011/04/30 21:35:21 misho Exp $
1.2       misho       7: *
1.2.2.1 ! misho       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
        !            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: */
1.1       misho      46: #include "global.h"
                     47: #include "aitsess.h"
                     48: 
                     49: 
                     50: #pragma GCC visibility push(hidden)
                     51: 
                     52: int sessErrno;
                     53: char sessError[MAX_STR + 1];
                     54: 
                     55: #pragma GCC visibility pop
                     56: 
                     57: // -----------------------------------------------------------
                     58: 
                     59: // Error maintenance functions ...
                     60: 
                     61: // sess_GetErrno() Get error code of last operation
                     62: inline int sess_GetErrno()
                     63: {
                     64:        return sessErrno;
                     65: }
                     66: // sess_GetError() Get error text of last operation
                     67: inline const char *sess_GetError()
                     68: {
                     69:        return sessError;
                     70: }
                     71: // sessDbg() Debug/Logging operations
                     72: static inline int sessDbg(FILE *f, char *fmt, ...)
                     73: {
                     74:        int ret = 0;
                     75:        va_list lst;
                     76: 
                     77:        va_start(lst, fmt);
                     78:        ret = vfprintf(f, fmt, lst);
                     79:        va_end(lst);
                     80: 
                     81:        return ret;
                     82: }
                     83: 
                     84: // -----------------------------------------------------------
                     85: 
                     86: /*
                     87:  * initSession() Initializing session structure, if session file not exists creating with specified tech
                     88:  * @cnID = Technology using in session. SHARED_IPC IPC tech; SHARED_MAP BSD MemoryMap tech
                     89:  * @csFName = Session filename for build key and identified
                     90:  * @Sess = Session item
                     91:  * return: 0 OK new key created, -1 error: no memory or file not created, 1 OK key finded
                     92: */
                     93: inline int initSession(const int cnID, const char *csFName, tagSess ** __restrict Sess)
                     94: {
                     95:        int h, ret = 0;
                     96:        char szStr[MAX_STR + 1];
                     97: 
                     98:        if (!*Sess) {
                     99:                *Sess = malloc(sizeof(tagSess));
                    100:                if (!*Sess) {
                    101:                        LOGERR;
                    102:                        return -1;
                    103:                }
                    104:        }
                    105:        memset(*Sess, 0, sizeof(tagSess));
                    106: 
                    107:        // If key file exist, session already connected
                    108:        if (!access(csFName, F_OK))
                    109:                ret = 1;
                    110:        // Build new key & new session
1.2       misho     111:        h = open(csFName, O_WRONLY | O_CREAT, MEM_MODE);
1.1       misho     112:        if (h == -1) {
                    113:                LOGERR;
                    114:                free(*Sess);
                    115:                return -1;
                    116:        }
                    117: 
                    118:        bzero(szStr, MAX_STR + 1);
                    119:        switch (cnID) {
                    120:                case SHARED_IPC:
                    121:                        strcpy(szStr, "IPC@");
                    122:                        break;
                    123:                case SHARED_MAP:
                    124:                        strcpy(szStr, "MAP@");
                    125:                        break;
                    126:                default:
                    127:                        errno = EPROTONOSUPPORT;
                    128:                        LOGERR;
                    129: 
                    130:                        close(h);
                    131:                        unlink(csFName);
                    132:                        free(*Sess);
                    133:                        return -1;
                    134:        }
                    135:        strcat(szStr, "AN_Session ver");
                    136:        strcat(szStr, "\n");
                    137:        write(h, szStr, strlen(szStr));
                    138:        close(h);
                    139: 
                    140:        (*Sess)->type = cnID;
                    141:        return ret;
                    142: }
                    143: 
                    144: /*
                    145:  * freeSession() Free allocated memory for session item and delete session file if present name
                    146:  * @csFName = Session filename for delete, if NULL nothing delete
                    147:  * @Sess = Session item
                    148: */
                    149: inline void freeSession(const char *csFName, tagSess ** __restrict Sess)
                    150: {
                    151:        (*Sess)->type ^= (*Sess)->type;
                    152:        if (csFName)
                    153:                unlink(csFName);
                    154:        if (*Sess)
                    155:                free(*Sess);
                    156:        *Sess = NULL;
                    157: }
                    158: 
                    159: 
                    160: /*
                    161:  * map_createSession() MMAP Created session and allocated resources
                    162:  * @csFName = Session name for identified
                    163:  * @cnSeed = Seed for securing key
                    164:  * @cnSize = Allocated shared memory size in bytes
                    165:  * @Sess = Session item
                    166:  * return: 0 Ok successful, -1 error: not allocated resources
                    167: */
                    168: int map_createSession(const char *csFName, const int cnSeed, const u_int cnSize, tagSess ** __restrict Sess)
                    169: {
                    170:        int ret = 0;
                    171:        char szSName[2][FILENAME_MAX + 1];
                    172:        void *mem;
                    173: 
                    174:        ret = initSession(SHARED_MAP, csFName, Sess);
                    175:        if (ret == -1 || !*Sess)
                    176:                return -1;
                    177: 
                    178:        // genkey
                    179:        (*Sess)->key = ftok(csFName, cnSeed);
                    180:        if ((*Sess)->key == -1) {
                    181:                LOGERR;
                    182:                freeSession(csFName, Sess);
                    183:                return -1;
                    184:        }
                    185: 
                    186:        // build semaphore & shared memory name
                    187:        memset(szSName, 0, (FILENAME_MAX + 1) * 2);
                    188:        snprintf(szSName[0], MAX_SEMNAME + 1, "/%X.ANS", (u_int) (*Sess)->key);
                    189:        snprintf(szSName[1], FILENAME_MAX + 1, "%s-%x.ANM", csFName, (u_int) (*Sess)->key);
                    190: 
                    191:        mem = malloc(cnSize);
                    192:        if (!mem) {
                    193:                LOGERR;
                    194:                freeSession(csFName, Sess);
                    195:                return -1;
                    196:        } else
                    197:                memset(mem, 0, cnSize);
                    198: 
                    199:        // create semaphore & add 1
1.2       misho     200:        (*Sess)->id.sid = sem_open(szSName[0], O_CREAT, MEM_MODE);
1.1       misho     201:        if ((*Sess)->id.sid == SEM_FAILED) {
                    202:                LOGERR;
                    203:                map_destroySession(csFName, Sess);
                    204:                free(mem);
                    205:                return -1;
                    206:        } else
                    207:                sem_post((*Sess)->id.sid);
                    208: 
                    209:        // create file for shared memory storage
1.2       misho     210:        (*Sess)->mem.fd = open(szSName[1], O_RDWR | O_CREAT, MEM_MODE);
1.1       misho     211:        if ((*Sess)->mem.fd == -1) {
                    212:                LOGERR;
                    213:                map_destroySession(csFName, Sess);
                    214:                free(mem);
                    215:                return -1;
                    216:        }
                    217:        // if is new shared memory session, fill file with zeros
                    218:        if (!ret) {
                    219:                if (write((*Sess)->mem.fd, mem, cnSize) != cnSize) {
                    220:                        LOGERR;
                    221:                        map_destroySession(csFName, Sess);
                    222:                        free(mem);
                    223:                        return -1;
                    224:                }
                    225:                if (lseek((*Sess)->mem.fd, 0, SEEK_SET)) {
                    226:                        LOGERR;
                    227:                        map_destroySession(csFName, Sess);
                    228:                        free(mem);
                    229:                        return -1;
                    230:                }
                    231:        }
                    232:        (*Sess)->eom = cnSize;
                    233: 
                    234:        free(mem);
                    235:        return ret;
                    236: }
                    237: 
                    238: /*
                    239:  * map_destroySession() MMAP free shared resources
                    240:  * @csFName = Session name for delete
                    241:  * @Sess = Session item
                    242: */
                    243: void map_destroySession(const char *csFName, tagSess ** __restrict Sess)
                    244: {
                    245:        int flg = 1;
                    246:        char szSName[2][FILENAME_MAX + 1];
                    247: 
                    248:        if (!*Sess)
                    249:                return;
                    250: 
                    251:        bzero(szSName, (FILENAME_MAX + 1) * 2);
                    252:        snprintf(szSName[0], MAX_SEMNAME + 1, "/%X.ANS", (u_int) (*Sess)->key);
                    253:        snprintf(szSName[1], FILENAME_MAX + 1, "%s-%x.ANM", csFName, (u_int) (*Sess)->key);
                    254: 
                    255:        if ((*Sess)->id.sid != SEM_FAILED) {
                    256:                if (sem_close((*Sess)->id.sid) == -1)
                    257:                        flg = 0;
                    258: 
                    259:                if (sem_unlink(szSName[0]) == -1)
                    260:                        /*flg = 0*/;
                    261:        }
                    262:        if ((*Sess)->mem.fd != -1) {
                    263:                if (close((*Sess)->mem.fd) == -1)
                    264:                        flg = 0;
                    265: 
                    266:                if (unlink(szSName[1]) == -1)
                    267:                        /*flg = 0*/;
                    268:        }
                    269:        (*Sess)->eom ^= (*Sess)->eom;
                    270: 
                    271:        freeSession(flg ? csFName : NULL, Sess);
                    272: }
                    273: 
                    274: /*
                    275:  * ipc_createSession() IPC Created session and allocated resources
                    276:  * @csFName = Session name for identified
                    277:  * @cnSeed = Seed for securing key
                    278:  * @cnSize = Allocated shared memory size in bytes
                    279:  * @Sess = Session item
                    280:  * return: 0 Ok successful, -1 error: not allocated resources
                    281: */
                    282: int ipc_createSession(const char *csFName, const int cnSeed, const u_int cnSize, tagSess ** __restrict Sess)
                    283: {
                    284:        int ret = 0;
                    285:        union semun sems;
                    286: 
                    287:        ret = initSession(SHARED_IPC, csFName, Sess);
                    288:        if (ret == -1 || !*Sess)
                    289:                return -1;
                    290: 
                    291:        // genkey
                    292:        (*Sess)->key = ftok(csFName, cnSeed);
                    293:        if ((*Sess)->key == -1) {
                    294:                LOGERR;
                    295:                freeSession(csFName, Sess);
                    296:                return -1;
                    297:        }
                    298: 
                    299:        // create semaphore
1.2       misho     300:        (*Sess)->id.semid = semget((*Sess)->key, 1, MEM_MODE | IPC_CREAT);
1.1       misho     301:        if ((*Sess)->id.semid == -1) {
                    302:                LOGERR;
                    303:                ipc_destroySession(csFName, Sess);
                    304:                return -1;
                    305:        }
                    306:        // if is new shared memory session, init sempahore with 1
                    307:        if (!ret) {
                    308:                sems.val = 1;
                    309:                if (semctl((*Sess)->id.semid, 0, SETVAL, sems) == -1) {
                    310:                        LOGERR;
                    311:                        ipc_destroySession(csFName, Sess);
                    312:                        return -1;
                    313:                }
                    314:        }
                    315: 
                    316:        // create shared memory object
1.2       misho     317:        (*Sess)->mem.shmid = shmget((*Sess)->key, cnSize, MEM_MODE | IPC_CREAT);
1.1       misho     318:        if ((*Sess)->mem.shmid == -1) {
                    319:                LOGERR;
                    320:                ipc_destroySession(csFName, Sess);
                    321:                return -1;
                    322:        }
                    323:        (*Sess)->eom = cnSize;
                    324: 
                    325:        return ret;
                    326: }
                    327: 
                    328: /*
                    329:  * ipc_destroySession() IPC free shared resources
                    330:  * @csFName = Session name for delete
                    331:  * @Sess = Session item
                    332: */
                    333: void ipc_destroySession(const char *csFName, tagSess ** __restrict Sess)
                    334: {
                    335:        int flg = 1;
                    336:        union semun sems;
                    337:        struct shmid_ds ds;
                    338: 
                    339:        if (!*Sess)
                    340:                return;
                    341: 
                    342:        if ((*Sess)->id.semid != -1)
                    343:                if (semctl((*Sess)->id.semid, 0, IPC_RMID, &sems) == -1)
                    344:                        flg = 0;
                    345:        if ((*Sess)->mem.shmid != -1)
                    346:                if (shmctl((*Sess)->mem.shmid, IPC_RMID, &ds) == -1)
                    347:                        flg = 0;
                    348:        (*Sess)->eom ^= (*Sess)->eom;
                    349: 
                    350:        freeSession(flg ? csFName : NULL, Sess);
                    351: }
                    352: 
                    353: 
                    354: /*
                    355:  * map_attachSession() MMAP Attach to shared memory & return begin address
                    356:  * @s = Session item
                    357:  * @procMem = Custom start address (optionl) *default must be 0*
                    358:  * return: NULL failed attach, !=NULL begin address of memory
                    359: */
                    360: inline void *map_attachSession(tagSess * __restrict s, void *procMem)
                    361: {
                    362:        struct stat sb;
                    363: 
                    364:        if (!s)
                    365:                return NULL;
                    366: 
                    367:        // Learn size of shared memory block
                    368:        sync();
                    369:        if (fstat(s->mem.fd, &sb) == -1) {
                    370:                LOGERR;
                    371:                return NULL;
                    372:        } else
                    373:                s->eom = sb.st_size;
                    374: 
                    375:        // attach to memory
                    376:        s->addr = mmap(procMem, s->eom, PROT_READ | PROT_WRITE, MAP_SHARED, s->mem.fd, 0);
                    377:        if (s->addr == MAP_FAILED) {
                    378:                LOGERR;
                    379:                s->addr = NULL;
                    380:        }
                    381: 
                    382:        return s->addr;
                    383: }
                    384: 
                    385: /*
                    386:  * map_detachSession() MMAP Detach from shared memory
                    387:  * @s = Session item
                    388: */
                    389: inline void map_detachSession(tagSess * __restrict s)
                    390: {
                    391:        if (!s)
                    392:                return;
                    393: 
                    394:        msync(s->addr, 0, MS_SYNC | MS_INVALIDATE);
                    395: 
                    396:        if (s->addr && s->eom) {
                    397:                munmap(s->addr, s->eom);
                    398:                s->addr = NULL;
                    399:        }
                    400: }
                    401: 
                    402: /*
                    403:  * ipc_attachSession() IPC Attach to shared memory & return begin address
                    404:  * @s = Session item
                    405:  * @procMem = Custom start address (optionl) *default must be 0*
                    406:  * return: NULL failed attach, !=NULL begin address of memory
                    407: */
                    408: inline void *ipc_attachSession(tagSess * __restrict s, void *procMem)
                    409: {
                    410:        if (!s)
                    411:                return NULL;
                    412: 
                    413:        s->addr = shmat(s->mem.shmid, procMem, 0);
                    414:        if (s->addr == (void*) -1) {
                    415:                LOGERR;
                    416:                s->addr = NULL;
                    417:        }
                    418: 
                    419:        return s->addr;
                    420: }
                    421: 
                    422: /*
                    423:  * ipc_detachSession() IPC Detach from shared memory
                    424:  * @s = Session item
                    425: */
                    426: inline void ipc_detachSession(tagSess * __restrict s)
                    427: {
                    428:        if (!s)
                    429:                return;
                    430: 
                    431:        if (s->addr) {
                    432:                shmdt(s->addr);
                    433:                s->addr = NULL;
                    434:        }
                    435: }
                    436: 
1.2       misho     437: /*
                    438:  * isAttached() Check for mapped/(attached) shared memory
                    439:  * @s = Session item
                    440:  * return: -1 null session item, 0 not attached, 1 attached memory
                    441: */
                    442: inline int isAttached(tagSess * __restrict s)
                    443: {
                    444:        if (!s)
                    445:                return -1;
                    446: 
                    447:        return (s->addr ? 1 : 0);
                    448: }
                    449: 
1.1       misho     450: 
                    451: /*
                    452:  * map_notSemaphore() MMAP negative block if semaphore isn`t signaled
                    453:  * @s = Session item
                    454: */
                    455: inline void map_notSemaphore(tagSess * __restrict s)
                    456: {
                    457:        int i = -1;
                    458: 
                    459:        if (!s)
                    460:                return;
                    461: 
                    462:        sem_getvalue(s->id.sid, &i);
                    463:        for (;i > 0; i--)
                    464:                sem_wait(s->id.sid);
                    465: }
                    466: 
                    467: /*
                    468:  * map_isSemaphored() MMAP Check semaphore
                    469:  * @s = Session item
                    470:  * return: -1 error: can`t return semaphore, 0 = false, 1 = true
                    471: */
                    472: inline int map_isSemaphored(tagSess * __restrict s)
                    473: {
                    474:        int val = -1;
                    475: 
                    476:        if (!s)
                    477:                return -1;
                    478: 
                    479:        sem_getvalue(s->id.sid, &val);
                    480:        return val ? 0 : 1;
                    481: }
                    482: 
                    483: /*
                    484:  * map_addSemaphore() MMAP unblock semaphore, increment semaphore
                    485:  * @s = Session item
                    486:  * return: 0 Ok, -1 error: can`t increment 
                    487: */
                    488: inline int map_addSemaphore(tagSess * __restrict s)
                    489: {
                    490:        if (!s)
                    491:                return -1;
                    492: 
                    493:        return sem_post(s->id.sid);
                    494: }
                    495: 
                    496: /*
                    497:  * map_decSemaphore() MMAP block semaphore, decrement semaphore
                    498:  * @s = Session item
                    499:  * return: 0 Ok, -1 error: can`t decrement 
                    500: */
                    501: inline int map_decSemaphore(tagSess * __restrict s)
                    502: {
                    503:        if (!s)
                    504:                return -1;
                    505: 
                    506:        return sem_wait(s->id.sid);
                    507: }
                    508: 
                    509: /*
                    510:  * ipc_notSemaphore() IPC negative block if semaphore isn`t signaled
                    511:  * @s = Session item
                    512: */
                    513: inline void ipc_notSemaphore(tagSess * __restrict s)
                    514: {
                    515:        struct sembuf sb = { 0, 0, 0 };
                    516: 
                    517:        if (s)
                    518:                semop(s->id.semid, &sb, 1);
                    519: }
                    520: 
                    521: /*
                    522:  * ipc_isSemaphored() IPC Check semaphore
                    523:  * @s = Session item
                    524:  * return: -1 error: can`t return semaphore, 0 = false, 1 = true
                    525: */
                    526: inline int ipc_isSemaphored(tagSess * __restrict s)
                    527: {
                    528:        struct sembuf sb = { 0, 0, IPC_NOWAIT };
                    529: 
                    530:        if (!s)
                    531:                return -1;
                    532: 
                    533:        return semop(s->id.semid, &sb, 1) + 1;
                    534: }
                    535: 
                    536: /*
                    537:  * ipc_addSemaphore() IPC unblock semaphore, increment semaphore
                    538:  * @s = Session item
                    539:  * return: 0 Ok, -1 error: can`t increment 
                    540: */
                    541: inline int ipc_addSemaphore(tagSess * __restrict s)
                    542: {
                    543:        struct sembuf sb = { 0, 1, 0 };
                    544: 
                    545:        if (!s)
                    546:                return -1;
                    547: 
                    548:        return semop(s->id.semid, &sb, 1);
                    549: }
                    550: 
                    551: /*
                    552:  * ipc_decSemaphore() IPC block semaphore, decrement semaphore
                    553:  * @s = Session item
                    554:  * return: 0 Ok, -1 error: can`t decrement 
                    555: */
                    556: inline int ipc_decSemaphore(tagSess * __restrict s)
                    557: {
                    558:        struct sembuf sb = { 0, -1, 0 };
                    559: 
                    560:        if (!s)
                    561:                return -1;
                    562: 
                    563:        return semop(s->id.semid, &sb, 1);
                    564: }

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