Fix failure when in static only route table mode
[ric-plt/lib/rmr.git] / src / rmr / si / src / si95 / sisendt.c
1 // vim: noet sw=4 ts=4:
2 /*
3 ==================================================================================
4     Copyright (c) 2020 Nokia
5     Copyright (c) 2020 AT&T Intellectual Property.
6
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
10
11        http://www.apache.org/licenses/LICENSE-2.0
12
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 ==================================================================================
19 */
20
21 /*
22 ****************************************************************************
23 *
24 *  Mnemonic: SIsendt
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
28 *
29 *  Date:     27 March 1995
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.
33 *
34 *****************************************************************************
35 */
36
37 #include "sisetup.h"     //  get setup stuff 
38 #include "sitransport.h"
39
40 /*
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
47 */
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
57
58         errno = EINVAL;
59
60         if( fd < 0 ) {
61                 errno = EBADFD;
62                 return SI_ERROR;                                        // bad form trying to use this fd
63         }
64
65         if( fd < MAX_FDS ) {                                    // straight from map if possible
66                 tpptr = gptr->tp_map[fd];
67         } else {
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
70         }
71
72         if( tpptr != NULL ) {
73                 if( (fd = tpptr->fd) < 0 ) {                    // fd user given might not be real, and this might be closed already
74                         errno = EBADFD;
75                         return SI_ERROR;
76                 }
77
78                 tpptr->sent++;                          // investigate: this may over count
79
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 );
84
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
87
88                 if( select( fd + 1, NULL, &writefds, &execpfds, &time ) > 0 ) {         //  would block if <= 0
89                         if( FD_ISSET( fd, &execpfds ) ) {       //  error? 
90                                 errno = EBADFD;
91                                 SIterm( gptr, tpptr );                          // mark block for deletion when safe
92                                 return SI_ERROR;                                        // and bail from this sinking ship
93                         } else {
94                                 errno = 0;
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 );
97                                         if( status >= 0 ) {
98                                                 sidx += status;
99                                                 ulen -= status;
100                                                 status = SI_OK;
101                                         } else {
102                                                 if( errno != EINTR || errno != EAGAIN ) {
103                                                         status = SI_ERROR;
104                                                         break;
105                                                 }
106                                         }
107                                 }
108                         }
109                 } else {
110                         errno = EBUSY;
111                         status = SI_ERR_BLOCKED;
112                 }
113         } else {
114                 errno = EBADFD;                 // fd in a bad state (probably losed)
115         }
116
117         return status;
118 }
119