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

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