]> git.evergreen-ils.org Git - Evergreen.git/blob - OpenSRF/src/libtransport/transport_socket.c
bug squashing party on the gateway. we now explicitly format the xml
[Evergreen.git] / OpenSRF / src / libtransport / transport_socket.c
1 #include "opensrf/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         if( sock_obj == NULL ) {
38                 fatal_handler( "connect(): null sock_obj" );
39                 return -1;
40         }
41         struct sockaddr_in remoteAddr, localAddr;
42         struct hostent *hptr;
43         int sock_fd;
44
45         #ifdef WIN32
46         WSADATA data;
47         char bfr;
48         if( WSAStartup(MAKEWORD(1,1), &data) ) {
49                 fatal_handler( "somethin's broke with windows socket startup" );
50                 return -1;
51         }
52         #endif
53
54
55
56         // ------------------------------------------------------------------
57         // Create the socket
58         // ------------------------------------------------------------------
59         if( (sock_fd = socket( AF_INET, SOCK_STREAM, 0 )) < 0 ) {
60                 fatal_handler( "tcp_connect(): Cannot create socket" );
61                 return -1;
62         }
63
64         // ------------------------------------------------------------------
65         // Get the hostname
66         // ------------------------------------------------------------------
67         if( (hptr = gethostbyname( sock_obj->server ) ) == NULL ) {
68                 fatal_handler( "tcp_connect(): Unknown Host" );
69                 return -1;
70         }
71
72         // ------------------------------------------------------------------
73         // Construct server info struct
74         // ------------------------------------------------------------------
75         memset( &remoteAddr, 0, sizeof(remoteAddr));
76         remoteAddr.sin_family = AF_INET;
77         remoteAddr.sin_port = htons( sock_obj->port );
78         memcpy( (char*) &remoteAddr.sin_addr.s_addr,
79                         hptr->h_addr_list[0], hptr->h_length );
80
81         // ------------------------------------------------------------------
82         // Construct local info struct
83         // ------------------------------------------------------------------
84         memset( &localAddr, 0, sizeof( localAddr ) );
85         localAddr.sin_family = AF_INET;
86         localAddr.sin_addr.s_addr = htonl( INADDR_ANY );
87         localAddr.sin_port = htons(0);
88
89         // ------------------------------------------------------------------
90         // Bind to a local port
91         // ------------------------------------------------------------------
92         if( bind( sock_fd, (struct sockaddr *) &localAddr, sizeof( localAddr ) ) < 0 ) {
93                 fatal_handler( "tcp_connect(): Cannot bind to local port" );
94                 return -1;
95         }
96
97         // ------------------------------------------------------------------
98         // Connect to server
99         // ------------------------------------------------------------------
100         if( connect( sock_fd, (struct sockaddr*) &remoteAddr, sizeof( struct sockaddr_in ) ) < 0 ) {
101                 fatal_handler( "tcp_connect(): Cannot connect to server %s", sock_obj->server );
102                 return -1;
103         }
104
105         sock_obj->sock_fd = sock_fd;
106         sock_obj->connected = 1;
107         return sock_fd;
108
109 }
110
111
112 int tcp_send( transport_socket* sock_obj, const char* data ){
113
114         if( sock_obj == NULL ) {
115                 fatal_handler( "tcp_send(): null sock_obj" );
116                 return 0;
117         }
118
119         //fprintf( stderr, "TCP Sending: \n%s\n", data );
120
121         // ------------------------------------------------------------------
122         // Send the data down the TCP pipe
123         // ------------------------------------------------------------------
124         if( send( sock_obj->sock_fd, data, strlen(data), 0 ) < 0 ) {
125                 fatal_handler( "tcp_send(): Error sending data" );
126                 return 0;
127         }
128
129         debug_handler( "Sent Data %s At %f Seconds", data, get_timestamp_millis() );
130         return 1;
131 }
132
133
134 int tcp_disconnect( transport_socket* sock_obj ){
135
136         if( sock_obj == NULL ) {
137                 fatal_handler( "tcp_disconnect(): null sock_obj" );
138                 return -1;
139         }
140
141         if( close( sock_obj->sock_fd ) == -1 ) {
142
143                 // ------------------------------------------------------------------
144                 // Not really worth throwing an exception for... should be logged.
145                 // ------------------------------------------------------------------
146                 warning_handler( "tcp_disconnect(): Error closing socket" );
147                 return -1;
148         } 
149
150         return 0;
151 }
152
153 // ------------------------------------------------------------------
154 // And now for the gory C socket code.
155 // Returns 0 on failure, 1 otherwise
156 // ------------------------------------------------------------------
157 int tcp_wait( transport_socket* sock_obj, int timeout ){
158
159         if( sock_obj == NULL ) {
160                 fatal_handler( "tcp_wait(): null sock_obj" );
161                 return 0;
162         }
163
164         int n = 0; 
165         int retval = 0;
166         char buf[BUFSIZE];
167         int sock_fd = sock_obj->sock_fd;
168
169
170         fd_set read_set;
171
172         FD_ZERO( &read_set );
173         FD_SET( sock_fd, &read_set );
174
175         // ------------------------------------------------------------------
176         // Build the timeval struct
177         // ------------------------------------------------------------------
178         struct timeval tv;
179         tv.tv_sec = timeout;
180         tv.tv_usec = 0;
181
182         if( timeout == -1 ) {  
183
184                 // ------------------------------------------------------------------
185                 // If timeout is -1, there is no timeout passed to the call to select
186                 // ------------------------------------------------------------------
187                 if( (retval = select( sock_fd + 1 , &read_set, NULL, NULL, NULL)) == -1 ) {
188                         warning_handler( "Call to select interrupted" );
189                         return 0;
190                 }
191
192         } else if( timeout != 0 ) { /* timeout of 0 means don't block */
193
194                 if( (retval = select( sock_fd + 1 , &read_set, NULL, NULL, &tv)) == -1 ) {
195                         warning_handler( "Call to select interrupted" );
196                         return 0;
197                 }
198         }
199
200         memset( &buf, 0, BUFSIZE );
201
202         if( set_fl( sock_fd, O_NONBLOCK ) < 0 ) 
203                 return 0;
204
205 #ifdef _ROUTER // just read one buffer full of data
206
207         n = recv(sock_fd, buf, BUFSIZE-1, 0);
208         sock_obj->data_received_callback( sock_obj->user_data, buf );
209         if( n == 0 )
210                 n = -1;
211
212 #else // read everything we can
213
214         debug_handler( "Leaving Socket Select At %f Seconds", get_timestamp_millis() );
215         while( (n = recv(sock_fd, buf, BUFSIZE-1, 0) ) > 0 ) {
216                 debug_handler("SOCKET Read:  \n%s\n", buf);
217                 sock_obj->data_received_callback( sock_obj->user_data, buf );
218                 memset( &buf, 0, BUFSIZE );
219         }
220
221 #endif
222
223         if( clr_fl( sock_fd, O_NONBLOCK ) < 0 ) {
224                 warning_handler("Unable to clear O_NONBLOCK flag on socket");
225                 return 0;
226         }
227
228
229         if( n < 0 ) { 
230                 if( errno != EAGAIN ) { 
231                         warning_handler( " * Error reading socket with errno %d", errno );
232                         return 0;
233                 }
234         }
235
236 #ifdef _ROUTER
237         return n;
238 #else
239         return 1;
240 #endif
241
242 }
243
244 int set_fl( int fd, int flags ) {
245         
246         int val;
247
248         if( (val = fcntl( fd, F_GETFL, 0) ) < 0 ) {
249                 fatal_handler("fcntl F_GETFL error");
250                 return -1;
251         }
252
253         val |= flags;
254
255         if( fcntl( fd, F_SETFL, val ) < 0 ) {
256                 fatal_handler( "fcntl F_SETFL error" );
257                 return -1;
258         }
259         return 0;
260 }
261         
262 int clr_fl( int fd, int flags ) {
263         
264         int val;
265
266         if( (val = fcntl( fd, F_GETFL, 0) ) < 0 ) {
267                 fatal_handler("fcntl F_GETFL error" );
268                 return -1;
269         }
270
271         val &= ~flags;
272
273         if( fcntl( fd, F_SETFL, val ) < 0 ) {
274                 fatal_handler( "fcntl F_SETFL error" );
275                 return -1;
276         }
277         return 0;
278 }
279         
280
281 /*
282 int tcp_connected( transport_socket* obj ) {
283
284         int ret;
285         if( ! obj->sock_fd ) { return 0; }
286
287         ret = read( obj->sock_fd  , NULL,0 );
288         if( ret <= 0 ) {
289                 return 0;
290         }
291         return 1;
292 }
293 */
294