]> git.evergreen-ils.org Git - OpenSRF.git/blob - src/libtransport/transport_socket.c
moved transport code over to utils/socket_bundle so we can keep the code
[OpenSRF.git] / src / libtransport / transport_socket.c
1 #include "transport_socket.h"
2
3
4 /*
5 int main( char* argc, char** argv ) {
6
7         transport_socket sock_obj;
8         sock_obj.port = 5222;
9         sock_obj.server = "10.0.0.4";
10         sock_obj.data_received_callback = &print_stuff;
11
12         printf("connecting...\n");
13         if( (tcp_connect( &sock_obj )) < 0 ) {
14                 printf( "error connecting" );
15         }
16
17         printf("sending...\n");
18         if( tcp_send( &sock_obj, "<stream>\n" ) < 0 ) {
19                 printf( "error sending" );
20         }
21         
22         printf("waiting...\n");
23         if( tcp_wait( &sock_obj, 15 ) < 0 ) {
24                 printf( "error receiving" );
25         }
26
27         printf("disconnecting...\n");
28         tcp_disconnect( &sock_obj );
29
30 }
31 */
32
33
34 // returns the socket fd, -1 on error
35 int tcp_connect( transport_socket* sock_obj ){
36
37
38         if( sock_obj == NULL ) {
39                 fatal_handler( "connect(): null sock_obj" );
40                 return -1;
41         }
42
43         struct sockaddr_in remoteAddr, localAddr;
44         struct hostent *hptr;
45         int sock_fd;
46
47         // ------------------------------------------------------------------
48         // Create the socket
49         // ------------------------------------------------------------------
50         if( (sock_fd = socket( AF_INET, SOCK_STREAM, 0 )) < 0 ) {
51                 fatal_handler( "tcp_connect(): Cannot create socket" );
52                 return -1;
53         }
54
55         // ------------------------------------------------------------------
56         // Get the hostname
57         // ------------------------------------------------------------------
58         if( (hptr = gethostbyname( sock_obj->server ) ) == NULL ) {
59                 fatal_handler( "tcp_connect(): Unknown Host => %s", sock_obj->server );
60                 return -1;
61         }
62
63         // ------------------------------------------------------------------
64         // Construct server info struct
65         // ------------------------------------------------------------------
66         memset( &remoteAddr, 0, sizeof(remoteAddr));
67         remoteAddr.sin_family = AF_INET;
68         remoteAddr.sin_port = htons( sock_obj->port );
69         memcpy( (char*) &remoteAddr.sin_addr.s_addr,
70                         hptr->h_addr_list[0], hptr->h_length );
71
72         // ------------------------------------------------------------------
73         // Construct local info struct
74         // ------------------------------------------------------------------
75         memset( &localAddr, 0, sizeof( localAddr ) );
76         localAddr.sin_family = AF_INET;
77         localAddr.sin_addr.s_addr = htonl( INADDR_ANY );
78         localAddr.sin_port = htons(0);
79
80         // ------------------------------------------------------------------
81         // Bind to a local port
82         // ------------------------------------------------------------------
83         if( bind( sock_fd, (struct sockaddr *) &localAddr, sizeof( localAddr ) ) < 0 ) {
84                 fatal_handler( "tcp_connect(): Cannot bind to local port" );
85                 return -1;
86         }
87
88         // ------------------------------------------------------------------
89         // Connect to server
90         // ------------------------------------------------------------------
91         if( connect( sock_fd, (struct sockaddr*) &remoteAddr, sizeof( struct sockaddr_in ) ) < 0 ) {
92                 fatal_handler( "tcp_connect(): Cannot connect to server %s", sock_obj->server );
93                 return -1;
94         }
95
96         sock_obj->sock_fd = sock_fd;
97         sock_obj->connected = 1;
98         return sock_fd;
99
100 }
101
102
103 int tcp_send( transport_socket* sock_obj, const char* data ){
104
105         if( sock_obj == NULL ) {
106                 fatal_handler( "tcp_send(): null sock_obj" );
107                 return 0;
108         }
109
110         //fprintf( stderr, "TCP Sending: \n%s\n", data );
111
112         // ------------------------------------------------------------------
113         // Send the data down the TCP pipe
114         // ------------------------------------------------------------------
115         if( send( sock_obj->sock_fd, data, strlen(data), 0 ) < 0 ) {
116                 fatal_handler( "tcp_send(): Error sending data" );
117                 return 0;
118         }
119
120         debug_handler( "Sent Data %s At %f Seconds", data, get_timestamp_millis() );
121         return 1;
122 }
123
124
125
126 int tcp_disconnect( transport_socket* sock_obj ){
127
128         if( sock_obj == NULL ) {
129                 fatal_handler( "tcp_disconnect(): null sock_obj" );
130                 return -1;
131         }
132
133         if( close( sock_obj->sock_fd ) == -1 ) {
134
135                 // ------------------------------------------------------------------
136                 // Not really worth throwing an exception for... should be logged.
137                 // ------------------------------------------------------------------
138                 warning_handler( "tcp_disconnect(): Error closing socket" );
139                 return -1;
140         } 
141
142         return 0;
143 }
144
145 // ------------------------------------------------------------------
146 // And now for the gory C socket code.
147 // Returns 0 on failure, 1 otherwise
148 // ------------------------------------------------------------------
149 int tcp_wait( transport_socket* sock_obj, int timeout ){
150
151         if( sock_obj == NULL ) {
152                 fatal_handler( "tcp_wait(): null sock_obj" );
153                 return 0;
154         }
155
156
157         int n = 0; 
158         int retval = 0;
159         char buf[BUFSIZE];
160         int sock_fd = sock_obj->sock_fd;
161
162         fd_set read_set;
163
164         FD_ZERO( &read_set );
165         FD_SET( sock_fd, &read_set );
166
167         // ------------------------------------------------------------------
168         // Build the timeval struct
169         // ------------------------------------------------------------------
170         struct timeval tv;
171         tv.tv_sec = timeout;
172         tv.tv_usec = 0;
173
174         if( timeout == -1 ) {  
175
176                 // ------------------------------------------------------------------
177                 // If timeout is -1, there is no timeout passed to the call to select
178                 // ------------------------------------------------------------------
179                 if( (retval = select( sock_fd + 1 , &read_set, NULL, NULL, NULL)) == -1 ) {
180                         warning_handler( "Call to select interrupted" );
181                         return 0;
182                 }
183
184         } else if( timeout != 0 ) { /* timeout of 0 means don't block */
185
186                 if( (retval = select( sock_fd + 1 , &read_set, NULL, NULL, &tv)) == -1 ) {
187                         warning_handler( "Call to select interrupted" );
188                         return 0;
189                 }
190         }
191
192         memset( &buf, 0, BUFSIZE );
193
194         if( set_fl( sock_fd, O_NONBLOCK ) < 0 ) 
195                 return 0;
196
197 #ifdef _ROUTER // just read one buffer full of data
198
199         n = recv(sock_fd, buf, BUFSIZE-1, 0);
200         sock_obj->data_received_callback( sock_obj->user_data, buf );
201         if( n == 0 )
202                 n = -1;
203
204 #else // read everything we can
205
206         debug_handler( "Leaving Socket Select At %f Seconds", get_timestamp_millis() );
207         while( (n = recv(sock_fd, buf, BUFSIZE-1, 0) ) > 0 ) {
208                 debug_handler("SOCKET Read:  \n%s\n", buf);
209                 sock_obj->data_received_callback( sock_obj->user_data, buf );
210                 memset( &buf, 0, BUFSIZE );
211         }
212
213 #endif
214
215         if( clr_fl( sock_fd, O_NONBLOCK ) < 0 ) {
216                 warning_handler("Unable to clear O_NONBLOCK flag on socket");
217                 return 0;
218         }
219
220
221         if( n < 0 ) { 
222                 if( errno != EAGAIN ) { 
223                         warning_handler( " * Error reading socket with errno %d", errno );
224                         return 0;
225                 }
226         }
227
228 #ifdef _ROUTER
229         return n;
230 #else
231         return sock_fd;
232 #endif
233
234 }
235
236
237 /*
238 int tcp_connected( transport_socket* obj ) {
239
240         int ret;
241         if( ! obj->sock_fd ) { return 0; }
242
243         ret = read( obj->sock_fd  , NULL,0 );
244         if( ret <= 0 ) {
245                 return 0;
246         }
247         return 1;
248 }
249 */
250