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

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