1 // vim: noet sw=4 ts=4:
3 ==================================================================================
4 Copyright (c) 2020 Nokia
5 Copyright (c) 2020 AT&T Intellectual Property.
7 Licensed under the Apache License, Version 2.0 (the "License");
8 you may not use this file except in compliance with the License.
9 You may obtain a copy of the License at
11 http://www.apache.org/licenses/LICENSE-2.0
13 Unless required by applicable law or agreed to in writing, software
14 distributed under the License is distributed on an "AS IS" BASIS,
15 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 See the License for the specific language governing permissions and
17 limitations under the License.
18 ==================================================================================
22 ****************************************************************************
25 * Abstract: This module contains various send functions:
26 * SIsendt -- send tcp with queuing if would block
27 * SIsendt_nq - send tcp without queuing if blocking
30 * Author: E. Scott Daniels
31 * Mod: 22 Feb 2002 - To better process queued data
32 * 14 Feb 2020 - To fix index bug if fd < 0.
34 *****************************************************************************
37 #include "sisetup.h" // get setup stuff
38 #include "sitransport.h"
41 Send a message on what is assumed to be a tcp connection. If the session
42 would block, then SI_ERR_BLOCKED is returned. Else, SI_OK or SI_ERROR
43 is returned to indicate state. Errno should be set to reflect error state:
44 EBADFD - error from system; fd was closed
45 EBUSY - system would block the send call
46 EINVAL - fd was not valid or did not reference an open session
48 //extern int SIsendt_nq( struct ginfo_blk *gptr, int fd, char *ubuf, int ulen ) {
49 extern int SIsendt( struct ginfo_blk *gptr, int fd, char *ubuf, int ulen ) {
50 int status = SI_ERROR; // assume we fail
51 fd_set writefds; // local write fdset to check blockage
52 fd_set execpfds; // exception fdset to check errors
53 struct tp_blk *tpptr; // pointer at the tp_blk for the session
54 struct ioq_blk *qptr; // pointer at i/o queue block
55 struct timeval time; // delay time parameter for select call
56 int sidx = 0; // send index
62 return SI_ERROR; // bad form trying to use this fd
65 if( fd < MAX_FDS ) { // straight from map if possible
66 tpptr = gptr->tp_map[fd];
68 // list should be locked before traversing
69 for( tpptr = gptr->tplist; tpptr != NULL && tpptr->fd != fd; tpptr = tpptr->next ); // find the block if out of map's range
73 if( (fd = tpptr->fd) < 0 ) { // fd user given might not be real, and this might be closed already
78 tpptr->sent++; // investigate: this may over count
80 FD_ZERO( &writefds ); // clear for select call
81 FD_SET( fd, &writefds ); // set to see if this one was writable
82 FD_ZERO( &execpfds ); // clear and set execptions fdset
83 FD_SET( fd, &execpfds );
85 time.tv_sec = 0; // set both to 0 if we just want a poll, else we block at max this amount
86 time.tv_usec = 1; // small pause on check to help drain things
88 if( select( fd + 1, NULL, &writefds, &execpfds, &time ) > 0 ) { // would block if <= 0
89 if( FD_ISSET( fd, &execpfds ) ) { // error?
91 SIterm( gptr, tpptr ); // mark block for deletion when safe
92 return SI_ERROR; // and bail from this sinking ship
95 while( ulen > 0 ) { // once we start, we must ensure that it all goes out
96 status = SEND( tpptr->fd, ubuf+sidx, (unsigned int) ulen, 0 );
102 if( errno != EINTR || errno != EAGAIN ) {
111 status = SI_ERR_BLOCKED;
114 errno = EBADFD; // fd in a bad state (probably losed)