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