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>