Annotation of libaitsess/src/aitsess.c, revision 1.3.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.3.2.2 ! misho 6: * $Id: aitsess.c,v 1.3.2.1 2011/09/08 07:22:00 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.2.1 misho 108: }
109: memset(*Sess, 0, sizeof(tagSess));
1.3 misho 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;
1.3.2.2 ! misho 231: }
! 232: if (!ret)
1.1 misho 233: sem_post((*Sess)->id.sid);
234:
1.3 misho 235: /* create file for shared memory storage */
1.2 misho 236: (*Sess)->mem.fd = open(szSName[1], O_RDWR | O_CREAT, MEM_MODE);
1.1 misho 237: if ((*Sess)->mem.fd == -1) {
238: LOGERR;
239: map_destroySession(csFName, Sess);
240: return -1;
241: }
1.3 misho 242: /* if is new shared memory session, fill file with zeros */
1.1 misho 243: if (!ret) {
1.3 misho 244: if (lseek((*Sess)->mem.fd, cnSize - 1, SEEK_SET) == -1) {
1.1 misho 245: LOGERR;
246: map_destroySession(csFName, Sess);
247: return -1;
1.3 misho 248: } else
249: write((*Sess)->mem.fd, "", 1);
250: lseek((*Sess)->mem.fd, 0, SEEK_SET);
1.1 misho 251: }
252: (*Sess)->eom = cnSize;
253:
254: return ret;
255: }
256:
257: /*
258: * map_destroySession() MMAP free shared resources
259: * @csFName = Session name for delete
260: * @Sess = Session item
261: */
1.3 misho 262: void
263: map_destroySession(const char *csFName, tagSess ** __restrict Sess)
1.1 misho 264: {
265: int flg = 1;
1.3 misho 266: char szSName[2][FILENAME_MAX];
1.1 misho 267:
1.3 misho 268: assert(Sess);
269: if (!Sess || !*Sess)
1.1 misho 270: return;
271:
1.3 misho 272: memset(szSName, 0, sizeof szSName);
273: snprintf(szSName[0], MAX_SEMNAME, "/%X.ANS", (u_int) (*Sess)->key);
274: snprintf(szSName[1], FILENAME_MAX, "%s-%x.ANM", csFName, (u_int) (*Sess)->key);
1.1 misho 275:
276: if ((*Sess)->id.sid != SEM_FAILED) {
277: if (sem_close((*Sess)->id.sid) == -1)
278: flg = 0;
279: if (sem_unlink(szSName[0]) == -1)
280: /*flg = 0*/;
281: }
282: if ((*Sess)->mem.fd != -1) {
283: if (close((*Sess)->mem.fd) == -1)
284: flg = 0;
285: if (unlink(szSName[1]) == -1)
286: /*flg = 0*/;
287: }
288: (*Sess)->eom ^= (*Sess)->eom;
289:
290: freeSession(flg ? csFName : NULL, Sess);
291: }
292:
293: /*
294: * ipc_createSession() IPC Created session and allocated resources
295: * @csFName = Session name for identified
296: * @cnSeed = Seed for securing key
297: * @cnSize = Allocated shared memory size in bytes
298: * @Sess = Session item
299: * return: 0 Ok successful, -1 error: not allocated resources
300: */
1.3 misho 301: int
302: ipc_createSession(const char *csFName, const int cnSeed, const u_int cnSize, tagSess ** __restrict Sess)
1.1 misho 303: {
1.3 misho 304: int ret = 0, id = SHARED_IPC;
1.1 misho 305: union semun sems;
306:
1.3 misho 307: ret = initSession(&id, csFName, Sess);
1.1 misho 308: if (ret == -1 || !*Sess)
309: return -1;
310:
1.3 misho 311: /* genkey */
1.1 misho 312: (*Sess)->key = ftok(csFName, cnSeed);
313: if ((*Sess)->key == -1) {
314: LOGERR;
315: freeSession(csFName, Sess);
316: return -1;
317: }
318:
1.3 misho 319: /* create semaphore */
1.2 misho 320: (*Sess)->id.semid = semget((*Sess)->key, 1, MEM_MODE | IPC_CREAT);
1.1 misho 321: if ((*Sess)->id.semid == -1) {
322: LOGERR;
323: ipc_destroySession(csFName, Sess);
324: return -1;
325: }
1.3 misho 326: /* if is new shared memory session, init sempahore with 1 */
1.1 misho 327: if (!ret) {
328: sems.val = 1;
329: if (semctl((*Sess)->id.semid, 0, SETVAL, sems) == -1) {
330: LOGERR;
331: ipc_destroySession(csFName, Sess);
332: return -1;
333: }
334: }
335:
1.3 misho 336: /* create shared memory object */
1.2 misho 337: (*Sess)->mem.shmid = shmget((*Sess)->key, cnSize, MEM_MODE | IPC_CREAT);
1.1 misho 338: if ((*Sess)->mem.shmid == -1) {
339: LOGERR;
340: ipc_destroySession(csFName, Sess);
341: return -1;
342: }
343: (*Sess)->eom = cnSize;
344:
345: return ret;
346: }
347:
348: /*
349: * ipc_destroySession() IPC free shared resources
350: * @csFName = Session name for delete
351: * @Sess = Session item
352: */
1.3 misho 353: void
354: ipc_destroySession(const char *csFName, tagSess ** __restrict Sess)
1.1 misho 355: {
356: int flg = 1;
357: union semun sems;
358: struct shmid_ds ds;
359:
1.3 misho 360: assert(Sess);
361: if (!Sess || !*Sess)
1.1 misho 362: return;
363:
364: if ((*Sess)->id.semid != -1)
365: if (semctl((*Sess)->id.semid, 0, IPC_RMID, &sems) == -1)
366: flg = 0;
367: if ((*Sess)->mem.shmid != -1)
368: if (shmctl((*Sess)->mem.shmid, IPC_RMID, &ds) == -1)
369: flg = 0;
370: (*Sess)->eom ^= (*Sess)->eom;
371:
372: freeSession(flg ? csFName : NULL, Sess);
373: }
374:
375:
376: /*
377: * map_attachSession() MMAP Attach to shared memory & return begin address
378: * @s = Session item
379: * @procMem = Custom start address (optionl) *default must be 0*
380: * return: NULL failed attach, !=NULL begin address of memory
381: */
1.3 misho 382: inline void *
383: map_attachSession(tagSess * __restrict s, void *procMem)
1.1 misho 384: {
385: struct stat sb;
386:
387: if (!s)
388: return NULL;
389:
1.3 misho 390: /* Learn size of shared memory block */
1.1 misho 391: sync();
392: if (fstat(s->mem.fd, &sb) == -1) {
393: LOGERR;
394: return NULL;
395: } else
396: s->eom = sb.st_size;
397:
1.3 misho 398: /* attach to memory */
1.1 misho 399: s->addr = mmap(procMem, s->eom, PROT_READ | PROT_WRITE, MAP_SHARED, s->mem.fd, 0);
400: if (s->addr == MAP_FAILED) {
401: LOGERR;
402: s->addr = NULL;
403: }
404:
405: return s->addr;
406: }
407:
408: /*
409: * map_detachSession() MMAP Detach from shared memory
410: * @s = Session item
411: */
1.3 misho 412: inline void
413: map_detachSession(tagSess * __restrict s)
1.1 misho 414: {
415: if (!s)
416: return;
417:
418: msync(s->addr, 0, MS_SYNC | MS_INVALIDATE);
419:
420: if (s->addr && s->eom) {
421: munmap(s->addr, s->eom);
422: s->addr = NULL;
423: }
424: }
425:
426: /*
427: * ipc_attachSession() IPC Attach to shared memory & return begin address
428: * @s = Session item
429: * @procMem = Custom start address (optionl) *default must be 0*
430: * return: NULL failed attach, !=NULL begin address of memory
431: */
1.3 misho 432: inline void *
433: ipc_attachSession(tagSess * __restrict s, void *procMem)
1.1 misho 434: {
435: if (!s)
436: return NULL;
437:
438: s->addr = shmat(s->mem.shmid, procMem, 0);
439: if (s->addr == (void*) -1) {
440: LOGERR;
441: s->addr = NULL;
442: }
443:
444: return s->addr;
445: }
446:
447: /*
448: * ipc_detachSession() IPC Detach from shared memory
449: * @s = Session item
450: */
1.3 misho 451: inline void
452: ipc_detachSession(tagSess * __restrict s)
1.1 misho 453: {
454: if (!s)
455: return;
456:
457: if (s->addr) {
458: shmdt(s->addr);
459: s->addr = NULL;
460: }
461: }
462:
1.2 misho 463: /*
464: * isAttached() Check for mapped/(attached) shared memory
465: * @s = Session item
466: * return: -1 null session item, 0 not attached, 1 attached memory
467: */
1.3 misho 468: inline int
469: isAttached(tagSess * __restrict s)
1.2 misho 470: {
471: if (!s)
472: return -1;
473:
474: return (s->addr ? 1 : 0);
475: }
476:
1.1 misho 477:
478: /*
479: * map_notSemaphore() MMAP negative block if semaphore isn`t signaled
480: * @s = Session item
481: */
1.3 misho 482: inline void
483: map_notSemaphore(tagSess * __restrict s)
1.1 misho 484: {
485: int i = -1;
486:
487: if (!s)
488: return;
489:
490: sem_getvalue(s->id.sid, &i);
491: for (;i > 0; i--)
492: sem_wait(s->id.sid);
493: }
494:
495: /*
496: * map_isSemaphored() MMAP Check semaphore
497: * @s = Session item
498: * return: -1 error: can`t return semaphore, 0 = false, 1 = true
499: */
1.3 misho 500: inline int
501: map_isSemaphored(tagSess * __restrict s)
1.1 misho 502: {
503: int val = -1;
504:
505: if (!s)
506: return -1;
507:
508: sem_getvalue(s->id.sid, &val);
509: return val ? 0 : 1;
510: }
511:
512: /*
513: * map_addSemaphore() MMAP unblock semaphore, increment semaphore
514: * @s = Session item
515: * return: 0 Ok, -1 error: can`t increment
516: */
1.3 misho 517: inline int
518: map_addSemaphore(tagSess * __restrict s)
1.1 misho 519: {
520: if (!s)
521: return -1;
522:
523: return sem_post(s->id.sid);
524: }
525:
526: /*
527: * map_decSemaphore() MMAP block semaphore, decrement semaphore
528: * @s = Session item
529: * return: 0 Ok, -1 error: can`t decrement
530: */
1.3 misho 531: inline int
532: map_decSemaphore(tagSess * __restrict s)
1.1 misho 533: {
534: if (!s)
535: return -1;
536:
537: return sem_wait(s->id.sid);
538: }
539:
540: /*
541: * ipc_notSemaphore() IPC negative block if semaphore isn`t signaled
542: * @s = Session item
543: */
1.3 misho 544: inline void
545: ipc_notSemaphore(tagSess * __restrict s)
1.1 misho 546: {
547: struct sembuf sb = { 0, 0, 0 };
548:
549: if (s)
550: semop(s->id.semid, &sb, 1);
551: }
552:
553: /*
554: * ipc_isSemaphored() IPC Check semaphore
555: * @s = Session item
556: * return: -1 error: can`t return semaphore, 0 = false, 1 = true
557: */
1.3 misho 558: inline int
559: ipc_isSemaphored(tagSess * __restrict s)
1.1 misho 560: {
561: struct sembuf sb = { 0, 0, IPC_NOWAIT };
562:
563: if (!s)
564: return -1;
565:
566: return semop(s->id.semid, &sb, 1) + 1;
567: }
568:
569: /*
570: * ipc_addSemaphore() IPC unblock semaphore, increment semaphore
571: * @s = Session item
572: * return: 0 Ok, -1 error: can`t increment
573: */
1.3 misho 574: inline int
575: ipc_addSemaphore(tagSess * __restrict s)
1.1 misho 576: {
577: struct sembuf sb = { 0, 1, 0 };
578:
579: if (!s)
580: return -1;
581:
582: return semop(s->id.semid, &sb, 1);
583: }
584:
585: /*
586: * ipc_decSemaphore() IPC block semaphore, decrement semaphore
587: * @s = Session item
588: * return: 0 Ok, -1 error: can`t decrement
589: */
1.3 misho 590: inline int
591: ipc_decSemaphore(tagSess * __restrict s)
1.1 misho 592: {
593: struct sembuf sb = { 0, -1, 0 };
594:
595: if (!s)
596: return -1;
597:
598: return semop(s->id.semid, &sb, 1);
599: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>