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