2 * Copyright (C) 1993 AmiTCP/IP Group, <amitcp-group@hut.fi>
3 * Helsinki University of Technology, Finland.
5 * Copyright (C) 2005 - 2007 The AROS Dev Team
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License version 2 as
9 * published by the Free Software Foundation.
11 * This program is distributed in the hope that it will be useful, but
12 * WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place - Suite 330, Boston,
25 #include <aros/asmcall.h>
26 #include <aros/libcall.h>
28 #include <sys/param.h>
29 #include <sys/systm.h>
30 #include <sys/socketvar.h>
31 #include <sys/kernel.h>
32 #include <sys/ioctl.h>
33 #include <sys/protosw.h>
34 #include <sys/malloc.h>
35 #include <sys/synch.h>
38 #include <sys/errno.h>
40 #include <sys/socket.h>
41 #include <net/route.h>
43 #include <kern/amiga_includes.h>
45 #include <api/amiga_api.h>
46 #include <api/amiga_libcallentry.h>
47 #include <api/allocdatabuffer.h>
49 #include <api/apicalls.h>
51 #include <net/if_protos.h>
53 #include <bsdsocket/socketbasetags.h>
55 #include <kern/uipc_domain_protos.h>
56 #include <kern/uipc_socket_protos.h>
57 #include <kern/uipc_socket2_protos.h>
60 static int selscan(struct SocketBase
*p
,
61 fd_set
*in
, fd_set
*ou
, fd_set
*ex
, fd_mask
*obits
,
62 int nfd
, int *retval
, int *selitemcount_p
);
63 void selenter(struct SocketBase
* p
, struct newselitem
** hdr
);
64 static void unselect(register struct newselbuf
* sb
);
65 void selwakeup(struct newselitem
**hdr
);
66 static int soo_select(struct socket
*so
, int which
, struct SocketBase
*p
);
67 static int countSockets(struct SocketBase
* libPtr
, struct socket
* so
);
70 * itimerfix copied from bsdss/server/kern/kern_time.c. since fields
71 * in struct timeval in amiga are ULONGs, values less than zero need
72 * not be checked. the second check, timeval less than resolution of
73 * the clock is not needed in amiga...hmm, is removed also.
75 static inline int itimerfix(struct timeval
*tv
)
77 if (tv
->tv_sec
> 100000000 || tv
->tv_usec
>= 1000000)
79 /* if (tv->tv_sec == 0 && tv->tv_usec != 0 && tv->tv_usec < tick)
85 * ffs() copied directly from bsdss/server/kern/subr_xxx.c
87 static inline int ffs(int mask
)
93 for (bit
= 1;; ++bit
) {
106 LONG
__IoctlSocket(LONG fdes
, ULONG cmd
, caddr_t data
, struct SocketBase
*libPtr
)
113 * Note: Syscall semaphore is essential here if two processes can access
114 * the same socket. (can it be changed to spl_? ?)
117 DSYSCALLS(log(LOG_DEBUG
,"IoctlSocket(%ld, 0x%08lx, 0x%08lx) called", fdes
, cmd
, *(ULONG
*)data
);)
118 ObtainSyscallSemaphore(libPtr
);
120 if (error
= getSock(libPtr
, fdes
, &so
))
124 * Interpret high order word to get size of the user data area
126 size
= IOCPARM_LEN(cmd
);
127 if (size
== 0 || size
> IOCPARM_MAX
) {
131 if (!(cmd
& IOC_IN
) && cmd
& IOC_OUT
)
133 * Zero the buffer so the user always
134 * gets back something deterministic.
140 case FIONCLEX
: /* should this return error ???? */
146 * data is a struct Task **, find corresponding SocketBase * and set owner
148 so
->so_pgid
= FindSocketBase(*(struct Task
**)data
);
154 *(struct Task
**)data
= so
->so_pgid
->thisTask
;
156 *(struct Task
**)data
= NULL
;
161 so
->so_state
|= SS_NBIO
;
163 so
->so_state
&= ~SS_NBIO
;
168 so
->so_state
|= SS_ASYNC
;
169 so
->so_rcv
.sb_flags
|= SB_ASYNC
;
170 so
->so_snd
.sb_flags
|= SB_ASYNC
;
172 so
->so_state
&= ~SS_ASYNC
;
173 so
->so_rcv
.sb_flags
&= ~SB_ASYNC
;
174 so
->so_snd
.sb_flags
&= ~SB_ASYNC
;
179 *(int *)data
= so
->so_rcv
.sb_cc
;
183 *(int *)data
= (so
->so_state
&SS_RCVATMARK
) != 0;
188 * Interface/routing/protocol specific ioctls:
189 * interface and routing ioctls should have a
190 * different entry since a socket's unnecessary -- not really,
191 * ifioctl needs the socket (?)
193 if ((IOCGROUP(cmd
) & 0XDF) == 'I') {
194 error
= (ifioctl(so
, cmd
, data
));
197 if (IOCGROUP(cmd
) == 'r') {
198 error
= (rtioctl(cmd
, data
));
201 error
= ((*so
->so_proto
->pr_usrreq
)(so
, PRU_CONTROL
,
202 (struct mbuf
*)(long)cmd
, (struct mbuf
*)data
, (struct mbuf
*)0));
205 ReleaseSyscallSemaphore(libPtr
);
206 DOPTERR(if (error
) log(LOG_ERR
,"IoctlSocket(): error %ld on command 0x%08lx", error
, cmd
);)
207 API_STD_RETURN(error
, 0);
210 AROS_LH3(LONG
, IoctlSocket
,
211 AROS_LHA(LONG
, fdes
, D0
),
212 AROS_LHA(ULONG
, cmd
, D1
),
213 AROS_LHA(caddr_t
, data
, A0
),
214 struct SocketBase
*, libPtr
, 19, UL
)
217 return __IoctlSocket(fdes
, cmd
, data
, libPtr
);
224 * Semaphore to prevent select buffers from simultaneous modifications
226 struct SignalSemaphore select_semaphore
= { };
230 #define SB_CLEAR 0 /* wait condition cleared */
231 #define SB_WILLWAIT 1 /* will wait if not cleared */
232 #define SB_WAITING 2 /* waiting - wake up */
235 struct newselitem
* si_next
; /* next selbuf in item chain */
236 struct newselitem
** si_prev
; /* back pointer */
237 struct newselbuf
* si_selbuf
; /* 'thread' waiting */
238 } s_item
[0]; /* selitems are allocated at select when right
239 number of descriptors are known */
242 void select_init(void)
244 InitSemaphore(&select_semaphore
);
248 * symbolic names FREAD and FWRITE aren'n needed anywhere else if only
249 * socket descriptors are in use.
255 * Select(), selscan(), selenter(), selwakeup() and unselect() are taken from
256 * ../server/kern/sys_generic.h in bsdss distribution. soo_select() is
257 * taken from ../server/kern/sys_socket.h, same distribution.
261 * Althrough the fd_set is used as the type of the masks, the size
262 * of the fd_set is not fixed, and is indeed calculated from nfds.
264 LONG
__WaitSelect(ULONG nfds
, fd_set
*readfds
, fd_set
*writefds
, fd_set
*exeptfds
,
265 struct timeval
*timeout
, ULONG
*sigmp
, struct SocketBase
*libPtr
)
268 u_int obitsize
; /* in bytes */
271 ULONG sigmask
= sigmp
? *sigmp
: 0;
273 struct newselbuf
* newselbuf
;
277 if (nfds
> libPtr
->dTableSize
)
278 nfds
= libPtr
->dTableSize
; /* forgiving; slightly wrong */
280 if (timeout
&& itimerfix(timeout
)) {
286 * We use selscan twice each time around the loop.
287 * The first time, we actually put ourself on device chains.
288 * The second time, we make a "fast" check for a true condition.
289 * selenter does nothing and we don't need to use unselect.
290 * We only need to zero obits once because if selscan
291 * turns on a bit it returns non-zero and we stop.
293 * The "fast" scan is also done before the loop is ever entered.
295 * We need to allocate some temporary buffers for output bit masks
296 * and, later for selitems. The amount of selitems needed is
297 * calculated during the first selscan -- when selenter does nothing
300 obitsize
= howmany(nfds
, NFDBITS
) * sizeof (fd_mask
);
301 if (allocDataBuffer(&libPtr
->selitems
, 3 * obitsize
) == FALSE
) {
305 obits
= (fd_mask
*)libPtr
->selitems
.db_Addr
;
307 aligned_bzero((caddr_t
)obits
, 3 * obitsize
);
310 * We make a first pass to check for conditions
311 * which are already true. Clearing uu_sb
312 * will keep selenter from doing anything.
315 error
= selscan(libPtr
, readfds
, writefds
, exeptfds
,
316 obits
, nfds
, &retval
, &selitemcount
);
319 * Check if the 'real' loop should be entered.
321 if (!error
&& !retval
) {
322 if (timeout
== NULL
|| timeout
->tv_secs
!= 0L || timeout
->tv_micro
!= 0L) {
325 * Send timeout if there is any.
328 tsleep_send_timeout(libPtr
, timeout
);
331 * Now, make sure there is room for all the selitems...
333 if (allocDataBuffer(&libPtr
->selitems
,
334 3 * obitsize
+ sizeof (struct newselbuf
) +
335 selitemcount
* sizeof(struct newselitem
)) == FALSE
) {
340 * We need to clear obits again _if_ the memory area for it has
343 if ((fd_mask
*)libPtr
->selitems
.db_Addr
!= obits
) {
344 obits
= (fd_mask
*)libPtr
->selitems
.db_Addr
;
345 aligned_bzero((caddr_t
)obits
, 3 * obitsize
);
347 newselbuf
= (struct newselbuf
*)((caddr_t
)obits
+ (3 * obitsize
));
352 * Now we get serious about blocking.
353 * selenter will put us on device chains.
354 * We don't need select_lock here because
355 * no other thread can get at selbuf yet.
358 newselbuf
->s_state
= SB_WILLWAIT
;
359 newselbuf
->s_count
= 0;
360 libPtr
->p_sb
= newselbuf
;
362 error
= selscan(libPtr
, readfds
, writefds
, exeptfds
,
363 obits
, nfds
, &retval
, &selitemcount
);
364 if (error
|| retval
) {
365 ObtainSemaphore(&select_semaphore
);
367 ReleaseSemaphore(&select_semaphore
);
372 * If the state is already SB_CLEAR, then a selwakeup
373 * slipped in after the selscan.
376 ObtainSemaphore(&select_semaphore
);
377 if (newselbuf
->s_state
== SB_CLEAR
) {
379 ReleaseSemaphore(&select_semaphore
);
382 newselbuf
->s_state
= SB_WAITING
;
383 tsleep_enter(libPtr
, (caddr_t
)newselbuf
, "select");
384 ReleaseSemaphore(&select_semaphore
);
385 /* ReleaseSemaphore(&syscall_semaphore); don't have this */
387 error
= tsleep_main(libPtr
, sigmask
);
389 /* ObtainSemaphore(&syscall_semaphore); see above */
390 ObtainSemaphore(&select_semaphore
);
392 ReleaseSemaphore(&select_semaphore
);
396 * The break at the end of this block means that selscan will NOT
397 * be done after this. This provides faster response to the
398 * used defined signals.
400 * Note also that the semantics of the tsleep_abort_timeout() has
401 * changed; it is now accepted to call it even after the timeout
404 if (error
== ERESTART
|| error
== EWOULDBLOCK
)
407 break; /* do not scan now */
412 * Scan for true conditions. Clearing uu_sb
413 * will keep selenter from doing anything.
416 error
= selscan(libPtr
, readfds
, writefds
, exeptfds
,
417 obits
, nfds
, &retval
, &selitemcount
);
422 if (timeout
) /* abort the timeout if any */
423 tsleep_abort_timeout(libPtr
, timeout
);
430 #define putbits(name, x) \
432 aligned_bcopy(((caddr_t)obits) + (x * obitsize), \
433 (caddr_t)name, obitsize); \
438 *sigmp
&= SetSignal(0L, sigmask
);
439 /* ULONG sigs = SetSignal(0L, sigmask);
442 SetSignal(0L,libPtr->sigIntrMask);*/
445 putbits(writefds
, 1);
446 putbits(exeptfds
, 2);
450 API_STD_RETURN(error
, retval
);
453 AROS_LH6(LONG
, WaitSelect
,
454 AROS_LHA(ULONG
, nfds
, D0
),
455 AROS_LHA(fd_set
*, readfds
, A0
),
456 AROS_LHA(fd_set
*, writefds
, A1
),
457 AROS_LHA(fd_set
*, exeptfds
, A2
),
458 AROS_LHA(struct timeval
*, timeout
, A3
),
459 AROS_LHA(ULONG
*, sigmp
, D1
),
460 struct SocketBase
*, libPtr
, 21, UL
)
463 DSYSCALLS(log(LOG_DEBUG
,"WaitSelect(%lu, 0x%08lx, 0x%08lx, 0x%08lx, 0x%08lx, 0x%08lx) called", nfds
, readfds
, writefds
, exeptfds
, timeout
, sigmp
);)
464 return __WaitSelect(nfds
, readfds
, writefds
, exeptfds
, timeout
, sigmp
, libPtr
);
468 AROS_LH1(LONG
, GetSocketEvents
,
469 AROS_LHA(ULONG
*,eventsp
, A0
),
470 struct SocketBase
*, libPtr
, 50, UL
)
477 ObtainSemaphore(&libPtr
->EventLock
);
478 se
= (struct soevent
*)RemHead((struct List
*)&libPtr
->EventList
);
479 ReleaseSemaphore(&libPtr
->EventLock
);
481 *eventsp
= se
->events
;
482 DEVENTS(log(LOG_DEBUG
,"GetSocketEvents(): events 0x%08lx for socket 0x%08lx libPtr = 0x%08lx", se
->events
, se
->socket
, libPtr
);)
485 for (i
= 0; i
< libPtr
->dTableSize
; i
++)
486 if (libPtr
->dTable
[i
] == so
)
488 DEVENTS(log(LOG_CRIT
,"GetSocketEvents(): unreferenced socket 0x%08lx libPtr = 0x%08lx", so
, libPtr
);)
490 DEVENTS(else log (LOG_DEBUG
,"GetSocketEvents(): no events pending libPtr = 0x%08lx", libPtr
);)
496 * Althrough the fd_set is used as the type of the masks, the size
497 * of the fd_set is not fixed, and is indeed calculated from nfd.
500 selscan(struct SocketBase
*p
,
507 int * selitemcount_p
)
509 register int which
, i
, j
, selitemcount
= 0;
510 register fd_mask bits
;
511 register fd_set
* cbits
;
516 u_int obitsize
= howmany(nfd
, NFDBITS
); /* in longwords */
518 for (which
= 0; which
< 3; which
++) {
535 for (i
= 0; i
< nfd
; i
+= NFDBITS
) {
536 bits
= cbits
->fds_bits
[i
/NFDBITS
];
537 while ((j
= ffs(bits
)) && i
+ --j
< nfd
) {
539 so
= p
->dTable
[i
+ j
];
545 if (soo_select(so
, flag
, p
)) {
546 FD_SET(i
+ j
, (fd_set
*)
547 (obits
+ (which
* obitsize
)));
555 *selitemcount_p
= selitemcount
;
560 * Add a select event to the current select buffer.
561 * Chain all select buffers that are waiting for
564 void selenter(struct SocketBase
* p
,
565 struct newselitem
** hdr
)
567 register struct newselbuf
*sb
= p
->p_sb
;
570 register struct newselitem
**sip
= hdr
;
571 register struct newselitem
*si
;
573 ObtainSemaphore(&select_semaphore
);
575 /* initialize this select item */
576 si
= &sb
->s_item
[sb
->s_count
++];
579 /* and add it to the device chain */
580 if (si
->si_next
= *sip
)
581 si
->si_next
->si_prev
= &si
->si_next
;
582 *(si
->si_prev
= sip
) = si
;
584 ReleaseSemaphore(&select_semaphore
);
589 unselect(register struct newselbuf
* sb
)
594 * We unchain the select items.
595 * This assumes select_lock is held.
598 for (i
= 0; i
< sb
->s_count
; i
++) {
599 register struct newselitem
*si
= &sb
->s_item
[i
];
602 * We remove this item from its device chain.
603 * If selwakeup already got to it, then this is a nop.
606 *si
->si_prev
= si
->si_next
;
611 * Wakeup all threads waiting on the same select event.
612 * Do not clear the other select events that each thread
613 * is waiting on; thread will do that itself.
615 void selwakeup(struct newselitem
**hdr
)
617 register struct newselitem
**sip
;
618 register struct newselitem
*si
;
620 ObtainSemaphore(&select_semaphore
);
622 for (sip
= hdr
; (si
= *sip
) != 0; sip
= &si
->si_next
) {
623 register struct newselbuf
*sb
;
626 /* for when unselect tries to dequeue this item */
627 si
->si_prev
= &si
->si_next
;
629 /* check for wakeup */
631 old_state
= sb
->s_state
;
632 sb
->s_state
= SB_CLEAR
;
633 if (old_state
== SB_WAITING
)
637 /* clear the device chain */
638 *(struct newselitem
**)hdr
= 0;
639 ReleaseSemaphore(&select_semaphore
);
643 soo_select(struct socket
*so
,
645 struct SocketBase
*p
)
647 register spl_t s
= splnet();
652 if (soreadable(so
)) {
656 sbselqueue(&so
->so_rcv
, p
);
660 if (sowriteable(so
)) {
664 sbselqueue(&so
->so_snd
, p
);
668 if (so
->so_oobmark
||
669 (so
->so_state
& SS_RCVATMARK
)) {
673 sbselqueue(&so
->so_rcv
, p
);
681 * countSockets() counts how many references ONE task (SocketBase) have to a
686 countSockets(struct SocketBase
* libPtr
, struct socket
* so
)
690 for (i
= 0; i
< libPtr
->dTableSize
; i
++)
691 if (libPtr
->dTable
[i
] == so
)
697 LONG
__CloseSocket(LONG fd
, struct SocketBase
*libPtr
)
704 ObtainSyscallSemaphore(libPtr
);
707 * Check from used sockets bitmask if this socket is in use
709 if (! FD_ISSET(fd
, (fd_set
*)(libPtr
->dTable
+ libPtr
->dTableSize
))) {
715 * If the link library cannot free the fd, then we cannot do it either.
717 if (libPtr
->fdCallback
)
718 if (error
= AROS_UFC2(int, libPtr
->fdCallback
,
719 AROS_UFCA(int, fd
, D0
),
720 AROS_UFCA(int, FDCB_FREE
, D1
)))
723 FD_CLR(fd
, (fd_set
*)(libPtr
->dTable
+ libPtr
->dTableSize
));
725 if (error
= getSock(libPtr
, fd
, &so
)) {
726 // error = ENOTSOCK; /* well, bit set, but socket == NULL */
727 error
= 0; /* ignore silently */
730 if (so
->so_pgid
== libPtr
&& countSockets(libPtr
, so
) == 1)
731 so
->so_pgid
= NULL
; /* not ours any more */
734 * Decrease the reference count of a socket (AmiTCP addition) and return if
737 if (--so
->so_refcnt
<= 0) {
739 /* Remove all events associated with this socket */
740 ObtainSemaphore(&libPtr
->EventLock
);
741 for (se
= (struct soevent
*)libPtr
->EventList
.mlh_Head
; se
->node
.mln_Succ
; se
= (struct soevent
*)se
->node
.mln_Succ
)
743 if (se
->socket
== so
) {
744 Remove((struct Node
*)se
);
748 ReleaseSemaphore(&libPtr
->EventLock
);
752 * now clear socket from descriptor table. Socket usage bitmask has been
755 libPtr
->dTable
[fd
] = NULL
;
758 ReleaseSyscallSemaphore(libPtr
);
759 API_STD_RETURN(error
, 0);
762 AROS_LH1(LONG
, CloseSocket
,
763 AROS_LHA(LONG
, fd
, D0
),
764 struct SocketBase
*, libPtr
,20, UL
)
767 DSYSCALLS(log(LOG_DEBUG
,"CloseSocket(%ld) called", fd
);)
768 return __CloseSocket(fd
, libPtr
);
773 struct MinNode sn_Node
;
775 struct socket
* sn_Socket
;
779 * checkId() checks that there are no released sockets w/ given id.
780 * used from function makeId().
783 static LONG
checkId(int id
)
788 for (sn
= releasedSocketList
.lh_Head
; sn
->ln_Succ
; sn
= sn
->ln_Succ
)
789 if (((struct SocketNode
*)sn
)->sn_Id
== id
) {
797 #define FIRSTUNIQUEID 65536
800 * makeId() gets next unique id for socket to be released if *id is -1
801 * otherwise calls checkId for given *id.
802 * used from functions ReleaseSocket() and ReleaseCopyOfSocket().
804 static LONG
makeId(LONG id
)
806 static LONG uniqueId
= FIRSTUNIQUEID
;
810 uniqueId
+= sizeof (void *);
812 uniqueId
= FIRSTUNIQUEID
;
813 } while (checkId(uniqueId
) != 0);
818 if (checkId(id
) == 0)
821 return -1; /* error */
825 /*LONG SAVEDS ReleaseSocket(
828 REG(a6, struct SocketBase *libPtr))*/
829 AROS_LH2(LONG
, ReleaseSocket
,
830 AROS_LHA(LONG
, fd
, D0
),
831 AROS_LHA(LONG
, id
, D1
),
832 struct SocketBase
*,libPtr
, 25, UL
)
835 struct SocketNode
*sn
;
840 DSYSCALLS(log(LOG_DEBUG
,"ReleaseSocket(%ld, %ld) called", fd
, id
);)
841 if ((ULONG
)id
>= FIRSTUNIQUEID
&& (id
= makeId(id
)) == -1) {
846 if ((error
= getSock(libPtr
, fd
, &so
)) != 0)
849 if ((sn
= AllocMem(sizeof (struct SocketNode
), MEMF_PUBLIC
)) == NULL
) {
854 * Tell the link library that the fd is free
856 if (libPtr
->fdCallback
)
857 if (error
= AROS_UFC2(int, libPtr
->fdCallback
,
858 AROS_UFCA(int, fd
, D0
),
859 AROS_UFCA(int, FDCB_FREE
, D1
)))
861 FreeMem(sn
, sizeof (struct SocketNode
));
865 /*if (so->so_pgid == libPtr && countSockets(libPtr, so) == 1)
866 so->so_pgid = NULL;*/ /* not ours any more */
869 libPtr
->dTable
[fd
] = NULL
;
870 FD_CLR(fd
, (fd_set
*)(libPtr
->dTable
+ libPtr
->dTableSize
));
873 AddTail(&releasedSocketList
, (struct Node
*)sn
);
876 Return
: API_STD_RETURN(error
, id
);
880 /*LONG SAVEDS ReleaseCopyOfSocket(
883 REG(a6, struct SocketBase *libPtr))*/
884 AROS_LH2(LONG
, ReleaseCopyOfSocket
,
885 AROS_LHA(LONG
, fd
, D0
),
886 AROS_LHA(LONG
, id
, D1
),
887 struct SocketBase
*, libPtr
, 26, UL
)
890 struct SocketNode
*sn
;
895 DSYSCALLS(log(LOG_DEBUG
,"ReleaseCopyOfSocket(%ld, %ld) called", fd
, id
);)
896 if ((ULONG
)id
>= FIRSTUNIQUEID
&& (id
= makeId(id
)) == -1) {
901 if ((error
= getSock(libPtr
, fd
, &so
)) != 0)
904 if ((sn
= AllocMem(sizeof (struct SocketNode
), MEMF_PUBLIC
)) == NULL
) {
908 /* so_pgid left intact */
913 AddTail(&releasedSocketList
, (struct Node
*)sn
);
916 Return
: API_STD_RETURN(error
, id
);
920 /*LONG SAVEDS ObtainSocket(
922 REG(d1, LONG domain),
924 REG(d3, LONG protocol),
925 REG(a6, struct SocketBase *libPtr))*/
926 AROS_LH4(LONG
, ObtainSocket
,
927 AROS_LHA(LONG
, id
, D0
),
928 AROS_LHA(LONG
, domain
, D1
),
929 AROS_LHA(LONG
, type
, D2
),
930 AROS_LHA(LONG
, protocol
, D3
),
931 struct SocketBase
*, libPtr
, 24, UL
)
940 DSYSCALLS(log(LOG_DEBUG
,"ObtainSocket(%ld, %ld, %ld, %ld) called", id
, domain
, type
, protocol
);)
942 if (id
< FIRSTUNIQUEID
) {
943 error
= EPFNOSUPPORT
;
949 prp
= pffindproto(domain
, protocol
, type
);
951 prp
= pffindtype(domain
, type
);
953 error
= EPROTONOSUPPORT
;
954 if (prp
->pr_type
!= type
)
960 if ((error
= sdFind(libPtr
, &fd
)) != 0)
964 * Tell the link library about the new fd
966 if (libPtr
->fdCallback
)
967 if (error
= AROS_UFC2(int, libPtr
->fdCallback
,
968 AROS_UFCA(int, fd
, D0
),
969 AROS_UFCA(int, FDCB_ALLOC
, D1
)))
973 for (sn
= releasedSocketList
.lh_Head
; sn
->ln_Succ
; sn
= sn
->ln_Succ
)
974 if (((struct SocketNode
*)sn
)->sn_Id
== id
) {
975 if (prp
!= ((struct SocketNode
*)sn
)->sn_Socket
->so_proto
)
979 libPtr
->dTable
[fd
] = ((struct SocketNode
*)sn
)->sn_Socket
;
980 // ((struct SocketNode *)sn)->sn_Socket->so_pgid = libPtr;
981 FD_SET(fd
, (fd_set
*)(libPtr
->dTable
+ libPtr
->dTableSize
));
982 FreeMem(sn
, sizeof (struct SocketNode
));
985 /* here if sdFind succeeded but search of socket failed */
989 * Free the just allocated fd
991 if (libPtr
->fdCallback
)
992 AROS_UFC2(int, libPtr
->fdCallback
,
993 AROS_UFCA(int, fd
, D0
),
994 AROS_UFCA(int, FDCB_FREE
, D1
));
998 Return
: API_STD_RETURN(error
, fd
);
1002 /*LONG SAVEDS Dup2Socket(
1005 REG(a6, struct SocketBase *libPtr))*/
1006 AROS_LH2(LONG
, Dup2Socket
,
1007 AROS_LHA(LONG
, fd1
, D0
),
1008 AROS_LHA(LONG
, fd2
, D1
),
1009 struct SocketBase
*, libPtr
, 44, UL
)
1017 DSYSCALLS(log(LOG_DEBUG
,"Dup2Socket(%ld, %ld) called", fd1
, fd2
);)
1018 ObtainSyscallSemaphore(libPtr
); /*many tasks may have access to the socket */
1022 else if ((error
= getSock(libPtr
, fd1
, &so
)))
1026 if ((error
= sdFind(libPtr
, &newfd
)))
1031 if ((ULONG
)fd2
>= libPtr
->dTableSize
) {
1035 if (libPtr
->dTable
[fd2
] != NULL
)
1036 __CloseSocket(fd2
, libPtr
);
1038 * Check if the fd is free on the link library
1040 if (libPtr
->fdCallback
)
1041 if (error
= AROS_UFC2(int, libPtr
->fdCallback
,
1042 AROS_UFCA(int, fd2
, D0
),
1043 AROS_UFCA(int, FDCB_CHECK
, D1
)))
1048 * Tell the link library about the new fd
1050 if (libPtr
->fdCallback
)
1051 if (error
= AROS_UFC2(int, libPtr
->fdCallback
,
1052 AROS_UFCA(int, fd2
, D0
),
1053 AROS_UFCA(int, FDCB_ALLOC
, D1
)))
1056 FD_SET(fd2
, (fd_set
*)(libPtr
->dTable
+ libPtr
->dTableSize
));
1060 libPtr
->dTable
[fd2
] = so
;
1064 ReleaseSyscallSemaphore(libPtr
);
1065 API_STD_RETURN(error
, fd2
);