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